mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-22 23:53:48 +01:00
77 lines
2.9 KiB
TypeScript
77 lines
2.9 KiB
TypeScript
import type { BladeMultName, BladeSkillName } from "@enums";
|
|
|
|
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
|
|
import { Bladeburner } from "./Bladeburner";
|
|
import { Availability } from "./Types";
|
|
import { PositiveInteger, PositiveSafeInteger, isPositiveInteger } from "../types";
|
|
import { PartialRecord, getRecordEntries } from "../Types/Record";
|
|
|
|
interface SkillParams {
|
|
name: BladeSkillName;
|
|
desc: string;
|
|
baseCost?: number;
|
|
costInc?: number;
|
|
maxLvl?: number;
|
|
mults: PartialRecord<BladeMultName, number>;
|
|
}
|
|
|
|
export class Skill {
|
|
name: BladeSkillName;
|
|
desc: string;
|
|
// Cost is in Skill Points
|
|
baseCost: number;
|
|
// Additive cost increase per level
|
|
costInc: number;
|
|
maxLvl: number;
|
|
mults: PartialRecord<BladeMultName, number> = {};
|
|
|
|
constructor(params: SkillParams) {
|
|
this.name = params.name;
|
|
this.desc = params.desc;
|
|
this.baseCost = params.baseCost ?? 1;
|
|
this.costInc = params.costInc ?? 1;
|
|
this.maxLvl = params.maxLvl ?? Number.MAX_SAFE_INTEGER;
|
|
for (const [multName, mult] of getRecordEntries(params.mults)) this.mults[multName] = mult;
|
|
}
|
|
|
|
calculateCost(currentLevel: number, count = 1 as PositiveInteger): number {
|
|
if (currentLevel + count > this.maxLvl) return Infinity;
|
|
|
|
const recursiveMode = (currentLevel: number, count: PositiveSafeInteger): number => {
|
|
if (count <= 1) {
|
|
return Math.floor((this.baseCost + currentLevel * this.costInc) * currentNodeMults.BladeburnerSkillCost);
|
|
} else {
|
|
const thisUpgrade = Math.floor(
|
|
(this.baseCost + currentLevel * this.costInc) * currentNodeMults.BladeburnerSkillCost,
|
|
);
|
|
return this.calculateCost(currentLevel + 1, (count - 1) as PositiveSafeInteger) + thisUpgrade;
|
|
}
|
|
};
|
|
|
|
// Use recursive mode if count is small
|
|
if (count <= 100) return recursiveMode(currentLevel, count as PositiveSafeInteger);
|
|
// Use optimized mode if count is large
|
|
else {
|
|
//unFloored is roughly equivalent to
|
|
//(this.baseCost + currentLevel * this.costInc) * BitNodeMultipliers.BladeburnerSkillCost
|
|
//being repeated for increasing currentLevel
|
|
const preMult = (count * (2 * this.baseCost + this.costInc * (2 * currentLevel + count + 1))) / 2;
|
|
const unFloored = preMult * currentNodeMults.BladeburnerSkillCost - count / 2;
|
|
return Math.floor(unFloored);
|
|
}
|
|
}
|
|
|
|
canUpgrade(bladeburner: Bladeburner, count = 1): Availability<{ cost: number }> {
|
|
const currentLevel = bladeburner.skills[this.name] ?? 0;
|
|
if (!isPositiveInteger(count)) return { error: `Invalid upgrade count ${count}` };
|
|
if (currentLevel + count > this.maxLvl) return { error: `Upgraded level ${currentLevel + count} exceeds max` };
|
|
const cost = this.calculateCost(currentLevel, count);
|
|
if (cost > bladeburner.skillPoints) return { error: `Insufficient skill points for upgrade` };
|
|
return { available: true, cost };
|
|
}
|
|
|
|
getMultiplier(name: BladeMultName): number {
|
|
return this.mults[name] ?? 0;
|
|
}
|
|
}
|