mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
(3) some definitions headers
This commit is contained in:
1 parent
fd8448b0a6
commit
244968bbbf
4 files changed
+175
-189
No files matched your search
@@ -16,10 +16,14 @@ import {
|
|||||||
OptionalDeviceSlots,
|
OptionalDeviceSlots,
|
||||||
ProvisionDefinitions,
|
ProvisionDefinitions,
|
||||||
ProvisionsCommon,
|
ProvisionsCommon,
|
||||||
|
ResearchCost,
|
||||||
SkillDefinitions,
|
SkillDefinitions,
|
||||||
|
sluggify,
|
||||||
SquadBattleTypeStylesYaml,
|
SquadBattleTypeStylesYaml,
|
||||||
TankDefinitions,
|
TankDefinitions,
|
||||||
TankmenAvatar,
|
TankmenAvatar,
|
||||||
|
toUniqueId,
|
||||||
|
VehicleDefinitionList,
|
||||||
} from "@blitzkit/core";
|
} from "@blitzkit/core";
|
||||||
import { SUPPORTED_LOCALE_BLITZ_MAP } from "@blitzkit/i18n";
|
import { SUPPORTED_LOCALE_BLITZ_MAP } from "@blitzkit/i18n";
|
||||||
import locales from "@blitzkit/i18n/locales.json";
|
import locales from "@blitzkit/i18n/locales.json";
|
||||||
@@ -29,11 +33,23 @@ import { BlitzKitAPI } from "./base";
|
|||||||
export class ServerBlitzKitAPI extends BlitzKitAPI {
|
export class ServerBlitzKitAPI extends BlitzKitAPI {
|
||||||
private vfs: AbstractVFS;
|
private vfs: AbstractVFS;
|
||||||
|
|
||||||
private stringsI18n: Record<string, Record<string, string>> = {};
|
private nationSlugDiscriminators = {
|
||||||
|
china: "cn",
|
||||||
|
european: "eu",
|
||||||
|
france: "fr",
|
||||||
|
germany: "de",
|
||||||
|
japan: "jp",
|
||||||
|
other: "ot",
|
||||||
|
uk: "gb",
|
||||||
|
usa: "us",
|
||||||
|
ussr: "ru",
|
||||||
|
};
|
||||||
|
|
||||||
|
private stringsI18n: Record<string, Record<string, string>> = {};
|
||||||
private nationsDir?: string[];
|
private nationsDir?: string[];
|
||||||
consumablesCommon: ConsumablesCommon = {};
|
private tankStringIdMap: Record<string, number> = {};
|
||||||
provisionsCommon: ProvisionsCommon = {};
|
private consumablesCommon: ConsumablesCommon = {};
|
||||||
|
private provisionsCommon: ProvisionsCommon = {};
|
||||||
|
|
||||||
// TODO: suffix with "yaml"s and "xml"s
|
// TODO: suffix with "yaml"s and "xml"s
|
||||||
private optionalDevices?: { root: OptionalDevices };
|
private optionalDevices?: { root: OptionalDevices };
|
||||||
@@ -45,6 +61,7 @@ export class ServerBlitzKitAPI extends BlitzKitAPI {
|
|||||||
private squadBattleTypeStyles?: SquadBattleTypeStylesYaml;
|
private squadBattleTypeStyles?: SquadBattleTypeStylesYaml;
|
||||||
private gameTypeSelectorStyles?: SquadBattleTypeStylesYaml;
|
private gameTypeSelectorStyles?: SquadBattleTypeStylesYaml;
|
||||||
private combatRoles?: CombatRolesYaml;
|
private combatRoles?: CombatRolesYaml;
|
||||||
|
private tierEqualizer?: string[][];
|
||||||
|
|
||||||
constructor(vfs: AbstractVFS) {
|
constructor(vfs: AbstractVFS) {
|
||||||
super();
|
super();
|
||||||
@@ -82,6 +99,10 @@ export class ServerBlitzKitAPI extends BlitzKitAPI {
|
|||||||
this.combatRoles = await this.vfs.yaml<CombatRolesYaml>(
|
this.combatRoles = await this.vfs.yaml<CombatRolesYaml>(
|
||||||
`Data/XML/item_defs/vehicles/common/combat_roles.yaml`,
|
`Data/XML/item_defs/vehicles/common/combat_roles.yaml`,
|
||||||
);
|
);
|
||||||
|
this.tierEqualizer = await this.vfs.csv(
|
||||||
|
`Data/XML/item_defs/vehicles/common/tier_equializer.csv`,
|
||||||
|
{ delimiter: ";" },
|
||||||
|
);
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
locales.supported.map(async ({ locale }) => {
|
locales.supported.map(async ({ locale }) => {
|
||||||
@@ -161,12 +182,144 @@ export class ServerBlitzKitAPI extends BlitzKitAPI {
|
|||||||
async tankDefinitions() {
|
async tankDefinitions() {
|
||||||
const tankDefinitions = TankDefinitions.create();
|
const tankDefinitions = TankDefinitions.create();
|
||||||
|
|
||||||
|
const gameModeNativeNames: Record<string, number> = {};
|
||||||
|
const squadBattleTypeGameModeNativeNameMatches =
|
||||||
|
this.squadBattleTypeStyles!.Prototypes[0].components.UIDataLocalBindingsComponent.data[1][2].matchAll(
|
||||||
|
/"(\d+)" -> "(battleType\/([a-zA-Z]+))"/g,
|
||||||
|
);
|
||||||
|
const gameTypeGameModeNativeNameMatches =
|
||||||
|
this.gameTypeSelectorStyles!.Prototypes[0].components.UIDataLocalBindingsComponent.data[1][2].matchAll(
|
||||||
|
/eGameMode\.([a-zA-Z]+) -> "~res:\/Gfx\/UI\/Hangar\/GameTypes\/battle-type_([^"]+)"/g,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const match of squadBattleTypeGameModeNativeNameMatches) {
|
||||||
|
const id = Number(match[1]);
|
||||||
|
gameModeNativeNames[match[3]] = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const match of gameTypeGameModeNativeNameMatches) {
|
||||||
|
Object.entries(gameModeNativeNames).forEach(([key, value]) => {
|
||||||
|
if (key.toLowerCase() === match[2].toLowerCase()) {
|
||||||
|
gameModeNativeNames[match[1]] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const botPattern = /^.+((tutorial_bot(\d+)?)|(TU))$/;
|
||||||
|
const slugRequesters = new Map<string, { id: number; key: string }[]>();
|
||||||
|
const idToNation: Record<number, string> = {};
|
||||||
|
|
||||||
|
for (const nation of this.nationsDir!) {
|
||||||
|
const tankList = await this.vfs.xml<{ root: VehicleDefinitionList }>(
|
||||||
|
`Data/XML/item_defs/vehicles/${nation}/list.xml`,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const tankKey in tankList.root) {
|
||||||
|
if (botPattern.test(tankKey)) continue;
|
||||||
|
|
||||||
|
const tank = tankList.root[tankKey];
|
||||||
|
const tankId = toUniqueId(nation, tank.id);
|
||||||
|
|
||||||
|
const name = (
|
||||||
|
(tank.shortUserString
|
||||||
|
? this.getString(tank.shortUserString)
|
||||||
|
: undefined) ?? this.getString(tank.userString)
|
||||||
|
).locales.en;
|
||||||
|
|
||||||
|
let slug = sluggify(name);
|
||||||
|
|
||||||
|
idToNation[tankId] = nation;
|
||||||
|
|
||||||
|
if (slugRequesters.has(slug)) {
|
||||||
|
slugRequesters.get(slug)!.push({ id: tankId, key: tankKey });
|
||||||
|
} else {
|
||||||
|
slugRequesters.set(slug, [{ id: tankId, key: tankKey }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const slugs = new Map<number, string>();
|
||||||
|
|
||||||
|
slugRequesters.forEach((requesters, slug) => {
|
||||||
|
if (requesters.length === 1) {
|
||||||
|
slugs.set(requesters[0].id, slug);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
`Multiple tanks share slug ${slug}: ${requesters
|
||||||
|
.map(({ key }) => key)
|
||||||
|
.join(", ")}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (requesters.length !== 2) {
|
||||||
|
throw new Error("Unresolvable number of duplicates :(");
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonCanonical = requesters.find(({ key }) => key.endsWith("TUR"));
|
||||||
|
|
||||||
|
if (nonCanonical === undefined) {
|
||||||
|
console.log("Using nations to discriminate");
|
||||||
|
// both are non-tutorial tanks, will have to discriminate using nation
|
||||||
|
|
||||||
|
requesters.forEach(({ id, key }) => {
|
||||||
|
const nation = idToNation[id];
|
||||||
|
const discriminator =
|
||||||
|
this.nationSlugDiscriminators[
|
||||||
|
nation as keyof typeof this.nationSlugDiscriminators
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log(`Solution: ${key} -> ${slug}-${discriminator}`);
|
||||||
|
slugs.set(id, `${slug}-${discriminator}`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("Using tutorial bot suffix to discriminate");
|
||||||
|
|
||||||
|
const canonical = requesters.find(({ key }) => !key.endsWith("TUR"));
|
||||||
|
|
||||||
|
if (canonical === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
"Two tutorial bots share the same slug? The world is truly broken.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Solution: ${canonical.key} -> ${slug}`);
|
||||||
|
slugs.set(canonical.id, slug);
|
||||||
|
console.log(`Solution: ${nonCanonical.key} -> ${slug}-tur`);
|
||||||
|
slugs.set(nonCanonical.id, `${slug}-tur`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tankXps = new Map<number, ResearchCost>();
|
||||||
|
|
||||||
return tankDefinitions;
|
return tankDefinitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
async camouflageDefinitions() {
|
async camouflageDefinitions() {
|
||||||
const camouflageDefinitions = CamouflageDefinitions.create();
|
const camouflageDefinitions = CamouflageDefinitions.create();
|
||||||
|
|
||||||
|
for (const camoKey in this.camouflagesXml!.root.camouflages) {
|
||||||
|
const camo = this.camouflagesXml!.root.camouflages[camoKey];
|
||||||
|
|
||||||
|
const yamlEntry = this.camouflagesYaml![camoKey];
|
||||||
|
const fullName = yamlEntry.userString
|
||||||
|
? this.getString(yamlEntry.userString)
|
||||||
|
: undefined;
|
||||||
|
const shortName = yamlEntry.shortUserString
|
||||||
|
? this.getString(yamlEntry.shortUserString)
|
||||||
|
: undefined;
|
||||||
|
const resolvedTankName = shortName ?? fullName;
|
||||||
|
const resolvedTankNameFull =
|
||||||
|
resolvedTankName === fullName ? undefined : fullName;
|
||||||
|
|
||||||
|
camouflageDefinitions.camouflages[camo.id] = {
|
||||||
|
id: camo.id,
|
||||||
|
name: this.getString(camo.userString),
|
||||||
|
tank_name: resolvedTankName,
|
||||||
|
tank_name_full: resolvedTankNameFull,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return camouflageDefinitions;
|
return camouflageDefinitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,3 +13,4 @@ export * from "./provisionsCommon";
|
|||||||
export * from "./squadBattleTypeStylesYaml";
|
export * from "./squadBattleTypeStylesYaml";
|
||||||
export * from "./tankmenAvatar";
|
export * from "./tankmenAvatar";
|
||||||
export * from "./tanksStats";
|
export * from "./tanksStats";
|
||||||
|
export * from "./vehicleDefinitionList";
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
export interface VehicleDefinitionList {
|
||||||
|
[key: string]: {
|
||||||
|
id: number;
|
||||||
|
userString: string;
|
||||||
|
shortUserString?: string;
|
||||||
|
description: string;
|
||||||
|
price: number | { gold: ""; "#text": number };
|
||||||
|
sellPrice?: { gold: ""; "#text": number };
|
||||||
|
enrichmentPermanentCost: number;
|
||||||
|
notInShop?: boolean;
|
||||||
|
tags: string;
|
||||||
|
level: number;
|
||||||
|
combatRole?: Record<string, string>;
|
||||||
|
configurationModes: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -20,7 +20,6 @@ import {
|
|||||||
ResearchCost,
|
ResearchCost,
|
||||||
ShellType,
|
ShellType,
|
||||||
SkillDefinitions,
|
SkillDefinitions,
|
||||||
sluggify,
|
|
||||||
TankClass,
|
TankClass,
|
||||||
TankDefinitions,
|
TankDefinitions,
|
||||||
TankPrice,
|
TankPrice,
|
||||||
@@ -30,24 +29,11 @@ import {
|
|||||||
Unlock,
|
Unlock,
|
||||||
Vector3,
|
Vector3,
|
||||||
} from "@blitzkit/core";
|
} from "@blitzkit/core";
|
||||||
import { readFile } from "fs/promises";
|
|
||||||
import { parse as parsePath } from "path";
|
import { parse as parsePath } from "path";
|
||||||
import type { Vector3Tuple } from "three";
|
import type { Vector3Tuple } from "three";
|
||||||
import { vfs } from "./constants";
|
import { vfs } from "./constants";
|
||||||
import type { TankParameters } from "./tankIcons";
|
import type { TankParameters } from "./tankIcons";
|
||||||
|
|
||||||
const nationSlugDiscriminators = {
|
|
||||||
china: "cn",
|
|
||||||
european: "eu",
|
|
||||||
france: "fr",
|
|
||||||
germany: "de",
|
|
||||||
japan: "jp",
|
|
||||||
other: "ot",
|
|
||||||
uk: "gb",
|
|
||||||
usa: "us",
|
|
||||||
ussr: "ru",
|
|
||||||
};
|
|
||||||
|
|
||||||
function parseResearchCost(raw: number | string) {
|
function parseResearchCost(raw: number | string) {
|
||||||
if (typeof raw === "number") {
|
if (typeof raw === "number") {
|
||||||
return {
|
return {
|
||||||
@@ -293,22 +279,6 @@ interface VehicleDefinitions {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export interface VehicleDefinitionList {
|
|
||||||
[key: string]: {
|
|
||||||
id: number;
|
|
||||||
userString: string;
|
|
||||||
shortUserString?: string;
|
|
||||||
description: string;
|
|
||||||
price: number | { gold: ""; "#text": number };
|
|
||||||
sellPrice?: { gold: ""; "#text": number };
|
|
||||||
enrichmentPermanentCost: number;
|
|
||||||
notInShop?: boolean;
|
|
||||||
tags: string;
|
|
||||||
level: number;
|
|
||||||
combatRole?: Record<string, string>;
|
|
||||||
configurationModes: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
interface TurretDefinitionsList {
|
interface TurretDefinitionsList {
|
||||||
nextAvailableId: number;
|
nextAvailableId: number;
|
||||||
ids: Record<string, number>;
|
ids: Record<string, number>;
|
||||||
@@ -406,7 +376,6 @@ const blitzShellKindToBlitzkit: Record<ShellKind, ShellType> = {
|
|||||||
HIGH_EXPLOSIVE: ShellType.SHELL_TYPE_HE,
|
HIGH_EXPLOSIVE: ShellType.SHELL_TYPE_HE,
|
||||||
HOLLOW_CHARGE: ShellType.SHELL_TYPE_HEAT,
|
HOLLOW_CHARGE: ShellType.SHELL_TYPE_HEAT,
|
||||||
};
|
};
|
||||||
export const botPattern = /^.+((tutorial_bot(\d+)?)|(TU))$/;
|
|
||||||
const blitzModuleTypeToBlitzkit: Record<keyof BlitzModuleType, ModuleType> = {
|
const blitzModuleTypeToBlitzkit: Record<keyof BlitzModuleType, ModuleType> = {
|
||||||
chassis: ModuleType.MODULE_TYPE_TRACKS,
|
chassis: ModuleType.MODULE_TYPE_TRACKS,
|
||||||
engine: ModuleType.MODULE_TYPE_ENGINE,
|
engine: ModuleType.MODULE_TYPE_ENGINE,
|
||||||
@@ -432,155 +401,6 @@ function assignArmor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function definitions() {
|
export async function definitions() {
|
||||||
const tankStringIdMap: Record<string, number> = {};
|
|
||||||
const tankXps = new Map<number, ResearchCost>();
|
|
||||||
|
|
||||||
const camouflagesXmlEntries = Object.entries(camouflagesXml.root.camouflages);
|
|
||||||
|
|
||||||
const gameModeNativeNames: Record<string, number> = {};
|
|
||||||
|
|
||||||
const consumableNativeNames: Record<string, number> = {};
|
|
||||||
const provisionNativeNames: Record<string, number> = {};
|
|
||||||
let equalizerDefinitions: string[][];
|
|
||||||
|
|
||||||
if (
|
|
||||||
await vfs.resolve("Data/XML/item_defs/vehicles/common/tier_equializer.csv")
|
|
||||||
) {
|
|
||||||
equalizerDefinitions = await vfs.csv(
|
|
||||||
`Data/XML/item_defs/vehicles/common/tier_equializer.csv`,
|
|
||||||
{ delimiter: ";" },
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const stubEqualizerDefinitions = await readFile("stub/equalizer.csv").then(
|
|
||||||
(buffer) => buffer.toString(),
|
|
||||||
);
|
|
||||||
|
|
||||||
equalizerDefinitions = await vfs._csv(stubEqualizerDefinitions, {
|
|
||||||
delimiter: ";",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const match of squadBattleTypeStyles.Prototypes[0].components.UIDataLocalBindingsComponent.data[1][2].matchAll(
|
|
||||||
/"(\d+)" -> "(battleType\/([a-zA-Z]+))"/g,
|
|
||||||
)) {
|
|
||||||
const id = Number(match[1]);
|
|
||||||
|
|
||||||
gameModeNativeNames[match[3]] = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const match of gameTypeSelectorStyles.Prototypes[0].components.UIDataLocalBindingsComponent.data[1][2].matchAll(
|
|
||||||
/eGameMode\.([a-zA-Z]+) -> "~res:\/Gfx\/UI\/Hangar\/GameTypes\/battle-type_([^"]+)"/g,
|
|
||||||
)) {
|
|
||||||
Object.entries(gameModeNativeNames).forEach(([key, value]) => {
|
|
||||||
if (key.toLowerCase() === match[2].toLowerCase()) {
|
|
||||||
gameModeNativeNames[match[1]] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
camouflagesXmlEntries.forEach(([camoKey, camo]) => {
|
|
||||||
const yamlEntry = camouflagesYaml[camoKey];
|
|
||||||
const fullName = yamlEntry.userString
|
|
||||||
? getString(yamlEntry.userString)
|
|
||||||
: undefined;
|
|
||||||
const shortName = yamlEntry.shortUserString
|
|
||||||
? getString(yamlEntry.shortUserString)
|
|
||||||
: undefined;
|
|
||||||
const resolvedTankName = shortName ?? fullName;
|
|
||||||
const resolvedTankNameFull =
|
|
||||||
resolvedTankName === fullName ? undefined : fullName;
|
|
||||||
|
|
||||||
camouflageDefinitions.camouflages[camo.id] = {
|
|
||||||
id: camo.id,
|
|
||||||
name: getString(camo.userString),
|
|
||||||
tank_name: resolvedTankName,
|
|
||||||
tank_name_full: resolvedTankNameFull,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const slugRequesters = new Map<string, { id: number; key: string }[]>();
|
|
||||||
const idToNation: Record<number, string> = {};
|
|
||||||
|
|
||||||
for (const nation of nationsDir) {
|
|
||||||
const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
|
|
||||||
`Data/XML/item_defs/vehicles/${nation}/list.xml`,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const tankKey in tankList.root) {
|
|
||||||
if (botPattern.test(tankKey)) continue;
|
|
||||||
|
|
||||||
const tank = tankList.root[tankKey];
|
|
||||||
const tankId = toUniqueId(nation, tank.id);
|
|
||||||
|
|
||||||
const name = (
|
|
||||||
(tank.shortUserString ? getString(tank.shortUserString) : undefined) ??
|
|
||||||
getString(tank.userString)
|
|
||||||
).locales.en;
|
|
||||||
|
|
||||||
let slug = sluggify(name);
|
|
||||||
|
|
||||||
idToNation[tankId] = nation;
|
|
||||||
|
|
||||||
if (slugRequesters.has(slug)) {
|
|
||||||
slugRequesters.get(slug)!.push({ id: tankId, key: tankKey });
|
|
||||||
} else {
|
|
||||||
slugRequesters.set(slug, [{ id: tankId, key: tankKey }]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const slugs = new Map<number, string>();
|
|
||||||
|
|
||||||
slugRequesters.forEach((requesters, slug) => {
|
|
||||||
if (requesters.length === 1) {
|
|
||||||
slugs.set(requesters[0].id, slug);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.warn(
|
|
||||||
`Multiple tanks share slug ${slug}: ${requesters
|
|
||||||
.map(({ key }) => key)
|
|
||||||
.join(", ")}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (requesters.length !== 2) {
|
|
||||||
throw new Error("Unresolvable number of duplicates :(");
|
|
||||||
}
|
|
||||||
|
|
||||||
const nonCanonical = requesters.find(({ key }) => key.endsWith("TUR"));
|
|
||||||
|
|
||||||
if (nonCanonical === undefined) {
|
|
||||||
console.log("Using nations to discriminate");
|
|
||||||
// both are non-tutorial tanks, will have to discriminate using nation
|
|
||||||
|
|
||||||
requesters.forEach(({ id, key }) => {
|
|
||||||
const nation = idToNation[id];
|
|
||||||
const discriminator =
|
|
||||||
nationSlugDiscriminators[
|
|
||||||
nation as keyof typeof nationSlugDiscriminators
|
|
||||||
];
|
|
||||||
|
|
||||||
console.log(`Solution: ${key} -> ${slug}-${discriminator}`);
|
|
||||||
slugs.set(id, `${slug}-${discriminator}`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log("Using tutorial bot suffix to discriminate");
|
|
||||||
|
|
||||||
const canonical = requesters.find(({ key }) => !key.endsWith("TUR"));
|
|
||||||
|
|
||||||
if (canonical === undefined) {
|
|
||||||
throw new Error(
|
|
||||||
"Two tutorial bots share the same slug? The world is truly broken.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Solution: ${canonical.key} -> ${slug}`);
|
|
||||||
slugs.set(canonical.id, slug);
|
|
||||||
console.log(`Solution: ${nonCanonical.key} -> ${slug}-tur`);
|
|
||||||
slugs.set(nonCanonical.id, `${slug}-tur`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const nation of nationsDir) {
|
for (const nation of nationsDir) {
|
||||||
const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
|
const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
|
||||||
`Data/XML/item_defs/vehicles/${nation}/list.xml`,
|
`Data/XML/item_defs/vehicles/${nation}/list.xml`,
|
||||||
@@ -742,7 +562,7 @@ export async function definitions() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const camouflages = camouflagesXmlEntries
|
const camouflages = Object.entries(camouflagesXml.root.camouflages)
|
||||||
.filter(([, camo]) => {
|
.filter(([, camo]) => {
|
||||||
if (!camo.vehicleFilter.include) return false;
|
if (!camo.vehicleFilter.include) return false;
|
||||||
if (camo.unlockCostCategory !== "legendary-skins-gold") return false;
|
if (camo.unlockCostCategory !== "legendary-skins-gold") return false;
|
||||||
@@ -761,7 +581,7 @@ export async function definitions() {
|
|||||||
})
|
})
|
||||||
.map(([, camo]) => camo.id);
|
.map(([, camo]) => camo.id);
|
||||||
|
|
||||||
let equalizerEntry = equalizerDefinitions.find(
|
let equalizerEntry = tierEqualizer.find(
|
||||||
(line) => line[0] === `${nation}:${tankKey}`,
|
(line) => line[0] === `${nation}:${tankKey}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1317,8 +1137,6 @@ export async function definitions() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Object.entries(consumablesCommon).forEach(([key, consumable]) => {
|
Object.entries(consumablesCommon).forEach(([key, consumable]) => {
|
||||||
consumableNativeNames[key] = consumable.id;
|
|
||||||
|
|
||||||
const entry: Consumable = {
|
const entry: Consumable = {
|
||||||
id: consumable.id,
|
id: consumable.id,
|
||||||
game_mode_exclusive: "gameModeFilter" in consumable,
|
game_mode_exclusive: "gameModeFilter" in consumable,
|
||||||
@@ -1417,8 +1235,6 @@ export async function definitions() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(provisionsCommon).forEach(([key, provision]) => {
|
Object.entries(provisionsCommon).forEach(([key, provision]) => {
|
||||||
provisionNativeNames[key] = provision.id;
|
|
||||||
|
|
||||||
const entry: Provision = {
|
const entry: Provision = {
|
||||||
id: provision.id,
|
id: provision.id,
|
||||||
exclude: [],
|
exclude: [],
|
||||||
|
|||||||
Reference in new issue
Block a user