From 7d02f6311f70241314726f99592608cabaf235bd Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:13:27 -0500 Subject: [PATCH] tank states --- packages/core/src/blitzkit/api/base.ts | 7 +- packages/core/src/blitzkit/api/client.ts | 2 +- .../src/blitzkit/api/server/5_equipments.ts | 2 +- .../src/blitzkit/api/server/7_provisions.ts | 222 ------------------ .../core/src/blitzkit/availableProvisions.ts | 10 +- .../src/blitzkit/createDefaultProvisions.ts | 20 +- packages/core/src/types/blitzScripts.ts | 2 + packages/core/src/types/provisionsCommon.ts | 4 +- .../src/blitzkit/consumable_definitions.proto | 2 - .../src/blitzkit/provision_definitions.proto | 3 - .../src/core/blitzkit/tankToDuelMember.ts | 39 --- .../[...locale]/tanks/[slug]/_index.tsx | 3 +- packages/website/src/stores/duel/constants.ts | 7 - packages/website/src/stores/duel/index.ts | 56 ----- packages/website/src/stores/tankopedia.ts | 42 +++- .../website/src/tankopedia/createTankState.ts | 38 +++ 16 files changed, 110 insertions(+), 349 deletions(-) delete mode 100644 packages/website/src/core/blitzkit/tankToDuelMember.ts delete mode 100644 packages/website/src/stores/duel/constants.ts delete mode 100644 packages/website/src/stores/duel/index.ts create mode 100644 packages/website/src/tankopedia/createTankState.ts diff --git a/packages/core/src/blitzkit/api/base.ts b/packages/core/src/blitzkit/api/base.ts index c3cc46ffc..b8a6ad860 100644 --- a/packages/core/src/blitzkit/api/base.ts +++ b/packages/core/src/blitzkit/api/base.ts @@ -16,7 +16,7 @@ export abstract class BlitzKitAPI { abstract skills(): Promise; abstract provisions(): Promise; abstract consumables(): Promise; - abstract equipments(): Promise; + abstract equipment(): Promise; abstract maps(): Promise; abstract models(): Promise; abstract camouflages(): Promise; @@ -29,4 +29,9 @@ export abstract class BlitzKitAPI { const tanks = await this.tanks(); return tanks.tanks[id]; } + + async model(id: number) { + const models = await this.models(); + return models.models[id]; + } } diff --git a/packages/core/src/blitzkit/api/client.ts b/packages/core/src/blitzkit/api/client.ts index 2fd78039b..880d150e9 100644 --- a/packages/core/src/blitzkit/api/client.ts +++ b/packages/core/src/blitzkit/api/client.ts @@ -53,7 +53,7 @@ export class ClientBlitzKitAPI extends BlitzKitAPI { return fetchPB(alias("api", "/definitions/skills.pb"), SkillDefinitions); } - equipments() { + equipment() { return fetchPB( alias("api", "/definitions/equipment.pb"), EquipmentDefinitions, diff --git a/packages/core/src/blitzkit/api/server/5_equipments.ts b/packages/core/src/blitzkit/api/server/5_equipments.ts index 4caad7cad..1fc1d3289 100644 --- a/packages/core/src/blitzkit/api/server/5_equipments.ts +++ b/packages/core/src/blitzkit/api/server/5_equipments.ts @@ -4,7 +4,7 @@ import { ServerBlitzKitAPI4 } from "./4_maps"; export abstract class ServerBlitzKitAPI5 extends ServerBlitzKitAPI4 { @Cache() - async equipments() { + async equipment() { const equipmentDefinitions = EquipmentDefinitions.create(); Object.entries(this.optionalDevices!.root).forEach( diff --git a/packages/core/src/blitzkit/api/server/7_provisions.ts b/packages/core/src/blitzkit/api/server/7_provisions.ts index afcc09018..0f60d8ab2 100644 --- a/packages/core/src/blitzkit/api/server/7_provisions.ts +++ b/packages/core/src/blitzkit/api/server/7_provisions.ts @@ -105,228 +105,6 @@ export abstract class ServerBlitzKitAPI7 extends ServerBlitzKitAPI6 { }); } } - - function applyCanonicalBonuses(map: Record) { - for (const key in map) { - entry.bonuses[key] = provision.script.bonusValues![map[key]]; - } - } - - function applyRootBonuses(map: Record) { - for (const key in map) { - entry.bonuses[key] = provision.script[map[key]]; - } - } - - function applyAttributeBonuses(map: Record) { - for (const key in map) { - if (!(map[key] in provision.script.attributes!)) continue; - entry.bonuses[key] = provision.script.attributes![map[key]]; - } - } - - switch (provision.script["#text"]) { - case "Stimulator": - applyCanonicalBonuses({ - crew_level_increase: "crewLevelIncrease", - }); - break; - - case "AntiHighExplosive": - applyCanonicalBonuses({ - anti_high_explosive_factor: "factor", - }); - break; - - case "Fuel": - applyCanonicalBonuses({ - engine_power_increase: "enginePowerIncrease", - turret_rotation_speed_increase: "turretRotationSpeedIncrease", - }); - break; - - case "SafetySet": - applyCanonicalBonuses({ - crew_chance_to_hit_factor: "crewChanceToHitFactor", - repair_speed_increase: "repairSpeedIncrease", - fire_protection_increase: "fireProtectionIncrease", - }); - break; - - case "SmallHPStock": - applyRootBonuses({ - hp_stock_percent: "hpStockPercent", - }); - break; - - case "GearOil": - applyCanonicalBonuses({ - forward_speed_limit_bias: "fwdSpeedLimitBias", - backward_speed_limit_bias: "bkwdSpeedLimitBias", - engine_power_increase: "enginePowerIncrease", - }); - break; - - case "GunPowder": - applyCanonicalBonuses({ - projectile_speed_factor: "projectileSpeedFactor", - }); - break; - - case "AttributesModifier": - applyAttributeBonuses({ - firm_ground_passability_increase: "firmGroundPassabilityIncrease", - medium_ground_passability_increase: - "mediumGroundPassabilityIncrease", - repair_speed_factor: "repairSpeedFactor", - - common_damage_factor: "commonDamageFactor", - gun_reload_factor: "gunReloadFactor", - pump_gun_reload_factor: "pumpGunReloadFactor", - gun_aiming_factor: "gunAimingFactor", - - engine_power_factor: "enginePowerFactor", - speed_limits_factor: "speedLimitsFactor", - chassis_health_factor: "chassisHealthFactor", - }); - break; - - case "LifestealHeal": - applyCanonicalBonuses({ - life_steal_factor: "lifestealFactor", - life_steal_random_factor: "lifestealRandomFactor", - kill_heal_factor: "killHealFactor", - heal_factor: "healFactor", - heal_random_factor: "healRandomFactor", - }); - break; - - case "RammingDamage": - applyCanonicalBonuses({ - ramming_damage_factor: "rammingDamageFactor", - dealing_ramming_damage_factor: "dealingRammingDamageFactor", - }); - break; - - case "AllyBuff": - applyCanonicalBonuses({ - gun_reloading_bonus: "gunReloadingBonus", - gun_aiming_time_bonus: "gunAimingTimeBonus", - vision_radius_bonus: "visionRadiusBonus", - }); - - applyRootBonuses({ - range: "range", - max_bonus_sources: "maxBonusSources", - }); - break; - - case "Stealth": - applyRootBonuses({ - sixth_sense_delay: "sixthSenseDelay", - stop_observing_delay_factor: "stopObservingDelayFactor", - }); - break; - - case "Revenge": - applyRootBonuses({ - revenge_damage_percentage: "revengeDamagePercentage", - effect_duration: "effectDuration", - }); - break; - - case "ComeBackKit": - applyRootBonuses({ - time_for_come_back: "timeForComeBack", - simple_mode: "simpleMode", - }); - break; - - case "EngineAndSpeedBoost": - applyCanonicalBonuses({ - engine_power_ability_factor: "enginePowerAbilityFactor", - speed_limit_ability_bonus: "speedLimitAbilityBonus", - }); - break; - - case "EnemyReloadTime": - // bonusValues is empty in the observed data. - break; - - case "Duplet": - applyCanonicalBonuses({ - shot_dispersion_angle_factor: "shotDispersionAngleFactor", - aiming_time_factor: "aimingTimeFactor", - time_between_shots: "timeBetweenShots", - }); - break; - - case "Fortune": - applyCanonicalBonuses({ - increased_damage_chance: "increasedDamageChance", - increase_damage_factor: "increaseDamageFactor", - }); - break; - - case "VampiricCurse": - applyRootBonuses({ - curse_strength: "curseStrength", - curse_reduction: "curseReduction", - curse_heal: "curseHeal", - }); - break; - - case "VampiricDeath": - applyRootBonuses({ - explode_damage_percent: "explodeDamagePercent", - range: "range", - }); - break; - - case "PermanentDamageShield": - applyRootBonuses({ - damage_reduction_percent: "damageReductionPercent", - }); - break; - - case "BigBoss": - applyCanonicalBonuses({ - gun_reload_factor: "gunReloadFactor", - common_damage_factor: "commonDamageFactor", - engine_power_factor: "enginePowerFactor", - speed_limits_factor: "speedLimitsFactor", - max_health_percent_bonus: "maxHealthPercentBonus", - max_statics_damage_percent: "maxStaticsDamagePercent", - }); - break; - - case "VampiricBoost": - break; - - case "ZombieMark": - applyAttributeBonuses({ - dealing_ramming_damage_factor: "dealingRammingDamageFactor", - ramming_damage_factor: "rammingDamageFactor", - engine_power_factor: "enginePowerFactor", - speed_limits_factor: "speedLimitsFactor", - common_damage_factor: "commonDamageFactor", - }); - break; - - case "HumanMark": - applyRootBonuses({ - opt_device_ramming_damage_override: - "optDeviceRammingDamageOverride", - }); - - // `bonusValues.item` is a nested array and therefore isn't - // appropriate for applyCanonicalBonuses(). - break; - - default: - console.warn(`Unhandled script type ${provision.script["#text"]}`); - console.dir(provision.script, { depth: null, colors: true }); - } }); return provisionDefinitions; diff --git a/packages/core/src/blitzkit/availableProvisions.ts b/packages/core/src/blitzkit/availableProvisions.ts index 31891631a..f38c708b1 100644 --- a/packages/core/src/blitzkit/availableProvisions.ts +++ b/packages/core/src/blitzkit/availableProvisions.ts @@ -1,12 +1,16 @@ -import { GunDefinition, ProvisionDefinitions, TankDefinition } from "../../../protos/src/blitzkit"; +import { + GunDefinition, + ProvisionDefinitions, + TankDefinition, +} from "../../../protos/src/blitzkit"; import { checkConsumableProvisionInclusivity } from "./checkConsumableProvisionInclusivity"; export function availableProvisions( tank: TankDefinition, gun: GunDefinition, - provisionDefinitions: ProvisionDefinitions + provisionDefinitions: ProvisionDefinitions, ) { return Object.values(provisionDefinitions.provisions).filter((provision) => - checkConsumableProvisionInclusivity(provision, tank, gun) + checkConsumableProvisionInclusivity(provision, tank, gun), ); } diff --git a/packages/core/src/blitzkit/createDefaultProvisions.ts b/packages/core/src/blitzkit/createDefaultProvisions.ts index 2719bb2d2..a895e7c73 100644 --- a/packages/core/src/blitzkit/createDefaultProvisions.ts +++ b/packages/core/src/blitzkit/createDefaultProvisions.ts @@ -1,5 +1,10 @@ -import { GunDefinition, ProvisionDefinitions, TankDefinition } from '../protos'; -import { availableProvisions } from './availableProvisions'; +import { + GunDefinition, + ProvisionDefinitions, + TankDefinition, +} from "@blitzkit/protos"; +import { BlitzScripts } from "../types/blitzScripts"; +import { availableProvisions } from "./availableProvisions"; const PROVISION_PREFERENCES = [ 19, // improved fuel @@ -14,9 +19,10 @@ function infinityFallback(value: number) { export function createDefaultProvisions( tank: TankDefinition, gun: GunDefinition, - provisionDefinitions: ProvisionDefinitions, + provisions: ProvisionDefinitions, + scripts: BlitzScripts, ) { - const provisionsList = availableProvisions(tank, gun, provisionDefinitions); + const provisionsList = availableProvisions(tank, gun, provisions); return provisionsList .sort( @@ -24,7 +30,11 @@ export function createDefaultProvisions( infinityFallback(PROVISION_PREFERENCES.indexOf(a.id)) - infinityFallback(PROVISION_PREFERENCES.indexOf(b.id)), ) - .sort((a, b) => (b.crew ?? 0) - (a.crew ?? 0)) + .sort( + (a, b) => + (scripts.provisions[b.id].bonusValues?.crewLevelIncrease ?? 0) - + (scripts.provisions[a.id].bonusValues?.crewLevelIncrease ?? 0), + ) .slice(0, tank.max_provisions) .map(({ id }) => id); } diff --git a/packages/core/src/types/blitzScripts.ts b/packages/core/src/types/blitzScripts.ts index a4c4fb585..c32759054 100644 --- a/packages/core/src/types/blitzScripts.ts +++ b/packages/core/src/types/blitzScripts.ts @@ -1,3 +1,5 @@ +import { BlitzEffectScript } from "./blitzEffectScript"; + export interface BlitzScripts { consumables: Record; provisions: Record; diff --git a/packages/core/src/types/provisionsCommon.ts b/packages/core/src/types/provisionsCommon.ts index 42bc2956a..23d180ab8 100644 --- a/packages/core/src/types/provisionsCommon.ts +++ b/packages/core/src/types/provisionsCommon.ts @@ -1,4 +1,4 @@ -import { ProvisionConsumableScript } from "@blitzkit/core/src/types/provisionConsumableScript"; +import { BlitzEffectScript } from "./blitzEffectScript"; import { ConsumablesVehicleFilter } from "./consumablesVehicleFilter"; export interface ProvisionsCommon { @@ -13,6 +13,6 @@ export interface ProvisionsCommon { include: { vehicle: ConsumablesVehicleFilter; nations?: string }; exclude?: { vehicle: ConsumablesVehicleFilter; nations?: string }; }; - script: ProvisionConsumableScript; + script: BlitzEffectScript; }; } diff --git a/packages/protos/src/blitzkit/consumable_definitions.proto b/packages/protos/src/blitzkit/consumable_definitions.proto index c07fdd2f8..a9c8c2094 100644 --- a/packages/protos/src/blitzkit/consumable_definitions.proto +++ b/packages/protos/src/blitzkit/consumable_definitions.proto @@ -11,8 +11,6 @@ message ConsumableDefinitions { message Consumable { required uint32 id = 1; required I18nString name = 2; - required uint32 cooldown = 3; - optional float duration = 4; required bool game_mode_exclusive = 5; repeated ConsumableTankFilter include = 6; repeated ConsumableTankFilter exclude = 7; diff --git a/packages/protos/src/blitzkit/provision_definitions.proto b/packages/protos/src/blitzkit/provision_definitions.proto index c4bc9345f..af4889e8b 100644 --- a/packages/protos/src/blitzkit/provision_definitions.proto +++ b/packages/protos/src/blitzkit/provision_definitions.proto @@ -17,7 +17,4 @@ message Provision { required bool game_mode_exclusive = 5; repeated ConsumableTankFilter include = 6; repeated ConsumableTankFilter exclude = 7; - - map bonuses = 8; - map effects = 9; } \ No newline at end of file diff --git a/packages/website/src/core/blitzkit/tankToDuelMember.ts b/packages/website/src/core/blitzkit/tankToDuelMember.ts deleted file mode 100644 index 34f0aec50..000000000 --- a/packages/website/src/core/blitzkit/tankToDuelMember.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - createDefaultProvisions, - Equalizer, - type ProvisionDefinitions, - type TankDefinition, -} from "@blitzkit/core"; -import type { DuelMember } from "../../stores/duel"; -import { genericDefaultEquipmentMatrix } from "../../stores/duel/constants"; - -export function tankToDuelMember( - tank: TankDefinition, - provisionDefinitions: ProvisionDefinitions, -) { - const turret = tank.turrets.at(-1)!; - const gun = turret.guns.at(-1)!; - - return { - camouflage: true, - consumables: [], - equipmentMatrix: genericDefaultEquipmentMatrix, - cooldownBooster: 0, - provisions: createDefaultProvisions(tank, gun, provisionDefinitions), - engine: tank.engines.at(-1)!, - gun, - shell: tank.turrets.at(-1)!.guns.at(-1)!.shells[0], - tank, - track: tank.tracks.at(-1)!, - turret, - assaultDistance: (gun.assault_ranges?.ranges[0].distance ?? 0) / 2, - } satisfies DuelMember; -} - -export const defaultEqualizer: Equalizer = { - armor: 1, - damage: 1, - health: 1, - module_health: 1, - penetration: 1, -}; diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx b/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx index 67b85b72d..64293fe37 100644 --- a/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx +++ b/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx @@ -4,7 +4,6 @@ import { computeCharacteristics } from "../../../../../blitzkit/computeCharacter import { withErrorWrapper } from "../../../../../hocs/withErrorWrapper"; import { withLocale } from "../../../../../hocs/withLocale"; import { useAwait } from "../../../../../hooks/useAwait"; -import { useEquipment } from "../../../../../hooks/useEquipment"; import { Tankopedia } from "../../../../../stores/tankopedia"; import styles from "./_index.module.css"; @@ -19,7 +18,7 @@ export const Page = withErrorWrapper( Tankopedia.useInitialization(protagonistTank); const protagonist = Tankopedia.use((state) => state.protagonist); - const protagonistEquipment = useEquipment(protagonistTank.tank!); + // const protagonistEquipment = useEquipment(protagonistTank.tank!); const characteristics = useMemo( () => computeCharacteristics(), diff --git a/packages/website/src/stores/duel/constants.ts b/packages/website/src/stores/duel/constants.ts deleted file mode 100644 index 40355db2e..000000000 --- a/packages/website/src/stores/duel/constants.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { EquipmentMatrix } from '.'; - -export const genericDefaultEquipmentMatrix: EquipmentMatrix = [ - [-1, 1, -1], - [0, 0, 0], - [0, 0, 0], -]; diff --git a/packages/website/src/stores/duel/index.ts b/packages/website/src/stores/duel/index.ts deleted file mode 100644 index a650159a5..000000000 --- a/packages/website/src/stores/duel/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { - ModelDefinition, - type EngineDefinition, - type GunDefinition, - type ShellDefinition, - type TankDefinition, - type TrackDefinition, - type TurretDefinition, -} from "@blitzkit/core"; -import { Varuna } from "varuna"; -import { api } from "../../blitzkit/api"; -import { tankToDuelMember } from "../../core/blitzkit/tankToDuelMember"; - -type EquipmentMatrixItem = -1 | 0 | 1; -type EquipmentMatrixRow = [ - EquipmentMatrixItem, - EquipmentMatrixItem, - EquipmentMatrixItem, -]; -export type EquipmentMatrix = [ - EquipmentMatrixRow, - EquipmentMatrixRow, - EquipmentMatrixRow, -]; - -export interface DuelMember { - tank: TankDefinition; - engine: EngineDefinition; - turret: TurretDefinition; - gun: GunDefinition; - shell: ShellDefinition; - track: TrackDefinition; - equipmentMatrix: EquipmentMatrix; - consumables: number[]; - provisions: number[]; - camouflage: boolean; - cooldownBooster: number; - assaultDistance: number; -} - -export interface DuelStore { - protagonist: DuelMember; - antagonist: DuelMember; - equalize: boolean; -} - -const provisionDefinitions = await api.provisions(); - -export const Duel = new Varuna< - DuelStore, - { tank: TankDefinition; model: ModelDefinition } ->(({ tank, model }) => { - const protagonist = tankToDuelMember(tank, provisionDefinitions); - - return { protagonist, antagonist: protagonist, model, equalize: false }; -}); diff --git a/packages/website/src/stores/tankopedia.ts b/packages/website/src/stores/tankopedia.ts index 6d99f2635..bd5fabaf7 100644 --- a/packages/website/src/stores/tankopedia.ts +++ b/packages/website/src/stores/tankopedia.ts @@ -1,6 +1,11 @@ import { createDefaultSkills, + EngineDefinition, + GunDefinition, ShellDefinition, + TankDefinition, + TrackDefinition, + TurretDefinition, type ModelDefinition, } from "@blitzkit/core"; import type { Vector3 } from "three"; @@ -9,6 +14,8 @@ import { api } from "../blitzkit/api"; import type { ArmorType } from "../components/Armor/components/SpacedArmorScene"; import type { ExternalModuleVariant } from "../components/Armor/components/SpacedArmorSceneComponent"; import type { XP_MULTIPLIERS } from "../components/Tankopedia/TechTreeSection"; +import { createTankState } from "../tankopedia/createTankState"; +import type { EquipmentMatrix } from "./duel"; import { TankopediaDisplay } from "./tankopediaPersistent/constants"; export interface ShotLayerBase { @@ -76,13 +83,34 @@ export enum TankopediaRelativeAgainst { All, } +export interface TankState { + tank: TankDefinition; + model: ModelDefinition; + + engine: EngineDefinition; + turret: TurretDefinition; + gun: GunDefinition; + shell: ShellDefinition; + track: TrackDefinition; + + equipment_matrix: EquipmentMatrix; + + consumables: number[]; + provisions: number[]; + camouflage: boolean; + cooldown_booster: number; + assault_distance: number; +} + interface Tankopedia { disturbed: boolean; revealed: boolean; + + protagonist: TankState; + shot?: Shot; skills: Record; relativeAgainst: TankopediaRelativeAgainst; - model: ModelDefinition; editStatic: boolean; highlightArmor?: { editingPlate: boolean; @@ -105,15 +133,19 @@ interface Tankopedia { statSearch?: string; } -const skillDefinitions = await api.skills(); +const skills = await api.skills(); +const models = await api.models(); -export const Tankopedia = new Varuna((model) => ({ +export const Tankopedia = new Varuna((tank) => ({ disturbed: false, revealed: false, + + protagonist: createTankState(tank), + model: models.models[tank.id], + relativeAgainst: TankopediaRelativeAgainst.Class, editStatic: false, - skills: createDefaultSkills(skillDefinitions), - model, + skills: createDefaultSkills(skills), xpMultiplier: 1, requestedDisplay: TankopediaDisplay.Model, display: TankopediaDisplay.Model, diff --git a/packages/website/src/tankopedia/createTankState.ts b/packages/website/src/tankopedia/createTankState.ts new file mode 100644 index 000000000..d7cf5ce41 --- /dev/null +++ b/packages/website/src/tankopedia/createTankState.ts @@ -0,0 +1,38 @@ +import { createDefaultProvisions, type TankDefinition } from "@blitzkit/core"; +import { api } from "../blitzkit/api"; +import type { EquipmentMatrix } from "../stores/duel"; +import type { TankState } from "../stores/tankopedia"; + +const models = await api.models(); +const provisions = await api.provisions(); +const scripts = await api.scripts(); + +export const genericDefaultEquipmentMatrix: EquipmentMatrix = [ + [-1, 1, -1], + [0, 0, 0], + [0, 0, 0], +]; + +export function createTankState(tank: TankDefinition) { + const turret = tank.turrets.at(-1)!; + const gun = turret.guns.at(-1)!; + + return { + tank, + model: models.models[turret.id], + + engine: tank.engines.at(-1)!, + turret, + gun, + shell: gun.shells[0], + track: tank.tracks.at(-1)!, + + equipment_matrix: genericDefaultEquipmentMatrix, + + consumables: [], + provisions: createDefaultProvisions(tank, gun, provisions, scripts), + camouflage: true, + cooldown_booster: 0, + assault_distance: (gun.assault_ranges?.ranges[0].distance ?? 0) / 2, + } satisfies TankState; +}