mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: start of better tech tree
This commit is contained in:
1 parent
7e6e480788
commit
44f35a813c
1 file changed
+133
-135
@@ -1,9 +1,18 @@
|
||||
import { ChevronRightIcon } from '@radix-ui/react-icons';
|
||||
import { Box, ChevronDownIcon, Flex, Heading, Text } from '@radix-ui/themes';
|
||||
import { CaretRightIcon, ChevronRightIcon } from '@radix-ui/react-icons';
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
Flex,
|
||||
Heading,
|
||||
ScrollArea,
|
||||
Text,
|
||||
} from '@radix-ui/themes';
|
||||
import Link from 'next/link';
|
||||
import { ComponentProps, use } from 'react';
|
||||
import { ComponentProps, use, useMemo } from 'react';
|
||||
import { asset } from '../../../../../../core/blitzkit/asset';
|
||||
import { tankDefinitions } from '../../../../../../core/blitzkit/tankDefinitions';
|
||||
import {
|
||||
TankDefinition,
|
||||
tankDefinitions,
|
||||
} from '../../../../../../core/blitzkit/tankDefinitions';
|
||||
import { TIER_ROMAN_NUMERALS } from '../../../../../../core/blitzkit/tankDefinitions/constants';
|
||||
import { formatCompact } from '../../../../../../core/math/formatCompact';
|
||||
import * as Duel from '../../../../../../stores/duel';
|
||||
@@ -49,158 +58,147 @@ export function TreeArrow({
|
||||
);
|
||||
}
|
||||
|
||||
export function TechTreeSection() {
|
||||
function Card({ id }: { id: number }) {
|
||||
const awaitedTankDefinitions = use(tankDefinitions);
|
||||
const tank = Duel.use((state) => state.protagonist.tank);
|
||||
const ancestor = awaitedTankDefinitions[id];
|
||||
|
||||
if (tank.treeType !== 'researchable') return null;
|
||||
return (
|
||||
<Link
|
||||
href={`/tools/tankopedia/${id}`}
|
||||
key={id}
|
||||
style={{
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<Flex direction="column" align="center">
|
||||
<img
|
||||
alt={ancestor.name}
|
||||
src={asset(`icons/tanks/big/${id}.webp`)}
|
||||
width={64}
|
||||
height={64}
|
||||
style={{
|
||||
objectFit: 'contain',
|
||||
}}
|
||||
/>
|
||||
|
||||
function Card({ id }: { id: number }) {
|
||||
const ancestor = awaitedTankDefinitions[id];
|
||||
|
||||
return (
|
||||
<Link
|
||||
href={`/tools/tankopedia/${id}`}
|
||||
key={id}
|
||||
style={{
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<Flex direction="column" align="center">
|
||||
<img
|
||||
alt={ancestor.name}
|
||||
src={asset(`icons/tanks/big/${id}.webp`)}
|
||||
width={64}
|
||||
height={64}
|
||||
style={{
|
||||
objectFit: 'contain',
|
||||
}}
|
||||
/>
|
||||
<Flex gap="2" align="center">
|
||||
<Text color="gray" size="1">
|
||||
{TIER_ROMAN_NUMERALS[ancestor.tier]}
|
||||
</Text>
|
||||
<Text wrap="nowrap">{ancestor.name}</Text>
|
||||
</Flex>
|
||||
|
||||
<Flex direction="column" align="center">
|
||||
<Flex gap="2" align="center">
|
||||
<Text color="gray" size="1">
|
||||
{TIER_ROMAN_NUMERALS[ancestor.tier]}
|
||||
<Flex gap="2" align="center">
|
||||
<Flex gap="1" align="center">
|
||||
<img
|
||||
alt="XP"
|
||||
src={asset('icons/currencies/xp.webp')}
|
||||
width={16}
|
||||
height={16}
|
||||
style={{
|
||||
objectFit: 'contain',
|
||||
}}
|
||||
/>
|
||||
<Text color="gray" size="1" wrap="nowrap">
|
||||
{ancestor.xp === undefined ? 0 : formatCompact(ancestor.xp!)}
|
||||
</Text>
|
||||
<Text>{ancestor.name}</Text>
|
||||
</Flex>
|
||||
|
||||
<Flex gap="2" align="center">
|
||||
<Flex gap="1" align="center">
|
||||
<img
|
||||
alt="XP"
|
||||
src={asset('icons/currencies/xp.webp')}
|
||||
width={16}
|
||||
height={16}
|
||||
style={{
|
||||
objectFit: 'contain',
|
||||
}}
|
||||
/>
|
||||
<Text color="gray" size="1">
|
||||
{formatCompact(ancestor.xp!)}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
<Flex gap="1" align="center">
|
||||
<img
|
||||
alt="Silver"
|
||||
src={asset('icons/currencies/silver.webp')}
|
||||
width={16}
|
||||
height={16}
|
||||
style={{
|
||||
objectFit: 'contain',
|
||||
}}
|
||||
/>
|
||||
<Text color="gray" size="1">
|
||||
{formatCompact(ancestor.price.value)}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex gap="1" align="center">
|
||||
<img
|
||||
alt="Silver"
|
||||
src={asset('icons/currencies/silver.webp')}
|
||||
width={16}
|
||||
height={16}
|
||||
style={{
|
||||
objectFit: 'contain',
|
||||
}}
|
||||
/>
|
||||
<Text color="gray" size="1" wrap="nowrap">
|
||||
{formatCompact(ancestor.price.value)}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Link>
|
||||
);
|
||||
</Flex>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export function TechTreeSection() {
|
||||
const tank = Duel.use((state) => state.protagonist.tank);
|
||||
const awaitedTankDefinitions = use(tankDefinitions);
|
||||
|
||||
if (
|
||||
tank.treeType !== 'researchable' ||
|
||||
tank.ancestors === undefined ||
|
||||
tank.ancestors.length === 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const ancestors = useMemo(() => {
|
||||
const treeBackwards: number[] = [];
|
||||
let ancestor: TankDefinition | undefined = tank;
|
||||
|
||||
while (ancestor !== undefined) {
|
||||
if (ancestor.ancestors === undefined || ancestor.ancestors.length === 0) {
|
||||
ancestor = undefined;
|
||||
break;
|
||||
} else if (ancestor.ancestors.length === 1) {
|
||||
ancestor = awaitedTankDefinitions[ancestor.ancestors[0]];
|
||||
} else {
|
||||
let bestAncestor = awaitedTankDefinitions[ancestor.ancestors[0]];
|
||||
|
||||
ancestor.ancestors.forEach((thisAncestorId) => {
|
||||
const possibleAncestor = awaitedTankDefinitions[thisAncestorId];
|
||||
|
||||
if (possibleAncestor.xp! < bestAncestor.xp!) {
|
||||
bestAncestor = possibleAncestor;
|
||||
}
|
||||
});
|
||||
|
||||
ancestor = bestAncestor as TankDefinition;
|
||||
}
|
||||
|
||||
treeBackwards.push(ancestor.id);
|
||||
}
|
||||
|
||||
return treeBackwards.reverse();
|
||||
}, []);
|
||||
|
||||
console.log(ancestors);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
my="6"
|
||||
p="5"
|
||||
py="6"
|
||||
direction="column"
|
||||
align="center"
|
||||
gap="4"
|
||||
style={{
|
||||
overflow: 'hidden',
|
||||
backgroundColor: 'var(--color-surface)',
|
||||
}}
|
||||
align="center"
|
||||
direction="column"
|
||||
position="relative"
|
||||
>
|
||||
<img
|
||||
src={asset(`flags/scratched/${tank.nation}.webp`)}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-40%, -50%)',
|
||||
filter: 'blur(2px)',
|
||||
opacity: 0.25,
|
||||
}}
|
||||
/>
|
||||
<Heading size="6">Tech tree</Heading>
|
||||
|
||||
<Heading mb="4">Tech tree</Heading>
|
||||
|
||||
<Flex align="center" gap="6" direction={{ initial: 'column', sm: 'row' }}>
|
||||
{tank.ancestors && (
|
||||
<>
|
||||
<Flex
|
||||
wrap="wrap"
|
||||
direction={{ initial: 'row', sm: 'column' }}
|
||||
maxHeight={{ initial: 'unset', sm: '320px' }}
|
||||
align="center"
|
||||
justify="center"
|
||||
gap="6"
|
||||
>
|
||||
{tank.ancestors.map((id) => (
|
||||
<Card key={id} id={id} />
|
||||
))}
|
||||
</Flex>
|
||||
|
||||
<Box display={{ initial: 'block', sm: 'none' }}>
|
||||
<TreeArrow down />
|
||||
</Box>
|
||||
<Box display={{ initial: 'none', sm: 'block' }}>
|
||||
<TreeArrow />
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Card id={tank.id} />
|
||||
|
||||
{tank.successors && (
|
||||
<>
|
||||
<Box display={{ initial: 'block', sm: 'none' }}>
|
||||
<TreeArrow down />
|
||||
</Box>
|
||||
<Box display={{ initial: 'none', sm: 'block' }}>
|
||||
<TreeArrow />
|
||||
</Box>
|
||||
|
||||
<Flex
|
||||
wrap="wrap"
|
||||
direction={{ initial: 'row', sm: 'column' }}
|
||||
maxHeight={{ initial: 'unset', sm: '320px' }}
|
||||
align="center"
|
||||
justify="center"
|
||||
gap="6"
|
||||
>
|
||||
{tank.successors.map((id) => (
|
||||
<Card key={id} id={id} />
|
||||
))}
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
<ScrollArea>
|
||||
<Flex align="center" gap="4" justify="center" p="4">
|
||||
{ancestors.map((id, index) => (
|
||||
<>
|
||||
{index > 0 && (
|
||||
<Text color="gray">
|
||||
<CaretRightIcon />
|
||||
</Text>
|
||||
)}
|
||||
<Card key={id} id={id} />
|
||||
</>
|
||||
))}
|
||||
</Flex>
|
||||
</ScrollArea>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user