fix: some linting for new proto 6

This commit is contained in:
TrèsAbhi committed 2024-10-06 00:02:50 -05:00
1 parent 96310a9d63
commit 95bb67bcf1
29 files changed
+229 -295

No files matched your search

@@ -24,7 +24,8 @@ export const PrimaryArmorScene = memo(() => {
const tankModelDefinition = useTankModelDefinition();
const trackModelDefinition = tankModelDefinition.tracks[track.id];
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
const gunModelDefinition = turretModelDefinition.guns[gun.id];
const gunModelDefinition =
turretModelDefinition.guns[gun.gunType!.value.base.id];
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
const turretOrigin = correctZYTuple(tankModelDefinition.turretOrigin);
const gunOrigin = correctZYTuple(turretModelDefinition.gunOrigin);
@@ -68,7 +69,7 @@ export const PrimaryArmorScene = memo(() => {
<group ref={turretContainer}>
{armorNodes.map((node) => {
const isCurrentTurret = node.name.startsWith(
`turret_${turretModelDefinition.model.toString().padStart(2, '0')}`,
`turret_${turretModelDefinition.modelId.toString().padStart(2, '0')}`,
);
const isVisible = isCurrentTurret;
const armorId = nameToArmorId(node.name);
@@ -102,7 +103,7 @@ export const PrimaryArmorScene = memo(() => {
<group ref={gunContainer}>
{armorNodes.map((node) => {
const isCurrentGun = node.name.startsWith(
`gun_${gunModelDefinition.model.toString().padStart(2, '0')}`,
`gun_${gunModelDefinition.modelId.toString().padStart(2, '0')}`,
);
const isVisible = isCurrentGun;
const armorId = nameToArmorId(node.name);
@@ -2,7 +2,6 @@ import {
type ShellDefinition,
canSplash,
isExplosive,
resolveNearPenetration,
resolvePenetrationCoefficient,
} from '@blitzkit/core';
import { useFrame } from '@react-three/fiber';
@@ -69,7 +68,7 @@ export function PrimaryArmorSceneComponent({
);
material.uniforms.isExplosive.value = isExplosive(shell.type);
material.uniforms.canSplash.value = canSplash(shell.type);
material.uniforms.damage.value = shell.damage.armor;
material.uniforms.damage.value = shell.armorDamage;
material.uniforms.explosionRadius.value = shell.explosionRadius;
const duel = duelStore.getState();
@@ -91,7 +90,7 @@ export function PrimaryArmorSceneComponent({
const duel = duelStore.getState();
const hasEnhancedArmor = await hasEquipment(
110,
duel.protagonist.tank.equipment,
duel.protagonist.tank.equipmentPreset,
equipment,
);
material.uniforms.thickness.value = hasEnhancedArmor
@@ -101,10 +100,10 @@ export function PrimaryArmorSceneComponent({
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
const duel = duelStore.getState();
const shell = duel.antagonist.shell;
const penetration = resolveNearPenetration(shell.penetration);
const penetration = shell.penetration.near;
const hasCalibratedShells = await hasEquipment(
103,
duel.antagonist.tank.equipment,
duel.antagonist.tank.equipmentPreset,
equipment,
);
@@ -37,7 +37,8 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
const tankModelDefinition = useTankModelDefinition();
const trackModelDefinition = tankModelDefinition.tracks[track.id];
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
const gunModelDefinition = turretModelDefinition.guns[gun.id];
const gunModelDefinition =
turretModelDefinition.guns[gun.gunType!.value.base.id];
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
const turretOrigin = correctZYTuple(tankModelDefinition.turretOrigin);
const gunOrigin = correctZYTuple(turretModelDefinition.gunOrigin);
@@ -105,7 +106,7 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
<group ref={turretContainer}>
{armorNodes.map((node) => {
const isCurrentTurret = node.name.startsWith(
`turret_${turretModelDefinition.model.toString().padStart(2, '0')}`,
`turret_${turretModelDefinition.modelId.toString().padStart(2, '0')}`,
);
const isVisible = isCurrentTurret;
const armorId = nameToArmorId(node.name);
@@ -140,7 +141,7 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
<group ref={gunContainer}>
{armorNodes.map((node) => {
const isCurrentGun = node.name.startsWith(
`gun_${gunModelDefinition.model.toString().padStart(2, '0')}`,
`gun_${gunModelDefinition.modelId.toString().padStart(2, '0')}`,
);
const isVisible = isCurrentGun;
const armorId = nameToArmorId(node.name);
@@ -172,7 +173,7 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
})}
{modelNodes.map((node) => {
const gunString = `gun_${gunModelDefinition.model
const gunString = `gun_${gunModelDefinition.modelId
.toString()
.padStart(2, '0')}`;
const isCurrentGun = gunModelDefinition.mask
@@ -1,6 +1,5 @@
import {
isExplosive,
resolveNearPenetration,
resolvePenetrationCoefficient,
type ShellDefinition,
} from '@blitzkit/core';
@@ -54,9 +53,7 @@ export function SpacedArmorSubSpaced({
useEffect(() => {
function handleShellChange(shell: ShellDefinition) {
material.uniforms.penetration.value = resolveNearPenetration(
shell.penetration,
);
material.uniforms.penetration.value = shell.penetration.near;
material.uniforms.caliber.value = shell.caliber;
material.uniforms.ricochet.value = degToRad(
isExplosive(shell.type) ? 90 : shell.ricochet!,
@@ -71,7 +68,7 @@ export function SpacedArmorSubSpaced({
const duel = duelStore.getState();
const hasEnhancedArmor = await hasEquipment(
110,
duel.protagonist.tank.equipment,
duel.protagonist.tank.equipmentPreset,
equipment,
);
material.uniforms.thickness.value = hasEnhancedArmor
@@ -81,10 +78,10 @@ export function SpacedArmorSubSpaced({
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
const duel = duelStore.getState();
const shell = duelStore.getState().antagonist.shell;
const penetration = resolveNearPenetration(shell.penetration);
const penetration = shell.penetration.near;
const hasCalibratedShells = await hasEquipment(
103,
duel.antagonist.tank.equipment,
duel.antagonist.tank.equipmentPreset,
equipment,
);
@@ -1,7 +1,6 @@
import {
ShellType,
isExplosive,
resolveNearPenetration,
resolvePenetrationCoefficient,
} from '@blitzkit/core';
import { useThree } from '@react-three/fiber';
@@ -104,16 +103,16 @@ export function SpacedArmorSceneComponent({
const hasCalibratedShells = await hasEquipment(
103,
antagonist.tank.equipment,
antagonist.tank.equipmentPreset,
antagonist.equipmentMatrix,
);
const hasEnhancedArmor = await hasEquipment(
110,
protagonist.tank.equipment,
protagonist.tank.equipmentPreset,
protagonist.equipmentMatrix,
);
const penetration =
resolveNearPenetration(shell.penetration) *
shell.penetration.near *
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
const thicknessCoefficient = hasEnhancedArmor ? 1.03 : 1;
const filteredIntersections = intersections.filter(
@@ -289,7 +288,7 @@ export function SpacedArmorSceneComponent({
const finalDamage = Math.max(
0,
0.5 *
shell.damage.armor *
shell.armorDamage *
(1 - distanceFromSpacedArmor / shell.explosionRadius!) -
1.1 *
(lastLayer.thicknessAngled +
@@ -312,7 +311,7 @@ export function SpacedArmorSceneComponent({
shot.damage = finalDamage;
} else {
shot.in.status = 'penetration';
shot.damage = shell.damage.armor;
shot.damage = shell.armorDamage;
}
} else {
if (lastLayer.status === 'blocked') {
@@ -320,7 +319,7 @@ export function SpacedArmorSceneComponent({
shot.damage = 0;
} else if (lastLayer.status === 'penetration') {
shot.in.status = 'penetration';
shot.damage = shell.damage.armor;
shot.damage = shell.armorDamage;
} else {
const caster = new Raycaster();
// https://math.stackexchange.com/a/13263/1222875
@@ -1,5 +1,6 @@
import { type TankClass } from '@blitzkit/core';
import { TankClass } from '@blitzkit/core';
import type { ComponentProps, ReactNode } from 'react';
import { StupidCat } from '../StupidCat';
import { ClassHeavy } from './components/ClassHeavy';
import { ClassLight } from './components/ClassLight';
import { ClassMedium } from './components/ClassMedium';
@@ -9,8 +10,9 @@ export const classIcons: Record<
TankClass,
(props: ComponentProps<'svg'>) => ReactNode
> = {
'AT-SPG': ClassTankDestroyer,
heavyTank: ClassHeavy,
lightTank: ClassLight,
mediumTank: ClassMedium,
[TankClass.TANK_DESTROYER]: ClassTankDestroyer,
[TankClass.HEAVY]: ClassHeavy,
[TankClass.LIGHT]: ClassLight,
[TankClass.MEDIUM]: ClassMedium,
[TankClass.UNRECOGNIZED]: StupidCat,
};
@@ -1,7 +1,7 @@
import {
asset,
fetchSkillDefinitions,
permanentSkills,
skillDefinitions,
TIER_ROMAN_NUMERALS,
type Tier,
} from '@blitzkit/core';
@@ -13,7 +13,7 @@ interface CrewSkillManagerProps {
onChange?: (skillLevels: Record<string, number>) => void;
}
const awaitedSkillDefinitions = await skillDefinitions;
const skillDefinitions = await fetchSkillDefinitions();
export function CrewSkillManager({
skillLevels,
@@ -21,41 +21,39 @@ export function CrewSkillManager({
}: CrewSkillManagerProps) {
return (
<Flex direction="column" gap="2">
{Object.entries(awaitedSkillDefinitions.classes).map(
([tankClass, skills]) => (
<Flex gap="2" key={tankClass}>
{skills.map((skill) => {
const level = skillLevels[skill];
{Object.entries(skillDefinitions.classes).map(([tankClass, skills]) => (
<Flex gap="2" key={tankClass}>
{skills.skills.map((skill) => {
const level = skillLevels[skill];
return (
<GenericTankComponentButton
key={skill}
special={!permanentSkills.includes(skill)}
selected={level > 0}
discriminator={
level === 0 ? undefined : TIER_ROMAN_NUMERALS[level as Tier]
return (
<GenericTankComponentButton
key={skill}
special={!permanentSkills.includes(skill)}
selected={level > 0}
discriminator={
level === 0 ? undefined : TIER_ROMAN_NUMERALS[level as Tier]
}
icon={asset(`icons/skills/${skill}.webp`)}
onClick={(event) => {
if (!onChange) return;
const draft = { ...skillLevels };
if (event.shiftKey) {
draft[skill] = draft[skill] === 0 ? 7 : 0;
} else {
draft[skill] = level - 1;
if (draft[skill] < 0) draft[skill] = 7;
}
icon={asset(`icons/skills/${skill}.webp`)}
onClick={(event) => {
if (!onChange) return;
const draft = { ...skillLevels };
if (event.shiftKey) {
draft[skill] = draft[skill] === 0 ? 7 : 0;
} else {
draft[skill] = level - 1;
if (draft[skill] < 0) draft[skill] = 7;
}
onChange(draft);
}}
/>
);
})}
</Flex>
),
)}
onChange(draft);
}}
/>
);
})}
</Flex>
))}
</Flex>
);
}
+4 -4
View File
@@ -1,9 +1,9 @@
---
import { gameDefinitions } from '@blitzkit/core';
import { fetchGameDefinitions } from '@blitzkit/core';
import { Code, Flex, Heading, Link, Text } from '@radix-ui/themes';
import packageJson from '../../../../package.json';
const awaitedGameDefinitions = await gameDefinitions;
const gameDefinitions = await fetchGameDefinitions();
---
<Flex
@@ -133,7 +133,7 @@ const awaitedGameDefinitions = await gameDefinitions;
{packageJson.version}
</Code>
<Code size="2" color="gray">
{awaitedGameDefinitions.version}
{gameDefinitions.version}
</Code>
<Code size="2" color="gray">
{import.meta.env.PUBLIC_ASSET_BRANCH}
@@ -148,7 +148,7 @@ const awaitedGameDefinitions = await gameDefinitions;
</Code>
<Text size="2" color="gray"> WoT Blitz </Text>
<Code size="2" color="gray">
{awaitedGameDefinitions.version}
{gameDefinitions.version}
</Code>
<Text size="2" color="gray"> CDN </Text>
<Code size="2" color="gray">
@@ -1,4 +1,4 @@
import { asset, provisionDefinitions } from '@blitzkit/core';
import { asset, fetchProvisionDefinitions } from '@blitzkit/core';
import { GenericTankComponentButton } from './GenericTankComponentButton';
import type { TankComponentButtonProps } from './TankComponentButton';
@@ -6,12 +6,12 @@ interface ProvisionButtonProps extends TankComponentButtonProps {
provision: number;
}
const awaitedProvisionDefinitions = await provisionDefinitions;
const provisionDefinitions = await fetchProvisionDefinitions();
export function ProvisionButton({ provision, ...props }: ProvisionButtonProps) {
return (
<GenericTankComponentButton
tooltip={awaitedProvisionDefinitions[provision].name}
tooltip={provisionDefinitions.provisions[provision].name}
icon={asset(`icons/provisions/${provision}.webp`)}
{...props}
/>
@@ -0,0 +1,3 @@
export function StupidCat() {
return <img src="https://i.imgur.com/6FBBzb9.png" />;
}
@@ -2,6 +2,7 @@ import {
asset,
fetchGameDefinitions,
TANK_CLASSES,
TankType,
TIER_ROMAN_NUMERALS,
type Tier,
} from '@blitzkit/core';
@@ -35,7 +36,7 @@ export function FilterControl({ compact }: FilterControlProps) {
>
<Flex direction={compact ? 'column' : { sm: 'row', initial: 'column' }}>
{times(5, (index) => {
const tier = (index + 1) as Tier;
const tier = index as Tier;
const selected = tankFilters.tiers?.includes(tier);
return (
@@ -46,29 +47,19 @@ export function FilterControl({ compact }: FilterControlProps) {
radius="none"
color={selected ? undefined : 'gray'}
highContrast
onClick={() =>
// mutateTankFilters((draft) => {
// if (draft.tiers?.includes(tier)) {
// draft.tiers = draft.tiers?.filter((t) => t !== tier);
// } else {
// draft.tiers = [...(draft.tiers ?? []), tier];
// }
// })
{
if (tankFilters.tiers.includes(tier)) {
$tankFilters.setKey(
'tiers',
tankFilters.tiers.filter((t) => t !== tier),
);
} else {
$tankFilters.setKey('tiers', [
...tankFilters.tiers,
tier,
]);
}
onClick={() => {
if (tankFilters.tiers.includes(tier)) {
$tankFilters.setKey(
'tiers',
tankFilters.tiers.filter((t) => t !== tier),
);
} else {
$tankFilters.setKey('tiers', [
...tankFilters.tiers,
tier,
]);
}
}
}}
>
<Text size="2">{TIER_ROMAN_NUMERALS[tier]}</Text>
</IconButton>
@@ -78,7 +69,7 @@ export function FilterControl({ compact }: FilterControlProps) {
</Flex>
<Flex direction={compact ? 'column' : { sm: 'row', initial: 'column' }}>
{times(5, (index) => {
const tier = (index + 6) as Tier;
const tier = (index + 5) as Tier;
const selected = tankFilters.tiers?.includes(tier);
return (
@@ -89,28 +80,19 @@ export function FilterControl({ compact }: FilterControlProps) {
radius="none"
color={selected ? undefined : 'gray'}
highContrast
onClick={() =>
// mutateTankFilters((draft) => {
// if (draft.tiers?.includes(tier)) {
// draft.tiers = draft.tiers?.filter((t) => t !== tier);
// } else {
// draft.tiers = [...(draft.tiers ?? []), tier];
// }
// })
{
if (tankFilters.tiers.includes(tier)) {
$tankFilters.setKey(
'tiers',
tankFilters.tiers.filter((t) => t !== tier),
);
} else {
$tankFilters.setKey('tiers', [
...tankFilters.tiers,
tier,
]);
}
onClick={() => {
if (tankFilters.tiers.includes(tier)) {
$tankFilters.setKey(
'tiers',
tankFilters.tiers.filter((t) => t !== tier),
);
} else {
$tankFilters.setKey('tiers', [
...tankFilters.tiers,
tier,
]);
}
}
}}
>
<Text size="2">{TIER_ROMAN_NUMERALS[tier]}</Text>
</IconButton>
@@ -256,30 +238,19 @@ export function FilterControl({ compact }: FilterControlProps) {
radius="none"
color={selected ? undefined : 'gray'}
highContrast
onClick={() =>
// mutateTankFilters((draft) => {
// if (draft.classes?.includes(tankClass)) {
// draft.classes = draft.classes?.filter(
// (c) => c !== tankClass,
// );
// } else {
// draft.classes = [...(draft.classes ?? []), tankClass];
// }
// })
{
if (tankFilters.classes.includes(tankClass)) {
$tankFilters.setKey(
'classes',
tankFilters.classes.filter((c) => c !== tankClass),
);
} else {
$tankFilters.setKey('classes', [
...tankFilters.classes,
tankClass,
]);
}
onClick={() => {
if (tankFilters.classes.includes(tankClass)) {
$tankFilters.setKey(
'classes',
tankFilters.classes.filter((c) => c !== tankClass),
);
} else {
$tankFilters.setKey('classes', [
...tankFilters.classes,
tankClass,
]);
}
}
}}
>
<Icon style={{ width: '1em', height: '1em' }} />
</IconButton>
@@ -296,73 +267,63 @@ export function FilterControl({ compact }: FilterControlProps) {
<Tooltip content="Researchable">
<IconButton
variant={
tankFilters.types?.includes('researchable') ? 'solid' : 'soft'
tankFilters.types?.includes(TankType.RESEARCHABLE)
? 'solid'
: 'soft'
}
radius="none"
color={
tankFilters.types?.includes('researchable') ? undefined : 'gray'
tankFilters.types?.includes(TankType.RESEARCHABLE)
? undefined
: 'gray'
}
highContrast
onClick={() =>
// mutateTankFilters((draft) => {
// if (draft.types?.includes('researchable')) {
// draft.types = draft.types?.filter(
// (t) => t !== 'researchable',
// );
// } else {
// draft.types = [...(draft.types ?? []), 'researchable'];
// }
// })
{
if (tankFilters.types.includes('researchable')) {
$tankFilters.setKey(
'types',
tankFilters.types.filter((t) => t !== 'researchable'),
);
} else {
$tankFilters.setKey('types', [
...tankFilters.types,
'researchable',
]);
}
onClick={() => {
if (tankFilters.types.includes(TankType.RESEARCHABLE)) {
$tankFilters.setKey(
'types',
tankFilters.types.filter((t) => t !== TankType.RESEARCHABLE),
);
} else {
$tankFilters.setKey('types', [
...tankFilters.types,
TankType.RESEARCHABLE,
]);
}
}
}}
>
<ResearchedIcon style={{ width: '1em', height: '1em' }} />
</IconButton>
</Tooltip>
<Tooltip content="Premium">
<IconButton
variant={tankFilters.types?.includes('premium') ? 'solid' : 'soft'}
radius="none"
color={tankFilters.types?.includes('premium') ? 'amber' : 'gray'}
highContrast
onClick={() =>
// mutateTankFilters((draft) => {
// if (draft.types?.includes('premium')) {
// draft.types = draft.types?.filter((t) => t !== 'premium');
// } else {
// draft.types = [...(draft.types ?? []), 'premium'];
// }
// })
{
if (tankFilters.types.includes('premium')) {
$tankFilters.setKey(
'types',
tankFilters.types.filter((t) => t !== 'premium'),
);
} else {
$tankFilters.setKey('types', [
...tankFilters.types,
'premium',
]);
}
}
variant={
tankFilters.types?.includes(TankType.PREMIUM) ? 'solid' : 'soft'
}
radius="none"
color={
tankFilters.types?.includes(TankType.PREMIUM) ? 'amber' : 'gray'
}
highContrast
onClick={() => {
if (tankFilters.types.includes(TankType.PREMIUM)) {
$tankFilters.setKey(
'types',
tankFilters.types.filter((t) => t !== TankType.PREMIUM),
);
} else {
$tankFilters.setKey('types', [
...tankFilters.types,
TankType.PREMIUM,
]);
}
}}
>
<Text
color={
tankFilters.types?.includes('premium') ? undefined : 'amber'
tankFilters.types?.includes(TankType.PREMIUM)
? undefined
: 'amber'
}
style={{ display: 'flex', justifyContent: 'center' }}
>
@@ -373,37 +334,32 @@ export function FilterControl({ compact }: FilterControlProps) {
<Tooltip content="Collector">
<IconButton
variant={
tankFilters.types?.includes('collector') ? 'solid' : 'soft'
tankFilters.types?.includes(TankType.COLLECTOR) ? 'solid' : 'soft'
}
radius="none"
color={tankFilters.types?.includes('collector') ? 'blue' : 'gray'}
highContrast
onClick={() =>
// mutateTankFilters((draft) => {
// if (draft.types?.includes('collector')) {
// draft.types = draft.types?.filter((t) => t !== 'collector');
// } else {
// draft.types = [...(draft.types ?? []), 'collector'];
// }
// })
{
if (tankFilters.types.includes('collector')) {
$tankFilters.setKey(
'types',
tankFilters.types.filter((t) => t !== 'collector'),
);
} else {
$tankFilters.setKey('types', [
...tankFilters.types,
'collector',
]);
}
}
color={
tankFilters.types?.includes(TankType.COLLECTOR) ? 'blue' : 'gray'
}
highContrast
onClick={() => {
if (tankFilters.types.includes(TankType.COLLECTOR)) {
$tankFilters.setKey(
'types',
tankFilters.types.filter((t) => t !== TankType.COLLECTOR),
);
} else {
$tankFilters.setKey('types', [
...tankFilters.types,
TankType.COLLECTOR,
]);
}
}}
>
<Text
color={
tankFilters.types?.includes('collector') ? undefined : 'blue'
tankFilters.types?.includes(TankType.COLLECTOR)
? undefined
: 'blue'
}
style={{ display: 'flex', justifyContent: 'center' }}
>
@@ -424,14 +380,9 @@ export function FilterControl({ compact }: FilterControlProps) {
radius="none"
color={tankFilters.testing === 'include' ? undefined : 'gray'}
highContrast
onClick={() =>
// mutateTankFilters((draft) => {
// draft.testing = 'include';
// })
{
$tankFilters.setKey('testing', 'include');
}
}
onClick={() => {
$tankFilters.setKey('testing', 'include');
}}
>
<ExperimentIcon
style={{ width: '1em', height: '1em', color: 'currentColor' }}
@@ -484,7 +435,6 @@ export function FilterControl({ compact }: FilterControlProps) {
<IconButton
color="red"
onClick={() => {
// tankFiltersStore.setState(tankFiltersStore.getInitialState(), true);
$tankFilters.set(initialTankFilters);
}}
>
@@ -1,16 +1,16 @@
import { equipmentDefinitions } from '@blitzkit/core';
import { fetchEquipmentDefinitions } from '@blitzkit/core';
import { Button, Flex, Heading } from '@radix-ui/themes';
import { Duel } from '../../../../stores/duel';
import { EquipmentManager } from '../../../EquipmentManager';
import { ConfigurationChildWrapper } from './ConfigurationChildWrapper';
const awaitedEquipmentDefinitions = await equipmentDefinitions;
const equipmentDefinitions = await fetchEquipmentDefinitions();
export function Equipment() {
const mutateDuel = Duel.useMutation();
const protagonist = Duel.use((state) => state.protagonist);
const equipmentPreset =
awaitedEquipmentDefinitions.presets[protagonist.tank.equipment];
equipmentDefinitions.presets[protagonist.tank.equipmentPreset];
const equipmentMatrix = Duel.use(
(state) => state.protagonist.equipmentMatrix,
);
@@ -28,7 +28,8 @@ export const TankModel = memo(() => {
const tankModelDefinition = useTankModelDefinition();
const turretModelDefinition =
tankModelDefinition.turrets[protagonist.turret.id];
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
const gunModelDefinition =
turretModelDefinition.guns[protagonist.gun.gunType!.value.base.id];
const { gltf } = useModel(protagonist.tank.id);
const nodes = Object.values(gltf.nodes);
const isDynamicArmorActive = Duel.use((state) =>
@@ -135,7 +136,7 @@ export const TankModel = memo(() => {
const isTurret = node.name.startsWith('turret_');
const isCurrentTurret =
node.name ===
`turret_${turretModelDefinition.model.toString().padStart(2, '0')}`;
`turret_${turretModelDefinition.modelId.toString().padStart(2, '0')}`;
const isVisible = isCurrentTurret;
const position = new Vector2();
const delta = new Vector2();
@@ -168,7 +169,7 @@ export const TankModel = memo(() => {
const duel = duelStore.getState();
const hasImprovedVerticalStabilizer = await hasEquipment(
122,
duel.protagonist.tank.equipment,
duel.protagonist.tank.equipmentPreset,
duel.protagonist.equipmentMatrix,
);
const boundingRect = canvas.getBoundingClientRect();
@@ -231,12 +232,12 @@ export const TankModel = memo(() => {
{nodes.map((node) => {
const isCurrentMantlet =
node.name ===
`gun_${gunModelDefinition.model
`gun_${gunModelDefinition.modelId
.toString()
.padStart(2, '0')}_mask`;
const isCurrentGun =
node.name ===
`gun_${gunModelDefinition.model.toString().padStart(2, '0')}`;
`gun_${gunModelDefinition.modelId.toString().padStart(2, '0')}`;
const isVisible = isCurrentGun || isCurrentMantlet;
const position = new Vector2();
const delta = new Vector2();
@@ -268,7 +269,7 @@ export const TankModel = memo(() => {
const duel = duelStore.getState();
const hasImprovedVerticalStabilizer = await hasEquipment(
122,
duel.protagonist.tank.equipment,
duel.protagonist.tank.equipmentPreset,
duel.protagonist.equipmentMatrix,
);
const boundingRect = canvas.getBoundingClientRect();
@@ -44,7 +44,8 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
const tankModelDefinition = useTankModelDefinition();
const turretModelDefinition =
tankModelDefinition.turrets[protagonist.turret.id];
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
const gunModelDefinition =
turretModelDefinition.guns[protagonist.gun.gunType!.value.base.id];
const display = TankopediaPersistent.useDeferred(
(state) => state.display,
TankopediaDisplay.Model,
@@ -185,7 +186,6 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
<ArmorPlateDisplay />
<AutoClear />
{/* idk why the shot display doesn't work without suspense here lol */}
<Suspense fallback={<ModelLoader />}>
{display === TankopediaDisplay.DynamicArmor && <Armor />}
{display === TankopediaDisplay.StaticArmor && (
@@ -1,6 +1,6 @@
import { fetchTankDefinitions, TankType } from '@blitzkit/core';
import { Box, Flex, Heading, Text } from '@radix-ui/themes';
import { Suspense, useEffect, useMemo, useRef } from 'react';
import { Suspense, useMemo, useRef } from 'react';
import { NAVBAR_HEIGHT } from '../../../constants/navbar';
import { Var } from '../../../core/radix/var';
import { useFullScreen } from '../../../hooks/useFullScreen';
@@ -44,10 +44,6 @@ export function HeroSection() {
return { value } satisfies ThicknessRange;
}, [protagonist]);
useEffect(() => {
// setDummyLoader(false);
}, []);
return (
<Flex justify="center" style={{ backgroundColor: Var('color-surface') }}>
<Flex
@@ -199,10 +199,12 @@ export function MetaSection() {
/>
</Flex>
</Listing>
{protagonist.xp && (
{protagonist.researchCost && (
<Listing label="Research XP">
<Flex align="center" gap="1">
{protagonist.xp.toLocaleString()}
{(
protagonist.researchCost.researchCostType!.value as number
).toLocaleString()}
<img
style={{ width: '1em', height: '1em' }}
alt="xp"