Compare commits

...
4 Commits
Author SHA1 Message Date
TrèsAbhi da1af66c77 feat: start of mechanics 2025-12-26 20:07:22 -06:00
TrèsAbhi 01409985a2 feat: list 2025-12-26 19:43:44 -06:00
TrèsAbhi a86ac0619a feat: stop working on ranking since a lot of tanks are broken 2025-12-26 19:37:52 -06:00
TrèsAbhi 385d165512 feat: optimize tankList 2025-12-26 19:21:14 -06:00
11 changed files with 95 additions and 40 deletions

No files matched your search

@@ -4,17 +4,23 @@ import { renderCharacteristic } from "../core/tankopedia/renderCharacteristic";
interface Props {
characteristic: CharacteristicOutput;
others: CharacteristicOutput[];
config: CharacteristicRenderConfig;
}
export function TankopediaCharacteristic({ characteristic, config }: Props) {
export function TankopediaCharacteristic({
characteristic,
others,
config,
}: Props) {
if (characteristic === null) return null;
const rendered = renderCharacteristic(characteristic, config);
return (
<p>
{config.name}: {rendered} {config.units && `${config.units}`} (1 / 1)
{config.name}: {rendered} {config.units && `${config.units}`} (1 /{" "}
{others.length})
</p>
);
}
+8 -5
View File
@@ -3,7 +3,7 @@ import { sluggify } from "@blitzkit/core";
import type { RemoteStorageComponent } from "@protos/blitz_static_remote_storage_component";
import { parse } from "yaml";
import type { Tank } from "../../protos/tank";
import type { TankListEntry } from "../../protos/tank_list";
import type { TankList, TankListEntry } from "../../protos/tank_list";
import type { Tanks } from "../../protos/tanks";
import { AbstractAPI } from "./abstract";
@@ -120,15 +120,13 @@ export class ServerAPI extends AbstractAPI {
const data: Tanks = { tanks: {} };
for (const { id } of tankList.list) {
console.log(id);
data.tanks[id] = await this.tank(id);
data.tanks[id] = await this._tank(id, tankList);
}
return data;
}
async tank(id: string) {
const tankList = await this.tankList();
async _tank(id: string, tankList: TankList) {
const tankListEntry = tankList.list.find((tank) => tank.id === id);
if (!tankListEntry) {
@@ -142,4 +140,9 @@ export class ServerAPI extends AbstractAPI {
return { tank, compensation, slug } satisfies Tank;
}
async tank(id: string) {
const tankList = await this.tankList();
return this._tank(id, tankList);
}
}
@@ -1,12 +1,11 @@
import { TankClass } from "@blitzkit/core";
import type { CompensationComponent } from "@protos/blitz_static_compensation_component";
import { type TankCatalogComponent } from "@protos/blitz_static_tank_component";
import {
ShellUpgrageSingleChange_AttributeName,
StageParameters,
TankAttributeChange_AttributeName,
} from "@protos/blitz_static_tank_upgrade_single_stage";
import { radToDeg } from "three/src/math/MathUtils.js";
import type { Tank } from "../../protos/tank";
import { applyPitchYawLimits } from "./applyPitchYawLimits";
import { TerrainHardness, type TankState } from "./tankState";
@@ -19,9 +18,8 @@ type Characteristic = (helpers: {
shell: (name: ShellUpgrageSingleChange_AttributeName) => number;
shellSafe: (name: ShellUpgrageSingleChange_AttributeName) => number | null;
state: TankState;
tank: TankCatalogComponent;
tank: Tank;
parameters: StageParameters;
compensation: CompensationComponent;
id: string;
}) => CharacteristicOutput;
@@ -254,7 +252,7 @@ export const characteristics = {
);
},
gun_depression({ parameters }) {
gun_depression({ parameters, tank }) {
return -radToDeg(
applyPitchYawLimits(
-Math.PI / 2,
@@ -349,7 +347,7 @@ export const characteristics = {
},
class({ tank }) {
return tank.tank_class;
return tank.tank!.tank_class;
},
camouflage({ attribute, characteristic, attributeSafe, state }) {
@@ -396,26 +394,30 @@ export const characteristics = {
},
nation({ tank }) {
return tank.nation;
return tank.tank!.nation;
},
name({ tank }) {
return tank.name!.value;
return tank.tank!.name!.value;
},
tier({ tank }) {
return tank.tier_catalog_id;
return tank.tank!.tier_catalog_id;
},
type({ tank }) {
return tank.tank_type;
return tank.tank!.tank_type;
},
id({ id }) {
return id;
},
compensation({ compensation }) {
return compensation.compensation?.currency_reward?.amount ?? null;
slug({ tank }) {
return tank.slug;
},
compensation({ tank }) {
return tank.compensation!.compensation?.currency_reward?.amount ?? null;
},
} satisfies Record<string, Characteristic>;
@@ -57,6 +57,7 @@ export const characteristicsOrder: CharacteristicsOrder = [
},
{ name: "compensation" },
{ name: "id" },
{ name: "slug" },
],
},
{
@@ -1,9 +1,8 @@
import type { CompensationComponent } from "@protos/blitz_static_compensation_component";
import type { TankCatalogComponent } from "@protos/blitz_static_tank_component";
import {
ShellUpgrageSingleChange_AttributeName,
TankAttributeChange_AttributeName,
} from "@protos/blitz_static_tank_upgrade_single_stage";
import type { Tank } from "../../protos/tank";
import { aggregateStageParameters } from "./aggregateStageParameters";
import {
characteristics,
@@ -19,13 +18,12 @@ export type ComputedCharacteristics = Record<
export function computeCharacteristics(
id: string,
tank: TankCatalogComponent,
compensation: CompensationComponent,
tank: Tank,
state: TankState
) {
const parameters = aggregateStageParameters(
tank.base_stats!,
tank.upgrade_stages.slice(0, state.stage)
tank.tank!.base_stats!,
tank.tank!.upgrade_stages.slice(0, state.stage)
);
const computed: Partial<ComputedCharacteristics> = {};
@@ -97,7 +95,6 @@ export function computeCharacteristics(
tank,
parameters,
id,
compensation,
});
computed[name] = value;
}
@@ -0,0 +1,12 @@
import type { APIContext } from "astro";
import { api } from "../../../core/api/dynamic";
export { getStaticPaths } from "./[id].pb";
/**
* Even Noah can't save these animals.
*/
export async function GET({ params }: APIContext<never, { id: string }>) {
const tank = await api.tank(params.id);
return Response.json(tank);
}
@@ -4,7 +4,6 @@ import { Tank } from "../../../protos/tank";
export const getStaticPaths = (async () => {
const { list } = await api.tankList();
return list.map(({ id }) => ({ params: { id } }));
}) satisfies GetStaticPaths;
@@ -0,0 +1,10 @@
import { api } from "../../../core/api/dynamic";
import { TankList } from "../../../protos/tank_list";
/**
* Literally all the tanks in one place lmao.
*/
export async function GET() {
const list = await api.tankList();
return new Response(TankList.encode(list).finish());
}
@@ -18,26 +18,50 @@ export function Page({ id }: { id: string }) {
}
function Content({ id }: { id: string }) {
const { tank, compensation } = useAwait(() => api.tank(id), `tank-${id}`);
const tank = useAwait(() => api.tank(id), `tank-${id}`);
const tankList = useAwait(() => api.tankList(), "tank-list");
const otherTanks = useAwait(() => api.tanks(), "tanks");
Tankopedia.useInitialization(tank!);
Tankopedia.useInitialization(tank.tank!);
const protagonist = Tankopedia.use((state) => state.protagonist);
const compare = Tankopedia.use((state) => state.compare);
const { characteristics, parameters } = useMemo(
() => computeCharacteristics(id, tank!, compensation!, protagonist),
const characteristics = useMemo(
() => computeCharacteristics(id, tank, protagonist),
[protagonist]
);
// const otherCharacteristics = useMemo(
// () =>
// tankList.list
// .filter((tank) => tank.id !== id)
// .map(({ id }) => {
// const state = { ...protagonist };
// const tank = otherTanks.tanks[id];
// return computeCharacteristics(
// id,
// tank.tank!,
// tank.compensation!,
// state
// );
// }),
// [protagonist]
// );
return (
<>
<h1>{id}</h1>
<div style={{ display: "flex", flexWrap: "wrap", gap: "1rem" }}>
{tank.tank?.feature_screens?.tags.map((tag) => (
<span>{tag.value}</span>
))}
</div>
<br />
<div style={{ display: "flex", flexWrap: "wrap" }}>
{times(tank!.upgrade_stages.length + 1, (index) => (
{times(tank.tank!.upgrade_stages.length + 1, (index) => (
<button
key={index}
onClick={() => {
@@ -54,7 +78,7 @@ function Content({ id }: { id: string }) {
<br />
<div style={{ display: "flex", flexWrap: "wrap" }}>
{parameters.shells_upgrades.map((shell) => (
{characteristics.parameters.shells_upgrades.map((shell) => (
<button
key={shell.shell_id}
onClick={() => {
@@ -72,11 +96,11 @@ function Content({ id }: { id: string }) {
<br />
<div>
<span>speed (0 - {characteristics.speed_forward})</span>
<span>speed (0 - {characteristics.characteristics.speed_forward})</span>
<input
type="range"
min={0}
max={characteristics.speed_forward as number}
max={characteristics.characteristics.speed_forward as number}
value={protagonist.speed}
onChange={(event) => {
Tankopedia.mutate((draft) => {
@@ -214,7 +238,8 @@ function Content({ id }: { id: string }) {
) : (
<TankopediaCharacteristic
key={`characteristic-${config.name}`}
characteristic={characteristics[config.name]}
characteristic={characteristics.characteristics[config.name]}
others={[]}
config={config}
/>
)
@@ -6,9 +6,9 @@ import BaseLayout from "../../../layouts/BaseLayout.astro";
import { Page } from "./_index";
export const getStaticPaths = (async () => {
const { tanks } = await api.tanks();
const { list } = await api.tankList();
return tanks.map((tank) => ({
return list.map((tank) => ({
params: { slug: tank.slug },
props: { id: tank.id },
}));
@@ -3,14 +3,14 @@ import "@radix-ui/colors/violet-dark.css";
import { api } from "../../core/api/dynamic";
import BaseLayout from "../../layouts/BaseLayout.astro";
const tanksList = await api.tanks();
const tankList = await api.tankList();
---
<BaseLayout accent="violet">
<h1>tanks</h1>
{
tanksList.tanks.map(({ id, slug }) => (
tankList.list.map(({ id, slug }) => (
<p>
<a href={`/tanks/${slug}`}>
{slug} ({id})