mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: migrated duel store
This commit is contained in:
1 parent
eaaea114a0
commit
332c1787f4
32 files changed
+223
-191
No files matched your search
@@ -12,13 +12,14 @@ import { ConsumablesManager } from '../../../../../../../components/ConsumablesM
|
|||||||
import { checkConsumableProvisionInclusivity } from '../../../../../../../core/blitzkit/checkConsumableProvisionInclusivity';
|
import { checkConsumableProvisionInclusivity } from '../../../../../../../core/blitzkit/checkConsumableProvisionInclusivity';
|
||||||
import { consumableDefinitions } from '../../../../../../../core/blitzkit/consumableDefinitions';
|
import { consumableDefinitions } from '../../../../../../../core/blitzkit/consumableDefinitions';
|
||||||
import { useEquipment } from '../../../../../../../hooks/useEquipment';
|
import { useEquipment } from '../../../../../../../hooks/useEquipment';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
import * as Duel from '../../../../../../../stores/duel';
|
||||||
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
||||||
|
|
||||||
export function Consumables() {
|
export function Consumables() {
|
||||||
const protagonist = useDuel((state) => state.protagonist!);
|
const mutateDuel = Duel.useMutation();
|
||||||
|
const protagonist = Duel.use((state) => state.protagonist!);
|
||||||
const awaitedConsumableDefinitions = use(consumableDefinitions);
|
const awaitedConsumableDefinitions = use(consumableDefinitions);
|
||||||
const consumables = useDuel((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(
|
||||||
@@ -27,7 +28,7 @@ export function Consumables() {
|
|||||||
protagonist.gun,
|
protagonist.gun,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const cooldownBooster = useDuel(
|
const cooldownBooster = Duel.use(
|
||||||
(state) => state.protagonist!.cooldownBooster,
|
(state) => state.protagonist!.cooldownBooster,
|
||||||
);
|
);
|
||||||
const hasConsumableDeliverySystem = useEquipment(118);
|
const hasConsumableDeliverySystem = useEquipment(118);
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ import { Button, Flex, Heading } from '@radix-ui/themes';
|
|||||||
import { use } from 'react';
|
import { use } from 'react';
|
||||||
import { EquipmentManager } from '../../../../../../../components/EquipmentManager';
|
import { EquipmentManager } from '../../../../../../../components/EquipmentManager';
|
||||||
import { equipmentDefinitions } from '../../../../../../../core/blitzkit/equipmentDefinitions';
|
import { equipmentDefinitions } from '../../../../../../../core/blitzkit/equipmentDefinitions';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
import * as Duel from '../../../../../../../stores/duel';
|
||||||
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
||||||
|
|
||||||
export function Equipment() {
|
export function Equipment() {
|
||||||
const protagonist = useDuel((state) => state.protagonist!);
|
const mutateDuel = Duel.useMutation();
|
||||||
|
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 = useDuel(
|
const equipmentMatrix = Duel.use(
|
||||||
(state) => state.protagonist!.equipmentMatrix,
|
(state) => state.protagonist!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+6
-5
@@ -3,18 +3,19 @@ import { clamp, debounce } from 'lodash';
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { GenericTankComponentButton } from '../../../../../../../components/ModuleButtons/GenericTankComponentButton';
|
import { GenericTankComponentButton } from '../../../../../../../components/ModuleButtons/GenericTankComponentButton';
|
||||||
import { asset } from '../../../../../../../core/blitzkit/asset';
|
import { asset } from '../../../../../../../core/blitzkit/asset';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
import * as Duel from '../../../../../../../stores/duel';
|
||||||
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
||||||
|
|
||||||
export function Miscellaneous() {
|
export function Miscellaneous() {
|
||||||
const camouflage = useDuel((state) => state.protagonist!.camouflage);
|
const mutateDuel = Duel.useMutation();
|
||||||
const cooldownBooster = useDuel(
|
const camouflage = Duel.use((state) => state.protagonist!.camouflage);
|
||||||
|
const cooldownBooster = Duel.use(
|
||||||
(state) => state.protagonist!.cooldownBooster,
|
(state) => state.protagonist!.cooldownBooster,
|
||||||
);
|
);
|
||||||
const crewMastery = useDuel((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 } = useDuel((state) => state.protagonist!);
|
const { tank } = Duel.use((state) => state.protagonist!);
|
||||||
|
|
||||||
const debouncedApplyDraft = useMemo(
|
const debouncedApplyDraft = useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
} from '../../../../../../../core/blitzkit/tankDefinitions';
|
} from '../../../../../../../core/blitzkit/tankDefinitions';
|
||||||
import { TIER_ROMAN_NUMERALS } from '../../../../../../../core/blitzkit/tankDefinitions/constants';
|
import { TIER_ROMAN_NUMERALS } from '../../../../../../../core/blitzkit/tankDefinitions/constants';
|
||||||
import { tankIcon } from '../../../../../../../core/blitzkit/tankIcon';
|
import { tankIcon } from '../../../../../../../core/blitzkit/tankIcon';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
import * as Duel from '../../../../../../../stores/duel';
|
||||||
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
||||||
|
|
||||||
function ModuleButton({
|
function ModuleButton({
|
||||||
@@ -116,17 +116,18 @@ function ModuleButton({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Modules() {
|
export function Modules() {
|
||||||
|
const mutateDuel = Duel.useMutation();
|
||||||
const awaitedTankDefinitions = use(tankDefinitions);
|
const awaitedTankDefinitions = use(tankDefinitions);
|
||||||
const tank = useDuel((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 = useDuel((state) => state.protagonist!.turret);
|
const turret = Duel.use((state) => state.protagonist!.turret);
|
||||||
const gun = useDuel((state) => state.protagonist!.gun);
|
const gun = Duel.use((state) => state.protagonist!.gun);
|
||||||
const engine = useDuel((state) => state.protagonist!.engine);
|
const engine = Duel.use((state) => state.protagonist!.engine);
|
||||||
const track = useDuel((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];
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ import { use } from 'react';
|
|||||||
import { ProvisionsManager } from '../../../../../../../components/ProvisionsManager';
|
import { ProvisionsManager } from '../../../../../../../components/ProvisionsManager';
|
||||||
import { availableProvisions } from '../../../../../../../core/blitzkit/availableProvisions';
|
import { availableProvisions } from '../../../../../../../core/blitzkit/availableProvisions';
|
||||||
import { provisionDefinitions } from '../../../../../../../core/blitzkit/provisionDefinitions';
|
import { provisionDefinitions } from '../../../../../../../core/blitzkit/provisionDefinitions';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
import * as Duel from '../../../../../../../stores/duel';
|
||||||
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
|
||||||
|
|
||||||
export function Provisions() {
|
export function Provisions() {
|
||||||
const { tank, gun } = useDuel((state) => state.protagonist!);
|
const mutateDuel = Duel.useMutation();
|
||||||
const provisions = useDuel((state) => state.protagonist!.provisions);
|
const { tank, gun } = Duel.use((state) => state.protagonist!);
|
||||||
|
const provisions = Duel.use((state) => state.protagonist!.provisions);
|
||||||
const awaitedProvisionDefinitions = use(provisionDefinitions);
|
const awaitedProvisionDefinitions = use(provisionDefinitions);
|
||||||
const provisionsList = availableProvisions(
|
const provisionsList = availableProvisions(
|
||||||
tank,
|
tank,
|
||||||
|
|||||||
@@ -28,12 +28,13 @@ import {
|
|||||||
} from '../../../../../../core/blitzkit/tankDefinitions/constants';
|
} from '../../../../../../core/blitzkit/tankDefinitions/constants';
|
||||||
import { useAdExempt } from '../../../../../../hooks/useAdExempt';
|
import { useAdExempt } from '../../../../../../hooks/useAdExempt';
|
||||||
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
|
import * as Duel from '../../../../../../stores/duel';
|
||||||
import * as TankopediaEphemeral from '../../../../../../stores/tankopediaEphemeral';
|
import * as TankopediaEphemeral from '../../../../../../stores/tankopediaEphemeral';
|
||||||
import { Info } from './components/Info';
|
import { Info } from './components/Info';
|
||||||
import { InfoWithDelta } from './components/InfoWithDelta';
|
import { InfoWithDelta } from './components/InfoWithDelta';
|
||||||
|
|
||||||
export function Characteristics() {
|
export function Characteristics() {
|
||||||
|
const mutateDuel = Duel.useMutation();
|
||||||
const exempt = useAdExempt();
|
const exempt = useAdExempt();
|
||||||
const awaitedEquipmentDefinitions = use(equipmentDefinitions);
|
const awaitedEquipmentDefinitions = use(equipmentDefinitions);
|
||||||
const awaitedModelDefinitions = use(modelDefinitions);
|
const awaitedModelDefinitions = use(modelDefinitions);
|
||||||
@@ -41,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 = useDuel((state) => state.protagonist!.crewMastery);
|
const crewMastery = Duel.use((state) => state.protagonist!.crewMastery);
|
||||||
const [penetrationDistance, setPenetrationDistance] = useState(250);
|
const [penetrationDistance, setPenetrationDistance] = useState(250);
|
||||||
|
|
||||||
const provisions = useDuel((state) => state.protagonist!.provisions);
|
const provisions = Duel.use((state) => state.protagonist!.provisions);
|
||||||
const provisionCrewBonus =
|
const provisionCrewBonus =
|
||||||
provisions.reduce(
|
provisions.reduce(
|
||||||
(total, provision) =>
|
(total, provision) =>
|
||||||
@@ -55,12 +56,12 @@ 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 = useDuel((state) => state.protagonist!.consumables);
|
const consumables = Duel.use((state) => state.protagonist!.consumables);
|
||||||
const camouflage = useDuel((state) => state.protagonist!.camouflage);
|
const camouflage = Duel.use((state) => state.protagonist!.camouflage);
|
||||||
const equipmentMatrix = useDuel(
|
const equipmentMatrix = Duel.use(
|
||||||
(state) => state.protagonist!.equipmentMatrix,
|
(state) => state.protagonist!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
const { tank, turret, gun, engine, track, shell } = useDuel(
|
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];
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { hasEquipment } from '../../../../../core/blitzkit/hasEquipment';
|
|||||||
import { modelDefinitions } from '../../../../../core/blitzkit/modelDefinitions';
|
import { modelDefinitions } from '../../../../../core/blitzkit/modelDefinitions';
|
||||||
import { Pose, poseEvent } from '../../../../../core/blitzkit/pose';
|
import { Pose, poseEvent } from '../../../../../core/blitzkit/pose';
|
||||||
import { useAwait } from '../../../../../hooks/useAwait';
|
import { useAwait } from '../../../../../hooks/useAwait';
|
||||||
import { useDuel } from '../../../../../stores/duel';
|
import * as Duel from '../../../../../stores/duel';
|
||||||
import * as TankopediaEphemeral from '../../../../../stores/tankopediaEphemeral';
|
import * as TankopediaEphemeral from '../../../../../stores/tankopediaEphemeral';
|
||||||
|
|
||||||
const poseDistances: Record<Pose, number> = {
|
const poseDistances: Record<Pose, number> = {
|
||||||
@@ -18,13 +18,14 @@ const poseDistances: Record<Pose, number> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function Controls() {
|
export function Controls() {
|
||||||
|
const duelStore = Duel.useStore();
|
||||||
const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
|
const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
|
||||||
const camera = useThree((state) => state.camera);
|
const camera = useThree((state) => state.camera);
|
||||||
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 = useDuel((state) => state.protagonist!);
|
const protagonist = Duel.use((state) => state.protagonist!);
|
||||||
const antagonist = useDuel((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 =
|
||||||
@@ -71,7 +72,7 @@ export function Controls() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
async function handlePoseEvent(event: Pose) {
|
async function handlePoseEvent(event: Pose) {
|
||||||
const duel = useDuel.getState();
|
const duel = duelStore.getState();
|
||||||
const hasImprovedVerticalStabilizer = await hasEquipment(
|
const hasImprovedVerticalStabilizer = await hasEquipment(
|
||||||
122,
|
122,
|
||||||
duel.protagonist!.tank.equipment,
|
duel.protagonist!.tank.equipment,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Heading, Text } from '@radix-ui/themes';
|
import { Heading, Text } from '@radix-ui/themes';
|
||||||
import PageWrapper from '../../../../../components/PageWrapper';
|
import PageWrapper from '../../../../../components/PageWrapper';
|
||||||
import { useDuel } from '../../../../../stores/duel';
|
import * as Duel from '../../../../../stores/duel';
|
||||||
|
|
||||||
export function HistorySection() {
|
export function HistorySection() {
|
||||||
const tank = useDuel((state) => state.protagonist!.tank);
|
const tank = Duel.use((state) => state.protagonist!.tank);
|
||||||
|
|
||||||
if (!tank.description) return null;
|
if (!tank.description) return null;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Environment } from '@react-three/drei';
|
import { Environment } from '@react-three/drei';
|
||||||
import { useModel } from '../../../../../hooks/useModel';
|
import { useModel } from '../../../../../hooks/useModel';
|
||||||
import { useDuel } from '../../../../../stores/duel';
|
import * as Duel from '../../../../../stores/duel';
|
||||||
import * as TankopediaPersistent from '../../../../../stores/tankopediaPersistent';
|
import * as TankopediaPersistent from '../../../../../stores/tankopediaPersistent';
|
||||||
|
|
||||||
export const ENVIRONMENTS = [
|
export const ENVIRONMENTS = [
|
||||||
@@ -12,7 +12,7 @@ export const ENVIRONMENTS = [
|
|||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export function Lighting() {
|
export function Lighting() {
|
||||||
const protagonist = useDuel((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,
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import { useFullScreen } from '../../../../../../hooks/useFullScreen';
|
|||||||
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
|
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
|
||||||
import strings from '../../../../../../lang/en-US.json';
|
import strings from '../../../../../../lang/en-US.json';
|
||||||
import { theme } from '../../../../../../stitches.config';
|
import { theme } from '../../../../../../stitches.config';
|
||||||
import { useDuel } from '../../../../../../stores/duel';
|
import * as Duel from '../../../../../../stores/duel';
|
||||||
import { TankSandbox } from './TankSandbox';
|
import { TankSandbox } from './TankSandbox';
|
||||||
import { Options } from './components/Options';
|
import { Options } from './components/Options';
|
||||||
|
|
||||||
export function HeroSection() {
|
export function HeroSection() {
|
||||||
const protagonist = useDuel((state) => state.protagonist!.tank);
|
const protagonist = Duel.use((state) => state.protagonist!.tank);
|
||||||
const antagonist = useDuel((state) => state.antagonist!.tank);
|
const antagonist = Duel.use((state) => state.antagonist!.tank);
|
||||||
const wideFormat = useWideFormat(880);
|
const wideFormat = useWideFormat(880);
|
||||||
const compareTanks =
|
const compareTanks =
|
||||||
protagonist.id === antagonist.id
|
protagonist.id === antagonist.id
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { modelDefinitions } from '../../../../../../core/blitzkit/modelDefinitio
|
|||||||
import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform';
|
import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform';
|
||||||
import { Pose, poseEvent } from '../../../../../../core/blitzkit/pose';
|
import { Pose, poseEvent } from '../../../../../../core/blitzkit/pose';
|
||||||
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
|
import * as Duel from '../../../../../../stores/duel';
|
||||||
import * as TankopediaEphemeral from '../../../../../../stores/tankopediaEphemeral';
|
import * as TankopediaEphemeral from '../../../../../../stores/tankopediaEphemeral';
|
||||||
import { Controls } from '../Control';
|
import { Controls } from '../Control';
|
||||||
import { Lighting } from '../Lighting';
|
import { Lighting } from '../Lighting';
|
||||||
@@ -20,7 +20,8 @@ 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 = useDuel((state) => state.protagonist!);
|
const protagonist = Duel.use((state) => state.protagonist!);
|
||||||
|
const mutateDuel = Duel.useMutation();
|
||||||
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
|
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
|
||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonist.turret.id];
|
tankModelDefinition.turrets[protagonist.turret.id];
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { asset } from '../../../../../../core/blitzkit/asset';
|
|||||||
import { tankDefinitions } from '../../../../../../core/blitzkit/tankDefinitions';
|
import { tankDefinitions } from '../../../../../../core/blitzkit/tankDefinitions';
|
||||||
import { TIER_ROMAN_NUMERALS } from '../../../../../../core/blitzkit/tankDefinitions/constants';
|
import { TIER_ROMAN_NUMERALS } from '../../../../../../core/blitzkit/tankDefinitions/constants';
|
||||||
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
|
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
|
||||||
import { useDuel } from '../../../../../../stores/duel';
|
import * as Duel from '../../../../../../stores/duel';
|
||||||
|
|
||||||
export function TreeArrow({
|
export function TreeArrow({
|
||||||
style,
|
style,
|
||||||
@@ -53,7 +53,7 @@ export function TreeArrow({
|
|||||||
export function TechTreeSection() {
|
export function TechTreeSection() {
|
||||||
const wideFormat = useWideFormat(720);
|
const wideFormat = useWideFormat(720);
|
||||||
const awaitedTankDefinitions = use(tankDefinitions);
|
const awaitedTankDefinitions = use(tankDefinitions);
|
||||||
const tank = useDuel((state) => state.protagonist!.tank);
|
const tank = Duel.use((state) => state.protagonist!.tank);
|
||||||
|
|
||||||
if (tank.treeType !== 'researchable') return null;
|
if (tank.treeType !== 'researchable') return null;
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import {
|
|||||||
import { useEquipment } from '../../../../../../../hooks/useEquipment';
|
import { useEquipment } from '../../../../../../../hooks/useEquipment';
|
||||||
import { useFullScreen } from '../../../../../../../hooks/useFullScreen';
|
import { useFullScreen } from '../../../../../../../hooks/useFullScreen';
|
||||||
import * as App from '../../../../../../../stores/app';
|
import * as App from '../../../../../../../stores/app';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
import * as Duel from '../../../../../../../stores/duel';
|
||||||
import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral';
|
import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral';
|
||||||
import * as TankopediaPersistent from '../../../../../../../stores/tankopediaPersistent';
|
import * as TankopediaPersistent from '../../../../../../../stores/tankopediaPersistent';
|
||||||
import { TankSearch } from '../../../../components/TankSearch';
|
import { TankSearch } from '../../../../components/TankSearch';
|
||||||
@@ -66,13 +66,14 @@ 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 = useDuel((state) => state.antagonist!.gun);
|
const antagonistGun = Duel.use((state) => state.antagonist!.gun);
|
||||||
const antagonistShell = useDuel((state) => state.antagonist!.shell);
|
const antagonistShell = Duel.use((state) => state.antagonist!.shell);
|
||||||
const [antagonistSelectorOpen, setAntagonistSelectorOpen] = useState(false);
|
const [antagonistSelectorOpen, setAntagonistSelectorOpen] = useState(false);
|
||||||
const antagonistTank = useDuel((state) => state.antagonist!.tank);
|
const antagonistTank = Duel.use((state) => state.antagonist!.tank);
|
||||||
const antagonistTurret = useDuel((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 hasEnhancedArmor = useEquipment(110);
|
const hasEnhancedArmor = useEquipment(110);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -21,12 +21,14 @@ import {
|
|||||||
import { normalizeAngleRad } from '../../../../../../../core/math/normalizeAngleRad';
|
import { normalizeAngleRad } from '../../../../../../../core/math/normalizeAngleRad';
|
||||||
import { useAwait } from '../../../../../../../hooks/useAwait';
|
import { useAwait } from '../../../../../../../hooks/useAwait';
|
||||||
import { useModel } from '../../../../../../../hooks/useModel';
|
import { useModel } from '../../../../../../../hooks/useModel';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
import * as Duel from '../../../../../../../stores/duel';
|
||||||
import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral';
|
import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral';
|
||||||
|
|
||||||
export const TankModel = memo(() => {
|
export const TankModel = memo(() => {
|
||||||
|
const mutateDuel = Duel.useMutation();
|
||||||
|
const duelStore = Duel.useStore();
|
||||||
const awaitedModelDefinitions = useAwait(modelDefinitions);
|
const awaitedModelDefinitions = useAwait(modelDefinitions);
|
||||||
const protagonist = useDuel((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);
|
||||||
@@ -216,7 +218,7 @@ export const TankModel = memo(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function handlePointerMove(event: PointerEvent) {
|
async function handlePointerMove(event: PointerEvent) {
|
||||||
const duel = useDuel.getState();
|
const duel = duelStore.getState();
|
||||||
const hasImprovedVerticalStabilizer = await hasEquipment(
|
const hasImprovedVerticalStabilizer = await hasEquipment(
|
||||||
122,
|
122,
|
||||||
duel.protagonist!.tank.equipment,
|
duel.protagonist!.tank.equipment,
|
||||||
@@ -296,7 +298,7 @@ export const TankModel = memo(() => {
|
|||||||
window.addEventListener('pointerup', handlePointerUp);
|
window.addEventListener('pointerup', handlePointerUp);
|
||||||
}
|
}
|
||||||
async function handlePointerMove(event: PointerEvent) {
|
async function handlePointerMove(event: PointerEvent) {
|
||||||
const duel = useDuel.getState();
|
const duel = duelStore.getState();
|
||||||
const hasImprovedVerticalStabilizer = await hasEquipment(
|
const hasImprovedVerticalStabilizer = await hasEquipment(
|
||||||
122,
|
122,
|
||||||
duel.protagonist!.tank.equipment,
|
duel.protagonist!.tank.equipment,
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ import {
|
|||||||
} from '../../../../../../core/blitzkit/modelTransform';
|
} from '../../../../../../core/blitzkit/modelTransform';
|
||||||
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
||||||
import { useFullScreen } from '../../../../../../hooks/useFullScreen';
|
import { useFullScreen } from '../../../../../../hooks/useFullScreen';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
|
import * as Duel from '../../../../../../stores/duel';
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
|
|
||||||
export function RotationInputs() {
|
export function RotationInputs() {
|
||||||
const protagonist = useDuel((state) => state.protagonist!);
|
const mutateDuel = Duel.useMutation();
|
||||||
|
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);
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
import { CaretRightIcon, UpdateIcon } from '@radix-ui/react-icons';
|
import { CaretRightIcon, UpdateIcon } from '@radix-ui/react-icons';
|
||||||
import { Button, Dialog, Flex, Heading } from '@radix-ui/themes';
|
import { Button, Dialog, Flex, Heading } from '@radix-ui/themes';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useState } from 'react';
|
import { use, useState } from 'react';
|
||||||
import { TREE_TYPE_ICONS } from '../../../../../components/Tanks/components/Item/constants';
|
import { TREE_TYPE_ICONS } from '../../../../../components/Tanks/components/Item/constants';
|
||||||
import { assignDuelMember } from '../../../../../core/blitzkit/assignDuelMember';
|
import { provisionDefinitions } from '../../../../../core/blitzkit/provisionDefinitions';
|
||||||
import { pushTankopediaPath } from '../../../../../core/blitzkit/pushTankopediaPath';
|
import { pushTankopediaPath } from '../../../../../core/blitzkit/pushTankopediaPath';
|
||||||
import { useDuel } from '../../../../../stores/duel';
|
import { tankToDuelMember } from '../../../../../core/blitzkit/tankToDuelMember';
|
||||||
|
import * as Duel from '../../../../../stores/duel';
|
||||||
import { TankSearch } from '../../components/TankSearch';
|
import { TankSearch } from '../../components/TankSearch';
|
||||||
|
|
||||||
export function Title() {
|
export function Title() {
|
||||||
const protagonist = useDuel((state) => state.protagonist!);
|
const awaitedProvisionDefinitions = use(provisionDefinitions);
|
||||||
const antagonist = useDuel((state) => state.antagonist!);
|
const protagonist = Duel.use((state) => state.protagonist!);
|
||||||
|
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]
|
||||||
: [protagonist.tank.id, antagonist.tank.id];
|
: [protagonist.tank.id, antagonist.tank.id];
|
||||||
const [changeTankDialogOpen, setChangeTankDialogOpen] = useState(false);
|
const [changeTankDialogOpen, setChangeTankDialogOpen] = useState(false);
|
||||||
|
const mutateDuel = Duel.useMutation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -76,9 +79,15 @@ export function Title() {
|
|||||||
<TankSearch
|
<TankSearch
|
||||||
compact
|
compact
|
||||||
onSelect={(tank) => {
|
onSelect={(tank) => {
|
||||||
assignDuelMember('protagonist', tank.id);
|
|
||||||
setChangeTankDialogOpen(false);
|
setChangeTankDialogOpen(false);
|
||||||
pushTankopediaPath(tank.id);
|
pushTankopediaPath(tank.id);
|
||||||
|
|
||||||
|
mutateDuel((draft) => {
|
||||||
|
draft.protagonist = tankToDuelMember(
|
||||||
|
tank,
|
||||||
|
awaitedProvisionDefinitions,
|
||||||
|
);
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import { Flex, Heading, Link, Text } from '@radix-ui/themes';
|
|||||||
import { use } from 'react';
|
import { use } from 'react';
|
||||||
import PageWrapper from '../../../../../components/PageWrapper';
|
import PageWrapper from '../../../../../components/PageWrapper';
|
||||||
import { videoDefinitions } from '../../../../../core/blitzkit/videos';
|
import { videoDefinitions } from '../../../../../core/blitzkit/videos';
|
||||||
import { useDuel } from '../../../../../stores/duel';
|
import * as Duel from '../../../../../stores/duel';
|
||||||
|
|
||||||
export function VideoSection() {
|
export function VideoSection() {
|
||||||
const tank = useDuel((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 ?? [];
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,8 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { AdMidSectionResponsive } from '../../../../components/AdMidSectionResponsive';
|
import { AdMidSectionResponsive } from '../../../../components/AdMidSectionResponsive';
|
||||||
import PageWrapper from '../../../../components/PageWrapper';
|
import PageWrapper from '../../../../components/PageWrapper';
|
||||||
import { assignDuelMember } from '../../../../core/blitzkit/assignDuelMember';
|
|
||||||
import { useAdExempt } from '../../../../hooks/useAdExempt';
|
import { useAdExempt } from '../../../../hooks/useAdExempt';
|
||||||
import { mutateDuel, useDuel } from '../../../../stores/duel';
|
import * as Duel from '../../../../stores/duel';
|
||||||
import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral';
|
import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral';
|
||||||
import { HistorySection } from './components/HistorySection';
|
import { HistorySection } from './components/HistorySection';
|
||||||
import { CharacteristicsSection } from './components/Model/CharacteristicsSection';
|
import { CharacteristicsSection } from './components/Model/CharacteristicsSection';
|
||||||
@@ -14,15 +13,14 @@ import { TechTreeSection } from './components/Model/TechTreeSection';
|
|||||||
import { ShotDisplaySection } from './components/ShotDisplaySection';
|
import { ShotDisplaySection } from './components/ShotDisplaySection';
|
||||||
import { VideoSection } from './components/VideoSection';
|
import { VideoSection } from './components/VideoSection';
|
||||||
|
|
||||||
|
// TODO: remove this param if not needed for duel assignment
|
||||||
export default function Page({ params }: { params: { id: string } }) {
|
export default function Page({ params }: { params: { id: string } }) {
|
||||||
const initialId = parseInt(params.id);
|
|
||||||
const assigned = useDuel((state) => state.assigned);
|
|
||||||
const exempt = useAdExempt();
|
const exempt = useAdExempt();
|
||||||
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
|
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
|
||||||
|
const mutateDuel = Duel.useMutation();
|
||||||
|
const duelStore = Duel.useStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
assignDuelMember('both', initialId);
|
|
||||||
|
|
||||||
function handleKeyDown(event: KeyboardEvent) {
|
function handleKeyDown(event: KeyboardEvent) {
|
||||||
if (document.activeElement instanceof HTMLInputElement) return;
|
if (document.activeElement instanceof HTMLInputElement) return;
|
||||||
|
|
||||||
@@ -59,10 +57,10 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('keydown', handleKeyDown);
|
window.removeEventListener('keydown', handleKeyDown);
|
||||||
};
|
};
|
||||||
}, [initialId, assigned]);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = useDuel.subscribe(
|
const unsubscribe = duelStore.subscribe(
|
||||||
(state) => state.protagonist?.tank.id,
|
(state) => state.protagonist?.tank.id,
|
||||||
() => {
|
() => {
|
||||||
mutateTankopediaEphemeral((draft) => {
|
mutateTankopediaEphemeral((draft) => {
|
||||||
@@ -76,19 +74,15 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapper p="0" noMaxWidth color="purple" size={1600}>
|
<PageWrapper p="0" noMaxWidth color="purple" size={1600}>
|
||||||
{assigned && (
|
<HeroSection />
|
||||||
<>
|
<ShotDisplaySection />
|
||||||
<HeroSection />
|
{!exempt && <AdMidSectionResponsive />}
|
||||||
<ShotDisplaySection />
|
<CharacteristicsSection />
|
||||||
{!exempt && <AdMidSectionResponsive />}
|
{!exempt && <AdMidSectionResponsive />}
|
||||||
<CharacteristicsSection />
|
<TechTreeSection />
|
||||||
{!exempt && <AdMidSectionResponsive />}
|
<VideoSection />
|
||||||
<TechTreeSection />
|
{!exempt && <AdMidSectionResponsive />}
|
||||||
<VideoSection />
|
<HistorySection />
|
||||||
{!exempt && <AdMidSectionResponsive />}
|
|
||||||
<HistorySection />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
|
import * as Duel from '../../../stores/duel';
|
||||||
import * as TankopediaEphemeral from '../../../stores/tankopediaEphemeral';
|
import * as TankopediaEphemeral from '../../../stores/tankopediaEphemeral';
|
||||||
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
||||||
import * as TankopediaSort from '../../../stores/tankopediaSort';
|
import * as TankopediaSort from '../../../stores/tankopediaSort';
|
||||||
|
|
||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<TankopediaPersistent.Provider>
|
<Duel.Provider>
|
||||||
<TankopediaEphemeral.Provider>
|
<TankopediaPersistent.Provider>
|
||||||
<TankopediaSort.Provider>{children}</TankopediaSort.Provider>
|
<TankopediaEphemeral.Provider>
|
||||||
</TankopediaEphemeral.Provider>
|
<TankopediaSort.Provider>{children}</TankopediaSort.Provider>
|
||||||
</TankopediaPersistent.Provider>
|
</TankopediaEphemeral.Provider>
|
||||||
|
</TankopediaPersistent.Provider>
|
||||||
|
</Duel.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ 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 { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
||||||
import { useDuel } from '../../../stores/duel';
|
import * as Duel from '../../../stores/duel';
|
||||||
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
||||||
import { CoreArmorSceneComponent } from './CoreArmorSceneComponent';
|
import { CoreArmorSceneComponent } from './CoreArmorSceneComponent';
|
||||||
import { ShotDisplay } from './ShotDisplay';
|
import { ShotDisplay } from './ShotDisplay';
|
||||||
@@ -22,7 +22,7 @@ export const CoreArmorScene = memo(() => {
|
|||||||
const gunContainer = useRef<Group>(null);
|
const gunContainer = useRef<Group>(null);
|
||||||
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
||||||
const initialTankopediaState = tankopediaPersistentStore.getState();
|
const initialTankopediaState = tankopediaPersistentStore.getState();
|
||||||
const protagonist = useDuel((draft) => draft.protagonist!);
|
const protagonist = Duel.use((draft) => draft.protagonist);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!modelDefinitions) return;
|
if (!modelDefinitions) return;
|
||||||
@@ -110,10 +110,10 @@ export const CoreArmorScene = memo(() => {
|
|||||||
return unsubscribe;
|
return unsubscribe;
|
||||||
});
|
});
|
||||||
|
|
||||||
const tank = useDuel((state) => state.protagonist!.tank);
|
const tank = Duel.use((state) => state.protagonist!.tank);
|
||||||
const track = useDuel((state) => state.protagonist!.track);
|
const track = Duel.use((state) => state.protagonist!.track);
|
||||||
const turret = useDuel((state) => state.protagonist!.turret);
|
const turret = Duel.use((state) => state.protagonist!.turret);
|
||||||
const gun = useDuel((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];
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { resolvePenetrationCoefficient } from '../../../../core/blitz/resolvePen
|
|||||||
import { hasEquipment } from '../../../../core/blitzkit/hasEquipment';
|
import { hasEquipment } from '../../../../core/blitzkit/hasEquipment';
|
||||||
import { jsxTree } from '../../../../core/blitzkit/jsxTree';
|
import { jsxTree } from '../../../../core/blitzkit/jsxTree';
|
||||||
import { ShellDefinition } from '../../../../core/blitzkit/tankDefinitions';
|
import { ShellDefinition } from '../../../../core/blitzkit/tankDefinitions';
|
||||||
import { EquipmentMatrix, useDuel } from '../../../../stores/duel';
|
import * as Duel from '../../../../stores/duel';
|
||||||
import * as TankopediaPersistent from '../../../../stores/tankopediaPersistent';
|
import * as TankopediaPersistent from '../../../../stores/tankopediaPersistent';
|
||||||
import fragmentShader from './shaders/fragment.glsl';
|
import fragmentShader from './shaders/fragment.glsl';
|
||||||
import vertexShader from './shaders/vertex.glsl';
|
import vertexShader from './shaders/vertex.glsl';
|
||||||
@@ -29,6 +29,7 @@ export function CoreArmorSceneComponent({
|
|||||||
thickness,
|
thickness,
|
||||||
}: CoreArmorSceneComponentProps) {
|
}: CoreArmorSceneComponentProps) {
|
||||||
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
||||||
|
const duelStore = Duel.useStore();
|
||||||
const material = new ShaderMaterial({
|
const material = new ShaderMaterial({
|
||||||
fragmentShader,
|
fragmentShader,
|
||||||
vertexShader,
|
vertexShader,
|
||||||
@@ -70,7 +71,7 @@ export function CoreArmorSceneComponent({
|
|||||||
material.uniforms.damage.value = shell.damage.armor;
|
material.uniforms.damage.value = shell.damage.armor;
|
||||||
material.uniforms.explosionRadius.value = shell.explosionRadius;
|
material.uniforms.explosionRadius.value = shell.explosionRadius;
|
||||||
|
|
||||||
const duel = useDuel.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);
|
||||||
}
|
}
|
||||||
@@ -83,9 +84,9 @@ export function CoreArmorSceneComponent({
|
|||||||
material.wireframe = visual.wireframe;
|
material.wireframe = visual.wireframe;
|
||||||
}
|
}
|
||||||
async function handleProtagonistEquipmentChange(
|
async function handleProtagonistEquipmentChange(
|
||||||
equipment: EquipmentMatrix,
|
equipment: Duel.EquipmentMatrix,
|
||||||
) {
|
) {
|
||||||
const duel = useDuel.getState();
|
const duel = duelStore.getState();
|
||||||
const hasEnhancedArmor = await hasEquipment(
|
const hasEnhancedArmor = await hasEquipment(
|
||||||
110,
|
110,
|
||||||
duel.protagonist!.tank.equipment,
|
duel.protagonist!.tank.equipment,
|
||||||
@@ -95,8 +96,10 @@ export function CoreArmorSceneComponent({
|
|||||||
? thickness * 1.03
|
? thickness * 1.03
|
||||||
: thickness;
|
: thickness;
|
||||||
}
|
}
|
||||||
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
async function handleAntagonistEquipmentChange(
|
||||||
const duel = useDuel.getState();
|
equipment: Duel.EquipmentMatrix,
|
||||||
|
) {
|
||||||
|
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(
|
||||||
@@ -110,26 +113,29 @@ export function CoreArmorSceneComponent({
|
|||||||
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShellChange(useDuel.getState().antagonist!.shell);
|
handleShellChange(duelStore.getState().antagonist!.shell);
|
||||||
handleVisualChange(tankopediaPersistentStore.getState().model.visual);
|
handleVisualChange(tankopediaPersistentStore.getState().model.visual);
|
||||||
handleProtagonistEquipmentChange(
|
handleProtagonistEquipmentChange(
|
||||||
useDuel.getState().protagonist!.equipmentMatrix,
|
duelStore.getState().protagonist!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
handleAntagonistEquipmentChange(
|
handleAntagonistEquipmentChange(
|
||||||
useDuel.getState().antagonist!.equipmentMatrix,
|
duelStore.getState().antagonist!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
|
|
||||||
const unsubscribes = [
|
const unsubscribes = [
|
||||||
useDuel.subscribe((state) => state.antagonist!.shell, handleShellChange),
|
duelStore.subscribe(
|
||||||
|
(state) => state.antagonist!.shell,
|
||||||
|
handleShellChange,
|
||||||
|
),
|
||||||
tankopediaPersistentStore.subscribe(
|
tankopediaPersistentStore.subscribe(
|
||||||
(state) => state.model.visual,
|
(state) => state.model.visual,
|
||||||
handleVisualChange,
|
handleVisualChange,
|
||||||
),
|
),
|
||||||
useDuel.subscribe(
|
duelStore.subscribe(
|
||||||
(state) => state.protagonist!.equipmentMatrix,
|
(state) => state.protagonist!.equipmentMatrix,
|
||||||
handleProtagonistEquipmentChange,
|
handleProtagonistEquipmentChange,
|
||||||
),
|
),
|
||||||
useDuel.subscribe(
|
duelStore.subscribe(
|
||||||
(state) => state.antagonist!.equipmentMatrix,
|
(state) => state.antagonist!.equipmentMatrix,
|
||||||
handleAntagonistEquipmentChange,
|
handleAntagonistEquipmentChange,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { resolveArmor } from '../../../core/blitzkit/resolveThickness';
|
|||||||
import { useArmor } from '../../../hooks/useArmor';
|
import { useArmor } from '../../../hooks/useArmor';
|
||||||
import { useModel } from '../../../hooks/useModel';
|
import { useModel } from '../../../hooks/useModel';
|
||||||
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
||||||
import { useDuel } from '../../../stores/duel';
|
import * as Duel from '../../../stores/duel';
|
||||||
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
||||||
import { SpacedArmorSceneComponent } from './SpacedArmorSceneComponent';
|
import { SpacedArmorSceneComponent } from './SpacedArmorSceneComponent';
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
|
|||||||
const gunContainer = useRef<Group>(null);
|
const gunContainer = useRef<Group>(null);
|
||||||
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
||||||
const initialTankopediaState = tankopediaPersistentStore.getState();
|
const initialTankopediaState = tankopediaPersistentStore.getState();
|
||||||
const protagonist = useDuel((draft) => draft.protagonist!);
|
const protagonist = Duel.use((draft) => draft.protagonist);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!modelDefinitions) return;
|
if (!modelDefinitions) return;
|
||||||
@@ -120,10 +120,10 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
|
|||||||
return unsubscribe;
|
return unsubscribe;
|
||||||
});
|
});
|
||||||
|
|
||||||
const tank = useDuel((state) => state.protagonist!.tank);
|
const tank = Duel.use((state) => state.protagonist!.tank);
|
||||||
const track = useDuel((state) => state.protagonist!.track);
|
const track = Duel.use((state) => state.protagonist!.track);
|
||||||
const turret = useDuel((state) => state.protagonist!.turret);
|
const turret = Duel.use((state) => state.protagonist!.turret);
|
||||||
const gun = useDuel((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);
|
||||||
|
|||||||
+17
-11
@@ -12,7 +12,7 @@ import { resolvePenetrationCoefficient } from '../../../../../../core/blitz/reso
|
|||||||
import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment';
|
import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment';
|
||||||
import { jsxTree } from '../../../../../../core/blitzkit/jsxTree';
|
import { jsxTree } from '../../../../../../core/blitzkit/jsxTree';
|
||||||
import { ShellDefinition } from '../../../../../../core/blitzkit/tankDefinitions';
|
import { ShellDefinition } from '../../../../../../core/blitzkit/tankDefinitions';
|
||||||
import { EquipmentMatrix, useDuel } from '../../../../../../stores/duel';
|
import * as Duel from '../../../../../../stores/duel';
|
||||||
import { ArmorType } from '../../../SpacedArmorScene';
|
import { ArmorType } from '../../../SpacedArmorScene';
|
||||||
import fragmentShader from './shaders/fragment.glsl';
|
import fragmentShader from './shaders/fragment.glsl';
|
||||||
import vertexShader from './shaders/vertex.glsl';
|
import vertexShader from './shaders/vertex.glsl';
|
||||||
@@ -30,6 +30,7 @@ export function SpacedArmorSubExternal({
|
|||||||
variant,
|
variant,
|
||||||
clip,
|
clip,
|
||||||
}: SpacedArmorSubExternalProps) {
|
}: SpacedArmorSubExternalProps) {
|
||||||
|
const duelStore = Duel.useStore();
|
||||||
const material = new ShaderMaterial({
|
const material = new ShaderMaterial({
|
||||||
fragmentShader,
|
fragmentShader,
|
||||||
vertexShader,
|
vertexShader,
|
||||||
@@ -53,9 +54,9 @@ export function SpacedArmorSubExternal({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
async function handleProtagonistEquipmentChange(
|
async function handleProtagonistEquipmentChange(
|
||||||
equipment: EquipmentMatrix,
|
equipment: Duel.EquipmentMatrix,
|
||||||
) {
|
) {
|
||||||
const duel = useDuel.getState();
|
const duel = duelStore.getState();
|
||||||
const hasEnhancedArmor = await hasEquipment(
|
const hasEnhancedArmor = await hasEquipment(
|
||||||
110,
|
110,
|
||||||
duel.protagonist!.tank.equipment,
|
duel.protagonist!.tank.equipment,
|
||||||
@@ -65,8 +66,10 @@ export function SpacedArmorSubExternal({
|
|||||||
? thickness * 1.03
|
? thickness * 1.03
|
||||||
: thickness;
|
: thickness;
|
||||||
}
|
}
|
||||||
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
async function handleAntagonistEquipmentChange(
|
||||||
const duel = useDuel.getState();
|
equipment: Duel.EquipmentMatrix,
|
||||||
|
) {
|
||||||
|
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(
|
||||||
@@ -80,21 +83,24 @@ export function SpacedArmorSubExternal({
|
|||||||
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShellChange(useDuel.getState().antagonist!.shell);
|
handleShellChange(duelStore.getState().antagonist!.shell);
|
||||||
handleProtagonistEquipmentChange(
|
handleProtagonistEquipmentChange(
|
||||||
useDuel.getState().protagonist!.equipmentMatrix,
|
duelStore.getState().protagonist!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
handleAntagonistEquipmentChange(
|
handleAntagonistEquipmentChange(
|
||||||
useDuel.getState().antagonist!.equipmentMatrix,
|
duelStore.getState().antagonist!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
|
|
||||||
const unsubscribes = [
|
const unsubscribes = [
|
||||||
useDuel.subscribe((state) => state.antagonist!.shell, handleShellChange),
|
duelStore.subscribe(
|
||||||
useDuel.subscribe(
|
(state) => state.antagonist!.shell,
|
||||||
|
handleShellChange,
|
||||||
|
),
|
||||||
|
duelStore.subscribe(
|
||||||
(state) => state.protagonist!.equipmentMatrix,
|
(state) => state.protagonist!.equipmentMatrix,
|
||||||
handleProtagonistEquipmentChange,
|
handleProtagonistEquipmentChange,
|
||||||
),
|
),
|
||||||
useDuel.subscribe(
|
duelStore.subscribe(
|
||||||
(state) => state.antagonist!.equipmentMatrix,
|
(state) => state.antagonist!.equipmentMatrix,
|
||||||
handleAntagonistEquipmentChange,
|
handleAntagonistEquipmentChange,
|
||||||
),
|
),
|
||||||
|
|||||||
+18
-12
@@ -13,7 +13,7 @@ import { resolvePenetrationCoefficient } from '../../../../../../core/blitz/reso
|
|||||||
import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment';
|
import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment';
|
||||||
import { jsxTree } from '../../../../../../core/blitzkit/jsxTree';
|
import { jsxTree } from '../../../../../../core/blitzkit/jsxTree';
|
||||||
import { ShellDefinition } from '../../../../../../core/blitzkit/tankDefinitions';
|
import { ShellDefinition } from '../../../../../../core/blitzkit/tankDefinitions';
|
||||||
import { EquipmentMatrix, useDuel } from '../../../../../../stores/duel';
|
import * as Duel from '../../../../../../stores/duel';
|
||||||
import { ArmorType } from '../../../SpacedArmorScene';
|
import { ArmorType } from '../../../SpacedArmorScene';
|
||||||
import fragmentShader from './shaders/fragment.glsl';
|
import fragmentShader from './shaders/fragment.glsl';
|
||||||
import vertexShader from './shaders/vertex.glsl';
|
import vertexShader from './shaders/vertex.glsl';
|
||||||
@@ -32,6 +32,7 @@ export function SpacedArmorSubSpaced({
|
|||||||
node,
|
node,
|
||||||
thickness,
|
thickness,
|
||||||
}: SpacedArmorSubSpacedProps) {
|
}: SpacedArmorSubSpacedProps) {
|
||||||
|
const duelStore = Duel.useStore();
|
||||||
const material = new ShaderMaterial({
|
const material = new ShaderMaterial({
|
||||||
fragmentShader,
|
fragmentShader,
|
||||||
vertexShader,
|
vertexShader,
|
||||||
@@ -63,9 +64,9 @@ export function SpacedArmorSubSpaced({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
async function handleProtagonistEquipmentChange(
|
async function handleProtagonistEquipmentChange(
|
||||||
equipment: EquipmentMatrix,
|
equipment: Duel.EquipmentMatrix,
|
||||||
) {
|
) {
|
||||||
const duel = useDuel.getState();
|
const duel = duelStore.getState();
|
||||||
const hasEnhancedArmor = await hasEquipment(
|
const hasEnhancedArmor = await hasEquipment(
|
||||||
110,
|
110,
|
||||||
duel.protagonist!.tank.equipment,
|
duel.protagonist!.tank.equipment,
|
||||||
@@ -75,9 +76,11 @@ export function SpacedArmorSubSpaced({
|
|||||||
? thickness * 1.03
|
? thickness * 1.03
|
||||||
: thickness;
|
: thickness;
|
||||||
}
|
}
|
||||||
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
async function handleAntagonistEquipmentChange(
|
||||||
const duel = useDuel.getState();
|
equipment: Duel.EquipmentMatrix,
|
||||||
const shell = useDuel.getState().antagonist!.shell;
|
) {
|
||||||
|
const duel = duelStore.getState();
|
||||||
|
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,
|
||||||
@@ -90,21 +93,24 @@ export function SpacedArmorSubSpaced({
|
|||||||
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShellChange(useDuel.getState().antagonist!.shell);
|
handleShellChange(duelStore.getState().antagonist!.shell);
|
||||||
handleProtagonistEquipmentChange(
|
handleProtagonistEquipmentChange(
|
||||||
useDuel.getState().protagonist!.equipmentMatrix,
|
duelStore.getState().protagonist!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
handleAntagonistEquipmentChange(
|
handleAntagonistEquipmentChange(
|
||||||
useDuel.getState().antagonist!.equipmentMatrix,
|
duelStore.getState().antagonist!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
|
|
||||||
const unsubscribes = [
|
const unsubscribes = [
|
||||||
useDuel.subscribe((state) => state.antagonist!.shell, handleShellChange),
|
duelStore.subscribe(
|
||||||
useDuel.subscribe(
|
(state) => state.antagonist!.shell,
|
||||||
|
handleShellChange,
|
||||||
|
),
|
||||||
|
duelStore.subscribe(
|
||||||
(state) => state.protagonist!.equipmentMatrix,
|
(state) => state.protagonist!.equipmentMatrix,
|
||||||
handleProtagonistEquipmentChange,
|
handleProtagonistEquipmentChange,
|
||||||
),
|
),
|
||||||
useDuel.subscribe(
|
duelStore.subscribe(
|
||||||
(state) => state.antagonist!.equipmentMatrix,
|
(state) => state.antagonist!.equipmentMatrix,
|
||||||
handleAntagonistEquipmentChange,
|
handleAntagonistEquipmentChange,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { resolvePenetrationCoefficient } from '../../../../core/blitz/resolvePen
|
|||||||
import { hasEquipment } from '../../../../core/blitzkit/hasEquipment';
|
import { hasEquipment } from '../../../../core/blitzkit/hasEquipment';
|
||||||
import { jsxTree } from '../../../../core/blitzkit/jsxTree';
|
import { jsxTree } from '../../../../core/blitzkit/jsxTree';
|
||||||
import { ShellType } from '../../../../core/blitzkit/tankDefinitions';
|
import { ShellType } from '../../../../core/blitzkit/tankDefinitions';
|
||||||
import { useDuel } from '../../../../stores/duel';
|
import * as Duel from '../../../../stores/duel';
|
||||||
import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral';
|
import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral';
|
||||||
import { ArmorType } from '../SpacedArmorScene';
|
import { ArmorType } from '../SpacedArmorScene';
|
||||||
import { SpacedArmorSubExternal } from './components/SpacedArmorSubExternal';
|
import { SpacedArmorSubExternal } from './components/SpacedArmorSubExternal';
|
||||||
@@ -74,6 +74,7 @@ export function SpacedArmorSceneComponent({
|
|||||||
}: SpacedArmorSceneComponentProps) {
|
}: SpacedArmorSceneComponentProps) {
|
||||||
const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
|
const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
|
||||||
const camera = useThree((state) => state.camera);
|
const camera = useThree((state) => state.camera);
|
||||||
|
const duelStore = Duel.useStore();
|
||||||
|
|
||||||
async function shoot(
|
async function shoot(
|
||||||
point: Vector3,
|
point: Vector3,
|
||||||
@@ -81,7 +82,7 @@ export function SpacedArmorSceneComponent({
|
|||||||
allowRicochet: boolean,
|
allowRicochet: boolean,
|
||||||
remainingPenetrationInput?: number,
|
remainingPenetrationInput?: number,
|
||||||
) {
|
) {
|
||||||
const { antagonist, protagonist } = useDuel.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 = {
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import { mutateDuel } from '../../stores/duel';
|
|
||||||
import { provisionDefinitions } from './provisionDefinitions';
|
|
||||||
import { tankDefinitions } from './tankDefinitions';
|
|
||||||
import { tankToDuelMember } from './tankToDuelMember';
|
|
||||||
|
|
||||||
export async function assignDuelMember(
|
|
||||||
type: 'antagonist' | 'protagonist' | 'both',
|
|
||||||
id: number,
|
|
||||||
) {
|
|
||||||
const awaitedTankDefinitions = await tankDefinitions;
|
|
||||||
const awaitedProvisionDefinitions = await provisionDefinitions;
|
|
||||||
const tank = awaitedTankDefinitions[id];
|
|
||||||
const member = tankToDuelMember(tank, awaitedProvisionDefinitions);
|
|
||||||
|
|
||||||
mutateDuel((draft) => {
|
|
||||||
draft.assigned = true;
|
|
||||||
if (type === 'antagonist') {
|
|
||||||
draft.antagonist = member;
|
|
||||||
} else if (type === 'protagonist') {
|
|
||||||
draft.protagonist = member;
|
|
||||||
} else {
|
|
||||||
draft.protagonist = member;
|
|
||||||
draft.antagonist = { ...member };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,13 @@
|
|||||||
import { Draft, produce } from 'immer';
|
import { Draft, produce } from 'immer';
|
||||||
import { createContext, ReactNode, useContext, useRef } from 'react';
|
import { usePathname } from 'next/navigation';
|
||||||
|
import {
|
||||||
|
createContext,
|
||||||
|
ReactNode,
|
||||||
|
useContext,
|
||||||
|
useMemo,
|
||||||
|
use as useReact,
|
||||||
|
useRef,
|
||||||
|
} from 'react';
|
||||||
import { StoreApi, useStore as useStoreZustand } from 'zustand';
|
import { StoreApi, useStore as useStoreZustand } from 'zustand';
|
||||||
|
|
||||||
interface StoreProviderProps {
|
interface StoreProviderProps {
|
||||||
@@ -13,16 +21,24 @@ type ExtractState<S> = S extends {
|
|||||||
? T
|
? T
|
||||||
: never;
|
: never;
|
||||||
|
|
||||||
|
interface InitialContext {
|
||||||
|
pathName: string;
|
||||||
|
}
|
||||||
|
|
||||||
export function createNextSafeStore<Store extends StoreApi<unknown>>(
|
export function createNextSafeStore<Store extends StoreApi<unknown>>(
|
||||||
initial: () => Store,
|
initial: (context: InitialContext) => Store | Promise<Store>,
|
||||||
) {
|
) {
|
||||||
type Type = Store extends StoreApi<infer T> ? T : never;
|
type Type = Store extends StoreApi<infer T> ? T : never;
|
||||||
|
|
||||||
const Context = createContext<Store | undefined>(undefined);
|
const Context = createContext<Store | undefined>(undefined);
|
||||||
|
|
||||||
function Provider({ children }: StoreProviderProps) {
|
function Provider({ children }: StoreProviderProps) {
|
||||||
|
const pathName = usePathname();
|
||||||
const storeRef = useRef<Store>();
|
const storeRef = useRef<Store>();
|
||||||
if (!storeRef.current) storeRef.current = initial() as Store;
|
const context = { pathName };
|
||||||
|
const storePromise = useMemo(async () => await initial(context), []);
|
||||||
|
const awaitedStore = useReact(storePromise);
|
||||||
|
if (!storeRef.current) storeRef.current = awaitedStore;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Context.Provider value={storeRef.current}>{children}</Context.Provider>
|
<Context.Provider value={storeRef.current}>{children}</Context.Provider>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
TankDefinition,
|
TankDefinition,
|
||||||
tankDefinitions,
|
tankDefinitions,
|
||||||
} from '../core/blitzkit/tankDefinitions';
|
} from '../core/blitzkit/tankDefinitions';
|
||||||
import { useDuel } from '../stores/duel';
|
import * as Duel from '../stores/duel';
|
||||||
|
|
||||||
export enum UseEccentricityMode {
|
export enum UseEccentricityMode {
|
||||||
Tier,
|
Tier,
|
||||||
@@ -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 = useDuel((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,15 +1,15 @@
|
|||||||
import { use, useMemo } from 'react';
|
import { use, useMemo } from 'react';
|
||||||
import { equipmentDefinitions } from '../core/blitzkit/equipmentDefinitions';
|
import { equipmentDefinitions } from '../core/blitzkit/equipmentDefinitions';
|
||||||
import { useDuel } from '../stores/duel';
|
import * as Duel from '../stores/duel';
|
||||||
|
|
||||||
export function useEquipment(id: number, antagonist = false) {
|
export function useEquipment(id: number, antagonist = false) {
|
||||||
const awaitedEquipmentDefinitions = use(equipmentDefinitions);
|
const awaitedEquipmentDefinitions = use(equipmentDefinitions);
|
||||||
const member = useDuel(
|
const member = Duel.use(
|
||||||
(state) => state[antagonist ? 'antagonist' : 'protagonist']!,
|
(state) => state[antagonist ? 'antagonist' : 'protagonist']!,
|
||||||
);
|
);
|
||||||
const equipmentRows =
|
const equipmentRows =
|
||||||
awaitedEquipmentDefinitions.presets[member.tank.equipment];
|
awaitedEquipmentDefinitions.presets[member.tank.equipment];
|
||||||
const equipmentMatrix = useDuel(
|
const equipmentMatrix = Duel.use(
|
||||||
(state) =>
|
(state) =>
|
||||||
state[antagonist ? 'antagonist' : 'protagonist']!.equipmentMatrix,
|
state[antagonist ? 'antagonist' : 'protagonist']!.equipmentMatrix,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useDuel } from '../stores/duel';
|
import * as Duel from '../stores/duel';
|
||||||
|
|
||||||
export function useProvision(id: number) {
|
export function useProvision(id: number) {
|
||||||
const provisions = useDuel((state) => state.protagonist!.provisions);
|
const provisions = Duel.use((state) => state.protagonist!.provisions);
|
||||||
return provisions.includes(id);
|
return provisions.includes(id);
|
||||||
}
|
}
|
||||||
+23
-12
@@ -1,14 +1,19 @@
|
|||||||
import { produce } from 'immer';
|
'use client';
|
||||||
|
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { subscribeWithSelector } from 'zustand/middleware';
|
import { subscribeWithSelector } from 'zustand/middleware';
|
||||||
|
import { provisionDefinitions } from '../../core/blitzkit/provisionDefinitions';
|
||||||
import {
|
import {
|
||||||
EngineDefinition,
|
EngineDefinition,
|
||||||
GunDefinition,
|
GunDefinition,
|
||||||
ShellDefinition,
|
ShellDefinition,
|
||||||
TankDefinition,
|
TankDefinition,
|
||||||
|
tankDefinitions,
|
||||||
TrackDefinition,
|
TrackDefinition,
|
||||||
TurretDefinition,
|
TurretDefinition,
|
||||||
} from '../../core/blitzkit/tankDefinitions';
|
} from '../../core/blitzkit/tankDefinitions';
|
||||||
|
import { tankToDuelMember } from '../../core/blitzkit/tankToDuelMember';
|
||||||
|
import { createNextSafeStore } from '../../core/zustand/createNextSafeStore';
|
||||||
|
|
||||||
type EquipmentMatrixItem = -1 | 0 | 1;
|
type EquipmentMatrixItem = -1 | 0 | 1;
|
||||||
type EquipmentMatrixRow = [
|
type EquipmentMatrixRow = [
|
||||||
@@ -40,17 +45,23 @@ export interface DuelMember {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Duel {
|
export interface Duel {
|
||||||
assigned: boolean;
|
protagonist: DuelMember;
|
||||||
protagonist?: DuelMember;
|
antagonist: DuelMember;
|
||||||
antagonist?: DuelMember;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useDuel = create<Duel>()(
|
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
|
||||||
subscribeWithSelector<Duel>(() => ({
|
async ({ pathName }) => {
|
||||||
assigned: false,
|
const id = Number(pathName.split('/')[3]);
|
||||||
})),
|
const awaitedTankDefinitions = await tankDefinitions;
|
||||||
|
const awaitedProvisionDefinitions = await provisionDefinitions;
|
||||||
|
const tank = awaitedTankDefinitions[id];
|
||||||
|
const protagonist = tankToDuelMember(tank, awaitedProvisionDefinitions);
|
||||||
|
|
||||||
|
return create<Duel>()(
|
||||||
|
subscribeWithSelector<Duel>(() => ({
|
||||||
|
protagonist,
|
||||||
|
antagonist: protagonist,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export function mutateDuel(recipe: (draft: Duel) => void) {
|
|
||||||
useDuel.setState(produce(recipe));
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { mintDark } from '@radix-ui/colors';
|
|
||||||
import { createColors } from 'bepaint';
|
|
||||||
|
|
||||||
export const mintTheme = {
|
|
||||||
colors: createColors(mintDark),
|
|
||||||
};
|
|
||||||
Reference in new issue
Block a user