mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: shell icons and modes
This commit is contained in:
1 parent
f8f88ff8f2
commit
634bd2ea07
8 files changed
+1110
-639
No files matched your search
Vendored
+1
@@ -5,6 +5,7 @@
|
|||||||
"accountinfo",
|
"accountinfo",
|
||||||
"alphatest",
|
"alphatest",
|
||||||
"apcr",
|
"apcr",
|
||||||
|
"atgm",
|
||||||
"bepaint",
|
"bepaint",
|
||||||
"BINORMAL",
|
"BINORMAL",
|
||||||
"blitzstars",
|
"blitzstars",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin';
|
import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin';
|
||||||
|
|
||||||
const withVanillaExtract = createVanillaExtractPlugin();
|
const withVanillaExtract = createVanillaExtractPlugin({ tests: /\.css$/ });
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"esbuild": "^0.19.3",
|
"esbuild": "^0.19.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"false": "^0.0.4",
|
||||||
"fuzzysort": "^2.0.4",
|
"fuzzysort": "^2.0.4",
|
||||||
"immer": "^10.0.2",
|
"immer": "^10.0.2",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
@@ -55,6 +56,7 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-fuzzysort": "^1.0.1",
|
"react-fuzzysort": "^1.0.1",
|
||||||
"satori": "^0.10.8",
|
"satori": "^0.10.8",
|
||||||
|
"sharp": "^0.33.0",
|
||||||
"three": "^0.159.0",
|
"three": "^0.159.0",
|
||||||
"vite-node": "^0.34.5",
|
"vite-node": "^0.34.5",
|
||||||
"vitepress": "^1.0.0-rc.20",
|
"vitepress": "^1.0.0-rc.20",
|
||||||
|
|||||||
+57
-2
@@ -2,10 +2,13 @@ import { config } from 'dotenv';
|
|||||||
import { existsSync } from 'fs';
|
import { existsSync } 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 { TankType } from '../src/components/Tanks';
|
import { TankType } from '../src/components/Tanks';
|
||||||
import { NATION_IDS } from '../src/constants/nations';
|
import { NATION_IDS } from '../src/constants/nations';
|
||||||
import { SCPGStream } from '../src/core/blitz/SCPGStream';
|
import { SCPGStream } from '../src/core/blitz/SCPGStream';
|
||||||
import { readBase64DVPL } from '../src/core/blitz/readBase64DVPL';
|
import { readBase64DVPL } from '../src/core/blitz/readBase64DVPL';
|
||||||
|
import { readDVPLFile } from '../src/core/blitz/readDVPLFile';
|
||||||
|
import { readStringDVPL } from '../src/core/blitz/readStringDVPL';
|
||||||
import { readXMLDVPL } from '../src/core/blitz/readXMLDVPL';
|
import { readXMLDVPL } from '../src/core/blitz/readXMLDVPL';
|
||||||
import { readYAMLDVPL } from '../src/core/blitz/readYAMLDVPL';
|
import { readYAMLDVPL } from '../src/core/blitz/readYAMLDVPL';
|
||||||
import { toUniqueId } from '../src/core/blitz/toUniqueId';
|
import { toUniqueId } from '../src/core/blitz/toUniqueId';
|
||||||
@@ -122,9 +125,9 @@ const blitzTankTypeToBlitzkrieg: Record<BlitzTankType, TankType> = {
|
|||||||
};
|
};
|
||||||
const blitzShellKindToBLitzkrieg: Record<ShellKind, ShellType> = {
|
const blitzShellKindToBLitzkrieg: Record<ShellKind, ShellType> = {
|
||||||
ARMOR_PIERCING: 'ap',
|
ARMOR_PIERCING: 'ap',
|
||||||
ARMOR_PIERCING_CR: 'apcr',
|
ARMOR_PIERCING_CR: 'ap_cr',
|
||||||
HIGH_EXPLOSIVE: 'he',
|
HIGH_EXPLOSIVE: 'he',
|
||||||
HOLLOW_CHARGE: 'heat',
|
HOLLOW_CHARGE: 'hc',
|
||||||
};
|
};
|
||||||
const DATA =
|
const DATA =
|
||||||
'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data';
|
'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data';
|
||||||
@@ -137,6 +140,7 @@ const DOI = {
|
|||||||
bigIcons: 'Gfx/UI/BigTankIcons',
|
bigIcons: 'Gfx/UI/BigTankIcons',
|
||||||
flags: 'Gfx/Lobby/flags',
|
flags: 'Gfx/Lobby/flags',
|
||||||
'3d': '3d',
|
'3d': '3d',
|
||||||
|
bigShellIcons: 'Gfx/Shared/tank-supply/ammunition/big',
|
||||||
};
|
};
|
||||||
|
|
||||||
const allTargets = argv.includes('--all-targets');
|
const allTargets = argv.includes('--all-targets');
|
||||||
@@ -217,6 +221,7 @@ if (allTargets || targets?.includes('definitions')) {
|
|||||||
normalization: shell.normalizationAngle,
|
normalization: shell.normalizationAngle,
|
||||||
ricochet: shell.ricochetAngle,
|
ricochet: shell.ricochetAngle,
|
||||||
type: blitzShellKindToBLitzkrieg[shell.kind],
|
type: blitzShellKindToBLitzkrieg[shell.kind],
|
||||||
|
icon: shell.icon,
|
||||||
};
|
};
|
||||||
|
|
||||||
return shellId;
|
return shellId;
|
||||||
@@ -487,3 +492,53 @@ if (allTargets || targets?.includes('tankModels')) {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allTargets || targets?.includes('shellIcons')) {
|
||||||
|
console.log('Building shell icons...');
|
||||||
|
|
||||||
|
const image = sharp(
|
||||||
|
await readDVPLFile(
|
||||||
|
`${DATA}/${DOI.bigShellIcons}/texture0.packed.webp.dvpl`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const changes = await Promise.all(
|
||||||
|
(await readdir(`${DATA}/${DOI.bigShellIcons}`))
|
||||||
|
.filter((file) => file.endsWith('_l.txt.dvpl'))
|
||||||
|
.map(async (file) => {
|
||||||
|
const name = file.match(/(.+)_l\.txt\.dvpl/)![1];
|
||||||
|
const sizes = (
|
||||||
|
await readStringDVPL(`${DATA}/${DOI.bigShellIcons}/${file}`)
|
||||||
|
)
|
||||||
|
.split('\n')[4]
|
||||||
|
.split(' ')
|
||||||
|
.map(Number);
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: (
|
||||||
|
await image
|
||||||
|
.clone()
|
||||||
|
.extract({
|
||||||
|
left: sizes[0],
|
||||||
|
top: sizes[1],
|
||||||
|
width: sizes[2],
|
||||||
|
height: sizes[3],
|
||||||
|
})
|
||||||
|
.toBuffer()
|
||||||
|
).toString('base64'),
|
||||||
|
encoding: 'base64',
|
||||||
|
path: `shells/${name}.webp`,
|
||||||
|
} satisfies FileChange;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Committing shell icons...');
|
||||||
|
commitMultipleFiles(
|
||||||
|
'tresabhi',
|
||||||
|
'blitzkrieg-assets',
|
||||||
|
'main',
|
||||||
|
'shell icons',
|
||||||
|
changes,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { ArrowLeftIcon } from '@radix-ui/react-icons';
|
import { ArrowLeftIcon, CaretRightIcon } from '@radix-ui/react-icons';
|
||||||
import {
|
import {
|
||||||
AspectRatio,
|
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
|
Dialog,
|
||||||
Flex,
|
Flex,
|
||||||
Heading,
|
Heading,
|
||||||
Inset,
|
|
||||||
Select,
|
|
||||||
Slider,
|
Slider,
|
||||||
|
Tabs,
|
||||||
Text,
|
Text,
|
||||||
Theme,
|
Theme,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
@@ -21,19 +20,23 @@ import Link from 'next/link';
|
|||||||
import { use, useEffect, useState } from 'react';
|
import { use, useEffect, useState } from 'react';
|
||||||
import { Flag } from '../../../../components/Flag';
|
import { Flag } from '../../../../components/Flag';
|
||||||
import PageWrapper from '../../../../components/PageWrapper';
|
import PageWrapper from '../../../../components/PageWrapper';
|
||||||
|
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 {
|
import {
|
||||||
TIER_ROMAN_NUMERALS,
|
TIER_ROMAN_NUMERALS,
|
||||||
tankDefinitions,
|
tankDefinitions,
|
||||||
|
tanksDefinitionsArray,
|
||||||
} from '../../../../core/blitzkrieg/definitions/tanks';
|
} from '../../../../core/blitzkrieg/definitions/tanks';
|
||||||
import { turretDefinitions } from '../../../../core/blitzkrieg/definitions/turrets';
|
import { turretDefinitions } from '../../../../core/blitzkrieg/definitions/turrets';
|
||||||
|
import * as styles from '../page.css';
|
||||||
|
|
||||||
const SIZE = 0.05;
|
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);
|
||||||
@@ -43,6 +46,12 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
);
|
);
|
||||||
const [gun, setGun] = useState(awaitedGunDefinitions[turret.guns[0]]);
|
const [gun, setGun] = useState(awaitedGunDefinitions[turret.guns[0]]);
|
||||||
const [crew, setCrew] = useState(100);
|
const [crew, setCrew] = useState(100);
|
||||||
|
const [versusTank, setVersusTank] = useState(
|
||||||
|
awaitedTanksDefinitionsArray[0].id,
|
||||||
|
);
|
||||||
|
const [mode, setMode] = useState<Mode>('model');
|
||||||
|
|
||||||
|
console.log(versusTank);
|
||||||
|
|
||||||
useEffect(() => setGun(awaitedGunDefinitions[turret.guns[0]]), [turret]);
|
useEffect(() => setGun(awaitedGunDefinitions[turret.guns[0]]), [turret]);
|
||||||
|
|
||||||
@@ -62,16 +71,24 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Flex gap="2" align="center">
|
<Flex gap="2" align="center">
|
||||||
<Heading>{tank.name}</Heading>
|
|
||||||
<Flag nation={tank.nation} />
|
<Flag nation={tank.nation} />
|
||||||
|
<Heading>{tank.name}</Heading>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<AspectRatio ratio={16 / 9}>
|
<Card style={{ position: 'relative' }}>
|
||||||
<Card
|
<Flex direction="column" gap="2">
|
||||||
style={{ width: '100%', height: '100%', position: 'relative' }}
|
<Tabs.Root
|
||||||
>
|
value={mode}
|
||||||
<Inset style={{ height: 'calc(100% + 24px)' }}>
|
onValueChange={(value) => setMode(value as Mode)}
|
||||||
|
>
|
||||||
|
<Tabs.List>
|
||||||
|
<Tabs.Trigger value="model">Model</Tabs.Trigger>
|
||||||
|
<Tabs.Trigger value="armor">Armor</Tabs.Trigger>
|
||||||
|
</Tabs.List>
|
||||||
|
</Tabs.Root>
|
||||||
|
|
||||||
|
<div style={{ height: '50vh', maxHeight: 576 }}>
|
||||||
<Canvas onPointerDown={(event) => event.preventDefault()}>
|
<Canvas onPointerDown={(event) => event.preventDefault()}>
|
||||||
<OrbitControls />
|
<OrbitControls />
|
||||||
|
|
||||||
@@ -80,58 +97,61 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
|
|
||||||
<mesh>
|
<mesh>
|
||||||
<torusKnotGeometry args={[undefined, undefined, 128, 16]} />
|
<torusKnotGeometry args={[undefined, undefined, 128, 16]} />
|
||||||
<meshStandardMaterial color="red" />
|
<meshStandardMaterial color="cyan" />
|
||||||
</mesh>
|
</mesh>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</Inset>
|
</div>
|
||||||
|
|
||||||
<Flex
|
{mode === 'armor' && (
|
||||||
gap="2"
|
<Flex gap="2" align="center" className={styles.enhancedArmor}>
|
||||||
align="center"
|
<Checkbox defaultChecked />
|
||||||
style={{
|
<Text>Enhanced armor</Text>
|
||||||
position: 'absolute',
|
</Flex>
|
||||||
left: 16,
|
)}
|
||||||
bottom: 16,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Checkbox defaultChecked />
|
|
||||||
<Text>Enhanced armor</Text>
|
|
||||||
</Flex>
|
|
||||||
</Card>
|
|
||||||
</AspectRatio>
|
|
||||||
|
|
||||||
<Card style={{}}>
|
|
||||||
<Flex align="center" justify="between" gap="2">
|
|
||||||
<Flex align="center" gap="4">
|
|
||||||
<Text>Versus</Text>
|
|
||||||
|
|
||||||
<Select.Root value="1">
|
|
||||||
<Select.Trigger variant="ghost" />
|
|
||||||
|
|
||||||
<Select.Content>
|
|
||||||
<Select.Item value="1">XM66F</Select.Item>
|
|
||||||
</Select.Content>
|
|
||||||
</Select.Root>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<Flex gap="2" align="center">
|
|
||||||
<Checkbox defaultChecked />
|
|
||||||
<Text>Calibrated shells</Text>
|
|
||||||
</Flex>
|
|
||||||
|
|
||||||
<Flex gap="1">
|
|
||||||
<Button variant="solid" radius="small">
|
|
||||||
<img src="/images/ammo/ap.png" width={24} height={24} />
|
|
||||||
</Button>
|
|
||||||
<Button variant="soft" radius="small" color="gray">
|
|
||||||
<img src="/images/ammo/hcp.png" width={24} height={24} />
|
|
||||||
</Button>
|
|
||||||
<Button variant="soft" radius="small" color="gray">
|
|
||||||
<img src="/images/ammo/he.png" width={24} height={24} />
|
|
||||||
</Button>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{mode === 'armor' && (
|
||||||
|
<Card>
|
||||||
|
<Flex align="center" justify="between" gap="2">
|
||||||
|
<Flex align="center" gap="4">
|
||||||
|
<Text>Versus</Text>
|
||||||
|
|
||||||
|
<Dialog.Root>
|
||||||
|
<Dialog.Trigger>
|
||||||
|
<Button variant="ghost">
|
||||||
|
{awaitedTankDefinitions[versusTank].name}
|
||||||
|
<CaretRightIcon />
|
||||||
|
</Button>
|
||||||
|
</Dialog.Trigger>
|
||||||
|
|
||||||
|
<Dialog.Content>Do something lol</Dialog.Content>
|
||||||
|
</Dialog.Root>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex gap="2" align="center">
|
||||||
|
<Checkbox defaultChecked />
|
||||||
|
<Text>Calibrated shells</Text>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex gap="1">
|
||||||
|
<Button variant="solid" radius="small">
|
||||||
|
<img src={asset('shells/ap.webp')} width={24} height={24} />
|
||||||
|
</Button>
|
||||||
|
<Button variant="soft" radius="small" color="gray">
|
||||||
|
<img
|
||||||
|
src={asset('shells/hc_premium.webp')}
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
<Button variant="soft" radius="small" color="gray">
|
||||||
|
<img src={asset('shells/he.webp')} width={24} height={24} />
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex gap="6" direction="column">
|
<Flex gap="6" direction="column">
|
||||||
|
|||||||
@@ -40,3 +40,18 @@ export const listingImage = style({
|
|||||||
transform: 'translate(-25%, 10%)',
|
transform: 'translate(-25%, 10%)',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const enhancedArmor = style({
|
||||||
|
'@media': {
|
||||||
|
'screen and (min-width: 400px)': {
|
||||||
|
position: 'absolute',
|
||||||
|
right: 16,
|
||||||
|
top: 16,
|
||||||
|
},
|
||||||
|
|
||||||
|
'screen and (max-width: 399px)': {
|
||||||
|
// left: 16,
|
||||||
|
// bottom: 16,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { asset } from '../asset';
|
import { asset } from '../asset';
|
||||||
|
|
||||||
export type ShellType = 'ap' | 'apcr' | 'he' | 'heat';
|
export type ShellType = 'ap' | 'ap_cr' | 'hc' | 'he';
|
||||||
|
|
||||||
export interface BlitzkriegShellDefinition {
|
export interface BlitzkriegShellDefinition {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -11,6 +11,7 @@ export interface BlitzkriegShellDefinition {
|
|||||||
normalization: number;
|
normalization: number;
|
||||||
ricochet: number;
|
ricochet: number;
|
||||||
type: ShellType;
|
type: ShellType;
|
||||||
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BlitzkriegShellDefinitions = Record<
|
export type BlitzkriegShellDefinitions = Record<
|
||||||
|
|||||||
Reference in new issue
Block a user