Fixed Netscript interpreter memory issues by breaking promise chains in while and for loops. Improved Stock Market UI. Added a button to kill script from log display box. Added confirm() Netscript function

This commit is contained in:
danielyxie 2017-11-02 16:47:09 -05:00
parent 52967d7f9d
commit bc6f0da677
15 changed files with 753 additions and 354 deletions

@ -73,8 +73,7 @@
padding: 10px; padding: 10px;
} }
.dialog-box-close-button, .dialog-box-close-button {
#log-box-close {
float: right; float: right;
color: #aaa; color: #aaa;
font-size: 20px; font-size: 20px;
@ -89,13 +88,21 @@
#log-box-close { #log-box-close {
position: fixed; position: fixed;
right: 26%; right: 27%;
}
#log-box-kill-script {
right: 11%;
position: relative;
}
#log-box-close, #log-box-kill-script {
float:right;
display:inline-block;
} }
.dialog-box-close-button:hover, .dialog-box-close-button:hover,
.dialog-box-close-button:focus, .dialog-box-close-button:focus,{
#log-box-close:hover,
#log-box-close:focus {
color: white; color: white;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;

464
dist/bundle.js vendored

@ -278,8 +278,10 @@ function PlayerObject() {
this.totalPlaytime = 0; this.totalPlaytime = 0;
this.playtimeSinceLastAug = 0; this.playtimeSinceLastAug = 0;
//Script production since last Aug installation //Production since last Augmentation installation
this.scriptProdSinceLastAug = 0; this.scriptProdSinceLastAug = 0;
this.stockProdSinceLastAug = 0;
this.crimeProdSinceLastAug = 0;
}; };
PlayerObject.prototype.init = function() { PlayerObject.prototype.init = function() {
@ -2492,6 +2494,7 @@ function dialogBoxCreate(txt) {
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return printArray; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return printArray; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return powerOfTwo; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return powerOfTwo; });
/* unused harmony export clearEventListenersEl */ /* unused harmony export clearEventListenersEl */
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return removeElementById; });
//General helper functions //General helper functions
//Returns the size (number of keys) of an object //Returns the size (number of keys) of an object
@ -2532,6 +2535,14 @@ function clearEventListenersEl(el) {
return newElem; return newElem;
} }
//Given its id, this function removes an element AND its children
function removeElementById(id) {
var elem = document.getElementById(id);
if (elem == null) {return;}
while(elem.firstChild) {elem.removeChild(elem.firstChild);}
elem.parentNode.removeChild(elem);
}
function getRandomInt(min, max) { function getRandomInt(min, max) {
if (min > max) {return getRandomInt(max, min);} if (min > max) {return getRandomInt(max, min);}
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
@ -3218,10 +3229,21 @@ let CONSTANTS = {
"have purchased. It takes an optional parameter specifying whether the hostname or IP addresses will be returned. If this " + "have purchased. It takes an optional parameter specifying whether the hostname or IP addresses will be returned. If this " +
"parameter is not specified, it is true by default and hostnames will be returned<br><br>" + "parameter is not specified, it is true by default and hostnames will be returned<br><br>" +
"<i><u>round(n)</u></i><br>Rounds the number n to the nearest integer. If the argument passed in is not a number, then the function will return 0.<br><br>" + "<i><u>round(n)</u></i><br>Rounds the number n to the nearest integer. If the argument passed in is not a number, then the function will return 0.<br><br>" +
"<i><u>write(port, data)</u></i><br>Writes data to a port. The first argument must be a number between 1 and 10 that specifies the port. The second " + "<i><u>write(port, data='', mode='a')</u></i><br>This function can be used to either write data to a port or to a text file (.txt).<br><br>" +
"argument defines the data to write to the port. If the second argument is not specified then it will write an empty string to the port.<br><br>" + "If the first argument is a number between 1 and 10, then it specifies a port and this function will write data to a port. If the second " +
"<i><u>read(port)</u></i><br>Reads data from a port. The first argument must be a number between 1 and 10 that specifies the port. A port is a serialized queue. " + "argument is not specified then it will write an empty string to the port. The third argument, mode, is not used when writing data to a port.<br><br>" +
"This function will remove the first element from the queue and return it. If the queue is empty, then the string 'NULL PORT DATA' will be returned. <br><br>" + "If the first argument is a string, then it specifies the name of a text file (.txt) and this function will write data to a text file. " +
"The second argument defines the data to be written to the text file. If it is not specified then it is an empty string by default. " +
"This third argument, mode, defines how the data will be written to the text file. If mode is set to 'w', then the data is written in 'write' " +
"mode which means that it will overwrite the existing data on the file, or it will create a new file if it does not already exist. Otherwise, " +
"the data will be written in 'append' mode which means that the data will be added at the end of the existing file, or it will create a new file if it " +
"does not already exist. If mode isn't specified then it will be 'a' for 'append' mode by default.<br><br>" +
"<i><u>read(port)</u></i><br>This function is used to read data from a port or from a text file (.txt).<br><br>" +
"This function takes a single argument. If this argument is a number between 1 and 10, then it specifies a port and it will read data from " +
"a port. A port is a serialized queue. This function will remove the first element from the queue and return it. If the queue is empty, " +
"then the string 'NULL PORT DATA' will be returned.<br><br>" +
"If the first argument is a string, then it specifies the name of a text file and this function will return the data in the " +
"specified text file. If the text file does not exist, an empty string will be returned<br><br>" +
"<i><u>scriptRunning(scriptname, hostname/ip)</u></i><br>Returns a boolean indicating whether any instance of the specified script is running " + "<i><u>scriptRunning(scriptname, hostname/ip)</u></i><br>Returns a boolean indicating whether any instance of the specified script is running " +
"on a server, regardless of its arguments. This is different than the isRunning() function because it does not " + "on a server, regardless of its arguments. This is different than the isRunning() function because it does not " +
"try to identify a specific instance of a running script by its arguments.<br><br>" + "try to identify a specific instance of a running script by its arguments.<br><br>" +
@ -3667,6 +3689,14 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.32.1<br>" +
"-Updated Netscript's 'interpreter/engine' to use the Bluebird promise library instead of native promises. " +
"It should now be faster and more memory-efficient. If this has broken any Netscript features please report it through Github or the subreddit (reddit.com/r/bitburner)<br>" +
"-Rebalanced stock market (adjusted parameters such as the volatility/trends/starting price of certain stocks)<br>" +
"-Added confirm() Netscript function<br>" +
"-Added 'Buy Max' and 'Sell All' functions to Stock Market UI<br>" +
"-Added 'Portfolio' Mode to Stock Market UI so you can only view stocks you have a position/order in<br>" +
"-Added a button to kill a script from its log display box<br>" +
"v0.32.0<br>" + "v0.32.0<br>" +
"-Released BitNode-8: Ghost of Wall Street<br>" + "-Released BitNode-8: Ghost of Wall Street<br>" +
"-Re-designed Stock Market UI<br>" + "-Re-designed Stock Market UI<br>" +
@ -18190,7 +18220,7 @@ function runScriptsLoop() {
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) { if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
try { try {
var ast = Object(__WEBPACK_IMPORTED_MODULE_7__utils_acorn_js__["parse"])(workerScripts[i].code); var ast = Object(__WEBPACK_IMPORTED_MODULE_7__utils_acorn_js__["parse"])(workerScripts[i].code);
console.log(ast); //console.log(ast);
} catch (e) { } catch (e) {
console.log("Error parsing script: " + workerScripts[i].name); console.log("Error parsing script: " + workerScripts[i].name);
Object(__WEBPACK_IMPORTED_MODULE_8__utils_DialogBox_js__["a" /* dialogBoxCreate */])("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e); Object(__WEBPACK_IMPORTED_MODULE_8__utils_DialogBox_js__["a" /* dialogBoxCreate */])("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e);
@ -18267,11 +18297,6 @@ function killWorkerScript(runningScriptObj, serverIp) {
workerScripts[i].fnWorker.env.stopFlag = true; workerScripts[i].fnWorker.env.stopFlag = true;
Object(__WEBPACK_IMPORTED_MODULE_4__NetscriptEvaluator_js__["c" /* killNetscriptDelay */])(workerScripts[i].fnWorker); Object(__WEBPACK_IMPORTED_MODULE_4__NetscriptEvaluator_js__["c" /* killNetscriptDelay */])(workerScripts[i].fnWorker);
} }
/*workerScripts[i].killTrigger();
if (workerScripts[i].fnWorker) {
workerScripts[i].fnWorker.env.stopFlag = true;
workerScripts[i].fnWorker.killTrigger();
}*/
return true; return true;
} }
} }
@ -21339,6 +21364,7 @@ function RunningScript(script, args) {
this.server = script.server; //IP Address only this.server = script.server; //IP Address only
this.logs = []; //Script logging. Array of strings, with each element being a log entry this.logs = []; //Script logging. Array of strings, with each element being a log entry
this.logUpd = false;
//Stats to display on the Scripts menu, and used to determine offline progress //Stats to display on the Scripts menu, and used to determine offline progress
this.offlineRunningTime = 0.01; //Seconds this.offlineRunningTime = 0.01; //Seconds
@ -21362,6 +21388,7 @@ RunningScript.prototype.log = function(txt) {
this.logs.shift(); this.logs.shift();
} }
this.logs.push(txt); this.logs.push(txt);
this.logUpd = true;
} }
RunningScript.prototype.displayLog = function() { RunningScript.prototype.displayLog = function() {
@ -22895,7 +22922,25 @@ function NetscriptFunctions(workerScript) {
return __WEBPACK_IMPORTED_MODULE_14__Player_js__["a" /* Player */].playtimeSinceLastAug; return __WEBPACK_IMPORTED_MODULE_14__Player_js__["a" /* Player */].playtimeSinceLastAug;
}, },
confirm : function(txt) { confirm : function(txt) {
if (__WEBPACK_IMPORTED_MODULE_30__utils_YesNoBox_js__["e" /* yesNoBoxOpen */]) {
workerScript.scriptRef.log("ERROR: confirm() failed because a pop-up dialog box is already open");
return false;
}
if (!Object(__WEBPACK_IMPORTED_MODULE_29__utils_StringHelperFunctions_js__["f" /* isString */])(txt)) {txt = String(txt);}
var yesBtn = Object(__WEBPACK_IMPORTED_MODULE_30__utils_YesNoBox_js__["d" /* yesNoBoxGetYesButton */])(), noBtn = Object(__WEBPACK_IMPORTED_MODULE_30__utils_YesNoBox_js__["c" /* yesNoBoxGetNoButton */])();
yesBtn.innerHTML = "Yes";
noBtn.innerHTML = "No";
return new Promise(function(resolve, reject) {
yesBtn.addEventListener("click", ()=>{
Object(__WEBPACK_IMPORTED_MODULE_30__utils_YesNoBox_js__["a" /* yesNoBoxClose */])();
resolve(true);
});
noBtn.addEventListener("click", ()=>{
Object(__WEBPACK_IMPORTED_MODULE_30__utils_YesNoBox_js__["a" /* yesNoBoxClose */])();
resolve(false);
});
Object(__WEBPACK_IMPORTED_MODULE_30__utils_YesNoBox_js__["b" /* yesNoBoxCreate */])(txt);
});
}, },
/* Singularity Functions */ /* Singularity Functions */
@ -27703,7 +27748,7 @@ let Terminal = {
else {rootAccess = "NO";} else {rootAccess = "NO";}
post("Root Access: " + rootAccess); post("Root Access: " + rootAccess);
post("Required hacking skill: " + __WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].getCurrentServer().requiredHackingSkill); post("Required hacking skill: " + __WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].getCurrentServer().requiredHackingSkill);
post("Estimated server security level(1-100): " + Object(__WEBPACK_IMPORTED_MODULE_17__utils_StringHelperFunctions_js__["c" /* formatNumber */])(Object(__WEBPACK_IMPORTED_MODULE_18__utils_HelperFunctions_js__["a" /* addOffset */])(__WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].getCurrentServer().hackDifficulty, 5), 3)); post("Estimated server security level: " + Object(__WEBPACK_IMPORTED_MODULE_17__utils_StringHelperFunctions_js__["c" /* formatNumber */])(Object(__WEBPACK_IMPORTED_MODULE_18__utils_HelperFunctions_js__["a" /* addOffset */])(__WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].getCurrentServer().hackDifficulty, 5), 3));
post("Estimated chance to hack: " + Object(__WEBPACK_IMPORTED_MODULE_17__utils_StringHelperFunctions_js__["c" /* formatNumber */])(Object(__WEBPACK_IMPORTED_MODULE_18__utils_HelperFunctions_js__["a" /* addOffset */])(__WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].calculateHackingChance() * 100, 5), 2) + "%"); post("Estimated chance to hack: " + Object(__WEBPACK_IMPORTED_MODULE_17__utils_StringHelperFunctions_js__["c" /* formatNumber */])(Object(__WEBPACK_IMPORTED_MODULE_18__utils_HelperFunctions_js__["a" /* addOffset */])(__WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].calculateHackingChance() * 100, 5), 2) + "%");
post("Estimated time to hack: " + Object(__WEBPACK_IMPORTED_MODULE_17__utils_StringHelperFunctions_js__["c" /* formatNumber */])(Object(__WEBPACK_IMPORTED_MODULE_18__utils_HelperFunctions_js__["a" /* addOffset */])(__WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].calculateHackingTime(), 5), 3) + " seconds"); post("Estimated time to hack: " + Object(__WEBPACK_IMPORTED_MODULE_17__utils_StringHelperFunctions_js__["c" /* formatNumber */])(Object(__WEBPACK_IMPORTED_MODULE_18__utils_HelperFunctions_js__["a" /* addOffset */])(__WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].calculateHackingTime(), 5), 3) + " seconds");
post("Estimated total money available on server: $" + Object(__WEBPACK_IMPORTED_MODULE_17__utils_StringHelperFunctions_js__["c" /* formatNumber */])(Object(__WEBPACK_IMPORTED_MODULE_18__utils_HelperFunctions_js__["a" /* addOffset */])(__WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].getCurrentServer().moneyAvailable, 5), 2)); post("Estimated total money available on server: $" + Object(__WEBPACK_IMPORTED_MODULE_17__utils_StringHelperFunctions_js__["c" /* formatNumber */])(Object(__WEBPACK_IMPORTED_MODULE_18__utils_HelperFunctions_js__["a" /* addOffset */])(__WEBPACK_IMPORTED_MODULE_11__Player_js__["a" /* Player */].getCurrentServer().moneyAvailable, 5), 2));
@ -36711,7 +36756,7 @@ function initStockMarket() {
StockMarket[omnitek] = omnitekStk; StockMarket[omnitek] = omnitekStk;
var foursigma = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].Sector12FourSigma; var foursigma = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].Sector12FourSigma;
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], 1.1, true, 18, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(60000, 70000)); var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], 1.05, true, 18, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(60000, 70000));
StockMarket[foursigma] = foursigmaStk; StockMarket[foursigma] = foursigmaStk;
var kuaigong = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].ChongqingKuaiGongInternational; var kuaigong = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].ChongqingKuaiGongInternational;
@ -36719,7 +36764,7 @@ function initStockMarket() {
StockMarket[kuaigong] = kuaigongStk; StockMarket[kuaigong] = kuaigongStk;
var fulcrum = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].AevumFulcrumTechnologies; var fulcrum = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].AevumFulcrumTechnologies;
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], 1.25, true, 17, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(30000, 35000)); var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], 1.25, true, 16, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(30000, 35000));
StockMarket[fulcrum] = fulcrumStk; StockMarket[fulcrum] = fulcrumStk;
var storm = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].IshimaStormTechnologies; var storm = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].IshimaStormTechnologies;
@ -36779,7 +36824,7 @@ function initStockMarket() {
StockMarket[rho] = rhoStk; StockMarket[rho] = rhoStk;
var alpha = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].Sector12AlphaEnterprises; var alpha = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].Sector12AlphaEnterprises;
var alphaStk = new Stock(alpha, StockSymbols[alpha], 2, true, 10, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(5000, 7500)); var alphaStk = new Stock(alpha, StockSymbols[alpha], 1.9, true, 10, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(5000, 7500));
StockMarket[alpha] = alphaStk; StockMarket[alpha] = alphaStk;
var syscore = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].VolhavenSysCoreSecurities; var syscore = __WEBPACK_IMPORTED_MODULE_2__Location_js__["a" /* Locations */].VolhavenSysCoreSecurities;
@ -36803,15 +36848,15 @@ function initStockMarket() {
StockMarket[fns] = fnsStk; StockMarket[fns] = fnsStk;
var sigmacosm = "Sigma Cosmetics"; var sigmacosm = "Sigma Cosmetics";
var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], 3, true, 0, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(2000, 3000)); var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], 2.8, true, 0, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(2000, 3000));
StockMarket[sigmacosm] = sigmacosmStk; StockMarket[sigmacosm] = sigmacosmStk;
var joesguns = "Joes Guns"; var joesguns = "Joes Guns";
var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], 4, true, 1, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(500, 1000)); var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], 3.7, true, 1, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(500, 1000));
StockMarket[joesguns] = joesgunsStk; StockMarket[joesguns] = joesgunsStk;
var catalyst = "Catalyst Ventures"; var catalyst = "Catalyst Ventures";
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.6, true, 15, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(500, 1000)); var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.5, true, 13, Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["d" /* getRandomInt */])(500, 1000));
StockMarket[catalyst] = catalystStk; StockMarket[catalyst] = catalystStk;
var microdyne = "Microdyne Technologies"; var microdyne = "Microdyne Technologies";
@ -36852,8 +36897,8 @@ function stockMarketCycle() {
for (var name in StockMarket) { for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) { if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name]; var stock = StockMarket[name];
var thresh = 0.59; var thresh = 0.6;
if (stock.b) {thresh = 0.41;} if (stock.b) {thresh = 0.4;}
if (Math.random() < thresh) { if (Math.random() < thresh) {
stock.b = !stock.b; stock.b = !stock.b;
} }
@ -36946,9 +36991,7 @@ function shortStock(stock, shares, workerScript=null) {
var newTotal = origTotal + totalPrice; var newTotal = origTotal + totalPrice;
stock.playerShortShares += shares; stock.playerShortShares += shares;
stock.playerAvgShortPx = newTotal / stock.playerShortShares; stock.playerAvgShortPx = newTotal / stock.playerShortShares;
if (__WEBPACK_IMPORTED_MODULE_1__engine_js__["Engine"].currentPage === __WEBPACK_IMPORTED_MODULE_1__engine_js__["Engine"].Page.StockMarket) {
updateStockPlayerPosition(stock); updateStockPlayerPosition(stock);
}
if (tixApi) { if (tixApi) {
workerScript.scriptRef.log("Bought a short position of " + Object(__WEBPACK_IMPORTED_MODULE_10__utils_StringHelperFunctions_js__["c" /* formatNumber */])(shares, 0) + " shares of " + stock.symbol + " at " + workerScript.scriptRef.log("Bought a short position of " + Object(__WEBPACK_IMPORTED_MODULE_10__utils_StringHelperFunctions_js__["c" /* formatNumber */])(shares, 0) + " shares of " + stock.symbol + " at " +
__WEBPACK_IMPORTED_MODULE_9__utils_numeral_min_js___default()(stock.price).format('($0.000a)') + " per share. Paid " + __WEBPACK_IMPORTED_MODULE_9__utils_numeral_min_js___default()(stock.price).format('($0.000a)') + " per share. Paid " +
@ -36990,9 +37033,7 @@ function sellShort(stock, shares, workerScript=null) {
if (stock.playerShortShares === 0) { if (stock.playerShortShares === 0) {
stock.playerAvgShortPx = 0; stock.playerAvgShortPx = 0;
} }
if (__WEBPACK_IMPORTED_MODULE_1__engine_js__["Engine"].currentPage === __WEBPACK_IMPORTED_MODULE_1__engine_js__["Engine"].Page.StockMarket) {
updateStockPlayerPosition(stock); updateStockPlayerPosition(stock);
}
if (tixApi) { if (tixApi) {
workerScript.scriptRef.log("Sold your short position of " + shares + " shares of " + stock.symbol + " at " + workerScript.scriptRef.log("Sold your short position of " + shares + " shares of " + stock.symbol + " at " +
__WEBPACK_IMPORTED_MODULE_9__utils_numeral_min_js___default()(stock.price).format('($0.000a)') + " per share. After commissions, you gained " + __WEBPACK_IMPORTED_MODULE_9__utils_numeral_min_js___default()(stock.price).format('($0.000a)') + " per share. After commissions, you gained " +
@ -37129,6 +37170,8 @@ function setStockMarketContentCreated(b) {
} }
var stockMarketContentCreated = false; var stockMarketContentCreated = false;
var stockMarketPortfolioMode = false;
var COMM = __WEBPACK_IMPORTED_MODULE_0__Constants_js__["a" /* CONSTANTS */].StockMarketCommission;
function displayStockMarketContent() { function displayStockMarketContent() {
if (__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasWseAccount == null) {__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasWseAccount = false;} if (__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasWseAccount == null) {__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasWseAccount = false;}
if (__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasTixApiAccess == null) {__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasTixApiAccess = false;} if (__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasTixApiAccess == null) {__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasTixApiAccess = false;}
@ -37166,6 +37209,27 @@ function displayStockMarketContent() {
return false; return false;
}); });
var stockList = document.getElementById("stock-market-list");
if (stockList == null) {return;}
if (!__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasWseAccount) {
stockMarketContentCreated = false;
while (stockList.firstChild) {
stockList.removeChild(stockList.firstChild);
}
return;
}
//Create stock market content if you have an account
if (!stockMarketContentCreated && __WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasWseAccount) {
console.log("Creating Stock Market UI");
document.getElementById("stock-market-commission").innerHTML =
"Commission Fees: Every transaction you make has a $" +
Object(__WEBPACK_IMPORTED_MODULE_10__utils_StringHelperFunctions_js__["c" /* formatNumber */])(__WEBPACK_IMPORTED_MODULE_0__Constants_js__["a" /* CONSTANTS */].StockMarketCommission, 2) + " commission fee.<br><br>" +
"WARNING: When you reset after installing Augmentations, the Stock Market is reset. " +
"This means all your positions are lost, so make sure to sell your stocks before installing " +
"Augmentations!";
var investopediaButton = Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["b" /* clearEventListeners */])("stock-market-investopedia"); var investopediaButton = Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["b" /* clearEventListeners */])("stock-market-investopedia");
investopediaButton.addEventListener("click", function() { investopediaButton.addEventListener("click", function() {
var txt = "When making a transaction on the stock market, there are two " + var txt = "When making a transaction on the stock market, there are two " +
@ -37211,26 +37275,38 @@ function displayStockMarketContent() {
return false; return false;
}); });
var stockList = document.getElementById("stock-market-list"); //Switch to Portfolio Mode Button
if (stockList == null) {return;} var modeBtn = Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["b" /* clearEventListeners */])("stock-market-mode");
if (modeBtn) {
if (!__WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasWseAccount) { modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
stockMarketContentCreated = false; "<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
while (stockList.firstChild) { modeBtn.addEventListener("click", switchToPortfolioMode);
stockList.removeChild(stockList.firstChild);
}
return;
} }
//Create stock market content if you have an account //Expand/Collapse tickers buttons
if (!stockMarketContentCreated && __WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].hasWseAccount) { var expandBtn = Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["b" /* clearEventListeners */])("stock-market-expand-tickers"),
console.log("Creating Stock Market UI"); collapseBtn = Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["b" /* clearEventListeners */])("stock-market-collapse-tickers"),
document.getElementById("stock-market-commission").innerHTML = stockList = document.getElementById("stock-market-list");
"Commission Fees: Every transaction you make has a $" + if (expandBtn) {
Object(__WEBPACK_IMPORTED_MODULE_10__utils_StringHelperFunctions_js__["c" /* formatNumber */])(__WEBPACK_IMPORTED_MODULE_0__Constants_js__["a" /* CONSTANTS */].StockMarketCommission, 2) + " commission fee.<br><br>" + expandBtn.addEventListener("click", ()=>{
"WARNING: When you reset after installing Augmentations, the Stock Market is reset. " + var tickerHdrs = stockList.getElementsByClassName("accordion-header");
"This means all your positions are lost, so make sure to sell your stocks before installing " + for (var i = 0; i < tickerHdrs.length; ++i) {
"Augmentations!"; if (!tickerHdrs[i].classList.contains("active")) {
tickerHdrs[i].click();
}
}
});
}
if (collapseBtn) {
collapseBtn.addEventListener("click",()=>{
var tickerHdrs = stockList.getElementsByClassName("accordion-header");
for (var i = 0; i < tickerHdrs.length; ++i) {
if (tickerHdrs[i].classList.contains("active")) {
tickerHdrs[i].click();
}
}
});
}
for (var name in StockMarket) { for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) { if (StockMarket.hasOwnProperty(name)) {
@ -37248,13 +37324,74 @@ function displayStockMarketContent() {
if (StockMarket.hasOwnProperty(name)) { if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name]; var stock = StockMarket[name];
updateStockTicker(stock, null); updateStockTicker(stock, null);
updateStockPlayerPosition(stock);
updateStockOrderList(stock); updateStockOrderList(stock);
} }
} }
} }
} }
//Displays only stocks you have position/order in
function switchToPortfolioMode() {
stockMarketPortfolioMode = true;
var stockList = document.getElementById("stock-market-list");
if (stockList == null) {return;}
var modeBtn = Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["b" /* clearEventListeners */])("stock-market-mode");
if (modeBtn) {
modeBtn.innerHTML = "Switch to 'All stocks' Mode" +
"<span class='tooltiptext'>Displays all stocks on the WSE</span>";
modeBtn.addEventListener("click", switchToDisplayAllMode);
}
while(stockList.firstChild) {stockList.removeChild(stockList.firstChild);}
//Get Order book (create it if it hasn't been created)
var orderBook = StockMarket["Orders"];
if (orderBook == null) {
var orders = {};
for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name];
if (!(stock instanceof Stock)) {continue;}
orders[stock.symbol] = [];
}
}
StockMarket["Orders"] = orders;
}
for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name];
if (!(stock instanceof Stock)) {continue;} //orders property is an array
var stockOrders = orderBook[stock.symbol];
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
stockOrders.length === 0) {continue;}
createStockTicker(stock);
}
}
setStockTickerClickHandlers();
}
//Displays all stocks
function switchToDisplayAllMode() {
stockMarketPortfolioMode = false;
var stockList = document.getElementById("stock-market-list");
if (stockList == null) {return;}
var modeBtn = Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["b" /* clearEventListeners */])("stock-market-mode");
if (modeBtn) {
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
modeBtn.addEventListener("click", switchToPortfolioMode);
}
while(stockList.firstChild) {stockList.removeChild(stockList.firstChild);}
for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name];
if (!(stock instanceof Stock)) {continue;} //orders property is an array
createStockTicker(stock);
}
}
setStockTickerClickHandlers();
}
function createStockTicker(stock) { function createStockTicker(stock) {
if (!(stock instanceof Stock)) { if (!(stock instanceof Stock)) {
console.log("Invalid stock in createStockSticker()"); console.log("Invalid stock in createStockSticker()");
@ -37269,6 +37406,7 @@ function createStockTicker(stock) {
//Div for entire panel //Div for entire panel
var stockDiv = document.createElement("div"); var stockDiv = document.createElement("div");
stockDiv.classList.add("accordion-panel"); stockDiv.classList.add("accordion-panel");
stockDiv.setAttribute("id", tickerId + "-panel");
/* Create panel DOM */ /* Create panel DOM */
var qtyInput = document.createElement("input"), var qtyInput = document.createElement("input"),
@ -37405,10 +37543,10 @@ function createStockTicker(stock) {
var pos = longShortSelect.options[longShortSelect.selectedIndex].text; var pos = longShortSelect.options[longShortSelect.selectedIndex].text;
pos === "Long" ? pos = PositionTypes.Long : pos = PositionTypes.Short; pos === "Long" ? pos = PositionTypes.Long : pos = PositionTypes.Short;
var ordType = orderTypeSelect.options[orderTypeSelect.selectedIndex].text; var ordType = orderTypeSelect.options[orderTypeSelect.selectedIndex].text;
var money = __WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].money.toMoney(); var money = __WEBPACK_IMPORTED_MODULE_5__Player_js__["a" /* Player */].money.toNumber();
switch (ordType) { switch (ordType) {
case "Market Order": case "Market Order":
var shares = Math.floor(money / stock.price); var shares = Math.floor((money - COMM) / stock.price);
pos === PositionTypes.Long ? buyStock(stock, shares) : shortStock(stock, shares, null); pos === PositionTypes.Long ? buyStock(stock, shares) : shortStock(stock, shares, null);
break; break;
case "Limit Order": case "Limit Order":
@ -37424,7 +37562,7 @@ function createStockTicker(stock) {
} else { } else {
type = OrderTypes.StopBuy; type = OrderTypes.StopBuy;
} }
var shares = Math.floor(money / price); var shares = Math.floor((money-COMM) / price);
placeOrder(stock, shares, price, type, pos); placeOrder(stock, shares, price, type, pos);
Object(__WEBPACK_IMPORTED_MODULE_11__utils_YesNoBox_js__["f" /* yesNoTxtInpBoxClose */])(); Object(__WEBPACK_IMPORTED_MODULE_11__utils_YesNoBox_js__["f" /* yesNoTxtInpBoxClose */])();
}); });
@ -37490,6 +37628,7 @@ function createStockTicker(stock) {
document.getElementById("stock-market-list").appendChild(li); document.getElementById("stock-market-list").appendChild(li);
updateStockTicker(stock, true); updateStockTicker(stock, true);
updateStockPlayerPosition(stock);
updateStockOrderList(stock); updateStockOrderList(stock);
} }
@ -37526,11 +37665,11 @@ function updateStockTicker(stock, increase) {
var hdr = document.getElementById(tickerId + "-hdr"); var hdr = document.getElementById(tickerId + "-hdr");
if (hdr == null) { if (hdr == null) {
console.log("ERROR: Couldn't find ticker element for stock: " + stock.symbol); if (!stockMarketPortfolioMode) {console.log("ERROR: Couldn't find ticker element for stock: " + stock.symbol);}
return; return;
} }
hdr.innerHTML = stock.name + " - " + stock.symbol + " - $" + Object(__WEBPACK_IMPORTED_MODULE_10__utils_StringHelperFunctions_js__["c" /* formatNumber */])(stock.price, 2); hdr.innerHTML = stock.name + " - " + stock.symbol + " - $" + Object(__WEBPACK_IMPORTED_MODULE_10__utils_StringHelperFunctions_js__["c" /* formatNumber */])(stock.price, 2);
if (increase !== null) { if (increase != null) {
increase ? hdr.style.color = "#66ff33" : hdr.style.color = "red"; increase ? hdr.style.color = "#66ff33" : hdr.style.color = "red";
} }
@ -37547,6 +37686,25 @@ function updateStockPlayerPosition(stock) {
return; return;
} }
var tickerId = "stock-market-ticker-" + stock.symbol; var tickerId = "stock-market-ticker-" + stock.symbol;
if (stockMarketPortfolioMode) {
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
StockMarket["Orders"] && StockMarket["Orders"][stock.symbol] &&
StockMarket["Orders"][stock.symbol].length === 0) {
Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["g" /* removeElementById */])(tickerId + "-hdr");
Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["g" /* removeElementById */])(tickerId + "-panel");
return;
} else {
//If the ticker hasn't been created, create it (handles updating)
//If it has been created, continue normally
if (document.getElementById(tickerId + "-hdr") == null) {
createStockTicker(stock);
setStockTickerClickHandlers();
return;
}
}
}
if (!(stock.posTxtEl instanceof Element)) { if (!(stock.posTxtEl instanceof Element)) {
stock.posTxtEl = document.getElementById(tickerId + "-position-text"); stock.posTxtEl = document.getElementById(tickerId + "-position-text");
} }
@ -37595,7 +37753,7 @@ function updateStockOrderList(stock) {
var tickerId = "stock-market-ticker-" + stock.symbol; var tickerId = "stock-market-ticker-" + stock.symbol;
var orderList = document.getElementById(tickerId + "-order-list"); var orderList = document.getElementById(tickerId + "-order-list");
if (orderList == null) { if (orderList == null) {
console.log("ERROR: Could not find order list for " + stock.symbol); if (!stockMarketPortfolioMode) {console.log("ERROR: Could not find order list for " + stock.symbol);}
return; return;
} }
@ -37610,6 +37768,24 @@ function updateStockOrderList(stock) {
return; return;
} }
if (stockMarketPortfolioMode) {
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
StockMarket["Orders"] && StockMarket["Orders"][stock.symbol] &&
StockMarket["Orders"][stock.symbol].length === 0) {
Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["g" /* removeElementById */])(tickerId + "-hdr");
Object(__WEBPACK_IMPORTED_MODULE_7__utils_HelperFunctions_js__["g" /* removeElementById */])(tickerId + "-panel");
return;
} else {
//If the ticker hasn't been created, create it (handles updating)
//If it has been created, continue normally
if (document.getElementById(tickerId + "-hdr") == null) {
createStockTicker(stock);
setStockTickerClickHandlers();
return;
}
}
}
//Remove everything from list //Remove everything from list
while (orderList.firstChild) { while (orderList.firstChild) {
orderList.removeChild(orderList.firstChild); orderList.removeChild(orderList.firstChild);
@ -37652,7 +37828,9 @@ function updateStockOrderList(stock) {
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return logBoxUpdateText; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return logBoxUpdateText; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return logBoxOpened; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return logBoxOpened; });
/* unused harmony export logBoxCurrentScript */ /* unused harmony export logBoxCurrentScript */
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__HelperFunctions_js__ = __webpack_require__(2); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_NetscriptWorker_js__ = __webpack_require__(11);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__HelperFunctions_js__ = __webpack_require__(2);
$(document).keydown(function(event) { $(document).keydown(function(event) {
@ -37670,6 +37848,7 @@ function logBoxInit() {
logBoxClose(); logBoxClose();
return false; return false;
}); });
document.getElementById("log-box-text-header").style.display = "inline-block";
}; };
document.addEventListener("DOMContentLoaded", logBoxInit, false); document.addEventListener("DOMContentLoaded", logBoxInit, false);
@ -37690,23 +37869,30 @@ function logBoxOpen() {
var logBoxOpened = false; var logBoxOpened = false;
var logBoxCurrentScript = null; var logBoxCurrentScript = null;
//ram argument is in GB
function logBoxCreate(script) { function logBoxCreate(script) {
logBoxCurrentScript = script; logBoxCurrentScript = script;
var killScriptBtn = Object(__WEBPACK_IMPORTED_MODULE_1__HelperFunctions_js__["b" /* clearEventListeners */])("log-box-kill-script");
killScriptBtn.addEventListener("click", ()=>{
Object(__WEBPACK_IMPORTED_MODULE_0__src_NetscriptWorker_js__["d" /* killWorkerScript */])(script, script.server);
return false;
});
document.getElementById('log-box-kill-script').style.display = "inline-block";
logBoxOpen(); logBoxOpen();
document.getElementById("log-box-text-header").innerHTML = document.getElementById("log-box-text-header").innerHTML =
logBoxCurrentScript.filename + " " + Object(__WEBPACK_IMPORTED_MODULE_0__HelperFunctions_js__["f" /* printArray */])(logBoxCurrentScript.args) + ":<br><br>"; logBoxCurrentScript.filename + " " + Object(__WEBPACK_IMPORTED_MODULE_1__HelperFunctions_js__["f" /* printArray */])(logBoxCurrentScript.args) + ":<br><br>";
logBoxCurrentScript.logUpd = true;
logBoxUpdateText(); logBoxUpdateText();
} }
function logBoxUpdateText() { function logBoxUpdateText() {
var txt = document.getElementById("log-box-text"); var txt = document.getElementById("log-box-text");
if (logBoxCurrentScript && logBoxOpened && txt) { if (logBoxCurrentScript && logBoxOpened && txt && logBoxCurrentScript.logUpd) {
txt.innerHTML = ""; txt.innerHTML = "";
for (var i = 0; i < logBoxCurrentScript.logs.length; ++i) { for (var i = 0; i < logBoxCurrentScript.logs.length; ++i) {
txt.innerHTML += logBoxCurrentScript.logs[i]; txt.innerHTML += logBoxCurrentScript.logs[i];
txt.innerHTML += "<br>"; txt.innerHTML += "<br>";
} }
logBoxCurrentScript.logUpd = false;
} }
} }
@ -40195,6 +40381,10 @@ function loadBitVerse(destroyedBitNodeNum) {
return writeRedPillLine("......................................."); return writeRedPillLine(".......................................");
}).then(function() { }).then(function() {
return writeRedPillLine("Welcome to the Bitverse..."); return writeRedPillLine("Welcome to the Bitverse...");
}).then(function() {
return writeRedPillLine(" ");
}).then(function() {
return writeRedPillLine("(Enter a new BitNode using the image above)");
}).then(function() { }).then(function() {
return Promise.resolve(true); return Promise.resolve(true);
}).catch(function(e){ }).catch(function(e){
@ -40356,17 +40546,10 @@ function evaluate(exp, workerScript) {
}); });
return Promise.all(argPromises).then(function(array) { return Promise.all(argPromises).then(function(array) {
return Promise.resolve(array) return Promise.resolve(array)
}).catch(function(e) {
return Promise.reject(e);
}); });
break; break;
case "CallExpression": case "CallExpression":
return evaluate(exp.callee, workerScript).then(function(func) { return evaluate(exp.callee, workerScript).then(function(func) {
/*
var argPromises = exp.arguments.map(function(arg) {
return evaluate(arg, workerScript);
});
Promise.all(argPromises).then(function(args) {*/
return Promise.map(exp.arguments, function(arg) { return Promise.map(exp.arguments, function(arg) {
return evaluate(arg, workerScript); return evaluate(arg, workerScript);
}).then(function(args) { }).then(function(args) {
@ -40430,8 +40613,6 @@ function evaluate(exp, workerScript) {
} catch (e) { } catch (e) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, e)); return Promise.reject(makeRuntimeRejectMsg(workerScript, e));
} }
}).catch(function(e) {
return Promise.reject(e);
}); });
} else { } else {
try { try {
@ -40453,11 +40634,7 @@ function evaluate(exp, workerScript) {
} }
} }
} }
}).catch(function(e) {
return Promise.reject(e);
}); });
}).catch(function(e) {
return Promise.reject(e);
}); });
break; break;
case "MemberExpression": case "MemberExpression":
@ -40478,31 +40655,17 @@ function evaluate(exp, workerScript) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to get property: " + e.toString())); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to get property: " + e.toString()));
} }
} }
}).catch(function(e) {
return Promise.reject(e);
}); });
break; break;
case "LogicalExpression": case "LogicalExpression":
case "BinaryExpression": case "BinaryExpression":
return evalBinary(exp, workerScript).then(function(res) { return evalBinary(exp, workerScript);
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
break; break;
case "UnaryExpression": case "UnaryExpression":
return evalUnary(exp, workerScript).then(function(res) { return evalUnary(exp, workerScript);
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
break; break;
case "AssignmentExpression": case "AssignmentExpression":
return evalAssignment(exp, workerScript).then(function(res) { return evalAssignment(exp, workerScript);
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
break; break;
case "UpdateExpression": case "UpdateExpression":
if (exp.argument.type==="Identifier"){ if (exp.argument.type==="Identifier"){
@ -40541,8 +40704,6 @@ function evaluate(exp, workerScript) {
case "ReturnStatement": case "ReturnStatement":
return evaluate(exp.argument, workerScript).then(function(res) { return evaluate(exp.argument, workerScript).then(function(res) {
return Promise.reject(["RETURNSTATEMENT", res]); return Promise.reject(["RETURNSTATEMENT", res]);
}).catch(function(e) {
return Promise.reject(e);
}); });
break; break;
case "BreakStatement": case "BreakStatement":
@ -40552,19 +40713,15 @@ function evaluate(exp, workerScript) {
return Promise.reject("CONTINUESTATEMENT"); return Promise.reject("CONTINUESTATEMENT");
break; break;
case "IfStatement": case "IfStatement":
return evaluateIf(exp, workerScript).then(function(forLoopRes) { return evaluateIf(exp, workerScript);
return Promise.resolve(forLoopRes);
}).catch(function(e) {
return Promise.reject(e);
});
break; break;
case "SwitchStatement": case "SwitchStatement":
var lineNum = getErrorLineNumber(exp, workerScript); var lineNum = getErrorLineNumber(exp, workerScript);
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Switch statements are not yet implemented in Netscript (line " + (lineNum+1) + ")")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Switch statements are not yet implemented in Netscript (line " + (lineNum+1) + ")"));
break; break;
case "WhileStatement": case "WhileStatement":
return evaluateWhile(exp, workerScript).then(function(forLoopRes) { return evaluateWhile(exp, workerScript).then(function(res) {
return Promise.resolve(forLoopRes); return Promise.resolve(res);
}).catch(function(e) { }).catch(function(e) {
if (e == "BREAKSTATEMENT" || if (e == "BREAKSTATEMENT" ||
(e instanceof __WEBPACK_IMPORTED_MODULE_4__NetscriptWorker_js__["b" /* WorkerScript */] && e.errorMessage == "BREAKSTATEMENT")) { (e instanceof __WEBPACK_IMPORTED_MODULE_4__NetscriptWorker_js__["b" /* WorkerScript */] && e.errorMessage == "BREAKSTATEMENT")) {
@ -40672,11 +40829,7 @@ function evalBinary(exp, workerScript){
default: default:
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unsupported operator: " + exp.operator)); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unsupported operator: " + exp.operator));
} }
}, function(e) {
return Promise.reject(e);
}); });
}, function(e) {
return Promise.reject(e);
}); });
} }
@ -40695,8 +40848,6 @@ function evalUnary(exp, workerScript){
} else { } else {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unimplemented unary operator: " + exp.operator)); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unimplemented unary operator: " + exp.operator));
} }
}).catch(function(e) {
return Promise.reject(e);
}); });
} }
@ -40723,10 +40874,6 @@ function getArrayElement(exp, workerScript) {
return Promise.resolve(indices); return Promise.resolve(indices);
} }
} }
}).catch(function(e) {
console.log(e);
console.log("Error getting index in getArrayElement: " + e.toString());
return Promise.reject(e);
}); });
} }
@ -40791,8 +40938,6 @@ function evalAssignment(exp, workerScript) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString())); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString()));
} }
} }
}, function(e) {
return Promise.reject(e);
}); });
} }
@ -40814,8 +40959,6 @@ function evaluateIf(exp, workerScript, i) {
} else { } else {
return Promise.resolve("endIf"); return Promise.resolve("endIf");
} }
}, function(e) {
return Promise.reject(e);
}); });
} }
@ -40823,10 +40966,12 @@ function evaluateIf(exp, workerScript, i) {
function evaluateFor(exp, workerScript) { function evaluateFor(exp, workerScript) {
var env = workerScript.env; var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);} if (env.stopFlag) {return Promise.reject(workerScript);}
return evaluate(exp.test, workerScript).then(function(resCond) { return new Promise(function(resolve, reject) {
function recurse() {
//Don't return a promise so the promise chain is broken on each recursion (saving memory)
evaluate(exp.test, workerScript).then(function(resCond) {
if (resCond) { if (resCond) {
//Execute code (body), update, and then recurse return evaluate(exp.body, workerScript).then(function(res) {
return evaluate(exp.body, workerScript).then(function(resCode) {
return evaluate(exp.update, workerScript); return evaluate(exp.update, workerScript);
}).catch(function(e) { }).catch(function(e) {
if (e == "CONTINUESTATEMENT" || if (e == "CONTINUESTATEMENT" ||
@ -40842,31 +40987,58 @@ function evaluateFor(exp, workerScript) {
} else { } else {
return Promise.reject(e); return Promise.reject(e);
} }
}).then(function(resPostloop) { }).then(recurse, reject).catch(function(e) {
return Promise.reject(e);
});
} else {
resolve();
}
}).catch(function(e) {
reject(e);
});
}
recurse();
});
/*
return evaluate(exp.test, workerScript).then(function(resCond) {
if (resCond) {
//Execute code (body), update, and then recurse
return evaluate(exp.body, workerScript).then(function(resCode) {
return evaluate(exp.update, workerScript);
}).catch(function(e) {
if (e == "CONTINUESTATEMENT" ||
(e instanceof WorkerScript && e.errorMessage == "CONTINUESTATEMENT")) {
//Continue statement, recurse to next iteration
return evaluate(exp.update, workerScript).then(function(resPostloop) {
return evaluateFor(exp, workerScript); return evaluateFor(exp, workerScript);
}).then(function(foo) { }).then(function(foo) {
return Promise.resolve("endForLoop"); return Promise.resolve("endForLoop");
}).catch(function(e) { }).catch(function(e) {
return Promise.reject(e); return Promise.reject(e);
}); });
} else {
return Promise.reject(e);
}
}).then(function(resPostloop) {
return evaluateFor(exp, workerScript);
}).then(function(foo) {
return Promise.resolve("endForLoop");
});
} else { } else {
return Promise.resolve("endForLoop"); //Doesn't need to resolve to any particular value return Promise.resolve("endForLoop"); //Doesn't need to resolve to any particular value
} }
}, function(e) { });*/
return Promise.reject(e);
});
} }
function evaluateWhile(exp, workerScript) { function evaluateWhile(exp, workerScript) {
var env = workerScript.env; var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);} if (env.stopFlag) {return Promise.reject(workerScript);}
return Promise.delay(__WEBPACK_IMPORTED_MODULE_1__Constants_js__["a" /* CONSTANTS */].CodeInstructionRunTime).then(function() { return new Promise(function (resolve, reject) {
return evaluate(exp.test, workerScript); function recurse() {
}).then(function(resCond) { //Don't return a promise so the promise chain is broken on each recursion (saving memory)
evaluate(exp.test, workerScript).then(function(resCond) {
if (resCond) { if (resCond) {
return evaluate(exp.body, workerScript).then(function(resCode) { return evaluate(exp.body, workerScript).catch(function(e) {
return Promise.resolve(resCode);
}).catch(function(e) {
if (e == "CONTINUESTATEMENT" || if (e == "CONTINUESTATEMENT" ||
(e instanceof __WEBPACK_IMPORTED_MODULE_4__NetscriptWorker_js__["b" /* WorkerScript */] && e.errorMessage == "CONTINUESTATEMENT")) { (e instanceof __WEBPACK_IMPORTED_MODULE_4__NetscriptWorker_js__["b" /* WorkerScript */] && e.errorMessage == "CONTINUESTATEMENT")) {
//Continue statement, recurse //Continue statement, recurse
@ -40878,20 +41050,17 @@ function evaluateWhile(exp, workerScript) {
} else { } else {
return Promise.reject(e); return Promise.reject(e);
} }
}).then(function(resCode) { }).then(recurse, reject).catch(function(e) {
return evaluateWhile(exp, workerScript).then(function(foo) {
return Promise.resolve("endWhileLoop");
}, function(e) {
return Promise.reject(e);
});
}).catch(function(e) {
return Promise.reject(e); return Promise.reject(e);
}); });
} else { } else {
return Promise.resolve("endWhileLoop"); //Doesn't need to resolve to any particular value resolve();
} }
}).catch(function(e) { }).catch(function(e) {
return Promise.reject(e); reject(e);
});
}
recurse();
}); });
} }
@ -40914,17 +41083,42 @@ function evaluateProg(exp, workerScript, index) {
} }
function killNetscriptDelay(workerScript) { function killNetscriptDelay(workerScript) {
if (workerScript instanceof __WEBPACK_IMPORTED_MODULE_4__NetscriptWorker_js__["b" /* WorkerScript */]) { /*
if (workerScript instanceof WorkerScript) {
if (workerScript.delay) { if (workerScript.delay) {
workerScript.delay.cancel(); workerScript.delay.cancel();
} }
} }
*/
if (workerScript instanceof __WEBPACK_IMPORTED_MODULE_4__NetscriptWorker_js__["b" /* WorkerScript */]) {
if (workerScript.delay) {
clearTimeout(workerScript.delay);
workerScript.delayResolve();
}
}
} }
function netscriptDelay(time, workerScript) { function netscriptDelay(time, workerScript) {
var delay = Promise.delay(time, true); /*
workerScript.delay = delay; workerScript.delay = new Promise(function(resolve, reject, onCancel) {
return delay; Promise.delay(time).then(function() {
resolve();
workerScript.delay = null;
});
onCancel(function() {
console.log("Cancelling and rejecting this Promise");
reject(workerScript);
})
});
return workerScript.delay;
*/
return new Promise(function(resolve, reject) {
workerScript.delay = setTimeout(()=>{
workerScript.delay = null;
resolve();
}, time);
workerScript.delayResolve = resolve;
});
} }
function makeRuntimeRejectMsg(workerScript, msg) { function makeRuntimeRejectMsg(workerScript, msg) {
@ -98882,12 +99076,12 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
} }
request.onsuccess = function(e) { request.onsuccess = function(e) {
console.log("Saved game to IndexedDB!"); //console.log("Saved game to IndexedDB!");
} }
try { try {
window.localStorage.setItem("bitburnerSave", saveString); window.localStorage.setItem("bitburnerSave", saveString);
console.log("Saved game to LocalStorage!"); //console.log("Saved game to LocalStorage!");
} catch(e) { } catch(e) {
if (e.code == 22) { if (e.code == 22) {
__WEBPACK_IMPORTED_MODULE_3__engine_js__["Engine"].createStatusText("Save failed for localStorage! Check console(F12)"); __WEBPACK_IMPORTED_MODULE_3__engine_js__["Engine"].createStatusText("Save failed for localStorage! Check console(F12)");

@ -781,10 +781,12 @@
If you purchase access to the TIX API, you will retain that access even after If you purchase access to the TIX API, you will retain that access even after
you 'reset' by installing Augmentations. you 'reset' by installing Augmentations.
</p> </p>
<a id="stock-market-buy-tix-api" class="a-link-button-inactive"> Buy Trade Information eXchange (TIX) API Access - COMING SOON</a> <a id="stock-market-buy-tix-api" class="a-link-button-inactive">Buy Trade Information eXchange (TIX) API Access</a>
<a id="stock-market-investopedia" class='a-link-button'>Investopedia</a> <a id="stock-market-investopedia" class='a-link-button'>Investopedia</a>
<p id="stock-market-commission"> </p> <p id="stock-market-commission"> </p>
<a id="stock-market-mode" class="a-link-button tooltip"></a>
<a id="stock-market-expand-tickers" class="a-link-button tooltip">Expand tickers</a>
<a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a>
<ul id="stock-market-list" style="list-style:none;"> <ul id="stock-market-list" style="list-style:none;">
</ul> </ul>
</div> </div>
@ -792,7 +794,8 @@
<!-- Log Box --> <!-- Log Box -->
<div id="log-box-container"> <div id="log-box-container">
<div id="log-box-content"> <div id="log-box-content">
<span id="log-box-close"> &times; </span> <span id="log-box-close" class="popup-box-button"> Close </span>
<span id="log-box-kill-script" class="popup-box-button">Kill Script</span>
<p id="log-box-text-header"> </p> <p id="log-box-text-header"> </p>
<p id="log-box-text"> </p> <p id="log-box-text"> </p>
</div> </div>

@ -647,10 +647,21 @@ let CONSTANTS = {
"have purchased. It takes an optional parameter specifying whether the hostname or IP addresses will be returned. If this " + "have purchased. It takes an optional parameter specifying whether the hostname or IP addresses will be returned. If this " +
"parameter is not specified, it is true by default and hostnames will be returned<br><br>" + "parameter is not specified, it is true by default and hostnames will be returned<br><br>" +
"<i><u>round(n)</u></i><br>Rounds the number n to the nearest integer. If the argument passed in is not a number, then the function will return 0.<br><br>" + "<i><u>round(n)</u></i><br>Rounds the number n to the nearest integer. If the argument passed in is not a number, then the function will return 0.<br><br>" +
"<i><u>write(port, data)</u></i><br>Writes data to a port. The first argument must be a number between 1 and 10 that specifies the port. The second " + "<i><u>write(port, data='', mode='a')</u></i><br>This function can be used to either write data to a port or to a text file (.txt).<br><br>" +
"argument defines the data to write to the port. If the second argument is not specified then it will write an empty string to the port.<br><br>" + "If the first argument is a number between 1 and 10, then it specifies a port and this function will write data to a port. If the second " +
"<i><u>read(port)</u></i><br>Reads data from a port. The first argument must be a number between 1 and 10 that specifies the port. A port is a serialized queue. " + "argument is not specified then it will write an empty string to the port. The third argument, mode, is not used when writing data to a port.<br><br>" +
"This function will remove the first element from the queue and return it. If the queue is empty, then the string 'NULL PORT DATA' will be returned. <br><br>" + "If the first argument is a string, then it specifies the name of a text file (.txt) and this function will write data to a text file. " +
"The second argument defines the data to be written to the text file. If it is not specified then it is an empty string by default. " +
"This third argument, mode, defines how the data will be written to the text file. If mode is set to 'w', then the data is written in 'write' " +
"mode which means that it will overwrite the existing data on the file, or it will create a new file if it does not already exist. Otherwise, " +
"the data will be written in 'append' mode which means that the data will be added at the end of the existing file, or it will create a new file if it " +
"does not already exist. If mode isn't specified then it will be 'a' for 'append' mode by default.<br><br>" +
"<i><u>read(port)</u></i><br>This function is used to read data from a port or from a text file (.txt).<br><br>" +
"This function takes a single argument. If this argument is a number between 1 and 10, then it specifies a port and it will read data from " +
"a port. A port is a serialized queue. This function will remove the first element from the queue and return it. If the queue is empty, " +
"then the string 'NULL PORT DATA' will be returned.<br><br>" +
"If the first argument is a string, then it specifies the name of a text file and this function will return the data in the " +
"specified text file. If the text file does not exist, an empty string will be returned<br><br>" +
"<i><u>scriptRunning(scriptname, hostname/ip)</u></i><br>Returns a boolean indicating whether any instance of the specified script is running " + "<i><u>scriptRunning(scriptname, hostname/ip)</u></i><br>Returns a boolean indicating whether any instance of the specified script is running " +
"on a server, regardless of its arguments. This is different than the isRunning() function because it does not " + "on a server, regardless of its arguments. This is different than the isRunning() function because it does not " +
"try to identify a specific instance of a running script by its arguments.<br><br>" + "try to identify a specific instance of a running script by its arguments.<br><br>" +
@ -1096,6 +1107,14 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.32.1<br>" +
"-Updated Netscript's 'interpreter/engine' to use the Bluebird promise library instead of native promises. " +
"It should now be faster and more memory-efficient. If this has broken any Netscript features please report it through Github or the subreddit (reddit.com/r/bitburner)<br>" +
"-Rebalanced stock market (adjusted parameters such as the volatility/trends/starting price of certain stocks)<br>" +
"-Added confirm() Netscript function<br>" +
"-Added 'Buy Max' and 'Sell All' functions to Stock Market UI<br>" +
"-Added 'Portfolio' Mode to Stock Market UI so you can only view stocks you have a position/order in<br>" +
"-Added a button to kill a script from its log display box<br>" +
"v0.32.0<br>" + "v0.32.0<br>" +
"-Released BitNode-8: Ghost of Wall Street<br>" + "-Released BitNode-8: Ghost of Wall Street<br>" +
"-Re-designed Stock Market UI<br>" + "-Re-designed Stock Market UI<br>" +

@ -72,17 +72,10 @@ function evaluate(exp, workerScript) {
}); });
return Promise.all(argPromises).then(function(array) { return Promise.all(argPromises).then(function(array) {
return Promise.resolve(array) return Promise.resolve(array)
}).catch(function(e) {
return Promise.reject(e);
}); });
break; break;
case "CallExpression": case "CallExpression":
return evaluate(exp.callee, workerScript).then(function(func) { return evaluate(exp.callee, workerScript).then(function(func) {
/*
var argPromises = exp.arguments.map(function(arg) {
return evaluate(arg, workerScript);
});
Promise.all(argPromises).then(function(args) {*/
return Promise.map(exp.arguments, function(arg) { return Promise.map(exp.arguments, function(arg) {
return evaluate(arg, workerScript); return evaluate(arg, workerScript);
}).then(function(args) { }).then(function(args) {
@ -146,8 +139,6 @@ function evaluate(exp, workerScript) {
} catch (e) { } catch (e) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, e)); return Promise.reject(makeRuntimeRejectMsg(workerScript, e));
} }
}).catch(function(e) {
return Promise.reject(e);
}); });
} else { } else {
try { try {
@ -169,11 +160,7 @@ function evaluate(exp, workerScript) {
} }
} }
} }
}).catch(function(e) {
return Promise.reject(e);
}); });
}).catch(function(e) {
return Promise.reject(e);
}); });
break; break;
case "MemberExpression": case "MemberExpression":
@ -194,31 +181,17 @@ function evaluate(exp, workerScript) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to get property: " + e.toString())); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to get property: " + e.toString()));
} }
} }
}).catch(function(e) {
return Promise.reject(e);
}); });
break; break;
case "LogicalExpression": case "LogicalExpression":
case "BinaryExpression": case "BinaryExpression":
return evalBinary(exp, workerScript).then(function(res) { return evalBinary(exp, workerScript);
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
break; break;
case "UnaryExpression": case "UnaryExpression":
return evalUnary(exp, workerScript).then(function(res) { return evalUnary(exp, workerScript);
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
break; break;
case "AssignmentExpression": case "AssignmentExpression":
return evalAssignment(exp, workerScript).then(function(res) { return evalAssignment(exp, workerScript);
return Promise.resolve(res);
}).catch(function(e) {
return Promise.reject(e);
});
break; break;
case "UpdateExpression": case "UpdateExpression":
if (exp.argument.type==="Identifier"){ if (exp.argument.type==="Identifier"){
@ -257,8 +230,6 @@ function evaluate(exp, workerScript) {
case "ReturnStatement": case "ReturnStatement":
return evaluate(exp.argument, workerScript).then(function(res) { return evaluate(exp.argument, workerScript).then(function(res) {
return Promise.reject(["RETURNSTATEMENT", res]); return Promise.reject(["RETURNSTATEMENT", res]);
}).catch(function(e) {
return Promise.reject(e);
}); });
break; break;
case "BreakStatement": case "BreakStatement":
@ -268,19 +239,15 @@ function evaluate(exp, workerScript) {
return Promise.reject("CONTINUESTATEMENT"); return Promise.reject("CONTINUESTATEMENT");
break; break;
case "IfStatement": case "IfStatement":
return evaluateIf(exp, workerScript).then(function(forLoopRes) { return evaluateIf(exp, workerScript);
return Promise.resolve(forLoopRes);
}).catch(function(e) {
return Promise.reject(e);
});
break; break;
case "SwitchStatement": case "SwitchStatement":
var lineNum = getErrorLineNumber(exp, workerScript); var lineNum = getErrorLineNumber(exp, workerScript);
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Switch statements are not yet implemented in Netscript (line " + (lineNum+1) + ")")); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Switch statements are not yet implemented in Netscript (line " + (lineNum+1) + ")"));
break; break;
case "WhileStatement": case "WhileStatement":
return evaluateWhile(exp, workerScript).then(function(forLoopRes) { return evaluateWhile(exp, workerScript).then(function(res) {
return Promise.resolve(forLoopRes); return Promise.resolve(res);
}).catch(function(e) { }).catch(function(e) {
if (e == "BREAKSTATEMENT" || if (e == "BREAKSTATEMENT" ||
(e instanceof WorkerScript && e.errorMessage == "BREAKSTATEMENT")) { (e instanceof WorkerScript && e.errorMessage == "BREAKSTATEMENT")) {
@ -388,11 +355,7 @@ function evalBinary(exp, workerScript){
default: default:
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unsupported operator: " + exp.operator)); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unsupported operator: " + exp.operator));
} }
}, function(e) {
return Promise.reject(e);
}); });
}, function(e) {
return Promise.reject(e);
}); });
} }
@ -411,8 +374,6 @@ function evalUnary(exp, workerScript){
} else { } else {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unimplemented unary operator: " + exp.operator)); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Unimplemented unary operator: " + exp.operator));
} }
}).catch(function(e) {
return Promise.reject(e);
}); });
} }
@ -439,10 +400,6 @@ function getArrayElement(exp, workerScript) {
return Promise.resolve(indices); return Promise.resolve(indices);
} }
} }
}).catch(function(e) {
console.log(e);
console.log("Error getting index in getArrayElement: " + e.toString());
return Promise.reject(e);
}); });
} }
@ -507,8 +464,6 @@ function evalAssignment(exp, workerScript) {
return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString())); return Promise.reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString()));
} }
} }
}, function(e) {
return Promise.reject(e);
}); });
} }
@ -530,8 +485,6 @@ function evaluateIf(exp, workerScript, i) {
} else { } else {
return Promise.resolve("endIf"); return Promise.resolve("endIf");
} }
}, function(e) {
return Promise.reject(e);
}); });
} }
@ -539,6 +492,40 @@ function evaluateIf(exp, workerScript, i) {
function evaluateFor(exp, workerScript) { function evaluateFor(exp, workerScript) {
var env = workerScript.env; var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);} if (env.stopFlag) {return Promise.reject(workerScript);}
return new Promise(function(resolve, reject) {
function recurse() {
//Don't return a promise so the promise chain is broken on each recursion (saving memory)
evaluate(exp.test, workerScript).then(function(resCond) {
if (resCond) {
return evaluate(exp.body, workerScript).then(function(res) {
return evaluate(exp.update, workerScript);
}).catch(function(e) {
if (e == "CONTINUESTATEMENT" ||
(e instanceof WorkerScript && e.errorMessage == "CONTINUESTATEMENT")) {
//Continue statement, recurse to next iteration
return evaluate(exp.update, workerScript).then(function(resPostloop) {
return evaluateFor(exp, workerScript);
}).then(function(foo) {
return Promise.resolve("endForLoop");
}).catch(function(e) {
return Promise.reject(e);
});
} else {
return Promise.reject(e);
}
}).then(recurse, reject).catch(function(e) {
return Promise.reject(e);
});
} else {
resolve();
}
}).catch(function(e) {
reject(e);
});
}
recurse();
});
/*
return evaluate(exp.test, workerScript).then(function(resCond) { return evaluate(exp.test, workerScript).then(function(resCond) {
if (resCond) { if (resCond) {
//Execute code (body), update, and then recurse //Execute code (body), update, and then recurse
@ -562,27 +549,22 @@ function evaluateFor(exp, workerScript) {
return evaluateFor(exp, workerScript); return evaluateFor(exp, workerScript);
}).then(function(foo) { }).then(function(foo) {
return Promise.resolve("endForLoop"); return Promise.resolve("endForLoop");
}).catch(function(e) {
return Promise.reject(e);
}); });
} else { } else {
return Promise.resolve("endForLoop"); //Doesn't need to resolve to any particular value return Promise.resolve("endForLoop"); //Doesn't need to resolve to any particular value
} }
}, function(e) { });*/
return Promise.reject(e);
});
} }
function evaluateWhile(exp, workerScript) { function evaluateWhile(exp, workerScript) {
var env = workerScript.env; var env = workerScript.env;
if (env.stopFlag) {return Promise.reject(workerScript);} if (env.stopFlag) {return Promise.reject(workerScript);}
return Promise.delay(CONSTANTS.CodeInstructionRunTime).then(function() { return new Promise(function (resolve, reject) {
return evaluate(exp.test, workerScript); function recurse() {
}).then(function(resCond) { //Don't return a promise so the promise chain is broken on each recursion (saving memory)
evaluate(exp.test, workerScript).then(function(resCond) {
if (resCond) { if (resCond) {
return evaluate(exp.body, workerScript).then(function(resCode) { return evaluate(exp.body, workerScript).catch(function(e) {
return Promise.resolve(resCode);
}).catch(function(e) {
if (e == "CONTINUESTATEMENT" || if (e == "CONTINUESTATEMENT" ||
(e instanceof WorkerScript && e.errorMessage == "CONTINUESTATEMENT")) { (e instanceof WorkerScript && e.errorMessage == "CONTINUESTATEMENT")) {
//Continue statement, recurse //Continue statement, recurse
@ -594,20 +576,17 @@ function evaluateWhile(exp, workerScript) {
} else { } else {
return Promise.reject(e); return Promise.reject(e);
} }
}).then(function(resCode) { }).then(recurse, reject).catch(function(e) {
return evaluateWhile(exp, workerScript).then(function(foo) {
return Promise.resolve("endWhileLoop");
}, function(e) {
return Promise.reject(e);
});
}).catch(function(e) {
return Promise.reject(e); return Promise.reject(e);
}); });
} else { } else {
return Promise.resolve("endWhileLoop"); //Doesn't need to resolve to any particular value resolve();
} }
}).catch(function(e) { }).catch(function(e) {
return Promise.reject(e); reject(e);
});
}
recurse();
}); });
} }
@ -630,17 +609,42 @@ function evaluateProg(exp, workerScript, index) {
} }
function killNetscriptDelay(workerScript) { function killNetscriptDelay(workerScript) {
/*
if (workerScript instanceof WorkerScript) { if (workerScript instanceof WorkerScript) {
if (workerScript.delay) { if (workerScript.delay) {
workerScript.delay.cancel(); workerScript.delay.cancel();
} }
} }
*/
if (workerScript instanceof WorkerScript) {
if (workerScript.delay) {
clearTimeout(workerScript.delay);
workerScript.delayResolve();
}
}
} }
function netscriptDelay(time, workerScript) { function netscriptDelay(time, workerScript) {
var delay = Promise.delay(time, true); /*
workerScript.delay = delay; workerScript.delay = new Promise(function(resolve, reject, onCancel) {
return delay; Promise.delay(time).then(function() {
resolve();
workerScript.delay = null;
});
onCancel(function() {
console.log("Cancelling and rejecting this Promise");
reject(workerScript);
})
});
return workerScript.delay;
*/
return new Promise(function(resolve, reject) {
workerScript.delay = setTimeout(()=>{
workerScript.delay = null;
resolve();
}, time);
workerScript.delayResolve = resolve;
});
} }
function makeRuntimeRejectMsg(workerScript, msg) { function makeRuntimeRejectMsg(workerScript, msg) {

@ -1351,7 +1351,25 @@ function NetscriptFunctions(workerScript) {
return Player.playtimeSinceLastAug; return Player.playtimeSinceLastAug;
}, },
confirm : function(txt) { confirm : function(txt) {
if (yesNoBoxOpen) {
workerScript.scriptRef.log("ERROR: confirm() failed because a pop-up dialog box is already open");
return false;
}
if (!isString(txt)) {txt = String(txt);}
var yesBtn = yesNoBoxGetYesButton(), noBtn = yesNoBoxGetNoButton();
yesBtn.innerHTML = "Yes";
noBtn.innerHTML = "No";
return new Promise(function(resolve, reject) {
yesBtn.addEventListener("click", ()=>{
yesNoBoxClose();
resolve(true);
});
noBtn.addEventListener("click", ()=>{
yesNoBoxClose();
resolve(false);
});
yesNoBoxCreate(txt);
});
}, },
/* Singularity Functions */ /* Singularity Functions */

@ -95,7 +95,7 @@ function runScriptsLoop() {
if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) { if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == false) {
try { try {
var ast = parse(workerScripts[i].code); var ast = parse(workerScripts[i].code);
console.log(ast); //console.log(ast);
} catch (e) { } catch (e) {
console.log("Error parsing script: " + workerScripts[i].name); console.log("Error parsing script: " + workerScripts[i].name);
dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e); dialogBoxCreate("Syntax ERROR in " + workerScripts[i].name + ":<br>" + e);
@ -172,11 +172,6 @@ function killWorkerScript(runningScriptObj, serverIp) {
workerScripts[i].fnWorker.env.stopFlag = true; workerScripts[i].fnWorker.env.stopFlag = true;
killNetscriptDelay(workerScripts[i].fnWorker); killNetscriptDelay(workerScripts[i].fnWorker);
} }
/*workerScripts[i].killTrigger();
if (workerScripts[i].fnWorker) {
workerScripts[i].fnWorker.env.stopFlag = true;
workerScripts[i].fnWorker.killTrigger();
}*/
return true; return true;
} }
} }

@ -190,8 +190,10 @@ function PlayerObject() {
this.totalPlaytime = 0; this.totalPlaytime = 0;
this.playtimeSinceLastAug = 0; this.playtimeSinceLastAug = 0;
//Script production since last Aug installation //Production since last Augmentation installation
this.scriptProdSinceLastAug = 0; this.scriptProdSinceLastAug = 0;
this.stockProdSinceLastAug = 0;
this.crimeProdSinceLastAug = 0;
}; };
PlayerObject.prototype.init = function() { PlayerObject.prototype.init = function() {

@ -265,6 +265,10 @@ function loadBitVerse(destroyedBitNodeNum) {
return writeRedPillLine("......................................."); return writeRedPillLine(".......................................");
}).then(function() { }).then(function() {
return writeRedPillLine("Welcome to the Bitverse..."); return writeRedPillLine("Welcome to the Bitverse...");
}).then(function() {
return writeRedPillLine(" ");
}).then(function() {
return writeRedPillLine("(Enter a new BitNode using the image above)");
}).then(function() { }).then(function() {
return Promise.resolve(true); return Promise.resolve(true);
}).catch(function(e){ }).catch(function(e){

@ -82,12 +82,12 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
} }
request.onsuccess = function(e) { request.onsuccess = function(e) {
console.log("Saved game to IndexedDB!"); //console.log("Saved game to IndexedDB!");
} }
try { try {
window.localStorage.setItem("bitburnerSave", saveString); window.localStorage.setItem("bitburnerSave", saveString);
console.log("Saved game to LocalStorage!"); //console.log("Saved game to LocalStorage!");
} catch(e) { } catch(e) {
if (e.code == 22) { if (e.code == 22) {
Engine.createStatusText("Save failed for localStorage! Check console(F12)"); Engine.createStatusText("Save failed for localStorage! Check console(F12)");

@ -528,6 +528,7 @@ function RunningScript(script, args) {
this.server = script.server; //IP Address only this.server = script.server; //IP Address only
this.logs = []; //Script logging. Array of strings, with each element being a log entry this.logs = []; //Script logging. Array of strings, with each element being a log entry
this.logUpd = false;
//Stats to display on the Scripts menu, and used to determine offline progress //Stats to display on the Scripts menu, and used to determine offline progress
this.offlineRunningTime = 0.01; //Seconds this.offlineRunningTime = 0.01; //Seconds
@ -551,6 +552,7 @@ RunningScript.prototype.log = function(txt) {
this.logs.shift(); this.logs.shift();
} }
this.logs.push(txt); this.logs.push(txt);
this.logUpd = true;
} }
RunningScript.prototype.displayLog = function() { RunningScript.prototype.displayLog = function() {

@ -6,7 +6,9 @@ import {WorkerScript} from "./NetscriptWorker.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
import {clearEventListeners, getRandomInt} from "../utils/HelperFunctions.js"; import {clearEventListeners, getRandomInt,
removeElementById,
clearEventListenersEl} from "../utils/HelperFunctions.js";
import {Reviver, Generic_toJSON, import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver.js"; Generic_fromJSON} from "../utils/JSONReviver.js";
import numeral from "../utils/numeral.min.js"; import numeral from "../utils/numeral.min.js";
@ -267,7 +269,7 @@ function initStockMarket() {
StockMarket[omnitek] = omnitekStk; StockMarket[omnitek] = omnitekStk;
var foursigma = Locations.Sector12FourSigma; var foursigma = Locations.Sector12FourSigma;
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], 1.1, true, 18, getRandomInt(60000, 70000)); var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], 1.05, true, 18, getRandomInt(60000, 70000));
StockMarket[foursigma] = foursigmaStk; StockMarket[foursigma] = foursigmaStk;
var kuaigong = Locations.ChongqingKuaiGongInternational; var kuaigong = Locations.ChongqingKuaiGongInternational;
@ -275,7 +277,7 @@ function initStockMarket() {
StockMarket[kuaigong] = kuaigongStk; StockMarket[kuaigong] = kuaigongStk;
var fulcrum = Locations.AevumFulcrumTechnologies; var fulcrum = Locations.AevumFulcrumTechnologies;
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], 1.25, true, 17, getRandomInt(30000, 35000)); var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], 1.25, true, 16, getRandomInt(30000, 35000));
StockMarket[fulcrum] = fulcrumStk; StockMarket[fulcrum] = fulcrumStk;
var storm = Locations.IshimaStormTechnologies; var storm = Locations.IshimaStormTechnologies;
@ -335,7 +337,7 @@ function initStockMarket() {
StockMarket[rho] = rhoStk; StockMarket[rho] = rhoStk;
var alpha = Locations.Sector12AlphaEnterprises; var alpha = Locations.Sector12AlphaEnterprises;
var alphaStk = new Stock(alpha, StockSymbols[alpha], 2, true, 10, getRandomInt(5000, 7500)); var alphaStk = new Stock(alpha, StockSymbols[alpha], 1.9, true, 10, getRandomInt(5000, 7500));
StockMarket[alpha] = alphaStk; StockMarket[alpha] = alphaStk;
var syscore = Locations.VolhavenSysCoreSecurities; var syscore = Locations.VolhavenSysCoreSecurities;
@ -359,15 +361,15 @@ function initStockMarket() {
StockMarket[fns] = fnsStk; StockMarket[fns] = fnsStk;
var sigmacosm = "Sigma Cosmetics"; var sigmacosm = "Sigma Cosmetics";
var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], 3, true, 0, getRandomInt(2000, 3000)); var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], 2.8, true, 0, getRandomInt(2000, 3000));
StockMarket[sigmacosm] = sigmacosmStk; StockMarket[sigmacosm] = sigmacosmStk;
var joesguns = "Joes Guns"; var joesguns = "Joes Guns";
var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], 4, true, 1, getRandomInt(500, 1000)); var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], 3.7, true, 1, getRandomInt(500, 1000));
StockMarket[joesguns] = joesgunsStk; StockMarket[joesguns] = joesgunsStk;
var catalyst = "Catalyst Ventures"; var catalyst = "Catalyst Ventures";
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.6, true, 15, getRandomInt(500, 1000)); var catalystStk = new Stock(catalyst, StockSymbols[catalyst], 1.5, true, 13, getRandomInt(500, 1000));
StockMarket[catalyst] = catalystStk; StockMarket[catalyst] = catalystStk;
var microdyne = "Microdyne Technologies"; var microdyne = "Microdyne Technologies";
@ -408,8 +410,8 @@ function stockMarketCycle() {
for (var name in StockMarket) { for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) { if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name]; var stock = StockMarket[name];
var thresh = 0.59; var thresh = 0.6;
if (stock.b) {thresh = 0.41;} if (stock.b) {thresh = 0.4;}
if (Math.random() < thresh) { if (Math.random() < thresh) {
stock.b = !stock.b; stock.b = !stock.b;
} }
@ -502,9 +504,7 @@ function shortStock(stock, shares, workerScript=null) {
var newTotal = origTotal + totalPrice; var newTotal = origTotal + totalPrice;
stock.playerShortShares += shares; stock.playerShortShares += shares;
stock.playerAvgShortPx = newTotal / stock.playerShortShares; stock.playerAvgShortPx = newTotal / stock.playerShortShares;
if (Engine.currentPage === Engine.Page.StockMarket) {
updateStockPlayerPosition(stock); updateStockPlayerPosition(stock);
}
if (tixApi) { if (tixApi) {
workerScript.scriptRef.log("Bought a short position of " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at " + workerScript.scriptRef.log("Bought a short position of " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at " +
numeral(stock.price).format('($0.000a)') + " per share. Paid " + numeral(stock.price).format('($0.000a)') + " per share. Paid " +
@ -546,9 +546,7 @@ function sellShort(stock, shares, workerScript=null) {
if (stock.playerShortShares === 0) { if (stock.playerShortShares === 0) {
stock.playerAvgShortPx = 0; stock.playerAvgShortPx = 0;
} }
if (Engine.currentPage === Engine.Page.StockMarket) {
updateStockPlayerPosition(stock); updateStockPlayerPosition(stock);
}
if (tixApi) { if (tixApi) {
workerScript.scriptRef.log("Sold your short position of " + shares + " shares of " + stock.symbol + " at " + workerScript.scriptRef.log("Sold your short position of " + shares + " shares of " + stock.symbol + " at " +
numeral(stock.price).format('($0.000a)') + " per share. After commissions, you gained " + numeral(stock.price).format('($0.000a)') + " per share. After commissions, you gained " +
@ -685,6 +683,8 @@ function setStockMarketContentCreated(b) {
} }
var stockMarketContentCreated = false; var stockMarketContentCreated = false;
var stockMarketPortfolioMode = false;
var COMM = CONSTANTS.StockMarketCommission;
function displayStockMarketContent() { function displayStockMarketContent() {
if (Player.hasWseAccount == null) {Player.hasWseAccount = false;} if (Player.hasWseAccount == null) {Player.hasWseAccount = false;}
if (Player.hasTixApiAccess == null) {Player.hasTixApiAccess = false;} if (Player.hasTixApiAccess == null) {Player.hasTixApiAccess = false;}
@ -722,6 +722,27 @@ function displayStockMarketContent() {
return false; return false;
}); });
var stockList = document.getElementById("stock-market-list");
if (stockList == null) {return;}
if (!Player.hasWseAccount) {
stockMarketContentCreated = false;
while (stockList.firstChild) {
stockList.removeChild(stockList.firstChild);
}
return;
}
//Create stock market content if you have an account
if (!stockMarketContentCreated && Player.hasWseAccount) {
console.log("Creating Stock Market UI");
document.getElementById("stock-market-commission").innerHTML =
"Commission Fees: Every transaction you make has a $" +
formatNumber(CONSTANTS.StockMarketCommission, 2) + " commission fee.<br><br>" +
"WARNING: When you reset after installing Augmentations, the Stock Market is reset. " +
"This means all your positions are lost, so make sure to sell your stocks before installing " +
"Augmentations!";
var investopediaButton = clearEventListeners("stock-market-investopedia"); var investopediaButton = clearEventListeners("stock-market-investopedia");
investopediaButton.addEventListener("click", function() { investopediaButton.addEventListener("click", function() {
var txt = "When making a transaction on the stock market, there are two " + var txt = "When making a transaction on the stock market, there are two " +
@ -767,26 +788,38 @@ function displayStockMarketContent() {
return false; return false;
}); });
var stockList = document.getElementById("stock-market-list"); //Switch to Portfolio Mode Button
if (stockList == null) {return;} var modeBtn = clearEventListeners("stock-market-mode");
if (modeBtn) {
if (!Player.hasWseAccount) { modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
stockMarketContentCreated = false; "<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
while (stockList.firstChild) { modeBtn.addEventListener("click", switchToPortfolioMode);
stockList.removeChild(stockList.firstChild);
}
return;
} }
//Create stock market content if you have an account //Expand/Collapse tickers buttons
if (!stockMarketContentCreated && Player.hasWseAccount) { var expandBtn = clearEventListeners("stock-market-expand-tickers"),
console.log("Creating Stock Market UI"); collapseBtn = clearEventListeners("stock-market-collapse-tickers"),
document.getElementById("stock-market-commission").innerHTML = stockList = document.getElementById("stock-market-list");
"Commission Fees: Every transaction you make has a $" + if (expandBtn) {
formatNumber(CONSTANTS.StockMarketCommission, 2) + " commission fee.<br><br>" + expandBtn.addEventListener("click", ()=>{
"WARNING: When you reset after installing Augmentations, the Stock Market is reset. " + var tickerHdrs = stockList.getElementsByClassName("accordion-header");
"This means all your positions are lost, so make sure to sell your stocks before installing " + for (var i = 0; i < tickerHdrs.length; ++i) {
"Augmentations!"; if (!tickerHdrs[i].classList.contains("active")) {
tickerHdrs[i].click();
}
}
});
}
if (collapseBtn) {
collapseBtn.addEventListener("click",()=>{
var tickerHdrs = stockList.getElementsByClassName("accordion-header");
for (var i = 0; i < tickerHdrs.length; ++i) {
if (tickerHdrs[i].classList.contains("active")) {
tickerHdrs[i].click();
}
}
});
}
for (var name in StockMarket) { for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) { if (StockMarket.hasOwnProperty(name)) {
@ -804,13 +837,74 @@ function displayStockMarketContent() {
if (StockMarket.hasOwnProperty(name)) { if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name]; var stock = StockMarket[name];
updateStockTicker(stock, null); updateStockTicker(stock, null);
updateStockPlayerPosition(stock);
updateStockOrderList(stock); updateStockOrderList(stock);
} }
} }
} }
} }
//Displays only stocks you have position/order in
function switchToPortfolioMode() {
stockMarketPortfolioMode = true;
var stockList = document.getElementById("stock-market-list");
if (stockList == null) {return;}
var modeBtn = clearEventListeners("stock-market-mode");
if (modeBtn) {
modeBtn.innerHTML = "Switch to 'All stocks' Mode" +
"<span class='tooltiptext'>Displays all stocks on the WSE</span>";
modeBtn.addEventListener("click", switchToDisplayAllMode);
}
while(stockList.firstChild) {stockList.removeChild(stockList.firstChild);}
//Get Order book (create it if it hasn't been created)
var orderBook = StockMarket["Orders"];
if (orderBook == null) {
var orders = {};
for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name];
if (!(stock instanceof Stock)) {continue;}
orders[stock.symbol] = [];
}
}
StockMarket["Orders"] = orders;
}
for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name];
if (!(stock instanceof Stock)) {continue;} //orders property is an array
var stockOrders = orderBook[stock.symbol];
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
stockOrders.length === 0) {continue;}
createStockTicker(stock);
}
}
setStockTickerClickHandlers();
}
//Displays all stocks
function switchToDisplayAllMode() {
stockMarketPortfolioMode = false;
var stockList = document.getElementById("stock-market-list");
if (stockList == null) {return;}
var modeBtn = clearEventListeners("stock-market-mode");
if (modeBtn) {
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
modeBtn.addEventListener("click", switchToPortfolioMode);
}
while(stockList.firstChild) {stockList.removeChild(stockList.firstChild);}
for (var name in StockMarket) {
if (StockMarket.hasOwnProperty(name)) {
var stock = StockMarket[name];
if (!(stock instanceof Stock)) {continue;} //orders property is an array
createStockTicker(stock);
}
}
setStockTickerClickHandlers();
}
function createStockTicker(stock) { function createStockTicker(stock) {
if (!(stock instanceof Stock)) { if (!(stock instanceof Stock)) {
console.log("Invalid stock in createStockSticker()"); console.log("Invalid stock in createStockSticker()");
@ -825,6 +919,7 @@ function createStockTicker(stock) {
//Div for entire panel //Div for entire panel
var stockDiv = document.createElement("div"); var stockDiv = document.createElement("div");
stockDiv.classList.add("accordion-panel"); stockDiv.classList.add("accordion-panel");
stockDiv.setAttribute("id", tickerId + "-panel");
/* Create panel DOM */ /* Create panel DOM */
var qtyInput = document.createElement("input"), var qtyInput = document.createElement("input"),
@ -961,10 +1056,10 @@ function createStockTicker(stock) {
var pos = longShortSelect.options[longShortSelect.selectedIndex].text; var pos = longShortSelect.options[longShortSelect.selectedIndex].text;
pos === "Long" ? pos = PositionTypes.Long : pos = PositionTypes.Short; pos === "Long" ? pos = PositionTypes.Long : pos = PositionTypes.Short;
var ordType = orderTypeSelect.options[orderTypeSelect.selectedIndex].text; var ordType = orderTypeSelect.options[orderTypeSelect.selectedIndex].text;
var money = Player.money.toMoney(); var money = Player.money.toNumber();
switch (ordType) { switch (ordType) {
case "Market Order": case "Market Order":
var shares = Math.floor(money / stock.price); var shares = Math.floor((money - COMM) / stock.price);
pos === PositionTypes.Long ? buyStock(stock, shares) : shortStock(stock, shares, null); pos === PositionTypes.Long ? buyStock(stock, shares) : shortStock(stock, shares, null);
break; break;
case "Limit Order": case "Limit Order":
@ -980,7 +1075,7 @@ function createStockTicker(stock) {
} else { } else {
type = OrderTypes.StopBuy; type = OrderTypes.StopBuy;
} }
var shares = Math.floor(money / price); var shares = Math.floor((money-COMM) / price);
placeOrder(stock, shares, price, type, pos); placeOrder(stock, shares, price, type, pos);
yesNoTxtInpBoxClose(); yesNoTxtInpBoxClose();
}); });
@ -1046,6 +1141,7 @@ function createStockTicker(stock) {
document.getElementById("stock-market-list").appendChild(li); document.getElementById("stock-market-list").appendChild(li);
updateStockTicker(stock, true); updateStockTicker(stock, true);
updateStockPlayerPosition(stock);
updateStockOrderList(stock); updateStockOrderList(stock);
} }
@ -1082,11 +1178,11 @@ function updateStockTicker(stock, increase) {
var hdr = document.getElementById(tickerId + "-hdr"); var hdr = document.getElementById(tickerId + "-hdr");
if (hdr == null) { if (hdr == null) {
console.log("ERROR: Couldn't find ticker element for stock: " + stock.symbol); if (!stockMarketPortfolioMode) {console.log("ERROR: Couldn't find ticker element for stock: " + stock.symbol);}
return; return;
} }
hdr.innerHTML = stock.name + " - " + stock.symbol + " - $" + formatNumber(stock.price, 2); hdr.innerHTML = stock.name + " - " + stock.symbol + " - $" + formatNumber(stock.price, 2);
if (increase !== null) { if (increase != null) {
increase ? hdr.style.color = "#66ff33" : hdr.style.color = "red"; increase ? hdr.style.color = "#66ff33" : hdr.style.color = "red";
} }
@ -1103,6 +1199,25 @@ function updateStockPlayerPosition(stock) {
return; return;
} }
var tickerId = "stock-market-ticker-" + stock.symbol; var tickerId = "stock-market-ticker-" + stock.symbol;
if (stockMarketPortfolioMode) {
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
StockMarket["Orders"] && StockMarket["Orders"][stock.symbol] &&
StockMarket["Orders"][stock.symbol].length === 0) {
removeElementById(tickerId + "-hdr");
removeElementById(tickerId + "-panel");
return;
} else {
//If the ticker hasn't been created, create it (handles updating)
//If it has been created, continue normally
if (document.getElementById(tickerId + "-hdr") == null) {
createStockTicker(stock);
setStockTickerClickHandlers();
return;
}
}
}
if (!(stock.posTxtEl instanceof Element)) { if (!(stock.posTxtEl instanceof Element)) {
stock.posTxtEl = document.getElementById(tickerId + "-position-text"); stock.posTxtEl = document.getElementById(tickerId + "-position-text");
} }
@ -1151,7 +1266,7 @@ function updateStockOrderList(stock) {
var tickerId = "stock-market-ticker-" + stock.symbol; var tickerId = "stock-market-ticker-" + stock.symbol;
var orderList = document.getElementById(tickerId + "-order-list"); var orderList = document.getElementById(tickerId + "-order-list");
if (orderList == null) { if (orderList == null) {
console.log("ERROR: Could not find order list for " + stock.symbol); if (!stockMarketPortfolioMode) {console.log("ERROR: Could not find order list for " + stock.symbol);}
return; return;
} }
@ -1166,6 +1281,24 @@ function updateStockOrderList(stock) {
return; return;
} }
if (stockMarketPortfolioMode) {
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
StockMarket["Orders"] && StockMarket["Orders"][stock.symbol] &&
StockMarket["Orders"][stock.symbol].length === 0) {
removeElementById(tickerId + "-hdr");
removeElementById(tickerId + "-panel");
return;
} else {
//If the ticker hasn't been created, create it (handles updating)
//If it has been created, continue normally
if (document.getElementById(tickerId + "-hdr") == null) {
createStockTicker(stock);
setStockTickerClickHandlers();
return;
}
}
}
//Remove everything from list //Remove everything from list
while (orderList.firstChild) { while (orderList.firstChild) {
orderList.removeChild(orderList.firstChild); orderList.removeChild(orderList.firstChild);

@ -493,7 +493,7 @@ let Terminal = {
else {rootAccess = "NO";} else {rootAccess = "NO";}
post("Root Access: " + rootAccess); post("Root Access: " + rootAccess);
post("Required hacking skill: " + Player.getCurrentServer().requiredHackingSkill); post("Required hacking skill: " + Player.getCurrentServer().requiredHackingSkill);
post("Estimated server security level(1-100): " + formatNumber(addOffset(Player.getCurrentServer().hackDifficulty, 5), 3)); post("Estimated server security level: " + formatNumber(addOffset(Player.getCurrentServer().hackDifficulty, 5), 3));
post("Estimated chance to hack: " + formatNumber(addOffset(Player.calculateHackingChance() * 100, 5), 2) + "%"); post("Estimated chance to hack: " + formatNumber(addOffset(Player.calculateHackingChance() * 100, 5), 2) + "%");
post("Estimated time to hack: " + formatNumber(addOffset(Player.calculateHackingTime(), 5), 3) + " seconds"); post("Estimated time to hack: " + formatNumber(addOffset(Player.calculateHackingTime(), 5), 3) + " seconds");
post("Estimated total money available on server: $" + formatNumber(addOffset(Player.getCurrentServer().moneyAvailable, 5), 2)); post("Estimated total money available on server: $" + formatNumber(addOffset(Player.getCurrentServer().moneyAvailable, 5), 2));

@ -38,6 +38,14 @@ function clearEventListenersEl(el) {
return newElem; return newElem;
} }
//Given its id, this function removes an element AND its children
function removeElementById(id) {
var elem = document.getElementById(id);
if (elem == null) {return;}
while(elem.firstChild) {elem.removeChild(elem.firstChild);}
elem.parentNode.removeChild(elem);
}
function getRandomInt(min, max) { function getRandomInt(min, max) {
if (min > max) {return getRandomInt(max, min);} if (min > max) {return getRandomInt(max, min);}
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
@ -67,4 +75,5 @@ function powerOfTwo(n) {
} }
export {sizeOfObject, addOffset, clearEventListeners, getRandomInt, export {sizeOfObject, addOffset, clearEventListeners, getRandomInt,
compareArrays, printArray, powerOfTwo, clearEventListenersEl}; compareArrays, printArray, powerOfTwo, clearEventListenersEl,
removeElementById};

@ -1,4 +1,5 @@
import {printArray} from "./HelperFunctions.js"; import {killWorkerScript} from "../src/NetscriptWorker.js";
import {printArray, clearEventListeners} from "./HelperFunctions.js";
$(document).keydown(function(event) { $(document).keydown(function(event) {
if (logBoxOpened && event.keyCode == 27) { if (logBoxOpened && event.keyCode == 27) {
@ -15,6 +16,7 @@ function logBoxInit() {
logBoxClose(); logBoxClose();
return false; return false;
}); });
document.getElementById("log-box-text-header").style.display = "inline-block";
}; };
document.addEventListener("DOMContentLoaded", logBoxInit, false); document.addEventListener("DOMContentLoaded", logBoxInit, false);
@ -35,23 +37,30 @@ function logBoxOpen() {
var logBoxOpened = false; var logBoxOpened = false;
var logBoxCurrentScript = null; var logBoxCurrentScript = null;
//ram argument is in GB
function logBoxCreate(script) { function logBoxCreate(script) {
logBoxCurrentScript = script; logBoxCurrentScript = script;
var killScriptBtn = clearEventListeners("log-box-kill-script");
killScriptBtn.addEventListener("click", ()=>{
killWorkerScript(script, script.server);
return false;
});
document.getElementById('log-box-kill-script').style.display = "inline-block";
logBoxOpen(); logBoxOpen();
document.getElementById("log-box-text-header").innerHTML = document.getElementById("log-box-text-header").innerHTML =
logBoxCurrentScript.filename + " " + printArray(logBoxCurrentScript.args) + ":<br><br>"; logBoxCurrentScript.filename + " " + printArray(logBoxCurrentScript.args) + ":<br><br>";
logBoxCurrentScript.logUpd = true;
logBoxUpdateText(); logBoxUpdateText();
} }
function logBoxUpdateText() { function logBoxUpdateText() {
var txt = document.getElementById("log-box-text"); var txt = document.getElementById("log-box-text");
if (logBoxCurrentScript && logBoxOpened && txt) { if (logBoxCurrentScript && logBoxOpened && txt && logBoxCurrentScript.logUpd) {
txt.innerHTML = ""; txt.innerHTML = "";
for (var i = 0; i < logBoxCurrentScript.logs.length; ++i) { for (var i = 0; i < logBoxCurrentScript.logs.length; ++i) {
txt.innerHTML += logBoxCurrentScript.logs[i]; txt.innerHTML += logBoxCurrentScript.logs[i];
txt.innerHTML += "<br>"; txt.innerHTML += "<br>";
} }
logBoxCurrentScript.logUpd = false;
} }
} }