From 67da59ef41a938ae5609e7fd6aaeb931213c421d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 13 Dec 2025 23:35:38 -0600 Subject: [PATCH] feat: start of stages --- .../src/core/blitz/aggregateAttributes.ts | 54 ------------ .../src/core/blitz/aggregateStages.ts | 85 +++++++++++++++++++ .../src/pages/tanks/[slug]/_index.tsx | 9 +- 3 files changed, 87 insertions(+), 61 deletions(-) delete mode 100644 packages/website-ue/src/core/blitz/aggregateAttributes.ts create mode 100644 packages/website-ue/src/core/blitz/aggregateStages.ts diff --git a/packages/website-ue/src/core/blitz/aggregateAttributes.ts b/packages/website-ue/src/core/blitz/aggregateAttributes.ts deleted file mode 100644 index 80533e9d5..000000000 --- a/packages/website-ue/src/core/blitz/aggregateAttributes.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { - TankAttributeChange_AttributeName, - TankAttributeChange_Modifier, - type TankAttributeChange, -} from "@protos/blitz_static_tank_upgrade_single_stage"; -import { times } from "lodash-es"; - -export type AggregatedAttributes = Partial< - Record ->; - -function patch( - changes: TankAttributeChange[], - attributes: AggregatedAttributes -) { - for (const { attribute_name, value, modifier } of changes) { - switch (modifier) { - case TankAttributeChange_Modifier.MODIFIER_OVERRIDE: - attributes[attribute_name] = value; - break; - - case TankAttributeChange_Modifier.MODIFIER_MULTIPLY: { - if (!(attribute_name in attributes)) { - throw new Error( - `Missing attribute ${TankAttributeChange_AttributeName[attribute_name]} to modify` - ); - } - } - - case TankAttributeChange_Modifier.MODIFIER_MULTIPLY: { - attributes[attribute_name]! *= value; - break; - } - - default: - throw new Error( - `Unhandled modified ${TankAttributeChange_Modifier[modifier]}` - ); - } - } -} - -export function aggregateAttributes( - base: TankAttributeChange[], - stages: TankAttributeChange[][], - stage: number -) { - const attributes: AggregatedAttributes = {}; - - patch(base, attributes); - times(stage, (index) => patch(stages[index], attributes)); - - return attributes; -} diff --git a/packages/website-ue/src/core/blitz/aggregateStages.ts b/packages/website-ue/src/core/blitz/aggregateStages.ts new file mode 100644 index 000000000..17b861e83 --- /dev/null +++ b/packages/website-ue/src/core/blitz/aggregateStages.ts @@ -0,0 +1,85 @@ +import { + StageParameters, + TankAttributeChange_AttributeName, + TankAttributeChange_Modifier, +} from "@protos/blitz_static_tank_upgrade_single_stage"; +import { times } from "lodash-es"; + +function patch(change: StageParameters, base: StageParameters) { + if (change.stage_number !== base.stage_number + 1) { + throw new Error("Change stage number must be 1 greater than base"); + } + + for (const attribute of change.attributes) { + const oldValue = base.attributes[attribute.attribute_name].value; + let newValue: number; + + switch (attribute.modifier) { + case TankAttributeChange_Modifier.MODIFIER_OVERRIDE: + newValue = attribute.value; + break; + + case TankAttributeChange_Modifier.MODIFIER_MULTIPLY: + case TankAttributeChange_Modifier.MODIFIER_ADD: { + if (!(attribute.attribute_name in base)) { + throw new Error( + `Missing attribute ${ + TankAttributeChange_AttributeName[attribute.attribute_name] + } to modify` + ); + } + } + + case TankAttributeChange_Modifier.MODIFIER_MULTIPLY: { + newValue = oldValue * attribute.value; + break; + } + + case TankAttributeChange_Modifier.MODIFIER_ADD: { + newValue = oldValue + attribute.value; + break; + } + + default: + throw new Error( + `Unhandled modified ${ + TankAttributeChange_Modifier[attribute.modifier] + }` + ); + } + + base.attributes[attribute.attribute_name] = { + modifier: TankAttributeChange_Modifier.MODIFIER_OVERRIDE, + attribute_name: attribute.attribute_name, + value: newValue, + }; + } +} + +export function aggregateStages( + base: StageParameters, + stages: StageParameters[], + stage: number +) { + const attributes = StageParameters.create(); + + patch(base, attributes); + + /** + * Bug in Reforged: base stats are stage 1, so is the first upgrade. Manually + * setting it to stage 0 below and if the bug's been fixed, throw an error + * in dev mode to allow clean up in the future. + */ + + if (attributes.stage_number === 0 && import.meta.env.DEV) { + throw new Error( + "Base stats are now stage 0. In-game bug fixed, please remove hack." + ); + } + + attributes.stage_number = 0; + + times(stage, (index) => patch(stages[index], attributes)); + + return attributes; +} diff --git a/packages/website-ue/src/pages/tanks/[slug]/_index.tsx b/packages/website-ue/src/pages/tanks/[slug]/_index.tsx index 35785662c..41bbd4240 100644 --- a/packages/website-ue/src/pages/tanks/[slug]/_index.tsx +++ b/packages/website-ue/src/pages/tanks/[slug]/_index.tsx @@ -1,7 +1,7 @@ import { times } from "lodash-es"; import { Suspense, useMemo } from "react"; import { api } from "../../../core/api/dynamic"; -import { aggregateAttributes } from "../../../core/blitz/aggregateAttributes"; +import { aggregateStages } from "../../../core/blitz/aggregateStages"; import { useAwait } from "../../../hooks/useAwait"; import { Tankopedia } from "../../../stores/tankopedia"; @@ -19,12 +19,7 @@ function Content({ id }: { id: string }) { const stage = Tankopedia.use((state) => state.stage); const attributes = useMemo( - () => - aggregateAttributes( - tank.base_stats!.attributes, - tank.upgrade_stages.map((stage) => stage.attributes), - stage - ), + () => aggregateStages(tank.base_stats!, tank.upgrade_stages, stage), [stage] );