From 18a3f061b4c3271520b90888d83a5b48a771b027 Mon Sep 17 00:00:00 2001 From: danielyxie Date: Fri, 29 Mar 2019 16:14:32 -0700 Subject: [PATCH] Rebalanced new Hacknet Node mechanics. Adjusted Hacknet API so that it'll work with hacknet Servers. Fixed Corporation bug with Issuing new Shares --- src/BitNode/BitNode.ts | 32 +++--- src/Constants.ts | 1 + .../ui/CorporationUIEventHandler.js | 1 + src/Hacking/README.md | 1 + src/Hacking/netscriptCanHack.ts | 53 +++++++++ src/Hacknet/HacknetHelpers.jsx | 20 +++- src/Hacknet/HacknetServer.ts | 7 +- src/Hacknet/HashManager.ts | 16 ++- src/Hacknet/data/HashUpgradesMetadata.ts | 32 +++--- src/Hacknet/ui/HashUpgradePopup.jsx | 31 +++--- src/NetscriptFunctions.js | 101 ++++++++++++------ src/Player.js | 2 + src/Terminal.js | 17 +-- src/types.ts | 9 ++ 14 files changed, 225 insertions(+), 98 deletions(-) create mode 100644 src/Hacking/README.md create mode 100644 src/Hacking/netscriptCanHack.ts diff --git a/src/BitNode/BitNode.ts b/src/BitNode/BitNode.ts index 8acbe9e5c..5ea5e01f1 100644 --- a/src/BitNode/BitNode.ts +++ b/src/BitNode/BitNode.ts @@ -350,21 +350,23 @@ export function initBitNodeMultipliers(p: IPlayer) { BitNodeMultipliers.CodingContractMoney = 0; break; case 9: // Hacktocracy - BitNodeMultipliers.HackingLevelMultiplier = 0.4; - BitNodeMultipliers.StrengthLevelMultiplier = 0.45; - BitNodeMultipliers.DefenseLevelMultiplier = 0.45; - BitNodeMultipliers.DexterityLevelMultiplier = 0.45; - BitNodeMultipliers.AgilityLevelMultiplier = 0.45; - BitNodeMultipliers.CharismaLevelMultiplier = 0.45; - BitNodeMultipliers.PurchasedServerLimit = 0; - BitNodeMultipliers.HomeComputerRamCost = 5; - BitNodeMultipliers.CrimeMoney = 0.5; - BitNodeMultipliers.ScriptHackMoney = 0.1; - BitNodeMultipliers.HackExpGain = 0.1; - BitNodeMultipliers.ServerStartingMoney = 0.1; - BitNodeMultipliers.ServerMaxMoney = 0.1; - BitNodeMultipliers.ServerStartingSecurity = 2.5; - BitNodeMultipliers.CorporationValuation = 0.5; + BitNodeMultipliers.HackingLevelMultiplier = 0.4; + BitNodeMultipliers.StrengthLevelMultiplier = 0.45; + BitNodeMultipliers.DefenseLevelMultiplier = 0.45; + BitNodeMultipliers.DexterityLevelMultiplier = 0.45; + BitNodeMultipliers.AgilityLevelMultiplier = 0.45; + BitNodeMultipliers.CharismaLevelMultiplier = 0.45; + BitNodeMultipliers.PurchasedServerLimit = 0; + BitNodeMultipliers.HomeComputerRamCost = 5; + BitNodeMultipliers.CrimeMoney = 0.5; + BitNodeMultipliers.ScriptHackMoney = 0.1; + BitNodeMultipliers.HackExpGain = 0.1; + BitNodeMultipliers.ServerStartingMoney = 0.1; + BitNodeMultipliers.ServerMaxMoney = 0.1; + BitNodeMultipliers.ServerStartingSecurity = 2.5; + BitNodeMultipliers.CorporationValuation = 0.5; + BitNodeMultipliers.FourSigmaMarketDataCost = 5; + BitNodeMultipliers.FourSigmaMarketDataApiCost = 4; break; case 10: // Digital Carbon BitNodeMultipliers.HackingLevelMultiplier = 0.2; diff --git a/src/Constants.ts b/src/Constants.ts index ae1d9c96f..9ab2c8244 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -285,6 +285,7 @@ export let CONSTANTS: IMap = { * Corporation Changes: ** 'Demand' value of products decreases more slowly ** Bug Fix: Fixed a Corporation issue that broke the Market-TA2 Research + ** Bug Fix: Issuing New Shares now works properly * Bug Fix: Money Statistics tracker was incorrectly recording profits when selling stocks manually * Bug Fix: Fixed an issue with the job requirement tooltip for security jobs diff --git a/src/Corporation/ui/CorporationUIEventHandler.js b/src/Corporation/ui/CorporationUIEventHandler.js index 46dfa16b3..8738966d3 100644 --- a/src/Corporation/ui/CorporationUIEventHandler.js +++ b/src/Corporation/ui/CorporationUIEventHandler.js @@ -31,6 +31,7 @@ import { numeralWrapper } from "../../ui/numeralFormat"; import { dialogBoxCreate } from "../../../utils/DialogBox"; +import { getRandomInt } from "../../../utils/helpers/getRandomInt"; import { KEY } from "../../../utils/helpers/keyCodes"; import { clearSelector } from "../../../utils/uiHelpers/clearSelector"; diff --git a/src/Hacking/README.md b/src/Hacking/README.md new file mode 100644 index 000000000..86be3f14e --- /dev/null +++ b/src/Hacking/README.md @@ -0,0 +1 @@ +Implementation of underlying Hacking mechanics diff --git a/src/Hacking/netscriptCanHack.ts b/src/Hacking/netscriptCanHack.ts new file mode 100644 index 000000000..875fd22f5 --- /dev/null +++ b/src/Hacking/netscriptCanHack.ts @@ -0,0 +1,53 @@ +/** + * Functions used to determine whether the target can be hacked (or grown/weakened). + * Meant to be used for Netscript implementation + * + * The returned status object's message should be used for logging in Netscript + */ +import { IReturnStatus } from "../types"; + +import { HacknetServer } from "../Hacknet/HacknetServer"; +import { IPlayer } from "../PersonObjects/IPlayer"; +import { Server } from "../Server/Server"; + +function baseCheck(server: Server | HacknetServer, fnName: string): IReturnStatus { + if (server instanceof HacknetServer) { + return { + res: false, + msg: `Cannot ${fnName} ${server.hostname} server because it is a Hacknet Node` + } + } + + if (server.hasAdminRights === false) { + return { + res: false, + msg: `Cannot ${fnName} ${server.hostname} server because you do not have root access`, + } + } + + return { res: true } +} + +export function netscriptCanHack(server: Server | HacknetServer, p: IPlayer): IReturnStatus { + const initialCheck = baseCheck(server, "hack"); + if (!initialCheck.res) { return initialCheck; } + + let s = server; + + if (s.requiredHackingSkill > p.hacking_skill) { + return { + res: false, + msg: `Cannot hack ${server.hostname} server because your hacking skill is not high enough`, + } + } + + return { res: true } +} + +export function netscriptCanGrow(server: Server | HacknetServer): IReturnStatus { + return baseCheck(server, "grow"); +} + +export function netscriptCanWeaken(server: Server | HacknetServer): IReturnStatus { + return baseCheck(server, "weaken"); +} diff --git a/src/Hacknet/HacknetHelpers.jsx b/src/Hacknet/HacknetHelpers.jsx index 50d1e5ccd..9a24e3afc 100644 --- a/src/Hacknet/HacknetHelpers.jsx +++ b/src/Hacknet/HacknetHelpers.jsx @@ -54,7 +54,6 @@ export function purchaseHacknet() { return; } } - /* END INTERACTIVE TUTORIAL */ if (hasHacknetServers()) { @@ -396,11 +395,21 @@ export function purchaseHashUpgrade(upgName, upgTarget) { break; } case "Exchange for Bladeburner Rank": { - // This will throw if player doesn't have a corporation + // This will throw if player isnt in Bladeburner try { - for (const division of Player.corporation.divisions) { - division.sciResearch.qty += upg.value; - } + Player.bladeburner.changeRank(upg.value); + } catch(e) { + Player.hashManager.refundUpgrade(upgName); + return false; + } + break; + } + case "Exchange for Bladeburner SP": { + // This will throw if player isn't in Bladeburner + try { + // As long as we don't change `Bladeburner.totalSkillPoints`, this + // shouldn't affect anything else + Player.bladeburner.skillPoints += upg.value; } catch(e) { Player.hashManager.refundUpgrade(upgName); return false; @@ -413,6 +422,7 @@ export function purchaseHashUpgrade(upgName, upgTarget) { } default: console.warn(`Unrecognized upgrade name ${upgName}. Upgrade has no effect`) + Player.hashManager.refundUpgrade(upgName); return false; } diff --git a/src/Hacknet/HacknetServer.ts b/src/Hacknet/HacknetServer.ts index af86618d9..0a353f617 100644 --- a/src/Hacknet/HacknetServer.ts +++ b/src/Hacknet/HacknetServer.ts @@ -327,16 +327,17 @@ export class HacknetServer extends BaseServer implements IHacknetNode { updateHashRate(p: IPlayer): void { const baseGain = HacknetServerHashesPerLevel * this.level; - const coreMultiplier = Math.pow(1.1, this.cores - 1); + const ramMultiplier = Math.pow(1.07, Math.log2(this.maxRam)); + const coreMultiplier = 1 + (this.cores - 1) / 5; const ramRatio = (1 - this.ramUsed / this.maxRam); - const hashRate = baseGain * coreMultiplier * ramRatio; + const hashRate = baseGain * ramMultiplier * coreMultiplier * ramRatio; this.hashRate = hashRate * p.hacknet_node_money_mult * BitNodeMultipliers.HacknetNodeMoney; if (isNaN(this.hashRate)) { this.hashRate = 0; - dialogBoxCreate(`Error calculating Hacknet Server hash production. This is a bug. Please report to game dev`, false); + console.error(`Error calculating Hacknet Server hash production. This is a bug. Please report to game dev`, false); } } diff --git a/src/Hacknet/HashManager.ts b/src/Hacknet/HashManager.ts index 1f01e7c24..4f6e94413 100644 --- a/src/Hacknet/HashManager.ts +++ b/src/Hacknet/HashManager.ts @@ -84,9 +84,14 @@ export class HashManager { return upg.getCost(currLevel); } - storeHashes(numHashes: number): void { - this.hashes += numHashes; - this.hashes = Math.min(this.hashes, this.capacity); + prestige(p: IPlayer): void { + for (const name in HashUpgrades) { + this.upgrades[name] = 0; + } + this.hashes = 0; + if (p != null) { + this.updateCapacity(p); + } } /** @@ -106,6 +111,11 @@ export class HashManager { this.hashes += cost; } + storeHashes(numHashes: number): void { + this.hashes += numHashes; + this.hashes = Math.min(this.hashes, this.capacity); + } + updateCapacity(p: IPlayer): void { if (p.hacknetNodes.length <= 0) { this.capacity = 0; diff --git a/src/Hacknet/data/HashUpgradesMetadata.ts b/src/Hacknet/data/HashUpgradesMetadata.ts index d1904ec35..1ced91216 100644 --- a/src/Hacknet/data/HashUpgradesMetadata.ts +++ b/src/Hacknet/data/HashUpgradesMetadata.ts @@ -3,7 +3,7 @@ import { IConstructorParams } from "../HashUpgrade"; export const HashUpgradesMetadata: IConstructorParams[] = [ { - costPerLevel: 2, + costPerLevel: 1, desc: "Sell hashes for $1m", name: "Sell for Money", value: 1e6, @@ -15,36 +15,36 @@ export const HashUpgradesMetadata: IConstructorParams[] = [ value: 1e9, }, { - costPerLevel: 100, - desc: "Use hashes to decrease the minimum security of a single server by 5%. " + + costPerLevel: 50, + desc: "Use hashes to decrease the minimum security of a single server by 2%. " + "Note that a server's minimum security cannot go below 1.", hasTargetServer: true, name: "Reduce Minimum Security", - value: 0.95, + value: 0.98, }, { - costPerLevel: 100, - desc: "Use hashes to increase the maximum amount of money on a single server by 5%", + costPerLevel: 50, + desc: "Use hashes to increase the maximum amount of money on a single server by 2%", hasTargetServer: true, name: "Increase Maximum Money", - value: 1.05, + value: 1.02, }, { - costPerLevel: 100, - desc: "Use hashes to improve the experience earned when studying at a university. " + + costPerLevel: 50, + desc: "Use hashes to improve the experience earned when studying at a university by 20%. " + "This effect persists until you install Augmentations", name: "Improve Studying", value: 20, // Improves studying by value% }, { - costPerLevel: 100, - desc: "Use hashes to improve the experience earned when training at the gym. This effect " + + costPerLevel: 50, + desc: "Use hashes to improve the experience earned when training at the gym by 20%. This effect " + "persists until you install Augmentations", name: "Improve Gym Training", value: 20, // Improves training by value% }, { - costPerLevel: 250, + costPerLevel: 200, desc: "Exchange hashes for 1k Scientific Research in all of your Corporation's Industries", name: "Exchange for Corporation Research", value: 1000, @@ -56,7 +56,13 @@ export const HashUpgradesMetadata: IConstructorParams[] = [ value: 100, }, { - costPerLevel: 200, + costPerLevel: 250, + desc: "Exchanges hashes for 10 Bladeburner Skill Points", + name: "Exchange for Bladeburner SP", + value: 10, + }, + { + costPerLevel: 150, desc: "Generate a random Coding Contract on your home computer", name: "Generate Coding Contract", value: 1, diff --git a/src/Hacknet/ui/HashUpgradePopup.jsx b/src/Hacknet/ui/HashUpgradePopup.jsx index 720f73a51..5f1591577 100644 --- a/src/Hacknet/ui/HashUpgradePopup.jsx +++ b/src/Hacknet/ui/HashUpgradePopup.jsx @@ -3,21 +3,22 @@ */ import React from "react"; -import { purchaseHashUpgrade } from "../HacknetHelpers"; -import { HashManager } from "../HashManager"; -import { HashUpgrades } from "../HashUpgrades"; +import { purchaseHashUpgrade } from "../HacknetHelpers"; +import { HashManager } from "../HashManager"; +import { HashUpgrades } from "../HashUpgrades"; -import { Player } from "../../Player"; -import { AllServers } from "../../Server/AllServers"; -import { Server } from "../../Server/Server"; +import { Player } from "../../Player"; +import { AllServers } from "../../Server/AllServers"; +import { Server } from "../../Server/Server"; -import { numeralWrapper } from "../../ui/numeralFormat"; +import { numeralWrapper } from "../../ui/numeralFormat"; -import { removePopup } from "../../ui/React/createPopup"; +import { removePopup } from "../../ui/React/createPopup"; +import { PopupCloseButton } from "../../ui/React/PopupCloseButton"; import { ServerDropdown, - ServerType } from "../../ui/React/ServerDropdown" + ServerType } from "../../ui/React/ServerDropdown" -import { dialogBoxCreate } from "../../../utils/DialogBox"; +import { dialogBoxCreate } from "../../../utils/DialogBox"; class HashUpgrade extends React.Component { constructor(props) { @@ -85,8 +86,6 @@ export class HashUpgradePopup extends React.Component { constructor(props) { super(props); - this.closePopup = this.closePopup.bind(this); - this.state = { totalHashes: Player.hashManager.hashes, } @@ -100,10 +99,6 @@ export class HashUpgradePopup extends React.Component { clearInterval(this.interval); } - closePopup() { - removePopup(this.props.popupId); - } - tick() { this.setState({ totalHashes: Player.hashManager.hashes, @@ -125,9 +120,7 @@ export class HashUpgradePopup extends React.Component { return (
- +

Spend your hashes on a variety of different upgrades

Hashes: {numeralWrapper.formatBigNumber(this.state.totalHashes)}

{upgradeElems} diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index fa9dbaef1..b6d5fa3da 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -29,7 +29,12 @@ import { Factions, import { joinFaction, purchaseAugmentation } from "./Faction/FactionHelpers"; import { FactionWorkType } from "./Faction/FactionWorkTypeEnum"; +import { netscriptCanGrow, + netscriptCanHack, + netscriptCanWeaken } from "./Hacking/netscriptCanHack"; import { getCostOfNextHacknetNode, + getCostOfNextHacknetServer, + hasHacknetServers, purchaseHacknet } from "./Hacknet/HacknetNode"; import {Locations} from "./Locations"; import { Message } from "./Message/Message"; @@ -194,11 +199,11 @@ function initSingularitySFFlags() { } function NetscriptFunctions(workerScript) { - var updateDynamicRam = function(fnName, ramCost) { + const updateDynamicRam = function(fnName, ramCost) { if (workerScript.dynamicLoadedFns[fnName]) {return;} workerScript.dynamicLoadedFns[fnName] = true; - const threads = workerScript.scriptRef.threads; + let threads = workerScript.scriptRef.threads; if (typeof threads !== 'number') { console.warn(`WorkerScript detected NaN for threadcount for ${workerScript.name} on ${workerScript.serverIp}`); threads = 1; @@ -215,7 +220,7 @@ function NetscriptFunctions(workerScript) { } }; - var updateStaticRam = function(fnName, ramCost) { + const updateStaticRam = function(fnName, ramCost) { if (workerScript.loadedFns[fnName]) { return 0; } else { @@ -230,7 +235,7 @@ function NetscriptFunctions(workerScript) { * @param {string} Hostname or IP of the server * @returns {Server} The specified Server */ - var safeGetServer = function(ip, callingFnName="") { + const safeGetServer = function(ip, callingFnName="") { var server = getServer(ip); if (server == null) { throw makeRuntimeRejectMsg(workerScript, `Invalid IP or hostname passed into ${callingFnName}() function`); @@ -239,17 +244,27 @@ function NetscriptFunctions(workerScript) { } // Utility function to get Hacknet Node object - var getHacknetNode = function(i) { + const getHacknetNode = function(i) { if (isNaN(i)) { throw makeRuntimeRejectMsg(workerScript, "Invalid index specified for Hacknet Node: " + i); } if (i < 0 || i >= Player.hacknetNodes.length) { throw makeRuntimeRejectMsg(workerScript, "Index specified for Hacknet Node is out-of-bounds: " + i); } - return Player.hacknetNodes[i]; + + if (hasHacknetServers()) { + const hserver = AllServers[Player.hacknetNodes[i]]; + if (hserver == null) { + throw makeRuntimeRejectMsg(workerScript, `Could not get Hacknet Server for index ${i}. This is probably a bug, please report to game dev`); + } + + return hserver; + } else { + return Player.hacknetNodes[i]; + } }; - var getCodingContract = function(fn, ip) { + const getCodingContract = function(fn, ip) { var server = safeGetServer(ip, "getCodingContract"); return server.getContract(fn); } @@ -263,43 +278,64 @@ function NetscriptFunctions(workerScript) { return purchaseHacknet(); }, getPurchaseNodeCost : function() { - return getCostOfNextHacknetNode(); + if (hasHacknetServers()) { + return getCostOfNextHacknetServer(); + } else { + return getCostOfNextHacknetNode(); + } }, getNodeStats : function(i) { - var node = getHacknetNode(i); - return { + const node = getHacknetNode(i); + const hasUpgraded = hasHacknetServers(); + const res = { name: node.name, level: node.level, - ram: node.ram, + ram: hasUpgraded ? node.maxRam : node.ram, cores: node.cores, - production: node.moneyGainRatePerSecond, + production: hasUpgraded ? node.hashRate : node.moneyGainRatePerSecond, timeOnline: node.onlineTimeSeconds, - totalProduction: node.totalMoneyGenerated, + totalProduction: hasUpgraded ? node.totalHashesGenerated : node.totalMoneyGenerated, }; + + if (hasUpgraded) { + res.cache = node.cache; + } + + return res; }, upgradeLevel : function(i, n) { - var node = getHacknetNode(i); + const node = getHacknetNode(i); return node.purchaseLevelUpgrade(n, Player); }, upgradeRam : function(i, n) { - var node = getHacknetNode(i); + const node = getHacknetNode(i); return node.purchaseRamUpgrade(n, Player); }, upgradeCore : function(i, n) { - var node = getHacknetNode(i); + const node = getHacknetNode(i); return node.purchaseCoreUpgrade(n, Player); }, + upgradeCache : function(i, n) { + if (!hasHacknetServers()) { return false; } + const node = getHacknetNode(i); + return node.purchaseCacheUpgrade(n, Player); + }, getLevelUpgradeCost : function(i, n) { - var node = getHacknetNode(i); + const node = getHacknetNode(i); return node.calculateLevelUpgradeCost(n, Player); }, getRamUpgradeCost : function(i, n) { - var node = getHacknetNode(i); + const node = getHacknetNode(i); return node.calculateRamUpgradeCost(n, Player); }, getCoreUpgradeCost : function(i, n) { - var node = getHacknetNode(i); + const node = getHacknetNode(i); return node.calculateCoreUpgradeCost(n, Player); + }, + getCacheUpgradeCost : function(i, n) { + if (!hasHacknetServers()) { return Infinity; } + const node = getHacknetNode(i); + return node.calculateCacheUpgradeCost(n); } }, sprintf : sprintf, @@ -351,19 +387,16 @@ function NetscriptFunctions(workerScript) { var hackingTime = calculateHackingTime(server); //This is in seconds //No root access or skill level too low - if (server.hasAdminRights == false) { - workerScript.scriptRef.log("Cannot hack this server (" + server.hostname + ") because user does not have root access"); - throw makeRuntimeRejectMsg(workerScript, "Cannot hack this server (" + server.hostname + ") because user does not have root access"); - } - - if (server.requiredHackingSkill > Player.hacking_skill) { - workerScript.scriptRef.log("Cannot hack this server (" + server.hostname + ") because user's hacking skill is not high enough"); - throw makeRuntimeRejectMsg(workerScript, "Cannot hack this server (" + server.hostname + ") because user's hacking skill is not high enough"); + const canHack = netscriptCanHack(server, Player); + if (!canHack.res) { + workerScript.scriptRef.log(`ERROR: ${canHack.msg}`); + throw makeRuntimeRejectMsg(workerScript, canHack.msg); } if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.hack == null) { workerScript.scriptRef.log("Attempting to hack " + ip + " in " + hackingTime.toFixed(3) + " seconds (t=" + threads + ")"); } + return netscriptDelay(hackingTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} var hackChance = calculateHackingChance(server); @@ -482,9 +515,10 @@ function NetscriptFunctions(workerScript) { } //No root access or skill level too low - if (server.hasAdminRights == false) { - workerScript.scriptRef.log("Cannot grow this server (" + server.hostname + ") because user does not have root access"); - throw makeRuntimeRejectMsg(workerScript, "Cannot grow this server (" + server.hostname + ") because user does not have root access"); + const canHack = netscriptCanGrow(server); + if (!canHack.res) { + workerScript.scriptRef.log(`ERROR: ${canHack.msg}`); + throw makeRuntimeRejectMsg(workerScript, canHack.msg); } var growTime = calculateGrowTime(server); @@ -543,9 +577,10 @@ function NetscriptFunctions(workerScript) { } //No root access or skill level too low - if (server.hasAdminRights == false) { - workerScript.scriptRef.log("Cannot weaken this server (" + server.hostname + ") because user does not have root access"); - throw makeRuntimeRejectMsg(workerScript, "Cannot weaken this server (" + server.hostname + ") because user does not have root access"); + const canHack = netscriptCanWeaken(server); + if (!canHack.res) { + workerScript.scriptRef.log(`ERROR: ${canHack.msg}`); + throw makeRuntimeRejectMsg(workerScript, canHack.msg); } var weakenTime = calculateWeakenTime(server); diff --git a/src/Player.js b/src/Player.js index a42e021fc..6ad8978d2 100644 --- a/src/Player.js +++ b/src/Player.js @@ -331,6 +331,7 @@ PlayerObject.prototype.prestigeAugmentation = function() { this.moneySourceA.reset(); this.hacknetNodes.length = 0; + this.hashManager.prestige(this); //Re-calculate skills and reset HP this.updateSkillLevels(); @@ -420,6 +421,7 @@ PlayerObject.prototype.prestigeSourceFile = function() { this.lastUpdate = new Date().getTime(); this.hacknetNodes.length = 0; + this.hashManager.prestige(this); //Gang this.gang = null; diff --git a/src/Terminal.js b/src/Terminal.js index e41bb5125..f68c6aaa0 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -1246,23 +1246,26 @@ let Terminal = { case "free": Terminal.executeFreeCommand(commandArray); break; - case "hack": - if (commandArray.length !== 1) { + case "hack": { + if (commandArray.length !== 1) { postError("Incorrect usage of hack command. Usage: hack"); return; } //Hack the current PC (usually for money) //You can't hack your home pc or servers you purchased - if (Player.getCurrentServer().purchasedByPlayer) { + if (s.purchasedByPlayer) { postError("Cannot hack your own machines! You are currently connected to your home PC or one of your purchased servers"); - } else if (Player.getCurrentServer().hasAdminRights == false ) { + } else if (s.hasAdminRights == false ) { postError("You do not have admin rights for this machine! Cannot hack"); - } else if (Player.getCurrentServer().requiredHackingSkill > Player.hacking_skill) { + } else if (s.requiredHackingSkill > Player.hacking_skill) { postError("Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill"); - } else { + } else if (s instanceof HacknetServer) { + postError("Cannot hack this type of Server") + } else { Terminal.startHack(); } break; + } case "help": if (commandArray.length !== 1 && commandArray.length !== 2) { postError("Incorrect usage of help command. Usage: help"); @@ -1894,7 +1897,7 @@ let Terminal = { //var dashes = Array(d * 2 + 1).join("-"); var c = "NO"; if (s.hasAdminRights) {c = "YES";} - post(`${dashes}Root Access: ${c} ${!isHacknet ? ", Required hacking skill: " + s.requiredHackingSkill : ""}`); + post(`${dashes}Root Access: ${c}${!isHacknet ? ", Required hacking skill: " + s.requiredHackingSkill : ""}`); if (!isHacknet) { post(dashes + "Number of open ports required to NUKE: " + s.numOpenPortsRequired); } post(dashes + "RAM: " + s.maxRam); post(" "); diff --git a/src/types.ts b/src/types.ts index 1c762fc44..ec1581932 100644 --- a/src/types.ts +++ b/src/types.ts @@ -35,3 +35,12 @@ export interface ISelfLoading { */ load(saveState: string): void; } + +/** + * Status object for functions that return a boolean indicating success/failure + * and an optional message + */ +export interface IReturnStatus { + res: boolean; + msg?: string; +}