fix: some linting for new proto 5

This commit is contained in:
TrèsAbhi committed 2024-10-05 23:20:04 -05:00
1 parent 53a9c5f2de
commit 96310a9d63
40 files changed
+378 -336

No files matched your search

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