forked from phenom/healer-man
54 lines
2.1 KiB
TypeScript
54 lines
2.1 KiB
TypeScript
import { isRomClassId, type ClassId, type RomClassId } from "../app/characterCatalog";
|
|
import catalog from "./romPlayerCatalog.generated.json";
|
|
|
|
type SourceStatName = "strength" | "stamina" | "intellect" | "wisdom" | "agility" | "health" | "mana";
|
|
interface GrowthRow { readonly levelOne: number; readonly flatGrowth: number; readonly percentGrowth: number }
|
|
type GrowthTable = Readonly<Record<RomClassId, Readonly<Record<SourceStatName, GrowthRow>>>>;
|
|
|
|
const GROWTH = catalog.baseStatGrowth as unknown as GrowthTable;
|
|
|
|
function sourceValue(row: GrowthRow, level: number): number {
|
|
const safeLevel = Math.max(1, Math.min(80, Math.trunc(level)));
|
|
let value = row.levelOne;
|
|
for (let current = 2; current <= safeLevel; current += 1) value = value * (1 + row.percentGrowth) + row.flatGrowth;
|
|
return Math.max(0, value);
|
|
}
|
|
|
|
export interface RomNativeBaseStats {
|
|
readonly strength: number;
|
|
readonly stamina: number;
|
|
readonly intellect: number;
|
|
readonly wisdom: number;
|
|
readonly agility: number;
|
|
readonly health: number;
|
|
readonly mana: number;
|
|
}
|
|
|
|
export function romNativeClassBaseStats(classId: RomClassId, level: number): RomNativeBaseStats {
|
|
const rows = GROWTH[classId];
|
|
return Object.freeze({
|
|
strength: sourceValue(rows.strength, level),
|
|
stamina: sourceValue(rows.stamina, level),
|
|
intellect: sourceValue(rows.intellect, level),
|
|
wisdom: sourceValue(rows.wisdom, level),
|
|
agility: sourceValue(rows.agility, level),
|
|
health: sourceValue(rows.health, level),
|
|
mana: sourceValue(rows.mana, level),
|
|
});
|
|
}
|
|
|
|
export function romDualClassBaseStats(
|
|
primaryClassId: ClassId,
|
|
secondaryClassId: ClassId | null | undefined,
|
|
level: number,
|
|
): RomNativeBaseStats | null {
|
|
if (!isRomClassId(primaryClassId)) return null;
|
|
const primary = romNativeClassBaseStats(primaryClassId, level);
|
|
if (!secondaryClassId || !isRomClassId(secondaryClassId)) return primary;
|
|
const secondary = romNativeClassBaseStats(secondaryClassId, level);
|
|
return Object.freeze(Object.fromEntries(Object.keys(primary).map((key) => [
|
|
key,
|
|
primary[key as keyof RomNativeBaseStats] + secondary[key as keyof RomNativeBaseStats] * .1,
|
|
])) as unknown as RomNativeBaseStats);
|
|
}
|