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;