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

-1
View File
@@ -8,7 +8,6 @@ export const TANK_CLASSES = [
TankClass.MEDIUM,
TankClass.HEAVY,
TankClass.TANK_DESTROYER,
TankClass.UNRECOGNIZED,
] as const;
export const emptyAllStats: BlitzStats = {
@@ -3,5 +3,5 @@ import { CamouflageDefinitions } from '../protos';
import { asset } from './asset';
export function fetchCamouflageDefinitions() {
return fetchPB(asset('definitions/camoufles.pb'), CamouflageDefinitions);
return fetchPB(asset('definitions/camouflages.pb'), CamouflageDefinitions);
}
@@ -12,7 +12,6 @@ export const SHELL_NAMES: Record<ShellType, string> = {
[ShellType.APCR]: 'APCR',
[ShellType.HEAT]: 'HEAT',
[ShellType.HE]: 'HE',
[ShellType.UNRECOGNIZED]: 'unrecognized',
};
export const CREW_MEMBER_NAMES: Record<CrewType, string> = {
[CrewType.COMMANDER]: 'Commander',
@@ -20,7 +19,6 @@ export const CREW_MEMBER_NAMES: Record<CrewType, string> = {
[CrewType.GUNNER]: 'Gunner',
[CrewType.LOADER]: 'Loader',
[CrewType.RADIOMAN]: 'Radioman',
[CrewType.UNRECOGNIZED]: 'unrecognized',
};
export const GUN_TYPE_NAMES: Record<
Exclude<GunDefinition['gunType'], undefined>['$case'],
@@ -38,7 +36,6 @@ export const TANK_ICONS: Record<TankClass, string> = {
[TankClass.LIGHT]: 'https://i.imgur.com/CSNha5V.png',
[TankClass.MEDIUM]: 'https://i.imgur.com/wvf3ltm.png',
[TankClass.HEAVY]: 'https://i.imgur.com/ECeqlZa.png',
[TankClass.UNRECOGNIZED]: 'https://i.imgur.com/6FBBzb9.png', // lmfao click on this
};
/**
* @deprecated use svg
@@ -48,7 +45,6 @@ export const TANK_ICONS_PREMIUM: Record<TankClass, string> = {
[TankClass.LIGHT]: 'https://i.imgur.com/zdkpTRb.png',
[TankClass.MEDIUM]: 'https://i.imgur.com/3z7eHX6.png',
[TankClass.HEAVY]: 'https://i.imgur.com/P3vbmyA.png',
[TankClass.UNRECOGNIZED]: 'https://i.imgur.com/6FBBzb9.png',
};
/**
* @deprecated use svg
@@ -58,7 +54,6 @@ export const TANK_ICONS_COLLECTOR: Record<TankClass, string> = {
[TankClass.LIGHT]: 'https://i.imgur.com/EwhtKkU.png',
[TankClass.MEDIUM]: 'https://i.imgur.com/u8YDMBh.png',
[TankClass.HEAVY]: 'https://i.imgur.com/8xRf3nc.png',
[TankClass.UNRECOGNIZED]: 'https://i.imgur.com/6FBBzb9.png',
};
export const TIERS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as const;
export const TIER_ROMAN_NUMERALS: Record<Tier, string> = {
@@ -72,7 +67,6 @@ export const TIER_ROMAN_NUMERALS: Record<Tier, string> = {
[Tier.VIII]: 'VIII',
[Tier.IX]: 'IX',
[Tier.X]: 'X',
[Tier.UNRECOGNIZED]: 'unrecognized',
};
export const flags: Record<string, string> = {
@@ -90,11 +84,4 @@ export const TREE_TYPE_ICONS: Record<TankType, Record<TankClass, string>> = {
[TankType.RESEARCHABLE]: TANK_ICONS,
[TankType.PREMIUM]: TANK_ICONS_PREMIUM,
[TankType.COLLECTOR]: TANK_ICONS_COLLECTOR,
[TankType.UNRECOGNIZED]: {
'-1': 'https://i.imgur.com/6FBBzb9.png',
'0': 'https://i.imgur.com/6FBBzb9.png',
'1': 'https://i.imgur.com/6FBBzb9.png',
'2': 'https://i.imgur.com/6FBBzb9.png',
'3': 'https://i.imgur.com/6FBBzb9.png',
},
};
+4 -5
View File
@@ -10,17 +10,16 @@ export async function fetchTankNames() {
const tankDefinitionsArray = Object.values(tankDefinitions.tanks);
return await Promise.all(
tankDefinitionsArray.map(async (tank, index) => {
const { id } = tankDefinitionsArray[index];
tankDefinitionsArray.map(async (tank) => {
return {
id,
id: tank.id,
name: tank.name,
nameFull: tank.nameFull,
searchableName: tank.nameFull ?? tank.name,
searchableNameDeburr: deburr(tank.nameFull ?? tank.name),
camouflages: tank.camouflages
?.map((id) => camouflageDefinitions.camouflages[id].name)
?.map((id) => camouflageDefinitions.camouflages[id]?.name)
.filter(Boolean)
.join(' '),
treeType: tank.type,
};
@@ -147,9 +147,6 @@ const blitzkitCrewTypeToBlitz: Record<CrewType, BlitzCrewType> = {
[CrewType.GUNNER]: 'gunner',
[CrewType.LOADER]: 'loader',
[CrewType.RADIOMAN]: 'radioman',
// this should never happen... i hope 😢
[CrewType.UNRECOGNIZED]: 'radioman',
};
interface VehicleDefinitions {
invisibility: {
+1
View File
@@ -30,6 +30,7 @@ const args = [
'--ts_proto_opt=esModuleInterop=true',
'--ts_proto_opt=oneof=unions-value',
'--ts_proto_opt=removeEnumPrefix=true',
'--ts_proto_opt=unrecognizedEnum=false',
'--ts_proto_out=.',
...files.map((file) => `${ROOT}/${file}`),
];
@@ -3,7 +3,6 @@ import { PlusIcon } from '@radix-ui/react-icons';
import { Box, Flex, Heading, IconButton, Text } from '@radix-ui/themes';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { use, useCallback, useEffect, useMemo, useState } from 'react';
import * as CompareEphemeral from '../../../stores/compareEphemeral';
export default function Page() {
const pathname = usePathname();
@@ -1,18 +1,18 @@
import {
averageDefinitions,
discoveredIdsDefinitions,
fetchAverageDefinitions,
fetchDiscoveredIdsDefinitions,
formatCompact,
} from '@blitzkit/core';
import { InfoCircledIcon } from '@radix-ui/react-icons';
import { Callout, Flex } from '@radix-ui/themes';
import { use } from 'react';
const discoveredIdsDefinitions = await fetchDiscoveredIdsDefinitions();
const averageDefinitions = await fetchAverageDefinitions();
export function Info() {
const awaitedDiscoveredIdsDefinitions = use(discoveredIdsDefinitions);
const awaitedAverageDefinitions = use(averageDefinitions);
const samples = awaitedDiscoveredIdsDefinitions.count;
const samples = discoveredIdsDefinitions.count;
const minutesAgo = Math.floor(
(Date.now() - awaitedAverageDefinitions.time) / (1000 * 60),
(Date.now() - averageDefinitions.time) / (1000 * 60),
);
const hoursAgo = Math.floor(minutesAgo / 60);
@@ -2,10 +2,10 @@ import {
asset,
coefficient,
CREW_MEMBER_NAMES,
equipmentDefinitions,
fetchEquipmentDefinitions,
fetchProvisionDefinitions,
GUN_TYPE_NAMES,
isExplosive,
provisionDefinitions,
resolvePenetrationCoefficient,
} from '@blitzkit/core';
import { AccessibilityIcon, InfoCircledIcon } from '@radix-ui/react-icons';
@@ -24,15 +24,15 @@ import { Fragment, useEffect, useRef, useState } from 'react';
import { Ad, AdType } from '../../../../../../../../website/src/components/Ad';
import { InfoWithDelta } from '../../../../../../../../website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/InfoWithDelta';
import { applyPitchYawLimits } from '../../../../../../../../website/src/core/blitz/applyPitchYawLimits';
import { tankCharacteristics } from '../../../../../../../../website/src/core/blitzkit/tankCharacteristics';
import { useAdExempt } from '../../../../../../../../website/src/hooks/useAdExempt';
import { useEquipment } from '../../../../../../../../website/src/hooks/useEquipment';
import { useTankModelDefinition } from '../../../../../../../../website/src/hooks/useTankModelDefinition';
import { Duel } from '../../../../../../../../website/src/stores/duel';
import { TankopediaEphemeral } from '../../../../../../../../website/src/stores/tankopediaEphemeral';
import { Info } from '../../../../performance/components/Info';
const awaitedEquipmentDefinitions = await equipmentDefinitions;
const awaitedProvisionDefinitions = await provisionDefinitions;
const equipmentDefinitions = await fetchEquipmentDefinitions();
const provisionDefinitions = await fetchProvisionDefinitions();
export function Characteristics() {
const mutateDuel = Duel.useMutation();
@@ -50,8 +50,8 @@ export function Characteristics() {
const provisionCrewBonus =
provisions.reduce(
(total, provision) =>
awaitedProvisionDefinitions[provision].crew
? total + awaitedProvisionDefinitions[provision].crew! / 100
provisionDefinitions.provisions[provision].crew
? total + provisionDefinitions.provisions[provision].crew! / 100
: total,
0,
) + (hasImprovedVentilation ? 0.08 : 0);
@@ -70,7 +70,8 @@ export function Characteristics() {
const stockGun = stockTurret.guns[0];
const tankModelDefinition = useTankModelDefinition();
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
const gunModelDefinition = turretModelDefinition.guns[gun.id];
const gunModelDefinition =
turretModelDefinition.guns[gun.gunType!.value.base.id];
const stats = tankCharacteristics(
{
tank,
@@ -95,8 +96,8 @@ export function Characteristics() {
},
{
tankModelDefinition,
equipmentDefinitions: awaitedEquipmentDefinitions,
provisionDefinitions: awaitedProvisionDefinitions,
equipmentDefinitions: equipmentDefinitions,
provisionDefinitions: provisionDefinitions,
},
);
@@ -143,7 +144,7 @@ export function Characteristics() {
<Heading size="5">Firepower</Heading>
<Flex>
{gun.shells.map((thisShell, shellIndex) => (
{gun.gunType!.value.base.shells.map((thisShell, shellIndex) => (
<Tooltip content={thisShell.name} key={thisShell.id}>
<IconButton
color={thisShell.id === shell.id ? undefined : 'gray'}
@@ -152,9 +153,13 @@ export function Characteristics() {
borderTopLeftRadius: shellIndex === 0 ? undefined : 0,
borderBottomLeftRadius: shellIndex === 0 ? undefined : 0,
borderTopRightRadius:
shellIndex === gun.shells.length - 1 ? undefined : 0,
shellIndex === gun.gunType!.value.base.shells.length - 1
? undefined
: 0,
borderBottomRightRadius:
shellIndex === gun.shells.length - 1 ? undefined : 0,
shellIndex === gun.gunType!.value.base.shells.length - 1
? undefined
: 0,
marginLeft: shellIndex === 0 ? 0 : -1,
}}
onClick={() => {
@@ -174,7 +179,7 @@ export function Characteristics() {
))}
</Flex>
</Flex>
<Info name="Gun type">{GUN_TYPE_NAMES[gun.type]}</Info>
<Info name="Gun type">{GUN_TYPE_NAMES[gun.gunType!.$case]}</Info>
<InfoWithDelta name="DPM" decimals={0} unit="hp / min">
{stats.dpm}
</InfoWithDelta>
@@ -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"
@@ -507,9 +507,9 @@ export function tankCharacteristics(
gun.gunType!.value.base.camouflageLoss;
const camouflageCaughtOnFire =
tank.camouflageOnFire * tank.camouflageStill * camouflageCoefficientStill;
const width = size[2];
const height = size[0];
const length = size[1];
const width = size.z;
const height = size.x;
const length = size.y;
const volume = width * height * length;
const shellNormalization = shell.normalization ?? 0;
const shellRicochet = isExplosive(shell.type) ? undefined : shell.ricochet;
@@ -32,6 +32,7 @@ const isRoot = pathname === '/';
)
}
<meta property="og:site_name" content="BlitzKit" />
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/favicon.png" />
<Party3 />
@@ -7,7 +7,7 @@ import { Page } from './index';
export const getStaticPaths = (async () => {
const tankDefinitions = await fetchTankDefinitions();
return Object.values(tankDefinitions).map((tank) => ({
return Object.values(tankDefinitions.tanks).map((tank) => ({
params: { id: tank.id },
}));
}) satisfies GetStaticPaths;
@@ -43,13 +43,10 @@ export function Page({ id }: PageProps) {
<CalloutsSection />
<MetaSection />
<TechTreeSection />
{/* {!exempt && <AdMidSectionResponsive />} */}
<CharacteristicsSection />
{/* {!exempt && <AdMidSectionResponsive />} */}
<GameModeSection />
<VideoSection />
<HistorySection />
{/* {!exempt && <AdMidSectionResponsive mb="6" />} */}
</PageWrapper>
</Duel.Provider>
</TankopediaPersistent.Provider>