bitburner-src/src/Hacknet/HacknetNode.ts

139 lines
4.3 KiB
TypeScript
Raw Normal View History

2019-03-25 04:03:24 +01:00
/**
* Hacknet Node Class
*
* Hacknet Nodes are specialized machines that passively earn the player money over time.
* They can be upgraded to increase their production
*/
import { IHacknetNode } from "./IHacknetNode";
import { CONSTANTS } from "../Constants";
import {
2021-09-05 01:09:30 +02:00
calculateMoneyGainRate,
calculateLevelUpgradeCost,
calculateCoreUpgradeCost,
calculateRamUpgradeCost,
} from "./formulas/HacknetNodes";
import { HacknetNodeConstants } from "./data/Constants";
2019-03-25 04:03:24 +01:00
2021-09-25 20:42:57 +02:00
import { dialogBoxCreate } from "../ui/React/DialogBox";
2022-07-15 01:00:10 +02:00
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
2022-01-09 20:58:12 +01:00
import { ObjectValidator, minMax } from "../utils/Validator";
2019-03-25 04:03:24 +01:00
export class HacknetNode implements IHacknetNode {
static validationData: ObjectValidator<HacknetNode> = {
2022-01-09 20:58:12 +01:00
cores: minMax(1, 1, HacknetNodeConstants.MaxCores),
level: minMax(1, 1, HacknetNodeConstants.MaxLevel),
ram: minMax(1, 1, HacknetNodeConstants.MaxRam),
onlineTimeSeconds: minMax(0, 0, Infinity),
2022-04-07 01:30:08 +02:00
totalMoneyGenerated: minMax(0, 0, Infinity),
};
2021-09-05 01:09:30 +02:00
// Node's number of cores
cores = 1;
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// Node's Level
level = 1;
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// Node's production per second
moneyGainRatePerSecond = 0;
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// Identifier for Node. Includes the full "name" (hacknet-node-N)
name: string;
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// How long this Node has existed, in seconds
onlineTimeSeconds = 0;
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// Node's RAM (GB)
ram = 1;
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// Total money earned by this Node
totalMoneyGenerated = 0;
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
constructor(name = "", prodMult = 1) {
this.name = name;
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
this.updateMoneyGainRate(prodMult);
}
2021-09-05 01:09:30 +02:00
// Get the cost to upgrade this Node's number of cores
calculateCoreUpgradeCost(levels = 1, costMult: number): number {
return calculateCoreUpgradeCost(this.cores, levels, costMult);
}
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// Get the cost to upgrade this Node's level
calculateLevelUpgradeCost(levels = 1, costMult: number): number {
return calculateLevelUpgradeCost(this.level, levels, costMult);
}
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// Get the cost to upgrade this Node's RAM
calculateRamUpgradeCost(levels = 1, costMult: number): number {
return calculateRamUpgradeCost(this.ram, levels, costMult);
}
2019-03-25 04:03:24 +01:00
2021-09-05 01:09:30 +02:00
// Process this Hacknet Node in the game loop.
// Returns the amount of money generated
process(numCycles = 1): number {
const seconds = (numCycles * CONSTANTS.MilliPerCycle) / 1000;
let gain = this.moneyGainRatePerSecond * seconds;
if (isNaN(gain)) {
console.error(`Hacknet Node ${this.name} calculated earnings of NaN`);
gain = 0;
2019-03-25 04:03:24 +01:00
}
2021-09-05 01:09:30 +02:00
this.totalMoneyGenerated += gain;
this.onlineTimeSeconds += seconds;
return gain;
}
// Upgrade this Node's number of cores, if possible
// Returns a boolean indicating whether new cores were successfully bought
upgradeCore(levels = 1, prodMult: number): void {
2021-09-09 05:47:34 +02:00
this.cores = Math.min(HacknetNodeConstants.MaxCores, Math.round(this.cores + levels));
2021-09-05 01:09:30 +02:00
this.updateMoneyGainRate(prodMult);
}
// Upgrade this Node's level, if possible
// Returns a boolean indicating whether the level was successfully updated
upgradeLevel(levels = 1, prodMult: number): void {
2021-09-09 05:47:34 +02:00
this.level = Math.min(HacknetNodeConstants.MaxLevel, Math.round(this.level + levels));
2021-09-05 01:09:30 +02:00
this.updateMoneyGainRate(prodMult);
}
// Upgrade this Node's RAM, if possible
// Returns a boolean indicating whether the RAM was successfully upgraded
upgradeRam(levels = 1, prodMult: number): void {
for (let i = 0; i < levels; ++i) {
this.ram *= 2; // Ram is always doubled
2019-03-25 04:03:24 +01:00
}
2021-09-05 01:09:30 +02:00
this.ram = Math.round(this.ram); // Handle any floating point precision issues
this.updateMoneyGainRate(prodMult);
}
// Re-calculate this Node's production and update the moneyGainRatePerSecond prop
updateMoneyGainRate(prodMult: number): void {
2021-09-09 05:47:34 +02:00
this.moneyGainRatePerSecond = calculateMoneyGainRate(this.level, this.ram, this.cores, prodMult);
2021-09-05 01:09:30 +02:00
if (isNaN(this.moneyGainRatePerSecond)) {
this.moneyGainRatePerSecond = 0;
dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer");
2021-05-01 09:17:31 +02:00
}
2021-09-05 01:09:30 +02:00
}
/**
* Serialize the current object to a JSON save state.
*/
2022-07-15 01:00:10 +02:00
toJSON(): IReviverValue {
2021-09-05 01:09:30 +02:00
return Generic_toJSON("HacknetNode", this);
}
/**
* Initiatizes a HacknetNode object from a JSON save state.
*/
2022-07-15 01:00:10 +02:00
static fromJSON(value: IReviverValue): HacknetNode {
2021-09-05 01:09:30 +02:00
return Generic_fromJSON(HacknetNode, value.data);
}
2019-03-25 04:03:24 +01:00
}
Reviver.constructors.HacknetNode = HacknetNode;