mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: integrated tank definitions
This commit is contained in:
1 parent
adb0bb2e69
commit
2aefe3f9e3
26 files changed
+475
-273
No files matched your search
+121
-66
@@ -1,5 +1,5 @@
|
|||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
import { existsSync } from 'fs';
|
import { existsSync, writeFileSync } from 'fs';
|
||||||
import { mkdir, readdir, rm } from 'fs/promises';
|
import { mkdir, readdir, rm } from 'fs/promises';
|
||||||
import { argv } from 'process';
|
import { argv } from 'process';
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
@@ -15,16 +15,14 @@ import { toUniqueId } from '../src/core/blitz/toUniqueId';
|
|||||||
import commitMultipleFiles, {
|
import commitMultipleFiles, {
|
||||||
FileChange,
|
FileChange,
|
||||||
} from '../src/core/blitzkrieg/commitMultipleFiles';
|
} from '../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
import { BlitzkriegGunDefinitions } from '../src/core/blitzkrieg/definitions/guns';
|
|
||||||
import {
|
import {
|
||||||
BlitzkriegShellDefinitions,
|
GunDefinition,
|
||||||
|
ShellDefinition,
|
||||||
ShellType,
|
ShellType,
|
||||||
} from '../src/core/blitzkrieg/definitions/shells';
|
TankDefinitions,
|
||||||
import {
|
|
||||||
BlitzkriegTankDefinitions,
|
|
||||||
Tier,
|
Tier,
|
||||||
} from '../src/core/blitzkrieg/definitions/tanks';
|
TurretDefinition,
|
||||||
import { BlitzkriegTurretDefinitions } from '../src/core/blitzkrieg/definitions/turrets';
|
} from '../src/core/blitzkrieg/tankDefinitions';
|
||||||
|
|
||||||
config();
|
config();
|
||||||
|
|
||||||
@@ -98,8 +96,12 @@ interface VehicleDefinitions {
|
|||||||
yawLimits: string | string[];
|
yawLimits: string | string[];
|
||||||
guns: {
|
guns: {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
|
reloadTime: number;
|
||||||
maxAmmo: number;
|
maxAmmo: number;
|
||||||
pitchLimits?: string | string[];
|
pitchLimits?: string | string[];
|
||||||
|
pumpGunMode?: boolean;
|
||||||
|
pumpGunReloadTimes?: string;
|
||||||
|
clip?: { count: number; rate: number };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -141,6 +143,7 @@ const DOI = {
|
|||||||
flags: 'Gfx/Lobby/flags',
|
flags: 'Gfx/Lobby/flags',
|
||||||
'3d': '3d',
|
'3d': '3d',
|
||||||
bigShellIcons: 'Gfx/Shared/tank-supply/ammunition/big',
|
bigShellIcons: 'Gfx/Shared/tank-supply/ammunition/big',
|
||||||
|
moduleIcons: 'Gfx/UI/ModulesTechTree',
|
||||||
};
|
};
|
||||||
|
|
||||||
const allTargets = argv.includes('--all-targets');
|
const allTargets = argv.includes('--all-targets');
|
||||||
@@ -154,10 +157,7 @@ if (!targets && !allTargets) throw new Error('No target(s) specified');
|
|||||||
if (allTargets || targets?.includes('definitions')) {
|
if (allTargets || targets?.includes('definitions')) {
|
||||||
console.log('Building tank definitions...');
|
console.log('Building tank definitions...');
|
||||||
|
|
||||||
const tankDefinitions: BlitzkriegTankDefinitions = {};
|
const definitions: TankDefinitions = {};
|
||||||
const turretDefinitions: BlitzkriegTurretDefinitions = {};
|
|
||||||
const gunDefinitions: BlitzkriegGunDefinitions = {};
|
|
||||||
const shellDefinitions: BlitzkriegShellDefinitions = {};
|
|
||||||
const nations = await readdir(`${DATA}/${DOI.vehicleDefinitions}`).then(
|
const nations = await readdir(`${DATA}/${DOI.vehicleDefinitions}`).then(
|
||||||
(nations) => nations.filter((nation) => nation !== 'common'),
|
(nations) => nations.filter((nation) => nation !== 'common'),
|
||||||
);
|
);
|
||||||
@@ -203,15 +203,41 @@ if (allTargets || targets?.includes('definitions')) {
|
|||||||
const gun = gunList.root.shared[gunKey];
|
const gun = gunList.root.shared[gunKey];
|
||||||
const pitchLimitsRaw =
|
const pitchLimitsRaw =
|
||||||
turretGunEntry.pitchLimits ?? gun.pitchLimits;
|
turretGunEntry.pitchLimits ?? gun.pitchLimits;
|
||||||
|
const gunPitch = (
|
||||||
|
typeof pitchLimitsRaw === 'string'
|
||||||
|
? pitchLimitsRaw
|
||||||
|
: pitchLimitsRaw.at(-1)!
|
||||||
|
)
|
||||||
|
.split(' ')
|
||||||
|
.map(Number) as [number, number];
|
||||||
|
const gunName =
|
||||||
|
strings[gun.userString] ?? gunKey.replaceAll('_', ' ');
|
||||||
|
const gunType =
|
||||||
|
'clip' in turretGunEntry
|
||||||
|
? turretGunEntry.pumpGunMode
|
||||||
|
? 'auto_reloader'
|
||||||
|
: 'auto_loader'
|
||||||
|
: 'regular';
|
||||||
|
const gunReload =
|
||||||
|
gunType === 'auto_reloader'
|
||||||
|
? turretGunEntry.pumpGunReloadTimes!.split(' ').map(Number)
|
||||||
|
: turretGunEntry.reloadTime;
|
||||||
|
const gunClipCount =
|
||||||
|
gunType === 'regular' ? undefined : turretGunEntry.clip!.count;
|
||||||
|
const gunInterClip =
|
||||||
|
gunType === 'regular'
|
||||||
|
? undefined
|
||||||
|
: 60 / turretGunEntry.clip!.rate;
|
||||||
const gunShells = Object.keys(gun.shots).map((shellKey) => {
|
const gunShells = Object.keys(gun.shots).map((shellKey) => {
|
||||||
const turretShellEntry = gun.shots[shellKey];
|
const turretShellEntry = gun.shots[shellKey];
|
||||||
const shell = shellList.root[shellKey];
|
const shell = shellList.root[shellKey];
|
||||||
const shellId = toUniqueId(nation, shell.id);
|
const shellId = toUniqueId(nation, shell.id);
|
||||||
|
const shellName =
|
||||||
|
strings[shell.userString] ?? shellKey.replaceAll('_', ' ');
|
||||||
|
|
||||||
shellDefinitions[shellId] = {
|
return {
|
||||||
id: shellId,
|
id: shellId,
|
||||||
name:
|
name: shellName,
|
||||||
strings[shell.userString] ?? shellKey.replaceAll('_', ' '),
|
|
||||||
speed: turretShellEntry.speed,
|
speed: turretShellEntry.speed,
|
||||||
damage: {
|
damage: {
|
||||||
armor: shell.damage.armor,
|
armor: shell.damage.armor,
|
||||||
@@ -222,28 +248,23 @@ if (allTargets || targets?.includes('definitions')) {
|
|||||||
ricochet: shell.ricochetAngle,
|
ricochet: shell.ricochetAngle,
|
||||||
type: blitzShellKindToBLitzkrieg[shell.kind],
|
type: blitzShellKindToBLitzkrieg[shell.kind],
|
||||||
icon: shell.icon,
|
icon: shell.icon,
|
||||||
};
|
} satisfies ShellDefinition;
|
||||||
|
|
||||||
return shellId;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gunDefinitions[gunId] = {
|
return {
|
||||||
id: gunId,
|
id: gunId,
|
||||||
pitch: (typeof pitchLimitsRaw === 'string'
|
pitch: gunPitch,
|
||||||
? pitchLimitsRaw
|
name: gunName,
|
||||||
: pitchLimitsRaw.at(-1)!
|
|
||||||
)
|
|
||||||
.split(' ')
|
|
||||||
.map(Number) as [number, number],
|
|
||||||
name: strings[gun.userString] ?? gunKey.replaceAll('_', ' '),
|
|
||||||
tier: gun.level as Tier,
|
tier: gun.level as Tier,
|
||||||
shells: gunShells,
|
shells: gunShells,
|
||||||
};
|
type: gunType,
|
||||||
|
reload: gunReload,
|
||||||
return gunId;
|
count: gunClipCount,
|
||||||
|
interClip: gunInterClip,
|
||||||
|
} as GunDefinition;
|
||||||
});
|
});
|
||||||
|
|
||||||
turretDefinitions[turretId] = {
|
return {
|
||||||
id: turretId,
|
id: turretId,
|
||||||
name:
|
name:
|
||||||
strings[turret.userString] ??
|
strings[turret.userString] ??
|
||||||
@@ -258,13 +279,11 @@ if (allTargets || targets?.includes('definitions')) {
|
|||||||
.split(' ')
|
.split(' ')
|
||||||
.map(Number) as [number, number],
|
.map(Number) as [number, number],
|
||||||
guns: turretGuns,
|
guns: turretGuns,
|
||||||
};
|
} satisfies TurretDefinition;
|
||||||
|
|
||||||
return turretId;
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
tankDefinitions[tankId] = {
|
definitions[tankId] = {
|
||||||
id: tankId,
|
id: tankId,
|
||||||
name:
|
name:
|
||||||
(tank.shortUserString
|
(tank.shortUserString
|
||||||
@@ -288,36 +307,37 @@ if (allTargets || targets?.includes('definitions')) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
console.log('Committing tank definitions...');
|
console.log('Committing tank definitions...');
|
||||||
await commitMultipleFiles(
|
writeFileSync('test.json', JSON.stringify(definitions, null, 2));
|
||||||
'tresabhi',
|
// await commitMultipleFiles(
|
||||||
'blitzkrieg-assets',
|
// 'tresabhi',
|
||||||
'main',
|
// 'blitzkrieg-assets',
|
||||||
'definitions',
|
// 'main',
|
||||||
[
|
// 'definitions',
|
||||||
{
|
// [
|
||||||
content: JSON.stringify(tankDefinitions),
|
// {
|
||||||
encoding: 'utf-8',
|
// content: JSON.stringify(tankDefinitions),
|
||||||
path: 'definitions/tanks.json',
|
// encoding: 'utf-8',
|
||||||
},
|
// path: 'definitions/tanks.json',
|
||||||
{
|
// },
|
||||||
content: JSON.stringify(turretDefinitions),
|
// {
|
||||||
encoding: 'utf-8',
|
// content: JSON.stringify(turretDefinitions),
|
||||||
path: 'definitions/turrets.json',
|
// encoding: 'utf-8',
|
||||||
},
|
// path: 'definitions/turrets.json',
|
||||||
{
|
// },
|
||||||
content: JSON.stringify(gunDefinitions),
|
// {
|
||||||
encoding: 'utf-8',
|
// content: JSON.stringify(gunDefinitions),
|
||||||
path: 'definitions/guns.json',
|
// encoding: 'utf-8',
|
||||||
},
|
// path: 'definitions/guns.json',
|
||||||
{
|
// },
|
||||||
content: JSON.stringify(shellDefinitions),
|
// {
|
||||||
encoding: 'utf-8',
|
// content: JSON.stringify(shellDefinitions),
|
||||||
path: 'definitions/shells.json',
|
// encoding: 'utf-8',
|
||||||
},
|
// path: 'definitions/shells.json',
|
||||||
],
|
// },
|
||||||
|
// ],
|
||||||
|
|
||||||
true,
|
// true,
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -356,14 +376,14 @@ if (
|
|||||||
changes.push({
|
changes.push({
|
||||||
content: await readBase64DVPL(big),
|
content: await readBase64DVPL(big),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: `icons/big/${id}.webp`,
|
path: `icons/tank/big/${id}.webp`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (allTargets || targets?.includes('smallTankIcons')) {
|
if (allTargets || targets?.includes('smallTankIcons')) {
|
||||||
changes.push({
|
changes.push({
|
||||||
content: await readBase64DVPL(small),
|
content: await readBase64DVPL(small),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: `icons/small/${id}.webp`,
|
path: `icons/tank/small/${id}.webp`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -527,7 +547,7 @@ if (allTargets || targets?.includes('shellIcons')) {
|
|||||||
.toBuffer()
|
.toBuffer()
|
||||||
).toString('base64'),
|
).toString('base64'),
|
||||||
encoding: 'base64',
|
encoding: 'base64',
|
||||||
path: `shells/${name}.webp`,
|
path: `icons/shells/${name}.webp`,
|
||||||
} satisfies FileChange;
|
} satisfies FileChange;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -542,3 +562,38 @@ if (allTargets || targets?.includes('shellIcons')) {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allTargets || targets?.includes('moduleIcons')) {
|
||||||
|
console.log('Building module icons...');
|
||||||
|
|
||||||
|
const changes = await Promise.all(
|
||||||
|
(await readdir(`${DATA}/${DOI.moduleIcons}`))
|
||||||
|
.filter(
|
||||||
|
(file) =>
|
||||||
|
!file.endsWith('@2x.packed.webp.dvpl') && file.startsWith('vehicle'),
|
||||||
|
)
|
||||||
|
.map(async (file) => {
|
||||||
|
const nameRaw = file.match(/vehicle(.+)\.packed\.webp\.dvpl/)![1];
|
||||||
|
const name = nameRaw[0].toLowerCase() + nameRaw.slice(1);
|
||||||
|
const content = await readBase64DVPL(
|
||||||
|
`${DATA}/${DOI.moduleIcons}/${file}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
content,
|
||||||
|
path: `icons/modules/${name}.webp`,
|
||||||
|
encoding: 'base64',
|
||||||
|
} satisfies FileChange;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Committing module icons...');
|
||||||
|
commitMultipleFiles(
|
||||||
|
'tresabhi',
|
||||||
|
'blitzkrieg-assets',
|
||||||
|
'main',
|
||||||
|
'module icons',
|
||||||
|
changes,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,9 +7,9 @@ import { TreeTypeEnum } from '../../../components/Tanks';
|
|||||||
import { WARGAMING_APPLICATION_ID } from '../../../constants/wargamingApplicationID';
|
import { WARGAMING_APPLICATION_ID } from '../../../constants/wargamingApplicationID';
|
||||||
import fetchBlitz from '../../../core/blitz/fetchBlitz';
|
import fetchBlitz from '../../../core/blitz/fetchBlitz';
|
||||||
import {
|
import {
|
||||||
BlitzkriegTankDefinition,
|
TankDefinition,
|
||||||
tankDefinitions,
|
tankDefinitions,
|
||||||
} from '../../../core/blitzkrieg/definitions/tanks';
|
} from '../../../core/blitzkrieg/tankDefinitions';
|
||||||
import { tankAverages } from '../../../core/blitzstars/tankAverages';
|
import { tankAverages } from '../../../core/blitzstars/tankAverages';
|
||||||
import calculateWN8 from '../../../core/statistics/calculateWN8';
|
import calculateWN8 from '../../../core/statistics/calculateWN8';
|
||||||
import { deltaTankStats } from '../../../core/statistics/deltaTankStats';
|
import { deltaTankStats } from '../../../core/statistics/deltaTankStats';
|
||||||
@@ -30,7 +30,7 @@ export default function SessionPage() {
|
|||||||
|
|
||||||
list: {
|
list: {
|
||||||
stats: IndividualTankStats;
|
stats: IndividualTankStats;
|
||||||
tankDefinitions?: BlitzkriegTankDefinition;
|
tankDefinitions?: TankDefinition;
|
||||||
career: IndividualTankStats;
|
career: IndividualTankStats;
|
||||||
currentWN8?: number;
|
currentWN8?: number;
|
||||||
careerWN8?: number;
|
careerWN8?: number;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
Dialog,
|
Dialog,
|
||||||
Flex,
|
Flex,
|
||||||
Heading,
|
Heading,
|
||||||
Separator,
|
|
||||||
Slider,
|
Slider,
|
||||||
Tabs,
|
Tabs,
|
||||||
Text,
|
Text,
|
||||||
@@ -27,52 +26,64 @@ import { debounce } from 'lodash';
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { use, useEffect, useRef, useState } from 'react';
|
import { use, useEffect, useRef, useState } from 'react';
|
||||||
import { Flag } from '../../../../components/Flag';
|
import { Flag } from '../../../../components/Flag';
|
||||||
|
import { ModuleButtons } from '../../../../components/ModuleButton';
|
||||||
import PageWrapper from '../../../../components/PageWrapper';
|
import PageWrapper from '../../../../components/PageWrapper';
|
||||||
import { asset } from '../../../../core/blitzkrieg/asset';
|
import { asset } from '../../../../core/blitzkrieg/asset';
|
||||||
import { gunDefinitions } from '../../../../core/blitzkrieg/definitions/guns';
|
import { gunDefinitions } from '../../../../core/blitzkrieg/definitions/guns';
|
||||||
import { shellDefinitions } from '../../../../core/blitzkrieg/definitions/shells';
|
import { shellDefinitions } from '../../../../core/blitzkrieg/definitions/shells';
|
||||||
|
import { turretDefinitions } from '../../../../core/blitzkrieg/definitions/turrets';
|
||||||
import {
|
import {
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
tankDefinitions,
|
tankDefinitions,
|
||||||
tankNamesDiacritics,
|
tankNamesDiacritics,
|
||||||
tanksDefinitionsArray,
|
} from '../../../../core/blitzkrieg/tankDefinitions';
|
||||||
} from '../../../../core/blitzkrieg/definitions/tanks';
|
|
||||||
import { turretDefinitions } from '../../../../core/blitzkrieg/definitions/turrets';
|
|
||||||
import * as styles from '../page.css';
|
import * as styles from '../page.css';
|
||||||
|
|
||||||
type Mode = 'model' | 'armor';
|
|
||||||
|
|
||||||
export default function Page({ params }: { params: { id: string } }) {
|
export default function Page({ params }: { params: { id: string } }) {
|
||||||
const id = parseInt(params.id);
|
const id = parseInt(params.id);
|
||||||
const awaitedTankDefinitions = use(tankDefinitions);
|
const awaitedTankDefinitions = use(tankDefinitions);
|
||||||
const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray);
|
|
||||||
const awaitedTurretDefinitions = use(turretDefinitions);
|
const awaitedTurretDefinitions = use(turretDefinitions);
|
||||||
const awaitedGunDefinitions = use(gunDefinitions);
|
const awaitedGunDefinitions = use(gunDefinitions);
|
||||||
const awaitedShellDefinitions = use(shellDefinitions);
|
const awaitedShellDefinitions = use(shellDefinitions);
|
||||||
const awaitedTankNamesDiacritics = use(tankNamesDiacritics);
|
const awaitedTankNamesDiacritics = use(tankNamesDiacritics);
|
||||||
const tank = awaitedTankDefinitions[id];
|
const tank = awaitedTankDefinitions[id];
|
||||||
const [turret, setTurret] = useState(
|
const [turret, setTurret] = useState(
|
||||||
awaitedTurretDefinitions[tank.turrets[0]],
|
awaitedTurretDefinitions[tank.turrets.at(-1)!],
|
||||||
);
|
);
|
||||||
const [gun, setGun] = useState(awaitedGunDefinitions[turret.guns[0]]);
|
const [gun, setGun] = useState(awaitedGunDefinitions[turret.guns.at(-1)!]);
|
||||||
const [crew, setCrew] = useState(100);
|
const [crew, setCrew] = useState(100);
|
||||||
const [versusTankId, setVersusTankId] = useState(
|
const [mode, setMode] = useState('model');
|
||||||
awaitedTanksDefinitionsArray[0].id,
|
|
||||||
);
|
|
||||||
const [mode, setMode] = useState<Mode>('model');
|
|
||||||
const versusTankSearchInput = useRef<HTMLInputElement>(null);
|
const versusTankSearchInput = useRef<HTMLInputElement>(null);
|
||||||
const [versusTankSearchResults, setVersusTankSearchResults] = useState<
|
const [versusTankSearchResults, setVersusTankSearchResults] = useState<
|
||||||
number[]
|
number[]
|
||||||
>([]);
|
>([]);
|
||||||
const [versusTankTurretId, setVersusTankTurretId] = useState(
|
const [versusTank, setVersusTank] = useState(tank);
|
||||||
awaitedTurretDefinitions[tank.turrets[0]].id,
|
const [versusTurret, setVersusTurret] = useState(
|
||||||
|
awaitedTurretDefinitions[versusTank.turrets.at(-1)!],
|
||||||
);
|
);
|
||||||
const versusTank = awaitedTankDefinitions[versusTankId];
|
const [versusGun, setVersusGun] = useState(
|
||||||
|
awaitedGunDefinitions[versusTurret.guns.at(-1)!],
|
||||||
|
);
|
||||||
|
const [versusTankTab, setVersusTankTab] = useState('search');
|
||||||
|
|
||||||
useEffect(() => setGun(awaitedGunDefinitions[turret.guns[0]]), [turret]);
|
useEffect(() => {
|
||||||
|
if (!turret.guns.includes(gun.id)) {
|
||||||
|
setGun(awaitedGunDefinitions[turret.guns.at(-1)!]);
|
||||||
|
}
|
||||||
|
}, [turret]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!versusTank.turrets.includes(versusTurret.id)) {
|
||||||
|
setVersusTurret(awaitedTurretDefinitions[versusTank.turrets.at(-1)!]);
|
||||||
|
}
|
||||||
|
}, [versusTank]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!versusTurret.guns.includes(versusGun.id)) {
|
||||||
|
setVersusGun(awaitedGunDefinitions[versusTurret.guns.at(-1)!]);
|
||||||
|
}
|
||||||
|
}, [versusTurret]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapper>
|
<PageWrapper color="purple">
|
||||||
<Flex gap="8" direction="column">
|
<Flex gap="8" direction="column">
|
||||||
<Flex gap="4" direction="column">
|
<Flex gap="4" direction="column">
|
||||||
<Flex justify="between" align="center">
|
<Flex justify="between" align="center">
|
||||||
@@ -94,10 +105,7 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
|
|
||||||
<Card style={{ position: 'relative' }}>
|
<Card style={{ position: 'relative' }}>
|
||||||
<Flex direction="column" gap="2">
|
<Flex direction="column" gap="2">
|
||||||
<Tabs.Root
|
<Tabs.Root value={mode} onValueChange={setMode}>
|
||||||
value={mode}
|
|
||||||
onValueChange={(value) => setMode(value as Mode)}
|
|
||||||
>
|
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
<Tabs.Trigger value="model">Model</Tabs.Trigger>
|
<Tabs.Trigger value="model">Model</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="armor">Armor</Tabs.Trigger>
|
<Tabs.Trigger value="armor">Armor</Tabs.Trigger>
|
||||||
@@ -136,86 +144,191 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
<Dialog.Root>
|
<Dialog.Root>
|
||||||
<Dialog.Trigger>
|
<Dialog.Trigger>
|
||||||
<Button variant="ghost">
|
<Button variant="ghost">
|
||||||
{awaitedTankDefinitions[versusTankId].name}
|
{versusTank.name}
|
||||||
<CaretRightIcon />
|
<CaretRightIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
|
|
||||||
<Dialog.Content>
|
<Dialog.Content>
|
||||||
<Flex direction="column" gap="6">
|
<Tabs.Root
|
||||||
<Flex direction="column" gap="2">
|
value={versusTankTab}
|
||||||
<Heading size="4">Search tank</Heading>
|
onValueChange={setVersusTankTab}
|
||||||
|
>
|
||||||
|
<Flex gap="4" direction="column">
|
||||||
|
<Tabs.List>
|
||||||
|
<Tabs.Trigger value="search">Search</Tabs.Trigger>
|
||||||
|
<Tabs.Trigger value="configure">
|
||||||
|
Configure
|
||||||
|
</Tabs.Trigger>
|
||||||
|
</Tabs.List>
|
||||||
|
|
||||||
<TextField.Root>
|
<Tabs.Content value="search">
|
||||||
<TextField.Slot>
|
<Flex
|
||||||
<MagnifyingGlassIcon />
|
direction="column"
|
||||||
</TextField.Slot>
|
gap="4"
|
||||||
<TextField.Input
|
style={{ flex: 1 }}
|
||||||
ref={versusTankSearchInput}
|
justify="center"
|
||||||
placeholder="Search tank..."
|
>
|
||||||
onChange={debounce(() => {
|
<TextField.Root>
|
||||||
setVersusTankSearchResults(
|
<TextField.Slot>
|
||||||
go(
|
<MagnifyingGlassIcon />
|
||||||
versusTankSearchInput.current!.value,
|
</TextField.Slot>
|
||||||
awaitedTankNamesDiacritics,
|
<TextField.Input
|
||||||
{ key: 'combined', limit: 8 },
|
ref={versusTankSearchInput}
|
||||||
).map((item) => item.obj.id),
|
placeholder="Search tank..."
|
||||||
);
|
onChange={debounce(() => {
|
||||||
}, 500)}
|
setVersusTankSearchResults(
|
||||||
/>
|
go(
|
||||||
</TextField.Root>
|
versusTankSearchInput.current!.value,
|
||||||
</Flex>
|
awaitedTankNamesDiacritics,
|
||||||
|
{ key: 'combined', limit: 8 },
|
||||||
|
).map((item) => item.obj.id),
|
||||||
|
);
|
||||||
|
}, 500)}
|
||||||
|
/>
|
||||||
|
</TextField.Root>
|
||||||
|
|
||||||
{(versusTankSearchResults.length > 0 ||
|
<Flex direction="column" gap="2">
|
||||||
versusTankSearchInput.current?.value) && (
|
{(versusTankSearchResults.length > 0 ||
|
||||||
<Flex direction="column" gap="2">
|
versusTankSearchInput.current?.value) && (
|
||||||
{versusTankSearchResults.map((id) => (
|
<Flex direction="column" gap="2">
|
||||||
<Button
|
{versusTankSearchResults.map((id) => (
|
||||||
key={id}
|
<Button
|
||||||
variant="ghost"
|
key={id}
|
||||||
onClick={() => {
|
variant="ghost"
|
||||||
setVersusTankId(id);
|
onClick={() => {
|
||||||
setVersusTankSearchResults([]);
|
setVersusTank(
|
||||||
versusTankSearchInput.current!.value = '';
|
awaitedTankDefinitions[id],
|
||||||
}}
|
);
|
||||||
|
setVersusTankSearchResults([]);
|
||||||
|
versusTankSearchInput.current!.value =
|
||||||
|
'';
|
||||||
|
setVersusTankTab('configure');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{awaitedTankDefinitions[id].name}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{versusTankSearchResults.length === 0 &&
|
||||||
|
(versusTankSearchInput.current
|
||||||
|
? versusTankSearchInput.current.value
|
||||||
|
.length > 0
|
||||||
|
: false) && (
|
||||||
|
<Button disabled variant="ghost">
|
||||||
|
No search results
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Tabs.Content>
|
||||||
|
|
||||||
|
<Tabs.Content value="configure">
|
||||||
|
<Flex direction="column" gap="4">
|
||||||
|
<Flex
|
||||||
|
direction="column"
|
||||||
|
gap="2"
|
||||||
|
style={{ flex: 1 }}
|
||||||
>
|
>
|
||||||
{awaitedTankDefinitions[id].name}
|
<Heading size="4">Configuration</Heading>
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{versusTankSearchResults.length === 0 &&
|
<Flex gap="2" wrap="wrap">
|
||||||
(versusTankSearchInput.current
|
<Flex>
|
||||||
? versusTankSearchInput.current.value.length > 0
|
{versusTank.turrets.map((id, index) => (
|
||||||
: false) && (
|
<Tooltip
|
||||||
<Button disabled variant="ghost">
|
content={
|
||||||
No search results
|
awaitedTurretDefinitions[id].name
|
||||||
</Button>
|
}
|
||||||
)}
|
>
|
||||||
</Flex>
|
<ModuleButtons
|
||||||
)}
|
key={id}
|
||||||
|
onClick={() =>
|
||||||
|
setVersusTurret(
|
||||||
|
awaitedTurretDefinitions[id],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
selected={versusTurret.id === id}
|
||||||
|
tier={
|
||||||
|
awaitedTurretDefinitions[id].tier
|
||||||
|
}
|
||||||
|
type="turret"
|
||||||
|
style={{
|
||||||
|
margin: -0.5,
|
||||||
|
borderTopLeftRadius:
|
||||||
|
index === 0 ? undefined : 0,
|
||||||
|
borderBottomLeftRadius:
|
||||||
|
index === 0 ? undefined : 0,
|
||||||
|
borderTopRightRadius:
|
||||||
|
index ===
|
||||||
|
versusTank.turrets.length - 1
|
||||||
|
? undefined
|
||||||
|
: 0,
|
||||||
|
borderBottomRightRadius:
|
||||||
|
index ===
|
||||||
|
versusTank.turrets.length - 1
|
||||||
|
? undefined
|
||||||
|
: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
{versusTurret.guns.map((id, index) => (
|
||||||
|
<Tooltip
|
||||||
|
content={awaitedGunDefinitions[id].name}
|
||||||
|
>
|
||||||
|
<ModuleButtons
|
||||||
|
key={id}
|
||||||
|
onClick={() =>
|
||||||
|
setVersusGun(
|
||||||
|
awaitedGunDefinitions[id],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
selected={versusGun.id === id}
|
||||||
|
tier={awaitedGunDefinitions[id].tier}
|
||||||
|
type="gun"
|
||||||
|
style={{
|
||||||
|
margin: -0.5,
|
||||||
|
borderTopLeftRadius:
|
||||||
|
index === 0 ? undefined : 0,
|
||||||
|
borderBottomLeftRadius:
|
||||||
|
index === 0 ? undefined : 0,
|
||||||
|
borderTopRightRadius:
|
||||||
|
index ===
|
||||||
|
versusTurret.guns.length - 1
|
||||||
|
? undefined
|
||||||
|
: 0,
|
||||||
|
borderBottomRightRadius:
|
||||||
|
index ===
|
||||||
|
versusTurret.guns.length - 1
|
||||||
|
? undefined
|
||||||
|
: 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
<Separator style={{ width: '100%' }} />
|
<Flex
|
||||||
|
direction="column"
|
||||||
<Flex direction="column" gap="2">
|
gap="2"
|
||||||
<Heading size="4">
|
style={{ flex: 1 }}
|
||||||
{awaitedTankDefinitions[versusTankId].name}
|
|
||||||
</Heading>
|
|
||||||
|
|
||||||
<Flex>
|
|
||||||
{versusTank.turrets.map((id) => (
|
|
||||||
<Button
|
|
||||||
key={id}
|
|
||||||
variant="ghost"
|
|
||||||
onClick={() => setVersusTankTurretId(id)}
|
|
||||||
radius="small"
|
|
||||||
color="gray"
|
|
||||||
>
|
>
|
||||||
{awaitedTurretDefinitions[id].name}
|
<Heading size="4">Properties</Heading>
|
||||||
</Button>
|
|
||||||
))}
|
<ul>
|
||||||
</Flex>
|
<li>Penetration</li>
|
||||||
|
</ul>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Tabs.Content>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Tabs.Root>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
</Dialog.Root>
|
</Dialog.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -227,17 +340,25 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
|
|
||||||
<Flex gap="1">
|
<Flex gap="1">
|
||||||
<Button variant="solid" radius="small">
|
<Button variant="solid" radius="small">
|
||||||
<img src={asset('shells/ap.webp')} width={24} height={24} />
|
|
||||||
</Button>
|
|
||||||
<Button variant="soft" radius="small" color="gray">
|
|
||||||
<img
|
<img
|
||||||
src={asset('shells/hc_premium.webp')}
|
src={asset('icons/shells/ap.webp')}
|
||||||
width={24}
|
width={24}
|
||||||
height={24}
|
height={24}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="soft" radius="small" color="gray">
|
<Button variant="soft" radius="small" color="gray">
|
||||||
<img src={asset('shells/he.webp')} width={24} height={24} />
|
<img
|
||||||
|
src={asset('icons/shells/hc_premium.webp')}
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
<Button variant="soft" radius="small" color="gray">
|
||||||
|
<img
|
||||||
|
src={asset('icons/shells/he.webp')}
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
NATIONS,
|
NATIONS,
|
||||||
TIERS,
|
TIERS,
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
} from '../../../../../core/blitzkrieg/definitions/tanks';
|
} from '../../../../../core/blitzkrieg/tankDefinitions';
|
||||||
import mutateTankopedia, {
|
import mutateTankopedia, {
|
||||||
TankopediaTestTankDisplay,
|
TankopediaTestTankDisplay,
|
||||||
useTankopedia,
|
useTankopedia,
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { CaretLeftIcon, CaretRightIcon } from '@radix-ui/react-icons';
|
import { CaretLeftIcon, CaretRightIcon } from '@radix-ui/react-icons';
|
||||||
import { Button, Flex, TextField } from '@radix-ui/themes';
|
import { Button, Flex, TextField } from '@radix-ui/themes';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { BlitzkriegTankDefinition } from '../../../../core/blitzkrieg/definitions/tanks';
|
import { TankDefinition } from '../../../../core/blitzkrieg/tankDefinitions';
|
||||||
|
|
||||||
interface PageTurnerProps {
|
interface PageTurnerProps {
|
||||||
page: number;
|
page: number;
|
||||||
setPage: (page: number) => void;
|
setPage: (page: number) => void;
|
||||||
searchedList: BlitzkriegTankDefinition[];
|
searchedList: TankDefinition[];
|
||||||
tanksPerPage: number;
|
tanksPerPage: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ import { Suspense, use, useEffect, useMemo, useRef, useState } from 'react';
|
|||||||
import PageWrapper from '../../../components/PageWrapper';
|
import PageWrapper from '../../../components/PageWrapper';
|
||||||
import { asset } from '../../../core/blitzkrieg/asset';
|
import { asset } from '../../../core/blitzkrieg/asset';
|
||||||
import {
|
import {
|
||||||
BlitzkriegTankDefinition,
|
|
||||||
TANK_ICONS,
|
TANK_ICONS,
|
||||||
TANK_ICONS_COLLECTOR,
|
TANK_ICONS_COLLECTOR,
|
||||||
TANK_ICONS_PREMIUM,
|
TANK_ICONS_PREMIUM,
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
|
TankDefinition,
|
||||||
tanksDefinitionsArray,
|
tanksDefinitionsArray,
|
||||||
} from '../../../core/blitzkrieg/definitions/tanks';
|
} from '../../../core/blitzkrieg/tankDefinitions';
|
||||||
import { tankIcon } from '../../../core/blitzkrieg/tankIcon';
|
import { tankIcon } from '../../../core/blitzkrieg/tankIcon';
|
||||||
import { theme } from '../../../stitches.config';
|
import { theme } from '../../../stitches.config';
|
||||||
import mutateTankopedia, {
|
import mutateTankopedia, {
|
||||||
@@ -117,10 +117,7 @@ export default function Page() {
|
|||||||
} else {
|
} else {
|
||||||
setSearchedList(
|
setSearchedList(
|
||||||
go(event.target.value, searchableTanks, {
|
go(event.target.value, searchableTanks, {
|
||||||
keys: [
|
keys: ['name', 'id'] satisfies (keyof TankDefinition)[],
|
||||||
'name',
|
|
||||||
'id',
|
|
||||||
] satisfies (keyof BlitzkriegTankDefinition)[],
|
|
||||||
}).map(({ obj }) => obj),
|
}).map(({ obj }) => obj),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { AllStats, getAccountInfo } from '../core/blitz/getAccountInfo';
|
|||||||
import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo';
|
import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo';
|
||||||
import getTankStats from '../core/blitz/getTankStats';
|
import getTankStats from '../core/blitz/getTankStats';
|
||||||
import getTreeType from '../core/blitz/getTreeType';
|
import getTreeType from '../core/blitz/getTreeType';
|
||||||
import { tankDefinitions } from '../core/blitzkrieg/definitions/tanks';
|
|
||||||
import { filtersToDescription } from '../core/blitzkrieg/filtersToDescription';
|
import { filtersToDescription } from '../core/blitzkrieg/filtersToDescription';
|
||||||
|
import { tankDefinitions } from '../core/blitzkrieg/tankDefinitions';
|
||||||
import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton';
|
import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton';
|
||||||
import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod';
|
import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod';
|
||||||
import { tankAverages } from '../core/blitzstars/tankAverages';
|
import { tankAverages } from '../core/blitzstars/tankAverages';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import { getAccountInfo } from '../core/blitz/getAccountInfo';
|
import { getAccountInfo } from '../core/blitz/getAccountInfo';
|
||||||
import { tankDefinitions } from '../core/blitzkrieg/definitions/tanks';
|
|
||||||
import getPeriodNow from '../core/blitzkrieg/getPeriodNow';
|
import getPeriodNow from '../core/blitzkrieg/getPeriodNow';
|
||||||
import getTimeDaysAgo from '../core/blitzkrieg/getTimeDaysAgo';
|
import getTimeDaysAgo from '../core/blitzkrieg/getTimeDaysAgo';
|
||||||
|
import { tankDefinitions } from '../core/blitzkrieg/tankDefinitions';
|
||||||
import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod';
|
import getStatsInPeriod from '../core/blitzstars/getStatsInPeriod';
|
||||||
import { tankAverages } from '../core/blitzstars/tankAverages';
|
import { tankAverages } from '../core/blitzstars/tankAverages';
|
||||||
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import { getAccountInfo } from '../core/blitz/getAccountInfo';
|
|||||||
import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo';
|
import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo';
|
||||||
import getTankStats from '../core/blitz/getTankStats';
|
import getTankStats from '../core/blitz/getTankStats';
|
||||||
import getTreeType from '../core/blitz/getTreeType';
|
import getTreeType from '../core/blitz/getTreeType';
|
||||||
|
import { emblemIdToURL } from '../core/blitzkrieg/emblemIdToURL';
|
||||||
import {
|
import {
|
||||||
BlitzkriegTankDefinition,
|
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
|
TankDefinition,
|
||||||
Tier,
|
Tier,
|
||||||
tankDefinitions,
|
tankDefinitions,
|
||||||
} from '../core/blitzkrieg/definitions/tanks';
|
} from '../core/blitzkrieg/tankDefinitions';
|
||||||
import { emblemIdToURL } from '../core/blitzkrieg/emblemIdToURL';
|
|
||||||
import { tankIcon } from '../core/blitzkrieg/tankIcon';
|
import { tankIcon } from '../core/blitzkrieg/tankIcon';
|
||||||
import addTierChoices from '../core/discord/addTierChoices';
|
import addTierChoices from '../core/discord/addTierChoices';
|
||||||
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
||||||
@@ -47,7 +47,7 @@ export const ownedTanksCommand: CommandRegistry = {
|
|||||||
)
|
)
|
||||||
).filter((tank) => tank.tankDefinitions?.tier === tier);
|
).filter((tank) => tank.tankDefinitions?.tier === tier);
|
||||||
const clanAccountInfo = await getClanAccountInfo(server, id, ['clan']);
|
const clanAccountInfo = await getClanAccountInfo(server, id, ['clan']);
|
||||||
const groupedTanks: Record<string, BlitzkriegTankDefinition[]> = {};
|
const groupedTanks: Record<string, TankDefinition[]> = {};
|
||||||
const nations: string[] = [];
|
const nations: string[] = [];
|
||||||
|
|
||||||
filteredTanks.forEach((tank) => {
|
filteredTanks.forEach((tank) => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { SlashCommandBuilder } from 'discord.js';
|
import { SlashCommandBuilder } from 'discord.js';
|
||||||
import { go } from 'fuzzysort';
|
import { go } from 'fuzzysort';
|
||||||
import markdownEscape from 'markdown-escape';
|
import markdownEscape from 'markdown-escape';
|
||||||
import { tankNamesDiacritics } from '../core/blitzkrieg/definitions/tanks';
|
import { tankNamesDiacritics } from '../core/blitzkrieg/tankDefinitions';
|
||||||
import addTankChoices from '../core/discord/addTankChoices';
|
import addTankChoices from '../core/discord/addTankChoices';
|
||||||
import embedInfo from '../core/discord/embedInfo';
|
import embedInfo from '../core/discord/embedInfo';
|
||||||
import { CommandRegistry } from '../events/interactionCreate';
|
import { CommandRegistry } from '../events/interactionCreate';
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { Button, Text } from '@radix-ui/themes';
|
||||||
|
import { ComponentProps } from 'react';
|
||||||
|
import { asset } from '../core/blitzkrieg/asset';
|
||||||
|
import { TIER_ROMAN_NUMERALS, Tier } from '../core/blitzkrieg/tankDefinitions';
|
||||||
|
|
||||||
|
interface ModuleButtonProps
|
||||||
|
extends Omit<ComponentProps<typeof Button>, 'type'> {
|
||||||
|
type: string;
|
||||||
|
tier: Tier;
|
||||||
|
selected?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ModuleButtons({
|
||||||
|
type,
|
||||||
|
tier,
|
||||||
|
selected,
|
||||||
|
style,
|
||||||
|
...props
|
||||||
|
}: ModuleButtonProps) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
radius="medium"
|
||||||
|
color={selected ? undefined : 'gray'}
|
||||||
|
variant={selected ? 'solid' : 'soft'}
|
||||||
|
style={{
|
||||||
|
padding: 0,
|
||||||
|
width: 48,
|
||||||
|
height: 40,
|
||||||
|
position: 'relative',
|
||||||
|
...style,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={asset(`icons/modules/${type}.webp`)}
|
||||||
|
style={{
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(calc(-50% + 2px), calc(-50% + 2px))',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
size="1"
|
||||||
|
weight="bold"
|
||||||
|
style={{
|
||||||
|
zIndex: 1,
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
right: 8,
|
||||||
|
textAlign: 'right',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{TIER_ROMAN_NUMERALS[tier]}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
TANK_ICONS,
|
TANK_ICONS,
|
||||||
TANK_ICONS_COLLECTOR,
|
TANK_ICONS_COLLECTOR,
|
||||||
TANK_ICONS_PREMIUM,
|
TANK_ICONS_PREMIUM,
|
||||||
} from '../../../core/blitzkrieg/definitions/tanks';
|
} from '../../../core/blitzkrieg/tankDefinitions';
|
||||||
import { theme } from '../../../stitches.config';
|
import { theme } from '../../../stitches.config';
|
||||||
|
|
||||||
export enum TreeTypeEnum {
|
export enum TreeTypeEnum {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Tier } from '../core/blitzkrieg/definitions/tanks';
|
import { Tier } from '../core/blitzkrieg/tankDefinitions';
|
||||||
import { theme } from '../stitches.config';
|
import { theme } from '../stitches.config';
|
||||||
|
|
||||||
export type TierWeightsRecord = Partial<Record<Tier, number>>;
|
export type TierWeightsRecord = Partial<Record<Tier, number>>;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { TreeTypeEnum } from '../../components/Tanks';
|
import { TreeTypeEnum } from '../../components/Tanks';
|
||||||
import { tankDefinitions } from '../blitzkrieg/definitions/tanks';
|
import { tankDefinitions } from '../blitzkrieg/tankDefinitions';
|
||||||
|
|
||||||
export default async function getTreeType(id: number) {
|
export default async function getTreeType(id: number) {
|
||||||
const entry = (await tankDefinitions)[id];
|
const entry = (await tankDefinitions)[id];
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { go } from 'fuzzysort';
|
|||||||
import {
|
import {
|
||||||
tankDefinitions,
|
tankDefinitions,
|
||||||
tanksDefinitionsArray,
|
tanksDefinitionsArray,
|
||||||
} from '../blitzkrieg/definitions/tanks';
|
} from '../blitzkrieg/tankDefinitions';
|
||||||
import { UserError } from '../blitzkrieg/userError';
|
import { UserError } from '../blitzkrieg/userError';
|
||||||
|
|
||||||
export default async function resolveTankId(tank: string | number) {
|
export default async function resolveTankId(tank: string | number) {
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import { asset } from '../asset';
|
|
||||||
import { Tier } from './tanks';
|
|
||||||
|
|
||||||
export interface BlitzkriegGunDefinition {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
tier: Tier;
|
|
||||||
pitch: [number, number];
|
|
||||||
shells: number[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BlitzkriegGunDefinitions = Record<number, BlitzkriegGunDefinition>;
|
|
||||||
|
|
||||||
export const gunDefinitions = fetch(asset('definitions/guns.json'), {
|
|
||||||
cache: 'no-cache',
|
|
||||||
}).then(
|
|
||||||
async (response) => response.json() as Promise<BlitzkriegGunDefinitions>,
|
|
||||||
);
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import { asset } from '../asset';
|
|
||||||
|
|
||||||
export type ShellType = 'ap' | 'ap_cr' | 'hc' | 'he';
|
|
||||||
|
|
||||||
export interface BlitzkriegShellDefinition {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
speed: number;
|
|
||||||
damage: { armor: number; devices: number };
|
|
||||||
caliber: number;
|
|
||||||
normalization: number;
|
|
||||||
ricochet: number;
|
|
||||||
type: ShellType;
|
|
||||||
icon: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BlitzkriegShellDefinitions = Record<
|
|
||||||
number,
|
|
||||||
BlitzkriegShellDefinition
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const shellDefinitions = fetch(asset('definitions/shells.json'), {
|
|
||||||
cache: 'no-cache',
|
|
||||||
}).then(
|
|
||||||
async (response) => response.json() as Promise<BlitzkriegShellDefinitions>,
|
|
||||||
);
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { asset } from '../asset';
|
|
||||||
import { Tier } from './tanks';
|
|
||||||
|
|
||||||
export interface BlitzkriegTurretDefinition {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
tier: Tier;
|
|
||||||
yaw: [number, number];
|
|
||||||
guns: number[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BlitzkriegTurretDefinitions = Record<
|
|
||||||
number,
|
|
||||||
BlitzkriegTurretDefinition
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const turretDefinitions = fetch(asset('definitions/turrets.json'), {
|
|
||||||
cache: 'no-cache',
|
|
||||||
}).then(
|
|
||||||
async (response) => response.json() as Promise<BlitzkriegTurretDefinitions>,
|
|
||||||
);
|
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
import { TREE_TYPE_NAMES } from '../../components/Tanks';
|
import { TREE_TYPE_NAMES } from '../../components/Tanks';
|
||||||
import { encyclopediaInfo } from '../blitz/encyclopediaInfo';
|
import { encyclopediaInfo } from '../blitz/encyclopediaInfo';
|
||||||
import { StatFilters } from '../statistics/filterStats';
|
import { StatFilters } from '../statistics/filterStats';
|
||||||
import {
|
import { TIER_ROMAN_NUMERALS, Tier, tankDefinitions } from './tankDefinitions';
|
||||||
TIER_ROMAN_NUMERALS,
|
|
||||||
Tier,
|
|
||||||
tankDefinitions,
|
|
||||||
} from './definitions/tanks';
|
|
||||||
|
|
||||||
export async function filtersToDescription({
|
export async function filtersToDescription({
|
||||||
nation,
|
nation,
|
||||||
|
|||||||
@@ -1,8 +1,51 @@
|
|||||||
import { deburr } from 'lodash';
|
import { deburr } from 'lodash';
|
||||||
import { TankType, TreeTypeString } from '../../../components/Tanks';
|
import { TankType, TreeTypeString } from '../../components/Tanks';
|
||||||
import { asset } from '../asset';
|
import { asset } from './asset';
|
||||||
|
|
||||||
export interface BlitzkriegTankDefinition {
|
export type ShellType = 'ap' | 'ap_cr' | 'hc' | 'he';
|
||||||
|
export interface ShellDefinition {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
speed: number;
|
||||||
|
damage: { armor: number; devices: number };
|
||||||
|
caliber: number;
|
||||||
|
normalization: number;
|
||||||
|
ricochet: number;
|
||||||
|
type: ShellType;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
export type GunDefinition = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
tier: Tier;
|
||||||
|
pitch: [number, number];
|
||||||
|
shells: ShellDefinition[];
|
||||||
|
} & (
|
||||||
|
| {
|
||||||
|
type: 'regular';
|
||||||
|
reload: number;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'auto_loader';
|
||||||
|
reload: number;
|
||||||
|
interClip: number;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'auto_reloader';
|
||||||
|
reload: number[];
|
||||||
|
interClip: number;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export interface TurretDefinition {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
tier: Tier;
|
||||||
|
yaw: [number, number];
|
||||||
|
guns: GunDefinition[];
|
||||||
|
}
|
||||||
|
export interface TankDefinition {
|
||||||
id: number;
|
id: number;
|
||||||
nation: string;
|
nation: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -10,23 +53,18 @@ export interface BlitzkriegTankDefinition {
|
|||||||
tier: Tier;
|
tier: Tier;
|
||||||
type: TankType;
|
type: TankType;
|
||||||
testing?: boolean;
|
testing?: boolean;
|
||||||
turrets: number[];
|
turrets: TurretDefinition[];
|
||||||
}
|
}
|
||||||
export type BlitzkriegTankDefinitions = Record<
|
export type TankDefinitions = Record<number, TankDefinition>;
|
||||||
number,
|
|
||||||
BlitzkriegTankDefinition
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const tankDefinitions = fetch(asset('definitions/tanks.json'), {
|
export const tankDefinitions = fetch(asset('definitions/tanks.json'), {
|
||||||
cache: 'no-cache',
|
cache: 'no-cache',
|
||||||
}).then(
|
}).then(async (response) => response.json() as Promise<TankDefinitions>);
|
||||||
async (response) => response.json() as Promise<BlitzkriegTankDefinitions>,
|
|
||||||
);
|
|
||||||
|
|
||||||
const entries = new Promise<BlitzkriegTankDefinition[]>(async (resolve) => {
|
const entries = new Promise<TankDefinition[]>(async (resolve) => {
|
||||||
resolve(Object.entries(await tankDefinitions).map(([, entry]) => entry));
|
resolve(Object.entries(await tankDefinitions).map(([, entry]) => entry));
|
||||||
});
|
});
|
||||||
export const tanksDefinitionsArray = new Promise<BlitzkriegTankDefinition[]>(
|
export const tanksDefinitionsArray = new Promise<TankDefinition[]>(
|
||||||
async (resolve) => {
|
async (resolve) => {
|
||||||
resolve((await entries).map((entry) => entry));
|
resolve((await entries).map((entry) => entry));
|
||||||
},
|
},
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { asset } from './asset';
|
import { asset } from './asset';
|
||||||
|
|
||||||
export function tankIcon(id: number, size: 'big' | 'small' = 'big') {
|
export function tankIcon(id: number, size: 'big' | 'small' = 'big') {
|
||||||
return asset(`icons/${size}/${id}.webp`);
|
return asset(`icons/tanks/${size}/${id}.webp`);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AllStats } from '../blitz/getAccountInfo';
|
import { AllStats } from '../blitz/getAccountInfo';
|
||||||
import { context } from '../blitzkrieg/context';
|
import { context } from '../blitzkrieg/context';
|
||||||
import { tankDefinitions } from '../blitzkrieg/definitions/tanks';
|
import { tankDefinitions } from '../blitzkrieg/tankDefinitions';
|
||||||
|
|
||||||
export interface SpecialStats {
|
export interface SpecialStats {
|
||||||
winrate: number;
|
winrate: number;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
CacheType,
|
CacheType,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import { go } from 'fuzzysort';
|
import { go } from 'fuzzysort';
|
||||||
import { tankNamesDiacritics } from '../blitzkrieg/definitions/tanks';
|
import { tankNamesDiacritics } from '../blitzkrieg/tankDefinitions';
|
||||||
import {
|
import {
|
||||||
DISCORD_CHOICES_MAX_NAME_SIZE,
|
DISCORD_CHOICES_MAX_NAME_SIZE,
|
||||||
OVERFLOW_SUFFIX,
|
OVERFLOW_SUFFIX,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { TreeTypeString } from '../../components/Tanks';
|
import { TreeTypeString } from '../../components/Tanks';
|
||||||
import { tankDefinitions } from '../blitzkrieg/definitions/tanks';
|
import { tankDefinitions } from '../blitzkrieg/tankDefinitions';
|
||||||
import { DiffedTankStats } from '../blitzstars/getStatsInPeriod';
|
import { DiffedTankStats } from '../blitzstars/getStatsInPeriod';
|
||||||
import { tankAverages } from '../blitzstars/tankAverages';
|
import { tankAverages } from '../blitzstars/tankAverages';
|
||||||
import calculateWN8 from './calculateWN8';
|
import calculateWN8 from './calculateWN8';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TierWeightsRecord } from '../../components/TierWeights';
|
import { TierWeightsRecord } from '../../components/TierWeights';
|
||||||
import { AllStats } from '../blitz/getAccountInfo';
|
import { AllStats } from '../blitz/getAccountInfo';
|
||||||
import { tankDefinitions } from '../blitzkrieg/definitions/tanks';
|
import { tankDefinitions } from '../blitzkrieg/tankDefinitions';
|
||||||
|
|
||||||
export async function getTierWeights(
|
export async function getTierWeights(
|
||||||
stats: Record<number, AllStats>,
|
stats: Record<number, AllStats>,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { produce } from 'immer';
|
import { produce } from 'immer';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { TankType, TreeTypeString } from '../components/Tanks';
|
import { TankType, TreeTypeString } from '../components/Tanks';
|
||||||
import { Tier } from '../core/blitzkrieg/definitions/tanks';
|
import { Tier } from '../core/blitzkrieg/tankDefinitions';
|
||||||
|
|
||||||
export type TankopediaSortBy = 'tier' | 'name';
|
export type TankopediaSortBy = 'tier' | 'name';
|
||||||
export type TankopediaSortDirection = 'ascending' | 'descending';
|
export type TankopediaSortDirection = 'ascending' | 'descending';
|
||||||
|
|||||||
Reference in new issue
Block a user