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