SpacedArmorScene

This commit is contained in:
tresabhi committed 2026-09-30 17:36:51 -05:00
1 parent 480d2226f7
commit 1ee6cdabe5
4 files changed
+28 -25

No files matched your search

@@ -12,8 +12,8 @@ import { useRef } from "react";
import { radToDeg } from "three/src/math/MathUtils.js"; import { radToDeg } from "three/src/math/MathUtils.js";
import { resolveArmorIndex } from "../core/blitzkit/resolveArmorIndex"; import { resolveArmorIndex } from "../core/blitzkit/resolveArmorIndex";
import { LocaleProvider, useLocale } from "../hooks/useLocale"; import { LocaleProvider, useLocale } from "../hooks/useLocale";
import { useStrings } from "../hooks/useStrings";
import { App } from "../stores/app"; import { App } from "../stores/app";
import { Duel } from "../stores/duel";
import { Tankopedia } from "../stores/tankopedia"; import { Tankopedia } from "../stores/tankopedia";
import { layerTypeNames } from "./ShotDisplayCard"; import { layerTypeNames } from "./ShotDisplayCard";
import { ArmorType } from "./SpacedArmorScene"; import { ArmorType } from "./SpacedArmorScene";
@@ -22,7 +22,8 @@ export function ArmorPlateDisplay() {
const highlightArmor = Tankopedia.use((state) => state.highlightArmor); const highlightArmor = Tankopedia.use((state) => state.highlightArmor);
const developerMode = App.useDeferred((state) => state.developerMode, false); const developerMode = App.useDeferred((state) => state.developerMode, false);
const input = useRef<HTMLInputElement>(null); const input = useRef<HTMLInputElement>(null);
const { locale, strings } = useLocale(); const locale = useLocale();
const strings = useStrings();
if (highlightArmor === undefined) return null; if (highlightArmor === undefined) return null;
@@ -4,11 +4,11 @@ import { correctZYTuple } from "../core/blitz/correctZYTuple";
import { nameToArmorId } from "../core/blitzkit/nameToArmorId"; import { nameToArmorId } from "../core/blitzkit/nameToArmorId";
import { resolveArmor } from "../core/blitzkit/resolveThickness"; import { resolveArmor } from "../core/blitzkit/resolveThickness";
import { useArmor } from "../hooks/useArmor"; import { useArmor } from "../hooks/useArmor";
import { useConsumable } from "../hooks/useConsumable";
import { DuelModule, useDuel } from "../hooks/useDuel";
import { useModel } from "../hooks/useModel"; import { useModel } from "../hooks/useModel";
import { useTankModelDefinition } from "../hooks/useTankModelDefinition";
import { useTankTransform } from "../hooks/useTankTransform"; import { useTankTransform } from "../hooks/useTankTransform";
import { Duel } from "../stores/duel"; import { Tankopedia } from "../stores/tankopedia";
import { ModelTankWrapper } from "./ModelTankWrapper";
import { SpacedArmorSceneComponent } from "./SpacedArmorSceneComponent"; import { SpacedArmorSceneComponent } from "./SpacedArmorSceneComponent";
export enum ArmorType { export enum ArmorType {
@@ -22,18 +22,19 @@ interface SpacedArmorSceneProps {
} }
export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => { export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
const wrapper = useRef<Group>(null);
const turretContainer = useRef<Group>(null!); const turretContainer = useRef<Group>(null!);
const gunContainer = useRef<Group>(null!); const gunContainer = useRef<Group>(null!);
const tank = Duel.use((state) => state.protagonist.tank); const tank = useDuel("protagonist", DuelModule.Tank);
const track = Duel.use((state) => state.protagonist.track); const track = useDuel("protagonist", DuelModule.Track);
const turret = Duel.use((state) => state.protagonist.turret); const turret = useDuel("protagonist", DuelModule.Turret);
const gun = Duel.use((state) => state.protagonist.gun); const gun = useDuel("protagonist", DuelModule.Gun);
const { gltf: armorGltf } = useArmor(tank.id); const { gltf: armorGltf } = useArmor(tank.id);
const { gltf: modelGltf } = useModel(tank.id); const { gltf: modelGltf } = useModel(tank.id);
const armorNodes = Object.values(armorGltf.nodes); const armorNodes = Object.values(armorGltf.nodes);
const modelNodes = Object.values(modelGltf.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 trackModelDefinition = tankModelDefinition.tracks[track.id];
const turretModelDefinition = tankModelDefinition.turrets[turret.id]; const turretModelDefinition = tankModelDefinition.turrets[turret.id];
const gunModelDefinition = turretModelDefinition.guns[gun.id]; const gunModelDefinition = turretModelDefinition.guns[gun.id];
@@ -44,14 +45,12 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
gunModelDefinition.mask === undefined gunModelDefinition.mask === undefined
? undefined ? undefined
: gunModelDefinition.mask + hullOrigin.y + turretOrigin.y + gunOrigin.y; : gunModelDefinition.mask + hullOrigin.y + turretOrigin.y + gunOrigin.y;
const isDynamicArmorActive = Duel.use((state) => const isDynamicArmorActive = useConsumable("protagonist", 73);
state.protagonist.consumables.includes(73),
);
useTankTransform(track, turret, turretContainer, gunContainer); useTankTransform(track, turret, turretContainer, gunContainer);
return ( return (
<ModelTankWrapper ref={wrapper}> <>
<group position={hullOrigin}> <group position={hullOrigin}>
{armorNodes.map((node) => { {armorNodes.map((node) => {
const isHull = node.name.startsWith("hull_"); const isHull = node.name.startsWith("hull_");
@@ -199,6 +198,6 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
})} })}
</group> </group>
</group> </group>
</ModelTankWrapper> </>
); );
}); });
@@ -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));
}
+6 -9
View File
@@ -1,11 +1,7 @@
import { createDefaultSkills } from "@blitzkit/core"; import { createDefaultSkills } from "@blitzkit/core";
import type { import type { ShellDefinition, TankDefinition } from "@blitzkit/protos";
ModelDefinition,
ShellDefinition,
TankDefinition,
} from "@blitzkit/protos";
import type { Vector3 } from "three";
import { Soapstone } from "soapstone"; import { Soapstone } from "soapstone";
import type { Vector3 } from "three";
import { api } from "../api/dynamic"; import { api } from "../api/dynamic";
import type { ArmorType } from "../components/SpacedArmorScene"; import type { ArmorType } from "../components/SpacedArmorScene";
import type { ExternalModuleVariant } from "../components/SpacedArmorSceneComponent"; import type { ExternalModuleVariant } from "../components/SpacedArmorSceneComponent";
@@ -85,7 +81,6 @@ interface Tankopedia {
protagonist: TankState; protagonist: TankState;
antagonist: TankState; antagonist: TankState;
model: ModelDefinition;
equalize: boolean; equalize: boolean;
@@ -117,7 +112,8 @@ interface Tankopedia {
const skills = await api.skills(); const skills = await api.skills();
const models = await api.models(); const models = await api.models();
export const Tankopedia = new Soapstone<Tankopedia, [TankDefinition]>((tank) => ({ export const Tankopedia = new Soapstone<Tankopedia, [TankDefinition]>(
(tank) => ({
disturbed: false, disturbed: false,
revealed: false, revealed: false,
@@ -133,4 +129,5 @@ export const Tankopedia = new Soapstone<Tankopedia, [TankDefinition]>((tank) =>
xpMultiplier: 1, xpMultiplier: 1,
requestedDisplay: TankopediaDisplay.Model, requestedDisplay: TankopediaDisplay.Model,
display: TankopediaDisplay.Model, display: TankopediaDisplay.Model,
})); }),
);