feat: shells

This commit is contained in:
TrèsAbhi committed 2025-12-18 16:45:02 -06:00
1 parent 4f1c4421e5
commit c6b7918525
5 files changed
+69 -27

No files matched your search

@@ -6,18 +6,10 @@ import {
export type CharacteristicOutput = number | null; export type CharacteristicOutput = number | null;
type Characteristic = (helpers: { type Characteristic = (helpers: {
characteristic: ( characteristic: (name: CharacteristicName) => CharacteristicOutput;
name: CharacteristicName, attribute: (name: TankAttributeChange_AttributeName) => number;
error?: boolean shell: (name: ShellUpgrageSingleChange_AttributeName) => number;
) => CharacteristicOutput; shellSafe: (name: ShellUpgrageSingleChange_AttributeName) => number | null;
attribute: (
name: TankAttributeChange_AttributeName,
error?: boolean
) => number;
shell: (
name: ShellUpgrageSingleChange_AttributeName,
error?: boolean
) => number;
}) => CharacteristicOutput; }) => CharacteristicOutput;
export type CharacteristicName = keyof typeof characteristics; export type CharacteristicName = keyof typeof characteristics;
@@ -96,8 +88,8 @@ export const characteristics = {
return shell(ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_CALIBER); return shell(ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_CALIBER);
}, },
normalization({ shell }) { normalization({ shellSafe }) {
return shell( return shellSafe(
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_NORMALIZATION ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_NORMALIZATION
); );
}, },
@@ -112,15 +104,17 @@ export const characteristics = {
return shell(ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_SPEED); return shell(ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_SPEED);
}, },
shell_range({ shell }) { shell_range({ shellSafe }) {
return shell( const maxDistance = shellSafe(
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_MAX_DISTANCE ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_MAX_DISTANCE
); );
return maxDistance === null ? Infinity : maxDistance;
}, },
shell_capacity({ shell }) { shell_capacity({ shellSafe }) {
return shell( const count = shellSafe(
ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_MAX_COUNT ShellUpgrageSingleChange_AttributeName.ATTRIBUTE_NAME_MAX_COUNT
); );
return count === -1 || count === null ? Infinity : count;
}, },
} satisfies Record<string, Characteristic>; } satisfies Record<string, Characteristic>;
@@ -36,7 +36,7 @@ export function computeCharacteristics(
return attribute.value; return attribute.value;
} }
function shell(name: ShellUpgrageSingleChange_AttributeName) { function shellSafe(name: ShellUpgrageSingleChange_AttributeName) {
const shell = parameters.shells_upgrades.find( const shell = parameters.shells_upgrades.find(
(shell) => shell.shell_id === state.shell (shell) => shell.shell_id === state.shell
); );
@@ -51,18 +51,29 @@ export function computeCharacteristics(
(change) => change.attribute_name === name (change) => change.attribute_name === name
); );
if (!attribute) { return attribute ? attribute.value : null;
}
function shell(name: ShellUpgrageSingleChange_AttributeName) {
const attribute = shellSafe(name);
if (attribute === null) {
throw new Error( throw new Error(
`Shell attribute ${ShellUpgrageSingleChange_AttributeName[name]} (${name}) not found` `Shell attribute ${ShellUpgrageSingleChange_AttributeName[name]} (${name}) not found`
); );
} }
return attribute.value; return attribute;
} }
for (const _name in characteristics) { for (const _name in characteristics) {
const name = _name as CharacteristicName; const name = _name as CharacteristicName;
const value = characteristics[name]({ characteristic, attribute, shell }); const value = characteristics[name]({
characteristic,
attribute,
shell,
shellSafe,
});
computed[name] = value; computed[name] = value;
} }
@@ -0,0 +1,9 @@
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<slot />
</body>
</html>
@@ -35,6 +35,8 @@ function Content({ id }: { id: string }) {
return ( return (
<> <>
<h1>{id}</h1>
<div style={{ display: "flex", flexWrap: "wrap" }}> <div style={{ display: "flex", flexWrap: "wrap" }}>
{times(tank.upgrade_stages.length, (index) => ( {times(tank.upgrade_stages.length, (index) => (
<button <button
@@ -50,9 +52,27 @@ function Content({ id }: { id: string }) {
))} ))}
</div> </div>
<br />
<div style={{ display: "flex", flexWrap: "wrap" }}>
{parameters.shells_upgrades.map((shell) => (
<button
key={shell.shell_id}
onClick={() => {
Tankopedia.mutate((draft) => {
draft.protagonist.shell = shell.shell_id;
});
}}
>
Shell {shell.shell_id}{" "}
{shell.shell_id === protagonist.shell && "(selected)"}
</button>
))}
</div>
{characteristicsGroups.map(({ group, order }) => ( {characteristicsGroups.map(({ group, order }) => (
<> <>
<h2>{group}</h2> <h2 key={group}>{group}</h2>
{order.map((entry) => { {order.map((entry) => {
if ("toy" in entry) { if ("toy" in entry) {
@@ -64,12 +84,17 @@ function Content({ id }: { id: string }) {
let rendered: string | number = characteristic; let rendered: string | number = characteristic;
if (typeof rendered === "number") { if (typeof rendered === "number") {
if (entry.decimals !== undefined) if (rendered === Infinity) {
rendered = rendered.toFixed(entry.decimals); rendered = "∞";
} else {
if (entry.decimals !== undefined) {
rendered = rendered.toFixed(entry.decimals);
}
}
} }
return ( return (
<p> <p key={entry.name}>
{entry.name}: {rendered} {entry.name}: {rendered}
</p> </p>
); );
@@ -1,6 +1,7 @@
--- ---
import type { GetStaticPaths } from "astro"; import type { GetStaticPaths } from "astro";
import { api } from "../../../core/api/dynamic"; import { api } from "../../../core/api/dynamic";
import BaseLayout from "../../../layouts/BaseLayout.astro";
import { Page } from "./_index"; import { Page } from "./_index";
export const getStaticPaths = (async () => { export const getStaticPaths = (async () => {
@@ -15,4 +16,6 @@ export const getStaticPaths = (async () => {
const { id } = Astro.props; const { id } = Astro.props;
--- ---
<Page {id} client:load /> <BaseLayout>
<Page {id} client:load />
</BaseLayout>