diff --git a/.vscode/settings.json b/.vscode/settings.json index 11a6322cd..e499c3141 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -88,6 +88,7 @@ "gameplay", "glsl", "GLTF", + "gtag", "haha", "highp", "iife", @@ -110,6 +111,7 @@ "Maddoxkkm", "malum", "mantlets", + "mediump", "metallicness", "metalness", "minitelrose", diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..456d31ebb --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,50 @@ +# BlitzKit License + +Version 1.1, August 5th, 2025. Copyright (c) TrรจsAbhi. + +Permission is hereby granted to anyone to: + +- Fork, clone, and download the contents of this repository. +- Modify the code locally in private. +- Use and run the code **only for personal, non-public testing, or educational purposes**. + +The following restrictions apply: + +- You may **not** deploy, host, or make this project or any derivative publicly accessible. +- You may **not** share screenshots, recordings, or any form of media from this project unless you intend to merge your changes back into BlitzKit. +- You may **not** use this project or its contents in any public or commercial product. +- You may **not** redistribute modified or unmodified versions of this project. + +Contributions: + +- You are encouraged to propose changes or improvements via pull requests to the original BlitzKit repository. +- Any such contributions will be considered under the same license terms unless explicitly stated otherwise. + +Violations of this license may result in revocation of usage rights and takedown requests. + +For questions or licensing inquiries, contact support@blitzkit.app. + +## Notes on Existing Forks + +All forks fall under these categories: + +- If your fork was made from commit `8462901` (Apr 17, 2023) or between commits `2958124` (Jul 3, 2023) and `85e483e` (Jul 13, 2024), your fork falls under the **MIT license**. +- If your fork was made from commits between `5646093` (Jul 13, 2024) and `e3f131c` (Aug 5, 2025), your fork falls under the **AGPL-3.0 license**. +- If your fork was made between commit `f7c356d` (Apr 17, 2023) and `2958124` (Jul 3, 2023), your fork falls under **a default exclusive copyright**. +- If your fork was made from commits between `e3f131c` (Aug 5, 2025) and today, your fork falls under **this license**. + +MIT and AGPL-3.0 licensed fork owners: + +- You may continue to use your fork of BlitzKit under the corresponding license. +- You may upgrade your fork up to commit `5cab394` (Aug 4, 2025) and keep the AGPL-3.0 license. +- You may upgrade to commit `e3f131c` (Aug 5, 2025) or beyond but have to **switch to this license** where all rules apply. + - If you upgrade to commit `e3f131c` (Aug 5, 2025) or beyond, you must retract all public deployments of BlitzKit. + - Existing screenshots, recordings, or any form of media can remain. + +Default exclusive copyright fork owners: + +- You may continue to use their forks under the AGPL-3.0 license as no license was applied to BlitzKit at the time of forking. + +BlitzKit licensed fork owners: + +- You may continue to upgrade to the latest commits only under the conditions of this license. diff --git a/docs/changelogs/1.27.12.md b/docs/changelogs/1.27.12.md new file mode 100644 index 000000000..05ecc0f58 --- /dev/null +++ b/docs/changelogs/1.27.12.md @@ -0,0 +1,18 @@ +# BlitzKit 1.27.12 + +This update only affects the website. + +## Features + +- Added the ability to sort by HE shell penetration +- The Tankopedia compare bars now account for equipment and selected shells +- Made the hero section of the Tankopedia a bit shorter to show users that the page is scrollable + +## Fixes + +- The "Clear filters" button no longer shows up after clearing the search bar +- Guns for some tanks no longer go transparent when far away from the camera +- The dynamic armor tab no longer lags and flickers when rotating the turret of a tank +- Reimplemented the missing tool backgrounds in the navigation bar hamburger menu +- The navigation bar now properly goes transparent for pages that request like the Tankopedia pages +- Removed the tank name text outline because it doesn't work on most devices diff --git a/docs/changelogs/1.27.13.md b/docs/changelogs/1.27.13.md new file mode 100644 index 000000000..d9752d77f --- /dev/null +++ b/docs/changelogs/1.27.13.md @@ -0,0 +1,19 @@ +# BlitzKit 1.27.13 + +This update adds a feature for a future version of WoTB ๐Ÿ‘๏ธ๐Ÿ‘ƒ๐Ÿ‘๏ธ + +## Features + +- Added compatibility for the new mechanic for the upcoming Polish Tank Destroyers + - This code will remain dormant until the update for WoTB is released +- Added a progress bar to the hero section of the Tankopedia to show that the model is loading +- Reordered some Tankopedia statistics to bring important statistics like Damage to the very top + +## Fixes + +- The second column in the footer is now aligned on mobile devices +- Fixed an issue that stopped the armor highlighting from working on the Kiwi browser and on older devices + +## Technical Changes + +- Removed permissions for robots to crawl non-blitzkit.app domains diff --git a/docs/changelogs/1.27.14.md b/docs/changelogs/1.27.14.md new file mode 100644 index 000000000..fa56a08b7 --- /dev/null +++ b/docs/changelogs/1.27.14.md @@ -0,0 +1,8 @@ +# BlitzKit 1.27.14 + +This is the 14th patch for `1.27`, making it the new longest lasting version beating the previous record of `1.15.13`! + +## Fixes + +- Optimized the rendering of the shells in the Tankopedia search +- The Assault Shells cursor now works on iOS devices diff --git a/docs/changelogs/1.27.15.md b/docs/changelogs/1.27.15.md new file mode 100644 index 000000000..65a42d1f5 --- /dev/null +++ b/docs/changelogs/1.27.15.md @@ -0,0 +1,7 @@ +# BlitzKit 1.27.15 + +I did not see this coming + +## Fixes + +- The Assault Shell graph now supports damage factors of above 100% now diff --git a/package.json b/package.json index 9171bf7e0..f11f7d4ca 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "blitzkit", "private": true, - "version": "1.28.0-beta.1", + "version": "1.27.15", "description": "๐ŸŽ‰ Tools for everything World of Tanks Blitz", "type": "module", "types": "./types.d.ts", @@ -21,7 +21,8 @@ "dev:bot": "bun run build:bot --dev && bun start:bot", "start:bot": "bun dist/bot/main.js", "dev:docs": "vitepress dev docs", - "dev:website": "cd packages/website-ue && bun run dev", + "dev:website": "cd packages/website && bun run dev", + "dev": "bun run dev:website", "dev:api": "bun --filter=@blitzkit/api run dev", "setup:depotdownloader": "bun --filter=@blitzkit/scripts run setup:depotdownloader", "setup:patches": "bun --filter=@blitzkit/scripts run setup:patches", diff --git a/packages/core/src/blitzkit/youtubers.ts b/packages/core/src/blitzkit/youtubers.ts index e9a162c0f..b9f8d46f3 100644 --- a/packages/core/src/blitzkit/youtubers.ts +++ b/packages/core/src/blitzkit/youtubers.ts @@ -4,4 +4,6 @@ export const youtubers = [ { id: 'UCxRpZqMElssTdPYDK3x7wyg', name: 'N90' }, { id: 'UC28Hc6p2MGoB5s78eHCYkQg', name: 'GuidesBlitz' }, { id: 'UCLMEfqtlwLDN-UXX21RiEww', name: 'WoT Blitz Best Replays' }, + { id: 'UC3fZbetRUFoJL0IEN7IhG0Q', name: 'EconomicsMate' }, + { id: 'UCtsUVwBlhEnUunAKLn2dtsg', name: 'Megalion69' }, ]; diff --git a/packages/core/src/protos/camouflage_definitions.ts b/packages/core/src/protos/camouflage_definitions.ts index 1533bfd11..49336ed41 100644 --- a/packages/core/src/protos/camouflage_definitions.ts +++ b/packages/core/src/protos/camouflage_definitions.ts @@ -5,10 +5,10 @@ // source: packages/core/src/protos/camouflage_definitions.proto /* eslint-disable */ -import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { createBaseI18nString, I18nString } from "./i18n"; +import { BinaryReader, BinaryWriter } from '@bufbuild/protobuf/wire'; +import { createBaseI18nString, I18nString } from './i18n'; -export const protobufPackage = "blitzkit"; +export const protobufPackage = 'blitzkit'; export interface CamouflageDefinitions { camouflages: { [key: number]: Camouflage }; @@ -22,8 +22,8 @@ export interface CamouflageDefinitions_CamouflagesEntry { export interface Camouflage { id: number; name: I18nString; - tank_name?: I18nString | undefined; - tank_name_full?: I18nString | undefined; + tank_name?: I18nString; + tank_name_full?: I18nString; } export function createBaseCamouflageDefinitions(): CamouflageDefinitions { @@ -31,15 +31,25 @@ export function createBaseCamouflageDefinitions(): CamouflageDefinitions { } export const CamouflageDefinitions: MessageFns = { - encode(message: CamouflageDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: CamouflageDefinitions, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { Object.entries(message.camouflages).forEach(([key, value]) => { - CamouflageDefinitions_CamouflagesEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + CamouflageDefinitions_CamouflagesEntry.encode( + { key: key as any, value }, + writer.uint32(10).fork(), + ).join(); }); return writer; }, - decode(input: BinaryReader | Uint8Array, length?: number): CamouflageDefinitions { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): CamouflageDefinitions { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseCamouflageDefinitions(); while (reader.pos < end) { @@ -50,7 +60,10 @@ export const CamouflageDefinitions: MessageFns = { break; } - const entry1 = CamouflageDefinitions_CamouflagesEntry.decode(reader, reader.uint32()); + const entry1 = CamouflageDefinitions_CamouflagesEntry.decode( + reader, + reader.uint32(), + ); if (entry1.value !== undefined) { message.camouflages[entry1.key] = entry1.value; } @@ -68,10 +81,12 @@ export const CamouflageDefinitions: MessageFns = { fromJSON(object: any): CamouflageDefinitions { return { camouflages: isObject(object.camouflages) - ? Object.entries(object.camouflages).reduce<{ [key: number]: Camouflage }>((acc, [key, value]) => { - acc[globalThis.Number(key)] = Camouflage.fromJSON(value); - return acc; - }, {}) + ? Object.entries(object.camouflages).reduce<{ + [key: number]: Camouflage; + }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = Camouflage.fromJSON(value); + return acc; + }, {}) : {}, }; }, @@ -90,20 +105,23 @@ export const CamouflageDefinitions: MessageFns = { return obj; }, - create, I>>(base?: I): CamouflageDefinitions { + create, I>>( + base?: I, + ): CamouflageDefinitions { return CamouflageDefinitions.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): CamouflageDefinitions { + fromPartial, I>>( + object: I, + ): CamouflageDefinitions { const message = createBaseCamouflageDefinitions(); - message.camouflages = Object.entries(object.camouflages ?? {}).reduce<{ [key: number]: Camouflage }>( - (acc, [key, value]) => { - if (value !== undefined) { - acc[globalThis.Number(key)] = Camouflage.fromPartial(value); - } - return acc; - }, - {}, - ); + message.camouflages = Object.entries(object.camouflages ?? {}).reduce<{ + [key: number]: Camouflage; + }>((acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = Camouflage.fromPartial(value); + } + return acc; + }, {}); return message; }, }; @@ -112,90 +130,116 @@ export function createBaseCamouflageDefinitions_CamouflagesEntry(): CamouflageDe return { key: 0, value: createBaseCamouflage() }; } -export const CamouflageDefinitions_CamouflagesEntry: MessageFns = { - encode(message: CamouflageDefinitions_CamouflagesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.key !== undefined) { - writer.uint32(8).uint32(message.key); - } - if (message.value !== undefined) { - Camouflage.encode(message.value, writer.uint32(18).fork()).join(); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): CamouflageDefinitions_CamouflagesEntry { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseCamouflageDefinitions_CamouflagesEntry(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 8) { - break; - } - - message.key = reader.uint32(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.value = Camouflage.decode(reader, reader.uint32()); - continue; - } +export const CamouflageDefinitions_CamouflagesEntry: MessageFns = + { + encode( + message: CamouflageDefinitions_CamouflagesEntry, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(message.key); } - if ((tag & 7) === 4 || tag === 0) { - break; + if (message.value !== undefined) { + Camouflage.encode(message.value, writer.uint32(18).fork()).join(); } - reader.skip(tag & 7); - } - return message; - }, + return writer; + }, - fromJSON(object: any): CamouflageDefinitions_CamouflagesEntry { - return { - key: globalThis.Number(assertSet("CamouflageDefinitions_CamouflagesEntry.key", object.key)), - value: Camouflage.fromJSON(assertSet("CamouflageDefinitions_CamouflagesEntry.value", object.value)), - }; - }, + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): CamouflageDefinitions_CamouflagesEntry { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseCamouflageDefinitions_CamouflagesEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } - toJSON(message: CamouflageDefinitions_CamouflagesEntry): unknown { - const obj: any = {}; - if (message.key !== undefined) { - obj.key = Math.round(message.key); - } - if (message.value !== undefined) { - obj.value = Camouflage.toJSON(message.value); - } - return obj; - }, + message.key = reader.uint32(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } - create, I>>( - base?: I, - ): CamouflageDefinitions_CamouflagesEntry { - return CamouflageDefinitions_CamouflagesEntry.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>( - object: I, - ): CamouflageDefinitions_CamouflagesEntry { - const message = createBaseCamouflageDefinitions_CamouflagesEntry(); - message.key = object.key ?? 0; - message.value = (object.value !== undefined && object.value !== null) - ? Camouflage.fromPartial(object.value) - : createBaseCamouflage(); - return message; - }, -}; + message.value = Camouflage.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): CamouflageDefinitions_CamouflagesEntry { + return { + key: globalThis.Number( + assertSet('CamouflageDefinitions_CamouflagesEntry.key', object.key), + ), + value: Camouflage.fromJSON( + assertSet( + 'CamouflageDefinitions_CamouflagesEntry.value', + object.value, + ), + ), + }; + }, + + toJSON(message: CamouflageDefinitions_CamouflagesEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = Camouflage.toJSON(message.value); + } + return obj; + }, + + create< + I extends Exact, I>, + >(base?: I): CamouflageDefinitions_CamouflagesEntry { + return CamouflageDefinitions_CamouflagesEntry.fromPartial( + base ?? ({} as any), + ); + }, + fromPartial< + I extends Exact, I>, + >(object: I): CamouflageDefinitions_CamouflagesEntry { + const message = createBaseCamouflageDefinitions_CamouflagesEntry(); + message.key = object.key ?? 0; + message.value = + object.value !== undefined && object.value !== null + ? Camouflage.fromPartial(object.value) + : createBaseCamouflage(); + return message; + }, + }; export function createBaseCamouflage(): Camouflage { - return { id: 0, name: createBaseI18nString(), tank_name: undefined, tank_name_full: undefined }; + return { + id: 0, + name: createBaseI18nString(), + tank_name: undefined, + tank_name_full: undefined, + }; } export const Camouflage: MessageFns = { - encode(message: Camouflage, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: Camouflage, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.id !== 0) { writer.uint32(8).uint32(message.id); } @@ -206,13 +250,17 @@ export const Camouflage: MessageFns = { I18nString.encode(message.tank_name, writer.uint32(26).fork()).join(); } if (message.tank_name_full !== undefined) { - I18nString.encode(message.tank_name_full, writer.uint32(34).fork()).join(); + I18nString.encode( + message.tank_name_full, + writer.uint32(34).fork(), + ).join(); } return writer; }, decode(input: BinaryReader | Uint8Array, length?: number): Camouflage { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseCamouflage(); while (reader.pos < end) { @@ -261,10 +309,14 @@ export const Camouflage: MessageFns = { fromJSON(object: any): Camouflage { return { - id: globalThis.Number(assertSet("Camouflage.id", object.id)), - name: I18nString.fromJSON(assertSet("Camouflage.name", object.name)), - tank_name: isSet(object.tank_name) ? I18nString.fromJSON(object.tank_name) : undefined, - tank_name_full: isSet(object.tank_name_full) ? I18nString.fromJSON(object.tank_name_full) : undefined, + id: globalThis.Number(assertSet('Camouflage.id', object.id)), + name: I18nString.fromJSON(assertSet('Camouflage.name', object.name)), + tank_name: isSet(object.tank_name) + ? I18nString.fromJSON(object.tank_name) + : undefined, + tank_name_full: isSet(object.tank_name_full) + ? I18nString.fromJSON(object.tank_name_full) + : undefined, }; }, @@ -288,37 +340,57 @@ export const Camouflage: MessageFns = { create, I>>(base?: I): Camouflage { return Camouflage.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): Camouflage { + fromPartial, I>>( + object: I, + ): Camouflage { const message = createBaseCamouflage(); message.id = object.id ?? 0; - message.name = (object.name !== undefined && object.name !== null) - ? I18nString.fromPartial(object.name) - : createBaseI18nString(); - message.tank_name = (object.tank_name !== undefined && object.tank_name !== null) - ? I18nString.fromPartial(object.tank_name) - : undefined; - message.tank_name_full = (object.tank_name_full !== undefined && object.tank_name_full !== null) - ? I18nString.fromPartial(object.tank_name_full) - : undefined; + message.name = + object.name !== undefined && object.name !== null + ? I18nString.fromPartial(object.name) + : createBaseI18nString(); + message.tank_name = + object.tank_name !== undefined && object.tank_name !== null + ? I18nString.fromPartial(object.tank_name) + : undefined; + message.tank_name_full = + object.tank_name_full !== undefined && object.tank_name_full !== null + ? I18nString.fromPartial(object.tank_name_full) + : undefined; return message; }, }; -type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; +type Builtin = + | Date + | Function + | Uint8Array + | string + | number + | boolean + | undefined; -export type DeepPartial = T extends Builtin ? T - : T extends globalThis.Array ? globalThis.Array> - : T extends ReadonlyArray ? ReadonlyArray> - : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } - : T extends {} ? { [K in keyof T]?: DeepPartial } - : Partial; +export type DeepPartial = T extends Builtin + ? T + : T extends globalThis.Array + ? globalThis.Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends { $case: string; value: unknown } + ? { $case: T['$case']; value?: DeepPartial } + : T extends {} + ? { [K in keyof T]?: DeepPartial } + : Partial; type KeysOfUnion = T extends T ? keyof T : never; -export type Exact = P extends Builtin ? P - : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; +export type Exact = P extends Builtin + ? P + : P & { [K in keyof P]: Exact } & { + [K in Exclude>]: never; + }; function isObject(value: any): boolean { - return typeof value === "object" && value !== null; + return typeof value === 'object' && value !== null; } function isSet(value: any): boolean { diff --git a/packages/core/src/protos/tank_definitions.proto b/packages/core/src/protos/tank_definitions.proto index 7e10afba7..52143cbee 100644 --- a/packages/core/src/protos/tank_definitions.proto +++ b/packages/core/src/protos/tank_definitions.proto @@ -157,6 +157,17 @@ message GunDefinitionBase { required float dispersion_damaged = 13; repeated Unlock unlocks = 14; required uint32 shell_capacity = 15; + optional AssaultRanges assault_ranges = 16; +} + +message AssaultRanges { + repeated AssaultRange ranges = 1; + repeated ShellType types = 2; +} + +message AssaultRange { + required float distance = 1; + required float factor = 2; } message ShellDefinition { diff --git a/packages/core/src/protos/tank_definitions.ts b/packages/core/src/protos/tank_definitions.ts index 40e3026a3..3a4365730 100644 --- a/packages/core/src/protos/tank_definitions.ts +++ b/packages/core/src/protos/tank_definitions.ts @@ -5,10 +5,10 @@ // source: packages/core/src/protos/tank_definitions.proto /* eslint-disable */ -import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; -import { createBaseI18nString, I18nString } from "./i18n"; +import { BinaryReader, BinaryWriter } from '@bufbuild/protobuf/wire'; +import { I18nString } from './i18n'; -export const protobufPackage = "blitzkit"; +export const protobufPackage = 'blitzkit'; export enum TankPriceType { CREDITS = 0, @@ -18,24 +18,28 @@ export enum TankPriceType { export function tankPriceTypeFromJSON(object: any): TankPriceType { switch (object) { case 0: - case "TANK_PRICE_TYPE_CREDITS": + case 'TANK_PRICE_TYPE_CREDITS': return TankPriceType.CREDITS; case 1: - case "TANK_PRICE_TYPE_GOLD": + case 'TANK_PRICE_TYPE_GOLD': return TankPriceType.GOLD; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankPriceType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum TankPriceType', + ); } } export function tankPriceTypeToJSON(object: TankPriceType): string { switch (object) { case TankPriceType.CREDITS: - return "TANK_PRICE_TYPE_CREDITS"; + return 'TANK_PRICE_TYPE_CREDITS'; case TankPriceType.GOLD: - return "TANK_PRICE_TYPE_GOLD"; + return 'TANK_PRICE_TYPE_GOLD'; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankPriceType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum TankPriceType', + ); } } @@ -49,34 +53,38 @@ export enum ShellType { export function shellTypeFromJSON(object: any): ShellType { switch (object) { case 0: - case "SHELL_TYPE_AP": + case 'SHELL_TYPE_AP': return ShellType.AP; case 1: - case "SHELL_TYPE_APCR": + case 'SHELL_TYPE_APCR': return ShellType.APCR; case 2: - case "SHELL_TYPE_HEAT": + case 'SHELL_TYPE_HEAT': return ShellType.HEAT; case 3: - case "SHELL_TYPE_HE": + case 'SHELL_TYPE_HE': return ShellType.HE; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum ShellType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum ShellType', + ); } } export function shellTypeToJSON(object: ShellType): string { switch (object) { case ShellType.AP: - return "SHELL_TYPE_AP"; + return 'SHELL_TYPE_AP'; case ShellType.APCR: - return "SHELL_TYPE_APCR"; + return 'SHELL_TYPE_APCR'; case ShellType.HEAT: - return "SHELL_TYPE_HEAT"; + return 'SHELL_TYPE_HEAT'; case ShellType.HE: - return "SHELL_TYPE_HE"; + return 'SHELL_TYPE_HE'; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum ShellType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum ShellType', + ); } } @@ -91,39 +99,43 @@ export enum ModuleType { export function moduleTypeFromJSON(object: any): ModuleType { switch (object) { case 0: - case "MODULE_TYPE_VEHICLE": + case 'MODULE_TYPE_VEHICLE': return ModuleType.VEHICLE; case 1: - case "MODULE_TYPE_ENGINE": + case 'MODULE_TYPE_ENGINE': return ModuleType.ENGINE; case 2: - case "MODULE_TYPE_TRACKS": + case 'MODULE_TYPE_TRACKS': return ModuleType.TRACKS; case 3: - case "MODULE_TYPE_TURRET": + case 'MODULE_TYPE_TURRET': return ModuleType.TURRET; case 4: - case "MODULE_TYPE_GUN": + case 'MODULE_TYPE_GUN': return ModuleType.GUN; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum ModuleType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum ModuleType', + ); } } export function moduleTypeToJSON(object: ModuleType): string { switch (object) { case ModuleType.VEHICLE: - return "MODULE_TYPE_VEHICLE"; + return 'MODULE_TYPE_VEHICLE'; case ModuleType.ENGINE: - return "MODULE_TYPE_ENGINE"; + return 'MODULE_TYPE_ENGINE'; case ModuleType.TRACKS: - return "MODULE_TYPE_TRACKS"; + return 'MODULE_TYPE_TRACKS'; case ModuleType.TURRET: - return "MODULE_TYPE_TURRET"; + return 'MODULE_TYPE_TURRET'; case ModuleType.GUN: - return "MODULE_TYPE_GUN"; + return 'MODULE_TYPE_GUN'; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum ModuleType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum ModuleType', + ); } } @@ -137,34 +149,38 @@ export enum TankClass { export function tankClassFromJSON(object: any): TankClass { switch (object) { case 0: - case "TANK_CLASS_LIGHT": + case 'TANK_CLASS_LIGHT': return TankClass.LIGHT; case 1: - case "TANK_CLASS_MEDIUM": + case 'TANK_CLASS_MEDIUM': return TankClass.MEDIUM; case 2: - case "TANK_CLASS_HEAVY": + case 'TANK_CLASS_HEAVY': return TankClass.HEAVY; case 3: - case "TANK_CLASS_TANK_DESTROYER": + case 'TANK_CLASS_TANK_DESTROYER': return TankClass.TANK_DESTROYER; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankClass"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum TankClass', + ); } } export function tankClassToJSON(object: TankClass): string { switch (object) { case TankClass.LIGHT: - return "TANK_CLASS_LIGHT"; + return 'TANK_CLASS_LIGHT'; case TankClass.MEDIUM: - return "TANK_CLASS_MEDIUM"; + return 'TANK_CLASS_MEDIUM'; case TankClass.HEAVY: - return "TANK_CLASS_HEAVY"; + return 'TANK_CLASS_HEAVY'; case TankClass.TANK_DESTROYER: - return "TANK_CLASS_TANK_DESTROYER"; + return 'TANK_CLASS_TANK_DESTROYER'; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankClass"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum TankClass', + ); } } @@ -177,29 +193,33 @@ export enum TankType { export function tankTypeFromJSON(object: any): TankType { switch (object) { case 0: - case "TANK_TYPE_RESEARCHABLE": + case 'TANK_TYPE_RESEARCHABLE': return TankType.RESEARCHABLE; case 1: - case "TANK_TYPE_PREMIUM": + case 'TANK_TYPE_PREMIUM': return TankType.PREMIUM; case 2: - case "TANK_TYPE_COLLECTOR": + case 'TANK_TYPE_COLLECTOR': return TankType.COLLECTOR; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum TankType', + ); } } export function tankTypeToJSON(object: TankType): string { switch (object) { case TankType.RESEARCHABLE: - return "TANK_TYPE_RESEARCHABLE"; + return 'TANK_TYPE_RESEARCHABLE'; case TankType.PREMIUM: - return "TANK_TYPE_PREMIUM"; + return 'TANK_TYPE_PREMIUM'; case TankType.COLLECTOR: - return "TANK_TYPE_COLLECTOR"; + return 'TANK_TYPE_COLLECTOR'; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum TankType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum TankType', + ); } } @@ -214,39 +234,43 @@ export enum CrewType { export function crewTypeFromJSON(object: any): CrewType { switch (object) { case 0: - case "CREW_TYPE_COMMANDER": + case 'CREW_TYPE_COMMANDER': return CrewType.COMMANDER; case 1: - case "CREW_TYPE_RADIOMAN": + case 'CREW_TYPE_RADIOMAN': return CrewType.RADIOMAN; case 2: - case "CREW_TYPE_GUNNER": + case 'CREW_TYPE_GUNNER': return CrewType.GUNNER; case 3: - case "CREW_TYPE_DRIVER": + case 'CREW_TYPE_DRIVER': return CrewType.DRIVER; case 4: - case "CREW_TYPE_LOADER": + case 'CREW_TYPE_LOADER': return CrewType.LOADER; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum CrewType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum CrewType', + ); } } export function crewTypeToJSON(object: CrewType): string { switch (object) { case CrewType.COMMANDER: - return "CREW_TYPE_COMMANDER"; + return 'CREW_TYPE_COMMANDER'; case CrewType.RADIOMAN: - return "CREW_TYPE_RADIOMAN"; + return 'CREW_TYPE_RADIOMAN'; case CrewType.GUNNER: - return "CREW_TYPE_GUNNER"; + return 'CREW_TYPE_GUNNER'; case CrewType.DRIVER: - return "CREW_TYPE_DRIVER"; + return 'CREW_TYPE_DRIVER'; case CrewType.LOADER: - return "CREW_TYPE_LOADER"; + return 'CREW_TYPE_LOADER'; default: - throw new globalThis.Error("Unrecognized enum value " + object + " for enum CrewType"); + throw new globalThis.Error( + 'Unrecognized enum value ' + object + ' for enum CrewType', + ); } } @@ -299,8 +323,8 @@ export interface TankDefinition_RolesEntry { export interface ResearchCost { research_cost_type?: - | { $case: "xp"; value: number } - | { $case: "seasonal_tokens"; value: ResearchCostSeasonalTokens } + | { $case: 'xp'; value: number } + | { $case: 'seasonal_tokens'; value: ResearchCostSeasonalTokens } | undefined; } @@ -355,9 +379,9 @@ export interface TurretDefinition { export interface GunDefinition { gun_type?: - | { $case: "regular"; value: GunDefinitionRegular } - | { $case: "auto_loader"; value: GunDefinitionAutoLoader } - | { $case: "auto_reloader"; value: GunDefinitionAutoReloader } + | { $case: 'regular'; value: GunDefinitionRegular } + | { $case: 'auto_loader'; value: GunDefinitionAutoLoader } + | { $case: 'auto_reloader'; value: GunDefinitionAutoReloader } | undefined; } @@ -408,6 +432,17 @@ export interface GunDefinitionBase { dispersion_damaged: number; unlocks: Unlock[]; shell_capacity: number; + assault_ranges?: AssaultRanges | undefined; +} + +export interface AssaultRanges { + ranges: AssaultRange[]; + types: ShellType[]; +} + +export interface AssaultRange { + distance: number; + factor: number; } export interface ShellDefinition { @@ -448,20 +483,27 @@ export interface Crew { substitute: CrewType[]; } -export function createBaseTankDefinitions(): TankDefinitions { +function createBaseTankDefinitions(): TankDefinitions { return { tanks: {} }; } export const TankDefinitions: MessageFns = { - encode(message: TankDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: TankDefinitions, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { Object.entries(message.tanks).forEach(([key, value]) => { - TankDefinitions_TanksEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + TankDefinitions_TanksEntry.encode( + { key: key as any, value }, + writer.uint32(10).fork(), + ).join(); }); return writer; }, decode(input: BinaryReader | Uint8Array, length?: number): TankDefinitions { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseTankDefinitions(); while (reader.pos < end) { @@ -472,7 +514,10 @@ export const TankDefinitions: MessageFns = { break; } - const entry1 = TankDefinitions_TanksEntry.decode(reader, reader.uint32()); + const entry1 = TankDefinitions_TanksEntry.decode( + reader, + reader.uint32(), + ); if (entry1.value !== undefined) { message.tanks[entry1.key] = entry1.value; } @@ -490,10 +535,12 @@ export const TankDefinitions: MessageFns = { fromJSON(object: any): TankDefinitions { return { tanks: isObject(object.tanks) - ? Object.entries(object.tanks).reduce<{ [key: number]: TankDefinition }>((acc, [key, value]) => { - acc[globalThis.Number(key)] = TankDefinition.fromJSON(value); - return acc; - }, {}) + ? Object.entries(object.tanks).reduce<{ + [key: number]: TankDefinition; + }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = TankDefinition.fromJSON(value); + return acc; + }, {}) : {}, }; }, @@ -512,106 +559,124 @@ export const TankDefinitions: MessageFns = { return obj; }, - create, I>>(base?: I): TankDefinitions { + create, I>>( + base?: I, + ): TankDefinitions { return TankDefinitions.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): TankDefinitions { + fromPartial, I>>( + object: I, + ): TankDefinitions { const message = createBaseTankDefinitions(); - message.tanks = Object.entries(object.tanks ?? {}).reduce<{ [key: number]: TankDefinition }>( - (acc, [key, value]) => { - if (value !== undefined) { - acc[globalThis.Number(key)] = TankDefinition.fromPartial(value); - } - return acc; - }, - {}, - ); + message.tanks = Object.entries(object.tanks ?? {}).reduce<{ + [key: number]: TankDefinition; + }>((acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = TankDefinition.fromPartial(value); + } + return acc; + }, {}); return message; }, }; -export function createBaseTankDefinitions_TanksEntry(): TankDefinitions_TanksEntry { - return { key: 0, value: createBaseTankDefinition() }; +function createBaseTankDefinitions_TanksEntry(): TankDefinitions_TanksEntry { + return { key: 0, value: undefined }; } -export const TankDefinitions_TanksEntry: MessageFns = { - encode(message: TankDefinitions_TanksEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.key !== undefined) { - writer.uint32(8).uint32(message.key); - } - if (message.value !== undefined) { - TankDefinition.encode(message.value, writer.uint32(18).fork()).join(); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): TankDefinitions_TanksEntry { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseTankDefinitions_TanksEntry(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 8) { - break; - } - - message.key = reader.uint32(); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.value = TankDefinition.decode(reader, reader.uint32()); - continue; - } +export const TankDefinitions_TanksEntry: MessageFns = + { + encode( + message: TankDefinitions_TanksEntry, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.key !== 0) { + writer.uint32(8).uint32(message.key); } - if ((tag & 7) === 4 || tag === 0) { - break; + if (message.value !== undefined) { + TankDefinition.encode(message.value, writer.uint32(18).fork()).join(); } - reader.skip(tag & 7); - } - return message; - }, + return writer; + }, - fromJSON(object: any): TankDefinitions_TanksEntry { - return { - key: globalThis.Number(assertSet("TankDefinitions_TanksEntry.key", object.key)), - value: TankDefinition.fromJSON(assertSet("TankDefinitions_TanksEntry.value", object.value)), - }; - }, + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): TankDefinitions_TanksEntry { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseTankDefinitions_TanksEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } - toJSON(message: TankDefinitions_TanksEntry): unknown { - const obj: any = {}; - if (message.key !== undefined) { - obj.key = Math.round(message.key); - } - if (message.value !== undefined) { - obj.value = TankDefinition.toJSON(message.value); - } - return obj; - }, + message.key = reader.uint32(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } - create, I>>(base?: I): TankDefinitions_TanksEntry { - return TankDefinitions_TanksEntry.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>(object: I): TankDefinitions_TanksEntry { - const message = createBaseTankDefinitions_TanksEntry(); - message.key = object.key ?? 0; - message.value = (object.value !== undefined && object.value !== null) - ? TankDefinition.fromPartial(object.value) - : createBaseTankDefinition(); - return message; - }, -}; + message.value = TankDefinition.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, -export function createBaseTankDefinition(): TankDefinition { + fromJSON(object: any): TankDefinitions_TanksEntry { + return { + key: isSet(object.key) ? globalThis.Number(object.key) : 0, + value: isSet(object.value) + ? TankDefinition.fromJSON(object.value) + : undefined, + }; + }, + + toJSON(message: TankDefinitions_TanksEntry): unknown { + const obj: any = {}; + if (message.key !== 0) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = TankDefinition.toJSON(message.value); + } + return obj; + }, + + create, I>>( + base?: I, + ): TankDefinitions_TanksEntry { + return TankDefinitions_TanksEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): TankDefinitions_TanksEntry { + const message = createBaseTankDefinitions_TanksEntry(); + message.key = object.key ?? 0; + message.value = + object.value !== undefined && object.value !== null + ? TankDefinition.fromPartial(object.value) + : undefined; + return message; + }, + }; + +function createBaseTankDefinition(): TankDefinition { return { id: 0, - slug: "", + slug: '', roles: {}, fixed_camouflage: false, camouflages: [], @@ -619,8 +684,8 @@ export function createBaseTankDefinition(): TankDefinition { successors: [], crew: [], health: 0, - nation: "", - name: createBaseI18nString(), + nation: '', + name: undefined, type: 0, max_consumables: 0, max_provisions: 0, @@ -631,28 +696,34 @@ export function createBaseTankDefinition(): TankDefinition { turrets: [], engines: [], tracks: [], - price: createBaseTankPrice(), + price: undefined, research_cost: undefined, speed_forwards: 0, speed_backwards: 0, camouflage_still: 0, camouflage_moving: 0, camouflage_onFire: 0, - equipment_preset: "", + equipment_preset: '', weight: 0, }; } export const TankDefinition: MessageFns = { - encode(message: TankDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: TankDefinition, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.id !== 0) { writer.uint32(8).uint32(message.id); } - if (message.slug !== "") { + if (message.slug !== '') { writer.uint32(18).string(message.slug); } Object.entries(message.roles).forEach(([key, value]) => { - TankDefinition_RolesEntry.encode({ key: key as any, value }, writer.uint32(26).fork()).join(); + TankDefinition_RolesEntry.encode( + { key: key as any, value }, + writer.uint32(26).fork(), + ).join(); }); if (message.fixed_camouflage !== false) { writer.uint32(40).bool(message.fixed_camouflage); @@ -678,7 +749,7 @@ export const TankDefinition: MessageFns = { if (message.health !== 0) { writer.uint32(80).uint32(message.health); } - if (message.nation !== "") { + if (message.nation !== '') { writer.uint32(90).string(message.nation); } if (message.name !== undefined) { @@ -718,7 +789,10 @@ export const TankDefinition: MessageFns = { TankPrice.encode(message.price, writer.uint32(186).fork()).join(); } if (message.research_cost !== undefined) { - ResearchCost.encode(message.research_cost, writer.uint32(194).fork()).join(); + ResearchCost.encode( + message.research_cost, + writer.uint32(194).fork(), + ).join(); } if (message.speed_forwards !== 0) { writer.uint32(205).float(message.speed_forwards); @@ -735,7 +809,7 @@ export const TankDefinition: MessageFns = { if (message.camouflage_onFire !== 0) { writer.uint32(237).float(message.camouflage_onFire); } - if (message.equipment_preset !== "") { + if (message.equipment_preset !== '') { writer.uint32(242).string(message.equipment_preset); } if (message.weight !== 0) { @@ -745,7 +819,8 @@ export const TankDefinition: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): TankDefinition { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseTankDefinition(); while (reader.pos < end) { @@ -772,7 +847,10 @@ export const TankDefinition: MessageFns = { break; } - const entry3 = TankDefinition_RolesEntry.decode(reader, reader.uint32()); + const entry3 = TankDefinition_RolesEntry.decode( + reader, + reader.uint32(), + ); if (entry3.value !== undefined) { message.roles[entry3.key] = entry3.value; } @@ -933,7 +1011,9 @@ export const TankDefinition: MessageFns = { break; } - message.turrets.push(TurretDefinition.decode(reader, reader.uint32())); + message.turrets.push( + TurretDefinition.decode(reader, reader.uint32()), + ); continue; } case 21: { @@ -941,7 +1021,9 @@ export const TankDefinition: MessageFns = { break; } - message.engines.push(EngineDefinition.decode(reader, reader.uint32())); + message.engines.push( + EngineDefinition.decode(reader, reader.uint32()), + ); continue; } case 22: { @@ -1035,15 +1117,20 @@ export const TankDefinition: MessageFns = { fromJSON(object: any): TankDefinition { return { - id: globalThis.Number(assertSet("TankDefinition.id", object.id)), - slug: globalThis.String(assertSet("TankDefinition.slug", object.slug)), + id: isSet(object.id) ? globalThis.Number(object.id) : 0, + slug: isSet(object.slug) ? globalThis.String(object.slug) : '', roles: isObject(object.roles) - ? Object.entries(object.roles).reduce<{ [key: number]: number }>((acc, [key, value]) => { - acc[globalThis.Number(key)] = Number(value); - return acc; - }, {}) + ? Object.entries(object.roles).reduce<{ [key: number]: number }>( + (acc, [key, value]) => { + acc[globalThis.Number(key)] = Number(value); + return acc; + }, + {}, + ) : {}, - fixed_camouflage: globalThis.Boolean(assertSet("TankDefinition.fixed_camouflage", object.fixed_camouflage)), + fixed_camouflage: isSet(object.fixed_camouflage) + ? globalThis.Boolean(object.fixed_camouflage) + : false, camouflages: globalThis.Array.isArray(object?.camouflages) ? object.camouflages.map((e: any) => globalThis.Number(e)) : [], @@ -1056,16 +1143,24 @@ export const TankDefinition: MessageFns = { crew: globalThis.Array.isArray(object?.crew) ? object.crew.map((e: any) => Crew.fromJSON(e)) : [], - health: globalThis.Number(assertSet("TankDefinition.health", object.health)), - nation: globalThis.String(assertSet("TankDefinition.nation", object.nation)), - name: I18nString.fromJSON(assertSet("TankDefinition.name", object.name)), - type: tankTypeFromJSON(assertSet("TankDefinition.type", object.type)), - max_consumables: globalThis.Number(assertSet("TankDefinition.max_consumables", object.max_consumables)), - max_provisions: globalThis.Number(assertSet("TankDefinition.max_provisions", object.max_provisions)), - tier: globalThis.Number(assertSet("TankDefinition.tier", object.tier)), - class: tankClassFromJSON(assertSet("TankDefinition.class", object.class)), - testing: globalThis.Boolean(assertSet("TankDefinition.testing", object.testing)), - deprecated: globalThis.Boolean(assertSet("TankDefinition.deprecated", object.deprecated)), + health: isSet(object.health) ? globalThis.Number(object.health) : 0, + nation: isSet(object.nation) ? globalThis.String(object.nation) : '', + name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined, + type: isSet(object.type) ? tankTypeFromJSON(object.type) : 0, + max_consumables: isSet(object.max_consumables) + ? globalThis.Number(object.max_consumables) + : 0, + max_provisions: isSet(object.max_provisions) + ? globalThis.Number(object.max_provisions) + : 0, + tier: isSet(object.tier) ? globalThis.Number(object.tier) : 0, + class: isSet(object.class) ? tankClassFromJSON(object.class) : 0, + testing: isSet(object.testing) + ? globalThis.Boolean(object.testing) + : false, + deprecated: isSet(object.deprecated) + ? globalThis.Boolean(object.deprecated) + : false, turrets: globalThis.Array.isArray(object?.turrets) ? object.turrets.map((e: any) => TurretDefinition.fromJSON(e)) : [], @@ -1075,15 +1170,29 @@ export const TankDefinition: MessageFns = { tracks: globalThis.Array.isArray(object?.tracks) ? object.tracks.map((e: any) => TrackDefinition.fromJSON(e)) : [], - price: TankPrice.fromJSON(assertSet("TankDefinition.price", object.price)), - research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined, - speed_forwards: globalThis.Number(assertSet("TankDefinition.speed_forwards", object.speed_forwards)), - speed_backwards: globalThis.Number(assertSet("TankDefinition.speed_backwards", object.speed_backwards)), - camouflage_still: globalThis.Number(assertSet("TankDefinition.camouflage_still", object.camouflage_still)), - camouflage_moving: globalThis.Number(assertSet("TankDefinition.camouflage_moving", object.camouflage_moving)), - camouflage_onFire: globalThis.Number(assertSet("TankDefinition.camouflage_onFire", object.camouflage_onFire)), - equipment_preset: globalThis.String(assertSet("TankDefinition.equipment_preset", object.equipment_preset)), - weight: globalThis.Number(assertSet("TankDefinition.weight", object.weight)), + price: isSet(object.price) ? TankPrice.fromJSON(object.price) : undefined, + research_cost: isSet(object.research_cost) + ? ResearchCost.fromJSON(object.research_cost) + : undefined, + speed_forwards: isSet(object.speed_forwards) + ? globalThis.Number(object.speed_forwards) + : 0, + speed_backwards: isSet(object.speed_backwards) + ? globalThis.Number(object.speed_backwards) + : 0, + camouflage_still: isSet(object.camouflage_still) + ? globalThis.Number(object.camouflage_still) + : 0, + camouflage_moving: isSet(object.camouflage_moving) + ? globalThis.Number(object.camouflage_moving) + : 0, + camouflage_onFire: isSet(object.camouflage_onFire) + ? globalThis.Number(object.camouflage_onFire) + : 0, + equipment_preset: isSet(object.equipment_preset) + ? globalThis.String(object.equipment_preset) + : '', + weight: isSet(object.weight) ? globalThis.Number(object.weight) : 0, }; }, @@ -1092,7 +1201,7 @@ export const TankDefinition: MessageFns = { if (message.id !== 0) { obj.id = Math.round(message.id); } - if (message.slug !== "") { + if (message.slug !== '') { obj.slug = message.slug; } if (message.roles) { @@ -1122,7 +1231,7 @@ export const TankDefinition: MessageFns = { if (message.health !== 0) { obj.health = Math.round(message.health); } - if (message.nation !== "") { + if (message.nation !== '') { obj.nation = message.nation; } if (message.name !== undefined) { @@ -1179,7 +1288,7 @@ export const TankDefinition: MessageFns = { if (message.camouflage_onFire !== 0) { obj.camouflage_onFire = message.camouflage_onFire; } - if (message.equipment_preset !== "") { + if (message.equipment_preset !== '') { obj.equipment_preset = message.equipment_preset; } if (message.weight !== 0) { @@ -1188,14 +1297,20 @@ export const TankDefinition: MessageFns = { return obj; }, - create, I>>(base?: I): TankDefinition { + create, I>>( + base?: I, + ): TankDefinition { return TankDefinition.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): TankDefinition { + fromPartial, I>>( + object: I, + ): TankDefinition { const message = createBaseTankDefinition(); message.id = object.id ?? 0; - message.slug = object.slug ?? ""; - message.roles = Object.entries(object.roles ?? {}).reduce<{ [key: number]: number }>((acc, [key, value]) => { + message.slug = object.slug ?? ''; + message.roles = Object.entries(object.roles ?? {}).reduce<{ + [key: number]: number; + }>((acc, [key, value]) => { if (value !== undefined) { acc[globalThis.Number(key)] = globalThis.Number(value); } @@ -1207,10 +1322,11 @@ export const TankDefinition: MessageFns = { message.successors = object.successors?.map((e) => e) || []; message.crew = object.crew?.map((e) => Crew.fromPartial(e)) || []; message.health = object.health ?? 0; - message.nation = object.nation ?? ""; - message.name = (object.name !== undefined && object.name !== null) - ? I18nString.fromPartial(object.name) - : createBaseI18nString(); + message.nation = object.nation ?? ''; + message.name = + object.name !== undefined && object.name !== null + ? I18nString.fromPartial(object.name) + : undefined; message.type = object.type ?? 0; message.max_consumables = object.max_consumables ?? 0; message.max_provisions = object.max_provisions ?? 0; @@ -1218,121 +1334,145 @@ export const TankDefinition: MessageFns = { message.class = object.class ?? 0; message.testing = object.testing ?? false; message.deprecated = object.deprecated ?? false; - message.turrets = object.turrets?.map((e) => TurretDefinition.fromPartial(e)) || []; - message.engines = object.engines?.map((e) => EngineDefinition.fromPartial(e)) || []; - message.tracks = object.tracks?.map((e) => TrackDefinition.fromPartial(e)) || []; - message.price = (object.price !== undefined && object.price !== null) - ? TankPrice.fromPartial(object.price) - : createBaseTankPrice(); - message.research_cost = (object.research_cost !== undefined && object.research_cost !== null) - ? ResearchCost.fromPartial(object.research_cost) - : undefined; + message.turrets = + object.turrets?.map((e) => TurretDefinition.fromPartial(e)) || []; + message.engines = + object.engines?.map((e) => EngineDefinition.fromPartial(e)) || []; + message.tracks = + object.tracks?.map((e) => TrackDefinition.fromPartial(e)) || []; + message.price = + object.price !== undefined && object.price !== null + ? TankPrice.fromPartial(object.price) + : undefined; + message.research_cost = + object.research_cost !== undefined && object.research_cost !== null + ? ResearchCost.fromPartial(object.research_cost) + : undefined; message.speed_forwards = object.speed_forwards ?? 0; message.speed_backwards = object.speed_backwards ?? 0; message.camouflage_still = object.camouflage_still ?? 0; message.camouflage_moving = object.camouflage_moving ?? 0; message.camouflage_onFire = object.camouflage_onFire ?? 0; - message.equipment_preset = object.equipment_preset ?? ""; + message.equipment_preset = object.equipment_preset ?? ''; message.weight = object.weight ?? 0; return message; }, }; -export function createBaseTankDefinition_RolesEntry(): TankDefinition_RolesEntry { +function createBaseTankDefinition_RolesEntry(): TankDefinition_RolesEntry { return { key: 0, value: 0 }; } -export const TankDefinition_RolesEntry: MessageFns = { - encode(message: TankDefinition_RolesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.key !== undefined) { - writer.uint32(8).uint32(message.key); - } - if (message.value !== undefined) { - writer.uint32(16).uint32(message.value); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): TankDefinition_RolesEntry { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseTankDefinition_RolesEntry(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 8) { - break; - } - - message.key = reader.uint32(); - continue; - } - case 2: { - if (tag !== 16) { - break; - } - - message.value = reader.uint32(); - continue; - } +export const TankDefinition_RolesEntry: MessageFns = + { + encode( + message: TankDefinition_RolesEntry, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.key !== 0) { + writer.uint32(8).uint32(message.key); } - if ((tag & 7) === 4 || tag === 0) { - break; + if (message.value !== 0) { + writer.uint32(16).uint32(message.value); } - reader.skip(tag & 7); - } - return message; - }, + return writer; + }, - fromJSON(object: any): TankDefinition_RolesEntry { - return { - key: globalThis.Number(assertSet("TankDefinition_RolesEntry.key", object.key)), - value: globalThis.Number(assertSet("TankDefinition_RolesEntry.value", object.value)), - }; - }, + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): TankDefinition_RolesEntry { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseTankDefinition_RolesEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } - toJSON(message: TankDefinition_RolesEntry): unknown { - const obj: any = {}; - if (message.key !== undefined) { - obj.key = Math.round(message.key); - } - if (message.value !== undefined) { - obj.value = Math.round(message.value); - } - return obj; - }, + message.key = reader.uint32(); + continue; + } + case 2: { + if (tag !== 16) { + break; + } - create, I>>(base?: I): TankDefinition_RolesEntry { - return TankDefinition_RolesEntry.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>(object: I): TankDefinition_RolesEntry { - const message = createBaseTankDefinition_RolesEntry(); - message.key = object.key ?? 0; - message.value = object.value ?? 0; - return message; - }, -}; + message.value = reader.uint32(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, -export function createBaseResearchCost(): ResearchCost { + fromJSON(object: any): TankDefinition_RolesEntry { + return { + key: isSet(object.key) ? globalThis.Number(object.key) : 0, + value: isSet(object.value) ? globalThis.Number(object.value) : 0, + }; + }, + + toJSON(message: TankDefinition_RolesEntry): unknown { + const obj: any = {}; + if (message.key !== 0) { + obj.key = Math.round(message.key); + } + if (message.value !== 0) { + obj.value = Math.round(message.value); + } + return obj; + }, + + create, I>>( + base?: I, + ): TankDefinition_RolesEntry { + return TankDefinition_RolesEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): TankDefinition_RolesEntry { + const message = createBaseTankDefinition_RolesEntry(); + message.key = object.key ?? 0; + message.value = object.value ?? 0; + return message; + }, + }; + +function createBaseResearchCost(): ResearchCost { return { research_cost_type: undefined }; } export const ResearchCost: MessageFns = { - encode(message: ResearchCost, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: ResearchCost, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { switch (message.research_cost_type?.$case) { - case "xp": + case 'xp': writer.uint32(8).uint32(message.research_cost_type.value); break; - case "seasonal_tokens": - ResearchCostSeasonalTokens.encode(message.research_cost_type.value, writer.uint32(18).fork()).join(); + case 'seasonal_tokens': + ResearchCostSeasonalTokens.encode( + message.research_cost_type.value, + writer.uint32(18).fork(), + ).join(); break; } return writer; }, decode(input: BinaryReader | Uint8Array, length?: number): ResearchCost { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseResearchCost(); while (reader.pos < end) { @@ -1343,7 +1483,7 @@ export const ResearchCost: MessageFns = { break; } - message.research_cost_type = { $case: "xp", value: reader.uint32() }; + message.research_cost_type = { $case: 'xp', value: reader.uint32() }; continue; } case 2: { @@ -1352,7 +1492,7 @@ export const ResearchCost: MessageFns = { } message.research_cost_type = { - $case: "seasonal_tokens", + $case: 'seasonal_tokens', value: ResearchCostSeasonalTokens.decode(reader, reader.uint32()), }; continue; @@ -1369,132 +1509,163 @@ export const ResearchCost: MessageFns = { fromJSON(object: any): ResearchCost { return { research_cost_type: isSet(object.xp) - ? { $case: "xp", value: globalThis.Number(object.xp) } + ? { $case: 'xp', value: globalThis.Number(object.xp) } : isSet(object.seasonal_tokens) - ? { $case: "seasonal_tokens", value: ResearchCostSeasonalTokens.fromJSON(object.seasonal_tokens) } - : undefined, + ? { + $case: 'seasonal_tokens', + value: ResearchCostSeasonalTokens.fromJSON( + object.seasonal_tokens, + ), + } + : undefined, }; }, toJSON(message: ResearchCost): unknown { const obj: any = {}; - if (message.research_cost_type?.$case === "xp") { + if (message.research_cost_type?.$case === 'xp') { obj.xp = Math.round(message.research_cost_type.value); } - if (message.research_cost_type?.$case === "seasonal_tokens") { - obj.seasonal_tokens = ResearchCostSeasonalTokens.toJSON(message.research_cost_type.value); + if (message.research_cost_type?.$case === 'seasonal_tokens') { + obj.seasonal_tokens = ResearchCostSeasonalTokens.toJSON( + message.research_cost_type.value, + ); } return obj; }, - create, I>>(base?: I): ResearchCost { + create, I>>( + base?: I, + ): ResearchCost { return ResearchCost.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): ResearchCost { + fromPartial, I>>( + object: I, + ): ResearchCost { const message = createBaseResearchCost(); if ( - object.research_cost_type?.$case === "xp" && - object.research_cost_type?.value !== undefined && - object.research_cost_type?.value !== null - ) { - message.research_cost_type = { $case: "xp", value: object.research_cost_type.value }; - } - if ( - object.research_cost_type?.$case === "seasonal_tokens" && + object.research_cost_type?.$case === 'xp' && object.research_cost_type?.value !== undefined && object.research_cost_type?.value !== null ) { message.research_cost_type = { - $case: "seasonal_tokens", - value: ResearchCostSeasonalTokens.fromPartial(object.research_cost_type.value), + $case: 'xp', + value: object.research_cost_type.value, + }; + } + if ( + object.research_cost_type?.$case === 'seasonal_tokens' && + object.research_cost_type?.value !== undefined && + object.research_cost_type?.value !== null + ) { + message.research_cost_type = { + $case: 'seasonal_tokens', + value: ResearchCostSeasonalTokens.fromPartial( + object.research_cost_type.value, + ), }; } return message; }, }; -export function createBaseResearchCostSeasonalTokens(): ResearchCostSeasonalTokens { +function createBaseResearchCostSeasonalTokens(): ResearchCostSeasonalTokens { return { season: 0, tokens: 0 }; } -export const ResearchCostSeasonalTokens: MessageFns = { - encode(message: ResearchCostSeasonalTokens, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.season !== 0) { - writer.uint32(8).uint32(message.season); - } - if (message.tokens !== 0) { - writer.uint32(16).uint32(message.tokens); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): ResearchCostSeasonalTokens { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseResearchCostSeasonalTokens(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 8) { - break; - } - - message.season = reader.uint32(); - continue; - } - case 2: { - if (tag !== 16) { - break; - } - - message.tokens = reader.uint32(); - continue; - } +export const ResearchCostSeasonalTokens: MessageFns = + { + encode( + message: ResearchCostSeasonalTokens, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.season !== 0) { + writer.uint32(8).uint32(message.season); } - if ((tag & 7) === 4 || tag === 0) { - break; + if (message.tokens !== 0) { + writer.uint32(16).uint32(message.tokens); } - reader.skip(tag & 7); - } - return message; - }, + return writer; + }, - fromJSON(object: any): ResearchCostSeasonalTokens { - return { - season: globalThis.Number(assertSet("ResearchCostSeasonalTokens.season", object.season)), - tokens: globalThis.Number(assertSet("ResearchCostSeasonalTokens.tokens", object.tokens)), - }; - }, + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): ResearchCostSeasonalTokens { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseResearchCostSeasonalTokens(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } - toJSON(message: ResearchCostSeasonalTokens): unknown { - const obj: any = {}; - if (message.season !== 0) { - obj.season = Math.round(message.season); - } - if (message.tokens !== 0) { - obj.tokens = Math.round(message.tokens); - } - return obj; - }, + message.season = reader.uint32(); + continue; + } + case 2: { + if (tag !== 16) { + break; + } - create, I>>(base?: I): ResearchCostSeasonalTokens { - return ResearchCostSeasonalTokens.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>(object: I): ResearchCostSeasonalTokens { - const message = createBaseResearchCostSeasonalTokens(); - message.season = object.season ?? 0; - message.tokens = object.tokens ?? 0; - return message; - }, -}; + message.tokens = reader.uint32(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, -export function createBaseTankPrice(): TankPrice { + fromJSON(object: any): ResearchCostSeasonalTokens { + return { + season: isSet(object.season) ? globalThis.Number(object.season) : 0, + tokens: isSet(object.tokens) ? globalThis.Number(object.tokens) : 0, + }; + }, + + toJSON(message: ResearchCostSeasonalTokens): unknown { + const obj: any = {}; + if (message.season !== 0) { + obj.season = Math.round(message.season); + } + if (message.tokens !== 0) { + obj.tokens = Math.round(message.tokens); + } + return obj; + }, + + create, I>>( + base?: I, + ): ResearchCostSeasonalTokens { + return ResearchCostSeasonalTokens.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): ResearchCostSeasonalTokens { + const message = createBaseResearchCostSeasonalTokens(); + message.season = object.season ?? 0; + message.tokens = object.tokens ?? 0; + return message; + }, + }; + +function createBaseTankPrice(): TankPrice { return { type: 0, value: 0 }; } export const TankPrice: MessageFns = { - encode(message: TankPrice, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: TankPrice, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.type !== 0) { writer.uint32(8).int32(message.type); } @@ -1505,7 +1676,8 @@ export const TankPrice: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): TankPrice { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseTankPrice(); while (reader.pos < end) { @@ -1538,8 +1710,8 @@ export const TankPrice: MessageFns = { fromJSON(object: any): TankPrice { return { - type: tankPriceTypeFromJSON(assertSet("TankPrice.type", object.type)), - value: globalThis.Number(assertSet("TankPrice.value", object.value)), + type: isSet(object.type) ? tankPriceTypeFromJSON(object.type) : 0, + value: isSet(object.value) ? globalThis.Number(object.value) : 0, }; }, @@ -1557,7 +1729,9 @@ export const TankPrice: MessageFns = { create, I>>(base?: I): TankPrice { return TankPrice.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): TankPrice { + fromPartial, I>>( + object: I, + ): TankPrice { const message = createBaseTankPrice(); message.type = object.type ?? 0; message.value = object.value ?? 0; @@ -1565,11 +1739,11 @@ export const TankPrice: MessageFns = { }, }; -export function createBaseTrackDefinition(): TrackDefinition { +function createBaseTrackDefinition(): TrackDefinition { return { id: 0, tier: 0, - name: createBaseI18nString(), + name: undefined, weight: 0, traverse_speed: 0, research_cost: undefined, @@ -1583,7 +1757,10 @@ export function createBaseTrackDefinition(): TrackDefinition { } export const TrackDefinition: MessageFns = { - encode(message: TrackDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: TrackDefinition, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.id !== 0) { writer.uint32(8).uint32(message.id); } @@ -1600,7 +1777,10 @@ export const TrackDefinition: MessageFns = { writer.uint32(45).float(message.traverse_speed); } if (message.research_cost !== undefined) { - ResearchCost.encode(message.research_cost, writer.uint32(50).fork()).join(); + ResearchCost.encode( + message.research_cost, + writer.uint32(50).fork(), + ).join(); } if (message.dispersion_move !== 0) { writer.uint32(61).float(message.dispersion_move); @@ -1624,7 +1804,8 @@ export const TrackDefinition: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): TrackDefinition { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseTrackDefinition(); while (reader.pos < end) { @@ -1737,20 +1918,34 @@ export const TrackDefinition: MessageFns = { fromJSON(object: any): TrackDefinition { return { - id: globalThis.Number(assertSet("TrackDefinition.id", object.id)), - tier: globalThis.Number(assertSet("TrackDefinition.tier", object.tier)), - name: I18nString.fromJSON(assertSet("TrackDefinition.name", object.name)), - weight: globalThis.Number(assertSet("TrackDefinition.weight", object.weight)), - traverse_speed: globalThis.Number(assertSet("TrackDefinition.traverse_speed", object.traverse_speed)), - research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined, - dispersion_move: globalThis.Number(assertSet("TrackDefinition.dispersion_move", object.dispersion_move)), - dispersion_traverse: globalThis.Number( - assertSet("TrackDefinition.dispersion_traverse", object.dispersion_traverse), - ), - resistance_hard: globalThis.Number(assertSet("TrackDefinition.resistance_hard", object.resistance_hard)), - resistance_medium: globalThis.Number(assertSet("TrackDefinition.resistance_medium", object.resistance_medium)), - resistance_soft: globalThis.Number(assertSet("TrackDefinition.resistance_soft", object.resistance_soft)), - unlocks: globalThis.Array.isArray(object?.unlocks) ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) : [], + id: isSet(object.id) ? globalThis.Number(object.id) : 0, + tier: isSet(object.tier) ? globalThis.Number(object.tier) : 0, + name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined, + weight: isSet(object.weight) ? globalThis.Number(object.weight) : 0, + traverse_speed: isSet(object.traverse_speed) + ? globalThis.Number(object.traverse_speed) + : 0, + research_cost: isSet(object.research_cost) + ? ResearchCost.fromJSON(object.research_cost) + : undefined, + dispersion_move: isSet(object.dispersion_move) + ? globalThis.Number(object.dispersion_move) + : 0, + dispersion_traverse: isSet(object.dispersion_traverse) + ? globalThis.Number(object.dispersion_traverse) + : 0, + resistance_hard: isSet(object.resistance_hard) + ? globalThis.Number(object.resistance_hard) + : 0, + resistance_medium: isSet(object.resistance_medium) + ? globalThis.Number(object.resistance_medium) + : 0, + resistance_soft: isSet(object.resistance_soft) + ? globalThis.Number(object.resistance_soft) + : 0, + unlocks: globalThis.Array.isArray(object?.unlocks) + ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) + : [], }; }, @@ -1795,21 +1990,27 @@ export const TrackDefinition: MessageFns = { return obj; }, - create, I>>(base?: I): TrackDefinition { + create, I>>( + base?: I, + ): TrackDefinition { return TrackDefinition.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): TrackDefinition { + fromPartial, I>>( + object: I, + ): TrackDefinition { const message = createBaseTrackDefinition(); message.id = object.id ?? 0; message.tier = object.tier ?? 0; - message.name = (object.name !== undefined && object.name !== null) - ? I18nString.fromPartial(object.name) - : createBaseI18nString(); + message.name = + object.name !== undefined && object.name !== null + ? I18nString.fromPartial(object.name) + : undefined; message.weight = object.weight ?? 0; message.traverse_speed = object.traverse_speed ?? 0; - message.research_cost = (object.research_cost !== undefined && object.research_cost !== null) - ? ResearchCost.fromPartial(object.research_cost) - : undefined; + message.research_cost = + object.research_cost !== undefined && object.research_cost !== null + ? ResearchCost.fromPartial(object.research_cost) + : undefined; message.dispersion_move = object.dispersion_move ?? 0; message.dispersion_traverse = object.dispersion_traverse ?? 0; message.resistance_hard = object.resistance_hard ?? 0; @@ -1820,10 +2021,10 @@ export const TrackDefinition: MessageFns = { }, }; -export function createBaseEngineDefinition(): EngineDefinition { +function createBaseEngineDefinition(): EngineDefinition { return { id: 0, - name: createBaseI18nString(), + name: undefined, research_cost: undefined, tier: 0, fire_chance: 0, @@ -1834,7 +2035,10 @@ export function createBaseEngineDefinition(): EngineDefinition { } export const EngineDefinition: MessageFns = { - encode(message: EngineDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: EngineDefinition, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.id !== 0) { writer.uint32(8).uint32(message.id); } @@ -1842,7 +2046,10 @@ export const EngineDefinition: MessageFns = { I18nString.encode(message.name, writer.uint32(18).fork()).join(); } if (message.research_cost !== undefined) { - ResearchCost.encode(message.research_cost, writer.uint32(26).fork()).join(); + ResearchCost.encode( + message.research_cost, + writer.uint32(26).fork(), + ).join(); } if (message.tier !== 0) { writer.uint32(32).uint32(message.tier); @@ -1863,7 +2070,8 @@ export const EngineDefinition: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): EngineDefinition { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseEngineDefinition(); while (reader.pos < end) { @@ -1944,14 +2152,20 @@ export const EngineDefinition: MessageFns = { fromJSON(object: any): EngineDefinition { return { - id: globalThis.Number(assertSet("EngineDefinition.id", object.id)), - name: I18nString.fromJSON(assertSet("EngineDefinition.name", object.name)), - research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined, - tier: globalThis.Number(assertSet("EngineDefinition.tier", object.tier)), - fire_chance: globalThis.Number(assertSet("EngineDefinition.fire_chance", object.fire_chance)), - power: globalThis.Number(assertSet("EngineDefinition.power", object.power)), - weight: globalThis.Number(assertSet("EngineDefinition.weight", object.weight)), - unlocks: globalThis.Array.isArray(object?.unlocks) ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) : [], + id: isSet(object.id) ? globalThis.Number(object.id) : 0, + name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined, + research_cost: isSet(object.research_cost) + ? ResearchCost.fromJSON(object.research_cost) + : undefined, + tier: isSet(object.tier) ? globalThis.Number(object.tier) : 0, + fire_chance: isSet(object.fire_chance) + ? globalThis.Number(object.fire_chance) + : 0, + power: isSet(object.power) ? globalThis.Number(object.power) : 0, + weight: isSet(object.weight) ? globalThis.Number(object.weight) : 0, + unlocks: globalThis.Array.isArray(object?.unlocks) + ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) + : [], }; }, @@ -1984,18 +2198,24 @@ export const EngineDefinition: MessageFns = { return obj; }, - create, I>>(base?: I): EngineDefinition { + create, I>>( + base?: I, + ): EngineDefinition { return EngineDefinition.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): EngineDefinition { + fromPartial, I>>( + object: I, + ): EngineDefinition { const message = createBaseEngineDefinition(); message.id = object.id ?? 0; - message.name = (object.name !== undefined && object.name !== null) - ? I18nString.fromPartial(object.name) - : createBaseI18nString(); - message.research_cost = (object.research_cost !== undefined && object.research_cost !== null) - ? ResearchCost.fromPartial(object.research_cost) - : undefined; + message.name = + object.name !== undefined && object.name !== null + ? I18nString.fromPartial(object.name) + : undefined; + message.research_cost = + object.research_cost !== undefined && object.research_cost !== null + ? ResearchCost.fromPartial(object.research_cost) + : undefined; message.tier = object.tier ?? 0; message.fire_chance = object.fire_chance ?? 0; message.power = object.power ?? 0; @@ -2005,14 +2225,14 @@ export const EngineDefinition: MessageFns = { }, }; -export function createBaseTurretDefinition(): TurretDefinition { +function createBaseTurretDefinition(): TurretDefinition { return { id: 0, health: 0, view_range: 0, traverse_speed: 0, research_cost: undefined, - name: createBaseI18nString(), + name: undefined, tier: 0, weight: 0, guns: [], @@ -2021,7 +2241,10 @@ export function createBaseTurretDefinition(): TurretDefinition { } export const TurretDefinition: MessageFns = { - encode(message: TurretDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: TurretDefinition, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.id !== 0) { writer.uint32(8).uint32(message.id); } @@ -2035,7 +2258,10 @@ export const TurretDefinition: MessageFns = { writer.uint32(37).float(message.traverse_speed); } if (message.research_cost !== undefined) { - ResearchCost.encode(message.research_cost, writer.uint32(42).fork()).join(); + ResearchCost.encode( + message.research_cost, + writer.uint32(42).fork(), + ).join(); } if (message.name !== undefined) { I18nString.encode(message.name, writer.uint32(50).fork()).join(); @@ -2056,7 +2282,8 @@ export const TurretDefinition: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): TurretDefinition { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseTurretDefinition(); while (reader.pos < end) { @@ -2153,16 +2380,26 @@ export const TurretDefinition: MessageFns = { fromJSON(object: any): TurretDefinition { return { - id: globalThis.Number(assertSet("TurretDefinition.id", object.id)), - health: globalThis.Number(assertSet("TurretDefinition.health", object.health)), - view_range: globalThis.Number(assertSet("TurretDefinition.view_range", object.view_range)), - traverse_speed: globalThis.Number(assertSet("TurretDefinition.traverse_speed", object.traverse_speed)), - research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined, - name: I18nString.fromJSON(assertSet("TurretDefinition.name", object.name)), - tier: globalThis.Number(assertSet("TurretDefinition.tier", object.tier)), - weight: globalThis.Number(assertSet("TurretDefinition.weight", object.weight)), - guns: globalThis.Array.isArray(object?.guns) ? object.guns.map((e: any) => GunDefinition.fromJSON(e)) : [], - unlocks: globalThis.Array.isArray(object?.unlocks) ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) : [], + id: isSet(object.id) ? globalThis.Number(object.id) : 0, + health: isSet(object.health) ? globalThis.Number(object.health) : 0, + view_range: isSet(object.view_range) + ? globalThis.Number(object.view_range) + : 0, + traverse_speed: isSet(object.traverse_speed) + ? globalThis.Number(object.traverse_speed) + : 0, + research_cost: isSet(object.research_cost) + ? ResearchCost.fromJSON(object.research_cost) + : undefined, + name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined, + tier: isSet(object.tier) ? globalThis.Number(object.tier) : 0, + weight: isSet(object.weight) ? globalThis.Number(object.weight) : 0, + guns: globalThis.Array.isArray(object?.guns) + ? object.guns.map((e: any) => GunDefinition.fromJSON(e)) + : [], + unlocks: globalThis.Array.isArray(object?.unlocks) + ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) + : [], }; }, @@ -2201,21 +2438,27 @@ export const TurretDefinition: MessageFns = { return obj; }, - create, I>>(base?: I): TurretDefinition { + create, I>>( + base?: I, + ): TurretDefinition { return TurretDefinition.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): TurretDefinition { + fromPartial, I>>( + object: I, + ): TurretDefinition { const message = createBaseTurretDefinition(); message.id = object.id ?? 0; message.health = object.health ?? 0; message.view_range = object.view_range ?? 0; message.traverse_speed = object.traverse_speed ?? 0; - message.research_cost = (object.research_cost !== undefined && object.research_cost !== null) - ? ResearchCost.fromPartial(object.research_cost) - : undefined; - message.name = (object.name !== undefined && object.name !== null) - ? I18nString.fromPartial(object.name) - : createBaseI18nString(); + message.research_cost = + object.research_cost !== undefined && object.research_cost !== null + ? ResearchCost.fromPartial(object.research_cost) + : undefined; + message.name = + object.name !== undefined && object.name !== null + ? I18nString.fromPartial(object.name) + : undefined; message.tier = object.tier ?? 0; message.weight = object.weight ?? 0; message.guns = object.guns?.map((e) => GunDefinition.fromPartial(e)) || []; @@ -2224,28 +2467,41 @@ export const TurretDefinition: MessageFns = { }, }; -export function createBaseGunDefinition(): GunDefinition { +function createBaseGunDefinition(): GunDefinition { return { gun_type: undefined }; } export const GunDefinition: MessageFns = { - encode(message: GunDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: GunDefinition, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { switch (message.gun_type?.$case) { - case "regular": - GunDefinitionRegular.encode(message.gun_type.value, writer.uint32(10).fork()).join(); + case 'regular': + GunDefinitionRegular.encode( + message.gun_type.value, + writer.uint32(10).fork(), + ).join(); break; - case "auto_loader": - GunDefinitionAutoLoader.encode(message.gun_type.value, writer.uint32(18).fork()).join(); + case 'auto_loader': + GunDefinitionAutoLoader.encode( + message.gun_type.value, + writer.uint32(18).fork(), + ).join(); break; - case "auto_reloader": - GunDefinitionAutoReloader.encode(message.gun_type.value, writer.uint32(26).fork()).join(); + case 'auto_reloader': + GunDefinitionAutoReloader.encode( + message.gun_type.value, + writer.uint32(26).fork(), + ).join(); break; } return writer; }, decode(input: BinaryReader | Uint8Array, length?: number): GunDefinition { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseGunDefinition(); while (reader.pos < end) { @@ -2256,7 +2512,10 @@ export const GunDefinition: MessageFns = { break; } - message.gun_type = { $case: "regular", value: GunDefinitionRegular.decode(reader, reader.uint32()) }; + message.gun_type = { + $case: 'regular', + value: GunDefinitionRegular.decode(reader, reader.uint32()), + }; continue; } case 2: { @@ -2264,7 +2523,10 @@ export const GunDefinition: MessageFns = { break; } - message.gun_type = { $case: "auto_loader", value: GunDefinitionAutoLoader.decode(reader, reader.uint32()) }; + message.gun_type = { + $case: 'auto_loader', + value: GunDefinitionAutoLoader.decode(reader, reader.uint32()), + }; continue; } case 3: { @@ -2273,7 +2535,7 @@ export const GunDefinition: MessageFns = { } message.gun_type = { - $case: "auto_reloader", + $case: 'auto_reloader', value: GunDefinitionAutoReloader.decode(reader, reader.uint32()), }; continue; @@ -2290,53 +2552,76 @@ export const GunDefinition: MessageFns = { fromJSON(object: any): GunDefinition { return { gun_type: isSet(object.regular) - ? { $case: "regular", value: GunDefinitionRegular.fromJSON(object.regular) } + ? { + $case: 'regular', + value: GunDefinitionRegular.fromJSON(object.regular), + } : isSet(object.auto_loader) - ? { $case: "auto_loader", value: GunDefinitionAutoLoader.fromJSON(object.auto_loader) } - : isSet(object.auto_reloader) - ? { $case: "auto_reloader", value: GunDefinitionAutoReloader.fromJSON(object.auto_reloader) } - : undefined, + ? { + $case: 'auto_loader', + value: GunDefinitionAutoLoader.fromJSON(object.auto_loader), + } + : isSet(object.auto_reloader) + ? { + $case: 'auto_reloader', + value: GunDefinitionAutoReloader.fromJSON(object.auto_reloader), + } + : undefined, }; }, toJSON(message: GunDefinition): unknown { const obj: any = {}; - if (message.gun_type?.$case === "regular") { + if (message.gun_type?.$case === 'regular') { obj.regular = GunDefinitionRegular.toJSON(message.gun_type.value); } - if (message.gun_type?.$case === "auto_loader") { + if (message.gun_type?.$case === 'auto_loader') { obj.auto_loader = GunDefinitionAutoLoader.toJSON(message.gun_type.value); } - if (message.gun_type?.$case === "auto_reloader") { - obj.auto_reloader = GunDefinitionAutoReloader.toJSON(message.gun_type.value); + if (message.gun_type?.$case === 'auto_reloader') { + obj.auto_reloader = GunDefinitionAutoReloader.toJSON( + message.gun_type.value, + ); } return obj; }, - create, I>>(base?: I): GunDefinition { + create, I>>( + base?: I, + ): GunDefinition { return GunDefinition.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): GunDefinition { + fromPartial, I>>( + object: I, + ): GunDefinition { const message = createBaseGunDefinition(); if ( - object.gun_type?.$case === "regular" && object.gun_type?.value !== undefined && object.gun_type?.value !== null - ) { - message.gun_type = { $case: "regular", value: GunDefinitionRegular.fromPartial(object.gun_type.value) }; - } - if ( - object.gun_type?.$case === "auto_loader" && - object.gun_type?.value !== undefined && - object.gun_type?.value !== null - ) { - message.gun_type = { $case: "auto_loader", value: GunDefinitionAutoLoader.fromPartial(object.gun_type.value) }; - } - if ( - object.gun_type?.$case === "auto_reloader" && + object.gun_type?.$case === 'regular' && object.gun_type?.value !== undefined && object.gun_type?.value !== null ) { message.gun_type = { - $case: "auto_reloader", + $case: 'regular', + value: GunDefinitionRegular.fromPartial(object.gun_type.value), + }; + } + if ( + object.gun_type?.$case === 'auto_loader' && + object.gun_type?.value !== undefined && + object.gun_type?.value !== null + ) { + message.gun_type = { + $case: 'auto_loader', + value: GunDefinitionAutoLoader.fromPartial(object.gun_type.value), + }; + } + if ( + object.gun_type?.$case === 'auto_reloader' && + object.gun_type?.value !== undefined && + object.gun_type?.value !== null + ) { + message.gun_type = { + $case: 'auto_reloader', value: GunDefinitionAutoReloader.fromPartial(object.gun_type.value), }; } @@ -2344,23 +2629,33 @@ export const GunDefinition: MessageFns = { }, }; -export function createBaseGunDefinitionRegular(): GunDefinitionRegular { - return { base: createBaseGunDefinitionBase(), extension: createBaseGunDefinitionRegularProperties() }; +function createBaseGunDefinitionRegular(): GunDefinitionRegular { + return { base: undefined, extension: undefined }; } export const GunDefinitionRegular: MessageFns = { - encode(message: GunDefinitionRegular, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: GunDefinitionRegular, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.base !== undefined) { GunDefinitionBase.encode(message.base, writer.uint32(10).fork()).join(); } if (message.extension !== undefined) { - GunDefinitionRegularProperties.encode(message.extension, writer.uint32(18).fork()).join(); + GunDefinitionRegularProperties.encode( + message.extension, + writer.uint32(18).fork(), + ).join(); } return writer; }, - decode(input: BinaryReader | Uint8Array, length?: number): GunDefinitionRegular { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): GunDefinitionRegular { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseGunDefinitionRegular(); while (reader.pos < end) { @@ -2379,7 +2674,10 @@ export const GunDefinitionRegular: MessageFns = { break; } - message.extension = GunDefinitionRegularProperties.decode(reader, reader.uint32()); + message.extension = GunDefinitionRegularProperties.decode( + reader, + reader.uint32(), + ); continue; } } @@ -2393,8 +2691,12 @@ export const GunDefinitionRegular: MessageFns = { fromJSON(object: any): GunDefinitionRegular { return { - base: GunDefinitionBase.fromJSON(assertSet("GunDefinitionRegular.base", object.base)), - extension: GunDefinitionRegularProperties.fromJSON(assertSet("GunDefinitionRegular.extension", object.extension)), + base: isSet(object.base) + ? GunDefinitionBase.fromJSON(object.base) + : undefined, + extension: isSet(object.extension) + ? GunDefinitionRegularProperties.fromJSON(object.extension) + : undefined, }; }, @@ -2409,98 +2711,126 @@ export const GunDefinitionRegular: MessageFns = { return obj; }, - create, I>>(base?: I): GunDefinitionRegular { + create, I>>( + base?: I, + ): GunDefinitionRegular { return GunDefinitionRegular.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): GunDefinitionRegular { + fromPartial, I>>( + object: I, + ): GunDefinitionRegular { const message = createBaseGunDefinitionRegular(); - message.base = (object.base !== undefined && object.base !== null) - ? GunDefinitionBase.fromPartial(object.base) - : createBaseGunDefinitionBase(); - message.extension = (object.extension !== undefined && object.extension !== null) - ? GunDefinitionRegularProperties.fromPartial(object.extension) - : createBaseGunDefinitionRegularProperties(); + message.base = + object.base !== undefined && object.base !== null + ? GunDefinitionBase.fromPartial(object.base) + : undefined; + message.extension = + object.extension !== undefined && object.extension !== null + ? GunDefinitionRegularProperties.fromPartial(object.extension) + : undefined; return message; }, }; -export function createBaseGunDefinitionRegularProperties(): GunDefinitionRegularProperties { +function createBaseGunDefinitionRegularProperties(): GunDefinitionRegularProperties { return { reload: 0 }; } -export const GunDefinitionRegularProperties: MessageFns = { - encode(message: GunDefinitionRegularProperties, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.reload !== 0) { - writer.uint32(13).float(message.reload); - } - return writer; - }, +export const GunDefinitionRegularProperties: MessageFns = + { + encode( + message: GunDefinitionRegularProperties, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.reload !== 0) { + writer.uint32(13).float(message.reload); + } + return writer; + }, - decode(input: BinaryReader | Uint8Array, length?: number): GunDefinitionRegularProperties { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGunDefinitionRegularProperties(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 13) { - break; + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): GunDefinitionRegularProperties { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGunDefinitionRegularProperties(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.reload = reader.float(); + continue; } - - message.reload = reader.float(); - continue; } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); } - if ((tag & 7) === 4 || tag === 0) { - break; + return message; + }, + + fromJSON(object: any): GunDefinitionRegularProperties { + return { + reload: isSet(object.reload) ? globalThis.Number(object.reload) : 0, + }; + }, + + toJSON(message: GunDefinitionRegularProperties): unknown { + const obj: any = {}; + if (message.reload !== 0) { + obj.reload = message.reload; } - reader.skip(tag & 7); - } - return message; - }, + return obj; + }, - fromJSON(object: any): GunDefinitionRegularProperties { - return { reload: globalThis.Number(assertSet("GunDefinitionRegularProperties.reload", object.reload)) }; - }, + create, I>>( + base?: I, + ): GunDefinitionRegularProperties { + return GunDefinitionRegularProperties.fromPartial(base ?? ({} as any)); + }, + fromPartial< + I extends Exact, I>, + >(object: I): GunDefinitionRegularProperties { + const message = createBaseGunDefinitionRegularProperties(); + message.reload = object.reload ?? 0; + return message; + }, + }; - toJSON(message: GunDefinitionRegularProperties): unknown { - const obj: any = {}; - if (message.reload !== 0) { - obj.reload = message.reload; - } - return obj; - }, - - create, I>>(base?: I): GunDefinitionRegularProperties { - return GunDefinitionRegularProperties.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>( - object: I, - ): GunDefinitionRegularProperties { - const message = createBaseGunDefinitionRegularProperties(); - message.reload = object.reload ?? 0; - return message; - }, -}; - -export function createBaseGunDefinitionAutoLoader(): GunDefinitionAutoLoader { - return { base: createBaseGunDefinitionBase(), extension: createBaseGunDefinitionAutoLoaderProperties() }; +function createBaseGunDefinitionAutoLoader(): GunDefinitionAutoLoader { + return { base: undefined, extension: undefined }; } export const GunDefinitionAutoLoader: MessageFns = { - encode(message: GunDefinitionAutoLoader, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: GunDefinitionAutoLoader, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.base !== undefined) { GunDefinitionBase.encode(message.base, writer.uint32(10).fork()).join(); } if (message.extension !== undefined) { - GunDefinitionAutoLoaderProperties.encode(message.extension, writer.uint32(18).fork()).join(); + GunDefinitionAutoLoaderProperties.encode( + message.extension, + writer.uint32(18).fork(), + ).join(); } return writer; }, - decode(input: BinaryReader | Uint8Array, length?: number): GunDefinitionAutoLoader { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): GunDefinitionAutoLoader { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseGunDefinitionAutoLoader(); while (reader.pos < end) { @@ -2519,7 +2849,10 @@ export const GunDefinitionAutoLoader: MessageFns = { break; } - message.extension = GunDefinitionAutoLoaderProperties.decode(reader, reader.uint32()); + message.extension = GunDefinitionAutoLoaderProperties.decode( + reader, + reader.uint32(), + ); continue; } } @@ -2533,10 +2866,12 @@ export const GunDefinitionAutoLoader: MessageFns = { fromJSON(object: any): GunDefinitionAutoLoader { return { - base: GunDefinitionBase.fromJSON(assertSet("GunDefinitionAutoLoader.base", object.base)), - extension: GunDefinitionAutoLoaderProperties.fromJSON( - assertSet("GunDefinitionAutoLoader.extension", object.extension), - ), + base: isSet(object.base) + ? GunDefinitionBase.fromJSON(object.base) + : undefined, + extension: isSet(object.extension) + ? GunDefinitionAutoLoaderProperties.fromJSON(object.extension) + : undefined, }; }, @@ -2546,321 +2881,381 @@ export const GunDefinitionAutoLoader: MessageFns = { obj.base = GunDefinitionBase.toJSON(message.base); } if (message.extension !== undefined) { - obj.extension = GunDefinitionAutoLoaderProperties.toJSON(message.extension); + obj.extension = GunDefinitionAutoLoaderProperties.toJSON( + message.extension, + ); } return obj; }, - create, I>>(base?: I): GunDefinitionAutoLoader { + create, I>>( + base?: I, + ): GunDefinitionAutoLoader { return GunDefinitionAutoLoader.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): GunDefinitionAutoLoader { + fromPartial, I>>( + object: I, + ): GunDefinitionAutoLoader { const message = createBaseGunDefinitionAutoLoader(); - message.base = (object.base !== undefined && object.base !== null) - ? GunDefinitionBase.fromPartial(object.base) - : createBaseGunDefinitionBase(); - message.extension = (object.extension !== undefined && object.extension !== null) - ? GunDefinitionAutoLoaderProperties.fromPartial(object.extension) - : createBaseGunDefinitionAutoLoaderProperties(); + message.base = + object.base !== undefined && object.base !== null + ? GunDefinitionBase.fromPartial(object.base) + : undefined; + message.extension = + object.extension !== undefined && object.extension !== null + ? GunDefinitionAutoLoaderProperties.fromPartial(object.extension) + : undefined; return message; }, }; -export function createBaseGunDefinitionAutoLoaderProperties(): GunDefinitionAutoLoaderProperties { +function createBaseGunDefinitionAutoLoaderProperties(): GunDefinitionAutoLoaderProperties { return { clip_reload: 0, intra_clip: 0, shell_count: 0 }; } -export const GunDefinitionAutoLoaderProperties: MessageFns = { - encode(message: GunDefinitionAutoLoaderProperties, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.clip_reload !== 0) { - writer.uint32(13).float(message.clip_reload); - } - if (message.intra_clip !== 0) { - writer.uint32(21).float(message.intra_clip); - } - if (message.shell_count !== 0) { - writer.uint32(29).float(message.shell_count); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): GunDefinitionAutoLoaderProperties { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGunDefinitionAutoLoaderProperties(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 13) { - break; - } - - message.clip_reload = reader.float(); - continue; - } - case 2: { - if (tag !== 21) { - break; - } - - message.intra_clip = reader.float(); - continue; - } - case 3: { - if (tag !== 29) { - break; - } - - message.shell_count = reader.float(); - continue; - } +export const GunDefinitionAutoLoaderProperties: MessageFns = + { + encode( + message: GunDefinitionAutoLoaderProperties, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.clip_reload !== 0) { + writer.uint32(13).float(message.clip_reload); } - if ((tag & 7) === 4 || tag === 0) { - break; + if (message.intra_clip !== 0) { + writer.uint32(21).float(message.intra_clip); } - reader.skip(tag & 7); - } - return message; - }, + if (message.shell_count !== 0) { + writer.uint32(29).float(message.shell_count); + } + return writer; + }, - fromJSON(object: any): GunDefinitionAutoLoaderProperties { - return { - clip_reload: globalThis.Number(assertSet("GunDefinitionAutoLoaderProperties.clip_reload", object.clip_reload)), - intra_clip: globalThis.Number(assertSet("GunDefinitionAutoLoaderProperties.intra_clip", object.intra_clip)), - shell_count: globalThis.Number(assertSet("GunDefinitionAutoLoaderProperties.shell_count", object.shell_count)), - }; - }, + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): GunDefinitionAutoLoaderProperties { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGunDefinitionAutoLoaderProperties(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } - toJSON(message: GunDefinitionAutoLoaderProperties): unknown { - const obj: any = {}; - if (message.clip_reload !== 0) { - obj.clip_reload = message.clip_reload; - } - if (message.intra_clip !== 0) { - obj.intra_clip = message.intra_clip; - } - if (message.shell_count !== 0) { - obj.shell_count = message.shell_count; - } - return obj; - }, + message.clip_reload = reader.float(); + continue; + } + case 2: { + if (tag !== 21) { + break; + } - create, I>>( - base?: I, - ): GunDefinitionAutoLoaderProperties { - return GunDefinitionAutoLoaderProperties.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>( - object: I, - ): GunDefinitionAutoLoaderProperties { - const message = createBaseGunDefinitionAutoLoaderProperties(); - message.clip_reload = object.clip_reload ?? 0; - message.intra_clip = object.intra_clip ?? 0; - message.shell_count = object.shell_count ?? 0; - return message; - }, -}; + message.intra_clip = reader.float(); + continue; + } + case 3: { + if (tag !== 29) { + break; + } -export function createBaseGunDefinitionAutoReloader(): GunDefinitionAutoReloader { - return { base: createBaseGunDefinitionBase(), extension: createBaseGunDefinitionAutoReloaderProperties() }; + message.shell_count = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GunDefinitionAutoLoaderProperties { + return { + clip_reload: isSet(object.clip_reload) + ? globalThis.Number(object.clip_reload) + : 0, + intra_clip: isSet(object.intra_clip) + ? globalThis.Number(object.intra_clip) + : 0, + shell_count: isSet(object.shell_count) + ? globalThis.Number(object.shell_count) + : 0, + }; + }, + + toJSON(message: GunDefinitionAutoLoaderProperties): unknown { + const obj: any = {}; + if (message.clip_reload !== 0) { + obj.clip_reload = message.clip_reload; + } + if (message.intra_clip !== 0) { + obj.intra_clip = message.intra_clip; + } + if (message.shell_count !== 0) { + obj.shell_count = message.shell_count; + } + return obj; + }, + + create, I>>( + base?: I, + ): GunDefinitionAutoLoaderProperties { + return GunDefinitionAutoLoaderProperties.fromPartial(base ?? ({} as any)); + }, + fromPartial< + I extends Exact, I>, + >(object: I): GunDefinitionAutoLoaderProperties { + const message = createBaseGunDefinitionAutoLoaderProperties(); + message.clip_reload = object.clip_reload ?? 0; + message.intra_clip = object.intra_clip ?? 0; + message.shell_count = object.shell_count ?? 0; + return message; + }, + }; + +function createBaseGunDefinitionAutoReloader(): GunDefinitionAutoReloader { + return { base: undefined, extension: undefined }; } -export const GunDefinitionAutoReloader: MessageFns = { - encode(message: GunDefinitionAutoReloader, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.base !== undefined) { - GunDefinitionBase.encode(message.base, writer.uint32(10).fork()).join(); - } - if (message.extension !== undefined) { - GunDefinitionAutoReloaderProperties.encode(message.extension, writer.uint32(18).fork()).join(); - } - return writer; - }, - - decode(input: BinaryReader | Uint8Array, length?: number): GunDefinitionAutoReloader { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGunDefinitionAutoReloader(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag !== 10) { - break; - } - - message.base = GunDefinitionBase.decode(reader, reader.uint32()); - continue; - } - case 2: { - if (tag !== 18) { - break; - } - - message.extension = GunDefinitionAutoReloaderProperties.decode(reader, reader.uint32()); - continue; - } +export const GunDefinitionAutoReloader: MessageFns = + { + encode( + message: GunDefinitionAutoReloader, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.base !== undefined) { + GunDefinitionBase.encode(message.base, writer.uint32(10).fork()).join(); } - if ((tag & 7) === 4 || tag === 0) { - break; + if (message.extension !== undefined) { + GunDefinitionAutoReloaderProperties.encode( + message.extension, + writer.uint32(18).fork(), + ).join(); } - reader.skip(tag & 7); - } - return message; - }, + return writer; + }, - fromJSON(object: any): GunDefinitionAutoReloader { - return { - base: GunDefinitionBase.fromJSON(assertSet("GunDefinitionAutoReloader.base", object.base)), - extension: GunDefinitionAutoReloaderProperties.fromJSON( - assertSet("GunDefinitionAutoReloader.extension", object.extension), - ), - }; - }, + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): GunDefinitionAutoReloader { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGunDefinitionAutoReloader(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } - toJSON(message: GunDefinitionAutoReloader): unknown { - const obj: any = {}; - if (message.base !== undefined) { - obj.base = GunDefinitionBase.toJSON(message.base); - } - if (message.extension !== undefined) { - obj.extension = GunDefinitionAutoReloaderProperties.toJSON(message.extension); - } - return obj; - }, + message.base = GunDefinitionBase.decode(reader, reader.uint32()); + continue; + } + case 2: { + if (tag !== 18) { + break; + } - create, I>>(base?: I): GunDefinitionAutoReloader { - return GunDefinitionAutoReloader.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>(object: I): GunDefinitionAutoReloader { - const message = createBaseGunDefinitionAutoReloader(); - message.base = (object.base !== undefined && object.base !== null) - ? GunDefinitionBase.fromPartial(object.base) - : createBaseGunDefinitionBase(); - message.extension = (object.extension !== undefined && object.extension !== null) - ? GunDefinitionAutoReloaderProperties.fromPartial(object.extension) - : createBaseGunDefinitionAutoReloaderProperties(); - return message; - }, -}; + message.extension = GunDefinitionAutoReloaderProperties.decode( + reader, + reader.uint32(), + ); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, -export function createBaseGunDefinitionAutoReloaderProperties(): GunDefinitionAutoReloaderProperties { + fromJSON(object: any): GunDefinitionAutoReloader { + return { + base: isSet(object.base) + ? GunDefinitionBase.fromJSON(object.base) + : undefined, + extension: isSet(object.extension) + ? GunDefinitionAutoReloaderProperties.fromJSON(object.extension) + : undefined, + }; + }, + + toJSON(message: GunDefinitionAutoReloader): unknown { + const obj: any = {}; + if (message.base !== undefined) { + obj.base = GunDefinitionBase.toJSON(message.base); + } + if (message.extension !== undefined) { + obj.extension = GunDefinitionAutoReloaderProperties.toJSON( + message.extension, + ); + } + return obj; + }, + + create, I>>( + base?: I, + ): GunDefinitionAutoReloader { + return GunDefinitionAutoReloader.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): GunDefinitionAutoReloader { + const message = createBaseGunDefinitionAutoReloader(); + message.base = + object.base !== undefined && object.base !== null + ? GunDefinitionBase.fromPartial(object.base) + : undefined; + message.extension = + object.extension !== undefined && object.extension !== null + ? GunDefinitionAutoReloaderProperties.fromPartial(object.extension) + : undefined; + return message; + }, + }; + +function createBaseGunDefinitionAutoReloaderProperties(): GunDefinitionAutoReloaderProperties { return { shell_reloads: [], intra_clip: 0, shell_count: 0 }; } -export const GunDefinitionAutoReloaderProperties: MessageFns = { - encode(message: GunDefinitionAutoReloaderProperties, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - writer.uint32(10).fork(); - for (const v of message.shell_reloads) { - writer.float(v); - } - writer.join(); - if (message.intra_clip !== 0) { - writer.uint32(21).float(message.intra_clip); - } - if (message.shell_count !== 0) { - writer.uint32(29).float(message.shell_count); - } - return writer; - }, +export const GunDefinitionAutoReloaderProperties: MessageFns = + { + encode( + message: GunDefinitionAutoReloaderProperties, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + writer.uint32(10).fork(); + for (const v of message.shell_reloads) { + writer.float(v); + } + writer.join(); + if (message.intra_clip !== 0) { + writer.uint32(21).float(message.intra_clip); + } + if (message.shell_count !== 0) { + writer.uint32(29).float(message.shell_count); + } + return writer; + }, - decode(input: BinaryReader | Uint8Array, length?: number): GunDefinitionAutoReloaderProperties { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGunDefinitionAutoReloaderProperties(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: { - if (tag === 13) { - message.shell_reloads.push(reader.float()); - - continue; - } - - if (tag === 10) { - const end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) { + decode( + input: BinaryReader | Uint8Array, + length?: number, + ): GunDefinitionAutoReloaderProperties { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGunDefinitionAutoReloaderProperties(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag === 13) { message.shell_reloads.push(reader.float()); + + continue; } + if (tag === 10) { + const end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) { + message.shell_reloads.push(reader.float()); + } + + continue; + } + + break; + } + case 2: { + if (tag !== 21) { + break; + } + + message.intra_clip = reader.float(); continue; } + case 3: { + if (tag !== 29) { + break; + } + message.shell_count = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { break; } - case 2: { - if (tag !== 21) { - break; - } - - message.intra_clip = reader.float(); - continue; - } - case 3: { - if (tag !== 29) { - break; - } - - message.shell_count = reader.float(); - continue; - } + reader.skip(tag & 7); } - if ((tag & 7) === 4 || tag === 0) { - break; + return message; + }, + + fromJSON(object: any): GunDefinitionAutoReloaderProperties { + return { + shell_reloads: globalThis.Array.isArray(object?.shell_reloads) + ? object.shell_reloads.map((e: any) => globalThis.Number(e)) + : [], + intra_clip: isSet(object.intra_clip) + ? globalThis.Number(object.intra_clip) + : 0, + shell_count: isSet(object.shell_count) + ? globalThis.Number(object.shell_count) + : 0, + }; + }, + + toJSON(message: GunDefinitionAutoReloaderProperties): unknown { + const obj: any = {}; + if (message.shell_reloads?.length) { + obj.shell_reloads = message.shell_reloads; } - reader.skip(tag & 7); - } - return message; - }, + if (message.intra_clip !== 0) { + obj.intra_clip = message.intra_clip; + } + if (message.shell_count !== 0) { + obj.shell_count = message.shell_count; + } + return obj; + }, - fromJSON(object: any): GunDefinitionAutoReloaderProperties { - return { - shell_reloads: globalThis.Array.isArray(object?.shell_reloads) - ? object.shell_reloads.map((e: any) => globalThis.Number(e)) - : [], - intra_clip: globalThis.Number(assertSet("GunDefinitionAutoReloaderProperties.intra_clip", object.intra_clip)), - shell_count: globalThis.Number(assertSet("GunDefinitionAutoReloaderProperties.shell_count", object.shell_count)), - }; - }, + create< + I extends Exact, I>, + >(base?: I): GunDefinitionAutoReloaderProperties { + return GunDefinitionAutoReloaderProperties.fromPartial( + base ?? ({} as any), + ); + }, + fromPartial< + I extends Exact, I>, + >(object: I): GunDefinitionAutoReloaderProperties { + const message = createBaseGunDefinitionAutoReloaderProperties(); + message.shell_reloads = object.shell_reloads?.map((e) => e) || []; + message.intra_clip = object.intra_clip ?? 0; + message.shell_count = object.shell_count ?? 0; + return message; + }, + }; - toJSON(message: GunDefinitionAutoReloaderProperties): unknown { - const obj: any = {}; - if (message.shell_reloads?.length) { - obj.shell_reloads = message.shell_reloads; - } - if (message.intra_clip !== 0) { - obj.intra_clip = message.intra_clip; - } - if (message.shell_count !== 0) { - obj.shell_count = message.shell_count; - } - return obj; - }, - - create, I>>( - base?: I, - ): GunDefinitionAutoReloaderProperties { - return GunDefinitionAutoReloaderProperties.fromPartial(base ?? ({} as any)); - }, - fromPartial, I>>( - object: I, - ): GunDefinitionAutoReloaderProperties { - const message = createBaseGunDefinitionAutoReloaderProperties(); - message.shell_reloads = object.shell_reloads?.map((e) => e) || []; - message.intra_clip = object.intra_clip ?? 0; - message.shell_count = object.shell_count ?? 0; - return message; - }, -}; - -export function createBaseGunDefinitionBase(): GunDefinitionBase { +function createBaseGunDefinitionBase(): GunDefinitionBase { return { id: 0, rotation_speed: 0, research_cost: undefined, weight: 0, - name: createBaseI18nString(), + name: undefined, tier: 0, shells: [], camouflage_loss: 0, @@ -2871,11 +3266,15 @@ export function createBaseGunDefinitionBase(): GunDefinitionBase { dispersion_damaged: 0, unlocks: [], shell_capacity: 0, + assault_ranges: undefined, }; } export const GunDefinitionBase: MessageFns = { - encode(message: GunDefinitionBase, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: GunDefinitionBase, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.id !== 0) { writer.uint32(8).uint32(message.id); } @@ -2883,7 +3282,10 @@ export const GunDefinitionBase: MessageFns = { writer.uint32(21).float(message.rotation_speed); } if (message.research_cost !== undefined) { - ResearchCost.encode(message.research_cost, writer.uint32(26).fork()).join(); + ResearchCost.encode( + message.research_cost, + writer.uint32(26).fork(), + ).join(); } if (message.weight !== 0) { writer.uint32(32).uint32(message.weight); @@ -2921,11 +3323,18 @@ export const GunDefinitionBase: MessageFns = { if (message.shell_capacity !== 0) { writer.uint32(120).uint32(message.shell_capacity); } + if (message.assault_ranges !== undefined) { + AssaultRanges.encode( + message.assault_ranges, + writer.uint32(130).fork(), + ).join(); + } return writer; }, decode(input: BinaryReader | Uint8Array, length?: number): GunDefinitionBase { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseGunDefinitionBase(); while (reader.pos < end) { @@ -3051,6 +3460,17 @@ export const GunDefinitionBase: MessageFns = { message.shell_capacity = reader.uint32(); continue; } + case 16: { + if (tag !== 130) { + break; + } + + message.assault_ranges = AssaultRanges.decode( + reader, + reader.uint32(), + ); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -3062,27 +3482,44 @@ export const GunDefinitionBase: MessageFns = { fromJSON(object: any): GunDefinitionBase { return { - id: globalThis.Number(assertSet("GunDefinitionBase.id", object.id)), - rotation_speed: globalThis.Number(assertSet("GunDefinitionBase.rotation_speed", object.rotation_speed)), - research_cost: isSet(object.research_cost) ? ResearchCost.fromJSON(object.research_cost) : undefined, - weight: globalThis.Number(assertSet("GunDefinitionBase.weight", object.weight)), - name: I18nString.fromJSON(assertSet("GunDefinitionBase.name", object.name)), - tier: globalThis.Number(assertSet("GunDefinitionBase.tier", object.tier)), + id: isSet(object.id) ? globalThis.Number(object.id) : 0, + rotation_speed: isSet(object.rotation_speed) + ? globalThis.Number(object.rotation_speed) + : 0, + research_cost: isSet(object.research_cost) + ? ResearchCost.fromJSON(object.research_cost) + : undefined, + weight: isSet(object.weight) ? globalThis.Number(object.weight) : 0, + name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined, + tier: isSet(object.tier) ? globalThis.Number(object.tier) : 0, shells: globalThis.Array.isArray(object?.shells) ? object.shells.map((e: any) => ShellDefinition.fromJSON(e)) : [], - camouflage_loss: globalThis.Number(assertSet("GunDefinitionBase.camouflage_loss", object.camouflage_loss)), - aim_time: globalThis.Number(assertSet("GunDefinitionBase.aim_time", object.aim_time)), - dispersion_base: globalThis.Number(assertSet("GunDefinitionBase.dispersion_base", object.dispersion_base)), - dispersion_traverse: globalThis.Number( - assertSet("GunDefinitionBase.dispersion_traverse", object.dispersion_traverse), - ), - dispersion_shot: globalThis.Number(assertSet("GunDefinitionBase.dispersion_shot", object.dispersion_shot)), - dispersion_damaged: globalThis.Number( - assertSet("GunDefinitionBase.dispersion_damaged", object.dispersion_damaged), - ), - unlocks: globalThis.Array.isArray(object?.unlocks) ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) : [], - shell_capacity: globalThis.Number(assertSet("GunDefinitionBase.shell_capacity", object.shell_capacity)), + camouflage_loss: isSet(object.camouflage_loss) + ? globalThis.Number(object.camouflage_loss) + : 0, + aim_time: isSet(object.aim_time) ? globalThis.Number(object.aim_time) : 0, + dispersion_base: isSet(object.dispersion_base) + ? globalThis.Number(object.dispersion_base) + : 0, + dispersion_traverse: isSet(object.dispersion_traverse) + ? globalThis.Number(object.dispersion_traverse) + : 0, + dispersion_shot: isSet(object.dispersion_shot) + ? globalThis.Number(object.dispersion_shot) + : 0, + dispersion_damaged: isSet(object.dispersion_damaged) + ? globalThis.Number(object.dispersion_damaged) + : 0, + unlocks: globalThis.Array.isArray(object?.unlocks) + ? object.unlocks.map((e: any) => Unlock.fromJSON(e)) + : [], + shell_capacity: isSet(object.shell_capacity) + ? globalThis.Number(object.shell_capacity) + : 0, + assault_ranges: isSet(object.assault_ranges) + ? AssaultRanges.fromJSON(object.assault_ranges) + : undefined, }; }, @@ -3133,25 +3570,35 @@ export const GunDefinitionBase: MessageFns = { if (message.shell_capacity !== 0) { obj.shell_capacity = Math.round(message.shell_capacity); } + if (message.assault_ranges !== undefined) { + obj.assault_ranges = AssaultRanges.toJSON(message.assault_ranges); + } return obj; }, - create, I>>(base?: I): GunDefinitionBase { + create, I>>( + base?: I, + ): GunDefinitionBase { return GunDefinitionBase.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): GunDefinitionBase { + fromPartial, I>>( + object: I, + ): GunDefinitionBase { const message = createBaseGunDefinitionBase(); message.id = object.id ?? 0; message.rotation_speed = object.rotation_speed ?? 0; - message.research_cost = (object.research_cost !== undefined && object.research_cost !== null) - ? ResearchCost.fromPartial(object.research_cost) - : undefined; + message.research_cost = + object.research_cost !== undefined && object.research_cost !== null + ? ResearchCost.fromPartial(object.research_cost) + : undefined; message.weight = object.weight ?? 0; - message.name = (object.name !== undefined && object.name !== null) - ? I18nString.fromPartial(object.name) - : createBaseI18nString(); + message.name = + object.name !== undefined && object.name !== null + ? I18nString.fromPartial(object.name) + : undefined; message.tier = object.tier ?? 0; - message.shells = object.shells?.map((e) => ShellDefinition.fromPartial(e)) || []; + message.shells = + object.shells?.map((e) => ShellDefinition.fromPartial(e)) || []; message.camouflage_loss = object.camouflage_loss ?? 0; message.aim_time = object.aim_time ?? 0; message.dispersion_base = object.dispersion_base ?? 0; @@ -3160,30 +3607,222 @@ export const GunDefinitionBase: MessageFns = { message.dispersion_damaged = object.dispersion_damaged ?? 0; message.unlocks = object.unlocks?.map((e) => Unlock.fromPartial(e)) || []; message.shell_capacity = object.shell_capacity ?? 0; + message.assault_ranges = + object.assault_ranges !== undefined && object.assault_ranges !== null + ? AssaultRanges.fromPartial(object.assault_ranges) + : undefined; return message; }, }; -export function createBaseShellDefinition(): ShellDefinition { +function createBaseAssaultRanges(): AssaultRanges { + return { ranges: [], types: [] }; +} + +export const AssaultRanges: MessageFns = { + encode( + message: AssaultRanges, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + for (const v of message.ranges) { + AssaultRange.encode(v!, writer.uint32(10).fork()).join(); + } + writer.uint32(18).fork(); + for (const v of message.types) { + writer.int32(v); + } + writer.join(); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): AssaultRanges { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseAssaultRanges(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.ranges.push(AssaultRange.decode(reader, reader.uint32())); + continue; + } + case 2: { + if (tag === 16) { + message.types.push(reader.int32() as any); + + continue; + } + + if (tag === 18) { + const end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) { + message.types.push(reader.int32() as any); + } + + continue; + } + + break; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): AssaultRanges { + return { + ranges: globalThis.Array.isArray(object?.ranges) + ? object.ranges.map((e: any) => AssaultRange.fromJSON(e)) + : [], + types: globalThis.Array.isArray(object?.types) + ? object.types.map((e: any) => shellTypeFromJSON(e)) + : [], + }; + }, + + toJSON(message: AssaultRanges): unknown { + const obj: any = {}; + if (message.ranges?.length) { + obj.ranges = message.ranges.map((e) => AssaultRange.toJSON(e)); + } + if (message.types?.length) { + obj.types = message.types.map((e) => shellTypeToJSON(e)); + } + return obj; + }, + + create, I>>( + base?: I, + ): AssaultRanges { + return AssaultRanges.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): AssaultRanges { + const message = createBaseAssaultRanges(); + message.ranges = + object.ranges?.map((e) => AssaultRange.fromPartial(e)) || []; + message.types = object.types?.map((e) => e) || []; + return message; + }, +}; + +function createBaseAssaultRange(): AssaultRange { + return { distance: 0, factor: 0 }; +} + +export const AssaultRange: MessageFns = { + encode( + message: AssaultRange, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.distance !== 0) { + writer.uint32(13).float(message.distance); + } + if (message.factor !== 0) { + writer.uint32(21).float(message.factor); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): AssaultRange { + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseAssaultRange(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.distance = reader.float(); + continue; + } + case 2: { + if (tag !== 21) { + break; + } + + message.factor = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): AssaultRange { + return { + distance: isSet(object.distance) ? globalThis.Number(object.distance) : 0, + factor: isSet(object.factor) ? globalThis.Number(object.factor) : 0, + }; + }, + + toJSON(message: AssaultRange): unknown { + const obj: any = {}; + if (message.distance !== 0) { + obj.distance = message.distance; + } + if (message.factor !== 0) { + obj.factor = message.factor; + } + return obj; + }, + + create, I>>( + base?: I, + ): AssaultRange { + return AssaultRange.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): AssaultRange { + const message = createBaseAssaultRange(); + message.distance = object.distance ?? 0; + message.factor = object.factor ?? 0; + return message; + }, +}; + +function createBaseShellDefinition(): ShellDefinition { return { id: 0, - name: createBaseI18nString(), + name: undefined, velocity: 0, armor_damage: 0, module_damage: 0, caliber: 0, - icon: "", - penetration: createBaseShellPenetration(), + icon: '', + penetration: undefined, type: 0, - normalization: undefined, - ricochet: undefined, - explosion_radius: undefined, + normalization: 0, + ricochet: 0, + explosion_radius: 0, range: 0, }; } export const ShellDefinition: MessageFns = { - encode(message: ShellDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: ShellDefinition, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.id !== 0) { writer.uint32(8).uint32(message.id); } @@ -3202,22 +3841,28 @@ export const ShellDefinition: MessageFns = { if (message.caliber !== 0) { writer.uint32(53).float(message.caliber); } - if (message.icon !== "") { + if (message.icon !== '') { writer.uint32(58).string(message.icon); } if (message.penetration !== undefined) { - ShellPenetration.encode(message.penetration, writer.uint32(66).fork()).join(); + ShellPenetration.encode( + message.penetration, + writer.uint32(66).fork(), + ).join(); } if (message.type !== 0) { writer.uint32(72).int32(message.type); } - if (message.normalization !== undefined && message.normalization !== undefined) { + if (message.normalization !== undefined && message.normalization !== 0) { writer.uint32(85).float(message.normalization); } - if (message.ricochet !== undefined && message.ricochet !== undefined) { + if (message.ricochet !== undefined && message.ricochet !== 0) { writer.uint32(93).float(message.ricochet); } - if (message.explosion_radius !== undefined && message.explosion_radius !== undefined) { + if ( + message.explosion_radius !== undefined && + message.explosion_radius !== 0 + ) { writer.uint32(101).float(message.explosion_radius); } if (message.range !== 0) { @@ -3227,7 +3872,8 @@ export const ShellDefinition: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): ShellDefinition { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseShellDefinition(); while (reader.pos < end) { @@ -3294,7 +3940,10 @@ export const ShellDefinition: MessageFns = { break; } - message.penetration = ShellPenetration.decode(reader, reader.uint32()); + message.penetration = ShellPenetration.decode( + reader, + reader.uint32(), + ); continue; } case 9: { @@ -3348,19 +3997,29 @@ export const ShellDefinition: MessageFns = { fromJSON(object: any): ShellDefinition { return { - id: globalThis.Number(assertSet("ShellDefinition.id", object.id)), - name: I18nString.fromJSON(assertSet("ShellDefinition.name", object.name)), - velocity: globalThis.Number(assertSet("ShellDefinition.velocity", object.velocity)), - armor_damage: globalThis.Number(assertSet("ShellDefinition.armor_damage", object.armor_damage)), - module_damage: globalThis.Number(assertSet("ShellDefinition.module_damage", object.module_damage)), - caliber: globalThis.Number(assertSet("ShellDefinition.caliber", object.caliber)), - icon: globalThis.String(assertSet("ShellDefinition.icon", object.icon)), - penetration: ShellPenetration.fromJSON(assertSet("ShellDefinition.penetration", object.penetration)), - type: shellTypeFromJSON(assertSet("ShellDefinition.type", object.type)), - normalization: isSet(object.normalization) ? globalThis.Number(object.normalization) : undefined, - ricochet: isSet(object.ricochet) ? globalThis.Number(object.ricochet) : undefined, - explosion_radius: isSet(object.explosion_radius) ? globalThis.Number(object.explosion_radius) : undefined, - range: globalThis.Number(assertSet("ShellDefinition.range", object.range)), + id: isSet(object.id) ? globalThis.Number(object.id) : 0, + name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined, + velocity: isSet(object.velocity) ? globalThis.Number(object.velocity) : 0, + armor_damage: isSet(object.armor_damage) + ? globalThis.Number(object.armor_damage) + : 0, + module_damage: isSet(object.module_damage) + ? globalThis.Number(object.module_damage) + : 0, + caliber: isSet(object.caliber) ? globalThis.Number(object.caliber) : 0, + icon: isSet(object.icon) ? globalThis.String(object.icon) : '', + penetration: isSet(object.penetration) + ? ShellPenetration.fromJSON(object.penetration) + : undefined, + type: isSet(object.type) ? shellTypeFromJSON(object.type) : 0, + normalization: isSet(object.normalization) + ? globalThis.Number(object.normalization) + : 0, + ricochet: isSet(object.ricochet) ? globalThis.Number(object.ricochet) : 0, + explosion_radius: isSet(object.explosion_radius) + ? globalThis.Number(object.explosion_radius) + : 0, + range: isSet(object.range) ? globalThis.Number(object.range) : 0, }; }, @@ -3384,7 +4043,7 @@ export const ShellDefinition: MessageFns = { if (message.caliber !== 0) { obj.caliber = message.caliber; } - if (message.icon !== "") { + if (message.icon !== '') { obj.icon = message.icon; } if (message.penetration !== undefined) { @@ -3393,13 +4052,16 @@ export const ShellDefinition: MessageFns = { if (message.type !== 0) { obj.type = shellTypeToJSON(message.type); } - if (message.normalization !== undefined && message.normalization !== undefined) { + if (message.normalization !== undefined && message.normalization !== 0) { obj.normalization = message.normalization; } - if (message.ricochet !== undefined && message.ricochet !== undefined) { + if (message.ricochet !== undefined && message.ricochet !== 0) { obj.ricochet = message.ricochet; } - if (message.explosion_radius !== undefined && message.explosion_radius !== undefined) { + if ( + message.explosion_radius !== undefined && + message.explosion_radius !== 0 + ) { obj.explosion_radius = message.explosion_radius; } if (message.range !== 0) { @@ -3408,38 +4070,47 @@ export const ShellDefinition: MessageFns = { return obj; }, - create, I>>(base?: I): ShellDefinition { + create, I>>( + base?: I, + ): ShellDefinition { return ShellDefinition.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): ShellDefinition { + fromPartial, I>>( + object: I, + ): ShellDefinition { const message = createBaseShellDefinition(); message.id = object.id ?? 0; - message.name = (object.name !== undefined && object.name !== null) - ? I18nString.fromPartial(object.name) - : createBaseI18nString(); + message.name = + object.name !== undefined && object.name !== null + ? I18nString.fromPartial(object.name) + : undefined; message.velocity = object.velocity ?? 0; message.armor_damage = object.armor_damage ?? 0; message.module_damage = object.module_damage ?? 0; message.caliber = object.caliber ?? 0; - message.icon = object.icon ?? ""; - message.penetration = (object.penetration !== undefined && object.penetration !== null) - ? ShellPenetration.fromPartial(object.penetration) - : createBaseShellPenetration(); + message.icon = object.icon ?? ''; + message.penetration = + object.penetration !== undefined && object.penetration !== null + ? ShellPenetration.fromPartial(object.penetration) + : undefined; message.type = object.type ?? 0; - message.normalization = object.normalization ?? undefined; - message.ricochet = object.ricochet ?? undefined; - message.explosion_radius = object.explosion_radius ?? undefined; + message.normalization = object.normalization ?? 0; + message.ricochet = object.ricochet ?? 0; + message.explosion_radius = object.explosion_radius ?? 0; message.range = object.range ?? 0; return message; }, }; -export function createBaseShellPenetration(): ShellPenetration { +function createBaseShellPenetration(): ShellPenetration { return { near: 0, far: 0 }; } export const ShellPenetration: MessageFns = { - encode(message: ShellPenetration, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: ShellPenetration, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.near !== 0) { writer.uint32(13).float(message.near); } @@ -3450,7 +4121,8 @@ export const ShellPenetration: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): ShellPenetration { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseShellPenetration(); while (reader.pos < end) { @@ -3483,8 +4155,8 @@ export const ShellPenetration: MessageFns = { fromJSON(object: any): ShellPenetration { return { - near: globalThis.Number(assertSet("ShellPenetration.near", object.near)), - far: globalThis.Number(assertSet("ShellPenetration.far", object.far)), + near: isSet(object.near) ? globalThis.Number(object.near) : 0, + far: isSet(object.far) ? globalThis.Number(object.far) : 0, }; }, @@ -3499,10 +4171,14 @@ export const ShellPenetration: MessageFns = { return obj; }, - create, I>>(base?: I): ShellPenetration { + create, I>>( + base?: I, + ): ShellPenetration { return ShellPenetration.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): ShellPenetration { + fromPartial, I>>( + object: I, + ): ShellPenetration { const message = createBaseShellPenetration(); message.near = object.near ?? 0; message.far = object.far ?? 0; @@ -3510,12 +4186,15 @@ export const ShellPenetration: MessageFns = { }, }; -export function createBaseUnlock(): Unlock { - return { id: 0, type: 0, cost: createBaseUnlockCost() }; +function createBaseUnlock(): Unlock { + return { id: 0, type: 0, cost: undefined }; } export const Unlock: MessageFns = { - encode(message: Unlock, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: Unlock, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.id !== 0) { writer.uint32(8).int32(message.id); } @@ -3529,7 +4208,8 @@ export const Unlock: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): Unlock { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseUnlock(); while (reader.pos < end) { @@ -3570,9 +4250,9 @@ export const Unlock: MessageFns = { fromJSON(object: any): Unlock { return { - id: globalThis.Number(assertSet("Unlock.id", object.id)), - type: moduleTypeFromJSON(assertSet("Unlock.type", object.type)), - cost: UnlockCost.fromJSON(assertSet("Unlock.cost", object.cost)), + id: isSet(object.id) ? globalThis.Number(object.id) : 0, + type: isSet(object.type) ? moduleTypeFromJSON(object.type) : 0, + cost: isSet(object.cost) ? UnlockCost.fromJSON(object.cost) : undefined, }; }, @@ -3597,20 +4277,24 @@ export const Unlock: MessageFns = { const message = createBaseUnlock(); message.id = object.id ?? 0; message.type = object.type ?? 0; - message.cost = (object.cost !== undefined && object.cost !== null) - ? UnlockCost.fromPartial(object.cost) - : createBaseUnlockCost(); + message.cost = + object.cost !== undefined && object.cost !== null + ? UnlockCost.fromPartial(object.cost) + : undefined; return message; }, }; -export function createBaseUnlockCost(): UnlockCost { - return { type: "", value: 0 }; +function createBaseUnlockCost(): UnlockCost { + return { type: '', value: 0 }; } export const UnlockCost: MessageFns = { - encode(message: UnlockCost, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.type !== "") { + encode( + message: UnlockCost, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { + if (message.type !== '') { writer.uint32(10).string(message.type); } if (message.value !== 0) { @@ -3620,7 +4304,8 @@ export const UnlockCost: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): UnlockCost { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseUnlockCost(); while (reader.pos < end) { @@ -3653,14 +4338,14 @@ export const UnlockCost: MessageFns = { fromJSON(object: any): UnlockCost { return { - type: globalThis.String(assertSet("UnlockCost.type", object.type)), - value: globalThis.Number(assertSet("UnlockCost.value", object.value)), + type: isSet(object.type) ? globalThis.String(object.type) : '', + value: isSet(object.value) ? globalThis.Number(object.value) : 0, }; }, toJSON(message: UnlockCost): unknown { const obj: any = {}; - if (message.type !== "") { + if (message.type !== '') { obj.type = message.type; } if (message.value !== 0) { @@ -3672,20 +4357,25 @@ export const UnlockCost: MessageFns = { create, I>>(base?: I): UnlockCost { return UnlockCost.fromPartial(base ?? ({} as any)); }, - fromPartial, I>>(object: I): UnlockCost { + fromPartial, I>>( + object: I, + ): UnlockCost { const message = createBaseUnlockCost(); - message.type = object.type ?? ""; + message.type = object.type ?? ''; message.value = object.value ?? 0; return message; }, }; -export function createBaseCrew(): Crew { +function createBaseCrew(): Crew { return { type: 0, count: 0, substitute: [] }; } export const Crew: MessageFns = { - encode(message: Crew, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + encode( + message: Crew, + writer: BinaryWriter = new BinaryWriter(), + ): BinaryWriter { if (message.type !== 0) { writer.uint32(8).int32(message.type); } @@ -3701,7 +4391,8 @@ export const Crew: MessageFns = { }, decode(input: BinaryReader | Uint8Array, length?: number): Crew { - const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const reader = + input instanceof BinaryReader ? input : new BinaryReader(input); let end = length === undefined ? reader.len : reader.pos + length; const message = createBaseCrew(); while (reader.pos < end) { @@ -3752,8 +4443,8 @@ export const Crew: MessageFns = { fromJSON(object: any): Crew { return { - type: crewTypeFromJSON(assertSet("Crew.type", object.type)), - count: globalThis.Number(assertSet("Crew.count", object.count)), + type: isSet(object.type) ? crewTypeFromJSON(object.type) : 0, + count: isSet(object.count) ? globalThis.Number(object.count) : 0, substitute: globalThis.Array.isArray(object?.substitute) ? object.substitute.map((e: any) => crewTypeFromJSON(e)) : [], @@ -3786,35 +4477,42 @@ export const Crew: MessageFns = { }, }; -type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; +type Builtin = + | Date + | Function + | Uint8Array + | string + | number + | boolean + | undefined; -export type DeepPartial = T extends Builtin ? T - : T extends globalThis.Array ? globalThis.Array> - : T extends ReadonlyArray ? ReadonlyArray> - : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } - : T extends {} ? { [K in keyof T]?: DeepPartial } - : Partial; +export type DeepPartial = T extends Builtin + ? T + : T extends globalThis.Array + ? globalThis.Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends { $case: string; value: unknown } + ? { $case: T['$case']; value?: DeepPartial } + : T extends {} + ? { [K in keyof T]?: DeepPartial } + : Partial; type KeysOfUnion = T extends T ? keyof T : never; -export type Exact = P extends Builtin ? P - : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; +export type Exact = P extends Builtin + ? P + : P & { [K in keyof P]: Exact } & { + [K in Exclude>]: never; + }; function isObject(value: any): boolean { - return typeof value === "object" && value !== null; + return typeof value === 'object' && value !== null; } function isSet(value: any): boolean { return value !== null && value !== undefined; } -function assertSet(field: string, value: T | undefined): T { - if (!isSet(value)) { - throw new TypeError(`Required field ${field} is not set`); - } - - return value as T; -} - export interface MessageFns { encode(message: T, writer?: BinaryWriter): BinaryWriter; decode(input: BinaryReader | Uint8Array, length?: number): T; diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json index e77bb6e95..58a6a4faa 100644 --- a/packages/i18n/strings/en.json +++ b/packages/i18n/strings/en.json @@ -799,6 +799,7 @@ "fire.caliber": "caliber", "fire.standardPenetration": "standard penetration", "fire.premiumPenetration": "premium penetration", + "fire.tertiaryPenetration": "tertiary penetration", "fire.damage": "damage", "fire.moduleDamage": "module damage", "fire.shellVelocity": "shell velocity", @@ -902,6 +903,10 @@ "tank_seo_description": "%s1 armor, statistics, equipment, provisions, and more. %s2 DPM, %s3hp alpha, %s4mm penetration, %s5kph top speed, %s6hp health.", "visualizers": { + "assault": { + "title": "Assault shells" + }, + "rotator": { "hull": "Hull", "turret": "Turret", @@ -1094,7 +1099,6 @@ "hull_traverse_speed": "Hull traverse speed", "camouflage": "Camouflage", "reload": "Reload", - "crewCount": "Crew count", "shellNormalization": "Normalization", "shellRicochet": "Ricochet", @@ -1108,6 +1112,7 @@ "caliber": "Caliber", "penetration": "Penetration", "damage": "Damage", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "Clipping potential", "moduleDamage": "Module damage", "explosionRadius": "Explosion radius", diff --git a/packages/i18n/strings/es.json b/packages/i18n/strings/es.json index 6ba418653..b0614d71c 100644 --- a/packages/i18n/strings/es.json +++ b/packages/i18n/strings/es.json @@ -698,6 +698,7 @@ "fire.caliber": "calibre", "fire.standardPenetration": "penetraciรณn estรกndar", "fire.premiumPenetration": "penetraciรณn prรฉmium", + "fire.tertiaryPenetration": "tertiary penetration", "fire.damage": "daรฑo", "fire.moduleDamage": "daรฑo al mรณdulo", "fire.shellVelocity": "velocidad del proyectil", @@ -786,6 +787,9 @@ "tank_seo_title": "%s1 - Nivel %s2 %s3 %s4 | %s5 Tankopedia | World of Tanks Blitz (WoTB)", "tank_seo_description": "%s1 blindaje, estadisticas, equipamiento, proviciones y mas.\n%s2 DPM, %3hp alfa, %s4mm penetracion, %s5kph velocidad maxima, %s6 hp salud", "visualizers": { + "assault": { + "title": "Assault shells" + }, "rotator": { "hull": "Hull", "turret": "Turret", @@ -975,6 +979,7 @@ "caliber": "Calibre", "penetration": "Penetraciรณn", "damage": "Daรฑo", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "Clipping potential", "moduleDamage": "Daรฑo a mรณdulos", "explosionRadius": "Radio de Explosiรณn", diff --git a/packages/i18n/strings/fr.json b/packages/i18n/strings/fr.json index d183a3ade..38a9bbb5f 100644 --- a/packages/i18n/strings/fr.json +++ b/packages/i18n/strings/fr.json @@ -698,6 +698,7 @@ "fire.caliber": "caliber", "fire.standardPenetration": "standard penetration", "fire.premiumPenetration": "premium penetration", + "fire.tertiaryPenetration": "tertiary penetration", "fire.damage": "damage", "fire.moduleDamage": "module damage", "fire.shellVelocity": "shell velocity", @@ -786,6 +787,9 @@ "tank_seo_title": "%s1 - Tier %s2 %s3 %s4 | %s5 Tankopedia | World of Tanks Blitz (WoTB)", "tank_seo_description": "%s1 armor, statistics, equipment, provisions, and more. %s2 DPM, %s3hp alpha, %s4mm penetration, %s5kph top speed, %s6hp health.", "visualizers": { + "assault": { + "title": "Assault shells" + }, "rotator": { "hull": "Hull", "turret": "Turret", @@ -975,6 +979,7 @@ "caliber": "Caliber", "penetration": "Penetration", "damage": "Dรฉgรขts", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "Clipping potential", "moduleDamage": "Module damage", "explosionRadius": "Explosion radius", diff --git a/packages/i18n/strings/ja.json b/packages/i18n/strings/ja.json index a73997df6..209598c11 100644 --- a/packages/i18n/strings/ja.json +++ b/packages/i18n/strings/ja.json @@ -698,6 +698,7 @@ "fire.caliber": "็ ฒๅฃๅพ„", "fire.standardPenetration": "้€šๅธธๅผพ่ฒซ้€šๅŠ›", "fire.premiumPenetration": "่ชฒ้‡‘ๅผพ่ฒซ้€šๅŠ›", + "fire.tertiaryPenetration": "tertiary penetration", "fire.damage": "ใƒ€ใƒกใƒผใ‚ธ", "fire.moduleDamage": "ใƒขใ‚ธใƒฅใƒผใƒซใƒ€ใƒกใƒผใ‚ธ", "fire.shellVelocity": "ๅผพ้€Ÿ", @@ -786,6 +787,9 @@ "tank_seo_title": "%s1 - Tier %s2 %s3 %s4 | %s5 Tankopedia | World of Tanks Blitz (WoTB)", "tank_seo_description": "%s1 armor, statistics, equipment, provisions, and more. %s2 DPM, %s3hp alpha, %s4mm penetration, %s5kph top speed, %s6hp health.", "visualizers": { + "assault": { + "title": "Assault shells" + }, "rotator": { "hull": "Hull", "turret": "Turret", @@ -975,6 +979,7 @@ "caliber": "ๅฃๅพ„", "penetration": "่ฒซ้€šๅŠ›", "damage": "ใƒ€ใƒกใƒผใ‚ธ", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "ๅผพๅ€‰็ซๅŠ›", "moduleDamage": "ใƒขใ‚ธใƒฅใƒผใƒซใƒ€ใƒกใƒผใ‚ธ", "explosionRadius": "็ˆ†้ขจๅŠๅพ„", diff --git a/packages/i18n/strings/pl.json b/packages/i18n/strings/pl.json index b95971eda..9f8ea28a5 100644 --- a/packages/i18n/strings/pl.json +++ b/packages/i18n/strings/pl.json @@ -380,7 +380,7 @@ }, "embeds": { "name": "osadzenie", - "description": "Jak dziaล‚a osadzanie" + "description": "Jak dziaล‚ajฤ… osadzone" }, "introduction": { "name": "wprowadzenie", @@ -698,6 +698,7 @@ "fire.caliber": "caliber", "fire.standardPenetration": "standard penetration", "fire.premiumPenetration": "premium penetration", + "fire.tertiaryPenetration": "tertiary penetration", "fire.damage": "damage", "fire.moduleDamage": "module damage", "fire.shellVelocity": "shell velocity", @@ -786,6 +787,9 @@ "tank_seo_title": "%s1 - Tier %s2 %s3 %s4 | %s5 Tankopedia | World of Tanks Blitz (WoTB)", "tank_seo_description": "%s1 armor, statistics, equipment, provisions, and more. %s2 DPM, %s3hp alpha, %s4mm penetration, %s5kph top speed, %s6hp health.", "visualizers": { + "assault": { + "title": "Assault shells" + }, "rotator": { "hull": "Hull", "turret": "Turret", @@ -975,6 +979,7 @@ "caliber": "Caliber", "penetration": "Penetration", "damage": "Uszkodzenia", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "Clipping potential", "moduleDamage": "Module damage", "explosionRadius": "Explosion radius", diff --git a/packages/i18n/strings/pt.json b/packages/i18n/strings/pt.json index 7e4567e19..ff7844c75 100644 --- a/packages/i18n/strings/pt.json +++ b/packages/i18n/strings/pt.json @@ -698,6 +698,7 @@ "fire.caliber": "calibre", "fire.standardPenetration": "penetraรงรฃo padrรฃo", "fire.premiumPenetration": "penetraรงรฃo premium", + "fire.tertiaryPenetration": "tertiary penetration", "fire.damage": "dano", "fire.moduleDamage": "dano a mรณdulos", "fire.shellVelocity": "velocidade do projรฉtil", @@ -786,6 +787,9 @@ "tank_seo_title": "%s1 - Nรญvel %s2 %s3 %s4 | %s5 Tanquepedia | World of Tanks Blitz (WoTB)", "tank_seo_description": "%s1 blindagem, estatรญsticas, equipamentos, provisรตes e mais. %s2 DPM, %s3hp alfa, %s4mm de penetraรงรฃo, %s5km/h velocidade mรกxima, %s6hp vida.", "visualizers": { + "assault": { + "title": "Assault shells" + }, "rotator": { "hull": "Hull", "turret": "Turret", @@ -975,6 +979,7 @@ "caliber": "Calibre", "penetration": "Penetraรงรฃo", "damage": "Dano", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "Potencial de clipe", "moduleDamage": "Dano a mรณdulos", "explosionRadius": "Raio de Explosรฃo", diff --git a/packages/i18n/strings/ru.json b/packages/i18n/strings/ru.json index ef6a4ee65..7ec10e078 100644 --- a/packages/i18n/strings/ru.json +++ b/packages/i18n/strings/ru.json @@ -697,7 +697,8 @@ "fire.reload": "ะฟะตั€ะตะทะฐั€ัะดะบะฐ", "fire.caliber": "ะบะฐะปะธะฑั€", "fire.standardPenetration": "ะฑะฐะทะพะฒะพะต ะฟั€ะพะฑะธั‚ะธะต", - "fire.premiumPenetration": "ัƒะปัƒั‡ัˆะตะฝะฝะพะต ะฟั€ะพะฑะธั‚ะธะต ", + "fire.premiumPenetration": "ะฟั€ะตะผะธัƒะผะฝะพะต ะฟั€ะพะฑะธั‚ะธะต ", + "fire.tertiaryPenetration": "ะฟั€ะพะฑะธั‚ะธะต ั‚ั€ะตั‚ัŒะตะณะพ ัะฝะฐั€ัะดะฐ", "fire.damage": "ัƒั€ะพะฝ", "fire.moduleDamage": "ัƒั€ะพะฝ ะฟะพ ะผะพะดัƒะปัะผ", "fire.shellVelocity": "ัะบะพั€ะพัั‚ัŒ ัะฝะฐั€ัะดะฐ", @@ -786,6 +787,9 @@ "tank_seo_title": "%s1 - %s4 %s3 %s2 ัƒั€ะพะฒะฝั | ะขะฐะฝะบะพะฟะตะดะธั %s5 | World of Tanks Blitz (WoTB)", "tank_seo_description": "%s1 ะฑั€ะพะฝั, ัั‚ะฐั‚ะธัั‚ะธะบะฐ, ะพะฑะพั€ัƒะดะพะฒะฐะฝะธะต, ัะฝะฐะฑะถะตะฝะธะต ะธ ะผะฝะพะณะพะต ะดั€ัƒะณะพะต. %s2 ะฃะ’ะœ, %s3hp ะฐะปัŒั„ะฐ, %s4mm ะฟั€ะพะฑะธั‚ะธะต, %s5ะบะผ/ั‡ ะปัƒั‡ัˆะฐั ัะบะพั€ะพัั‚ัŒ, %s6hp ะทะดะพั€ะพะฒัŒะต.", "visualizers": { + "assault": { + "title": "Assault shells" + }, "rotator": { "hull": "ะšะพั€ะฟัƒั", "turret": "ะ‘ะฐัˆะฝั", @@ -975,6 +979,7 @@ "caliber": "ะšะฐะปะธะฑั€", "penetration": "ะŸั€ะพะฑะธั‚ะธะต", "damage": "ะฃั€ะพะฝ", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "ะฃั€ะพะฝ ั ะฑะฐั€ะฐะฑะฐะฝะฐ", "moduleDamage": "ะฃั€ะพะฝ ะฟะพ ะผะพะดัƒะปัะผ", "explosionRadius": "ะ ะฐะทะปะตั‚ ะพัะบะพะปะบะพะฒ", diff --git a/packages/i18n/strings/uk.json b/packages/i18n/strings/uk.json index 11abffc29..3a7b9847e 100644 --- a/packages/i18n/strings/uk.json +++ b/packages/i18n/strings/uk.json @@ -2,7 +2,7 @@ "test": { "default": "ั‚ะตัั‚", "long": "This is a long test string. You MUST NEVER see this in the UI. My favorite fruit is %s1 because it has the color of %s2. I like it so much that I will say its name 3 times! %s1! %s1! %s1! Once again, it's %s2, not %s3.", - "fox": "The quick brown fox jumps over the lazy dog." + "fox": "ะจะฒะธะดะบะฐ ะฑัƒั€ะฐ ะปะธัะธั†ั ะฟะตั€ะตัั‚ั€ะธะฑัƒั” ั‡ะตั€ะตะท ะปั–ะฝะธะฒะพะณะพ ัะพะฑะฐะบัƒ." }, "common": { "units": { @@ -12,7 +12,7 @@ "hp": "%s1ั…ะฟ", "x": "ั…%s1", "percentage": "%s1%", - "deg_s": "%s1ยฐ/s" + "deg_s": "%s1ยฐ/ั" }, "gun_types": { "auto_loader": "ะœะฐะณะฐะทะธะฝะฝะฐ ัะธัั‚ะตะผะฐ ะทะฐั€ัะดะถะฐะฝะฝั", @@ -413,10 +413,10 @@ } }, "debug": { - "name": "debug", - "description": "Debug information about the bot", + "name": "ะฝะฐะปะฐะณะพะดะถะตะฝะฝั", + "description": "ะ†ะฝั„ะพั€ะผะฐั†ั–ั ะฟั€ะพ ะฝะฐะปะฐะณะพะดะถะตะฝะฝั ะฑะพั‚ะฐ", "body": { - "title": "# Debug\n\n", + "title": "# ะะฐะปะฐะณะพะดะถะตะฝะฝั\n\n", "version": "ะ’ะตั€ัั–ั", "shard": { "label": "ะฃะปะฐะผะพะบ", @@ -499,7 +499,7 @@ }, "embed": { "title": "ะะตะฒั–ั€ะฝะธะน ะพะฑะปั–ะบะพะฒะธะน ะทะฐะฟะธั?", - "description": "Use the command again and select a username from the search results." + "description": "ะ’ะธะบะพั€ะธัั‚ะฐะนั‚ะต ะบะพะผะฐะฝะดัƒ ั‰ะต ั€ะฐะท ั– ะฒะธะฑะตั€ั–ั‚ัŒ ั–ะผ'ั ะบะพั€ะธัั‚ัƒะฒะฐั‡ะฐ ะท ั€ะตะทัƒะปัŒั‚ะฐั‚ั–ะฒ ะฟะพัˆัƒะบัƒ." } }, "search_clans": { @@ -508,7 +508,7 @@ "options": { "limit": { "name": "ะปั–ะผั–ั‚", - "description": "The max number of clan results (default: %s1)" + "description": "ะœะฐะบัะธะผะฐะปัŒะฝะฐ ะบั–ะปัŒะบั–ัั‚ัŒ ั€ะตะทัƒะปัŒั‚ะฐั‚ั–ะฒ ะบะปะฐะฝัƒ (ะทะฐ ะทะฐะผะพะฒั‡ัƒะฒะฐะฝะฝัะผ: %s1)" } }, "body": { @@ -531,16 +531,16 @@ } }, "rating_leaderboard": { - "name": "rating-leaderboard", - "description": "Rating battles statistics", + "name": "ั‚ะฐะฑะปะธั†ั ั€ะตะนั‚ะธะฝะณัƒ", + "description": "ะกั‚ะฐั‚ะธัั‚ะธะบะฐ ั€ะตะนั‚ะธะฝะณะพะฒะธั… ะฑะพั—ะฒ", "subcommands": { "neighbors": { "name": "neighbors", "description": "Neighboring players on the leaderboard" }, "league": { - "name": "league", - "description": "Top players of a league" + "name": "ะปั–ะณะฐ", + "description": "ะะฐะนะบั€ะฐั‰ะธะน ะณั€ะฐะฒะตั†ัŒ ะปั–ะณะธ" } }, "options": { @@ -549,8 +549,8 @@ "description": "" }, "season": { - "name": "season", - "description": "Season number (default: current)", + "name": "ัะตะทะพะฝ", + "description": "ะ‘ะฐะทะพะฒะฐ ั–ะฝั„ะพั€ะผะฐั†ั–ั ะฟั€ะพ ะณั€ะฐะฒั†ั", "choices": { "current": "%s1 (current)" } @@ -578,14 +578,14 @@ "description": "ะšะพั€ะพั‚ะบะฐ ัั‚ะฐั‚ะธัั‚ะธะบะฐ ะทะฐ ะฟะตั€ั–ะพะด" }, "owned_tanks": { - "name": "owned-tanks", - "description": "Shows all own tanks in a tier", + "name": "ะพั‚ั€ะธะผะฐะฝั– ั‚ะฐะฝะบะธ", + "description": "ะŸะพะบะฐะทัƒั” ะฒัั– ะฒะฐัˆั– ั‚ะฐะฝะบะธ ะดะฐะฝะพะณะพ ั€ั–ะฒะฝั", "body": { "title": "# %s1's owned tier %s2 tanks\n\n" } }, "permissions": { - "name": "permissions", + "name": "ะดะพะทะฒะพะปะธ", "description": "Checks wether the bot has the required permissions to function", "body": { "title": "# Permissions\n\n%s1", @@ -615,7 +615,7 @@ }, "player_info": { "name": "player-info", - "description": "Basic information about a player", + "description": "ะ‘ะฐะทะพะฒะฐ ั–ะฝั„ะพั€ะผะฐั†ั–ั ะฟั€ะพ ะณั€ะฐะฒั†ั", "body": { "title": "%s1's information", "nickname": "ะั–ะบ", @@ -635,7 +635,7 @@ "description": "Today's rating statistics" }, "season": { - "name": "season", + "name": "ัะตะทะพะฝ", "description": "This season's rating statistics" } }, @@ -698,6 +698,7 @@ "fire.caliber": "ะบะฐะปั–ะฑั€", "fire.standardPenetration": "ะฑะฐะทะพะฒะต ะฟั€ะพะฑะธั‚ั‚ั", "fire.premiumPenetration": "ะฟั€ะตะผั–ัƒะผ ะฟั€ะพะฑะธั‚ั‚ั", + "fire.tertiaryPenetration": "tertiary penetration", "fire.damage": "ัˆะบะพะดะฐ", "fire.moduleDamage": "ัˆะบะพะดะฐ ะฟะพ ะผะพะดัƒะปัั…", "fire.shellVelocity": "ัˆะฒะธะดะบั–ัั‚ัŒ ะฟะพะปัŒะพั‚ัƒ ัะฝะฐั€ัะดะฐ", @@ -786,6 +787,9 @@ "tank_seo_title": "%s1 - ะ ั–ะฒะตะฝัŒ %s2 %s3 %s4 | %s5 ะขะฐะฝะบะพะฟะตะดั–ั | WoT Blitz", "tank_seo_description": "%s1 ะฑั€ะพะฝั, ั…ะฐั€ะฐะบั‚ะตั€ะธัั‚ะธะบะธ, ะพะฑะปะฐะดะฝะฐะฝะฝั, ะฐะผัƒะฝั–ั†ั–ั ั‚ะฐ ะฑั–ะปัŒัˆะต. %s2 ัˆะบะพะดะฐ ะฝะฐ ั…ะฒะธะปะธะฝัƒ, %s3 ั€ะฐะทะพะฒะฐ ัˆะบะพะดะฐ, %s4 ะผะผ ะฟั€ะพะฑะธั‚ั‚ั, %s5 ะบะผ/ะณะพะด ะผะฐะบัะธะผะฐะปัŒะฝะฐ ัˆะฒะธะดะบั–ัั‚ัŒ, %s6 ะผั–ั†ะฝั–ัั‚ัŒ.", "visualizers": { + "assault": { + "title": "Assault shells" + }, "rotator": { "hull": "Hull", "turret": "Turret", @@ -975,6 +979,7 @@ "caliber": "ะšะฐะปั–ะฑั€", "penetration": "ะ‘ั€ะพะฝะตะฟั€ะพะฑะธั‚ั‚ั", "damage": "ะจะบะพะดะฐ", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "Clipping potential", "moduleDamage": "ะจะบะพะดะฐ ะฟะพ ะผะพะดัƒะปัั…", "explosionRadius": "ะ ะฐะดั–ัƒั ั€ะพะทะปัŒะพั‚ัƒ ัƒะปะฐะผะบั–ะฒ", diff --git a/packages/i18n/strings/zh.json b/packages/i18n/strings/zh.json index 1339e35ae..fedec6ac4 100644 --- a/packages/i18n/strings/zh.json +++ b/packages/i18n/strings/zh.json @@ -41,15 +41,15 @@ "preview": "้ข„่งˆ" }, "locales": { - "en": "่‹ฑๆ–‡", - "es": "่ฅฟ็ญ็‰™ๆ–‡", - "pt": "่‘ก่„็‰™ๆ–‡", - "ru": "ไฟ„ๆ–‡", - "uk": "ไนŒๅ…‹ๅ…ฐๆ–‡", + "en": "่‹ฑ่ฏญ", + "es": "่ฅฟ็ญ็‰™่ฏญ", + "pt": "่‘ก่„็‰™่ฏญ", + "ru": "ไฟ„่ฏญ", + "uk": "ไนŒๅ…‹ๅ…ฐ่ฏญ", "zh": "ไธญๆ–‡", - "ja": "ๆ—ฅๆ–‡", - "fr": "ๆณ•ๆ–‡", - "pl": "ๆณขๅ…ฐๆ–‡" + "ja": "ๆ—ฅ่ฏญ", + "fr": "ๆณ•่ฏญ", + "pl": "ๆณขๅ…ฐ่ฏญ" }, "wn8_percentile": { "0": "้žๅธธๅทฎ", @@ -283,7 +283,7 @@ "name": "้˜ถ็บง", "description": "้˜ถ็บง", "choices": { - "tier": "%s1- %s2 ็บง" + "tier": "%s1้˜ถ - %s2" } } }, @@ -494,7 +494,7 @@ "accounts_linked": "ๅธๅทๅทฒ็ป‘ๅฎš", "no_role_permissions": { "title": "%s1 ้ชŒ่ฏๅคฑ่ดฅ", - "description": "ๆˆ‘ๆฒกๆœ‰็ฎก็†่ง’่‰ฒ็š„ๆƒ้™ใ€‚" + "description": "ๆˆ‘ๆฒกๆœ‰็ฎก็†่บซไปฝ็š„ๆƒ้™ใ€‚" } }, "embed": { @@ -517,7 +517,7 @@ } }, "search_players": { - "name": "ๆœ็ดข็Žฉๅฎถ", + "name": "ๆœ็ดข-็Žฉๅฎถ", "description": "ๆœ็ดข็Žฉๅฎถ", "options": { "limit": { @@ -578,7 +578,7 @@ "description": "ไธ€ๆฎตๆ—ถ้—ดๅ†…็š„ๅฟซ้€Ÿ็ปŸ่ฎก" }, "owned_tanks": { - "name": "ๅทฒๆ“ๆœ‰็š„ๆˆฐ่ปŠ", + "name": "ๅทฒๆ‹ฅๆœ‰็š„ๆˆ˜่ฝฆ", "description": "ๆ˜พ็คบ่ฏฅ้˜ถ็บงไธญๆ‰€ๆœ‰ๆ‚จๅทฒๆ‹ฅๆœ‰็š„ๆˆ˜่ฝฆ", "body": { "title": "# %s1 ๆ‰€ๆ‹ฅๆœ‰็š„ %s2 ้˜ถๆˆ˜่ฝฆ\n\n" @@ -589,8 +589,8 @@ "description": "ๆฃ€ๆŸฅๆœบๅ™จไบบๆ˜ฏๅฆๆ‹ฅๆœ‰่ฟ่กŒๆ‰€้œ€็š„ๆƒ้™", "body": { "title": "# ๆƒ้™\n\n%s1", - "view_channels": "ๆŸฅ็œ‹้ ป้“๏ผš้œ€่ฆๆ‰พๅˆฐ้‡ๆ–ฐๆ•ด็†ๆŒ‰้ˆ•ไฝฟ็”จ็š„่จŠๆฏ", - "read_message_history": "่ฎ€ๅ–ๆญทๅฒ่จŠๆฏ: ้œ€่ฆๆ‰พๅˆฐ่จŠๆฏไปฅ้‡ๆ–ฐๆ•ด็†", + "view_channels": "ๆŸฅ็œ‹้ข‘้“๏ผš้œ€่ฆๆ‰พๅˆฐ้‡ๆ–ฐๆ•ด็†ๆŒ‰้’ฎไฝฟ็”จ็š„่ฎฏๆฏ", + "read_message_history": "่ฏปๅ–ๆถˆๆฏๅކๅฒ: ้œ€่ฆๆ‰พๅˆฐๆถˆๆฏไปฅๅˆทๆ–ฐ", "attach_files": "้™„ๅŠ ๆ–‡ไปถ๏ผš้œ€่ฆๅฐ†ๅ›พๅƒๆทปๅŠ ๅˆฐๅŸบไบŽๅ›พๅƒ็š„ๅ‘ฝไปค", "external_emojis": "ๅค–้ƒจ่กจๆƒ…็ฌฆๅท๏ผš้œ€่ฆๆทปๅŠ ๅ›ฝๅฎถๆ——ๅธœๅ’Œๆˆ˜่ฝฆ็ฑปๅˆซ" } @@ -698,6 +698,7 @@ "fire.caliber": "ๅฃๅพ„", "fire.standardPenetration": "ๆ ‡ๅ‡†็‚ฎๅผน็ฉฟ้€ๅŠ›", "fire.premiumPenetration": "ๅŠ ๅ€ผ็‚ฎๅผน็ฉฟ้€ๅŠ›", + "fire.tertiaryPenetration": "tertiary penetration", "fire.damage": "็‚ฎๅผนไผคๅฎณๅ€ผ", "fire.moduleDamage": "ๆจก็ป„ไผคๅฎณๅ€ผ", "fire.shellVelocity": "็‚ฎๅผน้ฃž่กŒ้€Ÿๅบฆ", @@ -786,6 +787,9 @@ "tank_seo_title": "%s1 - %s2 ้˜ถ %s3 %s4 | %s5 ๆˆ˜่ฝฆ็™พ็ง‘ | ๆˆ˜่ฝฆไธ–็•Œ้—ชๅ‡ปๆˆ˜ (WoTB)", "tank_seo_description": "%s1 ่ฃ…็”ฒ๏ผŒ็ปŸ่ฎก่ฎพๅค‡๏ผŒ่ฃ…ๅค‡๏ผŒไพ›็ป™็ญ‰ใ€‚ %s2 ๆฏๅˆ†้’Ÿไผคๅฎณ๏ผŒ %s3็”Ÿๅ‘ฝๅ€ผ๏ผŒ %s4ๆฏซ็ฑณ็ฉฟ้€๏ผŒ %s5kph ๆœ€้ซ˜้€Ÿๅบฆ๏ผŒ %s6hp ็”Ÿๅ‘ฝๅ€ผใ€‚", "visualizers": { + "assault": { + "title": "Assault shells" + }, "rotator": { "hull": "่ฝฆไฝ“", "turret": "็‚ฎๅก”", @@ -796,9 +800,9 @@ }, "ricochet": { "angle": "่ง’ๅบฆ", - "normalization": "่ฝ‰ๆญฃ", + "normalization": "่ฝฌๆญฃ", "effective_angle": "ๆœ‰ๆ•ˆ่ง’ๅบฆ", - "armor": "่ฃ็”ฒ", + "armor": "่ฃ…็”ฒ", "no_ricochet": "้ซ˜็ˆ†ๅผนไธไผš่ทณๅผน" }, "view_range": { @@ -854,7 +858,7 @@ "track": "ๅฑฅๅธฆ" }, "status": { - "penetration": "%s1็”Ÿๅ‘ฝๅ€ผ ๆ“Š็ฉฟ", + "penetration": "%s1็”Ÿๅ‘ฝๅ€ผ ๅ‡ป็ฉฟ", "blocked": "ๆŠตๆŒกไผคๅฎณ", "ricochet": "่ทณๅผน", "splash": "%s1็”Ÿๅ‘ฝๅ€ผ ๆบ…ๅฐ„" @@ -975,6 +979,7 @@ "caliber": "ๅฃๅพ„", "penetration": "็ฉฟๆทฑ", "damage": "ไผคๅฎณ", + "damageWithoutAssault": "Damage without assault shells", "clipDamage": "ๅผนๅŒฃไผคๅฎณๆœŸๆœ›ๅ€ผ", "moduleDamage": "ๆจก็ป„ไผคๅฎณ", "explosionRadius": "ๆบ…ๅฐ„ๅŠๅพ„", diff --git a/packages/scripts/src/buildAssets/blitzkitTankIcons.ts b/packages/scripts/src/buildAssets/blitzkitTankIcons.ts index c2cb2f6f1..2170aac46 100644 --- a/packages/scripts/src/buildAssets/blitzkitTankIcons.ts +++ b/packages/scripts/src/buildAssets/blitzkitTankIcons.ts @@ -7,7 +7,6 @@ import { FileChange } from '../core/github/commitMultipleFiles'; export async function blitzkitTankIcons() { console.log('Building blitzkit tank icons...'); - console.log('Starting website dev server...'); const browser = await launch(); const page = await browser.newPage(); const tanks = Object.values((await fetchTankDefinitions()).tanks); @@ -19,12 +18,14 @@ export async function blitzkitTankIcons() { width: BLITZKIT_TANK_ICON_SIZE.width - 1, height: BLITZKIT_TANK_ICON_SIZE.height, }); - await page.goto(`http://localhost:4321/api/tankopedia/tank-icon/${id}/`, { - waitUntil: 'networkidle0', - }); - if (index === 0) { - console.log('Dev server started!'); + try { + await page.goto(`http://localhost:4321/api/tankopedia/tank-icon/${id}/`, { + waitUntil: 'networkidle0', + }); + } catch (error) { + console.error(`${id} ${name} time out`, error); + continue; } const screenshot = await page.screenshot({ diff --git a/packages/scripts/src/buildAssets/definitions.ts b/packages/scripts/src/buildAssets/definitions.ts index 917f94b65..8498021e0 100644 --- a/packages/scripts/src/buildAssets/definitions.ts +++ b/packages/scripts/src/buildAssets/definitions.ts @@ -1,5 +1,6 @@ import { Armor, + AssaultRanges, BlitzTankClass, CamouflageDefinitions, Consumable, @@ -274,6 +275,15 @@ interface VehicleDefinitions { pumpGunReloadTimes?: string; clip?: { count: number; rate: number }; models: { undamaged: string }; + extras?: { + trayShell?: { + kinds: string; + sectors: Record< + string, + { id: number; distance: number; factor: number }[] + >; + }; + }; }; }; }; @@ -561,11 +571,6 @@ export async function definitions() { (nations) => nations.filter((nation) => nation !== 'common'), ); const tankStringIdMap: Record = {}; - const stringsCache = await fetch( - 'https://stufficons.wgcdn.co/localizations/en.yaml', - ) - .then((response) => response.text()) - .then((string) => parseYaml(string) as BlitzStrings); const optionalDevices = await readXMLDVPL<{ root: OptionalDevices }>( `${DATA}/XML/item_defs/vehicles/common/optional_devices.xml`, ); @@ -723,39 +728,37 @@ export async function definitions() { const slugRequesters = new Map(); const idToNation: Record = {}; - await Promise.all( - nations.map(async (nation) => { - const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>( - `${DATA}/XML/item_defs/vehicles/${nation}/list.xml`, - ); + for (const nation of nations) { + const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>( + `${DATA}/XML/item_defs/vehicles/${nation}/list.xml`, + ); - for (const tankKey in tankList.root) { - if (botPattern.test(tankKey)) continue; + 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; + const tank = tankList.root[tankKey]; + const tankId = toUniqueId(nation, tank.id); - let slug = deburr(name).toLowerCase(); - slug = slug.replaceAll(nonAlphanumericRegex, '-'); - slug = slug.replaceAll(multipleDashesRegex, '-'); - slug = slug.replaceAll(trailingDashRegex, ''); - slug = slug.replaceAll(leadingDashRegex, ''); + const name = ( + (tank.shortUserString ? getString(tank.shortUserString) : undefined) ?? + getString(tank.userString) + ).locales.en; - idToNation[tankId] = nation; + let slug = deburr(name).toLowerCase(); + slug = slug.replaceAll(nonAlphanumericRegex, '-'); + slug = slug.replaceAll(multipleDashesRegex, '-'); + slug = slug.replaceAll(trailingDashRegex, ''); + slug = slug.replaceAll(leadingDashRegex, ''); - if (slugRequesters.has(slug)) { - slugRequesters.get(slug)!.push({ id: tankId, key: tankKey }); - } else { - slugRequesters.set(slug, [{ id: tankId, key: tankKey }]); - } + 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(); @@ -807,687 +810,706 @@ export async function definitions() { } }); - await Promise.all( - nations.map(async (nation) => { - const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>( - `${DATA}/XML/item_defs/vehicles/${nation}/list.xml`, + for (const nation of nations) { + const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>( + `${DATA}/XML/item_defs/vehicles/${nation}/list.xml`, + ); + const turretList = await readXMLDVPL<{ + root: TurretDefinitionsList; + }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/turrets.xml`); + const gunList = await readXMLDVPL<{ + root: GunDefinitionsList; + }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/guns.xml`); + const shellList = await readXMLDVPL<{ + root: ShellDefinitionsList; + }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/shells.xml`); + const enginesList = await readXMLDVPL<{ + root: EngineDefinitionsList; + }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/engines.xml`); + const chassisList = await readXMLDVPL<{ + root: ChassisDefinitionsList; + }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/chassis.xml`); + + function resolveUnlocks(unlocks?: BlitzModuleType) { + if (!unlocks) return []; + + return Object.entries(unlocks) + .map(([type, list]) => + (Array.isArray(list) ? list : [list]).map((item) => { + const typeTyped = type as keyof BlitzModuleType; + let rawId: number; + + if (typeTyped === 'chassis') { + rawId = chassisList.root.ids[item['#text']]; + } else if (typeTyped === 'engine') { + rawId = enginesList.root.ids[item['#text']]; + } else if (typeTyped === 'gun') { + rawId = gunList.root.ids[item['#text']]; + } else if (typeTyped === 'turret') { + rawId = turretList.root.ids[item['#text']]; + } else if (typeTyped === 'vehicle') { + rawId = tankList.root[item['#text']].id; + } + + return { + id: toUniqueId(nation, rawId!), + type: blitzModuleTypeToBlitzkit[typeTyped], + cost: { + type: + typeof item.cost === 'number' + ? 'xp' + : item.cost.split(':')[0], + value: + typeof item.cost === 'number' + ? item.cost + : Number(item.cost.split(':')[1]), + }, + } satisfies Unlock; + }), + ) + .flat(); + } + + for (const tankKey in tankList.root) { + if (botPattern.test(tankKey)) continue; + + const gunXps = new Map(); + const turretXps = new Map(); + const engineXps = new Map(); + const trackXps = new Map(); + const tank = tankList.root[tankKey]; + let tankPrice: TankPrice; + const tankDefinition = await readXMLDVPL<{ root: VehicleDefinitions }>( + `${DATA}/XML/item_defs/vehicles/${nation}/${tankKey}.xml`, ); - const turretList = await readXMLDVPL<{ - root: TurretDefinitionsList; - }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/turrets.xml`); - const gunList = await readXMLDVPL<{ - root: GunDefinitionsList; - }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/guns.xml`); - const shellList = await readXMLDVPL<{ - root: ShellDefinitionsList; - }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/shells.xml`); - const enginesList = await readXMLDVPL<{ - root: EngineDefinitionsList; - }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/engines.xml`); - const chassisList = await readXMLDVPL<{ - root: ChassisDefinitionsList; - }>(`${DATA}/XML/item_defs/vehicles/${nation}/components/chassis.xml`); + const tankParameters = await readYAMLDVPL( + `${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`, + ); + const turretOrigin = tankDefinition.root.hull.turretPositions.turret + .split(' ') + .map(Number) as Vector3Tuple; + const tankId = toUniqueId(nation, tank.id); - function resolveUnlocks(unlocks?: BlitzModuleType) { - if (!unlocks) return []; + const tankTags = tank.tags.split(' '); + const hullArmor: Armor = { spaced: [], thickness: {} }; + const equipment = tankDefinition.root.optDevicePreset; + tankStringIdMap[`${nation}:${tankKey}`] = tankId; + const slug = slugs.get(tankId); - return Object.entries(unlocks) - .map(([type, list]) => - (Array.isArray(list) ? list : [list]).map((item) => { - const typeTyped = type as keyof BlitzModuleType; - let rawId: number; - - if (typeTyped === 'chassis') { - rawId = chassisList.root.ids[item['#text']]; - } else if (typeTyped === 'engine') { - rawId = enginesList.root.ids[item['#text']]; - } else if (typeTyped === 'gun') { - rawId = gunList.root.ids[item['#text']]; - } else if (typeTyped === 'turret') { - rawId = turretList.root.ids[item['#text']]; - } else if (typeTyped === 'vehicle') { - rawId = tankList.root[item['#text']].id; - } - - return { - id: toUniqueId(nation, rawId!), - type: blitzModuleTypeToBlitzkit[typeTyped], - cost: { - type: - typeof item.cost === 'number' - ? 'xp' - : item.cost.split(':')[0], - value: - typeof item.cost === 'number' - ? item.cost - : Number(item.cost.split(':')[1]), - }, - } satisfies Unlock; - }), - ) - .flat(); + if (slug === undefined) { + throw new Error( + `Could not find slug for ${nation}/${tankKey} (${tankId})`, + ); } - for (const tankKey in tankList.root) { - if (botPattern.test(tankKey)) continue; + if (tank.sellPrice) { + tankPrice = { + type: TankPriceType.GOLD, + value: tank.sellPrice['#text'] * 2, + }; + } else if (typeof tank.price === 'number') { + tankPrice = { + type: TankPriceType.CREDITS, + value: tank.price, + }; + } else { + tankPrice = { + type: TankPriceType.CREDITS, + value: tank.price['#text'] * 400, + }; + } - const gunXps = new Map(); - const turretXps = new Map(); - const engineXps = new Map(); - const trackXps = new Map(); - const tank = tankList.root[tankKey]; - let tankPrice: TankPrice; - const tankDefinition = await readXMLDVPL<{ root: VehicleDefinitions }>( - `${DATA}/XML/item_defs/vehicles/${nation}/${tankKey}.xml`, + Object.keys(tankDefinition.root.hull.armor) + .filter((name) => name.startsWith('armor_')) + .forEach((name) => { + const armorIdString = name.match(/armor_(\d+)/)?.[1]; + + if (armorIdString === undefined) { + throw new SyntaxError(`Invalid armor id: ${name}`); + } + + const armorId = parseInt(armorIdString); + const armorRaw = tankDefinition.root.hull.armor[name]; + + if (typeof armorRaw === 'number') { + hullArmor.thickness[armorId] = armorRaw; + } else { + if (!hullArmor.spaced) hullArmor.spaced = []; + hullArmor.thickness[armorId] = armorRaw['#text']; + hullArmor.spaced.push(armorId); + } + }); + const crew: Crew[] = []; + const fixedCamouflage = tankTags.includes('eventCamouflage_user'); + const totalUnlocks: UnlocksListing[] = []; + + Object.entries(tankDefinition.root.crew).forEach(([crewKey, value]) => { + let entry: Crew; + const index = crew.findIndex( + ({ type }) => blitzkitCrewTypeToBlitz[type] === crewKey, ); - const tankParameters = await readYAMLDVPL( - `${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`, - ); - const turretOrigin = tankDefinition.root.hull.turretPositions.turret + if (index === -1) { + if (crewKey === '#text') return; + entry = { + type: blitzCrewTypeToBlitzkit[crewKey as BlitzCrewType], + count: 0, + substitute: [], + }; + crew.push(entry); + } else { + entry = crew[index]; + } + + if (typeof value === 'string') { + entry.count++; + + if (value !== '') { + entry.substitute = value.split(/\n| /).map((member) => { + return blitzCrewTypeToBlitzkit[member.trim() as BlitzCrewType]; + }); + } + } else { + if (entry.count === undefined) { + entry.count = value.length; + } else { + entry.count += value.length; + } + } + }); + + const camouflages = camouflagesXmlEntries + .filter(([, camo]) => { + if (!camo.vehicleFilter.include) return false; + if (camo.unlockCostCategory !== 'legendary-skins-gold') return false; + + const includeArray = Array.isArray(camo.vehicleFilter.include) + ? camo.vehicleFilter.include + : [camo.vehicleFilter.include]; + + return includeArray.some((filter) => { + if ('vehicle' in filter && filter.vehicle?.name) { + return filter.vehicle.name === `${nation}:${tankKey}`; + } + + return false; + }); + }) + .map(([, camo]) => camo.id); + + tankDefinitions.tanks[tankId] = { + ancestors: [], + successors: [], + id: tankId, + roles: {}, + camouflages: camouflages, + fixed_camouflage: fixedCamouflage, + crew, + weight: tankDefinition.root.hull.weight, + health: tankDefinition.root.hull.maxHealth, + speed_forwards: tankDefinition.root.speedLimits.forward, + speed_backwards: tankDefinition.root.speedLimits.backward, + equipment_preset: + typeof equipment === 'string' ? equipment : equipment.at(-1)!, + max_consumables: tankDefinition.root.consumableSlots, + max_provisions: tankDefinition.root.provisionSlots, + name: + (tank.shortUserString + ? getString(tank.shortUserString) + : undefined) ?? getString(tank.userString), + slug, + nation, + type: tankTags.includes('collectible') + ? TankType.COLLECTOR + : (typeof tank.price === 'number' ? false : 'gold' in tank.price) + ? TankType.PREMIUM + : TankType.RESEARCHABLE, + tier: tank.level, + class: blitzTankClassToBlitzkit[tankTags[0] as BlitzTankClass], + testing: tankTags.includes('testTank'), + deprecated: tankTags.includes('deprecated'), + price: tankPrice, + camouflage_still: tankDefinition.root.invisibility.still, + camouflage_moving: tankDefinition.root.invisibility.moving, + camouflage_onFire: tankDefinition.root.invisibility.firePenalty, + turrets: [], + engines: [], + tracks: [], + }; + + if (tank.combatRole) { + Object.entries(tank.combatRole).forEach(([gameMode, role]) => { + const id = Object.entries(gameModeNativeNames).find( + ([key]) => key.toLowerCase() === gameMode.toLowerCase(), + )?.[1]; + + if (id === undefined) { + throw new Error( + `Unknown game mode in tank ${tankKey}: ${gameMode}`, + ); + } + + tankDefinitions.tanks[tankId].roles[id] = combatRoles[role].id; + }); + } + + modelDefinitions.models[tankId] = { + armor: hullArmor, + turret_origin: vector3TupleToBlitzkit(turretOrigin), + initial_turret_rotation: tankDefinition.root.hull.turretInitialRotation + ? { + yaw: tankDefinition.root.hull.turretInitialRotation.yaw, + pitch: tankDefinition.root.hull.turretInitialRotation.pitch, + roll: tankDefinition.root.hull.turretInitialRotation.roll, + } + : undefined, + bounding_box: { + min: vector3TupleToBlitzkit(tankParameters.collision.hull.bbox.min), + max: vector3TupleToBlitzkit(tankParameters.collision.hull.bbox.max), + }, + turrets: {}, + tracks: {}, + }; + + Object.keys(tankDefinition.root.chassis).forEach((key) => { + const track = tankDefinition.root.chassis[key]; + const trackId = toUniqueId(nation, chassisList.root.ids[key]); + const terrainResistances = track.terrainResistance + .split(' ') + .map(Number); + const trackArmorRaw = track.armor.leftTrack; + const hullOrigin = track.hullPosition .split(' ') .map(Number) as Vector3Tuple; - const tankId = toUniqueId(nation, tank.id); - const tankTags = tank.tags.split(' '); - const hullArmor: Armor = { spaced: [], thickness: {} }; - const equipment = tankDefinition.root.optDevicePreset; - tankStringIdMap[`${nation}:${tankKey}`] = tankId; - const slug = slugs.get(tankId); - if (slug === undefined) { - throw new Error( - `Could not find slug for ${nation}/${tankKey} (${tankId})`, - ); - } - - if (tank.sellPrice) { - tankPrice = { - type: TankPriceType.GOLD, - value: tank.sellPrice['#text'] * 2, - }; - } else if (typeof tank.price === 'number') { - tankPrice = { - type: TankPriceType.CREDITS, - value: tank.price, - }; - } else { - tankPrice = { - type: TankPriceType.CREDITS, - value: tank.price['#text'] * 400, - }; - } - - Object.keys(tankDefinition.root.hull.armor) - .filter((name) => name.startsWith('armor_')) - .forEach((name) => { - const armorIdString = name.match(/armor_(\d+)/)?.[1]; - - if (armorIdString === undefined) { - throw new SyntaxError(`Invalid armor id: ${name}`); - } - - const armorId = parseInt(armorIdString); - const armorRaw = tankDefinition.root.hull.armor[name]; - - if (typeof armorRaw === 'number') { - hullArmor.thickness[armorId] = armorRaw; - } else { - if (!hullArmor.spaced) hullArmor.spaced = []; - hullArmor.thickness[armorId] = armorRaw['#text']; - hullArmor.spaced.push(armorId); - } - }); - const crew: Crew[] = []; - const fixedCamouflage = tankTags.includes('eventCamouflage_user'); - const totalUnlocks: UnlocksListing[] = []; - - Object.entries(tankDefinition.root.crew).forEach(([crewKey, value]) => { - let entry: Crew; - const index = crew.findIndex( - ({ type }) => blitzkitCrewTypeToBlitz[type] === crewKey, - ); - if (index === -1) { - if (crewKey === '#text') return; - entry = { - type: blitzCrewTypeToBlitzkit[crewKey as BlitzCrewType], - count: 0, - substitute: [], - }; - crew.push(entry); - } else { - entry = crew[index]; - } - - if (typeof value === 'string') { - entry.count++; - - if (value !== '') { - entry.substitute = value.split(/\n| /).map((member) => { - return blitzCrewTypeToBlitzkit[member.trim() as BlitzCrewType]; - }); - } - } else { - if (entry.count === undefined) { - entry.count = value.length; - } else { - entry.count += value.length; - } - } + totalUnlocks.push(track.unlocks); + tankDefinitions.tanks[tankId].tracks.push({ + id: trackId, + weight: track.weight, + name: getString(track.userString), + traverse_speed: track.rotationSpeed, + dispersion_move: track.shotDispersionFactors.vehicleMovement, + dispersion_traverse: track.shotDispersionFactors.vehicleRotation, + resistance_hard: terrainResistances[0], + resistance_medium: terrainResistances[1], + resistance_soft: terrainResistances[2], + tier: track.level, + unlocks: resolveUnlocks(track.unlocks), }); - const camouflages = camouflagesXmlEntries - .filter(([, camo]) => { - if (!camo.vehicleFilter.include) return false; - if (camo.unlockCostCategory !== 'legendary-skins-gold') - return false; - - const includeArray = Array.isArray(camo.vehicleFilter.include) - ? camo.vehicleFilter.include - : [camo.vehicleFilter.include]; - - return includeArray.some((filter) => { - if ('vehicle' in filter && filter.vehicle?.name) { - return filter.vehicle.name === `${nation}:${tankKey}`; - } - - return false; - }); - }) - .map(([, camo]) => camo.id); - - tankDefinitions.tanks[tankId] = { - ancestors: [], - successors: [], - id: tankId, - roles: {}, - camouflages: camouflages, - fixed_camouflage: fixedCamouflage, - crew, - weight: tankDefinition.root.hull.weight, - health: tankDefinition.root.hull.maxHealth, - speed_forwards: tankDefinition.root.speedLimits.forward, - speed_backwards: tankDefinition.root.speedLimits.backward, - equipment_preset: - typeof equipment === 'string' ? equipment : equipment.at(-1)!, - max_consumables: tankDefinition.root.consumableSlots, - max_provisions: tankDefinition.root.provisionSlots, - name: - (tank.shortUserString - ? getString(tank.shortUserString) - : undefined) ?? getString(tank.userString), - slug, - nation, - type: tankTags.includes('collectible') - ? TankType.COLLECTOR - : (typeof tank.price === 'number' ? false : 'gold' in tank.price) - ? TankType.PREMIUM - : TankType.RESEARCHABLE, - tier: tank.level, - class: blitzTankClassToBlitzkit[tankTags[0] as BlitzTankClass], - testing: tankTags.includes('testTank'), - deprecated: tankTags.includes('deprecated'), - price: tankPrice, - camouflage_still: tankDefinition.root.invisibility.still, - camouflage_moving: tankDefinition.root.invisibility.moving, - camouflage_onFire: tankDefinition.root.invisibility.firePenalty, - turrets: [], - engines: [], - tracks: [], + modelDefinitions.models[tankId].tracks[trackId] = { + thickness: + typeof trackArmorRaw === 'number' + ? trackArmorRaw + : trackArmorRaw['#text'], + origin: vector3TupleToBlitzkit(hullOrigin), }; + }); - if (tank.combatRole) { - Object.entries(tank.combatRole).forEach(([gameMode, role]) => { - const id = Object.entries(gameModeNativeNames).find( - ([key]) => key.toLowerCase() === gameMode.toLowerCase(), - )?.[1]; + Object.keys(tankDefinition.root.engines).forEach((engineKey) => { + const engine = tankDefinition.root.engines[engineKey]; + const engineListEntry = enginesList.root.shared[engineKey]; + const engineId = toUniqueId(nation, enginesList.root.ids[engineKey]); - if (id === undefined) { - throw new Error( - `Unknown game mode in tank ${tankKey}: ${gameMode}`, - ); - } + totalUnlocks.push(engine.unlocks); + tankDefinitions.tanks[tankId].engines.push({ + id: engineId, + name: getString(engineListEntry.userString), + fire_chance: engineListEntry.fireStartingChance, + tier: engineListEntry.level, + weight: engineListEntry.weight, + power: engineListEntry.power, + unlocks: resolveUnlocks(engine.unlocks), + }); + }); - tankDefinitions.tanks[tankId].roles[id] = combatRoles[role].id; - }); - } - - modelDefinitions.models[tankId] = { - armor: hullArmor, - turret_origin: vector3TupleToBlitzkit(turretOrigin), - initial_turret_rotation: tankDefinition.root.hull - .turretInitialRotation - ? { - yaw: tankDefinition.root.hull.turretInitialRotation.yaw, - pitch: tankDefinition.root.hull.turretInitialRotation.pitch, - roll: tankDefinition.root.hull.turretInitialRotation.roll, - } - : undefined, - bounding_box: { - min: vector3TupleToBlitzkit(tankParameters.collision.hull.bbox.min), - max: vector3TupleToBlitzkit(tankParameters.collision.hull.bbox.max), - }, - turrets: {}, - tracks: {}, - }; - - Object.keys(tankDefinition.root.chassis).forEach((key) => { - const track = tankDefinition.root.chassis[key]; - const trackId = toUniqueId(nation, chassisList.root.ids[key]); - const terrainResistances = track.terrainResistance + Object.keys(tankDefinition.root.turrets0).forEach( + (turretKey, turretIndex) => { + const turret = tankDefinition.root.turrets0[turretKey]; + const turretModel = Number( + parsePath(turret.models.undamaged).name.split('_')[1], + ); + const turretId = toUniqueId(nation, turretList.root.ids[turretKey]); + const turretYaw = ( + typeof turret.yawLimits === 'string' + ? turret.yawLimits + : turret.yawLimits.at(-1)! + ) .split(' ') - .map(Number); - const trackArmorRaw = track.armor.leftTrack; - const hullOrigin = track.hullPosition + .map(Number) as [number, number]; + const gunOrigin = ( + typeof turret.gunPosition === 'string' + ? turret.gunPosition + : turret.gunPosition[0] + ) .split(' ') .map(Number) as Vector3Tuple; + const turretArmor: Armor = { thickness: {}, spaced: [] }; - totalUnlocks.push(track.unlocks); - tankDefinitions.tanks[tankId].tracks.push({ - id: trackId, - weight: track.weight, - name: getString(track.userString), - traverse_speed: track.rotationSpeed, - dispersion_move: track.shotDispersionFactors.vehicleMovement, - dispersion_traverse: track.shotDispersionFactors.vehicleRotation, - resistance_hard: terrainResistances[0], - resistance_medium: terrainResistances[1], - resistance_soft: terrainResistances[2], - tier: track.level, - unlocks: resolveUnlocks(track.unlocks), + totalUnlocks.push(turret.unlocks); + Object.keys(turret.armor) + .filter((name) => name.startsWith('armor_')) + .forEach((name) => { + const armorIdString = name.match(/armor_(\d+)/)?.[1]; + + if (armorIdString === undefined) { + throw new SyntaxError(`Invalid armor id: ${name}`); + } + + const armorId = parseInt(armorIdString); + const armorRaw = turret.armor[name]; + + if (typeof armorRaw === 'number') { + turretArmor.thickness[armorId] = armorRaw; + } else { + if (!turretArmor.spaced) turretArmor.spaced = []; + turretArmor.thickness[armorId] = armorRaw['#text']; + turretArmor.spaced.push(armorId); + } + }); + + turret.userString; + + tankDefinitions.tanks[tankId].turrets.push({ + id: turretId, + traverse_speed: turret.rotationSpeed, + name: getString(turret.userString), + tier: turret.level, + guns: [], + health: turret.maxHealth, + view_range: turret.circularVisionRadius, + weight: turret.weight, + unlocks: resolveUnlocks(turret.unlocks), }); - modelDefinitions.models[tankId].tracks[trackId] = { - thickness: - typeof trackArmorRaw === 'number' - ? trackArmorRaw - : trackArmorRaw['#text'], - origin: vector3TupleToBlitzkit(hullOrigin), + modelDefinitions.models[tankId].turrets[turretId] = { + armor: turretArmor, + gun_origin: vector3TupleToBlitzkit(gunOrigin), + model_id: turretModel, + yaw: + -turretYaw[0] + turretYaw[1] === 360 + ? undefined + : { min: turretYaw[0], max: turretYaw[1] }, + guns: {}, + bounding_box: { + min: vector3TupleToBlitzkit( + tankParameters.collision[ + parsePath(turret.hitTester.collisionModel).name.toLowerCase() + ].bbox.min, + ), + max: vector3TupleToBlitzkit( + tankParameters.collision[ + parsePath(turret.hitTester.collisionModel).name.toLowerCase() + ].bbox.max, + ), + }, }; - }); - Object.keys(tankDefinition.root.engines).forEach((engineKey) => { - const engine = tankDefinition.root.engines[engineKey]; - const engineListEntry = enginesList.root.shared[engineKey]; - const engineId = toUniqueId(nation, enginesList.root.ids[engineKey]); - - totalUnlocks.push(engine.unlocks); - tankDefinitions.tanks[tankId].engines.push({ - id: engineId, - name: getString(engineListEntry.userString), - fire_chance: engineListEntry.fireStartingChance, - tier: engineListEntry.level, - weight: engineListEntry.weight, - power: engineListEntry.power, - unlocks: resolveUnlocks(engine.unlocks), - }); - }); - - Object.keys(tankDefinition.root.turrets0).forEach( - (turretKey, turretIndex) => { - const turret = tankDefinition.root.turrets0[turretKey]; - const turretModel = Number( - parsePath(turret.models.undamaged).name.split('_')[1], - ); - const turretId = toUniqueId(nation, turretList.root.ids[turretKey]); - const turretYaw = ( - typeof turret.yawLimits === 'string' - ? turret.yawLimits - : turret.yawLimits.at(-1)! + Object.keys(turret.guns).forEach((gunKey, gunIndex) => { + const gun = turret.guns[gunKey]; + const gunId = toUniqueId(nation, gunList.root.ids[gunKey]); + const gunListEntry = gunList.root.shared[gunKey]; + const pitchLimitsRaw = gun.pitchLimits ?? gunListEntry.pitchLimits; + const gunPitch = ( + typeof pitchLimitsRaw === 'string' + ? pitchLimitsRaw + : pitchLimitsRaw.at(-1)! ) .split(' ') .map(Number) as [number, number]; - const gunOrigin = ( - typeof turret.gunPosition === 'string' - ? turret.gunPosition - : turret.gunPosition[0] - ) - .split(' ') - .map(Number) as Vector3Tuple; - const turretArmor: Armor = { thickness: {}, spaced: [] }; + const gunModel = Number( + parsePath(gun.models.undamaged).name.split('_')[1], + ); + const gunName = getString(gunListEntry.userString); + const gunType = + 'clip' in gun + ? gun.pumpGunMode + ? 'autoReloader' + : 'autoLoader' + : 'regular'; + // 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; + const back = gun.extraPitchLimits?.back + ? gun.extraPitchLimits.back.split(' ').map(Number) + : undefined; + const transition = gun.extraPitchLimits?.transition + ? typeof gun.extraPitchLimits.transition === 'number' + ? gun.extraPitchLimits.transition + : gun.extraPitchLimits.transition.at(-1)! + : undefined; + const gunArmor: Armor = { thickness: {}, spaced: [] }; + const shotDispersionFactors = + gun.shotDispersionFactors ?? gunListEntry.shotDispersionFactors; + const maskName = `gun_${gunModel.toString().padStart(2, '0')}`; + const maskEnabled = + tankParameters.maskSlice?.[maskName]?.enabled ?? false; + let mask: number | undefined; + let assault_ranges: AssaultRanges | undefined; - totalUnlocks.push(turret.unlocks); - Object.keys(turret.armor) + if (gun.extras?.trayShell) { + const types = gun.extras.trayShell.kinds + .split(' ') + .map((string) => { + const trimmed = string.trim(); + + if (trimmed in blitzShellKindToBlitzkit) { + return blitzShellKindToBlitzkit[trimmed as ShellKind]; + } + + throw new SyntaxError(`Invalid shell kind: ${trimmed}`); + }); + const sectorNames = Object.keys(gun.extras.trayShell.sectors); + + if (sectorNames.length !== 1 || sectorNames[0] !== 'sector') { + throw new SyntaxError('Invalid tray shell sector'); + } + + const sector = gun.extras.trayShell.sectors.sector; + + assault_ranges = { + types, + ranges: sector.map((value) => ({ + factor: value.factor, + distance: value.distance, + })), + }; + } + + if (maskEnabled) { + const maskRaw = tankParameters.maskSlice![maskName]!; + mask = maskRaw.planePosition[1]; + } else { + mask = undefined; + } + + totalUnlocks.push(gun.unlocks); + Object.keys(gun.armor) .filter((name) => name.startsWith('armor_')) .forEach((name) => { const armorIdString = name.match(/armor_(\d+)/)?.[1]; - if (armorIdString === undefined) { throw new SyntaxError(`Invalid armor id: ${name}`); } - const armorId = parseInt(armorIdString); - const armorRaw = turret.armor[name]; - + const armorRaw = gun.armor[name]; if (typeof armorRaw === 'number') { - turretArmor.thickness[armorId] = armorRaw; + gunArmor.thickness[armorId] = armorRaw; } else { - if (!turretArmor.spaced) turretArmor.spaced = []; - turretArmor.thickness[armorId] = armorRaw['#text']; - turretArmor.spaced.push(armorId); + if (!gunArmor.spaced) gunArmor.spaced = []; + gunArmor.thickness[armorId] = armorRaw['#text']; + gunArmor.spaced.push(armorId); } }); - turret.userString; + const base = { + id: gunId, + weight: gunListEntry.weight, + rotation_speed: gunListEntry.rotationSpeed, + name: gunName, + tier: gunListEntry.level, + shells: [], + camouflage_loss: + typeof gun.invisibilityFactorAtShot === 'number' + ? gun.invisibilityFactorAtShot + : gun.invisibilityFactorAtShot.at(-1)!, + aim_time: gun.aimingTime ?? gunListEntry.aimingTime, + dispersion_base: + gun.shotDispersionRadius ?? gunListEntry.shotDispersionRadius, + dispersion_damaged: shotDispersionFactors.whileGunDamaged, + dispersion_shot: shotDispersionFactors.afterShot, + dispersion_traverse: shotDispersionFactors.turretRotation, + unlocks: resolveUnlocks(gun.unlocks), + shell_capacity: gun.maxAmmo ?? gunListEntry.maxAmmo, + assault_ranges, + } satisfies GunDefinitionBase; - tankDefinitions.tanks[tankId].turrets.push({ - id: turretId, - traverse_speed: turret.rotationSpeed, - name: getString(turret.userString), - tier: turret.level, - guns: [], - health: turret.maxHealth, - view_range: turret.circularVisionRadius, - weight: turret.weight, - unlocks: resolveUnlocks(turret.unlocks), - }); + tankDefinitions.tanks[tankId].turrets[turretIndex].guns.push({ + gun_type: + gunType === 'regular' + ? { + $case: 'regular', + value: { + base, + extension: { reload: gun.reloadTime }, + }, + } + : gunType === 'autoReloader' + ? { + $case: 'auto_reloader', + value: { + base, + extension: { + intra_clip: 60 / gun.clip!.rate, + shell_count: gunClipCount, + shell_reloads: gun + .pumpGunReloadTimes!.split(' ') + .map(Number), + }, + }, + } + : { + $case: 'auto_loader', + value: { + base, + extension: { + intra_clip: 60 / gun.clip!.rate, + clip_reload: gun.reloadTime, + shell_count: gunClipCount, + }, + }, + }, + } satisfies GunDefinition); - modelDefinitions.models[tankId].turrets[turretId] = { - armor: turretArmor, - gun_origin: vector3TupleToBlitzkit(gunOrigin), - model_id: turretModel, - yaw: - -turretYaw[0] + turretYaw[1] === 360 - ? undefined - : { min: turretYaw[0], max: turretYaw[1] }, - guns: {}, - bounding_box: { - min: vector3TupleToBlitzkit( - tankParameters.collision[ - parsePath( - turret.hitTester.collisionModel, - ).name.toLowerCase() - ].bbox.min, - ), - max: vector3TupleToBlitzkit( - tankParameters.collision[ - parsePath( - turret.hitTester.collisionModel, - ).name.toLowerCase() - ].bbox.max, - ), + modelDefinitions.models[tankId].turrets[turretId].guns[gunId] = { + armor: gunArmor, + model_id: gunModel, + mask, + thickness: + gun.armor.gun === undefined + ? 0 + : typeof gun.armor.gun === 'number' + ? gun.armor.gun + : gun.armor.gun['#text'], + pitch: { + min: gunPitch[0], + max: gunPitch[1], + + front: front + ? { + min: front[0], + max: front[1], + range: front[2], + } + : undefined, + back: back + ? { + min: back[0], + max: back[1], + range: back[2], + } + : undefined, + transition, }, }; - Object.keys(turret.guns).forEach((gunKey, gunIndex) => { - const gun = turret.guns[gunKey]; - const gunId = toUniqueId(nation, gunList.root.ids[gunKey]); - const gunListEntry = gunList.root.shared[gunKey]; - const pitchLimitsRaw = - gun.pitchLimits ?? gunListEntry.pitchLimits; - const gunPitch = ( - typeof pitchLimitsRaw === 'string' - ? pitchLimitsRaw - : pitchLimitsRaw.at(-1)! - ) + Object.keys(gunListEntry.shots).forEach((shellKey) => { + const gunShellEntry = gunListEntry.shots[shellKey]; + const shell = shellList.root[shellKey]; + const shellId = toUniqueId(nation, shell.id); + const shellName = getString(shell.userString); + const penetrationRaw = gunShellEntry.piercingPower .split(' ') - .map(Number) as [number, number]; - const gunModel = Number( - parsePath(gun.models.undamaged).name.split('_')[1], - ); - const gunName = getString(gunListEntry.userString); - const gunType = - 'clip' in gun - ? gun.pumpGunMode - ? 'autoReloader' - : 'autoLoader' - : 'regular'; - // 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; - const back = gun.extraPitchLimits?.back - ? gun.extraPitchLimits.back.split(' ').map(Number) - : undefined; - const transition = gun.extraPitchLimits?.transition - ? typeof gun.extraPitchLimits.transition === 'number' - ? gun.extraPitchLimits.transition - : gun.extraPitchLimits.transition.at(-1)! - : undefined; - const gunArmor: Armor = { thickness: {}, spaced: [] }; - const shotDispersionFactors = - gun.shotDispersionFactors ?? gunListEntry.shotDispersionFactors; - const maskName = `gun_${gunModel.toString().padStart(2, '0')}`; - const maskEnabled = - tankParameters.maskSlice?.[maskName]?.enabled ?? false; - let mask: number | undefined; + .filter((penetrationString) => penetrationString !== '') + .map(Number); - if (maskEnabled) { - const maskRaw = tankParameters.maskSlice![maskName]!; - mask = maskRaw.planePosition[1]; - } else { - mask = undefined; - } - - totalUnlocks.push(gun.unlocks); - Object.keys(gun.armor) - .filter((name) => name.startsWith('armor_')) - .forEach((name) => { - const armorIdString = name.match(/armor_(\d+)/)?.[1]; - if (armorIdString === undefined) { - throw new SyntaxError(`Invalid armor id: ${name}`); - } - const armorId = parseInt(armorIdString); - const armorRaw = gun.armor[name]; - if (typeof armorRaw === 'number') { - gunArmor.thickness[armorId] = armorRaw; - } else { - if (!gunArmor.spaced) gunArmor.spaced = []; - gunArmor.thickness[armorId] = armorRaw['#text']; - gunArmor.spaced.push(armorId); - } - }); - - const base = { - id: gunId, - weight: gunListEntry.weight, - rotation_speed: gunListEntry.rotationSpeed, - name: gunName, - tier: gunListEntry.level, - shells: [], - camouflage_loss: - typeof gun.invisibilityFactorAtShot === 'number' - ? gun.invisibilityFactorAtShot - : gun.invisibilityFactorAtShot.at(-1)!, - aim_time: gun.aimingTime ?? gunListEntry.aimingTime, - dispersion_base: - gun.shotDispersionRadius ?? gunListEntry.shotDispersionRadius, - dispersion_damaged: shotDispersionFactors.whileGunDamaged, - dispersion_shot: shotDispersionFactors.afterShot, - dispersion_traverse: shotDispersionFactors.turretRotation, - unlocks: resolveUnlocks(gun.unlocks), - shell_capacity: gun.maxAmmo ?? gunListEntry.maxAmmo, - } satisfies GunDefinitionBase; - - tankDefinitions.tanks[tankId].turrets[turretIndex].guns.push({ - gun_type: - gunType === 'regular' - ? { - $case: 'regular', - value: { - base, - extension: { reload: gun.reloadTime }, - }, - } - : gunType === 'autoReloader' - ? { - $case: 'auto_reloader', - value: { - base, - extension: { - intra_clip: 60 / gun.clip!.rate, - shell_count: gunClipCount, - shell_reloads: gun - .pumpGunReloadTimes!.split(' ') - .map(Number), - }, - }, - } - : { - $case: 'auto_loader', - value: { - base, - extension: { - intra_clip: 60 / gun.clip!.rate, - clip_reload: gun.reloadTime, - shell_count: gunClipCount, - }, - }, - }, - } satisfies GunDefinition); - - modelDefinitions.models[tankId].turrets[turretId].guns[gunId] = { - armor: gunArmor, - model_id: gunModel, - mask, - thickness: - gun.armor.gun === undefined - ? 0 - : typeof gun.armor.gun === 'number' - ? gun.armor.gun - : gun.armor.gun['#text'], - pitch: { - min: gunPitch[0], - max: gunPitch[1], - - front: front - ? { - min: front[0], - max: front[1], - range: front[2], - } + tankDefinitions.tanks[tankId].turrets[turretIndex].guns[ + gunIndex + ].gun_type!.value.base!.shells.push({ + id: shellId, + name: shellName, + velocity: gunShellEntry.speed, + armor_damage: shell.damage.armor, + module_damage: shell.damage.devices, + caliber: shell.caliber, + normalization: shell.normalizationAngle, + ricochet: shell.ricochetAngle, + type: blitzShellKindToBlitzkit[shell.kind], + explosion_radius: + shell.kind === 'HIGH_EXPLOSIVE' + ? (shell.explosionRadius ?? 0) : undefined, - back: back - ? { - min: back[0], - max: back[1], - range: back[2], - } - : undefined, - transition, + icon: shell.icon, + penetration: { + near: penetrationRaw[0], + far: penetrationRaw[1], }, - }; - - Object.keys(gunListEntry.shots).forEach((shellKey) => { - const gunShellEntry = gunListEntry.shots[shellKey]; - const shell = shellList.root[shellKey]; - const shellId = toUniqueId(nation, shell.id); - const shellName = getString(shell.userString); - const penetrationRaw = gunShellEntry.piercingPower - .split(' ') - .filter((penetrationString) => penetrationString !== '') - .map(Number); - - tankDefinitions.tanks[tankId].turrets[turretIndex].guns[ - gunIndex - ].gun_type!.value.base.shells.push({ - id: shellId, - name: shellName, - velocity: gunShellEntry.speed, - armor_damage: shell.damage.armor, - module_damage: shell.damage.devices, - caliber: shell.caliber, - normalization: shell.normalizationAngle, - ricochet: shell.ricochetAngle, - type: blitzShellKindToBlitzkit[shell.kind], - explosion_radius: - shell.kind === 'HIGH_EXPLOSIVE' - ? (shell.explosionRadius ?? 0) - : undefined, - icon: shell.icon, - penetration: { - near: penetrationRaw[0], - far: penetrationRaw[1], - }, - range: gunShellEntry.maxDistance, - }); + range: gunShellEntry.maxDistance, }); }); - }, - ); + }); + }, + ); - totalUnlocks.forEach((unlocks) => { - if (unlocks === undefined) return; + totalUnlocks.forEach((unlocks) => { + if (unlocks === undefined) return; - Object.entries(unlocks).forEach(([key, value]) => { - (Array.isArray(value) ? value : [value]).forEach((vehicle) => { - switch (key as keyof BlitzModuleType) { - case 'vehicle': { - const tankListEntry = tankList.root[vehicle['#text']]; - const currentTank = tankDefinitions.tanks[tankId]; - const successorId = toUniqueId(nation, tankListEntry.id); + Object.entries(unlocks).forEach(([key, value]) => { + (Array.isArray(value) ? value : [value]).forEach((vehicle) => { + switch (key as keyof BlitzModuleType) { + case 'vehicle': { + const tankListEntry = tankList.root[vehicle['#text']]; + const currentTank = tankDefinitions.tanks[tankId]; + const successorId = toUniqueId(nation, tankListEntry.id); - tankXps.set(successorId, parseResearchCost(vehicle.cost)); + tankXps.set(successorId, parseResearchCost(vehicle.cost)); - if (currentTank.successors === undefined) { - currentTank.successors = []; - } - if (!currentTank.successors!.includes(successorId)) { - currentTank.successors!.push(successorId); - } - break; + if (currentTank.successors === undefined) { + currentTank.successors = []; } - - case 'gun': { - gunXps.set( - toUniqueId(nation, gunList.root.ids[vehicle['#text']]), - parseResearchCost(vehicle.cost), - ); - break; - } - - case 'turret': { - turretXps.set( - toUniqueId(nation, turretList.root.ids[vehicle['#text']]), - parseResearchCost(vehicle.cost), - ); - break; - } - - case 'engine': { - engineXps.set( - toUniqueId(nation, enginesList.root.ids[vehicle['#text']]), - parseResearchCost(vehicle.cost), - ); - break; - } - - case 'chassis': { - trackXps.set( - toUniqueId(nation, chassisList.root.ids[vehicle['#text']]), - parseResearchCost(vehicle.cost), - ); - break; + if (!currentTank.successors!.includes(successorId)) { + currentTank.successors!.push(successorId); } + break; } - }); + + case 'gun': { + gunXps.set( + toUniqueId(nation, gunList.root.ids[vehicle['#text']]), + parseResearchCost(vehicle.cost), + ); + break; + } + + case 'turret': { + turretXps.set( + toUniqueId(nation, turretList.root.ids[vehicle['#text']]), + parseResearchCost(vehicle.cost), + ); + break; + } + + case 'engine': { + engineXps.set( + toUniqueId(nation, enginesList.root.ids[vehicle['#text']]), + parseResearchCost(vehicle.cost), + ); + break; + } + + case 'chassis': { + trackXps.set( + toUniqueId(nation, chassisList.root.ids[vehicle['#text']]), + parseResearchCost(vehicle.cost), + ); + break; + } + } }); }); + }); - Object.values(tankDefinitions.tanks[tankId].turrets).forEach( - (turret) => { - turret.research_cost = turretXps.get(turret.id); + Object.values(tankDefinitions.tanks[tankId].turrets).forEach((turret) => { + turret.research_cost = turretXps.get(turret.id); - Object.values(turret.guns).forEach((gunRaw) => { - gunRaw.gun_type!.value.base.research_cost = gunXps.get( - gunRaw.gun_type!.value.base.id, - ); - }); - }, - ); - - Object.values(tankDefinitions.tanks[tankId].engines).forEach( - (engine) => { - engine.research_cost = engineXps.get(engine.id); - }, - ); - - Object.values(tankDefinitions.tanks[tankId].tracks).forEach((track) => { - track.research_cost = trackXps.get(track.id); + Object.values(turret.guns).forEach((gunRaw) => { + gunRaw.gun_type!.value.base!.research_cost = gunXps.get( + gunRaw.gun_type!.value.base!.id, + ); }); - } - }), - ); + }); + + Object.values(tankDefinitions.tanks[tankId].engines).forEach((engine) => { + engine.research_cost = engineXps.get(engine.id); + }); + + Object.values(tankDefinitions.tanks[tankId].tracks).forEach((track) => { + track.research_cost = trackXps.get(track.id); + }); + } + } Object.values(tankDefinitions.tanks).forEach((tank) => { tank.research_cost = tankXps.get(tank.id); diff --git a/packages/scripts/src/buildAssets/index.ts b/packages/scripts/src/buildAssets/index.ts index 51483a711..dac11ccf7 100644 --- a/packages/scripts/src/buildAssets/index.ts +++ b/packages/scripts/src/buildAssets/index.ts @@ -21,7 +21,6 @@ import { gameModeBanners } from './gameModeBanners'; import { glossary } from './glossary'; import { migration } from './migration'; import { moduleIcons } from './moduleIcons'; -import { popularTanks } from './popularTanks'; import { shellIcons } from './shellIcons'; import { skillIcons } from './skillIcons'; import { tankArmors } from './tankArmors'; @@ -47,7 +46,7 @@ const methods = [ boosterIcons, tankIcons, blitzkitTankIcons, - popularTanks, + // popularTanks, glossary, ]; diff --git a/packages/scripts/src/buildAssets/tankModels.ts b/packages/scripts/src/buildAssets/tankModels.ts index 95901857a..5a5895ca2 100644 --- a/packages/scripts/src/buildAssets/tankModels.ts +++ b/packages/scripts/src/buildAssets/tankModels.ts @@ -32,9 +32,6 @@ export async function tankModels() { if (tankKey.includes('tutorial_bot')) continue; const id = toUniqueId(nation, tank.id); - - if (id !== 21777) continue; - const parameters = await readYAMLDVPL( `${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`, ); @@ -43,8 +40,6 @@ export async function tankModels() { parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, ''), ); - await writeFile('../../temp/model.glb', await nodeIO.writeBinary(model)); - changes.push({ path: `3d/tanks/models/${id}.glb`, content: Buffer.from(await nodeIO.writeBinary(model)), diff --git a/packages/scripts/src/core/github/commitMultipleFiles.ts b/packages/scripts/src/core/github/commitMultipleFiles.ts index 2b9804671..50655485b 100644 --- a/packages/scripts/src/core/github/commitMultipleFiles.ts +++ b/packages/scripts/src/core/github/commitMultipleFiles.ts @@ -73,12 +73,13 @@ export async function commitMultipleFiles( } if (diff.status === DiffStatus.Unchanged) { - console.log(`๐Ÿ”ต (${diff.change.toLocaleString()}B) ${change.path}`); + // just don't bother + // console.log(`๐Ÿ”ต (${diff.change.toLocaleString()}B) ${change.path}`); } else { console.log( `${ diff.status === DiffStatus.New ? '๐ŸŸข' : '๐ŸŸก' - } (+${diff.change.toLocaleString()}B) ${change.path}`, + } (${diff.change > 0 ? '+' : ''}${diff.change.toLocaleString()}B) ${change.path}`, ); changes.push(change); } diff --git a/packages/website/astro.config.mjs b/packages/website/astro.config.mjs index 45bd1c5dc..3b002a848 100644 --- a/packages/website/astro.config.mjs +++ b/packages/website/astro.config.mjs @@ -1,6 +1,5 @@ // @ts-check -import partytown from '@astrojs/partytown'; import react from '@astrojs/react'; import sitemap from '@astrojs/sitemap'; import { SUPPORTED_LOCALES } from '@blitzkit/i18n'; @@ -21,7 +20,7 @@ export default defineConfig({ outDir: '../../dist/website', prefetch: true, - integrations: [react(), sitemap(), partytown()], + integrations: [react(), sitemap()], vite: { resolve: { alias: { diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl index 916e480ec..1d7493a79 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/fragment.glsl @@ -1,3 +1,5 @@ +precision mediump float; + #define USE_FOG #include diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/vertex.glsl b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/vertex.glsl index d80ba8239..2c0140061 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/vertex.glsl +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/shaders/vertex.glsl @@ -1,3 +1,5 @@ +precision mediump float; + #define USE_FOG #include diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/shaders/fragment.glsl b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/shaders/fragment.glsl index ca6251f89..5d3ededb1 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/shaders/fragment.glsl +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/shaders/fragment.glsl @@ -1,3 +1,5 @@ +precision mediump float; + uniform float thickness; uniform float penetration; diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/shaders/vertex.glsl b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/shaders/vertex.glsl index 43b37bc3c..0c9b82ba3 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/shaders/vertex.glsl +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/shaders/vertex.glsl @@ -1,3 +1,5 @@ +precision mediump float; + #include void main() { diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/shaders/fragment.glsl b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/shaders/fragment.glsl index 7d486d5e8..6fafe53d1 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/shaders/fragment.glsl +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/shaders/fragment.glsl @@ -1,3 +1,5 @@ +precision mediump float; + varying vec3 vNormal; varying vec3 vViewPosition; diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/shaders/vertex.glsl b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/shaders/vertex.glsl index 82f94e255..459297160 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/shaders/vertex.glsl +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/shaders/vertex.glsl @@ -1,3 +1,5 @@ +precision mediump float; + varying vec3 vNormal; varying vec3 vViewPosition; diff --git a/packages/website/src/components/Compare/Body.tsx b/packages/website/src/components/Compare/Body.tsx index b4c0afd57..5cdfbd6a8 100644 --- a/packages/website/src/components/Compare/Body.tsx +++ b/packages/website/src/components/Compare/Body.tsx @@ -79,6 +79,12 @@ export function Body({ stats }: BodyProps) { + + {hasNonRegularGun && ( + + )} + + )} - - - {hasNonRegularGun && ( - - )} - - - + + BlitzKit { PUBLIC_ASSET_BRANCH !== 'preview' && ( @@ -140,7 +140,7 @@ const strings = getStrings(locale); CDN - + {packageJson.version} diff --git a/packages/website/src/components/Navbar.astro b/packages/website/src/components/Navbar.astro index 4074100fc..90d0b9a3b 100644 --- a/packages/website/src/components/Navbar.astro +++ b/packages/website/src/components/Navbar.astro @@ -17,7 +17,7 @@ export interface Props { integrated?: boolean; } -const { integrated } = Astro.props; +const { integrated = false } = Astro.props; const toolsFiltered = TOOLS.filter((tool) => !('href' in tool)); const { locale } = Astro.params; const branchName = resolveBranchName(locale); @@ -47,7 +47,7 @@ const strings = getStrings(locale); height: 100%; } - .navbar[data-expanded='false'] .content { + .navbar[data-expanded='false'][data-integrated='false'] .content { background-color: var(--black-a8); backdrop-filter: blur(4rem); box-shadow: var(--shadow-3); @@ -87,6 +87,7 @@ const strings = getStrings(locale); direction="column" align="center" data-expanded="false" + data-integrated={`${integrated}`} className="navbar" width="100%" top="0" @@ -232,7 +233,7 @@ const strings = getStrings(locale); - - -{/* nitro ads */} -{ - /* - -*/ -} diff --git a/packages/website/src/components/TankCard/index.tsx b/packages/website/src/components/TankCard/index.tsx index a0b366f82..ae508629a 100644 --- a/packages/website/src/components/TankCard/index.tsx +++ b/packages/website/src/components/TankCard/index.tsx @@ -80,7 +80,7 @@ export const TankCard = forwardRef( > {unwrap(tank.name)} diff --git a/packages/website/src/components/TankSearch/components/Card.tsx b/packages/website/src/components/TankSearch/components/Card.tsx index f5531692a..34d9234ec 100644 --- a/packages/website/src/components/TankSearch/components/Card.tsx +++ b/packages/website/src/components/TankSearch/components/Card.tsx @@ -27,6 +27,7 @@ export function TankSearchCard({ tank, onSelect }: TankSearchCardProps) { const gun = turret.guns.at(-1)!; const shell0 = gun.gun_type!.value.base.shells[0]; const shell1 = gun.gun_type!.value.base.shells[1]; + const shell2 = gun.gun_type!.value.base.shells[2]; const tracks = tank.tracks.at(-1)!; const engine = tank.engines.at(-1)!; const tankModelDefinition = modelDefinitions.models[tank.id]; @@ -57,6 +58,8 @@ export function TankSearchCard({ tank, onSelect }: TankSearchCardProps) { return shell0.penetration.near.toFixed(0); case 'fire.premiumPenetration': return shell1 ? shell1.penetration.near.toFixed(0) : '--'; + case 'fire.tertiaryPenetration': + return shell1 ? shell2.penetration.near.toFixed(0) : '--'; case 'fire.shellVelocity': return shell0.velocity.toFixed(0); case 'fire.shellCapacity': diff --git a/packages/website/src/components/TankSearch/components/FilterControl.tsx b/packages/website/src/components/TankSearch/components/FilterControl.tsx index 189c3893f..66cfce18d 100644 --- a/packages/website/src/components/TankSearch/components/FilterControl.tsx +++ b/packages/website/src/components/TankSearch/components/FilterControl.tsx @@ -84,6 +84,7 @@ function ShellFilter({ index, premium }: { index: number; premium?: boolean }) { return ( (null); const performSearch = useCallback( debounce(() => { - // tankFiltersStore.setState({ searching: false }); $tankFilters.setKey('searching', false); if (!input.current) return; const sanitized = input.current.value.trim(); - // tankFiltersStore.setState({ - // search: sanitized.length === 0 ? undefined : sanitized, - // }); - $tankFilters.setKey( - 'search', - sanitized.length === 0 ? undefined : sanitized, - ); + $tankFilters.setKey('search', sanitized.length === 0 ? null : sanitized); }, 500), [], ); const handleChange = useCallback(() => { - // if (!tankFiltersStore.getState().searching) { - // tankFiltersStore.setState({ searching: true }); - // } if (!tankFilters.searching) { $tankFilters.setKey('searching', true); } @@ -69,7 +59,7 @@ export function SearchBar({ topResult, skeleton, onSelect }: SearchBarProps) { + diff --git a/packages/website/src/components/TankSearch/index.tsx b/packages/website/src/components/TankSearch/index.tsx index 0d03cc671..58559fe76 100644 --- a/packages/website/src/components/TankSearch/index.tsx +++ b/packages/website/src/components/TankSearch/index.tsx @@ -60,7 +60,7 @@ export const TankSearch = memo( const tankFilters = useStore($tankFilters); const tankopediaSort = useStore($tankopediaSort); const tanksFiltered = useMemo(() => { - if (tankFilters.search === undefined) { + if (tankFilters.search === null) { const filtered = awaitedTanksDefinitionsArray.filter((tank) => filterTank(tankFilters, tank), ); @@ -238,6 +238,16 @@ export const TankSearch = memo( ); break; + case 'fire.tertiaryPenetration': + sorted = filtered.sort( + (a, b) => + (a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[2] + ?.penetration.near ?? 0) - + (b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[2] + ?.penetration.near ?? 0), + ); + break; + case 'fire.damage': sorted = filtered.sort( (a, b) => diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/components/Cursor/index.css b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/components/Cursor/index.css new file mode 100644 index 000000000..bf7e4950c --- /dev/null +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/components/Cursor/index.css @@ -0,0 +1,7 @@ +#assault-cursor { + cursor: grab; +} + +#assault-cursor:active { + cursor: grabbing; +} diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/components/Cursor/index.tsx b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/components/Cursor/index.tsx new file mode 100644 index 000000000..2e6f62f82 --- /dev/null +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/components/Cursor/index.tsx @@ -0,0 +1,123 @@ +import { DragHandleDots2Icon } from '@radix-ui/react-icons'; +import { Box, Flex, Text } from '@radix-ui/themes'; +import { useEffect, useRef, useState } from 'react'; +import { clamp } from 'three/src/math/MathUtils.js'; +import { + fakeLogSquishyHigh, + fakeLogSquishyHighInverse, +} from '../../../../../../../../../core/blitzkit/fakeLog'; +import { Var } from '../../../../../../../../../core/radix/var'; +import { Duel } from '../../../../../../../../../stores/duel'; +import './index.css'; + +interface Props { + maxDistance: number; + maxFakeDistance: number; +} + +export function AssaultCursor({ maxDistance, maxFakeDistance }: Props) { + const assaultDistance = Duel.use( + (state) => state.protagonist.assaultDistance, + ); + const [x, setX] = useState(fakeLogSquishyHigh(assaultDistance / maxDistance)); + const cursor = useRef(null); + const mutateDuel = Duel.useMutation(); + + useEffect(() => { + let localX = x; + let lastX = 0; + + function handlePointerDown(event: PointerEvent) { + event.preventDefault(); + + lastX = event.clientX; + + window.addEventListener('pointermove', handlePointerMove); + window.addEventListener('pointerup', handlePointerUp); + } + + function handlePointerMove(event: PointerEvent) { + event.preventDefault(); + + const parent = cursor.current?.parentElement; + + if (!parent) return; + + const width = parent.clientWidth; + const movementX = event.clientX - lastX; + lastX = event.clientX; + + setX((state) => { + localX = clamp(state + movementX / width, 0, 1); + return localX; + }); + } + + function handlePointerUp() { + mutateDuel((draft) => { + draft.protagonist.assaultDistance = + fakeLogSquishyHighInverse(localX * maxFakeDistance) * maxDistance; + }); + + window.removeEventListener('pointermove', handlePointerMove); + window.removeEventListener('pointerup', handlePointerUp); + } + + cursor.current?.addEventListener('pointerdown', handlePointerDown); + + return () => { + cursor.current?.removeEventListener('pointerdown', handlePointerDown); + window.removeEventListener('pointermove', handlePointerMove); + window.removeEventListener('pointerup', handlePointerUp); + }; + }, []); + + return ( + + + + + + + + + + + + ); +} diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/index.tsx b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/index.tsx new file mode 100644 index 000000000..cdd089725 --- /dev/null +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/AssaultRangesVisualizer/index.tsx @@ -0,0 +1,157 @@ +import type { AssaultRanges } from '@blitzkit/core'; +import { literals } from '@blitzkit/i18n'; +import { Box, Card, Flex, Text } from '@radix-ui/themes'; +import { clamp } from 'three/src/math/MathUtils.js'; +import { + fakeLogSquishyHigh, + fakeLogSquishyLow, +} from '../../../../../../../core/blitzkit/fakeLog'; +import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics'; +import { Var } from '../../../../../../../core/radix/var'; +import { useLocale } from '../../../../../../../hooks/useLocale'; +import { AssaultCursor } from './components/Cursor'; + +interface Props { + ranges: AssaultRanges; + stats: TankCharacteristics; +} + +export function AssaultRangesVisualizer({ ranges: _ranges, stats }: Props) { + const maxDistance = _ranges.ranges.at(-1)!.distance; + const ranges = _ranges.ranges.map((range) => ({ + factor: range.factor, + distance: range.distance, + fakeDistance: fakeLogSquishyHigh(range.distance / maxDistance), + })); + const maxFakeDistance = ranges.at(-1)!.fakeDistance; + const maxFactor = ranges[0].factor; + + const { strings } = useLocale(); + + return ( + + + + {strings.website.tools.tankopedia.visualizers.assault.title} + + + + + + {ranges.map((range, index) => ( + + {literals(strings.common.units.hp, [ + `${Math.round(stats.damageWithoutAssault * range.factor)}`, + ])} + + ))} + + + + {ranges.map((range, index) => { + const mix = + clamp(2 * (range.factor / maxFactor - 1) + 1, 0, 1) * 100; + const color0 = `color-mix(in hsl, ${Var('tomato-9')}, ${Var('jade-9')} ${mix}%)`; + const color1 = `color-mix(in hsl, ${Var('tomato-7')}, ${Var('jade-7')} ${mix}%)`; + const last = ranges[index - 1]; + const lastFakeDistance = last?.fakeDistance ?? 0; + const fakeWidth = range.fakeDistance - lastFakeDistance; + const fraction = fakeWidth / ranges.at(-1)!.fakeDistance; + + return ( + + ); + })} + + {ranges.map((range, index) => ( + + ))} + + + + + + + {ranges.map((range, index) => { + const last = ranges[index - 1]; + const lastFakeDistance = last?.fakeDistance ?? 0; + const fakeWidth = range.fakeDistance - lastFakeDistance; + const fraction = fakeWidth / ranges.at(-1)!.fakeDistance; + + return ( + + + {literals(strings.common.units.m, [ + `${Math.round(range.distance)}`, + ])} + + + ); + })} + + + + + ); +} diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/Firepower.tsx b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/Firepower.tsx index 1da75a991..19819e63e 100644 --- a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/Firepower.tsx +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/Firepower.tsx @@ -21,6 +21,7 @@ import { useEquipment } from '../../../../../../hooks/useEquipment'; import { useLocale } from '../../../../../../hooks/useLocale'; import { useTankModelDefinition } from '../../../../../../hooks/useTankModelDefinition'; import { Duel } from '../../../../../../stores/duel'; +import { AssaultRangesVisualizer } from './AssaultRangesVisualizer'; import { Info } from './Info'; import { InfoWithDelta } from './InfoWithDelta'; import { RicochetVisualizer } from './RicochetVisualizer'; @@ -112,6 +113,20 @@ export function Firepower({ stats }: StatsAcceptorProps) { {strings.common.gun_types[gun.gun_type!.$case]} + + {gun.gun_type!.$case !== 'regular' && ( + + )} + + + + {gun.gun_type!.value.base.assault_ranges?.types.includes(shell.type) && ( + + )} + {gun.gun_type!.$case === 'auto_reloader' && ( )} @@ -172,7 +187,6 @@ export function Firepower({ stats }: StatsAcceptorProps) { )} {/* */} - {typeof shell.penetration !== 'number' && ( <> )} - - {gun.gun_type!.$case !== 'regular' && ( - - )} - {isExplosive(shell.type) && ( state.protagonist.tank); + const shellIndex = Duel.use((state) => + state.protagonist.gun.gun_type!.value.base.shells.indexOf( + state.protagonist.shell, + ), + ); + const equipmentMatrix = Duel.use( + (state) => state.protagonist.equipmentMatrix, + ); const others = useMemo(() => { const defaultSkills = createDefaultSkills(skillDefinitions); @@ -86,6 +94,10 @@ export function InfoWithDelta({ provisionDefinitions, ); + if (member.gun.gun_type!.value.base.shells[shellIndex] === undefined) { + return undefined; + } + return tankCharacteristics( { applyDynamicArmor: false, @@ -97,8 +109,8 @@ export function InfoWithDelta({ provisions: member.provisions, engine: member.engine, gun: member.gun, - equipmentMatrix: member.equipmentMatrix, - shell: member.shell, + equipmentMatrix: equipmentMatrix, + shell: member.gun.gun_type!.value.base.shells[shellIndex], stockEngine: tank.engines[0], stockGun: tank.turrets[0].guns[0], stockTrack: tank.tracks[0], @@ -106,6 +118,7 @@ export function InfoWithDelta({ tank, track: member.track, turret: member.turret, + assaultDistance: member.assaultDistance, }, { equipmentDefinitions, @@ -115,14 +128,16 @@ export function InfoWithDelta({ ); }) .filter((tank) => { + if (tank === undefined) return false; + const othersValue = typeof props.value === 'function' ? props.value(tank)! : (tank[props.value] as number); return othersValue !== undefined; - }); - }, [relativeAgainst]); + }) as TankCharacteristics[]; + }, [relativeAgainst, shellIndex, equipmentMatrix]); const betterTanks = others.filter((tank) => { const othersValue = typeof props.value === 'function' diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/index.tsx b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/index.tsx index 060b03ef5..5e5de9e70 100644 --- a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/index.tsx +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/index.tsx @@ -24,6 +24,9 @@ export function Characteristics() { const provisions = Duel.use((state) => state.protagonist.provisions); const consumables = Duel.use((state) => state.protagonist.consumables); const camouflage = Duel.use((state) => state.protagonist.camouflage); + const assaultDistance = Duel.use( + (state) => state.protagonist.assaultDistance, + ); const equipmentMatrix = Duel.use( (state) => state.protagonist.equipmentMatrix, ); @@ -58,6 +61,7 @@ export function Characteristics() { applyReactiveArmor: false, applyDynamicArmor: false, applySpallLiner: false, + assaultDistance, }, { tankModelDefinition, diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/components/Tracker.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/components/Tracker.tsx new file mode 100644 index 000000000..9448e0ac3 --- /dev/null +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/components/Tracker.tsx @@ -0,0 +1,25 @@ +import { Box, Progress } from '@radix-ui/themes'; +import { useProgress } from '@react-three/drei'; + +interface Props { + fontSize?: string; +} + +export function Tracker({ fontSize }: Props) { + const { loaded, total } = useProgress(); + const progress = total === 0 ? 0 : (loaded / total) * 100; + + return ( + + + + ); +} diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx similarity index 74% rename from packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx index 677e19b99..44d1b3bca 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/Title/index.tsx @@ -1,13 +1,14 @@ import { TankType } from '@blitzkit/core'; import { Box, Heading } from '@radix-ui/themes'; -import { Var } from '../../../../../core/radix/var'; -import { useLocale } from '../../../../../hooks/useLocale'; -import { Duel } from '../../../../../stores/duel'; -import type { RadixColor } from '../../../../../stores/embedState'; -import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral'; +import { Var } from '../../../../../../core/radix/var'; +import { useLocale } from '../../../../../../hooks/useLocale'; +import { Duel } from '../../../../../../stores/duel'; +import type { RadixColor } from '../../../../../../stores/embedState'; +import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral'; +import { Tracker } from './components/Tracker'; interface TitleProps { - outline?: boolean; + foreground?: boolean; } export const NATION_COLORS: Record< @@ -65,7 +66,7 @@ export const NATION_COLORS: Record< }, }; -export function Title({ outline }: TitleProps) { +export function Title({ foreground }: TitleProps) { const { unwrap } = useLocale(); const protagonist = Duel.use((state) => state.protagonist.tank); const disturbed = TankopediaEphemeral.use((state) => state.disturbed); @@ -81,6 +82,11 @@ export function Title({ outline }: TitleProps) { : `${nationColors.text}-12`, ); const name = unwrap(protagonist.name); + const fontSize = revealed + ? disturbed + ? '2rem' + : `min(65vh, ${125 / name.length}vw)` + : `min(48vh, ${75 / name.length}vw)`; return ( {name} + + {!revealed && } ); } diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps/index.tsx index 15b6a60de..bc69ab476 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/SceneProps/index.tsx @@ -73,6 +73,9 @@ export function SceneProps() { const crewSkills = TankopediaEphemeral.use((state) => state.skills); const consumables = Duel.use((state) => state.protagonist.consumables); const provisions = Duel.use((state) => state.protagonist.provisions); + const assaultDistance = Duel.use( + (state) => state.protagonist.assaultDistance, + ); const equipmentMatrix = Duel.use( (state) => state.protagonist.equipmentMatrix, ); @@ -96,6 +99,7 @@ export function SceneProps() { stockTurret: tank.turrets[0], stockTrack: tank.tracks[0], track, + assaultDistance, }, { equipmentDefinitions, provisionDefinitions, tankModelDefinition }, ); diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TransitionSkeleton/shaders/fragment.glsl b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TransitionSkeleton/shaders/fragment.glsl index 4cf3f9b1e..4a62b866a 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TransitionSkeleton/shaders/fragment.glsl +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TransitionSkeleton/shaders/fragment.glsl @@ -1,3 +1,5 @@ +precision mediump float; + #define USE_FOG #include diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TransitionSkeleton/shaders/vertex.glsl b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TransitionSkeleton/shaders/vertex.glsl index d80ba8239..2c0140061 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TransitionSkeleton/shaders/vertex.glsl +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/components/TransitionSkeleton/shaders/vertex.glsl @@ -1,3 +1,5 @@ +precision mediump float; + #define USE_FOG #include diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx index 7133ca8a0..6ec1684d7 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox/index.tsx @@ -39,11 +39,11 @@ interface TankSandboxProps { naked?: boolean; } -export const forNear0 = 20; -export const fogFar0 = 25; +export const forNear0 = 30; +export const fogFar0 = 50; export const forNear1 = 0; export const fogFar1 = 0; -export const fogAnimationTime = 1.5; +export const fogAnimationTime = 2.5; export const TankSandbox = forwardRef( ({ thicknessRange, naked }, ref) => { @@ -74,7 +74,7 @@ export const TankSandbox = forwardRef( const interval = setInterval(() => { const t = (Date.now() - t0) / 1000; const x = t / fogAnimationTime; - const y = Math.cbrt(-2 * Math.abs(x - 0.5)) + 1; + const y = Math.sin(Math.PI * x); const near = forNear0 + (forNear1 - forNear0) * y; const far = fogFar0 + (fogFar1 - fogFar0) * y; diff --git a/packages/website/src/components/Tankopedia/HeroSection/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/index.tsx index 414908bce..e3dcc394d 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/index.tsx @@ -103,7 +103,7 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) { transitionDuration: '1s', background: isFullScreen ? 'black' : undefined, }} - height={disturbed && !isFullScreen ? 'calc(100svh - 6rem)' : '100vh'} + height={!isFullScreen ? 'calc(100svh - 6rem)' : '100vh'} maxHeight={isFullScreen ? undefined : '60rem'} maxWidth={isFullScreen ? undefined : '120rem'} flexGrow="1" @@ -136,7 +136,7 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) { height: '100%', transitionDuration: '2s', opacity: revealed ? 1 : 0, - filter: disturbed ? undefined : `drop-shadow(0 0 2rem black)`, + filter: disturbed ? undefined : `drop-shadow(0 0 1rem black)`, }} > @@ -153,7 +153,7 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) { - + <Title foreground /> </Flex> </Flex> ); diff --git a/packages/website/src/core/blitzkit/fakeLog.ts b/packages/website/src/core/blitzkit/fakeLog.ts new file mode 100644 index 000000000..1f40ef3e8 --- /dev/null +++ b/packages/website/src/core/blitzkit/fakeLog.ts @@ -0,0 +1,17 @@ +const GAMMA = 1.2; + +export function fakeLogSquishyHigh(x: number) { + return Math.sin((Math.PI / 2) * x) ** (1 / GAMMA); +} + +export function fakeLogSquishyHighInverse(y: number) { + return (2 / Math.PI) * Math.asin(y ** GAMMA); +} + +export function fakeLogSquishyLow(x: number) { + return x ** 2; +} + +export function fakeLogSquishyLowInverse(y: number) { + return y ** (1 / 2); +} diff --git a/packages/website/src/core/blitzkit/hasEquipment.ts b/packages/website/src/core/blitzkit/hasEquipment.ts index 854af3f77..cba049c4c 100644 --- a/packages/website/src/core/blitzkit/hasEquipment.ts +++ b/packages/website/src/core/blitzkit/hasEquipment.ts @@ -1,12 +1,12 @@ -import { fetchEquipmentDefinitions } from '@blitzkit/core'; import type { EquipmentMatrix } from '../../stores/duel'; +import { awaitableEquipmentDefinitions } from '../awaitables/equipmentDefinitions'; export async function hasEquipment( id: number, equipmentPreset: string, equipmentMatrix: EquipmentMatrix, ) { - const equipmentDefinitions = await fetchEquipmentDefinitions(); + const equipmentDefinitions = await awaitableEquipmentDefinitions; const preset = equipmentDefinitions.presets[equipmentPreset]; return preset.slots.some((slot, index) => { const row = Math.floor(index / 3); diff --git a/packages/website/src/core/blitzkit/tankCharacteristics.ts b/packages/website/src/core/blitzkit/tankCharacteristics.ts index a9410cb77..e8e021203 100644 --- a/packages/website/src/core/blitzkit/tankCharacteristics.ts +++ b/packages/website/src/core/blitzkit/tankCharacteristics.ts @@ -46,6 +46,7 @@ export function tankCharacteristics( applyReactiveArmor, applyDynamicArmor, applySpallLiner, + assaultDistance, }: { tank: TankDefinition; turret: TurretDefinition; @@ -65,6 +66,7 @@ export function tankCharacteristics( applyReactiveArmor: boolean; applyDynamicArmor: boolean; applySpallLiner: boolean; + assaultDistance: number; }, { tankModelDefinition, @@ -157,7 +159,15 @@ export function tankCharacteristics( [applyDynamicArmor, -0.1], [applySpallLiner && shell.type === ShellType.HE, -0.2], ); - const moduleDamageCoefficient = coefficient([hasTungsten, 0.15]); + const assaultDamageCoefficient = + gun.gun_type!.value.base.assault_ranges && + gun.gun_type!.value.base.assault_ranges.types.includes(shell.type) + ? (gun.gun_type!.value.base.assault_ranges.ranges.find( + ({ distance }) => distance >= assaultDistance, + )?.factor ?? 0) + : 1; + const moduleDamageCoefficient = + coefficient([hasTungsten, 0.15]) * assaultDamageCoefficient; const reloadCoefficient = (coefficient([hasGunRammer, -0.05]) * coefficient([true, degressiveStat(loaderMastery)])) / @@ -326,10 +336,13 @@ export function tankCharacteristics( stockTurret.weight + stockGun.gun_type!.value.base.weight; const resolvedEnginePower = engine.power * enginePowerCoefficient; + const damageCoefficientWithoutAssault = armorDamageCoefficient; + const damageCoefficient = + damageCoefficientWithoutAssault * assaultDamageCoefficient; const dpm = resolveDpm( gun, shell, - armorDamageCoefficient, + damageCoefficient, reloadCoefficient, intraClipCoefficient, ); @@ -352,7 +365,9 @@ export function tankCharacteristics( return current; }, null)!.index : undefined; - const damage = shell.armor_damage * armorDamageCoefficient; + const damageWithoutAssault = + shell.armor_damage * damageCoefficientWithoutAssault; + const damage = shell.armor_damage * damageCoefficient; const dpmEffective = gun.gun_type!.$case === 'auto_reloader' ? gun.gun_type!.value.extension.shell_reloads[0] > @@ -533,6 +548,7 @@ export function tankCharacteristics( caliber, penetration, damage, + damageWithoutAssault, clipDamage, moduleDamage, explosionRadius, diff --git a/packages/website/src/core/blitzkit/tankToDuelMember.ts b/packages/website/src/core/blitzkit/tankToDuelMember.ts index ab0d96a92..3792b6d15 100644 --- a/packages/website/src/core/blitzkit/tankToDuelMember.ts +++ b/packages/website/src/core/blitzkit/tankToDuelMember.ts @@ -40,5 +40,7 @@ export function tankToDuelMember( yaw, pitch, turret, + assaultDistance: + (gun.gun_type!.value.base.assault_ranges?.ranges[0].distance ?? 0) / 2, } satisfies DuelMember; } diff --git a/packages/website/src/pages/[...locale]/compare/_index.tsx b/packages/website/src/pages/[...locale]/compare/_index.tsx index f39e322f0..be223f84a 100644 --- a/packages/website/src/pages/[...locale]/compare/_index.tsx +++ b/packages/website/src/pages/[...locale]/compare/_index.tsx @@ -85,6 +85,7 @@ function Content() { member.key !== thisMember.key && member.provisions.includes(101), ), + assaultDistance: thisMember.assaultDistance, }, { equipmentDefinitions: equipmentDefinitions, diff --git a/packages/website/src/pages/[...locale]/tanks/[slug]/index.astro b/packages/website/src/pages/[...locale]/tanks/[slug]/index.astro index 11f8567f1..5db83f641 100644 --- a/packages/website/src/pages/[...locale]/tanks/[slug]/index.astro +++ b/packages/website/src/pages/[...locale]/tanks/[slug]/index.astro @@ -60,6 +60,7 @@ const url = import.meta.env.SITE + Astro.url.pathname; const icon = asset(`icons/tanks/big/${id}.webp`); const turret = tank.turrets.at(-1)!; const gun = turret.guns.at(-1)!; +const shell = gun.gun_type!.value.base.shells[0]; const characteristics = tankCharacteristics( { tank, @@ -74,12 +75,13 @@ const characteristics = tankCharacteristics( turret, gun, provisions: createDefaultProvisions(tank, gun, provisionDefinitions), - shell: gun.gun_type!.value.base.shells[0], + shell, stockEngine: tank.engines[0], stockGun: tank.turrets[0].guns[0], stockTurret: tank.turrets[0], stockTrack: tank.tracks[0], track: tank.tracks.at(-1)!, + assaultDistance: 0, }, { equipmentDefinitions, provisionDefinitions, tankModelDefinition }, ); diff --git a/packages/website/src/pages/robots.txt.ts b/packages/website/src/pages/robots.txt.ts index d37262f56..e056aa4a8 100644 --- a/packages/website/src/pages/robots.txt.ts +++ b/packages/website/src/pages/robots.txt.ts @@ -1,9 +1,12 @@ import type { APIContext } from 'astro'; +const ALLOW_ROBOTS = import.meta.env.ALLOW_ROBOTS; + export async function GET({ request }: APIContext) { const flags: Record<string, string | null> = { 'User-agent': '*', - Allow: '/', + Allow: ALLOW_ROBOTS ? '/' : null, + Disallow: ALLOW_ROBOTS ? null : '/', space: null, Sitemap: `${new URL(request.url).origin}/sitemap-index.xml`, diff --git a/packages/website/src/stores/duel/index.ts b/packages/website/src/stores/duel/index.ts index 132c5d789..310e5c703 100644 --- a/packages/website/src/stores/duel/index.ts +++ b/packages/website/src/stores/duel/index.ts @@ -39,6 +39,7 @@ export interface DuelMember { provisions: number[]; camouflage: boolean; cooldownBooster: number; + assaultDistance: number; } export interface DuelStore { diff --git a/packages/website/src/stores/tankFilters.ts b/packages/website/src/stores/tankFilters.ts index a2ba14df9..14eaac227 100644 --- a/packages/website/src/stores/tankFilters.ts +++ b/packages/website/src/stores/tankFilters.ts @@ -18,7 +18,7 @@ export interface TankFilters { classes: TankClass[]; types: TankType[]; testing: 'include' | 'exclude' | 'only'; - search?: string; + search: string | null; searching: boolean; gunType: CaseType<GunDefinition>[]; shells: [ShellType | null, ShellType | null, ShellType | null]; @@ -30,7 +30,7 @@ export const initialTankFilters: TankFilters = { classes: [], types: [], testing: 'include', - search: undefined, + search: null, searching: false, gunType: [], shells: [null, null, null], diff --git a/packages/website/src/stores/tankopediaPersistent/constants.ts b/packages/website/src/stores/tankopediaPersistent/constants.ts index 49bc4bda1..52f03f645 100644 --- a/packages/website/src/stores/tankopediaPersistent/constants.ts +++ b/packages/website/src/stores/tankopediaPersistent/constants.ts @@ -14,6 +14,7 @@ export const SORT_UNITS: Record<TankopediaSortBy, string | undefined> = { 'fire.gunDepression': 'ยฐ', 'fire.gunElevation': 'ยฐ', 'fire.premiumPenetration': 'mm', + 'fire.tertiaryPenetration': 'mm', 'fire.reload': 's', 'fire.shellVelocity': 'm/s', 'fire.shellRange': 'm',