feat: upgrade tankopedia stores

This commit is contained in:
TrèsAbhi committed 2024-07-09 14:43:33 -05:00
1 parent 5bf9f8ca9e
commit 84bbb05d43
26 files changed
+356 -356

No files matched your search

@@ -11,7 +11,7 @@ import { resolveArmor } from '../../../core/blitzkit/resolveThickness';
import { useArmor } from '../../../hooks/useArmor';
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
import { useDuel } from '../../../stores/duel';
import { useTankopediaPersistent } from '../../../stores/tankopedia';
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
import { CoreArmorSceneComponent } from './CoreArmorSceneComponent';
import { ShotDisplay } from './ShotDisplay';
@@ -20,7 +20,8 @@ export const CoreArmorScene = memo(() => {
const modelDefinitions = useModelDefinitions();
const turretContainer = useRef<Group>(null);
const gunContainer = useRef<Group>(null);
const initialTankopediaState = useTankopediaPersistent.getState();
const tankopediaPersistentStore = TankopediaPersistent.useStore();
const initialTankopediaState = tankopediaPersistentStore.getState();
const protagonist = useDuel((draft) => draft.protagonist!);
useEffect(() => {
@@ -99,7 +100,7 @@ export const CoreArmorScene = memo(() => {
});
useEffect(() => {
const unsubscribe = useTankopediaPersistent.subscribe(
const unsubscribe = tankopediaPersistentStore.subscribe(
(state) => state.mode,
(mode) => {
if (wrapper.current) wrapper.current.visible = mode === 'armor';
@@ -10,10 +10,7 @@ import { hasEquipment } from '../../../../core/blitzkit/hasEquipment';
import { jsxTree } from '../../../../core/blitzkit/jsxTree';
import { ShellDefinition } from '../../../../core/blitzkit/tankDefinitions';
import { EquipmentMatrix, useDuel } from '../../../../stores/duel';
import {
TankopediaPersistent,
useTankopediaPersistent,
} from '../../../../stores/tankopedia';
import * as TankopediaPersistent from '../../../../stores/tankopediaPersistent';
import fragmentShader from './shaders/fragment.glsl';
import vertexShader from './shaders/vertex.glsl';
import { spacedArmorRenderTarget } from './target';
@@ -31,6 +28,7 @@ export function CoreArmorSceneComponent({
node,
thickness,
}: CoreArmorSceneComponentProps) {
const tankopediaPersistentStore = TankopediaPersistent.useStore();
const material = new ShaderMaterial({
fragmentShader,
vertexShader,
@@ -77,7 +75,7 @@ export function CoreArmorSceneComponent({
await handleAntagonistEquipmentChange(duel.antagonist!.equipmentMatrix);
}
function handleVisualChange(
visual: TankopediaPersistent['model']['visual'],
visual: TankopediaPersistent.TankopediaPersistent['model']['visual'],
) {
material.uniforms.greenPenetration.value = visual.greenPenetration;
material.uniforms.opaque.value = visual.opaque || visual.wireframe;
@@ -113,7 +111,7 @@ export function CoreArmorSceneComponent({
}
handleShellChange(useDuel.getState().antagonist!.shell);
handleVisualChange(useTankopediaPersistent.getState().model.visual);
handleVisualChange(tankopediaPersistentStore.getState().model.visual);
handleProtagonistEquipmentChange(
useDuel.getState().protagonist!.equipmentMatrix,
);
@@ -123,7 +121,7 @@ export function CoreArmorSceneComponent({
const unsubscribes = [
useDuel.subscribe((state) => state.antagonist!.shell, handleShellChange),
useTankopediaPersistent.subscribe(
tankopediaPersistentStore.subscribe(
(state) => state.model.visual,
handleVisualChange,
),
@@ -4,15 +4,11 @@ import { useFrame } from '@react-three/fiber';
import { ComponentProps, useRef } from 'react';
import { Euler, Mesh, Quaternion } from 'three';
import { J_HAT } from '../../../constants/axis';
import {
ShotLayerNonExternal,
ShotStatus,
useTankopediaTemporary,
} from '../../../stores/tankopedia';
import * as TankopediaEphemeral from '../../../stores/tankopediaEphemeral';
import { ShotDisplayCard } from './ShotDisplayCard';
export const shotStatusColors: Record<
ShotStatus,
TankopediaEphemeral.ShotStatus,
ComponentProps<typeof Text>['color']
> = {
blocked: 'red',
@@ -27,7 +23,7 @@ const TRACER_THICK = 1 / 32;
const TRACER_THIN = TRACER_THICK / 2;
export function ShotDisplay() {
const shot = useTankopediaTemporary((state) => state.shot);
const shot = TankopediaEphemeral.use((state) => state.shot);
const inTracer = useRef<Mesh>(null);
const outTracer = useRef<Mesh>(null);
@@ -55,13 +51,16 @@ export function ShotDisplay() {
}, 0) + SHOT_DISPLAY_LENGTH_INFINITY;
const outLength =
shot.out && shot.out.layers.length > 0
? (shot.in.layers.at(-1) as ShotLayerNonExternal).point.distanceTo(
(shot.out.layers.at(-1) as ShotLayerNonExternal).point,
? (
shot.in.layers.at(-1) as TankopediaEphemeral.ShotLayerNonExternal
).point.distanceTo(
(shot.out.layers.at(-1) as TankopediaEphemeral.ShotLayerNonExternal)
.point,
)
: SHOT_DISPLAY_LENGTH_INFINITY;
const inLast = shot.in.layers.findLast(
(layer) => layer.type !== null,
) as ShotLayerNonExternal;
) as TankopediaEphemeral.ShotLayerNonExternal;
const outTitleColor = shot.out
? shotStatusColors[shot.out.status]
: undefined;
@@ -1,11 +1,7 @@
import { Card, Flex, Inset, Separator, Text } from '@radix-ui/themes';
import { ComponentProps } from 'react';
import { radToDeg } from 'three/src/math/MathUtils';
import {
ShotLayer,
ShotStatus,
useTankopediaTemporary,
} from '../../../stores/tankopedia';
import * as TankopediaEphemeral from '../../../stores/tankopediaEphemeral';
import { shotStatusColors } from './ShotDisplay';
import { ArmorType } from './SpacedArmorScene';
import { ExternalModuleVariant } from './SpacedArmorSceneComponent';
@@ -22,7 +18,7 @@ const externalLayerNames: Record<ExternalModuleVariant, string> = {
track: 'Tracks',
};
const shotStatusNames: Record<ShotStatus, string> = {
const shotStatusNames: Record<TankopediaEphemeral.ShotStatus, string> = {
blocked: 'Blocked',
ricochet: 'Ricochet',
penetration: 'penetration',
@@ -39,7 +35,7 @@ function LayerEntry({
layerIndex?: string;
shotStatusColor: ComponentProps<typeof Text>['color'];
layerName: string;
layer: ShotLayer;
layer: TankopediaEphemeral.ShotLayer;
angle?: number;
}) {
return (
@@ -113,7 +109,7 @@ function LayerEntry({
}
export function ShotDisplayCard() {
const shot = useTankopediaTemporary((state) => state.shot);
const shot = TankopediaEphemeral.use((state) => state.shot);
if (!shot) return null;
@@ -12,7 +12,7 @@ import { useArmor } from '../../../hooks/useArmor';
import { useModel } from '../../../hooks/useModel';
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
import { useDuel } from '../../../stores/duel';
import { useTankopediaPersistent } from '../../../stores/tankopedia';
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
import { SpacedArmorSceneComponent } from './SpacedArmorSceneComponent';
export enum ArmorType {
@@ -30,7 +30,8 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
const modelDefinitions = useModelDefinitions();
const turretContainer = useRef<Group>(null);
const gunContainer = useRef<Group>(null);
const initialTankopediaState = useTankopediaPersistent.getState();
const tankopediaPersistentStore = TankopediaPersistent.useStore();
const initialTankopediaState = tankopediaPersistentStore.getState();
const protagonist = useDuel((draft) => draft.protagonist!);
useEffect(() => {
@@ -109,7 +110,7 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
});
useEffect(() => {
const unsubscribe = useTankopediaPersistent.subscribe(
const unsubscribe = tankopediaPersistentStore.subscribe(
(state) => state.mode,
(mode) => {
if (wrapper.current) wrapper.current.visible = mode === 'armor';
@@ -17,12 +17,7 @@ import { hasEquipment } from '../../../../core/blitzkit/hasEquipment';
import { jsxTree } from '../../../../core/blitzkit/jsxTree';
import { ShellType } from '../../../../core/blitzkit/tankDefinitions';
import { useDuel } from '../../../../stores/duel';
import {
Shot,
ShotLayerBase,
ShotLayerNonExternal,
useTankopediaTemporary,
} from '../../../../stores/tankopedia';
import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral';
import { ArmorType } from '../SpacedArmorScene';
import { SpacedArmorSubExternal } from './components/SpacedArmorSubExternal';
import { SpacedArmorSubSpaced } from './components/SpacedArmorSubSpaced';
@@ -77,6 +72,7 @@ export function SpacedArmorSceneComponent({
clip,
...props
}: SpacedArmorSceneComponentProps) {
const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
const camera = useThree((state) => state.camera);
async function shoot(
@@ -88,7 +84,7 @@ export function SpacedArmorSceneComponent({
const { antagonist, protagonist } = useDuel.getState();
const shell = antagonist!.shell;
const cameraNormal = camera.position.clone().sub(point).normalize();
const shot: Shot = {
const shot: TankopediaEphemeral.Shot = {
damage: -1,
containsGaps: shell.type === ShellType.HEAT,
in: {
@@ -150,7 +146,9 @@ export function SpacedArmorSceneComponent({
);
if (shell.type === ShellType.HEAT && index > 0) {
const lastLayer = shot.in.layers.at(-1) as ShotLayerBase;
const lastLayer = shot.in.layers.at(
-1,
) as TankopediaEphemeral.ShotLayerBase;
const distance = lastLayer.point.distanceTo(intersection.point);
remainingPenetration -= 0.5 * remainingPenetration * distance;
const blocked = remainingPenetration <= 0;
@@ -244,8 +242,12 @@ export function SpacedArmorSceneComponent({
index++;
}
const lastLayer = shot.in.layers.at(-1) as ShotLayerNonExternal | undefined;
const firstLayer = shot.in.layers[0] as ShotLayerBase | undefined;
const lastLayer = shot.in.layers.at(-1) as
| TankopediaEphemeral.ShotLayerNonExternal
| undefined;
const firstLayer = shot.in.layers[0] as
| TankopediaEphemeral.ShotLayerBase
| undefined;
if (!lastLayer || !firstLayer) {
return null;
@@ -370,7 +372,7 @@ export function SpacedArmorSceneComponent({
true,
))!;
useTankopediaTemporary.setState({ shot });
tankopediaEphemeralStore.setState({ shot });
},
},
node.uuid,