feat: some hero code

This commit is contained in:
tresabhi committed 2025-03-20 12:33:36 -05:00
1 parent b856268ee0
commit 46374a7a26
11 files changed
+287 -327

No files matched your search

@@ -1,64 +0,0 @@
import { TankType } from '@blitzkit/core';
import { PageWrapper } from '../../../../../components/PageWrapper';
import { CalloutsSection } from '../../../../../components/Tankopedia/CalloutsSection';
import { CharacteristicsSection } from '../../../../../components/Tankopedia/CharacteristicsSection';
import { GameModeSection } from '../../../../../components/Tankopedia/GameModeSection';
import { HeroSection } from '../../../../../components/Tankopedia/HeroSection';
import { MetaSection } from '../../../../../components/Tankopedia/MetaSection';
import { TechTreeSection } from '../../../../../components/Tankopedia/TechTreeSection';
import { VideoSection } from '../../../../../components/Tankopedia/VideoSection';
import { awaitableModelDefinitions } from '../../../../../core/awaitables/modelDefinitions';
import { awaitableProvisionDefinitions } from '../../../../../core/awaitables/provisionDefinitions';
import { awaitableTankDefinitions } from '../../../../../core/awaitables/tankDefinitions';
import {
LocaleProvider,
type LocaleAcceptorProps,
} from '../../../../../hooks/useLocale';
import { App } from '../../../../../stores/app';
import { Duel } from '../../../../../stores/duel';
import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
import { TankopediaPersistent } from '../../../../../stores/tankopediaPersistent';
import type { MaybeSkeletonComponentProps } from '../../../../../types/maybeSkeletonComponentProps';
type PageProps = MaybeSkeletonComponentProps &
LocaleAcceptorProps & {
id: number;
};
const [tankDefinitions, provisionDefinitions, modelDefinitions] =
await Promise.all([
awaitableTankDefinitions,
awaitableProvisionDefinitions,
awaitableModelDefinitions,
]);
export function Page({ id, skeleton, locale }: PageProps) {
const tank = tankDefinitions.tanks[id];
const model = modelDefinitions.models[id];
return (
<LocaleProvider locale={locale}>
<TankopediaEphemeral.Provider data={model}>
<App.Provider>
<TankopediaPersistent.Provider>
<Duel.Provider
data={{ tank, provisionDefinitions: provisionDefinitions }}
>
<PageWrapper p="0" maxWidth="unset" color="purple" gap="9" pb="9">
<HeroSection skeleton={skeleton} />
<CalloutsSection />
<MetaSection />
{tank.type === TankType.RESEARCHABLE && !tank.deprecated && (
<TechTreeSection skeleton={skeleton} />
)}
<CharacteristicsSection />
<GameModeSection />
<VideoSection skeleton={skeleton} />
</PageWrapper>
</Duel.Provider>
</TankopediaPersistent.Provider>
</App.Provider>
</TankopediaEphemeral.Provider>
</LocaleProvider>
);
}
@@ -1,110 +0,0 @@
---
import {
asset,
createDefaultProvisions,
createDefaultSkills,
fetchEquipmentDefinitions,
fetchModelDefinitions,
fetchProvisionDefinitions,
fetchSkillDefinitions,
fetchTankDefinitions,
TIER_ROMAN_NUMERALS,
} from '@blitzkit/core';
import { DEFAULT_LOCALE, unwrapper } from '@blitzkit/i18n';
import { literals } from '@blitzkit/i18n/src/literals';
import type { GetStaticPaths } from 'astro';
import { tankCharacteristics } from '../../../../../core/blitzkit/tankCharacteristics';
import { getStrings } from '../../../../../core/i18n/getStrings';
import BaseLayout from '../../../../../layouts/BaseLayout.astro';
import { genericDefaultEquipmentMatrix } from '../../../../../stores/duel/constants';
import { getStaticPaths as parentGetStaticPaths } from '../index.astro';
import { Page } from './_index';
export const getStaticPaths = (async () => {
const tankDefinitions = await fetchTankDefinitions();
const parentPaths = parentGetStaticPaths();
return Object.values(tankDefinitions.tanks)
.map((tank) =>
parentPaths.map((parent) => ({
params: { ...parent.params, id: tank.id },
})),
)
.flat();
}) satisfies GetStaticPaths;
const { id } = Astro.params;
const locale = Astro.params.locale ?? DEFAULT_LOCALE;
const strings = getStrings(locale);
const tankDefinitions = await fetchTankDefinitions();
const skillDefinitions = await fetchSkillDefinitions();
const provisionDefinitions = await fetchProvisionDefinitions();
const equipmentDefinitions = await fetchEquipmentDefinitions();
const tankModelDefinitions = await fetchModelDefinitions();
const tank = tankDefinitions.tanks[id];
const tankModelDefinition = tankModelDefinitions.models[tank.id];
const name = tank.name_full ?? tank.name;
const unwrap = unwrapper(locale);
const title = literals(strings.website.tools.tanks.tank_seo_title, [
unwrap(name),
TIER_ROMAN_NUMERALS[tank.tier],
strings.common.nations_adjectives[
tank.nation as keyof typeof strings.common.nations_adjectives
],
strings.common.tank_class_short[tank.class],
'BlitzKit',
strings.common.nations[tank.nation as keyof typeof strings.common.nations],
]);
const url = import.meta.env.SITE + Astro.url.pathname;
const icon = asset(`icons/tanks/big/${id}.webp`);
const turret = tank.turrets.at(-1)!;
const gun = turret.guns.at(-1)!;
const characteristics = tankCharacteristics(
{
tank,
applyDynamicArmor: false,
applyReactiveArmor: false,
applySpallLiner: false,
camouflage: true,
consumables: [],
crewSkills: createDefaultSkills(skillDefinitions),
engine: tank.engines.at(-1)!,
equipmentMatrix: genericDefaultEquipmentMatrix,
turret,
gun,
provisions: createDefaultProvisions(tank, gun, provisionDefinitions),
shell: gun.gun_type!.value.base.shells[0],
stockEngine: tank.engines[0],
stockGun: tank.turrets[0].guns[0],
stockTurret: tank.turrets[0],
stockTrack: tank.tracks[0],
track: tank.tracks.at(-1)!,
},
{ equipmentDefinitions, provisionDefinitions, tankModelDefinition },
);
const description = literals(strings.website.tools.tanks.tank_seo_description, [
unwrap(name),
Math.round(characteristics.dpm).toLocaleString(locale),
Math.round(characteristics.damage).toLocaleString(locale),
Math.round(characteristics.penetration).toLocaleString(locale),
Math.round(characteristics.speedForwards).toLocaleString(locale),
Math.round(characteristics.health).toLocaleString(locale),
]);
---
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta property="og:image" content={icon} />
<meta property="og:url" content={url} />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:card" content="summary" />
<meta name="twitter:image:src" content={icon} />
<BaseLayout>
<Page {locale} id={id} client:only="react">
<Page {locale} id={id} skeleton slot="fallback" />
</Page>
</BaseLayout>
@@ -1,9 +1,8 @@
import { asset } from '@blitzkit/core';
import { Flex, type FlexProps, Progress } from '@radix-ui/themes';
import { Box, Flex, type FlexProps, Progress } from '@radix-ui/themes';
import { useProgress } from '@react-three/drei';
type TankSandboxLoaderProps = Omit<FlexProps, 'id'> & {
id: number;
id: string;
};
export function TankSandboxLoader({ id, ...props }: TankSandboxLoaderProps) {
@@ -11,9 +10,15 @@ export function TankSandboxLoader({ id, ...props }: TankSandboxLoaderProps) {
return (
<Flex width="100%" height="100%" align="center" justify="center" {...props}>
<img
src={asset(`icons/tanks/blitzkit/${id}.webp`)}
style={{ height: '75%', filter: 'blur(1rem)' }}
<Box
height="100%"
width="100%"
style={{
filter: 'blur(1rem)',
backgroundImage: `url(/api/tanks/${id}/icons/big.png)`,
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}}
/>
<Progress
size="3"
@@ -1,77 +1,70 @@
import { TankType } from '@blitzkit/core';
import { Box, Flex, Heading, Text } from '@radix-ui/themes';
import { times } from 'lodash-es';
import { Suspense, useEffect, useMemo, useRef } from 'react';
import { useRef } from 'react';
import { NAVBAR_HEIGHT } from '../../../constants/navbar';
import { awaitableTankDefinitions } from '../../../core/awaitables/tankDefinitions';
import { Var } from '../../../core/radix/var';
import { useFullScreen } from '../../../hooks/useFullScreen';
import { useLocale } from '../../../hooks/useLocale';
import { Duel } from '../../../stores/duel';
import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral';
import type { MaybeSkeletonComponentProps } from '../../../types/maybeSkeletonComponentProps';
import type { ThicknessRange } from '../../Armor/components/StaticArmor';
import { classIcons } from '../../ClassIcon';
import { Options } from './components/Options';
import { TankSandbox } from './components/TankSandbox';
import { TankSandboxLoader } from './components/TankSandboxLoader';
const tankDefinitions = await awaitableTankDefinitions;
export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) {
const armor = TankopediaEphemeral.use((state) => state.armor);
const { unwrap } = useLocale();
const canvas = useRef<HTMLCanvasElement>(null);
const isFullScreen = useFullScreen();
const protagonist = Duel.use((state) => state.protagonist.tank);
const Icon = classIcons[protagonist.class];
const treeColor =
protagonist.type === TankType.COLLECTOR
? 'blue'
: protagonist.type === TankType.PREMIUM
? 'amber'
: undefined;
const thicknessRange = useMemo(() => {
const entries = Object.values(tankDefinitions.tanks);
const filtered = entries.filter(
(thisTank) => thisTank.tier === protagonist.tier,
);
const value =
(filtered.reduce((accumulator, thisTank) => {
return (
accumulator +
thisTank.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
.penetration.near
);
}, 0) /
filtered.length) *
(3 / 4);
// const Icon = classIcons[protagonist.class];
// const treeColor =
// protagonist.type === TankType.COLLECTOR
// ? 'blue'
// : protagonist.type === TankType.PREMIUM
// ? 'amber'
// : undefined;
// const thicknessRange = useMemo(() => {
// const entries = Object.values(tankDefinitions.tanks);
// const filtered = entries.filter(
// (thisTank) => thisTank.tier === protagonist.tier,
// );
// const value =
// (filtered.reduce((accumulator, thisTank) => {
// return (
// accumulator +
// thisTank.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
// .penetration.near
// );
// }, 0) /
// filtered.length) *
// (3 / 4);
return { value } satisfies ThicknessRange;
}, [protagonist]);
const duelStore = Duel.useStore();
const mutateDuel = Duel.useMutation();
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
// return { value } satisfies ThicknessRange;
// }, [protagonist]);
const thicknessRange = { value: 300 };
// const duelStore = Duel.useStore();
// const mutateDuel = Duel.useMutation();
// const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
useEffect(() => {
function handleKeyDown(event: KeyboardEvent) {
const { shells } =
duelStore.getState().antagonist.gun.gun_type!.value.base;
// useEffect(() => {
// function handleKeyDown(event: KeyboardEvent) {
// const { shells } =
// duelStore.getState().antagonist.gun.gun_type!.value.base;
times(3, (index) => {
if (event.key === `${index + 1}` && shells.length > index) {
mutateDuel((draft) => {
draft.antagonist.shell = shells[index];
});
mutateTankopediaEphemeral((draft) => {
draft.customShell = undefined;
});
}
});
}
// times(3, (index) => {
// if (event.key === `${index + 1}` && shells.length > index) {
// mutateDuel((draft) => {
// draft.antagonist.shell = shells[index];
// });
// mutateTankopediaEphemeral((draft) => {
// draft.customShell = undefined;
// });
// }
// });
// }
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, []);
// window.addEventListener('keydown', handleKeyDown);
// return () => window.removeEventListener('keydown', handleKeyDown);
// }, []);
return (
<Flex justify="center" style={{ backgroundColor: Var('color-surface') }}>
@@ -105,19 +98,19 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) {
align={{ initial: 'center', md: 'start' }}
>
<Flex align="center" gap="3">
<Heading
{/* <Heading
color={treeColor}
trim="end"
size={{ initial: '7', lg: '6' }}
>
<Icon width="1em" height="1em" />
</Heading>
</Heading> */}
<Heading
weight="bold"
size={{ initial: '7', lg: '8' }}
wrap="nowrap"
color={treeColor}
// color={treeColor}
>
{unwrap(protagonist.name)}
</Heading>
@@ -144,12 +137,12 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) {
<Box width="100%" height="100%">
{skeleton && <TankSandboxLoader id={protagonist.id} />}
<Suspense fallback={<TankSandboxLoader id={protagonist.id} />}>
{/* <Suspense fallback={<TankSandboxLoader id={protagonist.id} />}>
<TankSandbox ref={canvas} thicknessRange={thicknessRange} />
</Suspense>
</Suspense> */}
</Box>
<Options canvas={canvas} thicknessRange={thicknessRange} />
{/* <Options canvas={canvas} thicknessRange={thicknessRange} /> */}
</Box>
</Box>
</Flex>
@@ -1,31 +1,26 @@
import {
createDefaultProvisions,
type ProvisionDefinitions,
type TankDefinition,
} from '@blitzkit/core';
import { Tank } from '@blitzkit/core';
import type { DuelMember } from '../../stores/duel';
import { genericDefaultEquipmentMatrix } from '../../stores/duel/constants';
export function tankToDuelMember(
tank: TankDefinition,
provisionDefinitions: ProvisionDefinitions,
tank: Tank,
// provisionDefinitions: ProvisionDefinitions,
) {
const turret = tank.turrets.at(-1)!;
const gun = turret.guns.at(-1)!;
// const turret = tank.turrets.at(-1)!;
// const gun = turret.guns.at(-1)!;
return {
camouflage: true,
consumables: [],
equipmentMatrix: genericDefaultEquipmentMatrix,
cooldownBooster: 0,
provisions: createDefaultProvisions(tank, gun, provisionDefinitions),
engine: tank.engines.at(-1)!,
gun,
shell: tank.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0],
// camouflage: true,
// consumables: [],
// equipmentMatrix: genericDefaultEquipmentMatrix,
// cooldownBooster: 0,
// provisions: createDefaultProvisions(tank, gun, provisionDefinitions),
// engine: tank.engines.at(-1)!,
// gun,
// shell: tank.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0],
tank,
track: tank.tracks.at(-1)!,
yaw: 0,
pitch: 0,
turret,
// track: tank.tracks.at(-1)!,
// yaw: 0,
// pitch: 0,
// turret,
} satisfies DuelMember;
}
@@ -1,26 +1,49 @@
import { Tank, TankArmor } from '@blitzkit/core';
import { Box } from '@radix-ui/themes';
import { OrbitControls } from '@react-three/drei';
import { Canvas } from '@react-three/fiber';
import { ArmorGroup } from '../../../../components/ArmorGroup';
import { PageWrapper } from '../../../../components/PageWrapper';
import { HeroSection } from '../../../../components/Tankopedia/HeroSection';
import {
LocaleProvider,
type LocaleAcceptorProps,
} from '../../../../hooks/useLocale';
import { App } from '../../../../stores/app';
import { Duel } from '../../../../stores/duel';
import { TankopediaEphemeral } from '../../../../stores/tankopediaEphemeral';
import { TankopediaPersistent } from '../../../../stores/tankopediaPersistent';
import type { MaybeSkeletonComponentProps } from '../../../../types/maybeSkeletonComponentProps';
interface PageProps {
tank: Tank;
armor: TankArmor;
}
type PageProps = MaybeSkeletonComponentProps &
LocaleAcceptorProps & {
tank: Tank;
armor: TankArmor;
};
export function Page({ tank, armor }: PageProps) {
export function Page({ tank, armor, skeleton, locale }: PageProps) {
return (
<PageWrapper p="0" maxWidth="unset">
<Box height="100%" width="100%" flexGrow="1" position="relative">
<Box position="absolute" top="0" left="0" width="100%" height="100%">
<Canvas>
<OrbitControls />
<ArmorGroup group="hull" tank={tank} armor={armor} />
</Canvas>
</Box>
</Box>
</PageWrapper>
<LocaleProvider locale={locale}>
<TankopediaEphemeral.Provider data={armor}>
<App.Provider>
<TankopediaPersistent.Provider>
<Duel.Provider
data={{
tank,
// provisionDefinitions,
}}
>
<PageWrapper p="0" maxWidth="unset" color="purple" gap="9" pb="9">
<HeroSection skeleton={skeleton} />
{/* <CalloutsSection /> */}
{/* <MetaSection /> */}
{/* {tank.type === TankType.RESEARCHABLE && !tank.deprecated && (
<TechTreeSection skeleton={skeleton} />
)} */}
{/* <CharacteristicsSection /> */}
{/* <GameModeSection /> */}
{/* <VideoSection skeleton={skeleton} /> */}
</PageWrapper>
</Duel.Provider>
</TankopediaPersistent.Provider>
</App.Provider>
</TankopediaEphemeral.Provider>
</LocaleProvider>
);
}
@@ -0,0 +1,30 @@
---
import { fetchTank, fetchTankArmor } from '@blitzkit/core';
import type { GetStaticPaths } from 'astro';
import { awaitableTanksFull } from '../../../../core/awaitables/tanksFull';
import BaseLayout from '../../../../layouts/BaseLayout.astro';
import { getStaticPaths as parentGetStaticPaths } from '../index.astro';
import { Page } from './_pre_index';
export const getStaticPaths = (async () => {
const tanksFull = await awaitableTanksFull;
const parentPaths = parentGetStaticPaths();
return tanksFull.tanks
.map((tank) =>
parentPaths.map((parent) => ({
params: { ...parent.params, slug: tank.slug },
props: { id: tank.id },
})),
)
.flat();
}) satisfies GetStaticPaths;
const { id } = Astro.props;
const tank = await fetchTank(id);
const armor = await fetchTankArmor(id);
---
<BaseLayout>
<Page {tank} {armor} client:load />
</BaseLayout>
@@ -0,0 +1,26 @@
import { Tank, TankArmor } from '@blitzkit/core';
import { Box } from '@radix-ui/themes';
import { OrbitControls } from '@react-three/drei';
import { Canvas } from '@react-three/fiber';
import { ArmorGroup } from '../../../../components/ArmorGroup';
import { PageWrapper } from '../../../../components/PageWrapper';
interface PageProps {
tank: Tank;
armor: TankArmor;
}
export function Page({ tank, armor }: PageProps) {
return (
<PageWrapper p="0" maxWidth="unset">
<Box height="100%" width="100%" flexGrow="1" position="relative">
<Box position="absolute" top="0" left="0" width="100%" height="100%">
<Canvas>
<OrbitControls />
<ArmorGroup group="hull" tank={tank} armor={armor} />
</Canvas>
</Box>
</Box>
</PageWrapper>
);
}
@@ -1,5 +1,6 @@
---
import { fetchTank, fetchTankArmor } from '@blitzkit/core';
import { DEFAULT_LOCALE } from '@blitzkit/i18n';
import type { GetStaticPaths } from 'astro';
import { awaitableTanksFull } from '../../../../core/awaitables/tanksFull';
import BaseLayout from '../../../../layouts/BaseLayout.astro';
@@ -20,11 +21,80 @@ export const getStaticPaths = (async () => {
.flat();
}) satisfies GetStaticPaths;
const locale = Astro.params.locale ?? DEFAULT_LOCALE;
const { id } = Astro.props;
const tank = await fetchTank(id);
const armor = await fetchTankArmor(id);
// const strings = getStrings(locale);
// const tankDefinitions = await fetchTankDefinitions();
// const skillDefinitions = await fetchSkillDefinitions();
// const provisionDefinitions = await fetchProvisionDefinitions();
// const equipmentDefinitions = await fetchEquipmentDefinitions();
// const tankModelDefinitions = await fetchModelDefinitions();
// const tank = tankDefinitions.tanks[id];
// const tankModelDefinition = tankModelDefinitions.models[tank.id];
// const name = tank.name_full ?? tank.name;
// const unwrap = unwrapper(locale);
// const title = literals(strings.website.tools.tanks.tank_seo_title, [
// unwrap(name),
// TIER_ROMAN_NUMERALS[tank.tier],
// strings.common.nations_adjectives[
// tank.nation as keyof typeof strings.common.nations_adjectives
// ],
// strings.common.tank_class_short[tank.class],
// 'BlitzKit',
// strings.common.nations[tank.nation as keyof typeof strings.common.nations],
// ]);
// const url = import.meta.env.SITE + Astro.url.pathname;
// const icon = asset(`icons/tanks/big/${id}.webp`);
// const turret = tank.turrets.at(-1)!;
// const gun = turret.guns.at(-1)!;
// const characteristics = tankCharacteristics(
// {
// tank,
// applyDynamicArmor: false,
// applyReactiveArmor: false,
// applySpallLiner: false,
// camouflage: true,
// consumables: [],
// crewSkills: createDefaultSkills(skillDefinitions),
// engine: tank.engines.at(-1)!,
// equipmentMatrix: genericDefaultEquipmentMatrix,
// turret,
// gun,
// provisions: createDefaultProvisions(tank, gun, provisionDefinitions),
// shell: gun.gun_type!.value.base.shells[0],
// stockEngine: tank.engines[0],
// stockGun: tank.turrets[0].guns[0],
// stockTurret: tank.turrets[0],
// stockTrack: tank.tracks[0],
// track: tank.tracks.at(-1)!,
// },
// { equipmentDefinitions, provisionDefinitions, tankModelDefinition },
// );
// const description = literals(strings.website.tools.tanks.tank_seo_description, [
// unwrap(name),
// Math.round(characteristics.dpm).toLocaleString(locale),
// Math.round(characteristics.damage).toLocaleString(locale),
// Math.round(characteristics.penetration).toLocaleString(locale),
// Math.round(characteristics.speedForwards).toLocaleString(locale),
// Math.round(characteristics.health).toLocaleString(locale),
// ]);
---
<!-- <title>{title}</title>
<meta property="og:title" content={title} />
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta property="og:image" content={icon} />
<meta property="og:url" content={url} />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:card" content="summary" />
<meta name="twitter:image:src" content={icon} /> -->
<BaseLayout>
<Page {tank} {armor} client:load />
<Page {tank} {armor} {locale} client:only="react">
<Page {tank} {armor} {locale} skeleton slot="fallback" />
</Page>
</BaseLayout>
+20 -26
View File
@@ -1,12 +1,4 @@
import {
type EngineDefinition,
type GunDefinition,
type ProvisionDefinitions,
type ShellDefinition,
type TankDefinition,
type TrackDefinition,
type TurretDefinition,
} from '@blitzkit/core';
import { Tank } from '@blitzkit/core';
import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import { tankToDuelMember } from '../../core/blitzkit/tankToDuelMember';
@@ -25,19 +17,19 @@ export type EquipmentMatrix = [
];
export interface DuelMember {
tank: TankDefinition;
engine: EngineDefinition;
turret: TurretDefinition;
gun: GunDefinition;
shell: ShellDefinition;
track: TrackDefinition;
equipmentMatrix: EquipmentMatrix;
pitch: number;
yaw: number;
consumables: number[];
provisions: number[];
camouflage: boolean;
cooldownBooster: number;
tank: Tank;
// engine: EngineDefinition;
// turret: TurretDefinition;
// gun: GunDefinition;
// shell: ShellDefinition;
// track: TrackDefinition;
// equipmentMatrix: EquipmentMatrix;
// pitch: number;
// yaw: number;
// consumables: number[];
// provisions: number[];
// camouflage: boolean;
// cooldownBooster: number;
}
export interface DuelStore {
@@ -48,12 +40,14 @@ export interface DuelStore {
export const Duel = createContextualStore(
({
tank,
provisionDefinitions,
// provisionDefinitions,
}: {
tank: TankDefinition;
provisionDefinitions: ProvisionDefinitions;
tank: Tank;
// provisionDefinitions: ProvisionDefinitions;
}) => {
const protagonist = tankToDuelMember(tank, provisionDefinitions);
const protagonist = tankToDuelMember(
tank, // provisionDefinitions
);
return create<DuelStore>()(
subscribeWithSelector<DuelStore>(() => ({
@@ -1,7 +1,7 @@
import {
createDefaultSkills,
ShellDefinition,
type ModelDefinition,
TankArmor,
} from '@blitzkit/core';
import type { Vector3 } from 'three';
import { create } from 'zustand';
@@ -101,7 +101,7 @@ interface TankopediaEphemeral {
skills: Record<string, number>;
relativeAgainst: TankopediaRelativeAgainst;
controlsEnabled: boolean;
model: ModelDefinition;
armor: TankArmor;
editStatic: boolean;
highlightArmor?: {
editingPlate: boolean;
@@ -124,19 +124,17 @@ interface TankopediaEphemeral {
const skillDefinitions = await awaitableSkillDefinitions;
export const TankopediaEphemeral = createContextualStore(
(model: ModelDefinition) => {
return create<TankopediaEphemeral>()(
subscribeWithSelector<TankopediaEphemeral>(() => ({
shootingRangeZoom: ShootingRangeZoom.Arcade,
relativeAgainst: TankopediaRelativeAgainst.Class,
editStatic: false,
skills: createDefaultSkills(skillDefinitions),
model,
controlsEnabled: true,
xpMultiplier: 1,
display: TankopediaDisplay.Model,
})),
);
},
);
export const TankopediaEphemeral = createContextualStore((armor: TankArmor) => {
return create<TankopediaEphemeral>()(
subscribeWithSelector<TankopediaEphemeral>(() => ({
shootingRangeZoom: ShootingRangeZoom.Arcade,
relativeAgainst: TankopediaRelativeAgainst.Class,
editStatic: false,
skills: createDefaultSkills(skillDefinitions),
armor,
controlsEnabled: true,
xpMultiplier: 1,
display: TankopediaDisplay.Model,
})),
);
});