Files
blitzkit/packages/website/src/stores/tankopedia.ts
T

123 lines
3.0 KiB
TypeScript
Raw Normal View History

2024-10-18 11:20:52 -05:00
import {
createDefaultSkills,
2024-11-10 20:50:46 -06:00
ShellDefinition,
2024-10-18 11:20:52 -05:00
type ModelDefinition,
2025-09-01 22:56:39 -05:00
} from "@blitzkit/core";
import type { Vector3 } from "three";
import { Varuna } from "varuna";
import type { ArmorType } from "../components/Armor/components/SpacedArmorScene";
import type { ExternalModuleVariant } from "../components/Armor/components/SpacedArmorSceneComponent";
import type { XP_MULTIPLIERS } from "../components/Tankopedia/TechTreeSection";
2026-08-04 14:02:52 -05:00
import { api } from "../core/blitzkit/api";
import { App } from "./app";
2025-09-01 22:56:39 -05:00
import { TankopediaDisplay } from "./tankopediaPersistent/constants";
2024-07-09 14:43:33 -05:00
export interface ShotLayerBase {
index: number;
thickness: number;
point: Vector3;
surfaceNormal: Vector3;
2025-09-01 22:56:39 -05:00
status: "blocked" | "penetration" | "ricochet";
2024-07-09 14:43:33 -05:00
}
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;
2025-09-01 22:56:39 -05:00
status: "penetration" | "blocked";
2024-07-09 14:43:33 -05:00
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[];
};
};
2025-09-01 22:56:39 -05:00
export type ShotStatus = "penetration" | "blocked" | "ricochet" | "splash";
2024-07-09 14:43:33 -05:00
export type ArmorPiercingLayer =
| {
distance: number;
nominal: number;
angled: number;
ricochet: boolean;
2025-09-01 22:56:39 -05:00
type: "core" | "spaced" | "external";
2024-07-09 14:43:33 -05:00
}
| {
2025-09-01 22:56:39 -05:00
type: "gap";
2024-07-09 14:43:33 -05:00
gap: number;
};
2024-11-12 20:58:05 -06:00
export enum TankopediaRelativeAgainst {
Class,
Tier,
All,
}
2025-09-01 22:56:39 -05:00
interface Tankopedia {
2025-04-14 19:26:41 -05:00
disturbed: boolean;
2025-04-15 00:35:12 -05:00
revealed: boolean;
modelRequested: boolean;
2024-09-21 20:26:58 -05:00
shot?: Shot;
skills: Record<string, number>;
2024-11-12 20:58:05 -06:00
relativeAgainst: TankopediaRelativeAgainst;
2024-09-21 20:26:58 -05:00
model: ModelDefinition;
editStatic: boolean;
highlightArmor?: {
editingPlate: boolean;
name: string;
point: Vector3;
thickness: number;
color: string;
} & (
| {
type: ArmorType.Primary | ArmorType.Spaced;
thicknessAngled: number;
angle: number;
}
| { type: ArmorType.External }
2024-09-14 18:32:36 -05:00
);
2024-09-21 20:26:58 -05:00
xpMultiplier: (typeof XP_MULTIPLIERS)[number];
2024-11-10 20:50:46 -06:00
customShell?: ShellDefinition;
2025-11-26 21:10:03 -06:00
requestedDisplay: TankopediaDisplay;
2024-12-01 20:23:23 -06:00
display: TankopediaDisplay;
2025-04-24 22:04:33 -05:00
statSearch?: string;
2024-09-21 20:26:58 -05:00
}
2024-09-22 21:12:18 -05:00
2026-08-04 14:02:52 -05:00
const skillDefinitions = await api.skillDefinitions();
2024-10-18 11:20:52 -05:00
2025-09-01 22:56:39 -05:00
export const Tankopedia = new Varuna<Tankopedia, ModelDefinition>((model) => ({
2025-09-01 18:51:04 -05:00
disturbed: false,
revealed: false,
modelRequested: App.state.autoLoadModels,
2025-09-01 18:51:04 -05:00
relativeAgainst: TankopediaRelativeAgainst.Class,
editStatic: false,
skills: createDefaultSkills(skillDefinitions),
model,
xpMultiplier: 1,
2025-11-26 21:10:03 -06:00
requestedDisplay: TankopediaDisplay.Model,
2025-09-01 18:51:04 -05:00
display: TankopediaDisplay.Model,
}));