feat: united duel data

This commit is contained in:
TrèsAbhi committed 2024-02-22 16:41:42 -06:00
1 parent da767213cb
commit 7e92f8ac50
23 files changed
+249 -249

No files matched your search

@@ -21,13 +21,13 @@ import {
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
import {
mutateTankopediaTemporary,
useTankopediaTemporary,
useTankopediaPersistent,
} from '../../../../../../stores/tankopedia';
import { TankSearch } from '../../../components/TankSearch';
export function AntagonistBar() {
const antagonist = useDuel((state) => state.antagonist!);
const mode = useTankopediaTemporary((state) => state.mode);
const mode = useTankopediaPersistent((state) => state.mode);
const [tab, setTab] = useState('search');
const [antagonistSelectorOpen, setAntagonistSelectorVisible] =
useState(false);
@@ -4,17 +4,13 @@ import { ConsumableButton } from '../../../../../../../components/ModuleButtons/
import { checkConsumableProvisionInclusivity } from '../../../../../../../core/blitzkrieg/checkConsumableProvisionInclusivity';
import { consumableDefinitions } from '../../../../../../../core/blitzkrieg/consumableDefinitions';
import { useEquipment } from '../../../../../../../hooks/useEquipment';
import { useDuel } from '../../../../../../../stores/duel';
import {
mutateTankopediaTemporary,
useTankopediaTemporary,
} from '../../../../../../../stores/tankopedia';
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
export function Consumables() {
const protagonist = useDuel((state) => state.protagonist!);
const awaitedConsumableDefinitions = use(consumableDefinitions);
const consumables = useTankopediaTemporary((state) => state.consumables);
const consumables = useDuel((state) => state.protagonist!.consumables);
const consumablesList = Object.values(awaitedConsumableDefinitions).filter(
(consumable) =>
checkConsumableProvisionInclusivity(
@@ -23,8 +19,8 @@ export function Consumables() {
protagonist.gun,
),
);
const cooldownBooster = useTankopediaTemporary(
(state) => state.cooldownBooster,
const cooldownBooster = useDuel(
(state) => state.protagonist!.cooldownBooster,
);
const hasConsumableDeliverySystem = useEquipment(118);
const hasHighEndConsumables = useEquipment(101);
@@ -59,13 +55,14 @@ export function Consumables() {
consumable={consumable.id}
selected={selected}
onClick={() => {
mutateTankopediaTemporary((draft) => {
mutateDuel((draft) => {
if (selected) {
draft.consumables = draft.consumables.filter(
(id) => id !== consumable.id,
);
draft.protagonist!.consumables =
draft.protagonist!.consumables.filter(
(id) => id !== consumable.id,
);
} else {
draft.consumables.push(consumable.id);
draft.protagonist!.consumables.push(consumable.id);
}
});
}}
@@ -2,11 +2,7 @@ import { Flex, Heading } from '@radix-ui/themes';
import { use } from 'react';
import { EquipmentButton } from '../../../../../../../components/ModuleButtons/EquipmentButton';
import { equipmentDefinitions } from '../../../../../../../core/blitzkrieg/equipmentDefinitions';
import { useDuel } from '../../../../../../../stores/duel';
import {
mutateTankopediaTemporary,
useTankopediaTemporary,
} from '../../../../../../../stores/tankopedia';
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
export function Equipments() {
@@ -14,9 +10,7 @@ export function Equipments() {
const awaitedEquipmentDefinitions = use(equipmentDefinitions);
const equipmentRows =
awaitedEquipmentDefinitions.presets[protagonist.tank.equipment];
const equipmentMatrix = useTankopediaTemporary(
(state) => state.equipmentMatrix,
);
const equipmentMatrix = useDuel((state) => state.protagonist!.equipment);
return (
<ConfigurationChildWrapper>
@@ -33,11 +27,12 @@ export function Equipments() {
rowChild
selected={equipmentMatrix[rowIndex][columnIndex] === -1}
onClick={() => {
mutateTankopediaTemporary((draft) => {
mutateDuel((draft) => {
if (equipmentMatrix[rowIndex][columnIndex] === -1) {
draft.equipmentMatrix[rowIndex][columnIndex] = 0;
draft.protagonist!.equipment[rowIndex][columnIndex] = 0;
} else {
draft.equipmentMatrix[rowIndex][columnIndex] = -1;
draft.protagonist!.equipment[rowIndex][columnIndex] =
-1;
}
});
}}
@@ -48,11 +43,11 @@ export function Equipments() {
rowChild
selected={equipmentMatrix[rowIndex][columnIndex] === 1}
onClick={() => {
mutateTankopediaTemporary((draft) => {
mutateDuel((draft) => {
if (equipmentMatrix[rowIndex][columnIndex] === 1) {
draft.equipmentMatrix[rowIndex][columnIndex] = 0;
draft.protagonist!.equipment[rowIndex][columnIndex] = 0;
} else {
draft.equipmentMatrix[rowIndex][columnIndex] = 1;
draft.protagonist!.equipment[rowIndex][columnIndex] = 1;
}
});
}}
@@ -3,19 +3,15 @@ import { clamp, debounce } from 'lodash';
import { useEffect, useMemo, useRef, useState } from 'react';
import { GenericTankComponentButton } from '../../../../../../../components/ModuleButtons/GenericTankComponentButton';
import { asset } from '../../../../../../../core/blitzkrieg/asset';
import { useDuel } from '../../../../../../../stores/duel';
import {
mutateTankopediaTemporary,
useTankopediaTemporary,
} from '../../../../../../../stores/tankopedia';
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
export function Miscellaneous() {
const camouflage = useTankopediaTemporary((state) => state.camouflage);
const cooldownBooster = useTankopediaTemporary(
(state) => state.cooldownBooster,
const camouflage = useDuel((state) => state.protagonist!.camouflage);
const cooldownBooster = useDuel(
(state) => state.protagonist!.cooldownBooster,
);
const crewMastery = useTankopediaTemporary((state) => state.crewMastery);
const crewMastery = useDuel((state) => state.protagonist!.crewMastery);
const crewInput = useRef<HTMLInputElement>(null);
const [crewMasteryDraft, setCrewMasteryDraft] = useState(crewMastery);
const { tank } = useDuel((state) => state.protagonist!);
@@ -23,8 +19,8 @@ export function Miscellaneous() {
const debouncedApplyDraft = useMemo(
() =>
debounce((value) => {
mutateTankopediaTemporary((draft) => {
draft.crewMastery = value;
mutateDuel((draft) => {
draft.protagonist!.crewMastery = value;
});
}, 500),
[],
@@ -53,8 +49,8 @@ export function Miscellaneous() {
first
last
onClick={() => {
mutateTankopediaTemporary((draft) => {
draft.camouflage = !camouflage;
mutateDuel((draft) => {
draft.protagonist!.camouflage = !camouflage;
});
}}
/>
@@ -77,9 +73,10 @@ export function Miscellaneous() {
transform: 'translate(-50%, -50%) scale(0.8)',
}}
onClick={() => {
mutateTankopediaTemporary((draft) => {
draft.cooldownBooster++;
if (draft.cooldownBooster === 4) draft.cooldownBooster = 0;
mutateDuel((draft) => {
draft.protagonist!.cooldownBooster++;
if (draft.protagonist!.cooldownBooster === 4)
draft.protagonist!.cooldownBooster = 0;
});
}}
/>
@@ -106,8 +103,12 @@ export function Miscellaneous() {
return;
}
mutateTankopediaTemporary((draft) => {
draft.crewMastery = clamp(newValue / 100, 0.5, 1);
mutateDuel((draft) => {
draft.protagonist!.crewMastery = clamp(
newValue / 100,
0.5,
1,
);
});
}}
onKeyUp={(event) => {
@@ -3,16 +3,12 @@ import { use } from 'react';
import { ProvisionButton } from '../../../../../../../components/ModuleButtons/ProvisionButton';
import { availableProvisions } from '../../../../../../../core/blitzkrieg/availableProvisions';
import { provisionDefinitions } from '../../../../../../../core/blitzkrieg/provisionDefinitions';
import { useDuel } from '../../../../../../../stores/duel';
import {
mutateTankopediaTemporary,
useTankopediaTemporary,
} from '../../../../../../../stores/tankopedia';
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
export function Provisions() {
const { tank, gun } = useDuel((state) => state.protagonist!);
const provisions = useTankopediaTemporary((state) => state.provisions);
const provisions = useDuel((state) => state.protagonist!.provisions);
const awaitedProvisionDefinitions = use(provisionDefinitions);
const provisionsList = availableProvisions(
tank,
@@ -38,13 +34,14 @@ export function Provisions() {
provision={provision.id}
selected={selected}
onClick={() => {
mutateTankopediaTemporary((draft) => {
mutateDuel((draft) => {
if (selected) {
draft.provisions = draft.provisions.filter(
(id) => id !== provision.id,
);
draft.protagonist!.provisions =
draft.protagonist!.provisions.filter(
(id) => id !== provision.id,
);
} else {
draft.provisions.push(provision.id);
draft.protagonist!.provisions.push(provision.id);
}
});
}}
@@ -24,7 +24,6 @@ import { useEquipment } from '../../../../../../hooks/useEquipment';
import { useProvision } from '../../../../../../hooks/useProvision';
import { useProvisions } from '../../../../../../hooks/useProvisions';
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
import { useTankopediaTemporary } from '../../../../../../stores/tankopedia';
import { Info } from './components/Info';
import { InfoWithDelta } from './components/InfoWithDelta';
@@ -35,7 +34,7 @@ export function Characteristics() {
);
const hasImprovedVentilation = useEquipment(102);
const provisions = useProvisions();
const crewMastery = useTankopediaTemporary((state) => state.crewMastery);
const crewMastery = useDuel((state) => state.protagonist!.crewMastery);
const provisionCrewBonus =
provisions.reduce(
(total, provision) =>
@@ -67,7 +66,7 @@ export function Characteristics() {
stockTurret.weight +
stockGun.weight;
const [penetrationDistance, setPenetrationDistance] = useState(250);
const camouflage = useTankopediaTemporary((state) => state.camouflage);
const camouflage = useDuel((state) => state.protagonist!.camouflage);
const hasRammer = useEquipment(100);
const hasCalibratedShells = useEquipment(103);
const hasEnhancedGunLayingDrive = useEquipment(104);
@@ -11,11 +11,11 @@ import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTran
import { Pose, poseEvent } from '../../../../../../core/blitzkrieg/pose';
import { tankIcon } from '../../../../../../core/blitzkrieg/tankIcon';
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
import { useDuel } from '../../../../../../stores/duel';
import {
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
import mutateTankopediaPersistent, {
TankopediaMode,
mutateTankopediaTemporary,
useTankopediaTemporary,
useTankopediaPersistent,
} from '../../../../../../stores/tankopedia';
import { Controls } from '../Control';
import { Lighting } from '../Lighting';
@@ -33,7 +33,7 @@ export function TankSandbox() {
const awaitedModelDefinitions = use(modelDefinitions);
const canvasWrapper = useRef<HTMLDivElement>(null);
const [isFullScreen, setIsFullScreen] = useState(false);
const mode = useTankopediaTemporary((state) => state.mode);
const mode = useTankopediaPersistent((state) => state.mode);
const protagonist = useDuel((state) => state.protagonist!);
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
const turretModelDefinition =
@@ -65,7 +65,7 @@ export function TankSandbox() {
function handlePoseEvent(pose: Pose) {
switch (pose) {
case Pose.HullDown: {
mutateTankopediaTemporary((draft) => {
mutateDuel((draft) => {
const [pitch, yaw] = applyPitchYawLimits(
-Infinity,
0,
@@ -74,15 +74,15 @@ export function TankSandbox() {
);
modelTransformEvent.emit({ pitch, yaw });
draft.model.pose.pitch = pitch;
draft.model.pose.yaw = yaw;
draft.protagonist!.pitch = pitch;
draft.protagonist!.yaw = yaw;
});
break;
}
case Pose.FaceHug: {
mutateTankopediaTemporary((draft) => {
mutateDuel((draft) => {
const [pitch, yaw] = applyPitchYawLimits(
Infinity,
0,
@@ -91,15 +91,15 @@ export function TankSandbox() {
);
modelTransformEvent.emit({ pitch, yaw });
draft.model.pose.pitch = pitch;
draft.model.pose.yaw = yaw;
draft.protagonist!.pitch = pitch;
draft.protagonist!.yaw = yaw;
});
break;
}
case Pose.Default:
mutateTankopediaTemporary((draft) => {
mutateDuel((draft) => {
const [pitch, yaw] = applyPitchYawLimits(
0,
0,
@@ -108,8 +108,8 @@ export function TankSandbox() {
);
modelTransformEvent.emit({ pitch, yaw });
draft.model.pose.pitch = pitch;
draft.model.pose.yaw = yaw;
draft.protagonist!.pitch = pitch;
draft.protagonist!.yaw = yaw;
});
break;
@@ -126,10 +126,10 @@ export function TankSandbox() {
});
useEffect(() => {
mutateTankopediaTemporary((draft) => {
[draft.model.pose.pitch, draft.model.pose.yaw] = applyPitchYawLimits(
draft.model.pose.pitch,
draft.model.pose.yaw,
mutateDuel((draft) => {
[draft.protagonist!.pitch, draft.protagonist!.yaw] = applyPitchYawLimits(
draft.protagonist!.pitch,
draft.protagonist!.yaw,
gunModelDefinition.pitch,
turretModelDefinition.yaw,
);
@@ -157,7 +157,7 @@ export function TankSandbox() {
<Tabs.Root
value={mode}
onValueChange={(mode) => {
mutateTankopediaTemporary((draft) => {
mutateTankopediaPersistent((draft) => {
draft.mode = mode as TankopediaMode;
});
}}
@@ -12,7 +12,7 @@ import { resolveArmor } from '../../../../../../../../../core/blitzkrieg/resolve
import { useArmor } from '../../../../../../../../../hooks/useArmor';
import { useModelDefinitions } from '../../../../../../../../../hooks/useModelDefinitions';
import { useDuel } from '../../../../../../../../../stores/duel';
import { useTankopediaTemporary } from '../../../../../../../../../stores/tankopedia';
import { useTankopediaPersistent } from '../../../../../../../../../stores/tankopedia';
export function ArmorHighlighting() {
const protagonist = useDuel((state) => state.protagonist!);
@@ -20,7 +20,7 @@ export function ArmorHighlighting() {
const modelDefinitions = useModelDefinitions();
const gunContainer = useRef<Group>(null);
const turretContainer = useRef<Group>(null);
const initialTankopediaState = useTankopediaTemporary.getState();
const initialTankopediaState = useTankopediaPersistent.getState();
useEffect(() => {
const hullOrigin = new Vector3(
@@ -80,14 +80,14 @@ export function ArmorHighlighting() {
turretContainer.current?.position.copy(turretPosition);
turretContainer.current?.rotation.copy(turretRotation);
}
const unsubscribe = useTankopediaTemporary.subscribe(
const unsubscribe = useTankopediaPersistent.subscribe(
(state) => state.mode,
(mode) => {
if (wrapper.current) wrapper.current.visible = mode === 'armor';
},
);
handleModelTransform(useTankopediaTemporary.getState().model.pose);
handleModelTransform(useDuel.getState().protagonist!);
modelTransformEvent.on(handleModelTransform);
return () => {
@@ -13,7 +13,7 @@ import { useArmor } from '../../../../../../../../../hooks/useArmor';
import { useModel } from '../../../../../../../../../hooks/useModel';
import { useModelDefinitions } from '../../../../../../../../../hooks/useModelDefinitions';
import { useDuel } from '../../../../../../../../../stores/duel';
import { useTankopediaTemporary } from '../../../../../../../../../stores/tankopedia';
import { useTankopediaPersistent } from '../../../../../../../../../stores/tankopedia';
interface ExternalModuleMaskProps {
ornamental?: boolean;
@@ -33,7 +33,7 @@ export const ExternalModuleMask = memo<ExternalModuleMaskProps>(
const modelDefinitions = useModelDefinitions();
const turretContainer = useRef<Group>(null);
const gunContainer = useRef<Group>(null);
const initialTankopediaState = useTankopediaTemporary.getState();
const initialTankopediaState = useTankopediaPersistent.getState();
useEffect(() => {
const hullOrigin = new Vector3(
@@ -102,7 +102,7 @@ export const ExternalModuleMask = memo<ExternalModuleMaskProps>(
turretContainer.current?.rotation.copy(turretRotation);
}
handleModelTransform(useTankopediaTemporary.getState().model.pose);
handleModelTransform(useDuel.getState().protagonist!);
modelTransformEvent.on(handleModelTransform);
return () => {
@@ -111,7 +111,7 @@ export const ExternalModuleMask = memo<ExternalModuleMaskProps>(
});
useEffect(() => {
const unsubscribe = useTankopediaTemporary.subscribe(
const unsubscribe = useTankopediaPersistent.subscribe(
(state) => state.mode,
(mode) => {
if (wrapper.current) wrapper.current.visible = mode === 'armor';
@@ -13,7 +13,7 @@ import { useArmor } from '../../../../../../../../../hooks/useArmor';
import { useModel } from '../../../../../../../../../hooks/useModel';
import { useModelDefinitions } from '../../../../../../../../../hooks/useModelDefinitions';
import { useDuel } from '../../../../../../../../../stores/duel';
import { useTankopediaTemporary } from '../../../../../../../../../stores/tankopedia';
import { useTankopediaPersistent } from '../../../../../../../../../stores/tankopedia';
interface SpacedArmorDepthProps {
ornamental?: boolean;
@@ -37,7 +37,7 @@ export const SpacedArmorDepth = memo<SpacedArmorDepthProps>(
const modelDefinitions = useModelDefinitions();
const turretContainer = useRef<Group>(null);
const gunContainer = useRef<Group>(null);
const initialTankopediaState = useTankopediaTemporary.getState();
const initialTankopediaState = useTankopediaPersistent.getState();
useEffect(() => {
if (!modelDefinitions) return;
@@ -108,7 +108,7 @@ export const SpacedArmorDepth = memo<SpacedArmorDepthProps>(
turretContainer.current?.rotation.copy(turretRotation);
}
handleModelTransform(useTankopediaTemporary.getState().model.pose);
handleModelTransform(useDuel.getState().protagonist!);
modelTransformEvent.on(handleModelTransform);
return () => {
@@ -117,7 +117,7 @@ export const SpacedArmorDepth = memo<SpacedArmorDepthProps>(
});
useEffect(() => {
const unsubscribe = useTankopediaTemporary.subscribe(
const unsubscribe = useTankopediaPersistent.subscribe(
(state) => state.mode,
(mode) => {
if (wrapper.current) wrapper.current.visible = mode === 'armor';
@@ -15,10 +15,9 @@ import {
} from '../../../../../../../core/blitzkrieg/modelTransform';
import { normalizeAnglePI } from '../../../../../../../core/math/normalizeAngle180';
import { useModel } from '../../../../../../../hooks/useModel';
import { useDuel } from '../../../../../../../stores/duel';
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
import mutateTankopediaPersistent, {
mutateTankopediaTemporary,
useTankopediaTemporary,
} from '../../../../../../../stores/tankopedia';
export const TankModel = memo(() => {
@@ -27,7 +26,6 @@ export const TankModel = memo(() => {
>(undefined);
const protagonist = useDuel((draft) => draft.protagonist!);
const canvas = useThree((state) => state.gl.domElement);
const physical = useTankopediaTemporary((state) => state.model.pose);
const hullContainer = useRef<Group>(null);
const turretContainer = useRef<Group>(null);
const gunContainer = useRef<Group>(null);
@@ -156,8 +154,8 @@ export const TankModel = memo(() => {
event.stopPropagation();
if (isTurret) {
yaw = physical.yaw;
pitch = physical.pitch;
yaw = protagonist.yaw;
pitch = protagonist.pitch;
mutateTankopediaPersistent((draft) => {
draft.model.visual.controlsEnabled = false;
@@ -179,9 +177,9 @@ export const TankModel = memo(() => {
modelTransformEvent.emit({ pitch, yaw });
}
function handlePointerUp() {
mutateTankopediaTemporary((draft) => {
draft.model.pose.pitch = normalizeAnglePI(pitch);
draft.model.pose.yaw = normalizeAnglePI(yaw);
mutateDuel((draft) => {
draft.protagonist!.pitch = normalizeAnglePI(pitch);
draft.protagonist!.yaw = normalizeAnglePI(yaw);
});
mutateTankopediaPersistent((draft) => {
draft.model.visual.controlsEnabled = true;
@@ -223,8 +221,8 @@ export const TankModel = memo(() => {
mutateTankopediaTemporary((draft) => {
draft.shot = undefined;
});
pitch = physical.pitch;
yaw = physical.yaw;
pitch = protagonist.pitch;
yaw = protagonist.yaw;
window.addEventListener('pointermove', handlePointerMove);
window.addEventListener('pointerup', handlePointerUp);
}
@@ -241,9 +239,9 @@ export const TankModel = memo(() => {
mutateTankopediaPersistent((draft) => {
draft.model.visual.controlsEnabled = true;
});
mutateTankopediaTemporary((draft) => {
draft.model.pose.pitch = normalizeAnglePI(pitch);
draft.model.pose.yaw = normalizeAnglePI(yaw);
mutateDuel((draft) => {
draft.protagonist!.pitch = normalizeAnglePI(pitch);
draft.protagonist!.yaw = normalizeAnglePI(yaw);
});
window.removeEventListener('pointermove', handlePointerMove);
window.removeEventListener('pointerup', handlePointerUp);
@@ -4,33 +4,29 @@ import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawL
import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions';
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
import { useEquipment } from '../../../../../../hooks/useEquipment';
import { useDuel } from '../../../../../../stores/duel';
import {
mutateTankopediaTemporary,
useTankopediaTemporary,
} from '../../../../../../stores/tankopedia';
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
import { useTankopediaPersistent } from '../../../../../../stores/tankopedia';
import { QuickEquipmentButton } from './components/QuickEquipmentButton';
export function RotationInputs() {
const protagonist = useDuel((state) => state.protagonist!);
const physical = useTankopediaTemporary((state) => state.model.pose);
const awaitedModelDefinitions = use(modelDefinitions);
const turretYawInput = useRef<HTMLInputElement>(null);
const gunPitchInput = useRef<HTMLInputElement>(null);
const mode = useTankopediaTemporary((state) => state.mode);
const hasCalibratedShells = useEquipment(103);
const mode = useTankopediaPersistent((state) => state.mode);
const hasCalibratedShells = useEquipment(103, true);
const hasEnhancedArmor = useEquipment(110);
useEffect(() => {
turretYawInput.current!.value = `${-Math.round(
physical.yaw * (180 / Math.PI),
protagonist.yaw * (180 / Math.PI),
)}`;
}, [physical.yaw]);
}, [protagonist.yaw]);
useEffect(() => {
gunPitchInput.current!.value = `${-Math.round(
physical.pitch * (180 / Math.PI),
protagonist.pitch * (180 / Math.PI),
)}`;
}, [physical.pitch]);
}, [protagonist.pitch]);
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
const turretModelDefinition =
@@ -68,18 +64,18 @@ export function RotationInputs() {
Yaw
</TextField.Slot>
<TextField.Input
defaultValue={Math.round(physical.yaw * (180 / Math.PI))}
defaultValue={Math.round(protagonist.yaw * (180 / Math.PI))}
onBlur={() => {
const [pitch, yaw] = applyPitchYawLimits(
physical.pitch,
protagonist.pitch,
-Number(turretYawInput.current?.value) * (Math.PI / 180),
gunModelDefinition.pitch,
turretModelDefinition.yaw,
);
modelTransformEvent.emit({ pitch, yaw });
mutateTankopediaTemporary((state) => {
state.model.pose.pitch = pitch;
state.model.pose.yaw = yaw;
useDuel((state) => {
state.protagonist!.pitch = pitch;
state.protagonist!.yaw = yaw;
});
turretYawInput.current!.value = `${Math.round(
yaw * (180 / Math.PI),
@@ -116,18 +112,18 @@ export function RotationInputs() {
Pitch
</TextField.Slot>
<TextField.Input
defaultValue={-Math.round(physical.pitch * (180 / Math.PI))}
defaultValue={-Math.round(protagonist.pitch * (180 / Math.PI))}
onBlur={() => {
const [pitch, yaw] = applyPitchYawLimits(
-Number(gunPitchInput.current?.value) * (Math.PI / 180),
physical.yaw,
protagonist.yaw,
gunModelDefinition.pitch,
turretModelDefinition.yaw,
);
modelTransformEvent.emit({ pitch, yaw });
mutateTankopediaTemporary((state) => {
state.model.pose.pitch = pitch;
state.model.pose.yaw = yaw;
mutateDuel((state) => {
state.protagonist!.pitch = pitch;
state.protagonist!.yaw = yaw;
});
gunPitchInput.current!.value = `${Math.round(
pitch * (180 / Math.PI),
@@ -158,8 +154,8 @@ export function RotationInputs() {
equipment={103}
active={hasCalibratedShells}
onClick={() => {
mutateTankopediaTemporary((draft) => {
draft.equipmentMatrix[0][0] = hasCalibratedShells ? 0 : 1;
mutateDuel((draft) => {
draft.antagonist!.equipment[0][0] = hasCalibratedShells ? 0 : 1;
});
}}
/>
@@ -167,8 +163,8 @@ export function RotationInputs() {
equipment={110}
active={hasEnhancedArmor}
onClick={() => {
mutateTankopediaTemporary((draft) => {
draft.equipmentMatrix[1][1] = hasEnhancedArmor ? 0 : -1;
mutateDuel((draft) => {
draft.protagonist!.equipment[1][1] = hasEnhancedArmor ? 0 : -1;
});
}}
/>
+5 -43
View File
@@ -1,11 +1,9 @@
'use client';
import { Flex } from '@radix-ui/themes';
import { use, useEffect } from 'react';
import { useEffect } from 'react';
import PageWrapper from '../../../../components/PageWrapper';
import { availableProvisions } from '../../../../core/blitzkrieg/availableProvisions';
import { provisionDefinitions } from '../../../../core/blitzkrieg/provisionDefinitions';
import { tankDefinitions } from '../../../../core/blitzkrieg/tankDefinitions';
import { assignDuelMember } from '../../../../core/blitzkrieg/assignDuelMember';
import { useWideFormat } from '../../../../hooks/useWideFormat';
import { mutateDuel, useDuel } from '../../../../stores/duel';
import { mutateTankopediaTemporary } from '../../../../stores/tankopedia';
@@ -20,26 +18,12 @@ import { TankSandbox } from './components/Model/TankSandbox';
import { Title } from './components/Title';
export default function Page({ params }: { params: { id: string } }) {
const id = parseInt(params.id);
const awaitedTankDefinitions = use(tankDefinitions);
const tank = awaitedTankDefinitions[id];
const gun = tank.turrets.at(-1)!.guns.at(-1)!;
const initialId = parseInt(params.id);
const assigned = useDuel((state) => state.assigned);
const wideFormat = useWideFormat();
useEffect(() => {
mutateDuel((draft) => {
draft.assigned = true;
draft.protagonist = {
tank,
engine: tank.engines.at(-1)!,
turret: tank.turrets.at(-1)!,
gun,
shell: tank.turrets.at(-1)!.guns.at(-1)!.shells[0],
track: tank.tracks.at(-1)!,
};
draft.antagonist = { ...draft.protagonist };
});
assignDuelMember('both', initialId);
function handleKeyDown(event: KeyboardEvent) {
if (document.activeElement instanceof HTMLInputElement) return;
@@ -72,34 +56,12 @@ export default function Page({ params }: { params: { id: string } }) {
}
}
(async () => {
const provisionsList = availableProvisions(
tank,
gun,
await provisionDefinitions,
);
mutateTankopediaTemporary((draft) => {
draft.model.pose.yaw = 0;
draft.model.pose.pitch = 0;
draft.consumables = [];
draft.provisions = provisionsList
.filter((provision) => provision.crew !== undefined)
.map((provision) => provision.id);
draft.shot = undefined;
draft.equipmentMatrix = [
[1, -1, -1],
[0, 0, 0],
[0, 0, 0],
];
});
})();
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [id, assigned]);
}, [initialId, assigned]);
return (
<PageWrapper color="purple" size="double">