mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-22 03:07:04 +02:00
feat: fire chance
This commit is contained in:
1 parent
eea2024549
commit
c34edbd3ac
8 files changed
+94
-32
No files matched your search
@@ -55,6 +55,17 @@ type ShellDefinitionsList = Record<
|
||||
> & {
|
||||
icons: Record<string, string>;
|
||||
};
|
||||
interface EngineDefinitionsList {
|
||||
nextAvailableId: number;
|
||||
ids: Record<string, number>;
|
||||
shared: {
|
||||
[key: string]: {
|
||||
userString: string;
|
||||
level: number;
|
||||
fireStartingChance: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
type VehicleDefinitionArmor = Record<
|
||||
string,
|
||||
number | { vehicleDamageFactor: 0; '#text': number }
|
||||
@@ -91,6 +102,9 @@ interface VehicleDefinitions {
|
||||
};
|
||||
};
|
||||
};
|
||||
engines: {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
turrets0: {
|
||||
[key: string]: {
|
||||
maxHealth: number;
|
||||
@@ -260,7 +274,7 @@ export async function definitions(production: boolean) {
|
||||
(nations) => nations.filter((nation) => nation !== 'common'),
|
||||
);
|
||||
const tankStringIdMap: Record<string, number> = {};
|
||||
const strings = await readYAMLDVPL<Strings>(
|
||||
const stringsPreInstalled = await readYAMLDVPL<Strings>(
|
||||
`${DATA}/${POI.strings}/en.yaml.dvpl`,
|
||||
);
|
||||
const stringsCache = await fetch(POI.cachedStrings)
|
||||
@@ -269,6 +283,10 @@ export async function definitions(production: boolean) {
|
||||
const optionalDevices = await readXMLDVPL<{ root: OptionalDevices }>(
|
||||
`${DATA}/${POI.optionalDevices}.dvpl`,
|
||||
);
|
||||
const strings = {
|
||||
...stringsPreInstalled,
|
||||
...stringsCache,
|
||||
};
|
||||
const optionalDeviceSlots = await readXMLDVPL<{
|
||||
root: OptionalDeviceSlots;
|
||||
}>(`${DATA}/${POI.optionalDeviceSlots}.dvpl`);
|
||||
@@ -299,6 +317,11 @@ export async function definitions(production: boolean) {
|
||||
}>(
|
||||
`${DATA}/${POI.vehicleDefinitions}/${nation}/components/shells.xml.dvpl`,
|
||||
);
|
||||
const enginesList = await readXMLDVPL<{
|
||||
root: EngineDefinitionsList;
|
||||
}>(
|
||||
`${DATA}/${POI.vehicleDefinitions}/${nation}/components/engines.xml.dvpl`,
|
||||
);
|
||||
|
||||
for (const tankKey in tankList.root) {
|
||||
const tank = tankList.root[tankKey];
|
||||
@@ -354,12 +377,9 @@ export async function definitions(production: boolean) {
|
||||
provisions: tankDefinition.root.provisionSlots,
|
||||
name:
|
||||
(tank.shortUserString
|
||||
? strings[tank.shortUserString] ??
|
||||
stringsCache[tank.shortUserString]
|
||||
: undefined) ??
|
||||
strings[tank.userString] ??
|
||||
stringsCache[tank.userString],
|
||||
name_full: strings[tank.userString] ?? stringsCache[tank.userString],
|
||||
? strings[tank.shortUserString]
|
||||
: undefined) ?? strings[tank.userString],
|
||||
name_full: strings[tank.userString],
|
||||
nation,
|
||||
tree_type: tankTags.includes('collectible')
|
||||
? 'collector'
|
||||
@@ -376,6 +396,7 @@ export async function definitions(production: boolean) {
|
||||
firing: tankDefinition.root.invisibility.firePenalty,
|
||||
},
|
||||
turrets: [],
|
||||
engines: [],
|
||||
};
|
||||
|
||||
if (
|
||||
@@ -402,6 +423,18 @@ export async function definitions(production: boolean) {
|
||||
turrets: {},
|
||||
};
|
||||
|
||||
Object.keys(tankDefinition.root.engines).forEach((engineKey) => {
|
||||
const engine = enginesList.root.shared[engineKey];
|
||||
const engineId = toUniqueId(nation, enginesList.root.ids[engineKey]);
|
||||
|
||||
tankDefinitions[tankId].engines.push({
|
||||
id: engineId,
|
||||
name: strings[engine.userString],
|
||||
fire_chance: engine.fireStartingChance,
|
||||
tier: engine.level as Tier,
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(tankDefinition.root.turrets0).forEach(
|
||||
(turretKey, turretIndex) => {
|
||||
const turret = tankDefinition.root.turrets0[turretKey];
|
||||
|
||||
@@ -104,6 +104,7 @@ export function AntagonistBar() {
|
||||
onSelect={(tank) => {
|
||||
mutateDuel((draft) => {
|
||||
draft.antagonist!.tank = tank;
|
||||
draft.antagonist!.engine = tank.engines.at(-1)!;
|
||||
draft.antagonist!.turret = tank.turrets.at(-1)!;
|
||||
draft.antagonist!.gun =
|
||||
draft.antagonist!.turret.guns.at(-1)!;
|
||||
|
||||
@@ -11,25 +11,24 @@ export function Modules() {
|
||||
<ConfigurationChildWrapper>
|
||||
<Heading size="4">Modules</Heading>
|
||||
|
||||
<Flex gap="2">
|
||||
<Flex gap="2" wrap="wrap">
|
||||
<Flex>
|
||||
{protagonist.tank.turrets.map((thisTurret, index) => {
|
||||
{protagonist.tank.turrets.map((turret, index) => {
|
||||
return (
|
||||
<ModuleButton
|
||||
key={thisTurret.id}
|
||||
selected={protagonist.turret.id === thisTurret.id}
|
||||
key={turret.id}
|
||||
selected={protagonist.turret.id === turret.id}
|
||||
type="module"
|
||||
module="turret"
|
||||
discriminator={TIER_ROMAN_NUMERALS[thisTurret.tier]}
|
||||
discriminator={TIER_ROMAN_NUMERALS[turret.tier]}
|
||||
first={index === 0}
|
||||
last={index === protagonist.tank.turrets.length - 1}
|
||||
rowChild
|
||||
onClick={() => {
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist!.turret = thisTurret;
|
||||
draft.protagonist!.gun = thisTurret.guns.at(-1)!;
|
||||
draft.protagonist!.shell =
|
||||
thisTurret.guns.at(-1)!.shells[0];
|
||||
draft.protagonist!.turret = turret;
|
||||
draft.protagonist!.gun = turret.guns.at(-1)!;
|
||||
draft.protagonist!.shell = turret.guns.at(-1)!.shells[0];
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@@ -38,21 +37,43 @@ export function Modules() {
|
||||
</Flex>
|
||||
|
||||
<Flex>
|
||||
{protagonist.turret.guns.map((thisGun, index) => {
|
||||
{protagonist.turret.guns.map((gun, index) => {
|
||||
return (
|
||||
<ModuleButton
|
||||
key={thisGun.id}
|
||||
key={gun.id}
|
||||
type="module"
|
||||
module="gun"
|
||||
discriminator={TIER_ROMAN_NUMERALS[thisGun.tier]}
|
||||
selected={protagonist.gun.id === thisGun.id}
|
||||
discriminator={TIER_ROMAN_NUMERALS[gun.tier]}
|
||||
selected={protagonist.gun.id === gun.id}
|
||||
first={index === 0}
|
||||
last={index === protagonist.turret.guns.length - 1}
|
||||
rowChild
|
||||
onClick={() => {
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist!.gun = thisGun;
|
||||
draft.protagonist!.shell = thisGun.shells[0];
|
||||
draft.protagonist!.gun = gun;
|
||||
draft.protagonist!.shell = gun.shells[0];
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
|
||||
<Flex>
|
||||
{protagonist.tank.engines.map((engine, index) => {
|
||||
return (
|
||||
<ModuleButton
|
||||
key={engine.id}
|
||||
type="module"
|
||||
module="engine"
|
||||
discriminator={TIER_ROMAN_NUMERALS[engine.tier]}
|
||||
selected={protagonist.engine.id === engine.id}
|
||||
first={index === 0}
|
||||
last={index === protagonist.tank.engines.length - 1}
|
||||
rowChild
|
||||
onClick={() => {
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist!.engine = engine;
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -14,7 +14,9 @@ import { Provisions } from './components/Provisions';
|
||||
|
||||
export function Characteristics() {
|
||||
const awaitedModelDefinitions = use(modelDefinitions);
|
||||
const { tank, turret, gun, shell } = useDuel((state) => state.protagonist!);
|
||||
const { tank, turret, gun, shell, engine } = useDuel(
|
||||
(state) => state.protagonist!,
|
||||
);
|
||||
const tankModelDefinition = awaitedModelDefinitions[tank.id];
|
||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||
@@ -52,7 +54,7 @@ export function Characteristics() {
|
||||
{tank.health + turret.health}
|
||||
</Info>
|
||||
<Info name="Fire chance" unit="%">
|
||||
TODO
|
||||
{Math.round(engine.fire_chance * 100)}
|
||||
</Info>
|
||||
<Info name="View range" unit="m">
|
||||
TODO
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { UpdateIcon } from '@radix-ui/react-icons';
|
||||
import { Button, Dialog, Flex, Heading } from '@radix-ui/themes';
|
||||
import { useState } from 'react';
|
||||
import { TREE_TYPE_ICONS } from '../../../../../components/Tanks';
|
||||
import { mutateDuel, useDuel } from '../../../../../stores/duel';
|
||||
import { TankSearch } from '../../components/TankSearch';
|
||||
import { useState } from 'react';
|
||||
|
||||
export function Title() {
|
||||
const protagonist = useDuel((state) => state.protagonist!);
|
||||
@@ -61,6 +61,7 @@ export function Title() {
|
||||
onSelect={(tank) => {
|
||||
mutateDuel((draft) => {
|
||||
draft.protagonist!.tank = tank;
|
||||
draft.protagonist!.engine = tank.engines.at(-1)!;
|
||||
draft.protagonist!.turret = tank.turrets.at(-1)!;
|
||||
draft.protagonist!.gun =
|
||||
draft.protagonist!.turret.guns.at(-1)!;
|
||||
|
||||
@@ -22,18 +22,13 @@ export default function Page({ params }: { params: { id: string } }) {
|
||||
draft.assigned = true;
|
||||
draft.protagonist = {
|
||||
tank: awaitedTankDefinitions[id],
|
||||
engine: awaitedTankDefinitions[id].engines.at(-1)!,
|
||||
turret: awaitedTankDefinitions[id].turrets.at(-1)!,
|
||||
gun: awaitedTankDefinitions[id].turrets.at(-1)!.guns.at(-1)!,
|
||||
shell: awaitedTankDefinitions[id].turrets.at(-1)!.guns.at(-1)!
|
||||
.shells[0],
|
||||
};
|
||||
draft.antagonist = {
|
||||
tank: awaitedTankDefinitions[id],
|
||||
turret: awaitedTankDefinitions[id].turrets.at(-1)!,
|
||||
gun: awaitedTankDefinitions[id].turrets.at(-1)!.guns.at(-1)!,
|
||||
shell: awaitedTankDefinitions[id].turrets.at(-1)!.guns.at(-1)!
|
||||
.shells[0],
|
||||
};
|
||||
draft.antagonist = { ...draft.protagonist };
|
||||
});
|
||||
|
||||
mutateTankopediaTemporary((draft) => {
|
||||
|
||||
@@ -26,10 +26,17 @@ export interface TankDefinition {
|
||||
type: TankType;
|
||||
testing?: boolean;
|
||||
turrets: TurretDefinition[];
|
||||
engines: EngineDefinition[];
|
||||
price: TankDefinitionPrice;
|
||||
camouflage: { still: number; moving: number; firing: number };
|
||||
equipment: string;
|
||||
}
|
||||
export interface EngineDefinition {
|
||||
id: number;
|
||||
name: string;
|
||||
tier: Tier;
|
||||
fire_chance: number;
|
||||
}
|
||||
export type TankDefinitionPrice =
|
||||
| { type: 'credits'; value: number }
|
||||
| { type: 'gold'; value: number };
|
||||
|
||||
@@ -3,6 +3,7 @@ import { create } from 'zustand';
|
||||
import { persist, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { TankType, TreeType } from '../components/Tanks';
|
||||
import {
|
||||
EngineDefinition,
|
||||
GunDefinition,
|
||||
ShellDefinition,
|
||||
TankDefinition,
|
||||
@@ -16,6 +17,7 @@ export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only';
|
||||
export type TankopediaMode = 'model' | 'armor';
|
||||
export interface DuelMember {
|
||||
tank: TankDefinition;
|
||||
engine: EngineDefinition;
|
||||
turret: TurretDefinition;
|
||||
gun: GunDefinition;
|
||||
shell: ShellDefinition;
|
||||
|
||||
Reference in new issue
Block a user