From 107977e6f4c3e2c6a47e4c82bcc72a13f616fcfa Mon Sep 17 00:00:00 2001 From: danielyxie Date: Wed, 20 Feb 2019 00:42:27 -0800 Subject: [PATCH] Various bugfixes --- doc/source/basicgameplay/codingcontracts.rst | 13 +++++ .../netscriptsingularityfunctions.rst | 2 + src/Bladeburner.js | 54 ++++++++++++------- src/CinematicText.js | 13 ++--- src/Constants.ts | 6 ++- src/Message.js | 1 - src/Missions.js | 8 ++- src/NetscriptEvaluator.js | 4 +- src/NetscriptFunctions.js | 7 ++- src/NetscriptWorker.js | 5 +- src/Player.js | 14 +++++ src/Prestige.js | 18 +++---- src/RedPill.js | 3 +- src/SaveObject.js | 4 +- src/Script.js | 3 +- src/Terminal.js | 36 ++++++------- src/TextFile.ts | 11 ++-- src/ui/createStatusText.ts | 3 +- src/utils/SetTimeoutRef.ts | 5 ++ 19 files changed, 139 insertions(+), 71 deletions(-) create mode 100644 src/utils/SetTimeoutRef.ts diff --git a/doc/source/basicgameplay/codingcontracts.rst b/doc/source/basicgameplay/codingcontracts.rst index fe8b994fc..f3e2d4004 100644 --- a/doc/source/basicgameplay/codingcontracts.rst +++ b/doc/source/basicgameplay/codingcontracts.rst @@ -208,3 +208,16 @@ The list contains the name of (i.e. the value returned by | | | (a)())() -> ["(a)()()", "(a())()"] | | | | )( -> [""] | +------------------------------------+------------------------------------------------------------------------------------------+ +| Find All Valid Math Expressions | | You are given a string which contains only digits between 0 and 9 as well as a target | +| | | number. Return all possible ways you can add the +, -, and * operators to the string | +| | | of digits such that it evaluates to the target number. | +| | | | +| | | The answer should be provided as an array of strings containing the valid expressions. | +| | | | +| | | Examples: | +| | | Input: digits = "123", target = 6 | +| | | Output: ["1+2+3", "1*2*3"] | +| | | | +| | | Input: digits = "105", target = 5 | +| | | Output: ["1*0+5", "10-5"] | ++------------------------------------+------------------------------------------------------------------------------------------+ diff --git a/doc/source/netscript/netscriptsingularityfunctions.rst b/doc/source/netscript/netscriptsingularityfunctions.rst index 1b07c2ed2..9ba8da067 100644 --- a/doc/source/netscript/netscriptsingularityfunctions.rst +++ b/doc/source/netscript/netscriptsingularityfunctions.rst @@ -167,8 +167,10 @@ getCharacterInformation bitnode: Current BitNode number city: Name of city you are currently in factions: Array of factions you are currently a member of + hp: Current health points jobs: Array of all companies at which you have jobs jobTitle: Array of job positions for all companies you are employed at. Same order as 'jobs' + maxHp: Maximum health points tor: Boolean indicating whether or not you have a tor router // The following is an object with many of the player's multipliers from Augmentations/Source Files diff --git a/src/Bladeburner.js b/src/Bladeburner.js index bf32b5e2f..b7b1ead82 100644 --- a/src/Bladeburner.js +++ b/src/Bladeburner.js @@ -10,6 +10,7 @@ import { Locations } from "./Locations"; import { Player } from "./Player"; import { hackWorldDaemon, redPillFlag } from "./RedPill"; import { numeralWrapper } from "./ui/numeralFormat"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; import { KEY } from "../utils/helpers/keyCodes"; import { createProgressBarText } from "../utils/helpers/createProgressBarText"; @@ -182,7 +183,7 @@ $(document).keydown(function(event) { var prevCommand = consoleHistory[consoleHistoryIndex]; DomElems.consoleInput.value = prevCommand; - setTimeout(function(){DomElems.consoleInput.selectionStart = DomElems.consoleInput.selectionEnd = 10000; }, 0); + setTimeoutRef(function(){DomElems.consoleInput.selectionStart = DomElems.consoleInput.selectionEnd = 10000; }, 0); } if (event.keyCode === KEY.DOWNARROW) { @@ -583,16 +584,17 @@ var GeneralActions = {}; //Training, Field Analysis, Recruitment, etc. //Action Identifier const ActionTypes = Object.freeze({ - "Idle": 1, - "Contract": 2, - "Operation": 3, - "BlackOp": 4, - "BlackOperation": 4, - "Training": 5, - "Recruitment": 6, - "FieldAnalysis": 7, - "Field Analysis": 7, - "Diplomacy": 8, + "Idle": 1, + "Contract": 2, + "Operation": 3, + "BlackOp": 4, + "BlackOperation": 4, + "Training": 5, + "Recruitment": 6, + "FieldAnalysis": 7, + "Field Analysis": 7, + "Diplomacy": 8, + "Hyperbolic Regeneration Chamber": 9, }); function ActionIdentifier(params={}) { if (params.name) {this.name = params.name;} @@ -1144,16 +1146,18 @@ Bladeburner.prototype.startAction = function(actionId) { exceptionAlert(e); } break; - case ActionTypes["Training"]: - this.actionTimeToComplete = 30; - break; case ActionTypes["Recruitment"]: this.actionTimeToComplete = this.getRecruitmentTime(); break; + case ActionTypes["Training"]: case ActionTypes["FieldAnalysis"]: case ActionTypes["Field Analysis"]: this.actionTimeToComplete = 30; break; + case ActionTypes["Diplomacy"]: + case ActionTypes["Hyperbolic Regeneration Chamber"]: + this.actionTimeToComplete = 60; + break; default: throw new Error("Invalid Action Type in Bladeburner.startAction(): " + actionId.type); break; @@ -1399,12 +1403,19 @@ Bladeburner.prototype.completeAction = function() { var eff = this.getDiplomacyEffectiveness(); console.log(`Diplomacy Effectiveness: ${eff}`); this.getCurrentCity().chaos *= eff; + if (this.getCurrentCity().chaos < 0) { this.getCurrentCity().chaos = 0; } if (this.logging.general) { this.log(`Diplomacy completed. Chaos levels in the current city fell by ${numeralWrapper.formatPercentage(1 - eff)}`); } this.startAction(this.action); // Repeat Action break; + case ActionTypes["Hyperbolic Regeneration Chamber"]: + Player.regenerateHp(1); + this.stamina += 0.05; // TODO Turn this into a const and adjust value + this.startAction(this.action); + break; default: + console.error(`Bladeburner.completeAction() called for invalid action: ${this.action.type}`); break; } } @@ -3840,13 +3851,13 @@ function initBladeburner() { Skills[SkillNames.Overclock] = new Skill({ name:SkillNames.Overclock, desc:"Each level of this skill decreases the time it takes " + - "to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 95)", + "to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 90)", baseCost: 3, costInc: 1.2, maxLvl: 90, actionTime:1 }); Skills[SkillNames.Reaper] = new Skill({ name: SkillNames.Reaper, - desc: "Each level of this skill increases your effective combat stats for Bladeburner actions by 3%", + desc: "Each level of this skill increases your effective combat stats for Bladeburner actions by 2%", baseCost:3, costInc: 2.1, effStr: 2, effDef: 2, effDex: 2, effAgi: 2 }); @@ -3882,7 +3893,7 @@ function initBladeburner() { name: SkillNames.Hyperdrive, desc: "Each level of this skill increases the experience earned from Contracts, Operations, and BlackOps by 5%", baseCost: 1, costInc: 3, - expGain: 4, + expGain: 5, }); //General Actions @@ -3919,7 +3930,14 @@ function initBladeburner() { desc: "Improve diplomatic relations with the Synthoid population. " + "Completing this action will reduce the Chaos level in your current city.

" + "Does NOT require stamina." - }) + }); + + actionName = "Hyperbolic Regeneration Chamber"; + GeneralActions[actionName] = new Action({ + name: actionName, + desc: "Enter cryogenic stasis using the Bladeburner division's hi-tech Regeneration Chamber. " + + "This will slowly heal your wounds and slightly increase your stamina gain.

", + }); //Black Operations BlackOperations["Operation Typhoon"] = new BlackOperation({ diff --git a/src/CinematicText.js b/src/CinematicText.js index 9d6f433f4..32bf59bde 100644 --- a/src/CinematicText.js +++ b/src/CinematicText.js @@ -1,9 +1,10 @@ -import {Engine} from "./engine"; +import {Engine} from "./engine"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; -import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement"; -import {createElement} from "../utils/uiHelpers/createElement"; -import {exceptionAlert} from "../utils/helpers/exceptionAlert"; -import {isString} from "../utils/helpers/isString"; +import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement"; +import {createElement} from "../utils/uiHelpers/createElement"; +import {exceptionAlert} from "../utils/helpers/exceptionAlert"; +import {isString} from "../utils/helpers/isString"; var cinematicTextFlag = false; @@ -59,7 +60,7 @@ function writeCinematicTextLine(line) { function writeCinematicTextLetter(pElem, line, i=0) { return new Promise(function(resolve, reject) { - setTimeout(function() { + setTimeoutRef(function() { if (i >= line.length) { var textToShow = line.substring(0, i); pElem.innerHTML = textToShow; diff --git a/src/Constants.ts b/src/Constants.ts index 1fe1d118e..52677f181 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -517,7 +517,7 @@ export let CONSTANTS: IMap = { ** Increased the effect of the "Hyperdrive" skill ** Slightly increased the rate which the skill point cost rises for almost all skills ** The "Overlock" Skill now has a maximum level of 90 instead of 95 - ** Added a new General Action: Diplomacy + ** Added two new General Actions: Diplomacy and Hyperbolic Regeneration Chamber ** Lowered the rep cost of the "Blade's Simulacrum" augmentation, but increased the price * Added new BitNode multipliers: @@ -530,6 +530,10 @@ export let CONSTANTS: IMap = { * 'The Covenant' now requires 20 total Augmentations to get invited, rather than 30 * You can now purchase permanent Duplicate Sleeves from 'The Covenant'. This requires Source-File 10, and you must be in BN-10 or after * Increased the money gained from Coding Contracts by 50% + * getCharacterInformation() function now returns the player's HP and max HP + * Bug Fix: You can no longer disconnect the enemy's connections in Hacking Missions + * Bug Fix: After installing Augmentations, the Terminal display will now correctly show the current server as "home" + * Bug Fix: Fixed an exploit where you could change the duration of timed functions (e.g. hack, weaken) in NetscriptJS ` } diff --git a/src/Message.js b/src/Message.js index 6022f51d5..7ebee10fa 100644 --- a/src/Message.js +++ b/src/Message.js @@ -32,7 +32,6 @@ Reviver.constructors.Message = Message; //Sends message to player, including a pop up function sendMessage(msg, forced=false) { - console.log("sending message: " + msg.filename); msg.recvd = true; if (forced || !Settings.SuppressMessages) { showMessage(msg); diff --git a/src/Missions.js b/src/Missions.js index 67f3e4f5c..17b2d9378 100644 --- a/src/Missions.js +++ b/src/Missions.js @@ -1021,13 +1021,17 @@ HackingMission.prototype.initJsPlumb = function() { } //Clicking a connection drops it - instance.bind("click", function(conn, originalEvent) { + instance.bind("click", (conn, originalEvent) => { + // Cannot drop enemy's connections + const sourceNode = this.getNodeFromElement(conn.source); + if (sourceNode.enmyCtrl) { return; } + var endpoints = conn.endpoints; endpoints[0].detachFrom(endpoints[1]); }); //Connection events - instance.bind("connection", (info)=>{ + instance.bind("connection", (info) => { var targetNode = this.getNodeFromElement(info.target); //Do not detach for enemy nodes diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index e86a72169..8e144ac15 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -8,6 +8,8 @@ import { Settings } from "./Settings/Settings"; import { Script, findRunningScript, RunningScript } from "./Script"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; + import {parse, Node} from "../utils/acorn"; import {arrayToString} from "../utils/helpers/arrayToString"; import {isValidIPAddress} from "../utils/helpers/isValidIPAddress"; @@ -134,7 +136,7 @@ export function killNetscriptDelay(workerScript) { export function netscriptDelay(time, workerScript) { return new Promise(function(resolve, reject) { - workerScript.delay = setTimeout(()=>{ + workerScript.delay = setTimeoutRef(() => { workerScript.delay = null; resolve(); }, time); diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 5ff052abc..2e67db7f6 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -55,6 +55,7 @@ import { getStockmarket4SDataCost, getStockMarket4STixApiCost } from "./StockMarket/StockMarketCosts"; import {numeralWrapper} from "./ui/numeralFormat"; import {post} from "./ui/postToTerminal"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; import {TextFile, getTextFile, createTextFile} from "./TextFile"; import {unknownBladeburnerActionErrorMessage, @@ -853,7 +854,7 @@ function NetscriptFunctions(workerScript) { if (scriptname == null || threads == null) { throw makeRuntimeRejectMsg(workerScript, "Invalid scriptname or numThreads argument passed to spawn()"); } - setTimeout(()=>{ + setTimeoutRef(() => { if (scriptname === undefined) { throw makeRuntimeRejectMsg(workerScript, "spawn() call has incorrect number of arguments. Usage: spawn(scriptname, numThreads, [arg1], [arg2]...)"); } @@ -870,7 +871,7 @@ function NetscriptFunctions(workerScript) { } return runScriptFromScript(scriptServer, scriptname, argsForNewScript, workerScript, threads); - }, 20000); + }, 20e3); if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.spawn == null) { workerScript.scriptRef.log("spawn() will execute " + scriptname + " in 20 seconds"); } @@ -2909,8 +2910,10 @@ function NetscriptFunctions(workerScript) { bitnode: Player.bitNodeN, city: Player.city, factions: Player.factions.slice(), + hp: Player.hp, jobs: Object.keys(Player.jobs), jobTitles: Object.values(Player.jobs), + maxHp: Player.max_hp, mult: { agility: Player.agility_mult, agilityExp: Player.agility_exp_mult, diff --git a/src/NetscriptWorker.js b/src/NetscriptWorker.js index 4bc3377d4..936dc82f6 100644 --- a/src/NetscriptWorker.js +++ b/src/NetscriptWorker.js @@ -13,6 +13,7 @@ import {executeJSScript} from "./NetscriptJSEvaluator"; import {NetscriptPort} from "./NetscriptPort"; import {AllServers} from "./Server"; import {Settings} from "./Settings/Settings"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; import {generate} from 'escodegen'; @@ -283,7 +284,7 @@ function startNetscript1Script(workerScript) { if (workerScript.env.stopFlag) { return reject(workerScript); } if (interpreter.step()) { - window.setTimeout(runInterpreter, Settings.CodeInstructionRunTime); + setTimeoutRef(runInterpreter, Settings.CodeInstructionRunTime); } else { resolve(workerScript); } @@ -553,7 +554,7 @@ function runScriptsLoop() { } } - setTimeout(runScriptsLoop, 6000); + setTimeoutRef(runScriptsLoop, 6000); } //Queues a script to be killed by settings its stop flag to true. Then, the code will reject diff --git a/src/Player.js b/src/Player.js index 61cc7abd5..497c921f0 100644 --- a/src/Player.js +++ b/src/Player.js @@ -1690,6 +1690,11 @@ PlayerObject.prototype.singularityStopWork = function() { //Returns true if hospitalized, false otherwise PlayerObject.prototype.takeDamage = function(amt) { + if (typeof amt !== "number") { + console.warn(`Player.takeDamage() called without a numeric argument: ${amt}`); + return; + } + this.hp -= amt; if (this.hp <= 0) { this.hospitalize(); @@ -1699,6 +1704,15 @@ PlayerObject.prototype.takeDamage = function(amt) { } } +PlayerObject.prototype.regenerateHp = function(amt) { + if (typeof amt !== "number") { + console.warn(`Player.regenerateHp() called without a numeric argument: ${amt}`); + return; + } + this.hp += amt; + if (this.hp > this.max_hp) { this.hp = this.max_hp; } +} + PlayerObject.prototype.hospitalize = function() { if (Settings.SuppressHospitalizationPopup === false) { dialogBoxCreate( diff --git a/src/Prestige.js b/src/Prestige.js index bda6724a7..3e46c03f1 100755 --- a/src/Prestige.js +++ b/src/Prestige.js @@ -48,17 +48,21 @@ let BitNode8StartingMoney = 250e6; //Prestige by purchasing augmentation function prestigeAugmentation() { - // Load Terminal Screen - var mainMenu = document.getElementById("mainmenu-container"); - mainMenu.style.visibility = "visible"; - Terminal.resetTerminalInput(); - Engine.loadTerminalContent(); + // Set Navigation to Terminal screen, for any logic that depends on it routing.navigateTo(Page.Terminal); initBitNodeMultipliers(Player); Player.prestigeAugmentation(); + // Now actually go to the Terminal Screen (and reset it) + var mainMenu = document.getElementById("mainmenu-container"); + mainMenu.style.visibility = "visible"; + Terminal.resetTerminalInput(); + Engine.loadTerminalContent(); + $("#terminal tr:not(:last)").remove(); + postNetburnerText(); + //Delete all Worker Scripts objects prestigeWorkerScripts(); @@ -116,10 +120,6 @@ function prestigeAugmentation() { Player.reapplyAllSourceFiles(); initCompanies(); - //Clear terminal - $("#terminal tr:not(:last)").remove(); - postNetburnerText(); - //Messages initMessages(); diff --git a/src/RedPill.js b/src/RedPill.js index 0f03fd86f..43a913c90 100644 --- a/src/RedPill.js +++ b/src/RedPill.js @@ -6,6 +6,7 @@ import { SourceFiles, SourceFile } from "./SourceFile"; import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile"; import { Terminal } from "./Terminal"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners"; import {dialogBoxCreate} from "../utils/DialogBox"; @@ -34,7 +35,7 @@ function writeRedPillLine(line) { function writeRedPillLetter(pElem, line, i=0) { return new Promise(function(resolve, reject) { - setTimeout(function() { + setTimeoutRef(function() { if (i >= line.length) { var textToShow = line.substring(0, i); pElem.innerHTML = "> " + textToShow; diff --git a/src/SaveObject.js b/src/SaveObject.js index b48514899..69492e264 100755 --- a/src/SaveObject.js +++ b/src/SaveObject.js @@ -17,6 +17,8 @@ import {AllServers, loadAllServers} from "./Server"; import {Settings} from "./Settings/Settings"; import {loadSpecialServerIps, SpecialServerIps} from "./SpecialServerIps"; import {loadStockMarket, StockMarket} from "./StockMarket/StockMarket"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; + import {dialogBoxCreate} from "../utils/DialogBox"; import {gameOptionsBoxClose} from "../utils/GameOptions"; import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners"; @@ -546,7 +548,7 @@ BitburnerSaveObject.prototype.exportGame = function() { a.download = "bitburnerSave.json"; document.body.appendChild(a); a.click(); - setTimeout(function() { + setTimeoutRef(function() { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 0); diff --git a/src/Script.js b/src/Script.js index 5bf56a1e2..fe511aad8 100755 --- a/src/Script.js +++ b/src/Script.js @@ -20,6 +20,7 @@ import {TextFile} from "./TextFile"; import {parse, Node} from "../utils/acorn"; import {Page, routing} from "./ui/navigationTracking"; import {numeralWrapper} from "./ui/numeralFormat"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; import {dialogBoxCreate} from "../utils/DialogBox"; import {Reviver, Generic_toJSON, Generic_fromJSON} from "../utils/JSONReviver"; @@ -758,7 +759,7 @@ Script.prototype.download = function() { a.download = filename; document.body.appendChild(a); a.click(); - setTimeout(function() { + setTimeoutRef(function() { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 0); diff --git a/src/Terminal.js b/src/Terminal.js index 1facae0a4..1f8c8994f 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -35,6 +35,7 @@ import {Settings} from "./Settings/Settings"; import {SpecialServerIps, SpecialServerNames} from "./SpecialServerIps"; import {getTextFile} from "./TextFile"; +import { setTimeoutRef } from "./utils/SetTimeoutRef"; import {containsAllStrings, longestCommonStart} from "../utils/StringHelperFunctions"; import {Page, routing} from "./ui/navigationTracking"; @@ -128,7 +129,7 @@ $(document).keydown(function(event) { } var prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex]; terminalInput.value = prevCommand; - setTimeout(function(){terminalInput.selectionStart = terminalInput.selectionEnd = 10000; }, 0); + setTimeoutRef(function(){terminalInput.selectionStart = terminalInput.selectionEnd = 10000; }, 0); } if (event.keyCode === KEY.DOWNARROW || @@ -1405,7 +1406,7 @@ let Terminal = { } else if (executableName.endsWith(".cct")) { Terminal.runContract(executableName); } else { - Terminal.runProgram(executableName); + Terminal.runProgram(commandArray); } } break; @@ -1993,30 +1994,27 @@ let Terminal = { //First called when the "run [program]" command is called. Checks to see if you //have the executable and, if you do, calls the executeProgram() function - runProgram: function(programName) { - //Check if you have the program on your computer. If you do, execute it, otherwise - //display an error message - var splitArgs = programName.split(" "); - var name = " "; - if (splitArgs.length > 1) { - name = splitArgs[0]; - } else { - name = programName; - } - if (Player.hasProgram(name)) { - Terminal.executeProgram(programName); + runProgram: function(commandArray) { + if (commandArray.length < 2) { return; } + + // Check if you have the program on your computer. If you do, execute it, otherwise + // display an error message + const programName = commandArray[1]; + + if (Player.hasProgram(programName)) { + Terminal.executeProgram(commandArray); return; } post("ERROR: No such executable on home computer (Only programs that exist on your home computer can be run)"); }, //Contains the implementations of all possible programs - executeProgram: function(programName) { + executeProgram: function(commandArray) { + if (commandArray.length < 2) { return; } + var s = Player.getCurrentServer(); - var splitArgs = programName.split(" "); - if (splitArgs.length > 1) { - programName = splitArgs[0]; - } + const programName = commandArray[1]; + const splitArgs = commandArray.slice(1); // TODO: refactor this/these out of Terminal. This logic could reside closer to the Programs themselves. /** diff --git a/src/TextFile.ts b/src/TextFile.ts index 99b685c93..74254fff2 100644 --- a/src/TextFile.ts +++ b/src/TextFile.ts @@ -1,3 +1,4 @@ +import { setTimeoutRef } from "./utils/SetTimeoutRef"; import { dialogBoxCreate } from "../utils/DialogBox"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver"; @@ -52,12 +53,10 @@ export class TextFile { a.download = this.fn; document.body.appendChild(a); a.click(); - setTimeout( - () => { - document.body.removeChild(a); - window.URL.revokeObjectURL(url); - }, - 0); + setTimeoutRef(() => { + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + }, 0); } } diff --git a/src/ui/createStatusText.ts b/src/ui/createStatusText.ts index b0a8c1d91..c0ae47446 100644 --- a/src/ui/createStatusText.ts +++ b/src/ui/createStatusText.ts @@ -1,3 +1,4 @@ +import { setTimeoutRef } from "../utils/SetTimeoutRef"; import { getElementById } from "../../utils/uiHelpers/getElementById"; import { Action } from "../types"; @@ -23,5 +24,5 @@ export function createStatusText(text: string) { statusElement.innerText = ""; }; - x = setTimeout(handler, threeSeconds); + x = setTimeoutRef(handler, threeSeconds); } diff --git a/src/utils/SetTimeoutRef.ts b/src/utils/SetTimeoutRef.ts new file mode 100644 index 000000000..c79b7cce4 --- /dev/null +++ b/src/utils/SetTimeoutRef.ts @@ -0,0 +1,5 @@ +// This is a reference to the native setTimeout() function +// setTimeout() is used in various places around the game's source code. +// This reference is used to make sure that if players alter window.setTimeout() +// through NetscriptJS, then the game will still function properly +export const setTimeoutRef = window.setTimeout;