feat: shell swapping

This commit is contained in:
TrèsAbhi committed 2024-01-10 17:57:41 -06:00
1 parent 32ee10445d
commit 371dcad568
4 files changed
+107 -73

No files matched your search

@@ -5,6 +5,7 @@ import { GLTFLoader } from 'three-stdlib';
import { ArmorMesh } from '../../../../../../../components/ArmorMesh'; import { ArmorMesh } from '../../../../../../../components/ArmorMesh';
import { HeadsUpDisplay } from '../../../../../../../components/HeadsUpDisplay'; import { HeadsUpDisplay } from '../../../../../../../components/HeadsUpDisplay';
import { X_AXIS } from '../../../../../../../constants/axis'; import { X_AXIS } from '../../../../../../../constants/axis';
import { numericPenetration } from '../../../../../../../core/blitz/numericPenetration';
import { asset } from '../../../../../../../core/blitzkrieg/asset'; import { asset } from '../../../../../../../core/blitzkrieg/asset';
import { import {
ModelDefinitions, ModelDefinitions,
@@ -97,7 +98,7 @@ export function TankArmor(props: TankArmorProps) {
key={node.uuid} key={node.uuid}
geometry={(node as Mesh).geometry} geometry={(node as Mesh).geometry}
thickness={thickness} thickness={thickness}
penetration={252} penetration={numericPenetration(antagonist.shell.penetration)}
ricochet={antagonist.shell.ricochet} ricochet={antagonist.shell.ricochet}
caliber={antagonist.shell.caliber} caliber={antagonist.shell.caliber}
normalization={antagonist.shell.normalization} normalization={antagonist.shell.normalization}
@@ -123,7 +124,7 @@ export function TankArmor(props: TankArmorProps) {
position={turretOrigin} position={turretOrigin}
geometry={(node as Mesh).geometry} geometry={(node as Mesh).geometry}
thickness={thickness} thickness={thickness}
penetration={252} penetration={numericPenetration(antagonist.shell.penetration)}
ricochet={antagonist.shell.ricochet} ricochet={antagonist.shell.ricochet}
caliber={antagonist.shell.caliber} caliber={antagonist.shell.caliber}
normalization={antagonist.shell.normalization} normalization={antagonist.shell.normalization}
@@ -155,7 +156,7 @@ export function TankArmor(props: TankArmorProps) {
position={turretOrigin.clone().add(gunOrigin)} position={turretOrigin.clone().add(gunOrigin)}
geometry={(node as Mesh).geometry} geometry={(node as Mesh).geometry}
thickness={thickness} thickness={thickness}
penetration={252} penetration={numericPenetration(antagonist.shell.penetration)}
ricochet={antagonist.shell.ricochet} ricochet={antagonist.shell.ricochet}
caliber={antagonist.shell.caliber} caliber={antagonist.shell.caliber}
normalization={antagonist.shell.normalization} normalization={antagonist.shell.normalization}
@@ -18,8 +18,7 @@ import {
import { go } from 'fuzzysort'; import { go } from 'fuzzysort';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { use, useRef, useState } from 'react'; import { use, useRef, useState } from 'react';
import { ModuleButtons } from '../../../../../components/ModuleButton'; import { ModuleButton } from '../../../../../components/ModuleButton';
import { asset } from '../../../../../core/blitzkrieg/asset';
import { import {
SHELL_NAMES, SHELL_NAMES,
tankDefinitions, tankDefinitions,
@@ -169,7 +168,12 @@ export function VersusBar() {
<Flex> <Flex>
{antagonist.tank.turrets.map((turret, index) => ( {antagonist.tank.turrets.map((turret, index) => (
<Tooltip content={turret.name} key={turret.id}> <Tooltip content={turret.name} key={turret.id}>
<ModuleButtons <ModuleButton
rowChild
first={index === 0}
last={
index === antagonist.tank.turrets.length - 1
}
key={turret.id} key={turret.id}
onClick={() => { onClick={() => {
mutateTankopedia((draft) => { mutateTankopedia((draft) => {
@@ -184,24 +188,8 @@ export function VersusBar() {
}} }}
selected={antagonist.turret.id === turret.id} selected={antagonist.turret.id === turret.id}
tier={turret.tier} tier={turret.tier}
type="turret" type="module"
style={{ module="turret"
margin: -0.5,
borderTopLeftRadius:
index === 0 ? undefined : 0,
borderBottomLeftRadius:
index === 0 ? undefined : 0,
borderTopRightRadius:
index ===
antagonist.tank.turrets.length - 1
? undefined
: 0,
borderBottomRightRadius:
index ===
antagonist.tank.turrets.length - 1
? undefined
: 0,
}}
/> />
</Tooltip> </Tooltip>
))} ))}
@@ -209,7 +197,12 @@ export function VersusBar() {
<Flex> <Flex>
{antagonist.turret.guns.map((gun, index) => ( {antagonist.turret.guns.map((gun, index) => (
<Tooltip content={gun.name} key={gun.id}> <Tooltip content={gun.name} key={gun.id}>
<ModuleButtons <ModuleButton
rowChild
first={index === 0}
last={
index === antagonist.turret.guns.length - 1
}
onClick={() => { onClick={() => {
mutateTankopedia((draft) => { mutateTankopedia((draft) => {
if (!draft.areTanksAssigned) return; if (!draft.areTanksAssigned) return;
@@ -219,24 +212,8 @@ export function VersusBar() {
}} }}
selected={antagonist.gun.id === gun.id} selected={antagonist.gun.id === gun.id}
tier={gun.tier} tier={gun.tier}
type="gun" type="module"
style={{ module="gun"
margin: -0.5,
borderTopLeftRadius:
index === 0 ? undefined : 0,
borderBottomLeftRadius:
index === 0 ? undefined : 0,
borderTopRightRadius:
index ===
antagonist.turret.guns.length - 1
? undefined
: 0,
borderBottomRightRadius:
index ===
antagonist.turret.guns.length - 1
? undefined
: 0,
}}
/> />
</Tooltip> </Tooltip>
))} ))}
@@ -278,8 +255,27 @@ export function VersusBar() {
<Text>Calibrated</Text> <Text>Calibrated</Text>
</Flex> </Flex>
<Flex gap="1"> <Flex>
<Button variant="solid" radius="small"> {antagonist.gun.shells.map((shell, index) => {
return (
<ModuleButton
selected={antagonist.shell.id === shell.id}
type="shell"
shell={shell.type}
rowChild
first={index === 0}
key={shell.id}
last={index === antagonist.gun.shells.length - 1}
onClick={() => {
mutateTankopedia((draft) => {
if (!draft.areTanksAssigned) return;
draft.antagonist.shell = shell;
});
}}
/>
);
})}
{/* <Button variant="solid" radius="small">
<img src={asset('icons/shells/ap.webp')} width={24} height={24} /> <img src={asset('icons/shells/ap.webp')} width={24} height={24} />
</Button> </Button>
<Button variant="soft" radius="small" color="gray"> <Button variant="soft" radius="small" color="gray">
@@ -291,7 +287,7 @@ export function VersusBar() {
</Button> </Button>
<Button variant="soft" radius="small" color="gray"> <Button variant="soft" radius="small" color="gray">
<img src={asset('icons/shells/he.webp')} width={24} height={24} /> <img src={asset('icons/shells/he.webp')} width={24} height={24} />
</Button> </Button> */}
</Flex> </Flex>
</Flex> </Flex>
</Card> </Card>
+59 -27
View File
@@ -1,20 +1,35 @@
import { Button, Text } from '@radix-ui/themes'; import { Button, Text } from '@radix-ui/themes';
import { ComponentProps } from 'react'; import { ComponentProps } from 'react';
import { asset } from '../core/blitzkrieg/asset'; import { asset } from '../core/blitzkrieg/asset';
import { TIER_ROMAN_NUMERALS, Tier } from '../core/blitzkrieg/tankDefinitions'; import {
ShellType,
TIER_ROMAN_NUMERALS,
Tier,
} from '../core/blitzkrieg/tankDefinitions';
interface ModuleButtonProps type ModuleButtonProps = Omit<ComponentProps<typeof Button>, 'type'> & {
extends Omit<ComponentProps<typeof Button>, 'type'> {
type: string;
tier: Tier;
selected?: boolean; selected?: boolean;
} first?: boolean;
last?: boolean;
rowChild?: boolean;
} & (
| {
type: 'module';
module: string;
tier: Tier;
}
| {
type: 'shell';
shell: ShellType;
}
);
export function ModuleButtons({ export function ModuleButton({
type,
tier,
selected, selected,
style, style,
first = true,
last = true,
rowChild,
...props ...props
}: ModuleButtonProps) { }: ModuleButtonProps) {
return ( return (
@@ -27,34 +42,51 @@ export function ModuleButtons({
width: 48, width: 48,
height: 40, height: 40,
position: 'relative', position: 'relative',
borderTopLeftRadius: first ? undefined : 0,
borderTopRightRadius: last ? undefined : 0,
borderBottomLeftRadius: first ? undefined : 0,
borderBottomRightRadius: last ? undefined : 0,
margin: rowChild ? -0.5 : 'unset',
...style, ...style,
}} }}
{...props} {...(props as unknown as ComponentProps<typeof Button>)}
> >
<img <img
src={asset(`icons/modules/${type}.webp`)} src={asset(
props.type === 'module'
? `icons/modules/${props.module}.webp`
: `icons/shells/${props.shell}.webp`,
)}
style={{ style={{
width: 32, width: 32,
height: 32, height: 32,
position: 'absolute', position: 'absolute',
top: '50%', ...(props.type === 'module'
left: '50%', ? {
transform: 'translate(calc(-50% + 2px), calc(-50% + 2px))', top: '50%',
left: '50%',
transform: 'translate(calc(-50% + 2px), calc(-50% + 2px))',
}
: {
transform: 'scale(0.75)',
}),
}} }}
/> />
<Text {props.type === 'module' && (
size="1" <Text
weight="bold" size="1"
style={{ weight="bold"
zIndex: 1, style={{
position: 'absolute', zIndex: 1,
top: '50%', position: 'absolute',
right: 8, top: '50%',
textAlign: 'right', right: 8,
}} textAlign: 'right',
> }}
{TIER_ROMAN_NUMERALS[tier]} >
</Text> {TIER_ROMAN_NUMERALS[props.tier]}
</Text>
)}
</Button> </Button>
); );
} }
+5
View File
@@ -0,0 +1,5 @@
import { Vector2Tuple } from 'three';
export function numericPenetration(penetration: number | Vector2Tuple) {
return typeof penetration === 'number' ? penetration : penetration[0];
}