Various bugfixes

This commit is contained in:
danielyxie
2019-02-20 00:42:27 -08:00
parent 6d81c00f37
commit 107977e6f4
19 changed files with 139 additions and 71 deletions

View File

@ -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"] |
+------------------------------------+------------------------------------------------------------------------------------------+

View File

@ -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

View File

@ -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.<br><br>" +
"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.<br><br>",
});
//Black Operations
BlackOperations["Operation Typhoon"] = new BlackOperation({

View File

@ -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;

View File

@ -517,7 +517,7 @@ export let CONSTANTS: IMap<any> = {
** 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<any> = {
* '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
`
}

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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(

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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.
/**

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;