/** * This is a central class for storing and managing the player's hashes, * which are generated by Hacknet Servers * * It is also used to keep track of what upgrades the player has bought with * his hashes, and contains method for grabbing the data/multipliers from * those upgrades */ import { HashUpgrades } from "./HashUpgrades"; import { HashUpgrade } from "./HashUpgrade"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; export class HashManager { // Max number of hashes this can hold. Equal to the sum of capacities of // all Hacknet Servers capacity = 0; // Number of hashes currently in storage hashes = 0; // Map of Hash Upgrade Name -> levels in that upgrade upgrades: Record = {}; constructor() { for (const name of Object.keys(HashUpgrades)) { this.upgrades[name] = 0; } } /** * Generic helper function for getting a multiplier from a HashUpgrade */ getMult(upgName: string): number { const upg = HashUpgrades[upgName]; const currLevel = this.upgrades[upgName]; if (upg == null || currLevel == null) { console.error(`Could not find Hash Study upgrade`); return 1; } return 1 + (upg.value * currLevel) / 100; } /** * One of the Hash upgrades improves studying. This returns that multiplier */ getStudyMult(): number { const upgName = "Improve Studying"; return this.getMult(upgName); } /** * One of the Hash upgrades improves gym training. This returns that multiplier */ getTrainingMult(): number { const upgName = "Improve Gym Training"; return this.getMult(upgName); } getUpgrade(upgName: string): HashUpgrade | null { const upg = HashUpgrades[upgName]; if (!upg) { console.error(`Invalid Upgrade Name given to HashManager.getUpgrade(): ${upgName}`); return null; } return upg; } /** * Get the cost (in hashes) of an upgrade */ getUpgradeCost(upgName: string, count = 1): number { const upg = this.getUpgrade(upgName); const currLevel = this.upgrades[upgName]; if (upg == null || currLevel == null) { console.error(`Invalid Upgrade Name given to HashManager.getUpgradeCost(): ${upgName}`); return Infinity; } return upg.getCost(currLevel, count); } prestige(): void { for (const name of Object.keys(HashUpgrades)) { this.upgrades[name] = 0; } this.hashes = 0; // When prestiging, player's hacknet nodes are always reset. So capacity = 0 this.updateCapacity(0); } /** * Reverts an upgrade and refunds the hashes used to buy it */ refundUpgrade(upgName: string, count = 1): void { const upg = HashUpgrades[upgName]; // Reduce the level first, so we get the right cost this.upgrades[upgName] -= count; const currLevel = this.upgrades[upgName]; if (upg == null || currLevel == null || currLevel < 0) { console.error(`Invalid Upgrade Name given to HashManager.upgrade(): ${upgName}`); return; } const cost = upg.getCost(currLevel, count); this.hashes += cost; } /** * Stores the given hashes, capping at capacity * @param numHashes The number of hashes to increment * @returns The number of wasted hashes (over capacity) */ storeHashes(numHashes: number): number { this.hashes += numHashes; let wastedHashes = this.hashes; this.hashes = Math.min(this.hashes, this.capacity); wastedHashes -= this.hashes; return wastedHashes; } updateCapacity(newCap: number): void { if (newCap < 0) { this.capacity = 0; } this.capacity = Math.max(newCap, 0); } /** * Returns boolean indicating whether or not the upgrade was successfully purchased * Note that this does NOT actually implement the effect */ upgrade(upgName: string, count = 1): boolean { const upg = HashUpgrades[upgName]; if (upg == null) { console.error(`Invalid Upgrade Name given to HashManager.upgrade(): ${upgName}`); return false; } const cost = this.getUpgradeCost(upgName, count); if (this.hashes < cost) { return false; } this.hashes -= cost; this.upgrades[upgName] += count; return true; } //Serialize the current object to a JSON save state. toJSON(): IReviverValue { return Generic_toJSON("HashManager", this); } // Initiatizes a HashManager object from a JSON save state. static fromJSON(value: IReviverValue): HashManager { return Generic_fromJSON(HashManager, value.data); } } Reviver.constructors.HashManager = HashManager;