feat: remove assertion

This commit is contained in:
TrèsAbhi committed 2024-07-10 13:11:09 -05:00
1 parent b0b68f3fd3
commit 74d4b8edf4
26 files changed
+172 -188

No files matched your search

@@ -17,9 +17,9 @@ import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
export function Consumables() { export function Consumables() {
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const protagonist = Duel.use((state) => state.protagonist!); const protagonist = Duel.use((state) => state.protagonist);
const awaitedConsumableDefinitions = use(consumableDefinitions); const awaitedConsumableDefinitions = use(consumableDefinitions);
const consumables = Duel.use((state) => state.protagonist!.consumables); const consumables = Duel.use((state) => state.protagonist.consumables);
const consumablesList = Object.values(awaitedConsumableDefinitions).filter( const consumablesList = Object.values(awaitedConsumableDefinitions).filter(
(consumable) => (consumable) =>
checkConsumableProvisionInclusivity( checkConsumableProvisionInclusivity(
@@ -29,7 +29,7 @@ export function Consumables() {
), ),
); );
const cooldownBooster = Duel.use( const cooldownBooster = Duel.use(
(state) => state.protagonist!.cooldownBooster, (state) => state.protagonist.cooldownBooster,
); );
const hasConsumableDeliverySystem = useEquipment(118); const hasConsumableDeliverySystem = useEquipment(118);
const hasHighEndConsumables = useEquipment(101); const hasHighEndConsumables = useEquipment(101);
@@ -61,7 +61,7 @@ export function Consumables() {
color="red" color="red"
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.consumables = []; draft.protagonist.consumables = [];
}); });
}} }}
> >
@@ -79,7 +79,7 @@ export function Consumables() {
timers timers
onChange={(consumables) => { onChange={(consumables) => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.consumables = consumables; draft.protagonist.consumables = consumables;
}); });
}} }}
/> />
@@ -7,12 +7,12 @@ import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
export function Equipment() { export function Equipment() {
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const protagonist = Duel.use((state) => state.protagonist!); const protagonist = Duel.use((state) => state.protagonist);
const awaitedEquipmentDefinitions = use(equipmentDefinitions); const awaitedEquipmentDefinitions = use(equipmentDefinitions);
const equipmentPreset = const equipmentPreset =
awaitedEquipmentDefinitions.presets[protagonist.tank.equipment]; awaitedEquipmentDefinitions.presets[protagonist.tank.equipment];
const equipmentMatrix = Duel.use( const equipmentMatrix = Duel.use(
(state) => state.protagonist!.equipmentMatrix, (state) => state.protagonist.equipmentMatrix,
); );
return ( return (
@@ -24,7 +24,7 @@ export function Equipment() {
color="red" color="red"
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.equipmentMatrix.forEach((row) => { draft.protagonist.equipmentMatrix.forEach((row) => {
row.forEach((_, index) => { row.forEach((_, index) => {
row[index] = 0; row[index] = 0;
}); });
@@ -41,7 +41,7 @@ export function Equipment() {
preset={equipmentPreset} preset={equipmentPreset}
onChange={(matrix) => { onChange={(matrix) => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.equipmentMatrix = matrix; draft.protagonist.equipmentMatrix = matrix;
}); });
}} }}
/> />
@@ -8,20 +8,20 @@ import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
export function Miscellaneous() { export function Miscellaneous() {
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const camouflage = Duel.use((state) => state.protagonist!.camouflage); const camouflage = Duel.use((state) => state.protagonist.camouflage);
const cooldownBooster = Duel.use( const cooldownBooster = Duel.use(
(state) => state.protagonist!.cooldownBooster, (state) => state.protagonist.cooldownBooster,
); );
const crewMastery = Duel.use((state) => state.protagonist!.crewMastery); const crewMastery = Duel.use((state) => state.protagonist.crewMastery);
const crewInput = useRef<HTMLInputElement>(null); const crewInput = useRef<HTMLInputElement>(null);
const [crewMasteryDraft, setCrewMasteryDraft] = useState(crewMastery); const [crewMasteryDraft, setCrewMasteryDraft] = useState(crewMastery);
const { tank } = Duel.use((state) => state.protagonist!); const { tank } = Duel.use((state) => state.protagonist);
const debouncedApplyDraft = useMemo( const debouncedApplyDraft = useMemo(
() => () =>
debounce((value) => { debounce((value) => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.crewMastery = value; draft.protagonist.crewMastery = value;
}); });
}, 500), }, 500),
[], [],
@@ -51,7 +51,7 @@ export function Miscellaneous() {
last last
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.camouflage = !camouflage; draft.protagonist.camouflage = !camouflage;
}); });
}} }}
/> />
@@ -75,9 +75,9 @@ export function Miscellaneous() {
}} }}
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.cooldownBooster++; draft.protagonist.cooldownBooster++;
if (draft.protagonist!.cooldownBooster === 4) if (draft.protagonist.cooldownBooster === 4)
draft.protagonist!.cooldownBooster = 0; draft.protagonist.cooldownBooster = 0;
}); });
}} }}
/> />
@@ -103,11 +103,7 @@ export function Miscellaneous() {
} }
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.crewMastery = clamp( draft.protagonist.crewMastery = clamp(newValue / 100, 0.5, 1);
newValue / 100,
0.5,
1,
);
}); });
}} }}
onKeyUp={(event) => { onKeyUp={(event) => {
@@ -118,16 +118,16 @@ function ModuleButton({
export function Modules() { export function Modules() {
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const awaitedTankDefinitions = use(tankDefinitions); const awaitedTankDefinitions = use(tankDefinitions);
const tank = Duel.use((state) => state.protagonist!.tank); const tank = Duel.use((state) => state.protagonist.tank);
const hasUpgrades = const hasUpgrades =
tank.turrets.length > 1 || tank.turrets.length > 1 ||
tank.turrets[0].guns.length > 1 || tank.turrets[0].guns.length > 1 ||
tank.engines.length > 1 || tank.engines.length > 1 ||
tank.tracks.length > 1; tank.tracks.length > 1;
const turret = Duel.use((state) => state.protagonist!.turret); const turret = Duel.use((state) => state.protagonist.turret);
const gun = Duel.use((state) => state.protagonist!.gun); const gun = Duel.use((state) => state.protagonist.gun);
const engine = Duel.use((state) => state.protagonist!.engine); const engine = Duel.use((state) => state.protagonist.engine);
const track = Duel.use((state) => state.protagonist!.track); const track = Duel.use((state) => state.protagonist.track);
const turret0 = tank.turrets[0]; const turret0 = tank.turrets[0];
const gun0 = turret0.guns[0]; const gun0 = turret0.guns[0];
const engine0 = tank.engines[0]; const engine0 = tank.engines[0];
@@ -140,44 +140,44 @@ export function Modules() {
function setByUnlock(unlock: Unlock) { function setByUnlock(unlock: Unlock) {
mutateDuel((draft) => { mutateDuel((draft) => {
if (unlock.type === 'turret') { if (unlock.type === 'turret') {
draft.protagonist!.turret = draft.protagonist!.tank.turrets.find( draft.protagonist.turret = draft.protagonist.tank.turrets.find(
(turret) => turret.id === unlock.id, (turret) => turret.id === unlock.id,
)!; )!;
if ( if (
!draft.protagonist!.turret.guns.some( !draft.protagonist.turret.guns.some(
(gun) => gun.id === draft.protagonist!.gun.id, (gun) => gun.id === draft.protagonist.gun.id,
) )
) { ) {
draft.protagonist!.gun = draft.protagonist!.turret.guns.at(-1)!; draft.protagonist.gun = draft.protagonist.turret.guns.at(-1)!;
draft.protagonist!.shell = draft.protagonist!.gun.shells[0]; draft.protagonist.shell = draft.protagonist.gun.shells[0];
} }
} else if (unlock.type === 'gun') { } else if (unlock.type === 'gun') {
const gunInTurret = draft.protagonist!.turret.guns.find( const gunInTurret = draft.protagonist.turret.guns.find(
(gun) => gun.id === unlock.id, (gun) => gun.id === unlock.id,
); );
if (gunInTurret) { if (gunInTurret) {
draft.protagonist!.gun = gunInTurret; draft.protagonist.gun = gunInTurret;
draft.protagonist!.shell = gunInTurret.shells[0]; draft.protagonist.shell = gunInTurret.shells[0];
} else { } else {
// TODO: warn somehow? // TODO: warn somehow?
const suitableTurret = draft.protagonist!.tank.turrets.find( const suitableTurret = draft.protagonist.tank.turrets.find((turret) =>
(turret) => turret.guns.some((gun) => gun.id === unlock.id), turret.guns.some((gun) => gun.id === unlock.id),
)!; )!;
const gunInSuitableTurret = suitableTurret.guns.find( const gunInSuitableTurret = suitableTurret.guns.find(
(gun) => gun.id === unlock.id, (gun) => gun.id === unlock.id,
)!; )!;
draft.protagonist!.turret = suitableTurret; draft.protagonist.turret = suitableTurret;
draft.protagonist!.gun = gunInSuitableTurret; draft.protagonist.gun = gunInSuitableTurret;
draft.protagonist!.shell = gunInSuitableTurret.shells[0]; draft.protagonist.shell = gunInSuitableTurret.shells[0];
} }
} else if (unlock.type === 'engine') { } else if (unlock.type === 'engine') {
draft.protagonist!.engine = draft.protagonist!.tank.engines.find( draft.protagonist.engine = draft.protagonist.tank.engines.find(
(engine) => engine.id === unlock.id, (engine) => engine.id === unlock.id,
)!; )!;
} else if (unlock.type === 'chassis') { } else if (unlock.type === 'chassis') {
draft.protagonist!.track = draft.protagonist!.tank.tracks.find( draft.protagonist.track = draft.protagonist.tank.tracks.find(
(track) => track.id === unlock.id, (track) => track.id === unlock.id,
)!; )!;
} }
@@ -320,13 +320,11 @@ export function Modules() {
color="red" color="red"
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.turret = draft.protagonist.turret = draft.protagonist.tank.turrets[0];
draft.protagonist!.tank.turrets[0]; draft.protagonist.gun = draft.protagonist.turret.guns[0];
draft.protagonist!.gun = draft.protagonist!.turret.guns[0]; draft.protagonist.shell = draft.protagonist.gun.shells[0];
draft.protagonist!.shell = draft.protagonist!.gun.shells[0]; draft.protagonist.engine = draft.protagonist.tank.engines[0];
draft.protagonist!.engine = draft.protagonist.track = draft.protagonist.tank.tracks[0];
draft.protagonist!.tank.engines[0];
draft.protagonist!.track = draft.protagonist!.tank.tracks[0];
}); });
}} }}
> >
@@ -336,15 +334,14 @@ export function Modules() {
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.turret = draft.protagonist.turret =
draft.protagonist!.tank.turrets.at(-1)!; draft.protagonist.tank.turrets.at(-1)!;
draft.protagonist!.gun = draft.protagonist.gun = draft.protagonist.turret.guns.at(-1)!;
draft.protagonist!.turret.guns.at(-1)!; draft.protagonist.shell = draft.protagonist.gun.shells[0];
draft.protagonist!.shell = draft.protagonist!.gun.shells[0]; draft.protagonist.engine =
draft.protagonist!.engine = draft.protagonist.tank.engines.at(-1)!;
draft.protagonist!.tank.engines.at(-1)!; draft.protagonist.track =
draft.protagonist!.track = draft.protagonist.tank.tracks.at(-1)!;
draft.protagonist!.tank.tracks.at(-1)!;
}); });
}} }}
> >
@@ -8,8 +8,8 @@ import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
export function Provisions() { export function Provisions() {
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const { tank, gun } = Duel.use((state) => state.protagonist!); const { tank, gun } = Duel.use((state) => state.protagonist);
const provisions = Duel.use((state) => state.protagonist!.provisions); const provisions = Duel.use((state) => state.protagonist.provisions);
const awaitedProvisionDefinitions = use(provisionDefinitions); const awaitedProvisionDefinitions = use(provisionDefinitions);
const provisionsList = availableProvisions( const provisionsList = availableProvisions(
tank, tank,
@@ -26,7 +26,7 @@ export function Provisions() {
color="red" color="red"
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.provisions = []; draft.protagonist.provisions = [];
}); });
}} }}
> >
@@ -40,7 +40,7 @@ export function Provisions() {
disabled={tank.provisions === provisions.length} disabled={tank.provisions === provisions.length}
onChange={(provisions) => { onChange={(provisions) => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.provisions = provisions; draft.protagonist.provisions = provisions;
}); });
}} }}
/> />
@@ -42,10 +42,10 @@ export function Characteristics() {
const crewSkills = TankopediaEphemeral.use((state) => state.skills); const crewSkills = TankopediaEphemeral.use((state) => state.skills);
const penetrationDistanceInput = useRef<HTMLInputElement>(null); const penetrationDistanceInput = useRef<HTMLInputElement>(null);
const hasImprovedVentilation = useEquipment(102); const hasImprovedVentilation = useEquipment(102);
const crewMastery = Duel.use((state) => state.protagonist!.crewMastery); const crewMastery = Duel.use((state) => state.protagonist.crewMastery);
const [penetrationDistance, setPenetrationDistance] = useState(250); const [penetrationDistance, setPenetrationDistance] = useState(250);
const provisions = Duel.use((state) => state.protagonist!.provisions); const provisions = Duel.use((state) => state.protagonist.provisions);
const provisionCrewBonus = const provisionCrewBonus =
provisions.reduce( provisions.reduce(
(total, provision) => (total, provision) =>
@@ -56,13 +56,13 @@ export function Characteristics() {
) + (hasImprovedVentilation ? 0.08 : 0); ) + (hasImprovedVentilation ? 0.08 : 0);
const commanderMastery = crewMastery + provisionCrewBonus; const commanderMastery = crewMastery + provisionCrewBonus;
const crewMemberMastery = commanderMastery * 1.1; const crewMemberMastery = commanderMastery * 1.1;
const consumables = Duel.use((state) => state.protagonist!.consumables); const consumables = Duel.use((state) => state.protagonist.consumables);
const camouflage = Duel.use((state) => state.protagonist!.camouflage); const camouflage = Duel.use((state) => state.protagonist.camouflage);
const equipmentMatrix = Duel.use( const equipmentMatrix = Duel.use(
(state) => state.protagonist!.equipmentMatrix, (state) => state.protagonist.equipmentMatrix,
); );
const { tank, turret, gun, engine, track, shell } = Duel.use( const { tank, turret, gun, engine, track, shell } = Duel.use(
(state) => state.protagonist!, (state) => state.protagonist,
); );
const stockEngine = tank.engines[0]; const stockEngine = tank.engines[0];
const stockTrack = tank.tracks[0]; const stockTrack = tank.tracks[0];
@@ -119,9 +119,9 @@ export function Characteristics() {
}, [penetrationDistance]); }, [penetrationDistance]);
useEffect(() => { useEffect(() => {
mutateDuel((draft) => { mutateDuel((draft) => {
[draft.protagonist!.pitch, draft.protagonist!.yaw] = applyPitchYawLimits( [draft.protagonist.pitch, draft.protagonist.yaw] = applyPitchYawLimits(
draft.protagonist!.pitch, draft.protagonist.pitch,
draft.protagonist!.yaw, draft.protagonist.yaw,
gunModelDefinition.pitch, gunModelDefinition.pitch,
turretModelDefinition.yaw, turretModelDefinition.yaw,
hasImprovedVerticalStabilizer, hasImprovedVerticalStabilizer,
@@ -159,7 +159,7 @@ export function Characteristics() {
}} }}
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.shell = thisShell; draft.protagonist.shell = thisShell;
}); });
}} }}
> >
@@ -24,8 +24,8 @@ export function Controls() {
const canvas = useThree((state) => state.gl.domElement); const canvas = useThree((state) => state.gl.domElement);
const orbitControls = useRef<OrbitControlsClass>(null); const orbitControls = useRef<OrbitControlsClass>(null);
const awaitedModelDefinitions = useAwait(modelDefinitions); const awaitedModelDefinitions = useAwait(modelDefinitions);
const protagonist = Duel.use((state) => state.protagonist!); const protagonist = Duel.use((state) => state.protagonist);
const antagonist = Duel.use((state) => state.antagonist!); const antagonist = Duel.use((state) => state.antagonist);
const protagonistModelDefinition = const protagonistModelDefinition =
awaitedModelDefinitions[protagonist.tank.id]; awaitedModelDefinitions[protagonist.tank.id];
const protagonistTrackModelDefinition = const protagonistTrackModelDefinition =
@@ -75,8 +75,8 @@ export function Controls() {
const duel = duelStore.getState(); const duel = duelStore.getState();
const hasImprovedVerticalStabilizer = await hasEquipment( const hasImprovedVerticalStabilizer = await hasEquipment(
122, 122,
duel.protagonist!.tank.equipment, duel.protagonist.tank.equipment,
duel.protagonist!.equipmentMatrix, duel.protagonist.equipmentMatrix,
); );
switch (event) { switch (event) {
@@ -3,7 +3,7 @@ import PageWrapper from '../../../../../components/PageWrapper';
import * as Duel from '../../../../../stores/duel'; import * as Duel from '../../../../../stores/duel';
export function HistorySection() { export function HistorySection() {
const tank = Duel.use((state) => state.protagonist!.tank); const tank = Duel.use((state) => state.protagonist.tank);
if (!tank.description) return null; if (!tank.description) return null;
@@ -12,7 +12,7 @@ export const ENVIRONMENTS = [
] as const; ] as const;
export function Lighting() { export function Lighting() {
const protagonist = Duel.use((state) => state.protagonist!); const protagonist = Duel.use((state) => state.protagonist);
const { hasPbr } = useModel(protagonist.tank.id); const { hasPbr } = useModel(protagonist.tank.id);
const showEnvironment = TankopediaPersistent.use( const showEnvironment = TankopediaPersistent.use(
(state) => state.model.visual.showEnvironment, (state) => state.model.visual.showEnvironment,
@@ -10,8 +10,8 @@ import { TankSandbox } from './TankSandbox';
import { Options } from './components/Options'; import { Options } from './components/Options';
export function HeroSection() { export function HeroSection() {
const protagonist = Duel.use((state) => state.protagonist!.tank); const protagonist = Duel.use((state) => state.protagonist.tank);
const antagonist = Duel.use((state) => state.antagonist!.tank); const antagonist = Duel.use((state) => state.antagonist.tank);
const compareTanks = const compareTanks =
protagonist.id === antagonist.id protagonist.id === antagonist.id
? [protagonist.id] ? [protagonist.id]
@@ -20,7 +20,7 @@ export function TankSandbox() {
const canvas = useRef<HTMLCanvasElement>(null); const canvas = useRef<HTMLCanvasElement>(null);
const hasImprovedVerticalStabilizer = useEquipment(122); const hasImprovedVerticalStabilizer = useEquipment(122);
const awaitedModelDefinitions = use(modelDefinitions); const awaitedModelDefinitions = use(modelDefinitions);
const protagonist = Duel.use((state) => state.protagonist!); const protagonist = Duel.use((state) => state.protagonist);
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id]; const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
const turretModelDefinition = const turretModelDefinition =
@@ -55,8 +55,8 @@ export function TankSandbox() {
); );
modelTransformEvent.emit({ pitch, yaw }); modelTransformEvent.emit({ pitch, yaw });
draft.protagonist!.pitch = pitch; draft.protagonist.pitch = pitch;
draft.protagonist!.yaw = yaw; draft.protagonist.yaw = yaw;
}); });
break; break;
@@ -73,8 +73,8 @@ export function TankSandbox() {
); );
modelTransformEvent.emit({ pitch, yaw }); modelTransformEvent.emit({ pitch, yaw });
draft.protagonist!.pitch = pitch; draft.protagonist.pitch = pitch;
draft.protagonist!.yaw = yaw; draft.protagonist.yaw = yaw;
}); });
break; break;
@@ -91,8 +91,8 @@ export function TankSandbox() {
); );
modelTransformEvent.emit({ pitch, yaw }); modelTransformEvent.emit({ pitch, yaw });
draft.protagonist!.pitch = pitch; draft.protagonist.pitch = pitch;
draft.protagonist!.yaw = yaw; draft.protagonist.yaw = yaw;
}); });
break; break;
@@ -108,9 +108,9 @@ export function TankSandbox() {
useEffect(() => { useEffect(() => {
mutateDuel((draft) => { mutateDuel((draft) => {
[draft.protagonist!.pitch, draft.protagonist!.yaw] = applyPitchYawLimits( [draft.protagonist.pitch, draft.protagonist.yaw] = applyPitchYawLimits(
draft.protagonist!.pitch, draft.protagonist.pitch,
draft.protagonist!.yaw, draft.protagonist.yaw,
gunModelDefinition.pitch, gunModelDefinition.pitch,
turretModelDefinition.yaw, turretModelDefinition.yaw,
hasImprovedVerticalStabilizer, hasImprovedVerticalStabilizer,
@@ -51,7 +51,7 @@ export function TreeArrow({
export function TechTreeSection() { export function TechTreeSection() {
const awaitedTankDefinitions = use(tankDefinitions); const awaitedTankDefinitions = use(tankDefinitions);
const tank = Duel.use((state) => state.protagonist!.tank); const tank = Duel.use((state) => state.protagonist.tank);
if (tank.treeType !== 'researchable') return null; if (tank.treeType !== 'researchable') return null;
@@ -66,11 +66,11 @@ export function Options() {
(state) => state.model.visual.environment, (state) => state.model.visual.environment,
); );
const developerMode = App.use((state) => state.developerMode); const developerMode = App.use((state) => state.developerMode);
const antagonistGun = Duel.use((state) => state.antagonist!.gun); const antagonistGun = Duel.use((state) => state.antagonist.gun);
const antagonistShell = Duel.use((state) => state.antagonist!.shell); const antagonistShell = Duel.use((state) => state.antagonist.shell);
const [antagonistSelectorOpen, setAntagonistSelectorOpen] = useState(false); const [antagonistSelectorOpen, setAntagonistSelectorOpen] = useState(false);
const antagonistTank = Duel.use((state) => state.antagonist!.tank); const antagonistTank = Duel.use((state) => state.antagonist.tank);
const antagonistTurret = Duel.use((state) => state.antagonist!.turret); const antagonistTurret = Duel.use((state) => state.antagonist.turret);
const hasCalibratedShells = useEquipment(103, true); const hasCalibratedShells = useEquipment(103, true);
const [tab, setTab] = useState('search'); const [tab, setTab] = useState('search');
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
@@ -151,7 +151,7 @@ export function Options() {
}} }}
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.antagonist!.shell = thisShell; draft.antagonist.shell = thisShell;
}); });
mutateTankopediaEphemeral((draft) => { mutateTankopediaEphemeral((draft) => {
draft.shot = undefined; draft.shot = undefined;
@@ -183,7 +183,7 @@ export function Options() {
}} }}
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.antagonist!.equipmentMatrix[0][0] = hasCalibratedShells draft.antagonist.equipmentMatrix[0][0] = hasCalibratedShells
? 0 ? 0
: 1; : 1;
}); });
@@ -215,7 +215,7 @@ export function Options() {
}} }}
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.equipmentMatrix[1][1] = hasEnhancedArmor draft.protagonist.equipmentMatrix[1][1] = hasEnhancedArmor
? 0 ? 0
: -1; : -1;
}); });
@@ -298,14 +298,14 @@ export function Options() {
compact compact
onSelect={(tank) => { onSelect={(tank) => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.antagonist!.tank = tank; draft.antagonist.tank = tank;
draft.antagonist!.engine = tank.engines.at(-1)!; draft.antagonist.engine = tank.engines.at(-1)!;
draft.antagonist!.track = tank.tracks.at(-1)!; draft.antagonist.track = tank.tracks.at(-1)!;
draft.antagonist!.turret = tank.turrets.at(-1)!; draft.antagonist.turret = tank.turrets.at(-1)!;
draft.antagonist!.gun = draft.antagonist.gun =
draft.antagonist!.turret.guns.at(-1)!; draft.antagonist.turret.guns.at(-1)!;
draft.antagonist!.shell = draft.antagonist.shell =
draft.antagonist!.gun.shells[0]; draft.antagonist.gun.shells[0];
}); });
setAntagonistSelectorOpen(false); setAntagonistSelectorOpen(false);
}} }}
@@ -332,11 +332,11 @@ export function Options() {
key={turret.id} key={turret.id}
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.antagonist!.turret = turret; draft.antagonist.turret = turret;
draft.antagonist!.gun = draft.antagonist.gun =
turret.guns.at(-1)!; turret.guns.at(-1)!;
draft.antagonist!.shell = draft.antagonist.shell =
draft.antagonist!.gun.shells[0]; draft.antagonist.gun.shells[0];
}); });
mutateTankopediaEphemeral((draft) => { mutateTankopediaEphemeral((draft) => {
draft.shot = undefined; draft.shot = undefined;
@@ -361,8 +361,8 @@ export function Options() {
} }
onClick={() => { onClick={() => {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.antagonist!.gun = gun; draft.antagonist.gun = gun;
draft.antagonist!.shell = gun.shells[0]; draft.antagonist.shell = gun.shells[0];
}); });
}} }}
selected={antagonistGun.id === gun.id} selected={antagonistGun.id === gun.id}
@@ -28,7 +28,7 @@ export const TankModel = memo(() => {
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const duelStore = Duel.useStore(); const duelStore = Duel.useStore();
const awaitedModelDefinitions = useAwait(modelDefinitions); const awaitedModelDefinitions = useAwait(modelDefinitions);
const protagonist = Duel.use((draft) => draft.protagonist!); const protagonist = Duel.use((draft) => draft.protagonist);
const canvas = useThree((state) => state.gl.domElement); const canvas = useThree((state) => state.gl.domElement);
const hullContainer = useRef<Group>(null); const hullContainer = useRef<Group>(null);
const turretContainer = useRef<Group>(null); const turretContainer = useRef<Group>(null);
@@ -221,8 +221,8 @@ export const TankModel = memo(() => {
const duel = duelStore.getState(); const duel = duelStore.getState();
const hasImprovedVerticalStabilizer = await hasEquipment( const hasImprovedVerticalStabilizer = await hasEquipment(
122, 122,
duel.protagonist!.tank.equipment, duel.protagonist.tank.equipment,
duel.protagonist!.equipmentMatrix, duel.protagonist.equipmentMatrix,
); );
const boundingRect = canvas.getBoundingClientRect(); const boundingRect = canvas.getBoundingClientRect();
@@ -240,8 +240,8 @@ export const TankModel = memo(() => {
} }
function handlePointerUp() { function handlePointerUp() {
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.pitch = normalizeAngleRad(pitch); draft.protagonist.pitch = normalizeAngleRad(pitch);
draft.protagonist!.yaw = normalizeAngleRad(yaw); draft.protagonist.yaw = normalizeAngleRad(yaw);
}); });
mutateTankopediaTemporary((draft) => { mutateTankopediaTemporary((draft) => {
draft.controlsEnabled = true; draft.controlsEnabled = true;
@@ -301,8 +301,8 @@ export const TankModel = memo(() => {
const duel = duelStore.getState(); const duel = duelStore.getState();
const hasImprovedVerticalStabilizer = await hasEquipment( const hasImprovedVerticalStabilizer = await hasEquipment(
122, 122,
duel.protagonist!.tank.equipment, duel.protagonist.tank.equipment,
duel.protagonist!.equipmentMatrix, duel.protagonist.equipmentMatrix,
); );
const boundingRect = canvas.getBoundingClientRect(); const boundingRect = canvas.getBoundingClientRect();
delta.set(event.clientX, event.clientY).sub(position); delta.set(event.clientX, event.clientY).sub(position);
@@ -322,8 +322,8 @@ export const TankModel = memo(() => {
draft.controlsEnabled = true; draft.controlsEnabled = true;
}); });
mutateDuel((draft) => { mutateDuel((draft) => {
draft.protagonist!.pitch = normalizeAngleRad(pitch); draft.protagonist.pitch = normalizeAngleRad(pitch);
draft.protagonist!.yaw = normalizeAngleRad(yaw); draft.protagonist.yaw = normalizeAngleRad(yaw);
}); });
window.removeEventListener('pointermove', handlePointerMove); window.removeEventListener('pointermove', handlePointerMove);
window.removeEventListener('pointerup', handlePointerUp); window.removeEventListener('pointerup', handlePointerUp);
@@ -15,7 +15,7 @@ import * as styles from './index.css';
export function RotationInputs() { export function RotationInputs() {
const mutateDuel = Duel.useMutation(); const mutateDuel = Duel.useMutation();
const protagonist = Duel.use((state) => state.protagonist!); const protagonist = Duel.use((state) => state.protagonist);
const awaitedModelDefinitions = use(modelDefinitions); const awaitedModelDefinitions = use(modelDefinitions);
const yawInput = useRef<HTMLInputElement>(null); const yawInput = useRef<HTMLInputElement>(null);
const pitchInput = useRef<HTMLInputElement>(null); const pitchInput = useRef<HTMLInputElement>(null);
@@ -90,8 +90,8 @@ export function RotationInputs() {
); );
modelTransformEvent.emit({ pitch, yaw }); modelTransformEvent.emit({ pitch, yaw });
mutateDuel((state) => { mutateDuel((state) => {
state.protagonist!.pitch = pitch; state.protagonist.pitch = pitch;
state.protagonist!.yaw = yaw; state.protagonist.yaw = yaw;
}); });
yawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1); yawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1);
}} }}
@@ -137,8 +137,8 @@ export function RotationInputs() {
); );
modelTransformEvent.emit({ pitch, yaw }); modelTransformEvent.emit({ pitch, yaw });
mutateDuel((state) => { mutateDuel((state) => {
state.protagonist!.pitch = pitch; state.protagonist.pitch = pitch;
state.protagonist!.yaw = yaw; state.protagonist.yaw = yaw;
}); });
pitchInput.current!.value = ( pitchInput.current!.value = (
-radToDeg(protagonist.pitch) + initialGunPitch -radToDeg(protagonist.pitch) + initialGunPitch
@@ -11,8 +11,8 @@ import { TankSearch } from '../../components/TankSearch';
export function Title() { export function Title() {
const awaitedProvisionDefinitions = use(provisionDefinitions); const awaitedProvisionDefinitions = use(provisionDefinitions);
const protagonist = Duel.use((state) => state.protagonist!); const protagonist = Duel.use((state) => state.protagonist);
const antagonist = Duel.use((state) => state.antagonist!); const antagonist = Duel.use((state) => state.antagonist);
const compareTanks = const compareTanks =
protagonist.tank.id === antagonist.tank.id protagonist.tank.id === antagonist.tank.id
? [protagonist.tank.id] ? [protagonist.tank.id]
@@ -5,7 +5,7 @@ import { videoDefinitions } from '../../../../../core/blitzkit/videos';
import * as Duel from '../../../../../stores/duel'; import * as Duel from '../../../../../stores/duel';
export function VideoSection() { export function VideoSection() {
const tank = Duel.use((state) => state.protagonist!.tank); const tank = Duel.use((state) => state.protagonist.tank);
const awaitedVideoDefinitions = use(videoDefinitions); const awaitedVideoDefinitions = use(videoDefinitions);
const videos = awaitedVideoDefinitions[tank.id]?.videos ?? []; const videos = awaitedVideoDefinitions[tank.id]?.videos ?? [];
+5 -5
View File
@@ -32,20 +32,20 @@ export default function Page() {
if (event.key === '1') { if (event.key === '1') {
wipeShot(); wipeShot();
mutateDuel((draft) => { mutateDuel((draft) => {
draft.antagonist!.shell = draft.antagonist!.gun.shells[0]; draft.antagonist.shell = draft.antagonist.gun.shells[0];
}); });
} else if (event.key === '2') { } else if (event.key === '2') {
wipeShot(); wipeShot();
mutateDuel((draft) => { mutateDuel((draft) => {
if (draft.antagonist!.gun.shells[1]) { if (draft.antagonist.gun.shells[1]) {
draft.antagonist!.shell = draft.antagonist!.gun.shells[1]; draft.antagonist.shell = draft.antagonist.gun.shells[1];
} }
}); });
} else if (event.key === '3') { } else if (event.key === '3') {
wipeShot(); wipeShot();
mutateDuel((draft) => { mutateDuel((draft) => {
if (draft.antagonist!.gun.shells[2]) { if (draft.antagonist.gun.shells[2]) {
draft.antagonist!.shell = draft.antagonist!.gun.shells[2]; draft.antagonist.shell = draft.antagonist.gun.shells[2];
} }
}); });
} }
@@ -110,10 +110,10 @@ export const CoreArmorScene = memo(() => {
return unsubscribe; return unsubscribe;
}); });
const tank = Duel.use((state) => state.protagonist!.tank); const tank = Duel.use((state) => state.protagonist.tank);
const track = Duel.use((state) => state.protagonist!.track); const track = Duel.use((state) => state.protagonist.track);
const turret = Duel.use((state) => state.protagonist!.turret); const turret = Duel.use((state) => state.protagonist.turret);
const gun = Duel.use((state) => state.protagonist!.gun); const gun = Duel.use((state) => state.protagonist.gun);
const armorGltf = useArmor(tank.id); const armorGltf = useArmor(tank.id);
const armorNodes = Object.values(armorGltf.nodes); const armorNodes = Object.values(armorGltf.nodes);
const tankModelDefinition = modelDefinitions[tank.id]; const tankModelDefinition = modelDefinitions[tank.id];
@@ -72,8 +72,8 @@ export function CoreArmorSceneComponent({
material.uniforms.explosionRadius.value = shell.explosionRadius; material.uniforms.explosionRadius.value = shell.explosionRadius;
const duel = duelStore.getState(); const duel = duelStore.getState();
await handleProtagonistEquipmentChange(duel.protagonist!.equipmentMatrix); await handleProtagonistEquipmentChange(duel.protagonist.equipmentMatrix);
await handleAntagonistEquipmentChange(duel.antagonist!.equipmentMatrix); await handleAntagonistEquipmentChange(duel.antagonist.equipmentMatrix);
} }
function handleVisualChange( function handleVisualChange(
visual: TankopediaPersistent.TankopediaPersistent['model']['visual'], visual: TankopediaPersistent.TankopediaPersistent['model']['visual'],
@@ -89,7 +89,7 @@ export function CoreArmorSceneComponent({
const duel = duelStore.getState(); const duel = duelStore.getState();
const hasEnhancedArmor = await hasEquipment( const hasEnhancedArmor = await hasEquipment(
110, 110,
duel.protagonist!.tank.equipment, duel.protagonist.tank.equipment,
equipment, equipment,
); );
material.uniforms.thickness.value = hasEnhancedArmor material.uniforms.thickness.value = hasEnhancedArmor
@@ -100,11 +100,11 @@ export function CoreArmorSceneComponent({
equipment: Duel.EquipmentMatrix, equipment: Duel.EquipmentMatrix,
) { ) {
const duel = duelStore.getState(); const duel = duelStore.getState();
const shell = duel.antagonist!.shell; const shell = duel.antagonist.shell;
const penetration = resolveNearPenetration(shell.penetration); const penetration = resolveNearPenetration(shell.penetration);
const hasCalibratedShells = await hasEquipment( const hasCalibratedShells = await hasEquipment(
103, 103,
duel.antagonist!.tank.equipment, duel.antagonist.tank.equipment,
equipment, equipment,
); );
@@ -113,30 +113,27 @@ export function CoreArmorSceneComponent({
resolvePenetrationCoefficient(hasCalibratedShells, shell.type); resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
} }
handleShellChange(duelStore.getState().antagonist!.shell); handleShellChange(duelStore.getState().antagonist.shell);
handleVisualChange(tankopediaPersistentStore.getState().model.visual); handleVisualChange(tankopediaPersistentStore.getState().model.visual);
handleProtagonistEquipmentChange( handleProtagonistEquipmentChange(
duelStore.getState().protagonist!.equipmentMatrix, duelStore.getState().protagonist.equipmentMatrix,
); );
handleAntagonistEquipmentChange( handleAntagonistEquipmentChange(
duelStore.getState().antagonist!.equipmentMatrix, duelStore.getState().antagonist.equipmentMatrix,
); );
const unsubscribes = [ const unsubscribes = [
duelStore.subscribe( duelStore.subscribe((state) => state.antagonist.shell, handleShellChange),
(state) => state.antagonist!.shell,
handleShellChange,
),
tankopediaPersistentStore.subscribe( tankopediaPersistentStore.subscribe(
(state) => state.model.visual, (state) => state.model.visual,
handleVisualChange, handleVisualChange,
), ),
duelStore.subscribe( duelStore.subscribe(
(state) => state.protagonist!.equipmentMatrix, (state) => state.protagonist.equipmentMatrix,
handleProtagonistEquipmentChange, handleProtagonistEquipmentChange,
), ),
duelStore.subscribe( duelStore.subscribe(
(state) => state.antagonist!.equipmentMatrix, (state) => state.antagonist.equipmentMatrix,
handleAntagonistEquipmentChange, handleAntagonistEquipmentChange,
), ),
]; ];
@@ -120,10 +120,10 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
return unsubscribe; return unsubscribe;
}); });
const tank = Duel.use((state) => state.protagonist!.tank); const tank = Duel.use((state) => state.protagonist.tank);
const track = Duel.use((state) => state.protagonist!.track); const track = Duel.use((state) => state.protagonist.track);
const turret = Duel.use((state) => state.protagonist!.turret); const turret = Duel.use((state) => state.protagonist.turret);
const gun = Duel.use((state) => state.protagonist!.gun); const gun = Duel.use((state) => state.protagonist.gun);
const armorGltf = useArmor(tank.id); const 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);
@@ -59,7 +59,7 @@ export function SpacedArmorSubExternal({
const duel = duelStore.getState(); const duel = duelStore.getState();
const hasEnhancedArmor = await hasEquipment( const hasEnhancedArmor = await hasEquipment(
110, 110,
duel.protagonist!.tank.equipment, duel.protagonist.tank.equipment,
equipment, equipment,
); );
material.uniforms.thickness.value = hasEnhancedArmor material.uniforms.thickness.value = hasEnhancedArmor
@@ -70,11 +70,11 @@ export function SpacedArmorSubExternal({
equipment: Duel.EquipmentMatrix, equipment: Duel.EquipmentMatrix,
) { ) {
const duel = duelStore.getState(); const duel = duelStore.getState();
const shell = duel.antagonist!.shell; const shell = duel.antagonist.shell;
const penetration = resolveNearPenetration(shell.penetration); const penetration = resolveNearPenetration(shell.penetration);
const hasCalibratedShells = await hasEquipment( const hasCalibratedShells = await hasEquipment(
103, 103,
duel.antagonist!.tank.equipment, duel.antagonist.tank.equipment,
equipment, equipment,
); );
@@ -83,25 +83,22 @@ export function SpacedArmorSubExternal({
resolvePenetrationCoefficient(hasCalibratedShells, shell.type); resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
} }
handleShellChange(duelStore.getState().antagonist!.shell); handleShellChange(duelStore.getState().antagonist.shell);
handleProtagonistEquipmentChange( handleProtagonistEquipmentChange(
duelStore.getState().protagonist!.equipmentMatrix, duelStore.getState().protagonist.equipmentMatrix,
); );
handleAntagonistEquipmentChange( handleAntagonistEquipmentChange(
duelStore.getState().antagonist!.equipmentMatrix, duelStore.getState().antagonist.equipmentMatrix,
); );
const unsubscribes = [ const unsubscribes = [
duelStore.subscribe((state) => state.antagonist.shell, handleShellChange),
duelStore.subscribe( duelStore.subscribe(
(state) => state.antagonist!.shell, (state) => state.protagonist.equipmentMatrix,
handleShellChange,
),
duelStore.subscribe(
(state) => state.protagonist!.equipmentMatrix,
handleProtagonistEquipmentChange, handleProtagonistEquipmentChange,
), ),
duelStore.subscribe( duelStore.subscribe(
(state) => state.antagonist!.equipmentMatrix, (state) => state.antagonist.equipmentMatrix,
handleAntagonistEquipmentChange, handleAntagonistEquipmentChange,
), ),
]; ];
@@ -69,7 +69,7 @@ export function SpacedArmorSubSpaced({
const duel = duelStore.getState(); const duel = duelStore.getState();
const hasEnhancedArmor = await hasEquipment( const hasEnhancedArmor = await hasEquipment(
110, 110,
duel.protagonist!.tank.equipment, duel.protagonist.tank.equipment,
equipment, equipment,
); );
material.uniforms.thickness.value = hasEnhancedArmor material.uniforms.thickness.value = hasEnhancedArmor
@@ -80,11 +80,11 @@ export function SpacedArmorSubSpaced({
equipment: Duel.EquipmentMatrix, equipment: Duel.EquipmentMatrix,
) { ) {
const duel = duelStore.getState(); const duel = duelStore.getState();
const shell = duelStore.getState().antagonist!.shell; const shell = duelStore.getState().antagonist.shell;
const penetration = resolveNearPenetration(shell.penetration); const penetration = resolveNearPenetration(shell.penetration);
const hasCalibratedShells = await hasEquipment( const hasCalibratedShells = await hasEquipment(
103, 103,
duel.antagonist!.tank.equipment, duel.antagonist.tank.equipment,
equipment, equipment,
); );
@@ -93,25 +93,22 @@ export function SpacedArmorSubSpaced({
resolvePenetrationCoefficient(hasCalibratedShells, shell.type); resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
} }
handleShellChange(duelStore.getState().antagonist!.shell); handleShellChange(duelStore.getState().antagonist.shell);
handleProtagonistEquipmentChange( handleProtagonistEquipmentChange(
duelStore.getState().protagonist!.equipmentMatrix, duelStore.getState().protagonist.equipmentMatrix,
); );
handleAntagonistEquipmentChange( handleAntagonistEquipmentChange(
duelStore.getState().antagonist!.equipmentMatrix, duelStore.getState().antagonist.equipmentMatrix,
); );
const unsubscribes = [ const unsubscribes = [
duelStore.subscribe((state) => state.antagonist.shell, handleShellChange),
duelStore.subscribe( duelStore.subscribe(
(state) => state.antagonist!.shell, (state) => state.protagonist.equipmentMatrix,
handleShellChange,
),
duelStore.subscribe(
(state) => state.protagonist!.equipmentMatrix,
handleProtagonistEquipmentChange, handleProtagonistEquipmentChange,
), ),
duelStore.subscribe( duelStore.subscribe(
(state) => state.antagonist!.equipmentMatrix, (state) => state.antagonist.equipmentMatrix,
handleAntagonistEquipmentChange, handleAntagonistEquipmentChange,
), ),
]; ];
@@ -83,7 +83,7 @@ export function SpacedArmorSceneComponent({
remainingPenetrationInput?: number, remainingPenetrationInput?: number,
) { ) {
const { antagonist, protagonist } = duelStore.getState(); const { antagonist, protagonist } = duelStore.getState();
const shell = antagonist!.shell; const shell = antagonist.shell;
const cameraNormal = camera.position.clone().sub(point).normalize(); const cameraNormal = camera.position.clone().sub(point).normalize();
const shot: TankopediaEphemeral.Shot = { const shot: TankopediaEphemeral.Shot = {
damage: -1, damage: -1,
@@ -97,13 +97,13 @@ export function SpacedArmorSceneComponent({
const hasCalibratedShells = await hasEquipment( const hasCalibratedShells = await hasEquipment(
103, 103,
antagonist!.tank.equipment, antagonist.tank.equipment,
antagonist!.equipmentMatrix, antagonist.equipmentMatrix,
); );
const hasEnhancedArmor = await hasEquipment( const hasEnhancedArmor = await hasEquipment(
110, 110,
protagonist!.tank.equipment, protagonist.tank.equipment,
protagonist!.equipmentMatrix, protagonist.equipmentMatrix,
); );
const penetration = const penetration =
resolveNearPenetration(shell.penetration) * resolveNearPenetration(shell.penetration) *
+1 -1
View File
@@ -13,7 +13,7 @@ export enum UseEccentricityMode {
export function useEccentricity(mode: UseEccentricityMode) { export function useEccentricity(mode: UseEccentricityMode) {
const awaitedTankDefinitions = use(tankDefinitions); const awaitedTankDefinitions = use(tankDefinitions);
const tank = Duel.use((state) => state.protagonist!.tank); const tank = Duel.use((state) => state.protagonist.tank);
const similarTanks = useMemo( const similarTanks = useMemo(
() => () =>
Object.values(awaitedTankDefinitions).filter( Object.values(awaitedTankDefinitions).filter(
+1 -1
View File
@@ -1,6 +1,6 @@
import * as Duel from '../stores/duel'; import * as Duel from '../stores/duel';
export function useProvision(id: number) { export function useProvision(id: number) {
const provisions = Duel.use((state) => state.protagonist!.provisions); const provisions = Duel.use((state) => state.protagonist.provisions);
return provisions.includes(id); return provisions.includes(id);
} }