Files
blitzkit/packages/website-legacy/src/stores/tankopediaEphemeral.ts
T

105 lines
2.5 KiB
TypeScript
Raw Normal View History

2024-07-09 14:45:29 -05:00
'use client';
2024-09-08 10:42:34 -05:00
import { ModelDefinition } from '@blitzkit/core';
2024-07-09 14:43:33 -05:00
import { Vector3 } from 'three';
import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
2024-08-25 21:06:56 -05:00
import { XP_MULTIPLIERS } from '../app/tools/tankopedia/[id]/components/Model/TechTreeSection';
2024-09-07 21:45:00 -05:00
import { ArmorType } from '../components/Armor/components/SpacedArmorScene';
import { ExternalModuleVariant } from '../components/Armor/components/SpacedArmorSceneComponent';
2024-09-08 10:42:34 -05:00
import { createNextSafeStore } from '../core/zustand/createNextSafeStore';
2024-07-09 14:43:33 -05:00
interface TankopediaEphemeral {
shot?: Shot;
skills: Record<string, number>;
controlsEnabled: boolean;
2024-07-30 13:24:55 -05:00
model: ModelDefinition;
2024-07-31 13:11:25 -05:00
editStatic: boolean;
2024-07-29 13:22:20 -05:00
highlightArmor?: {
2024-08-01 14:00:43 -05:00
editingPlate: boolean;
2024-07-29 13:22:20 -05:00
name: string;
point: Vector3;
thickness: number;
color: string;
} & (
| {
2024-07-29 20:46:57 -05:00
type: ArmorType.Primary | ArmorType.Spaced;
2024-07-29 13:22:20 -05:00
thicknessAngled: number;
angle: number;
}
| { type: ArmorType.External }
);
2024-08-25 21:06:56 -05:00
xpMultiplier: (typeof XP_MULTIPLIERS)[number];
2024-07-09 14:43:33 -05:00
}
export interface ShotLayerBase {
index: number;
thickness: number;
point: Vector3;
surfaceNormal: Vector3;
status: 'blocked' | 'penetration' | 'ricochet';
}
interface ShotLayerExternal extends ShotLayerBase {
type: ArmorType.External;
variant: ExternalModuleVariant;
}
export interface ShotLayerNonExternal extends ShotLayerBase {
type: Exclude<ArmorType, ArmorType.External>;
angle: number;
thicknessAngled: number;
}
export interface ShotLayerGap {
type: null;
status: 'penetration' | 'blocked';
distance: number;
}
export type ShotLayer = ShotLayerExternal | ShotLayerNonExternal | ShotLayerGap;
export type Shot = {
containsGaps: boolean;
damage: number;
2024-07-23 21:01:32 -05:00
splashRadius?: number;
2024-07-09 14:43:33 -05:00
in: {
surfaceNormal: Vector3;
status: ShotStatus;
layers: ShotLayer[];
};
out?: {
surfaceNormal: Vector3;
status: ShotStatus;
layers: ShotLayer[];
};
};
export type ShotStatus = 'penetration' | 'blocked' | 'ricochet' | 'splash';
export type ArmorPiercingLayer =
| {
distance: number;
nominal: number;
angled: number;
ricochet: boolean;
type: 'core' | 'spaced' | 'external';
}
| {
type: 'gap';
gap: number;
};
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
2024-07-30 13:24:55 -05:00
(model: ModelDefinition) =>
2024-07-09 14:43:33 -05:00
create<TankopediaEphemeral>()(
subscribeWithSelector<TankopediaEphemeral>(() => ({
2024-07-31 13:11:25 -05:00
editStatic: false,
2024-07-09 14:43:33 -05:00
skills: {},
2024-07-30 13:24:55 -05:00
model,
2024-07-09 14:43:33 -05:00
controlsEnabled: true,
2024-08-25 21:06:56 -05:00
xpMultiplier: 1,
2024-07-09 14:43:33 -05:00
})),
),
);