mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: start of more attrs
This commit is contained in:
1 parent
6ce1135835
commit
7b830f5a71
6 files changed
+128
-49
No files matched your search
@@ -3,50 +3,83 @@ import {
|
||||
TankAttributeChange_AttributeName,
|
||||
} from "@protos/blitz_static_tank_upgrade_single_stage";
|
||||
|
||||
export type CharacteristicOutput = number | string | null;
|
||||
export type CharacteristicOutput = number | null;
|
||||
|
||||
interface Characteristic {
|
||||
value: (helpers: {
|
||||
characteristic: (name: CharacteristicName) => CharacteristicOutput;
|
||||
attribute: (name: TankAttributeChange_AttributeName) => number;
|
||||
shell: (name: ShellUpgrageSingleChange_AttributeName) => number;
|
||||
}) => CharacteristicOutput;
|
||||
}
|
||||
type Characteristic = (helpers: {
|
||||
characteristic: (name: CharacteristicName) => CharacteristicOutput;
|
||||
attribute: (name: TankAttributeChange_AttributeName) => number;
|
||||
shell: (name: ShellUpgrageSingleChange_AttributeName) => number;
|
||||
}) => CharacteristicOutput;
|
||||
|
||||
export type CharacteristicName = keyof typeof characteristics;
|
||||
|
||||
export enum GunType {
|
||||
Regular,
|
||||
AutoLoader,
|
||||
AutoReloader,
|
||||
}
|
||||
|
||||
export const characteristics = {
|
||||
gun_type: {
|
||||
value({ attribute }) {
|
||||
const isPump = attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_IS_PUMP
|
||||
);
|
||||
gun_type({ attribute }) {
|
||||
const isPump = attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_IS_PUMP
|
||||
);
|
||||
|
||||
if (isPump === 1) return "auto_reloader";
|
||||
if (isPump === 1) return GunType.AutoReloader;
|
||||
|
||||
const clipSize = attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_CLIP_SIZE
|
||||
);
|
||||
const clipSize = attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_CLIP_SIZE
|
||||
);
|
||||
|
||||
if (clipSize === 1) return "regular";
|
||||
if (clipSize === 1) return GunType.Regular;
|
||||
|
||||
return "auto_loader";
|
||||
},
|
||||
return GunType.AutoLoader;
|
||||
},
|
||||
|
||||
damage: {
|
||||
value({ shell }) {
|
||||
return shell(
|
||||
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_ARMOR_DAMAGE
|
||||
);
|
||||
},
|
||||
damage({ shell }) {
|
||||
return shell(
|
||||
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_ARMOR_DAMAGE
|
||||
);
|
||||
},
|
||||
|
||||
dpm: {
|
||||
value({ characteristic }) {
|
||||
const damage = characteristic("damage");
|
||||
module_damage({ shell }) {
|
||||
return shell(
|
||||
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_MODULE_DAMAGE
|
||||
);
|
||||
},
|
||||
|
||||
return 1;
|
||||
},
|
||||
penetration({ shell }) {
|
||||
return shell(
|
||||
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_PIERCING_POWER
|
||||
);
|
||||
},
|
||||
|
||||
reload({ characteristic, attribute }) {
|
||||
const gunType = characteristic("gun_type")!;
|
||||
|
||||
if (gunType !== GunType.Regular) return null;
|
||||
|
||||
return attribute(
|
||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_RELOAD_TIME
|
||||
);
|
||||
},
|
||||
|
||||
dpm({ characteristic }) {
|
||||
let dps: number;
|
||||
const gunType = characteristic("gun_type")!;
|
||||
const damage = characteristic("damage")!;
|
||||
|
||||
switch (gunType) {
|
||||
case GunType.Regular: {
|
||||
const reload = characteristic("reload")!;
|
||||
dps = damage / reload;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error("Unknown gun type");
|
||||
}
|
||||
|
||||
return 60 * dps;
|
||||
},
|
||||
} satisfies Record<string, Characteristic>;
|
||||
@@ -1,14 +1,28 @@
|
||||
import type { CharacteristicName } from "./characteristics";
|
||||
|
||||
export enum BetterDirection {
|
||||
Higher,
|
||||
Lower,
|
||||
}
|
||||
|
||||
type CharacteristicsOrder = {
|
||||
group: string;
|
||||
order: CharacteristicName[];
|
||||
order: {
|
||||
name: CharacteristicName;
|
||||
decimals?: number;
|
||||
}[];
|
||||
}[];
|
||||
|
||||
export const characteristicsGroups = [
|
||||
{
|
||||
group: "firepower",
|
||||
order: ["gun_type", "dpm"],
|
||||
order: [
|
||||
{ name: "gun_type" },
|
||||
{ name: "dpm", decimals: 0 },
|
||||
{ name: "damage" },
|
||||
{ name: "module_damage" },
|
||||
{ name: "penetration" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "maneuverability",
|
||||
|
||||
+8
-5
@@ -8,10 +8,11 @@ import {
|
||||
type CharacteristicName,
|
||||
type CharacteristicOutput,
|
||||
} from "./characteristics";
|
||||
import type { TankState } from "./tankState";
|
||||
|
||||
export function renderCharacteristics(
|
||||
export function computeCharacteristics(
|
||||
parameters: StageParameters,
|
||||
shellId: number
|
||||
state: TankState
|
||||
) {
|
||||
const computed: Partial<Record<CharacteristicName, CharacteristicOutput>> =
|
||||
{};
|
||||
@@ -34,7 +35,7 @@ export function renderCharacteristics(
|
||||
|
||||
function shell(name: ShellUpgrageSingleChange_AttributeName) {
|
||||
const shell = parameters.shells_upgrades.find(
|
||||
(shell) => shell.shell_id === name
|
||||
(shell) => shell.shell_id === state.shell
|
||||
);
|
||||
|
||||
if (!shell) throw new Error(`Shell ${name} not found`);
|
||||
@@ -50,7 +51,9 @@ export function renderCharacteristics(
|
||||
|
||||
for (const _name in characteristics) {
|
||||
const name = _name as CharacteristicName;
|
||||
const _characteristic = characteristics[name];
|
||||
const value = _characteristic.value({ characteristic, attribute, shell });
|
||||
const value = characteristics[name]({ characteristic, attribute, shell });
|
||||
computed[name] = value;
|
||||
}
|
||||
|
||||
return computed as Record<CharacteristicName, CharacteristicOutput>;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface TankState {
|
||||
stage: number;
|
||||
|
||||
shell: number;
|
||||
}
|
||||
@@ -2,7 +2,8 @@ import { times } from "lodash-es";
|
||||
import { Suspense, useMemo } from "react";
|
||||
import { api } from "../../../core/api/dynamic";
|
||||
import { aggregateStageParameters } from "../../../core/tankopedia/aggregateStageParameters";
|
||||
import { characteristics } from "../../../core/tankopedia/characteristics";
|
||||
import { characteristicsGroups } from "../../../core/tankopedia/characteristicsGroups";
|
||||
import { computeCharacteristics } from "../../../core/tankopedia/computeCharacteristics";
|
||||
import { useAwait } from "../../../hooks/useAwait";
|
||||
import { Tankopedia } from "../../../stores/tankopedia";
|
||||
|
||||
@@ -17,11 +18,19 @@ export function Page({ id }: { id: string }) {
|
||||
function Content({ id }: { id: string }) {
|
||||
const tank = useAwait(() => api.tank(id), `tank-${id}`);
|
||||
|
||||
const stage = Tankopedia.use((state) => state.stage);
|
||||
const protagonist = Tankopedia.use((state) => state.protagonist);
|
||||
const parameters = useMemo(
|
||||
() =>
|
||||
aggregateStageParameters(tank.base_stats!, tank.upgrade_stages, stage),
|
||||
[stage]
|
||||
aggregateStageParameters(
|
||||
tank.base_stats!,
|
||||
tank.upgrade_stages,
|
||||
protagonist.shell
|
||||
),
|
||||
[protagonist]
|
||||
);
|
||||
const characteristics = useMemo(
|
||||
() => computeCharacteristics(parameters, protagonist),
|
||||
[protagonist]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -32,23 +41,35 @@ function Content({ id }: { id: string }) {
|
||||
key={index}
|
||||
onClick={() => {
|
||||
Tankopedia.mutate((draft) => {
|
||||
draft.stage = index;
|
||||
draft.protagonist.stage = index;
|
||||
});
|
||||
}}
|
||||
>
|
||||
Stage {index} {index === stage && "(selected)"}
|
||||
Stage {index} {index === protagonist.stage && "(selected)"}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{characteristicsOrder.map(({ group, order }) => (
|
||||
{characteristicsGroups.map(({ group, order }) => (
|
||||
<>
|
||||
<h2>{group}</h2>
|
||||
|
||||
{order.map((name) => {
|
||||
{order.map(({ name, decimals }) => {
|
||||
const characteristic = characteristics[name];
|
||||
|
||||
return <span>{}</span>;
|
||||
if (characteristic === null) return null;
|
||||
|
||||
let rendered: string | number = characteristic;
|
||||
|
||||
if (typeof rendered === "number") {
|
||||
if (decimals !== undefined) rendered = rendered.toFixed(decimals);
|
||||
}
|
||||
|
||||
return (
|
||||
<p>
|
||||
{name}: {rendered}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
))}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Varuna } from "varuna";
|
||||
import type { TankState } from "../core/tankopedia/tankState";
|
||||
|
||||
interface Tankopedia {
|
||||
stage: number;
|
||||
protagonist: TankState;
|
||||
}
|
||||
|
||||
export const Tankopedia = new Varuna<Tankopedia>({ stage: 0 });
|
||||
export const Tankopedia = new Varuna<Tankopedia>({
|
||||
protagonist: { stage: 0, shell: 0 },
|
||||
});
|
||||
Reference in new issue
Block a user