This commit is contained in:
tresabhi committed 2026-10-12 10:47:00 -05:00
1 parent 3d8cfc3aeb
commit bc6257a0c3
5 files changed
+118 -34

No files matched your search

+18 -2
View File
@@ -101,6 +101,24 @@ export const characteristics = {
},
},
reloads: {
type: CharacteristicType.NumberList,
should_render({ gun }) {
return gun.gun_type!.$case === "auto_reloader";
},
compute({ gun, characteristic }) {
if (gun.gun_type!.$case !== "auto_reloader") return [];
const reloadCoefficient = characteristic("_reload_coefficient") as number;
return gun.gun_type!.value.shell_reloads.map(
(reload) => reload * reloadCoefficient,
);
},
},
intra_clip: {
type: CharacteristicType.Number,
@@ -195,8 +213,6 @@ export const characteristics = {
// module_damage_range: unavailable,
// reloads: unavailable,
clip_size: {
type: CharacteristicType.Number,
@@ -87,7 +87,12 @@ export const characteristicsGroups: CharacteristicsGroup[] = [
units: "s",
ranking: CharacteristicRanking.LowerIsBetter,
},
{ name: "reloads", decimals: 1, units: "s" },
{
name: "reloads",
decimals: 1,
units: "s",
ranking: CharacteristicRanking.LowerIsBetter,
},
{ toy: "reload" },
],
@@ -1,10 +1,12 @@
import { literalsArray } from "@blitzkit/i18n/src/literals";
import { type ReactNode } from "react";
import { Fragment, type ReactNode } from "react";
import { Text } from "../components/Text";
import { characteristics } from "../config/characteristics";
import type {
CharacteristicRenderConfig,
CharacteristicReturnType,
} from "../types/characteristics";
import { CharacteristicType } from "../types/characteristics";
import { useLocale } from "./useLocale";
import { useStrings } from "./useStrings";
@@ -21,39 +23,61 @@ export function useCharacteristicRenderer() {
if (config.render)
return config.render({ output: characteristic, strings });
if (typeof characteristic === "number") {
if (Number.isFinite(characteristic)) {
let value: ReactNode = characteristic;
function renderNumber(
value: number,
units: CharacteristicRenderConfig["units"],
): ReactNode {
if (!Number.isFinite(value)) return `${value < 0 ? "-" : ""}∞`;
if (config.decimals !== undefined) {
value *= 10 ** config.decimals;
value = Math.round(value);
value /= 10 ** config.decimals;
}
let rendered: ReactNode = value;
if (config.localize) {
value = value.toLocaleString(locale);
} else {
value = value.toFixed(config.decimals);
}
if (config.units !== undefined) {
value = literalsArray(strings.units[config.units], {
value: <Text>{value}</Text>,
});
}
return value;
if (config.decimals !== undefined) {
rendered *= 10 ** config.decimals;
rendered = Math.round(rendered);
rendered /= 10 ** config.decimals;
}
return `${characteristic < 0 ? "-" : ""}∞`;
if (config.localize) {
rendered = rendered.toLocaleString(locale);
} else {
rendered = rendered.toFixed(config.decimals);
}
if (units !== undefined) {
rendered = literalsArray(strings.units[units], {
value: <Text>{rendered}</Text>,
});
}
return rendered;
}
if (typeof characteristic === "string") {
return characteristic;
}
switch (characteristics[config.name].type) {
case CharacteristicType.Enum:
return characteristic as string;
throw new Error("Unknown characteristic type");
case CharacteristicType.Number:
return renderNumber(characteristic as number, config.units);
case CharacteristicType.NumberList: {
const values = (characteristic as number[]).map((value, index) => (
<Fragment key={index}>
{index > 0 && ", "}
{renderNumber(value, undefined)}
</Fragment>
));
if (config.units === undefined) return values;
return (
<>
{literalsArray(strings.units[config.units], {
value: <Text>{values}</Text>,
})}
</>
);
}
}
}
return renderCharacteristic;
@@ -1,8 +1,11 @@
import { characteristics as characteristicDefinitions } from "../config/characteristics";
import { characteristicsGroups } from "../config/characteristicsGroups";
import {
CharacteristicRanking as CharacteristicRankingDirection,
CharacteristicType,
type CharacteristicName,
type CharacteristicRenderConfig,
type CharacteristicReturnType,
type ComputedCharacteristics,
} from "../types/characteristics";
@@ -24,6 +27,35 @@ export interface CharacteristicRank {
score: number;
}
function rankingValue(
name: CharacteristicName,
value?: CharacteristicReturnType,
) {
if (value === undefined) return;
switch (characteristicDefinitions[name].type) {
case CharacteristicType.Enum:
return;
case CharacteristicType.Number:
return value as number;
case CharacteristicType.NumberList: {
const values = value as number[];
if (values.length === 0) return;
let total = 0;
for (const current of values) {
total += current;
}
return total / values.length;
}
}
}
export function calculateRankings(
characteristics: ComputedCharacteristics,
comparisons: ComputedCharacteristics[],
@@ -31,7 +63,9 @@ export function calculateRankings(
const rankings = new Map<CharacteristicName, CharacteristicRank>();
for (const [name, value] of characteristics) {
if (typeof value !== "number" || name[0] === "_") continue;
const currentValue = rankingValue(name, value);
if (currentValue === undefined || name[0] === "_") continue;
const config = characteristicConfigs.get(name)!;
@@ -41,13 +75,13 @@ export function calculateRankings(
config.ranking === CharacteristicRankingDirection.LowerIsBetter;
const values = comparisons
.map((comparison) => comparison.get(name))
.filter((other) => typeof other === "number");
.map((comparison) => rankingValue(name, comparison.get(name)))
.filter((other) => other !== undefined);
if (values.length === 0) continue;
const betterCount = values.filter((other) =>
lowerIsBetter ? other < value : other > value,
lowerIsBetter ? other < currentValue : other > currentValue,
).length;
rankings.set(name, {
@@ -27,6 +27,10 @@ export type Characteristic = {
type: CharacteristicType.Number;
compute(context: CharacteristicContext): number;
}
| {
type: CharacteristicType.NumberList;
compute(context: CharacteristicContext): number[];
}
);
export type CharacteristicScript = (
@@ -63,6 +67,7 @@ export type CrewStatRole = "commander" | "loader" | "gunner" | "driver";
export enum CharacteristicType {
Enum,
Number,
NumberList,
}
export enum CharacteristicRanking {