mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
fix: some linting for new proto 5
This commit is contained in:
1 parent
53a9c5f2de
commit
96310a9d63
40 files changed
+409
-367
No files matched your search
@@ -188,7 +188,7 @@ export async function renderBreakdown(
|
|||||||
key={id}
|
key={id}
|
||||||
displayType="tank"
|
displayType="tank"
|
||||||
class={tankDefinition?.class}
|
class={tankDefinition?.class}
|
||||||
displayType={tankDefinition?.type}
|
type={tankDefinition?.type}
|
||||||
title={
|
title={
|
||||||
tankDefinition?.name ??
|
tankDefinition?.name ??
|
||||||
translate('bot.commands.breakdown.body.unknown_tank', [`${id}`])
|
translate('bot.commands.breakdown.body.unknown_tank', [`${id}`])
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
blitzStarsTankAverages,
|
|
||||||
calculateWN8,
|
calculateWN8,
|
||||||
emblemURL,
|
emblemURL,
|
||||||
getClanAccountInfo,
|
getClanAccountInfo,
|
||||||
idToRegion,
|
idToRegion,
|
||||||
mapDefinitions,
|
|
||||||
tankDefinitions,
|
|
||||||
tankIcon,
|
tankIcon,
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
@@ -13,7 +10,12 @@ import { clamp } from 'lodash-es';
|
|||||||
import { CommandWrapper } from '../components/CommandWrapper';
|
import { CommandWrapper } from '../components/CommandWrapper';
|
||||||
import { TitleBar } from '../components/TitleBar';
|
import { TitleBar } from '../components/TitleBar';
|
||||||
import { iconPng } from '../core/blitzkit/iconPng';
|
import { iconPng } from '../core/blitzkit/iconPng';
|
||||||
|
import {
|
||||||
|
mapDefinitions,
|
||||||
|
tankDefinitions,
|
||||||
|
} from '../core/blitzkit/nonBlockingPromises';
|
||||||
import { RenderConfiguration } from '../core/blitzkit/renderConfiguration';
|
import { RenderConfiguration } from '../core/blitzkit/renderConfiguration';
|
||||||
|
import { blitzStarsTankAverages } from '../core/blitzstars/tankAverages';
|
||||||
import { buttonLink } from '../core/discord/buttonLink';
|
import { buttonLink } from '../core/discord/buttonLink';
|
||||||
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
@@ -223,7 +225,7 @@ async function playerListing(
|
|||||||
) {
|
) {
|
||||||
const awaitedTankAverages = await blitzStarsTankAverages;
|
const awaitedTankAverages = await blitzStarsTankAverages;
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const awaitedTankDefinitions = await tankDefinitions;
|
||||||
const tank = awaitedTankDefinitions[player.vehicle_descr];
|
const tank = awaitedTankDefinitions.tanks[player.vehicle_descr];
|
||||||
const blockAccent = recordingPlayer ? '_amber' : '';
|
const blockAccent = recordingPlayer ? '_amber' : '';
|
||||||
const healthAccent = protagonistTeam
|
const healthAccent = protagonistTeam
|
||||||
? recordingPlayer
|
? recordingPlayer
|
||||||
@@ -502,7 +504,7 @@ export const replayCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
replayData.protagonist_team === replayData.winner_team
|
replayData.protagonist_team === replayData.winner_team
|
||||||
? 'Victory'
|
? 'Victory'
|
||||||
: 'Defeat'
|
: 'Defeat'
|
||||||
} • ${awaitedMapDefinitions[replayData.map_id].name}`}
|
} • ${awaitedMapDefinitions.maps[replayData.map_id].name}`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
getClanAccountInfo,
|
getClanAccountInfo,
|
||||||
getTankStats,
|
getTankStats,
|
||||||
TANK_ICONS,
|
TANK_ICONS,
|
||||||
tankDefinitions,
|
TankType,
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
import { escapeMarkdown, Locale } from 'discord.js';
|
import { escapeMarkdown, Locale } from 'discord.js';
|
||||||
@@ -15,6 +15,7 @@ import { TitleBar } from '../components/TitleBar';
|
|||||||
import { resolveTankId } from '../core/blitz/resolveTankId';
|
import { resolveTankId } from '../core/blitz/resolveTankId';
|
||||||
import { buildTechTreeLine } from '../core/blitzkit/buildTechTreeLine';
|
import { buildTechTreeLine } from '../core/blitzkit/buildTechTreeLine';
|
||||||
import { iconPng } from '../core/blitzkit/iconPng';
|
import { iconPng } from '../core/blitzkit/iconPng';
|
||||||
|
import { tankDefinitions } from '../core/blitzkit/nonBlockingPromises';
|
||||||
import { resolveAncestry } from '../core/blitzkit/resolveAncestry';
|
import { resolveAncestry } from '../core/blitzkit/resolveAncestry';
|
||||||
import { tankIconPng } from '../core/blitzkit/tankIconPng';
|
import { tankIconPng } from '../core/blitzkit/tankIconPng';
|
||||||
import { addUsernameChoices } from '../core/discord/addUsernameChoices';
|
import { addUsernameChoices } from '../core/discord/addUsernameChoices';
|
||||||
@@ -76,7 +77,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
const startingTankRaw = interaction.options.getString('starting-tank');
|
const startingTankRaw = interaction.options.getString('starting-tank');
|
||||||
const targetTank = awaitedTankDefinitions[targetTankId];
|
const targetTank = awaitedTankDefinitions.tanks[targetTankId];
|
||||||
const { id, region } = await resolvePlayerFromCommand(interaction);
|
const { id, region } = await resolvePlayerFromCommand(interaction);
|
||||||
let startingTankId: number;
|
let startingTankId: number;
|
||||||
const targetTankAncestry = await resolveAncestry(targetTankId);
|
const targetTankAncestry = await resolveAncestry(targetTankId);
|
||||||
@@ -94,7 +95,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const startingTank = awaitedTankDefinitions[startingTankId];
|
const startingTank = awaitedTankDefinitions.tanks[startingTankId];
|
||||||
|
|
||||||
if (startingTank.tier > targetTank.tier) {
|
if (startingTank.tier > targetTank.tier) {
|
||||||
return translate('bot.commands.research.errors.unordered', [
|
return translate('bot.commands.research.errors.unordered', [
|
||||||
@@ -111,7 +112,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (targetTank.treeType !== 'researchable') {
|
if (targetTank.type !== TankType.RESEARCHABLE) {
|
||||||
return translate('bot.commands.research.errors.non_tech_tree', [
|
return translate('bot.commands.research.errors.non_tech_tree', [
|
||||||
escapeMarkdown(targetTank.name),
|
escapeMarkdown(targetTank.name),
|
||||||
]);
|
]);
|
||||||
@@ -137,7 +138,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
|
|
||||||
const foundAncestor = targetTankAncestry.find(
|
const foundAncestor = targetTankAncestry.find(
|
||||||
(id) =>
|
(id) =>
|
||||||
awaitedTankDefinitions[id].tier === 1 ||
|
awaitedTankDefinitions.tanks[id].tier === 1 ||
|
||||||
tankStats.some(({ tank_id }) => tank_id === id),
|
tankStats.some(({ tank_id }) => tank_id === id),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -159,7 +160,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined;
|
const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined;
|
||||||
const costs = await Promise.all(
|
const costs = await Promise.all(
|
||||||
line.map(async (id) => {
|
line.map(async (id) => {
|
||||||
const tank = awaitedTankDefinitions[id];
|
const tank = awaitedTankDefinitions.tanks[id];
|
||||||
const turretXps = new Map<number, number>();
|
const turretXps = new Map<number, number>();
|
||||||
const gunXps = new Map<number, number>();
|
const gunXps = new Map<number, number>();
|
||||||
const engineXps = new Map<number, number>();
|
const engineXps = new Map<number, number>();
|
||||||
@@ -171,8 +172,11 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
turret.guns.forEach((gun) => {
|
turret.guns.forEach((gun) => {
|
||||||
if (gun.xp !== undefined) {
|
if (gun.gunType!.value.base.xp !== undefined) {
|
||||||
gunXps.set(gun.id, gun.xp);
|
gunXps.set(
|
||||||
|
gun.gunType!.value.base.id,
|
||||||
|
gun.gunType!.value.base.xp,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -353,7 +357,7 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
|
|
||||||
{await Promise.all(
|
{await Promise.all(
|
||||||
line.map(async (id, index) => {
|
line.map(async (id, index) => {
|
||||||
const tank = awaitedTankDefinitions[id];
|
const tank = awaitedTankDefinitions.tanks[id];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { tankDefinitions, tankNames } from '@blitzkit/core';
|
|
||||||
import { Locale } from 'discord.js';
|
import { Locale } from 'discord.js';
|
||||||
import { go } from 'fuzzysort';
|
import { go } from 'fuzzysort';
|
||||||
import markdownEscape from 'markdown-escape';
|
import markdownEscape from 'markdown-escape';
|
||||||
|
import { tankNames } from '../blitzkit/nonBlockingPromises';
|
||||||
import { UserError } from '../blitzkit/userError';
|
import { UserError } from '../blitzkit/userError';
|
||||||
import { tankNamesTechTreeOnly } from '../discord/autocompleteTanks';
|
import { tankNamesTechTreeOnly } from '../discord/autocompleteTanks';
|
||||||
import { translator } from '../localization/translator';
|
import { translator } from '../localization/translator';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { tankDefinitions } from '@blitzkit/core';
|
import { fetchTankDefinitions } from '@blitzkit/core';
|
||||||
import { resolveAncestry } from './resolveAncestry';
|
import { resolveAncestry } from './resolveAncestry';
|
||||||
|
|
||||||
export async function buildTechTreeLine(start: number, end: number) {
|
export async function buildTechTreeLine(start: number, end: number) {
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
const endTank = awaitedTankDefinitions[end];
|
const endTank = tankDefinitions.tanks[end];
|
||||||
if (!endTank.ancestors) throw new Error('End tank has no ancestors');
|
if (!endTank.ancestors) throw new Error('End tank has no ancestors');
|
||||||
const line = [end];
|
const line = [end];
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import {
|
import {
|
||||||
StatFilters,
|
fetchTankDefinitions,
|
||||||
tankDefinitions,
|
|
||||||
Tier,
|
Tier,
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
import { Locale } from 'discord.js';
|
import { Locale } from 'discord.js';
|
||||||
|
import { StatFilters } from '../blitzstars/filterStats';
|
||||||
import { translator } from '../localization/translator';
|
import { translator } from '../localization/translator';
|
||||||
|
|
||||||
export async function filtersToDescription(
|
export async function filtersToDescription(
|
||||||
{ nation, tier, tankType, treeType, tank }: StatFilters,
|
{ nation, tier, type, class: tankClass, tank }: StatFilters,
|
||||||
locale: Locale,
|
locale: Locale,
|
||||||
) {
|
) {
|
||||||
const { translate } = translator(locale);
|
const { translate } = translator(locale);
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const awaitedTankDefinitions = await fetchTankDefinitions();
|
||||||
const info: string[] = [];
|
const info: string[] = [];
|
||||||
|
|
||||||
// TODO: somehow localize tank names?
|
// TODO: somehow localize tank names?
|
||||||
if (tank) return awaitedTankDefinitions[tank].name;
|
if (tank) return awaitedTankDefinitions.tanks[tank].name;
|
||||||
if (nation) info.push(translate(`common.nations.${nation}`));
|
if (nation) info.push(translate(`common.nations.${nation}`));
|
||||||
if (tier) {
|
if (tier) {
|
||||||
info.push(
|
info.push(
|
||||||
translate('bot.common.filters.tier', [TIER_ROMAN_NUMERALS[tier as Tier]]),
|
translate('bot.common.filters.tier', [TIER_ROMAN_NUMERALS[tier as Tier]]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (tankType) info.push(translate(`common.tank_class_short.${tankType}`));
|
if (tankClass) info.push(translate(`common.tank_class_short.${tankClass}`));
|
||||||
if (treeType) info.push(translate(`common.tree_type.${treeType}`));
|
if (type) info.push(translate(`common.tree_type.${type}`));
|
||||||
|
|
||||||
return info.length === 0
|
return info.length === 0
|
||||||
? translate('bot.common.filters.none')
|
? translate('bot.common.filters.none')
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
import { fetchGameDefinitions, fetchTankDefinitions } from '@blitzkit/core';
|
import {
|
||||||
|
fetchGameDefinitions,
|
||||||
|
fetchMapDefinitions,
|
||||||
|
fetchTankDefinitions,
|
||||||
|
fetchTankNames,
|
||||||
|
} from '@blitzkit/core';
|
||||||
|
|
||||||
export const tankDefinitions = fetchTankDefinitions();
|
export const tankDefinitions = fetchTankDefinitions();
|
||||||
export const gameDefinitions = fetchGameDefinitions();
|
export const gameDefinitions = fetchGameDefinitions();
|
||||||
|
export const tankNames = fetchTankNames();
|
||||||
|
export const mapDefinitions = fetchMapDefinitions();
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { tankDefinitions } from '@blitzkit/core';
|
import { fetchTankDefinitions } from '@blitzkit/core';
|
||||||
|
|
||||||
export async function resolveAncestry(id: number) {
|
export async function resolveAncestry(id: number) {
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
const tank = awaitedTankDefinitions[id];
|
const tank = tankDefinitions.tanks[id];
|
||||||
const ancestors: number[] = [];
|
const ancestors: number[] = [];
|
||||||
|
|
||||||
if (tank.ancestors) {
|
if (tank.ancestors) {
|
||||||
@@ -20,6 +20,6 @@ export async function resolveAncestry(id: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ancestors.sort(
|
return ancestors.sort(
|
||||||
(a, b) => awaitedTankDefinitions[b].tier - awaitedTankDefinitions[a].tier,
|
(a, b) => tankDefinitions.tanks[b].tier - tankDefinitions.tanks[a].tier,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { tankNames } from '@blitzkit/core';
|
import { fetchTankNames, TankType } from '@blitzkit/core';
|
||||||
import {
|
import {
|
||||||
ApplicationCommandOptionChoiceData,
|
ApplicationCommandOptionChoiceData,
|
||||||
AutocompleteInteraction,
|
AutocompleteInteraction,
|
||||||
@@ -9,9 +9,10 @@ import {
|
|||||||
DISCORD_CHOICES_MAX_NAME_SIZE,
|
DISCORD_CHOICES_MAX_NAME_SIZE,
|
||||||
OVERFLOW_SUFFIX,
|
OVERFLOW_SUFFIX,
|
||||||
} from './autocompleteClan/constants';
|
} from './autocompleteClan/constants';
|
||||||
|
import { tankNames } from '../blitzkit/nonBlockingPromises';
|
||||||
|
|
||||||
export const tankNamesTechTreeOnly = tankNames.then((names) =>
|
export const tankNamesTechTreeOnly = fetchTankNames().then((names) =>
|
||||||
names.filter((tank) => tank.treeType === 'researchable'),
|
names.filter((tank) => tank.treeType === TankType.RESEARCHABLE),
|
||||||
);
|
);
|
||||||
|
|
||||||
export async function autocompleteTanks(
|
export async function autocompleteTanks(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { type ShellDefinition, ShellType } from '@blitzkit/core';
|
import { type ShellDefinition, ShellType } from '@blitzkit/core';
|
||||||
|
|
||||||
export function canSplash(type: ShellDefinition['type']): type is ShellType.HE {
|
export function canSplash(type: ShellDefinition['type']): type is ShellType.HE {
|
||||||
return type === ShellType.SHELL_TYPE_HE;
|
return type === ShellType.HE;
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
import { Vector3Tuple } from 'three';
|
import { Vector3Tuple } from 'three';
|
||||||
import { Tier } from '../blitzkit';
|
import { Tier } from '../protos';
|
||||||
|
|
||||||
export const equipmentPriceMatrix: Record<Tier, Vector3Tuple> = {
|
export const equipmentPriceMatrix: Record<Tier, Vector3Tuple> = {
|
||||||
1: [100, 200, 300],
|
[Tier.I]: [100, 200, 300],
|
||||||
2: [200, 300, 400],
|
[Tier.II]: [200, 300, 400],
|
||||||
3: [400, 500, 600],
|
[Tier.III]: [400, 500, 600],
|
||||||
4: [4000, 5000, 6000],
|
[Tier.IV]: [4000, 5000, 6000],
|
||||||
5: [40_000, 50_000, 60_000],
|
[Tier.V]: [40_000, 50_000, 60_000],
|
||||||
6: [100_000, 120_000, 140_000],
|
[Tier.VI]: [100_000, 120_000, 140_000],
|
||||||
7: [150_000, 170_000, 190_000],
|
[Tier.VII]: [150_000, 170_000, 190_000],
|
||||||
8: [200_000, 225_000, 250_000],
|
[Tier.VIII]: [200_000, 225_000, 250_000],
|
||||||
9: [250_000, 275_000, 300_000],
|
[Tier.IX]: [250_000, 275_000, 300_000],
|
||||||
10: [300_000, 350_000, 400_000],
|
[Tier.X]: [300_000, 350_000, 400_000],
|
||||||
|
[Tier.UNRECOGNIZED]: [0, 0, 0],
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
import { ProvisionDefinitions } from '@blitzkit/core';
|
import {
|
||||||
|
GunDefinition,
|
||||||
|
ProvisionDefinitions,
|
||||||
|
TankDefinition,
|
||||||
|
} from '@blitzkit/core';
|
||||||
import { checkConsumableProvisionInclusivity } from './checkConsumableProvisionInclusivity';
|
import { checkConsumableProvisionInclusivity } from './checkConsumableProvisionInclusivity';
|
||||||
import { GunDefinition, TankDefinition } from './tankDefinitions';
|
|
||||||
|
|
||||||
export function availableProvisions(
|
export function availableProvisions(
|
||||||
tank: TankDefinition,
|
tank: TankDefinition,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Samples } from '.';
|
|
||||||
import { emptyAllStats } from '../../blitz/constants';
|
import { emptyAllStats } from '../../blitz/constants';
|
||||||
|
import { Samples } from '../../protos';
|
||||||
import { BlitzkitStats } from '../../statistics';
|
import { BlitzkitStats } from '../../statistics';
|
||||||
|
|
||||||
export const emptyAverageDefinitionsAllStats: BlitzkitStats = {
|
export const emptyAverageDefinitionsAllStats: BlitzkitStats = {
|
||||||
@@ -12,11 +12,11 @@ export const averageDefinitionsAllStatsKeys = Object.keys(
|
|||||||
) as (keyof BlitzkitStats)[];
|
) as (keyof BlitzkitStats)[];
|
||||||
|
|
||||||
export const emptySamples: Samples = {
|
export const emptySamples: Samples = {
|
||||||
d_1: 0,
|
d1: 0,
|
||||||
d_7: 0,
|
d7: 0,
|
||||||
d_30: 0,
|
d30: 0,
|
||||||
d_60: 0,
|
d60: 0,
|
||||||
d_90: 0,
|
d90: 0,
|
||||||
d_120: 0,
|
d120: 0,
|
||||||
total: 0,
|
total: 0,
|
||||||
};
|
};
|
||||||
@@ -1,53 +1,64 @@
|
|||||||
import { ConsumableEntry, ProvisionEntry } from '@blitzkit/core';
|
import {
|
||||||
import { GunDefinition, TankDefinition } from './tankDefinitions';
|
Consumable,
|
||||||
|
ConsumableTankCategoryFilterCategory,
|
||||||
|
GunDefinition,
|
||||||
|
Provision,
|
||||||
|
TankDefinition,
|
||||||
|
} from '../protos';
|
||||||
|
|
||||||
export function checkConsumableProvisionInclusivity(
|
export function checkConsumableProvisionInclusivity(
|
||||||
consumableProvision: ConsumableEntry | ProvisionEntry,
|
consumableProvision: Consumable | Provision,
|
||||||
tank: TankDefinition,
|
tank: TankDefinition,
|
||||||
gun: GunDefinition,
|
gun: GunDefinition,
|
||||||
) {
|
) {
|
||||||
const included =
|
const included =
|
||||||
!consumableProvision.gameMode &&
|
!consumableProvision.gameModeExclusive &&
|
||||||
consumableProvision.include?.every((rule) => {
|
consumableProvision.include?.every((rule) => {
|
||||||
switch (rule.type) {
|
switch (rule.filterType!.$case) {
|
||||||
case 'tier':
|
case 'tiers':
|
||||||
return rule.min <= tank.tier && tank.tier <= rule.max;
|
return (
|
||||||
|
rule.filterType!.value.min <= tank.tier &&
|
||||||
|
tank.tier <= rule.filterType!.value.max
|
||||||
|
);
|
||||||
|
|
||||||
case 'ids':
|
case 'ids':
|
||||||
return rule.ids.includes(tank.id);
|
return rule.filterType!.value.ids.includes(tank.id);
|
||||||
|
|
||||||
case 'nation':
|
case 'nations':
|
||||||
return rule.nations.includes(tank.nation);
|
return rule.filterType!.value.nations.includes(tank.nation);
|
||||||
|
|
||||||
case 'category':
|
case 'categories':
|
||||||
throw new SyntaxError('Category filtering found in include rule');
|
throw new SyntaxError('Category filtering found in include rule');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const excluded =
|
const excluded =
|
||||||
consumableProvision.gameMode ||
|
consumableProvision.gameModeExclusive ||
|
||||||
consumableProvision.exclude?.some((rule) => {
|
consumableProvision.exclude?.some((rule) => {
|
||||||
switch (rule.type) {
|
switch (rule.filterType!.$case) {
|
||||||
case 'tier':
|
case 'tiers':
|
||||||
return rule.min <= tank.tier && tank.tier <= rule.max;
|
return (
|
||||||
|
rule.filterType!.value.min <= tank.tier &&
|
||||||
|
tank.tier <= rule.filterType!.value.max
|
||||||
|
);
|
||||||
|
|
||||||
case 'ids':
|
case 'ids':
|
||||||
return rule.ids.includes(tank.id);
|
return rule.filterType!.value.ids.includes(tank.id);
|
||||||
|
|
||||||
case 'nation':
|
case 'nations':
|
||||||
return rule.nations.includes(tank.nation);
|
return rule.filterType!.value.nations.includes(tank.nation);
|
||||||
|
|
||||||
case 'category':
|
case 'categories':
|
||||||
return rule.categories.some((category) => {
|
return rule.filterType!.value.categories.some((category) => {
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case 'clip':
|
case ConsumableTankCategoryFilterCategory.CLIP:
|
||||||
return gun.type !== 'regular';
|
return gun.gunType!.$case !== 'regular';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!consumableProvision.gameMode &&
|
!consumableProvision.gameModeExclusive &&
|
||||||
consumableProvision.include?.length > 0 &&
|
consumableProvision.include?.length > 0 &&
|
||||||
included &&
|
included &&
|
||||||
!excluded
|
!excluded
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export function createDefaultSkills(skillDefinitions: SkillDefinitions) {
|
|||||||
const skills: Record<string, number> = {};
|
const skills: Record<string, number> = {};
|
||||||
|
|
||||||
Object.values(skillDefinitions.classes).forEach((tankSkills) => {
|
Object.values(skillDefinitions.classes).forEach((tankSkills) => {
|
||||||
tankSkills.forEach((skill) => {
|
tankSkills.skills.forEach((skill) => {
|
||||||
skills[skill] = permanentSkills.includes(skill) ? 7 : 0;
|
skills[skill] = permanentSkills.includes(skill) ? 7 : 0;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import { RatingInfo, Region, asset, superDecompress } from '@blitzkit/core';
|
// import { RatingInfo, Region, asset } from '@blitzkit/core';
|
||||||
|
|
||||||
const cache: Record<
|
// const cache: Record<
|
||||||
Region,
|
// Region,
|
||||||
Record<
|
// Record<
|
||||||
number,
|
// number,
|
||||||
RatingInfo & {
|
// RatingInfo & {
|
||||||
detail: undefined;
|
// detail: undefined;
|
||||||
}
|
// }
|
||||||
>
|
// >
|
||||||
> = {
|
// > = {
|
||||||
com: {},
|
// com: {},
|
||||||
eu: {},
|
// eu: {},
|
||||||
asia: {},
|
// asia: {},
|
||||||
};
|
// };
|
||||||
|
|
||||||
export async function getArchivedRatingInfo(region: Region, season: number) {
|
// export async function getArchivedRatingInfo(region: Region, season: number) {
|
||||||
if (!cache[region][season]) {
|
// if (!cache[region][season]) {
|
||||||
const info = await fetch(
|
// const info = await fetch(
|
||||||
asset(`regions/${region}/rating/${season}/info.cdon.lz4`),
|
// asset(`regions/${region}/rating/${season}/info.cdon.lz4`),
|
||||||
)
|
// )
|
||||||
.then((response) => response.arrayBuffer())
|
// .then((response) => response.arrayBuffer())
|
||||||
.then((buffer) =>
|
// .then((buffer) =>
|
||||||
superDecompress<RatingInfo & { detail: undefined }>(buffer),
|
// superDecompress<RatingInfo & { detail: undefined }>(buffer),
|
||||||
);
|
// );
|
||||||
cache[region][season] = info;
|
// cache[region][season] = info;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return cache[region][season];
|
// return cache[region][season];
|
||||||
}
|
// }
|
||||||
@@ -10,10 +10,9 @@ export * from './consumableDefinitions';
|
|||||||
export * from './createDefaultSkills';
|
export * from './createDefaultSkills';
|
||||||
export * from './degressiveStat';
|
export * from './degressiveStat';
|
||||||
export * from './discoveredIdDefinitions';
|
export * from './discoveredIdDefinitions';
|
||||||
// export * from './emblemURL';
|
export * from './emblemURL';
|
||||||
export * from './equipmentDefinitions';
|
export * from './equipmentDefinitions';
|
||||||
export * from './eventManager';
|
export * from './eventManager';
|
||||||
export * from './resolveGun';
|
|
||||||
// export * from './flagUserActivity';
|
// export * from './flagUserActivity';
|
||||||
export * from './gameDefinitions';
|
export * from './gameDefinitions';
|
||||||
// export * from './getArchivedLatestSeasonNumber';
|
// export * from './getArchivedLatestSeasonNumber';
|
||||||
@@ -23,7 +22,7 @@ export * from './gameDefinitions';
|
|||||||
// export * from './getTimeDaysAgo';
|
// export * from './getTimeDaysAgo';
|
||||||
export * from './isExplosive';
|
export * from './isExplosive';
|
||||||
// export * from './linkBlitzAndDiscord';
|
// export * from './linkBlitzAndDiscord';
|
||||||
// export * from './mapDefinitions';
|
export * from './mapDefinitions';
|
||||||
export * from './modelDefinitions';
|
export * from './modelDefinitions';
|
||||||
export * from './normalizeBoundingBox';
|
export * from './normalizeBoundingBox';
|
||||||
// export * from './parseBkni';
|
// export * from './parseBkni';
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { BoundingBox } from '@blitzkit/core';
|
import { BoundingBox, Vector3 } from '@blitzkit/core';
|
||||||
import { Vector3Tuple } from 'three';
|
|
||||||
|
|
||||||
export function normalizeBoundingBox(boundingBox: BoundingBox) {
|
export function normalizeBoundingBox(boundingBox: BoundingBox) {
|
||||||
return boundingBox.max.map(
|
return {
|
||||||
(max, index) => max - boundingBox.min[index],
|
x: boundingBox.max.x - boundingBox.min.x,
|
||||||
) as Vector3Tuple;
|
y: boundingBox.max.y - boundingBox.min.y,
|
||||||
|
z: boundingBox.max.z - boundingBox.min.z,
|
||||||
|
} satisfies Vector3;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
import { GunDefinition, ShellDefinition } from './tankDefinitions';
|
import {
|
||||||
|
GunDefinition,
|
||||||
|
GunDefinitionAutoReloaderProperties,
|
||||||
|
ShellDefinition,
|
||||||
|
} from '../protos';
|
||||||
|
|
||||||
export function resolveDpm(
|
export function resolveDpm(
|
||||||
gun: GunDefinition,
|
gun: GunDefinition,
|
||||||
@@ -7,30 +11,38 @@ export function resolveDpm(
|
|||||||
reloadCoefficient = 1,
|
reloadCoefficient = 1,
|
||||||
intraClipCoefficient = 1,
|
intraClipCoefficient = 1,
|
||||||
) {
|
) {
|
||||||
const alpha = shell.damage.armor * damageCoefficient;
|
const alpha = shell.armorDamage * damageCoefficient;
|
||||||
let dps: number;
|
let dps: number;
|
||||||
|
|
||||||
if (gun.type === 'regular') {
|
if (gun.gunType!.$case === 'regular') {
|
||||||
dps = alpha / (reloadCoefficient * gun.reload);
|
dps = alpha / (reloadCoefficient * gun.gunType!.value.extension.reload);
|
||||||
} else if (gun.type === 'autoLoader') {
|
} else if (gun.gunType!.$case === 'autoLoader') {
|
||||||
dps =
|
dps =
|
||||||
(alpha * gun.count) /
|
(alpha * gun.gunType!.value.extension.shellCount) /
|
||||||
(gun.reload * reloadCoefficient +
|
(gun.gunType!.value.extension.clipReload * reloadCoefficient +
|
||||||
(gun.count - 1) * gun.intraClip * intraClipCoefficient);
|
(gun.gunType!.value.extension.shellCount - 1) *
|
||||||
|
gun.gunType!.value.extension.intraClip *
|
||||||
|
intraClipCoefficient);
|
||||||
} else {
|
} else {
|
||||||
const mostOptimalShell = gun.reload.reduce<null | {
|
const mostOptimalShell =
|
||||||
index: number;
|
gun.gunType!.value.extension.shellReloads.reduce<null | {
|
||||||
reload: number;
|
index: number;
|
||||||
}>((current, reloadRaw, index) => {
|
reload: number;
|
||||||
const reload =
|
}>((current, reloadRaw, index) => {
|
||||||
reloadRaw * reloadCoefficient +
|
const reload =
|
||||||
(index > 0 ? gun.intraClip * intraClipCoefficient : 0);
|
reloadRaw * reloadCoefficient +
|
||||||
|
(index > 0
|
||||||
|
? (
|
||||||
|
gun.gunType!.value
|
||||||
|
.extension as GunDefinitionAutoReloaderProperties
|
||||||
|
).intraClip * intraClipCoefficient
|
||||||
|
: 0);
|
||||||
|
|
||||||
if (current === null || reload < current.reload) {
|
if (current === null || reload < current.reload) {
|
||||||
return { index, reload };
|
return { index, reload };
|
||||||
}
|
}
|
||||||
return current;
|
return current;
|
||||||
}, null)!;
|
}, null)!;
|
||||||
|
|
||||||
dps = alpha / mostOptimalShell?.reload;
|
dps = alpha / mostOptimalShell?.reload;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import { GunDefinition } from '../protos';
|
|
||||||
|
|
||||||
export function resolveGun(gun: GunDefinition) {
|
|
||||||
if (gun.regular) return gun.regular;
|
|
||||||
else if (gun.autoLoader) return gun.autoLoader;
|
|
||||||
else if (gun.autoReloader) return gun.autoReloader;
|
|
||||||
|
|
||||||
throw new Error('Could not resolve gun');
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ShellType } from '../blitzkit/tankDefinitions';
|
import { ShellType } from '../protos';
|
||||||
|
|
||||||
export function resolvePenetrationCoefficient(
|
export function resolvePenetrationCoefficient(
|
||||||
calibratedShells: boolean,
|
calibratedShells: boolean,
|
||||||
@@ -6,11 +6,11 @@ export function resolvePenetrationCoefficient(
|
|||||||
) {
|
) {
|
||||||
if (!calibratedShells) return 1;
|
if (!calibratedShells) return 1;
|
||||||
|
|
||||||
return type === 'ap'
|
return type === ShellType.AP
|
||||||
? 1.08
|
? 1.08
|
||||||
: type === 'ap_cr'
|
: type === ShellType.APCR
|
||||||
? 1.05
|
? 1.05
|
||||||
: type === 'hc'
|
: type === ShellType.HEAT
|
||||||
? 1.13
|
? 1.13
|
||||||
: 1.08;
|
: 1.08;
|
||||||
}
|
}
|
||||||
@@ -9,3 +9,4 @@ export * from './protos';
|
|||||||
export * from './statistics';
|
export * from './statistics';
|
||||||
export * from './streams';
|
export * from './streams';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ message Consumable {
|
|||||||
required uint32 id = 1;
|
required uint32 id = 1;
|
||||||
required string name = 2;
|
required string name = 2;
|
||||||
required uint32 cooldown = 3;
|
required uint32 cooldown = 3;
|
||||||
optional uint32 duration = 4;
|
optional float duration = 4;
|
||||||
required bool game_mode_exclusive = 5;
|
required bool game_mode_exclusive = 5;
|
||||||
repeated ConsumableTankFilter include = 6;
|
repeated ConsumableTankFilter include = 6;
|
||||||
repeated ConsumableTankFilter exclude = 7;
|
repeated ConsumableTankFilter exclude = 7;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ message ModelDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message Armor {
|
message Armor {
|
||||||
map<uint32, uint32> thickness = 1;
|
map<uint32, float> thickness = 1;
|
||||||
repeated uint32 spaced = 2;
|
repeated uint32 spaced = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,13 +52,13 @@ message BoundingBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message TrackModelDefinition {
|
message TrackModelDefinition {
|
||||||
required uint32 thickness = 1;
|
required float thickness = 1;
|
||||||
required Vector3 origin = 2;
|
required Vector3 origin = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GunModelDefinition {
|
message GunModelDefinition {
|
||||||
required Armor armor = 1;
|
required Armor armor = 1;
|
||||||
required uint32 thickness = 2;
|
required float thickness = 2;
|
||||||
required uint32 model_id = 3;
|
required uint32 model_id = 3;
|
||||||
required PitchLimits pitch = 4;
|
required PitchLimits pitch = 4;
|
||||||
optional float mask = 5;
|
optional float mask = 5;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ message TankDefinition {
|
|||||||
repeated EngineDefinition engines = 21;
|
repeated EngineDefinition engines = 21;
|
||||||
repeated TrackDefinition tracks = 22;
|
repeated TrackDefinition tracks = 22;
|
||||||
required TankPrice price = 23;
|
required TankPrice price = 23;
|
||||||
optional uint32 xp = 24;
|
optional ResearchCost research_cost = 24;
|
||||||
required float speed_forwards = 25;
|
required float speed_forwards = 25;
|
||||||
required float speed_backwards = 26;
|
required float speed_backwards = 26;
|
||||||
required float camouflage_still = 27;
|
required float camouflage_still = 27;
|
||||||
@@ -40,6 +40,18 @@ message TankDefinition {
|
|||||||
required uint32 weight = 31;
|
required uint32 weight = 31;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ResearchCost {
|
||||||
|
oneof research_cost_type {
|
||||||
|
uint32 xp = 1;
|
||||||
|
ResearchCostSeasonalTokens seasonal_tokens = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResearchCostSeasonalTokens {
|
||||||
|
required uint32 season = 1;
|
||||||
|
required uint32 tokens = 2;
|
||||||
|
}
|
||||||
|
|
||||||
enum TankPriceType {
|
enum TankPriceType {
|
||||||
TANK_PRICE_TYPE_CREDITS = 0;
|
TANK_PRICE_TYPE_CREDITS = 0;
|
||||||
TANK_PRICE_TYPE_GOLD = 1;
|
TANK_PRICE_TYPE_GOLD = 1;
|
||||||
@@ -56,7 +68,7 @@ message TrackDefinition {
|
|||||||
required string name = 3;
|
required string name = 3;
|
||||||
required uint32 weight = 4;
|
required uint32 weight = 4;
|
||||||
required float traverse_speed = 5;
|
required float traverse_speed = 5;
|
||||||
optional uint32 xp = 6;
|
optional ResearchCost research_cost = 6;
|
||||||
required float dispersion_move = 7;
|
required float dispersion_move = 7;
|
||||||
required float dispersion_traverse = 8;
|
required float dispersion_traverse = 8;
|
||||||
required float resistance_hard = 9;
|
required float resistance_hard = 9;
|
||||||
@@ -68,7 +80,7 @@ message TrackDefinition {
|
|||||||
message EngineDefinition {
|
message EngineDefinition {
|
||||||
required uint32 id = 1;
|
required uint32 id = 1;
|
||||||
required string name = 2;
|
required string name = 2;
|
||||||
optional uint32 xp = 3;
|
optional ResearchCost research_cost = 3;
|
||||||
required Tier tier = 4;
|
required Tier tier = 4;
|
||||||
required float fire_chance = 5;
|
required float fire_chance = 5;
|
||||||
required uint32 power = 6;
|
required uint32 power = 6;
|
||||||
@@ -81,7 +93,7 @@ message TurretDefinition {
|
|||||||
required uint32 health = 2;
|
required uint32 health = 2;
|
||||||
required uint32 view_range = 3;
|
required uint32 view_range = 3;
|
||||||
required float traverse_speed = 4;
|
required float traverse_speed = 4;
|
||||||
optional uint32 xp = 5;
|
optional ResearchCost research_cost = 5;
|
||||||
required string name = 6;
|
required string name = 6;
|
||||||
required Tier tier = 7;
|
required Tier tier = 7;
|
||||||
required uint32 weight = 8;
|
required uint32 weight = 8;
|
||||||
@@ -131,7 +143,7 @@ message GunDefinitionAutoReloaderProperties {
|
|||||||
message GunDefinitionBase {
|
message GunDefinitionBase {
|
||||||
required uint32 id = 1;
|
required uint32 id = 1;
|
||||||
required float rotation_speed = 2;
|
required float rotation_speed = 2;
|
||||||
optional uint32 xp = 3;
|
optional ResearchCost research_cost = 3;
|
||||||
required uint32 weight = 4;
|
required uint32 weight = 4;
|
||||||
required string name = 5;
|
required string name = 5;
|
||||||
required Tier tier = 6;
|
required Tier tier = 6;
|
||||||
@@ -151,13 +163,13 @@ message ShellDefinition {
|
|||||||
required uint32 velocity = 3;
|
required uint32 velocity = 3;
|
||||||
required uint32 armor_damage = 4;
|
required uint32 armor_damage = 4;
|
||||||
required uint32 module_damage = 5;
|
required uint32 module_damage = 5;
|
||||||
required uint32 caliber = 6;
|
required float caliber = 6;
|
||||||
required string icon = 7;
|
required string icon = 7;
|
||||||
required ShellPenetration penetration = 8;
|
required ShellPenetration penetration = 8;
|
||||||
required ShellType type = 9;
|
required ShellType type = 9;
|
||||||
required uint32 normalization = 10;
|
optional float normalization = 10;
|
||||||
required uint32 ricochet = 11;
|
optional float ricochet = 11;
|
||||||
required uint32 explosion_radius = 12;
|
optional float explosion_radius = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ShellType {
|
enum ShellType {
|
||||||
@@ -168,8 +180,8 @@ enum ShellType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ShellPenetration {
|
message ShellPenetration {
|
||||||
required uint32 near = 1;
|
required float near = 1;
|
||||||
required uint32 far = 2;
|
required float far = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Unlock {
|
message Unlock {
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import { tankDefinitions, Tier } from '../blitzkit/tankDefinitions';
|
import { fetchTankDefinitions } from '../blitzkit';
|
||||||
|
import { Tier } from '../protos';
|
||||||
import { BlitzStats } from './compositeStats/constants';
|
import { BlitzStats } from './compositeStats/constants';
|
||||||
|
|
||||||
export async function getTierWeights(
|
export async function getTierWeights(
|
||||||
stats: Record<number, BlitzStats>,
|
stats: Record<number, BlitzStats>,
|
||||||
order: number[] = Object.keys(stats).map(parseInt),
|
order: number[] = Object.keys(stats).map(parseInt),
|
||||||
) {
|
) {
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
const tierWeights: TierWeightsRecord = {};
|
const tierWeights: TierWeightsRecord = {};
|
||||||
|
|
||||||
order.forEach((id) => {
|
order.forEach((id) => {
|
||||||
const entry = awaitedTankDefinitions[id];
|
const entry = tankDefinitions.tanks[id];
|
||||||
|
|
||||||
if (!entry) return;
|
if (!entry) return;
|
||||||
if (!tierWeights[entry.tier]) tierWeights[entry.tier] = 0;
|
if (!tierWeights[entry.tier]) tierWeights[entry.tier] = 0;
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ import {
|
|||||||
EquipmentSlot,
|
EquipmentSlot,
|
||||||
GameDefinitions,
|
GameDefinitions,
|
||||||
GunDefinition,
|
GunDefinition,
|
||||||
|
GunDefinitionBase,
|
||||||
MapDefinitions,
|
MapDefinitions,
|
||||||
ModelDefinitions,
|
ModelDefinitions,
|
||||||
ModuleType,
|
ModuleType,
|
||||||
Provision,
|
Provision,
|
||||||
ProvisionDefinitions,
|
ProvisionDefinitions,
|
||||||
|
ResearchCost,
|
||||||
ShellType,
|
ShellType,
|
||||||
SkillDefinitions,
|
SkillDefinitions,
|
||||||
TankClass,
|
TankClass,
|
||||||
@@ -41,6 +43,24 @@ import { DATA } from './constants';
|
|||||||
import { Avatar } from './skillIcons';
|
import { Avatar } from './skillIcons';
|
||||||
import { TankParameters } from './tankIcons';
|
import { TankParameters } from './tankIcons';
|
||||||
|
|
||||||
|
function parseResearchCost(raw: number | string) {
|
||||||
|
if (typeof raw === 'number') {
|
||||||
|
return {
|
||||||
|
researchCostType: { $case: 'xp', value: raw },
|
||||||
|
} satisfies ResearchCost;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
researchCostType: {
|
||||||
|
$case: 'seasonalTokens',
|
||||||
|
value: {
|
||||||
|
season: Number(/prx_season_(\d+):\d+/.exec(raw)![1]),
|
||||||
|
tokens: Number(/prx_season_\d+:(\d+)/.exec(raw)![1]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies ResearchCost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type BlitzTankFilterDefinitionCategory = 'clip';
|
type BlitzTankFilterDefinitionCategory = 'clip';
|
||||||
const blitzTankFilterDefinitionCategoryToBlitzkit: Record<
|
const blitzTankFilterDefinitionCategoryToBlitzkit: Record<
|
||||||
BlitzTankFilterDefinitionCategory,
|
BlitzTankFilterDefinitionCategory,
|
||||||
@@ -75,8 +95,8 @@ type ShellDefinitionsList = Record<
|
|||||||
kind: ShellKind;
|
kind: ShellKind;
|
||||||
caliber: number;
|
caliber: number;
|
||||||
damage: { armor: number; devices: number };
|
damage: { armor: number; devices: number };
|
||||||
normalizationAngle: number;
|
normalizationAngle?: number;
|
||||||
ricochetAngle: number;
|
ricochetAngle?: number;
|
||||||
explosionRadius?: number;
|
explosionRadius?: number;
|
||||||
}
|
}
|
||||||
> & {
|
> & {
|
||||||
@@ -593,7 +613,7 @@ export async function definitions() {
|
|||||||
`${DATA}/XML/item_defs/tankmen/avatar.xml.dvpl`,
|
`${DATA}/XML/item_defs/tankmen/avatar.xml.dvpl`,
|
||||||
);
|
);
|
||||||
const maps = await readYAMLDVPL<Maps>(`${DATA}/maps.yaml.dvpl`);
|
const maps = await readYAMLDVPL<Maps>(`${DATA}/maps.yaml.dvpl`);
|
||||||
const tankXps = new Map<number, number>();
|
const tankXps = new Map<number, ResearchCost>();
|
||||||
const camouflagesXml = await readXMLDVPL<{ root: CamouflagesXML }>(
|
const camouflagesXml = await readXMLDVPL<{ root: CamouflagesXML }>(
|
||||||
`${DATA}/XML/item_defs/vehicles/common/camouflages.xml.dvpl`,
|
`${DATA}/XML/item_defs/vehicles/common/camouflages.xml.dvpl`,
|
||||||
);
|
);
|
||||||
@@ -726,10 +746,10 @@ export async function definitions() {
|
|||||||
for (const tankKey in tankList.root) {
|
for (const tankKey in tankList.root) {
|
||||||
if (botPattern.test(tankKey)) continue;
|
if (botPattern.test(tankKey)) continue;
|
||||||
|
|
||||||
const gunXps = new Map<number, number>();
|
const gunXps = new Map<number, ResearchCost>();
|
||||||
const turretXps = new Map<number, number>();
|
const turretXps = new Map<number, ResearchCost>();
|
||||||
const engineXps = new Map<number, number>();
|
const engineXps = new Map<number, ResearchCost>();
|
||||||
const trackXps = new Map<number, number>();
|
const trackXps = new Map<number, ResearchCost>();
|
||||||
const tank = tankList.root[tankKey];
|
const tank = tankList.root[tankKey];
|
||||||
let tankPrice: TankPrice;
|
let tankPrice: TankPrice;
|
||||||
const tankDefinition = await readXMLDVPL<{ root: VehicleDefinitions }>(
|
const tankDefinition = await readXMLDVPL<{ root: VehicleDefinitions }>(
|
||||||
@@ -794,6 +814,7 @@ export async function definitions() {
|
|||||||
({ type }) => blitzkitCrewTypeToBlitz[type] === crewKey,
|
({ type }) => blitzkitCrewTypeToBlitz[type] === crewKey,
|
||||||
);
|
);
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
|
if (crewKey === '#text') return;
|
||||||
entry = {
|
entry = {
|
||||||
type: blitzCrewTypeToBlitzkit[crewKey as BlitzCrewType],
|
type: blitzCrewTypeToBlitzkit[crewKey as BlitzCrewType],
|
||||||
count: 1,
|
count: 1,
|
||||||
@@ -808,12 +829,9 @@ export async function definitions() {
|
|||||||
entry.count++;
|
entry.count++;
|
||||||
|
|
||||||
if (value !== '') {
|
if (value !== '') {
|
||||||
entry.substitute = value
|
entry.substitute = value.split(/\n| /).map((member) => {
|
||||||
.split('\n')
|
return blitzCrewTypeToBlitzkit[member.trim() as BlitzCrewType];
|
||||||
.map(
|
});
|
||||||
(member) =>
|
|
||||||
blitzCrewTypeToBlitzkit[member.trim() as BlitzCrewType],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (entry.count === undefined) {
|
if (entry.count === undefined) {
|
||||||
@@ -1091,14 +1109,9 @@ export async function definitions() {
|
|||||||
? 'autoReloader'
|
? 'autoReloader'
|
||||||
: 'autoLoader'
|
: 'autoLoader'
|
||||||
: 'regular';
|
: 'regular';
|
||||||
const gunReload =
|
// const gunReload = gun.reloadTime;
|
||||||
gunType === 'autoReloader'
|
// const shellReloads =
|
||||||
? gun.pumpGunReloadTimes!.split(' ').map(Number)
|
const gunClipCount = gunType === 'regular' ? 1 : gun.clip!.count;
|
||||||
: gun.reloadTime;
|
|
||||||
const gunClipCount =
|
|
||||||
gunType === 'regular' ? undefined : gun.clip!.count;
|
|
||||||
const gunIntraClip =
|
|
||||||
gunType === 'regular' ? undefined : 60 / gun.clip!.rate;
|
|
||||||
const front = gun.extraPitchLimits?.front
|
const front = gun.extraPitchLimits?.front
|
||||||
? gun.extraPitchLimits.front.split(' ').map(Number)
|
? gun.extraPitchLimits.front.split(' ').map(Number)
|
||||||
: undefined;
|
: undefined;
|
||||||
@@ -1144,32 +1157,62 @@ export async function definitions() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
tankDefinitions.tanks[tankId].turrets[turretIndex].guns.push({
|
const base = {
|
||||||
id: gunId,
|
id: gunId,
|
||||||
weight: gunListEntry.weight,
|
weight: gunListEntry.weight,
|
||||||
rotationSpeed: gunListEntry.rotationSpeed,
|
rotationSpeed: gunListEntry.rotationSpeed,
|
||||||
name: gunName,
|
name: gunName,
|
||||||
tier: gunListEntry.level as Tier,
|
tier: gunListEntry.level as Tier,
|
||||||
shells: [],
|
shells: [],
|
||||||
type: gunType,
|
|
||||||
reload: gunReload,
|
|
||||||
count: gunClipCount,
|
|
||||||
intraClip: gunIntraClip,
|
|
||||||
camouflageLoss:
|
camouflageLoss:
|
||||||
typeof gun.invisibilityFactorAtShot === 'number'
|
typeof gun.invisibilityFactorAtShot === 'number'
|
||||||
? gun.invisibilityFactorAtShot
|
? gun.invisibilityFactorAtShot
|
||||||
: gun.invisibilityFactorAtShot.at(-1)!,
|
: gun.invisibilityFactorAtShot.at(-1)!,
|
||||||
aimTime: gun.aimingTime ?? gunListEntry.aimingTime,
|
aimTime: gun.aimingTime ?? gunListEntry.aimingTime,
|
||||||
dispersion: {
|
dispersionBase:
|
||||||
base:
|
gun.shotDispersionRadius ?? gunListEntry.shotDispersionRadius,
|
||||||
gun.shotDispersionRadius ??
|
dispersionDamaged: shotDispersionFactors.whileGunDamaged,
|
||||||
gunListEntry.shotDispersionRadius,
|
dispersionShot: shotDispersionFactors.afterShot,
|
||||||
damaged: shotDispersionFactors.whileGunDamaged,
|
dispersionTraverse: shotDispersionFactors.turretRotation,
|
||||||
shot: shotDispersionFactors.afterShot,
|
|
||||||
traverse: shotDispersionFactors.turretRotation,
|
|
||||||
},
|
|
||||||
unlocks: resolveUnlocks(gun.unlocks),
|
unlocks: resolveUnlocks(gun.unlocks),
|
||||||
} as GunDefinition);
|
} satisfies GunDefinitionBase;
|
||||||
|
|
||||||
|
tankDefinitions.tanks[tankId].turrets[turretIndex].guns.push({
|
||||||
|
gunType:
|
||||||
|
gunType === 'regular'
|
||||||
|
? {
|
||||||
|
$case: 'regular',
|
||||||
|
value: {
|
||||||
|
base,
|
||||||
|
extension: { reload: gun.reloadTime },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: gunType === 'autoReloader'
|
||||||
|
? {
|
||||||
|
$case: 'autoReloader',
|
||||||
|
value: {
|
||||||
|
base,
|
||||||
|
extension: {
|
||||||
|
intraClip: 60 / gun.clip!.rate,
|
||||||
|
shellCount: gunClipCount,
|
||||||
|
shellReloads: gun
|
||||||
|
.pumpGunReloadTimes!.split(' ')
|
||||||
|
.map(Number),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
$case: 'autoLoader',
|
||||||
|
value: {
|
||||||
|
base,
|
||||||
|
extension: {
|
||||||
|
intraClip: 60 / gun.clip!.rate,
|
||||||
|
clipReload: gun.reloadTime,
|
||||||
|
shellCount: gunClipCount,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies GunDefinition);
|
||||||
|
|
||||||
modelDefinitions.models[tankId].turrets[turretId].guns[gunId] = {
|
modelDefinitions.models[tankId].turrets[turretId].guns[gunId] = {
|
||||||
armor: gunArmor,
|
armor: gunArmor,
|
||||||
@@ -1214,33 +1257,27 @@ export async function definitions() {
|
|||||||
.filter((penetrationString) => penetrationString !== '')
|
.filter((penetrationString) => penetrationString !== '')
|
||||||
.map(Number);
|
.map(Number);
|
||||||
|
|
||||||
Object.values(
|
tankDefinitions.tanks[tankId].turrets[turretIndex].guns[
|
||||||
tankDefinitions.tanks[tankId].turrets[turretIndex].guns[
|
gunIndex
|
||||||
gunIndex
|
].gunType!.value.base.shells.push({
|
||||||
],
|
id: shellId,
|
||||||
).forEach((gun) => {
|
name: shellName,
|
||||||
gun.shells.push({
|
velocity: gunShellEntry.speed,
|
||||||
id: shellId,
|
armorDamage: shell.damage.armor,
|
||||||
name: shellName,
|
moduleDamage: shell.damage.devices,
|
||||||
speed: gunShellEntry.speed,
|
caliber: shell.caliber,
|
||||||
damage: {
|
normalization: shell.normalizationAngle,
|
||||||
armor: shell.damage.armor,
|
ricochet: shell.ricochetAngle,
|
||||||
module: shell.damage.devices,
|
type: blitzShellKindToBlitzkit[shell.kind],
|
||||||
},
|
explosionRadius:
|
||||||
caliber: shell.caliber,
|
shell.kind === 'HIGH_EXPLOSIVE'
|
||||||
normalization: shell.normalizationAngle,
|
? (shell.explosionRadius ?? 0)
|
||||||
ricochet: shell.ricochetAngle,
|
: undefined,
|
||||||
type: blitzShellKindToBlitzkit[shell.kind],
|
icon: shell.icon,
|
||||||
explosionRadius:
|
penetration: {
|
||||||
shell.kind === 'HIGH_EXPLOSIVE'
|
near: penetrationRaw[0],
|
||||||
? (shell.explosionRadius ?? 0)
|
far: penetrationRaw[1],
|
||||||
: undefined,
|
},
|
||||||
icon: shell.icon,
|
|
||||||
penetration:
|
|
||||||
penetrationRaw[0] === penetrationRaw[1]
|
|
||||||
? penetrationRaw[0]
|
|
||||||
: [penetrationRaw[0], penetrationRaw[1]],
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1258,7 +1295,7 @@ export async function definitions() {
|
|||||||
const currentTank = tankDefinitions.tanks[tankId];
|
const currentTank = tankDefinitions.tanks[tankId];
|
||||||
const successorId = toUniqueId(nation, tankListEntry.id);
|
const successorId = toUniqueId(nation, tankListEntry.id);
|
||||||
|
|
||||||
tankXps.set(successorId, vehicle.cost as number);
|
tankXps.set(successorId, parseResearchCost(vehicle.cost));
|
||||||
|
|
||||||
if (currentTank.successors === undefined) {
|
if (currentTank.successors === undefined) {
|
||||||
currentTank.successors = [];
|
currentTank.successors = [];
|
||||||
@@ -1272,7 +1309,7 @@ export async function definitions() {
|
|||||||
case 'gun': {
|
case 'gun': {
|
||||||
gunXps.set(
|
gunXps.set(
|
||||||
toUniqueId(nation, gunList.root.ids[vehicle['#text']]),
|
toUniqueId(nation, gunList.root.ids[vehicle['#text']]),
|
||||||
vehicle.cost as number,
|
parseResearchCost(vehicle.cost),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1280,7 +1317,7 @@ export async function definitions() {
|
|||||||
case 'turret': {
|
case 'turret': {
|
||||||
turretXps.set(
|
turretXps.set(
|
||||||
toUniqueId(nation, turretList.root.ids[vehicle['#text']]),
|
toUniqueId(nation, turretList.root.ids[vehicle['#text']]),
|
||||||
vehicle.cost as number,
|
parseResearchCost(vehicle.cost),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1288,7 +1325,7 @@ export async function definitions() {
|
|||||||
case 'engine': {
|
case 'engine': {
|
||||||
engineXps.set(
|
engineXps.set(
|
||||||
toUniqueId(nation, enginesList.root.ids[vehicle['#text']]),
|
toUniqueId(nation, enginesList.root.ids[vehicle['#text']]),
|
||||||
vehicle.cost as number,
|
parseResearchCost(vehicle.cost),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1296,7 +1333,7 @@ export async function definitions() {
|
|||||||
case 'chassis': {
|
case 'chassis': {
|
||||||
trackXps.set(
|
trackXps.set(
|
||||||
toUniqueId(nation, chassisList.root.ids[vehicle['#text']]),
|
toUniqueId(nation, chassisList.root.ids[vehicle['#text']]),
|
||||||
vehicle.cost as number,
|
parseResearchCost(vehicle.cost),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1307,31 +1344,31 @@ export async function definitions() {
|
|||||||
|
|
||||||
Object.values(tankDefinitions.tanks[tankId].turrets).forEach(
|
Object.values(tankDefinitions.tanks[tankId].turrets).forEach(
|
||||||
(turret) => {
|
(turret) => {
|
||||||
turret.xp = turretXps.get(turret.id);
|
turret.researchCost = turretXps.get(turret.id);
|
||||||
|
|
||||||
Object.values(turret.guns).forEach((gunRaw) => {
|
Object.values(turret.guns).forEach((gunRaw) => {
|
||||||
Object.values(gunRaw).forEach((gun) => {
|
gunRaw.gunType!.value.base.researchCost = gunXps.get(
|
||||||
gun.xp = gunXps.get(gun.id);
|
gunRaw.gunType!.value.base.id,
|
||||||
});
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Object.values(tankDefinitions.tanks[tankId].engines).forEach(
|
Object.values(tankDefinitions.tanks[tankId].engines).forEach(
|
||||||
(engine) => {
|
(engine) => {
|
||||||
engine.xp = engineXps.get(engine.id);
|
engine.researchCost = engineXps.get(engine.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Object.values(tankDefinitions.tanks[tankId].tracks).forEach((track) => {
|
Object.values(tankDefinitions.tanks[tankId].tracks).forEach((track) => {
|
||||||
track.xp = trackXps.get(track.id);
|
track.researchCost = trackXps.get(track.id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
Object.values(tankDefinitions.tanks).forEach((tank) => {
|
Object.values(tankDefinitions.tanks).forEach((tank) => {
|
||||||
tank.xp = tankXps.get(tank.id);
|
tank.researchCost = tankXps.get(tank.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.values(tankDefinitions.tanks).forEach((tank) => {
|
Object.values(tankDefinitions.tanks).forEach((tank) => {
|
||||||
@@ -1357,18 +1394,18 @@ export async function definitions() {
|
|||||||
([optionalDeviceSlotKey, optionalDeviceSlotEntry]) => {
|
([optionalDeviceSlotKey, optionalDeviceSlotEntry]) => {
|
||||||
if (optionalDeviceSlotKey === 'emptyPreset') return;
|
if (optionalDeviceSlotKey === 'emptyPreset') return;
|
||||||
|
|
||||||
equipmentDefinitions.presets[optionalDeviceSlotKey].slots = Object.values(
|
equipmentDefinitions.presets[optionalDeviceSlotKey] = {
|
||||||
optionalDeviceSlotEntry,
|
slots: Object.values(optionalDeviceSlotEntry)
|
||||||
)
|
.map((level) => {
|
||||||
.map((level) => {
|
return Object.values(level).map((options) => {
|
||||||
return Object.values(level).map((options) => {
|
return {
|
||||||
return {
|
left: optionalDevices.root[options.device0].id,
|
||||||
left: optionalDevices.root[options.device0].id,
|
right: optionalDevices.root[options.device1].id,
|
||||||
right: optionalDevices.root[options.device1].id,
|
} satisfies EquipmentSlot;
|
||||||
} satisfies EquipmentSlot;
|
});
|
||||||
});
|
})
|
||||||
})
|
.flat(),
|
||||||
.flat();
|
};
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1400,17 +1437,17 @@ export async function definitions() {
|
|||||||
entry.include.push({
|
entry.include.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'tiers',
|
$case: 'tiers',
|
||||||
tiers: { min: includeRaw.minLevel, max: includeRaw.maxLevel },
|
value: { min: includeRaw.minLevel, max: includeRaw.maxLevel },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else if ('name' in includeRaw) {
|
} else if ('name' in includeRaw) {
|
||||||
entry.include.push({
|
entry.include.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'ids',
|
$case: 'ids',
|
||||||
ids: {
|
value: {
|
||||||
ids: includeRaw.name
|
ids: includeRaw.name.split(/ +/).map((key) => {
|
||||||
.split(' ')
|
return tankStringIdMap[key];
|
||||||
.map((key) => tankStringIdMap[key]),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -1420,7 +1457,7 @@ export async function definitions() {
|
|||||||
entry.include.push({
|
entry.include.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'nations',
|
$case: 'nations',
|
||||||
nations: {
|
value: {
|
||||||
nations: consumable.vehicleFilter.include.nations.split(' '),
|
nations: consumable.vehicleFilter.include.nations.split(' '),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1435,10 +1472,10 @@ export async function definitions() {
|
|||||||
entry.exclude!.push({
|
entry.exclude!.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'ids',
|
$case: 'ids',
|
||||||
ids: {
|
value: {
|
||||||
ids: excludeRaw.name
|
ids: excludeRaw.name.split(/ +/).map((key) => {
|
||||||
.split(' ')
|
return tankStringIdMap[key];
|
||||||
.map((key) => tankStringIdMap[key]),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -1446,7 +1483,7 @@ export async function definitions() {
|
|||||||
entry.exclude!.push({
|
entry.exclude!.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'categories',
|
$case: 'categories',
|
||||||
categories: {
|
value: {
|
||||||
categories: excludeRaw.extendedTags
|
categories: excludeRaw.extendedTags
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.map(
|
.map(
|
||||||
@@ -1464,7 +1501,7 @@ export async function definitions() {
|
|||||||
entry.exclude!.push({
|
entry.exclude!.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'nations',
|
$case: 'nations',
|
||||||
nations: {
|
value: {
|
||||||
nations: consumable.vehicleFilter.exclude.nations.split(' '),
|
nations: consumable.vehicleFilter.exclude.nations.split(' '),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1500,7 +1537,7 @@ export async function definitions() {
|
|||||||
entry.include.push({
|
entry.include.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'tiers',
|
$case: 'tiers',
|
||||||
tiers: {
|
value: {
|
||||||
min: includeRaw.minLevel,
|
min: includeRaw.minLevel,
|
||||||
max: includeRaw.maxLevel,
|
max: includeRaw.maxLevel,
|
||||||
},
|
},
|
||||||
@@ -1510,10 +1547,10 @@ export async function definitions() {
|
|||||||
entry.include.push({
|
entry.include.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'ids',
|
$case: 'ids',
|
||||||
ids: {
|
value: {
|
||||||
ids: includeRaw.name
|
ids: includeRaw.name.split(/ +/).map((key) => {
|
||||||
.split(' ')
|
return tankStringIdMap[key];
|
||||||
.map((key) => tankStringIdMap[key]),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -1523,7 +1560,7 @@ export async function definitions() {
|
|||||||
entry.include.push({
|
entry.include.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'nations',
|
$case: 'nations',
|
||||||
nations: {
|
value: {
|
||||||
nations: provision.vehicleFilter.include.nations.split(' '),
|
nations: provision.vehicleFilter.include.nations.split(' '),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1538,9 +1575,9 @@ export async function definitions() {
|
|||||||
entry.exclude!.push({
|
entry.exclude!.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'ids',
|
$case: 'ids',
|
||||||
ids: {
|
value: {
|
||||||
ids: excludeRaw.name
|
ids: excludeRaw.name
|
||||||
.split(' ')
|
.split(/ +/)
|
||||||
.map((key) => tankStringIdMap[key]),
|
.map((key) => tankStringIdMap[key]),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1549,7 +1586,7 @@ export async function definitions() {
|
|||||||
entry.exclude!.push({
|
entry.exclude!.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'categories',
|
$case: 'categories',
|
||||||
categories: {
|
value: {
|
||||||
categories: excludeRaw.extendedTags
|
categories: excludeRaw.extendedTags
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.map(
|
.map(
|
||||||
@@ -1567,7 +1604,7 @@ export async function definitions() {
|
|||||||
entry.exclude!.push({
|
entry.exclude!.push({
|
||||||
filterType: {
|
filterType: {
|
||||||
$case: 'nations',
|
$case: 'nations',
|
||||||
nations: {
|
value: {
|
||||||
nations: provision.vehicleFilter.exclude.nations.split(' '),
|
nations: provision.vehicleFilter.exclude.nations.split(' '),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1617,47 +1654,47 @@ export async function definitions() {
|
|||||||
{
|
{
|
||||||
content: encodePB64(GameDefinitions, gameDefinitions),
|
content: encodePB64(GameDefinitions, gameDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/game.cdon.lz4',
|
path: 'definitions/game.pb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: encodePB64(TankDefinitions, tankDefinitions),
|
content: encodePB64(TankDefinitions, tankDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/tanks.cdon.lz4',
|
path: 'definitions/tanks.pb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: encodePB64(ModelDefinitions, modelDefinitions),
|
content: encodePB64(ModelDefinitions, modelDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/models.cdon.lz4',
|
path: 'definitions/models.pb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: encodePB64(EquipmentDefinitions, equipmentDefinitions),
|
content: encodePB64(EquipmentDefinitions, equipmentDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/equipment.cdon.lz4',
|
path: 'definitions/equipment.pb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: encodePB64(ConsumableDefinitions, consumableDefinitions),
|
content: encodePB64(ConsumableDefinitions, consumableDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/consumables.cdon.lz4',
|
path: 'definitions/consumables.pb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: encodePB64(ProvisionDefinitions, provisionDefinitions),
|
content: encodePB64(ProvisionDefinitions, provisionDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/provisions.cdon.lz4',
|
path: 'definitions/provisions.pb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: encodePB64(SkillDefinitions, skillDefinitions),
|
content: encodePB64(SkillDefinitions, skillDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/skills.cdon.lz4',
|
path: 'definitions/skills.pb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: encodePB64(MapDefinitions, mapDefinitions),
|
content: encodePB64(MapDefinitions, mapDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/maps.cdon.lz4',
|
path: 'definitions/maps.pb',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: encodePB64(CamouflageDefinitions, camouflageDefinitions),
|
content: encodePB64(CamouflageDefinitions, camouflageDefinitions),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: 'definitions/camouflages.cdon.lz4',
|
path: 'definitions/camouflages.pb',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,8 @@ for (const method of methods) {
|
|||||||
try {
|
try {
|
||||||
await method();
|
await method();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`Failed method ${method.name}; skipping...`, error);
|
console.warn(`Failed method ${method.name}; skipping...`);
|
||||||
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,9 +9,7 @@ export async function moduleIcons() {
|
|||||||
console.log('Building module icons...');
|
console.log('Building module icons...');
|
||||||
|
|
||||||
const changes = await Promise.all(
|
const changes = await Promise.all(
|
||||||
(
|
(await readdir(`${DATA}/Gfx/UI/ModulesTechTree`))
|
||||||
await readdir(`${DATA}/Gfx/UI/ModulesTechTree`)
|
|
||||||
)
|
|
||||||
.filter(
|
.filter(
|
||||||
(file) =>
|
(file) =>
|
||||||
!file.endsWith('@2x.packed.webp.dvpl') && file.startsWith('vehicle'),
|
!file.endsWith('@2x.packed.webp.dvpl') && file.startsWith('vehicle'),
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { tankDefinitions } from '@blitzkit/core';
|
import { fetchTankDefinitions } from '@blitzkit/core';
|
||||||
|
|
||||||
// random vercel bug forces require import
|
// random vercel bug forces require import
|
||||||
const { writeFileSync } = require('fs');
|
const { writeFileSync } = require('fs');
|
||||||
|
|
||||||
console.log('Building sitemap...');
|
console.log('Building sitemap...');
|
||||||
|
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
const values = Object.values(awaitedTankDefinitions);
|
const values = Object.values(tankDefinitions);
|
||||||
const txt = values
|
const txt = values
|
||||||
.map((tank) => `https://blitzkit.app/tools/tankopedia/${tank.id}/`)
|
.map((tank) => `https://blitzkit.app/tools/tankopedia/${tank.id}/`)
|
||||||
.join('\n');
|
.join('\n');
|
||||||
|
|||||||
@@ -1,22 +1,9 @@
|
|||||||
import {
|
import { createDefaultSkills } from '@blitzkit/core';
|
||||||
createDefaultSkills,
|
|
||||||
equipmentDefinitions,
|
|
||||||
modelDefinitions,
|
|
||||||
provisionDefinitions,
|
|
||||||
skillDefinitions,
|
|
||||||
tankDefinitions,
|
|
||||||
} from '@blitzkit/core';
|
|
||||||
import { PlusIcon } from '@radix-ui/react-icons';
|
import { PlusIcon } from '@radix-ui/react-icons';
|
||||||
import { Box, Flex, Heading, IconButton, Text } from '@radix-ui/themes';
|
import { Box, Flex, Heading, IconButton, Text } from '@radix-ui/themes';
|
||||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
||||||
import { use, useCallback, useEffect, useMemo, useState } from 'react';
|
import { use, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { CompareControls } from '../../../../../website/src/components/Controls';
|
|
||||||
import { DamageWarning } from '../../../../../website/src/components/DamageWarning';
|
|
||||||
import { PageWrapper } from '../../../components/PageWrapper';
|
|
||||||
import { tankCharacteristics } from '../../../core/blitzkit/tankCharacteristics';
|
|
||||||
import { tankToCompareMember } from '../../../core/blitzkit/tankToCompareMember';
|
|
||||||
import * as CompareEphemeral from '../../../stores/compareEphemeral';
|
import * as CompareEphemeral from '../../../stores/compareEphemeral';
|
||||||
import { CompareTable } from '../../../../../website/src/components/Compare/CompareTable';
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
import { averageDefinitionsArray, tankDefinitions } from '@blitzkit/core';
|
|
||||||
import { Table } from '@radix-ui/themes';
|
import { Table } from '@radix-ui/themes';
|
||||||
import { times } from 'lodash-es';
|
import { times } from 'lodash-es';
|
||||||
import { Suspense, use, useEffect, useMemo, useState } from 'react';
|
import { Suspense, use, useEffect, useMemo, useState } from 'react';
|
||||||
import { filterTank } from '../../../../core/blitzkit/filterTank';
|
|
||||||
import * as TankFilters from '../../../../stores/tankFilters';
|
|
||||||
import * as TankPerformancePersistent from '../../../../stores/tankPerformancePersistent';
|
|
||||||
import * as TankPerformanceSort from '../../../../stores/tankPerformanceSort';
|
|
||||||
import { RowLoader } from './RowLoader';
|
import { RowLoader } from './RowLoader';
|
||||||
import { TankRow } from './TankRow';
|
import { TankRow } from './TankRow';
|
||||||
import { Total } from './Total';
|
import { Total } from './Total';
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
averageDefinitionsArray,
|
|
||||||
formatCompact,
|
formatCompact,
|
||||||
TANK_CLASSES,
|
TANK_CLASSES,
|
||||||
TankClass,
|
TankClass,
|
||||||
tankDefinitions,
|
|
||||||
Tier,
|
Tier,
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import {
|
|||||||
STAT_NAMES,
|
STAT_NAMES,
|
||||||
Stat,
|
Stat,
|
||||||
UNLOCALIZED_REGION_NAMES_SHORT,
|
UNLOCALIZED_REGION_NAMES_SHORT,
|
||||||
blitzStarsTankAverages,
|
|
||||||
deltaTankStats,
|
deltaTankStats,
|
||||||
|
fetchTankDefinitions,
|
||||||
generateStats,
|
generateStats,
|
||||||
getAccountInfo,
|
getAccountInfo,
|
||||||
getTankStats,
|
getTankStats,
|
||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
prettifyStats,
|
prettifyStats,
|
||||||
searchPlayersAcrossRegions,
|
searchPlayersAcrossRegions,
|
||||||
sumBlitzStarsStats,
|
sumBlitzStarsStats,
|
||||||
tankDefinitions,
|
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
import {
|
import {
|
||||||
ArrowDownIcon,
|
ArrowDownIcon,
|
||||||
@@ -37,9 +36,8 @@ import {
|
|||||||
} from '@radix-ui/themes';
|
} from '@radix-ui/themes';
|
||||||
import { debounce } from 'lodash-es';
|
import { debounce } from 'lodash-es';
|
||||||
import { use, useEffect, useMemo, useRef, useState } from 'react';
|
import { use, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { PageWrapper } from '../../../components/PageWrapper';
|
|
||||||
import { TankRowHeaderCell } from '../../../components/TankRowHeaderCell';
|
const awaitedTankDefinitions = await fetchTankDefinitions();
|
||||||
import * as Session from '../../../stores/session';
|
|
||||||
|
|
||||||
export default function Page({
|
export default function Page({
|
||||||
searchParams,
|
searchParams,
|
||||||
@@ -47,8 +45,6 @@ export default function Page({
|
|||||||
searchParams: { id?: string };
|
searchParams: { id?: string };
|
||||||
}) {
|
}) {
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [loaded, setLoaded] = useState(false);
|
||||||
const awaitedTankDefinitions = use(tankDefinitions);
|
|
||||||
const awaitedTankAvearges = use(blitzStarsTankAverages);
|
|
||||||
const [showSearch, setShowSearch] = useState(false);
|
const [showSearch, setShowSearch] = useState(false);
|
||||||
const [searching, setSearching] = useState(false);
|
const [searching, setSearching] = useState(false);
|
||||||
const [searchResults, setSearchResults] = useState<AccountListWithServer>([]);
|
const [searchResults, setSearchResults] = useState<AccountListWithServer>([]);
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import {
|
import {
|
||||||
modelDefinitions,
|
fetchModelDefinitions,
|
||||||
provisionDefinitions,
|
fetchTankDefinitions,
|
||||||
tankDefinitions,
|
|
||||||
tankDefinitionsArray,
|
|
||||||
tankIcon,
|
tankIcon,
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
import strings from '@blitzkit/core/lang/en-US.json';
|
import strings from '@blitzkit/core/lang/en-US.json';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import * as Duel from '../../../../stores/duel';
|
|
||||||
import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral';
|
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
const tanks = await tankDefinitionsArray;
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
|
const tanks = Object.values(tankDefinitions.tanks);
|
||||||
return tanks.map((tank) => ({ id: `${tank.id}` }));
|
return tanks.map((tank) => ({ id: `${tank.id}` }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
|
const definitions = await fetchModelDefinitions();
|
||||||
|
|
||||||
export default async function Layout({
|
export default async function Layout({
|
||||||
children,
|
children,
|
||||||
params,
|
params,
|
||||||
@@ -24,11 +24,9 @@ export default async function Layout({
|
|||||||
params: { id: string };
|
params: { id: string };
|
||||||
}) {
|
}) {
|
||||||
const id = Number(params.id);
|
const id = Number(params.id);
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const tankModelDefinition = definitions[id];
|
||||||
const awaitedModelDefinitions = await modelDefinitions;
|
|
||||||
const tankModelDefinition = awaitedModelDefinitions[id];
|
|
||||||
const awaitedProvisionDefinitions = await provisionDefinitions;
|
const awaitedProvisionDefinitions = await provisionDefinitions;
|
||||||
const tank = awaitedTankDefinitions[id];
|
const tank = tankDefinitions[id];
|
||||||
const title = `${tank.name} - Tier ${TIER_ROMAN_NUMERALS[tank.tier]} ${
|
const title = `${tank.name} - Tier ${TIER_ROMAN_NUMERALS[tank.tier]} ${
|
||||||
(strings.common.nations_adjectives as Record<string, string>)[tank.nation]
|
(strings.common.nations_adjectives as Record<string, string>)[tank.nation]
|
||||||
} ${strings.common.tank_class_short[tank.class]}`;
|
} ${strings.common.tank_class_short[tank.class]}`;
|
||||||
@@ -38,7 +36,7 @@ export default async function Layout({
|
|||||||
<TankopediaEphemeral.Provider data={tankModelDefinition}>
|
<TankopediaEphemeral.Provider data={tankModelDefinition}>
|
||||||
<Duel.Provider
|
<Duel.Provider
|
||||||
data={{
|
data={{
|
||||||
tank: awaitedTankDefinitions[id],
|
tank: tankDefinitions[id],
|
||||||
provisionDefinitions: awaitedProvisionDefinitions,
|
provisionDefinitions: awaitedProvisionDefinitions,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -7,16 +7,5 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src/**/*", ".next/types/**/*.ts"]
|
||||||
"src/**/*",
|
|
||||||
".next/types/**/*.ts",
|
|
||||||
"../website/src/components/TankSearch/components/FilterControl.tsx",
|
|
||||||
"../website/src/components/Tankopedia/HeroSection/index.tsx",
|
|
||||||
"../website/src/components/Tankopedia/GameModeSection.tsx",
|
|
||||||
"../website/src/components/Tankopedia/CharacteristicsSection.tsx",
|
|
||||||
"../website/src/components/Tankopedia/MetaSection",
|
|
||||||
"../website/src/components/Tankopedia/HistorySection.tsx",
|
|
||||||
"../website/src/components/Tankopedia/CalloutsSection.tsx",
|
|
||||||
"../website/src/components/Tankopedia/ShotDisplaySection.tsx"
|
|
||||||
, "../website/src/components/Tankopedia/CharacteristicsSection/components/ConfigurationChildWrapper.tsx", "../website/src/components/Tankopedia/VideoSection.tsx", "../website/src/components/DamageWarning.tsx", "../website/src/components/Controls.tsx", "../website/src/components/Compare/CompareTable.tsx" ]
|
|
||||||
}
|
}
|
||||||
+8
-9
@@ -1,20 +1,19 @@
|
|||||||
import { compositeStatsKeys, tankDefinitionsArray } from '@blitzkit/core';
|
import { compositeStatsKeys, fetchTankDefinitions } from '@blitzkit/core';
|
||||||
import strings from '@blitzkit/core/lang/en-US.json';
|
import strings from '@blitzkit/core/lang/en-US.json';
|
||||||
import { use } from 'react';
|
import { breakdownConfig } from '../../constants/embeds';
|
||||||
import {
|
import { useEmbedStateCurry } from '../../stores/embedState/utilities';
|
||||||
BreakdownEmbedCard,
|
import { BreakdownEmbedCard, BreakdownEmbedWrapper } from '../TanksEmbed';
|
||||||
BreakdownEmbedWrapper,
|
|
||||||
} from '../../../../components/TanksEmbed';
|
|
||||||
import { breakdownConfig } from '../../../../../../website/src/constants/embeds';
|
|
||||||
import { useEmbedStateCurry } from '../../../../stores/embedState/utilities';
|
|
||||||
|
|
||||||
export const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({
|
export const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({
|
||||||
label: strings.common.composite_stats[value],
|
label: strings.common.composite_stats[value],
|
||||||
value,
|
value,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const tanks = await fetchTankDefinitions().then((tanks) =>
|
||||||
|
Object.values(tanks.tanks),
|
||||||
|
);
|
||||||
|
|
||||||
export function BreakdownPreview() {
|
export function BreakdownPreview() {
|
||||||
const tanks = use(tankDefinitionsArray);
|
|
||||||
const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
|
const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -6,7 +6,6 @@ import {
|
|||||||
fetchTankNames,
|
fetchTankNames,
|
||||||
normalizeBoundingBox,
|
normalizeBoundingBox,
|
||||||
resolveDpm,
|
resolveDpm,
|
||||||
resolveGun,
|
|
||||||
unionBoundingBox,
|
unionBoundingBox,
|
||||||
type TankDefinition,
|
type TankDefinition,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
@@ -115,10 +114,10 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.camouflageStill *
|
a.camouflageStill *
|
||||||
resolveGun(a.turrets.at(-1)!.guns.at(-1)!).gun!
|
a.turrets.at(-1)!.guns.at(-1)!.gunType!.value.base
|
||||||
.camouflageLoss -
|
.camouflageLoss -
|
||||||
b.camouflageStill *
|
b.camouflageStill *
|
||||||
resolveGun(b.turrets.at(-1)!.guns.at(-1)!).gun!
|
b.turrets.at(-1)!.guns.at(-1)!.gunType!.value.base
|
||||||
.camouflageLoss,
|
.camouflageLoss,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -143,8 +142,8 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
bTurretModelDefinition.boundingBox,
|
bTurretModelDefinition.boundingBox,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const aVolume = aSize[0] * aSize[1] * aSize[2];
|
const aVolume = aSize.x * aSize.y * aSize.z;
|
||||||
const bVolume = bSize[0] * bSize[1] * bSize[2];
|
const bVolume = bSize.x * bSize.y * bSize.z;
|
||||||
|
|
||||||
return aVolume - bVolume;
|
return aVolume - bVolume;
|
||||||
});
|
});
|
||||||
@@ -170,8 +169,8 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
bTurretModelDefinition.boundingBox,
|
bTurretModelDefinition.boundingBox,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const aLength = Math.max(aSize[0], aSize[1], aSize[2]);
|
const aLength = Math.max(aSize.x, aSize.y, aSize.z);
|
||||||
const bLength = Math.max(bSize[0], bSize[1], bSize[2]);
|
const bLength = Math.max(bSize.x, bSize.y, bSize.z);
|
||||||
|
|
||||||
return aLength - bLength;
|
return aLength - bLength;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { resolveNearPenetration, tankDefinitions } from '@blitzkit/core';
|
import { fetchTankDefinitions, TankType } from '@blitzkit/core';
|
||||||
import { Box, Flex, Heading, Text } from '@radix-ui/themes';
|
import { Box, Flex, Heading, Text } from '@radix-ui/themes';
|
||||||
import { Suspense, useEffect, useMemo, useRef } from 'react';
|
import { Suspense, useEffect, useMemo, useRef } from 'react';
|
||||||
import { NAVBAR_HEIGHT } from '../../../constants/navbar';
|
import { NAVBAR_HEIGHT } from '../../../constants/navbar';
|
||||||
@@ -11,7 +11,7 @@ import { Options } from './components/Options';
|
|||||||
import { TankSandbox } from './components/TankSandbox';
|
import { TankSandbox } from './components/TankSandbox';
|
||||||
import { TankSandboxLoader } from './components/TankSandboxLoader';
|
import { TankSandboxLoader } from './components/TankSandboxLoader';
|
||||||
|
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
|
|
||||||
export function HeroSection() {
|
export function HeroSection() {
|
||||||
const canvas = useRef<HTMLCanvasElement>(null);
|
const canvas = useRef<HTMLCanvasElement>(null);
|
||||||
@@ -20,13 +20,13 @@ export function HeroSection() {
|
|||||||
const Icon = classIcons[protagonist.class];
|
const Icon = classIcons[protagonist.class];
|
||||||
// const [dummyLoader, setDummyLoader] = useState(true);
|
// const [dummyLoader, setDummyLoader] = useState(true);
|
||||||
const treeColor =
|
const treeColor =
|
||||||
protagonist.treeType === 'collector'
|
protagonist.type === TankType.COLLECTOR
|
||||||
? 'blue'
|
? 'blue'
|
||||||
: protagonist.treeType === 'premium'
|
: protagonist.type === TankType.PREMIUM
|
||||||
? 'amber'
|
? 'amber'
|
||||||
: undefined;
|
: undefined;
|
||||||
const thicknessRange = useMemo(() => {
|
const thicknessRange = useMemo(() => {
|
||||||
const entries = Object.values(awaitedTankDefinitions);
|
const entries = Object.values(tankDefinitions.tanks);
|
||||||
const filtered = entries.filter(
|
const filtered = entries.filter(
|
||||||
(thisTank) => thisTank.tier === protagonist.tier,
|
(thisTank) => thisTank.tier === protagonist.tier,
|
||||||
);
|
);
|
||||||
@@ -34,9 +34,8 @@ export function HeroSection() {
|
|||||||
(filtered.reduce((accumulator, thisTank) => {
|
(filtered.reduce((accumulator, thisTank) => {
|
||||||
return (
|
return (
|
||||||
accumulator +
|
accumulator +
|
||||||
resolveNearPenetration(
|
thisTank.turrets.at(-1)!.guns.at(-1)!.gunType!.value.base.shells[0]
|
||||||
thisTank.turrets.at(-1)!.guns.at(-1)!.shells[0].penetration,
|
.penetration.near
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}, 0) /
|
}, 0) /
|
||||||
filtered.length) *
|
filtered.length) *
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { CompositeStatsKey } from '@blitzkit/core';
|
import { type CompositeStatsKey } from '@blitzkit/core';
|
||||||
import { grayA, grayDark, grayDarkA } from '@radix-ui/colors';
|
import { grayA, grayDark, grayDarkA } from '@radix-ui/colors';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import {
|
import {
|
||||||
BreakdownPreview,
|
BreakdownPreview,
|
||||||
compositeStatsKeysOptions,
|
compositeStatsKeysOptions,
|
||||||
} from '../../../website-legacy/src/app/tools/embed/configurations/breakdown';
|
} from '../components/Embeds/breakdown';
|
||||||
import type {
|
import type {
|
||||||
EmbedConfig,
|
EmbedConfig,
|
||||||
ExtractEmbedConfigTypes,
|
ExtractEmbedConfigTypes,
|
||||||
|
|||||||
Reference in new issue
Block a user