feat: module tree

This commit is contained in:
TrèsAbhi committed 2024-05-04 11:00:54 -05:00
1 parent 89e97f484b
commit 7af5d5f465
4 files changed
+192 -32

No files matched your search

@@ -1,31 +1,84 @@
import { Heading } from '@radix-ui/themes';
import { Flex, Heading } from '@radix-ui/themes';
import { use } from 'react';
import { ModuleButton } from '../../../../../../components/ModuleButtons/ModuleButton';
import PageWrapper from '../../../../../../components/PageWrapper';
import {
EngineDefinition,
GunDefinition,
ModuleDefinition,
ModuleType,
TankDefinition,
tankDefinitions,
TrackDefinition,
TurretDefinition,
Unlock,
} from '../../../../../../core/blitzkit/tankDefinitions';
import { useDuel } from '../../../../../../stores/duel';
import { TIER_ROMAN_NUMERALS } from '../../../../../../core/blitzkit/tankDefinitions/constants';
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
import { TreeArrow } from './TechTreeSection';
export function ModulesSection() {
const awaitedTankDefinitions = use(tankDefinitions);
const tank = useDuel((state) => state.protagonist!.tank);
const turret = useDuel((state) => state.protagonist!.turret);
const gun = useDuel((state) => state.protagonist!.gun);
const engine = useDuel((state) => state.protagonist!.engine);
const track = useDuel((state) => state.protagonist!.track);
const turret0 = tank.turrets[0];
const gun0 = turret0.guns[0];
const engine0 = tank.engines[0];
const track0 = tank.tracks[0];
function setByUnlock(unlock: Unlock) {
mutateDuel((draft) => {
if (unlock.type === 'turret') {
draft.protagonist!.turret = draft.protagonist!.tank.turrets.find(
(turret) => turret.id === unlock.id,
)!;
if (
!draft.protagonist!.turret.guns.some(
(gun) => gun.id === draft.protagonist!.gun.id,
)
) {
draft.protagonist!.gun = draft.protagonist!.turret.guns.at(-1)!;
draft.protagonist!.shell = draft.protagonist!.gun.shells.at(-1)!;
}
} else if (unlock.type === 'gun') {
const gunInTurret = draft.protagonist!.turret.guns.find(
(gun) => gun.id === unlock.id,
);
if (gunInTurret) {
draft.protagonist!.gun = gunInTurret;
draft.protagonist!.shell = gunInTurret.shells.at(-1)!;
} else {
// TODO: warn somehow?
const suitableTurret = draft.protagonist!.tank.turrets.find(
(turret) => turret.guns.some((gun) => gun.id === unlock.id),
)!;
const gunInSuitableTurret = suitableTurret.guns.find(
(gun) => gun.id === unlock.id,
)!;
draft.protagonist!.turret = suitableTurret;
draft.protagonist!.gun = gunInSuitableTurret;
draft.protagonist!.shell = gunInSuitableTurret.shells.at(-1)!;
}
} else if (unlock.type === 'engine') {
draft.protagonist!.engine = draft.protagonist!.tank.engines.find(
(engine) => engine.id === unlock.id,
)!;
} else if (unlock.type === 'chassis') {
draft.protagonist!.track = draft.protagonist!.tank.tracks.find(
(track) => track.id === unlock.id,
)!;
}
});
}
function tree(type: ModuleType, unlocks: Unlock[]) {
return (
<ul>
<Flex direction="column" gap="2">
{unlocks.map((unlock) => {
let module:
| TrackDefinition
| EngineDefinition
| TurretDefinition
| GunDefinition
| undefined = undefined;
let module: ModuleDefinition | TankDefinition | undefined = undefined;
console.log(unlock.type);
if (unlock.type === 'chassis') {
module = tank.tracks.find((track) => track.id === unlock.id)!;
@@ -43,31 +96,131 @@ export function ModulesSection() {
if (module === undefined) return null;
const unlocksFiltered = (module as ModuleDefinition).unlocks?.filter(
({ type }) => type !== 'vehicle',
);
return (
<li>
{unlock.type} {module.name}
{module.unlocks && tree(type, module.unlocks)}
</li>
<Flex align="center" gap="2">
<ModuleButton
first
last
module={unlock.type}
discriminator={TIER_ROMAN_NUMERALS[module.tier]}
selected={
(unlock.type === 'turret'
? turret.id
: unlock.type === 'gun'
? gun.id
: unlock.type === 'engine'
? engine.id
: unlock.type === 'chassis'
? track.id
: -1) === unlock.id
}
onClick={() => setByUnlock(unlock)}
/>
{unlocksFiltered && unlocksFiltered.length > 0 && (
<>
<TreeArrow style={{ width: 32 }} />
{tree(type, (module as ModuleDefinition).unlocks!)}
</>
)}
</Flex>
);
})}
</ul>
</Flex>
);
}
return (
<PageWrapper>
<Heading>turret0</Heading>
{tank.turrets[0].unlocks && tree('turret', tank.turrets[0].unlocks)}
<Heading>Modules</Heading>
<Heading>gun0</Heading>
{tank.turrets[0].guns[0].unlocks &&
tree('gun', tank.turrets[0].guns[0].unlocks)}
<Flex direction="column" gap="2">
<Flex align="center" gap="2">
<ModuleButton
module="turret"
first
last
discriminator={TIER_ROMAN_NUMERALS[turret0.tier]}
selected={turret0.id === turret.id}
onClick={() => setByUnlock({ id: turret0.id, type: 'turret' })}
/>
<Heading>engine0</Heading>
{tank.engines[0].unlocks && tree('engine', tank.engines[0].unlocks)}
{turret0.unlocks && (
<>
<TreeArrow style={{ width: 32, flex: undefined }} />
{tree('turret', turret0.unlocks)}
</>
)}
</Flex>
<Heading>track0</Heading>
{tank.tracks[0].unlocks && tree('chassis', tank.tracks[0].unlocks)}
<Flex align="center" gap="2">
<ModuleButton
module="gun"
first
last
discriminator={TIER_ROMAN_NUMERALS[gun0.tier]}
selected={gun0.id === gun.id}
onClick={() => setByUnlock({ id: gun0.id, type: 'gun' })}
/>
{gun0.unlocks && (
<>
<TreeArrow style={{ width: 32, flex: undefined }} />
{tree('gun', gun0.unlocks)}
</>
)}
</Flex>
<Flex align="center" gap="2">
<ModuleButton
module="engine"
first
last
discriminator={TIER_ROMAN_NUMERALS[engine0.tier]}
selected={engine0.id === engine.id}
onClick={() => setByUnlock({ id: engine0.id, type: 'engine' })}
/>
{engine0.unlocks && (
<>
<TreeArrow style={{ width: 32, flex: undefined }} />
{tree('engine', engine0.unlocks)}
</>
)}
</Flex>
<Flex align="center" gap="2">
<ModuleButton
module="chassis"
first
last
discriminator={TIER_ROMAN_NUMERALS[track0.tier]}
selected={track0.id === track.id}
onClick={() => setByUnlock({ id: track0.id, type: 'chassis' })}
/>
{track0.unlocks && (
<>
<TreeArrow style={{ width: 32, flex: undefined }} />
{tree('chassis', track0.unlocks)}
</>
)}
</Flex>
{/* <Heading>gun0</Heading>
{tank.turrets[0].guns[0].unlocks &&
tree('gun', tank.turrets[0].guns[0].unlocks)}
<Heading>engine0</Heading>
{tank.engines[0].unlocks && tree('engine', tank.engines[0].unlocks)}
<Heading>track0</Heading>
{tank.tracks[0].unlocks && tree('chassis', tank.tracks[0].unlocks)} */}
</Flex>
</PageWrapper>
);
}
@@ -1,20 +1,22 @@
import { ChevronRightIcon } from '@radix-ui/react-icons';
import { Flex, Heading, Text } from '@radix-ui/themes';
import Link from 'next/link';
import { use } from 'react';
import { ComponentProps, use } from 'react';
import PageWrapper from '../../../../../../components/PageWrapper';
import { asset } from '../../../../../../core/blitzkit/asset';
import { tankDefinitions } from '../../../../../../core/blitzkit/tankDefinitions';
import { TIER_ROMAN_NUMERALS } from '../../../../../../core/blitzkit/tankDefinitions/constants';
import { useDuel } from '../../../../../../stores/duel';
function Arrow() {
export function TreeArrow({ style, ...props }: ComponentProps<typeof Text>) {
return (
<Text
color="gray"
style={{
flex: 1,
...style,
}}
{...props}
>
<Flex
style={{
@@ -130,7 +132,7 @@ export function TechTreeSection() {
))}
</Flex>
<Arrow />
<TreeArrow />
</>
)}
@@ -160,7 +162,7 @@ export function TechTreeSection() {
{tank.successors && (
<>
<Arrow />
<TreeArrow />
<Flex
wrap="wrap"
+1 -1
View File
@@ -62,8 +62,8 @@ export default function Page({ params }: { params: { id: string } }) {
<>
<HeroSection />
{/* <TankopediaPlug /> */}
<TechTreeSection />
<ModulesSection />
<TechTreeSection />
{/* <CharacteristicsSection />
<TankopediaSeparator /> */}
<Videos />
@@ -24,6 +24,11 @@ export interface Crew {
count?: number;
substitute?: CrewMember[];
}
export type ModuleDefinition =
| TrackDefinition
| EngineDefinition
| TurretDefinition
| GunDefinition;
export interface TankDefinition {
id: number;
description?: string;