mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +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,
|
TankAttributeChange_AttributeName,
|
||||||
} from "@protos/blitz_static_tank_upgrade_single_stage";
|
} from "@protos/blitz_static_tank_upgrade_single_stage";
|
||||||
|
|
||||||
export type CharacteristicOutput = number | string | null;
|
export type CharacteristicOutput = number | null;
|
||||||
|
|
||||||
interface Characteristic {
|
type Characteristic = (helpers: {
|
||||||
value: (helpers: {
|
characteristic: (name: CharacteristicName) => CharacteristicOutput;
|
||||||
characteristic: (name: CharacteristicName) => CharacteristicOutput;
|
attribute: (name: TankAttributeChange_AttributeName) => number;
|
||||||
attribute: (name: TankAttributeChange_AttributeName) => number;
|
shell: (name: ShellUpgrageSingleChange_AttributeName) => number;
|
||||||
shell: (name: ShellUpgrageSingleChange_AttributeName) => number;
|
}) => CharacteristicOutput;
|
||||||
}) => CharacteristicOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CharacteristicName = keyof typeof characteristics;
|
export type CharacteristicName = keyof typeof characteristics;
|
||||||
|
|
||||||
|
export enum GunType {
|
||||||
|
Regular,
|
||||||
|
AutoLoader,
|
||||||
|
AutoReloader,
|
||||||
|
}
|
||||||
|
|
||||||
export const characteristics = {
|
export const characteristics = {
|
||||||
gun_type: {
|
gun_type({ attribute }) {
|
||||||
value({ attribute }) {
|
const isPump = attribute(
|
||||||
const isPump = attribute(
|
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_IS_PUMP
|
||||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_IS_PUMP
|
);
|
||||||
);
|
|
||||||
|
|
||||||
if (isPump === 1) return "auto_reloader";
|
if (isPump === 1) return GunType.AutoReloader;
|
||||||
|
|
||||||
const clipSize = attribute(
|
const clipSize = attribute(
|
||||||
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_CLIP_SIZE
|
TankAttributeChange_AttributeName.ATTRIBUTE_NAME_CLIP_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
if (clipSize === 1) return "regular";
|
if (clipSize === 1) return GunType.Regular;
|
||||||
|
|
||||||
return "auto_loader";
|
return GunType.AutoLoader;
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
damage: {
|
damage({ shell }) {
|
||||||
value({ shell }) {
|
return shell(
|
||||||
return shell(
|
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_ARMOR_DAMAGE
|
||||||
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_ARMOR_DAMAGE
|
);
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
dpm: {
|
module_damage({ shell }) {
|
||||||
value({ characteristic }) {
|
return shell(
|
||||||
const damage = characteristic("damage");
|
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>;
|
} satisfies Record<string, Characteristic>;
|
||||||
@@ -1,14 +1,28 @@
|
|||||||
import type { CharacteristicName } from "./characteristics";
|
import type { CharacteristicName } from "./characteristics";
|
||||||
|
|
||||||
|
export enum BetterDirection {
|
||||||
|
Higher,
|
||||||
|
Lower,
|
||||||
|
}
|
||||||
|
|
||||||
type CharacteristicsOrder = {
|
type CharacteristicsOrder = {
|
||||||
group: string;
|
group: string;
|
||||||
order: CharacteristicName[];
|
order: {
|
||||||
|
name: CharacteristicName;
|
||||||
|
decimals?: number;
|
||||||
|
}[];
|
||||||
}[];
|
}[];
|
||||||
|
|
||||||
export const characteristicsGroups = [
|
export const characteristicsGroups = [
|
||||||
{
|
{
|
||||||
group: "firepower",
|
group: "firepower",
|
||||||
order: ["gun_type", "dpm"],
|
order: [
|
||||||
|
{ name: "gun_type" },
|
||||||
|
{ name: "dpm", decimals: 0 },
|
||||||
|
{ name: "damage" },
|
||||||
|
{ name: "module_damage" },
|
||||||
|
{ name: "penetration" },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
group: "maneuverability",
|
group: "maneuverability",
|
||||||
|
|||||||
+8
-5
@@ -8,10 +8,11 @@ import {
|
|||||||
type CharacteristicName,
|
type CharacteristicName,
|
||||||
type CharacteristicOutput,
|
type CharacteristicOutput,
|
||||||
} from "./characteristics";
|
} from "./characteristics";
|
||||||
|
import type { TankState } from "./tankState";
|
||||||
|
|
||||||
export function renderCharacteristics(
|
export function computeCharacteristics(
|
||||||
parameters: StageParameters,
|
parameters: StageParameters,
|
||||||
shellId: number
|
state: TankState
|
||||||
) {
|
) {
|
||||||
const computed: Partial<Record<CharacteristicName, CharacteristicOutput>> =
|
const computed: Partial<Record<CharacteristicName, CharacteristicOutput>> =
|
||||||
{};
|
{};
|
||||||
@@ -34,7 +35,7 @@ export function renderCharacteristics(
|
|||||||
|
|
||||||
function shell(name: ShellUpgrageSingleChange_AttributeName) {
|
function shell(name: ShellUpgrageSingleChange_AttributeName) {
|
||||||
const shell = parameters.shells_upgrades.find(
|
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`);
|
if (!shell) throw new Error(`Shell ${name} not found`);
|
||||||
@@ -50,7 +51,9 @@ export function renderCharacteristics(
|
|||||||
|
|
||||||
for (const _name in characteristics) {
|
for (const _name in characteristics) {
|
||||||
const name = _name as CharacteristicName;
|
const name = _name as CharacteristicName;
|
||||||
const _characteristic = characteristics[name];
|
const value = characteristics[name]({ characteristic, attribute, shell });
|
||||||
const value = _characteristic.value({ 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 { Suspense, useMemo } from "react";
|
||||||
import { api } from "../../../core/api/dynamic";
|
import { api } from "../../../core/api/dynamic";
|
||||||
import { aggregateStageParameters } from "../../../core/tankopedia/aggregateStageParameters";
|
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 { useAwait } from "../../../hooks/useAwait";
|
||||||
import { Tankopedia } from "../../../stores/tankopedia";
|
import { Tankopedia } from "../../../stores/tankopedia";
|
||||||
|
|
||||||
@@ -17,11 +18,19 @@ export function Page({ id }: { id: string }) {
|
|||||||
function Content({ id }: { id: string }) {
|
function Content({ id }: { id: string }) {
|
||||||
const tank = useAwait(() => api.tank(id), `tank-${id}`);
|
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(
|
const parameters = useMemo(
|
||||||
() =>
|
() =>
|
||||||
aggregateStageParameters(tank.base_stats!, tank.upgrade_stages, stage),
|
aggregateStageParameters(
|
||||||
[stage]
|
tank.base_stats!,
|
||||||
|
tank.upgrade_stages,
|
||||||
|
protagonist.shell
|
||||||
|
),
|
||||||
|
[protagonist]
|
||||||
|
);
|
||||||
|
const characteristics = useMemo(
|
||||||
|
() => computeCharacteristics(parameters, protagonist),
|
||||||
|
[protagonist]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -32,23 +41,35 @@ function Content({ id }: { id: string }) {
|
|||||||
key={index}
|
key={index}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
Tankopedia.mutate((draft) => {
|
Tankopedia.mutate((draft) => {
|
||||||
draft.stage = index;
|
draft.protagonist.stage = index;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Stage {index} {index === stage && "(selected)"}
|
Stage {index} {index === protagonist.stage && "(selected)"}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{characteristicsOrder.map(({ group, order }) => (
|
{characteristicsGroups.map(({ group, order }) => (
|
||||||
<>
|
<>
|
||||||
<h2>{group}</h2>
|
<h2>{group}</h2>
|
||||||
|
|
||||||
{order.map((name) => {
|
{order.map(({ name, decimals }) => {
|
||||||
const characteristic = characteristics[name];
|
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 { Varuna } from "varuna";
|
||||||
|
import type { TankState } from "../core/tankopedia/tankState";
|
||||||
|
|
||||||
interface Tankopedia {
|
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