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",
|
||||
"alphatest",
|
||||
"apcr",
|
||||
"atgm",
|
||||
"bepaint",
|
||||
"BINORMAL",
|
||||
"blitzstars",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin';
|
||||
|
||||
const withVanillaExtract = createVanillaExtractPlugin();
|
||||
const withVanillaExtract = createVanillaExtractPlugin({ tests: /\.css$/ });
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"dotenv": "^16.3.1",
|
||||
"esbuild": "^0.19.3",
|
||||
"express": "^4.18.2",
|
||||
"false": "^0.0.4",
|
||||
"fuzzysort": "^2.0.4",
|
||||
"immer": "^10.0.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
@@ -55,6 +56,7 @@
|
||||
"react-dom": "^18.2.0",
|
||||
"react-fuzzysort": "^1.0.1",
|
||||
"satori": "^0.10.8",
|
||||
"sharp": "^0.33.0",
|
||||
"three": "^0.159.0",
|
||||
"vite-node": "^0.34.5",
|
||||
"vitepress": "^1.0.0-rc.20",
|
||||
|
||||
+57
-2
@@ -2,10 +2,13 @@ import { config } from 'dotenv';
|
||||
import { existsSync } from 'fs';
|
||||
import { mkdir, readdir, rm } from 'fs/promises';
|
||||
import { argv } from 'process';
|
||||
import sharp from 'sharp';
|
||||
import { TankType } from '../src/components/Tanks';
|
||||
import { NATION_IDS } from '../src/constants/nations';
|
||||
import { SCPGStream } from '../src/core/blitz/SCPGStream';
|
||||
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 { readYAMLDVPL } from '../src/core/blitz/readYAMLDVPL';
|
||||
import { toUniqueId } from '../src/core/blitz/toUniqueId';
|
||||
@@ -122,9 +125,9 @@ const blitzTankTypeToBlitzkrieg: Record<BlitzTankType, TankType> = {
|
||||
};
|
||||
const blitzShellKindToBLitzkrieg: Record<ShellKind, ShellType> = {
|
||||
ARMOR_PIERCING: 'ap',
|
||||
ARMOR_PIERCING_CR: 'apcr',
|
||||
ARMOR_PIERCING_CR: 'ap_cr',
|
||||
HIGH_EXPLOSIVE: 'he',
|
||||
HOLLOW_CHARGE: 'heat',
|
||||
HOLLOW_CHARGE: 'hc',
|
||||
};
|
||||
const DATA =
|
||||
'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data';
|
||||
@@ -137,6 +140,7 @@ const DOI = {
|
||||
bigIcons: 'Gfx/UI/BigTankIcons',
|
||||
flags: 'Gfx/Lobby/flags',
|
||||
'3d': '3d',
|
||||
bigShellIcons: 'Gfx/Shared/tank-supply/ammunition/big',
|
||||
};
|
||||
|
||||
const allTargets = argv.includes('--all-targets');
|
||||
@@ -217,6 +221,7 @@ if (allTargets || targets?.includes('definitions')) {
|
||||
normalization: shell.normalizationAngle,
|
||||
ricochet: shell.ricochetAngle,
|
||||
type: blitzShellKindToBLitzkrieg[shell.kind],
|
||||
icon: shell.icon,
|
||||
};
|
||||
|
||||
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';
|
||||
|
||||
import { ArrowLeftIcon } from '@radix-ui/react-icons';
|
||||
import { ArrowLeftIcon, CaretRightIcon } from '@radix-ui/react-icons';
|
||||
import {
|
||||
AspectRatio,
|
||||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
Dialog,
|
||||
Flex,
|
||||
Heading,
|
||||
Inset,
|
||||
Select,
|
||||
Slider,
|
||||
Tabs,
|
||||
Text,
|
||||
Theme,
|
||||
Tooltip,
|
||||
@@ -21,19 +20,23 @@ import Link from 'next/link';
|
||||
import { use, useEffect, useState } from 'react';
|
||||
import { Flag } from '../../../../components/Flag';
|
||||
import PageWrapper from '../../../../components/PageWrapper';
|
||||
import { asset } from '../../../../core/blitzkrieg/asset';
|
||||
import { gunDefinitions } from '../../../../core/blitzkrieg/definitions/guns';
|
||||
import { shellDefinitions } from '../../../../core/blitzkrieg/definitions/shells';
|
||||
import {
|
||||
TIER_ROMAN_NUMERALS,
|
||||
tankDefinitions,
|
||||
tanksDefinitionsArray,
|
||||
} from '../../../../core/blitzkrieg/definitions/tanks';
|
||||
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 } }) {
|
||||
const id = parseInt(params.id);
|
||||
const awaitedTankDefinitions = use(tankDefinitions);
|
||||
const awaitedTanksDefinitionsArray = use(tanksDefinitionsArray);
|
||||
const awaitedTurretDefinitions = use(turretDefinitions);
|
||||
const awaitedGunDefinitions = use(gunDefinitions);
|
||||
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 [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]);
|
||||
|
||||
@@ -62,16 +71,24 @@ export default function Page({ params }: { params: { id: string } }) {
|
||||
</Link>
|
||||
|
||||
<Flex gap="2" align="center">
|
||||
<Heading>{tank.name}</Heading>
|
||||
<Flag nation={tank.nation} />
|
||||
<Heading>{tank.name}</Heading>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<AspectRatio ratio={16 / 9}>
|
||||
<Card
|
||||
style={{ width: '100%', height: '100%', position: 'relative' }}
|
||||
>
|
||||
<Inset style={{ height: 'calc(100% + 24px)' }}>
|
||||
<Card style={{ position: 'relative' }}>
|
||||
<Flex direction="column" gap="2">
|
||||
<Tabs.Root
|
||||
value={mode}
|
||||
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()}>
|
||||
<OrbitControls />
|
||||
|
||||
@@ -80,58 +97,61 @@ export default function Page({ params }: { params: { id: string } }) {
|
||||
|
||||
<mesh>
|
||||
<torusKnotGeometry args={[undefined, undefined, 128, 16]} />
|
||||
<meshStandardMaterial color="red" />
|
||||
<meshStandardMaterial color="cyan" />
|
||||
</mesh>
|
||||
</Canvas>
|
||||
</Inset>
|
||||
</div>
|
||||
|
||||
<Flex
|
||||
gap="2"
|
||||
align="center"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
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>
|
||||
{mode === 'armor' && (
|
||||
<Flex gap="2" align="center" className={styles.enhancedArmor}>
|
||||
<Checkbox defaultChecked />
|
||||
<Text>Enhanced armor</Text>
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
</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 gap="6" direction="column">
|
||||
|
||||
@@ -40,3 +40,18 @@ export const listingImage = style({
|
||||
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';
|
||||
|
||||
export type ShellType = 'ap' | 'apcr' | 'he' | 'heat';
|
||||
export type ShellType = 'ap' | 'ap_cr' | 'hc' | 'he';
|
||||
|
||||
export interface BlitzkriegShellDefinition {
|
||||
id: number;
|
||||
@@ -11,6 +11,7 @@ export interface BlitzkriegShellDefinition {
|
||||
normalization: number;
|
||||
ricochet: number;
|
||||
type: ShellType;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
export type BlitzkriegShellDefinitions = Record<
|
||||
|
||||
Reference in new issue
Block a user