From 1ee6cdabe5263bccd867ac6a968ef35be0cea63d Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 30 Sep 2026 17:36:51 -0500 Subject: [PATCH] SpacedArmorScene --- .../src/components/ArmorPlateDisplay.tsx | 5 ++- .../src/components/SpacedArmorScene.tsx | 27 +++++++------ packages/website/src/hooks/useConsumable.ts | 6 +++ packages/website/src/stores/tankopedia.ts | 39 +++++++++---------- 4 files changed, 40 insertions(+), 37 deletions(-) create mode 100644 packages/website/src/hooks/useConsumable.ts diff --git a/packages/website/src/components/ArmorPlateDisplay.tsx b/packages/website/src/components/ArmorPlateDisplay.tsx index b47811abd..c3306f75e 100644 --- a/packages/website/src/components/ArmorPlateDisplay.tsx +++ b/packages/website/src/components/ArmorPlateDisplay.tsx @@ -12,8 +12,8 @@ import { useRef } from "react"; import { radToDeg } from "three/src/math/MathUtils.js"; import { resolveArmorIndex } from "../core/blitzkit/resolveArmorIndex"; import { LocaleProvider, useLocale } from "../hooks/useLocale"; +import { useStrings } from "../hooks/useStrings"; import { App } from "../stores/app"; -import { Duel } from "../stores/duel"; import { Tankopedia } from "../stores/tankopedia"; import { layerTypeNames } from "./ShotDisplayCard"; import { ArmorType } from "./SpacedArmorScene"; @@ -22,7 +22,8 @@ export function ArmorPlateDisplay() { const highlightArmor = Tankopedia.use((state) => state.highlightArmor); const developerMode = App.useDeferred((state) => state.developerMode, false); const input = useRef(null); - const { locale, strings } = useLocale(); + const locale = useLocale(); + const strings = useStrings(); if (highlightArmor === undefined) return null; diff --git a/packages/website/src/components/SpacedArmorScene.tsx b/packages/website/src/components/SpacedArmorScene.tsx index 7fddd9c1c..dfd8caedd 100644 --- a/packages/website/src/components/SpacedArmorScene.tsx +++ b/packages/website/src/components/SpacedArmorScene.tsx @@ -4,11 +4,11 @@ import { correctZYTuple } from "../core/blitz/correctZYTuple"; import { nameToArmorId } from "../core/blitzkit/nameToArmorId"; import { resolveArmor } from "../core/blitzkit/resolveThickness"; import { useArmor } from "../hooks/useArmor"; +import { useConsumable } from "../hooks/useConsumable"; +import { DuelModule, useDuel } from "../hooks/useDuel"; import { useModel } from "../hooks/useModel"; -import { useTankModelDefinition } from "../hooks/useTankModelDefinition"; import { useTankTransform } from "../hooks/useTankTransform"; -import { Duel } from "../stores/duel"; -import { ModelTankWrapper } from "./ModelTankWrapper"; +import { Tankopedia } from "../stores/tankopedia"; import { SpacedArmorSceneComponent } from "./SpacedArmorSceneComponent"; export enum ArmorType { @@ -22,18 +22,19 @@ interface SpacedArmorSceneProps { } export const SpacedArmorScene = memo(({ scene }) => { - const wrapper = useRef(null); const turretContainer = useRef(null!); const gunContainer = useRef(null!); - const tank = Duel.use((state) => state.protagonist.tank); - const track = Duel.use((state) => state.protagonist.track); - const turret = Duel.use((state) => state.protagonist.turret); - const gun = Duel.use((state) => state.protagonist.gun); + const tank = useDuel("protagonist", DuelModule.Tank); + const track = useDuel("protagonist", DuelModule.Track); + const turret = useDuel("protagonist", DuelModule.Turret); + const gun = useDuel("protagonist", DuelModule.Gun); const { gltf: armorGltf } = useArmor(tank.id); const { gltf: modelGltf } = useModel(tank.id); const armorNodes = Object.values(armorGltf.nodes); const modelNodes = Object.values(modelGltf.nodes); - const tankModelDefinition = useTankModelDefinition(); + const tankModelDefinition = Tankopedia.use( + (state) => state.protagonist.model, + ); const trackModelDefinition = tankModelDefinition.tracks[track.id]; const turretModelDefinition = tankModelDefinition.turrets[turret.id]; const gunModelDefinition = turretModelDefinition.guns[gun.id]; @@ -44,14 +45,12 @@ export const SpacedArmorScene = memo(({ scene }) => { gunModelDefinition.mask === undefined ? undefined : gunModelDefinition.mask + hullOrigin.y + turretOrigin.y + gunOrigin.y; - const isDynamicArmorActive = Duel.use((state) => - state.protagonist.consumables.includes(73), - ); + const isDynamicArmorActive = useConsumable("protagonist", 73); useTankTransform(track, turret, turretContainer, gunContainer); return ( - + <> {armorNodes.map((node) => { const isHull = node.name.startsWith("hull_"); @@ -199,6 +198,6 @@ export const SpacedArmorScene = memo(({ scene }) => { })} - + ); }); diff --git a/packages/website/src/hooks/useConsumable.ts b/packages/website/src/hooks/useConsumable.ts new file mode 100644 index 000000000..0960c5d36 --- /dev/null +++ b/packages/website/src/hooks/useConsumable.ts @@ -0,0 +1,6 @@ +import { Tankopedia } from "../stores/tankopedia"; +import type { DuelSide } from "./useEquipment"; + +export function useConsumable(side: DuelSide, id: number) { + return Tankopedia.use((state) => state[side].consumables.includes(id)); +} diff --git a/packages/website/src/stores/tankopedia.ts b/packages/website/src/stores/tankopedia.ts index f244c371a..01c2015b6 100644 --- a/packages/website/src/stores/tankopedia.ts +++ b/packages/website/src/stores/tankopedia.ts @@ -1,11 +1,7 @@ import { createDefaultSkills } from "@blitzkit/core"; -import type { - ModelDefinition, - ShellDefinition, - TankDefinition, -} from "@blitzkit/protos"; -import type { Vector3 } from "three"; +import type { ShellDefinition, TankDefinition } from "@blitzkit/protos"; import { Soapstone } from "soapstone"; +import type { Vector3 } from "three"; import { api } from "../api/dynamic"; import type { ArmorType } from "../components/SpacedArmorScene"; import type { ExternalModuleVariant } from "../components/SpacedArmorSceneComponent"; @@ -85,7 +81,6 @@ interface Tankopedia { protagonist: TankState; antagonist: TankState; - model: ModelDefinition; equalize: boolean; @@ -117,20 +112,22 @@ interface Tankopedia { const skills = await api.skills(); const models = await api.models(); -export const Tankopedia = new Soapstone((tank) => ({ - disturbed: false, - revealed: false, +export const Tankopedia = new Soapstone( + (tank) => ({ + disturbed: false, + revealed: false, - protagonist: createTankState(tank), - antagonist: createTankState(tank), - model: models.models[tank.id], + protagonist: createTankState(tank), + antagonist: createTankState(tank), + model: models.models[tank.id], - equalize: false, + equalize: false, - relativeAgainst: TankopediaRelativeAgainst.Class, - editStatic: false, - skills: createDefaultSkills(skills), - xpMultiplier: 1, - requestedDisplay: TankopediaDisplay.Model, - display: TankopediaDisplay.Model, -})); + relativeAgainst: TankopediaRelativeAgainst.Class, + editStatic: false, + skills: createDefaultSkills(skills), + xpMultiplier: 1, + requestedDisplay: TankopediaDisplay.Model, + display: TankopediaDisplay.Model, + }), +);