mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-10 01:33:54 +01:00
Various QOL improvements and bug fixes
This commit is contained in:
parent
8c8e3f2476
commit
840df3087f
@ -454,3 +454,48 @@ do not allow cross-origin origin sharing (CORS). This includes websites such
|
||||
as gist and pastebin. One notable site it will work on is rawgithub. Example::
|
||||
|
||||
$ wget https://raw.githubusercontent.com/danielyxie/bitburner/master/README.md game_readme.txt
|
||||
|
||||
Argument Parsing
|
||||
----------------
|
||||
When evaluating a terminal command, arguments are initially parsed based on whitespace (usually spaces).
|
||||
Each whitespace character signifies the end of an argument, and potentially the start
|
||||
of new one. For most terminal commands, this is all you need to know.
|
||||
|
||||
When running scripts, however, it is important to know in more detail how arguments are parsed.
|
||||
There are two main points:
|
||||
|
||||
1. Quotation marks can be used to wrap a single argument and force it to be parsed as
|
||||
a string. Any whitespace inside the quotation marks will not cause a new argument
|
||||
to be parsed.
|
||||
2. Anything that can represent a number is automatically cast to a number, unless its
|
||||
surrounded by quotation marks.
|
||||
|
||||
Here's an example to show how these rules work. Consider the following script `argType.script`::
|
||||
|
||||
tprint("Number of args: " + args.length);
|
||||
for (var i = 0; i < args.length; ++i) {
|
||||
tprint(typeof args[i]);
|
||||
}
|
||||
|
||||
Then if we run the following terminal command::
|
||||
|
||||
$ run argType.script 123 1e3 "5" "this is a single argument"
|
||||
|
||||
We'll see the following in the Terminal::
|
||||
|
||||
Running script with 1 thread(s) and args: [123, 1000, "5", "this is a single argument"].
|
||||
May take a few seconds to start up the process...
|
||||
argType.script: Number of args: 4
|
||||
argType.script: number
|
||||
argType.script: number
|
||||
argType.script: string
|
||||
argType.script: string
|
||||
|
||||
Chaining Commands
|
||||
-----------------
|
||||
You can run multiple Terminal commands at once by separating each command
|
||||
with a semicolon (;).
|
||||
|
||||
Example::
|
||||
|
||||
$ run foo.script; tail foo.script
|
||||
|
@ -1211,6 +1211,26 @@ vsprintf
|
||||
|
||||
See `this link <https://github.com/alexei/sprintf.js>`_ for details.
|
||||
|
||||
nFormat
|
||||
^^^^^^^
|
||||
|
||||
.. js:function:: nFormat(n, format)
|
||||
|
||||
:param number n: Number to format
|
||||
:param string format: Formatter
|
||||
|
||||
Converts a number into a string with the specified formatter. This uses the
|
||||
`numeraljs <http://numeraljs.com/>`_ library, so the formatters must be compatible
|
||||
with that.
|
||||
|
||||
This is the same function that the game itself uses to display numbers.
|
||||
|
||||
Examples::
|
||||
|
||||
nFormat(1.23e9, "$0.000a"); // Returns "$1.230b"
|
||||
nFormat(12345.678, "0,0"); // Returns "12,346"
|
||||
nFormat(0.84, "0.0%"); // Returns "84.0%
|
||||
|
||||
prompt
|
||||
^^^^^^
|
||||
|
||||
|
@ -209,7 +209,19 @@ to specify a namespace for the import::
|
||||
//...
|
||||
}
|
||||
|
||||
Note that exporting functions is not required.
|
||||
.. warning:: For those who are experienced with JavaScript, note that the `export`
|
||||
keyword should **NOT** be used in :ref:`netscript1`, as this will break the script.
|
||||
It can, however, be used in :ref:`netscriptjs` (but it's not required).
|
||||
|
||||
Importing in NetscriptJS
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
There is a minor annoyance when using the `import` feature in :ref:`netscriptjs`.
|
||||
If you make a change in a NetscriptJS script, then you have to manually "refresh" all other
|
||||
scripts that import from that script.
|
||||
|
||||
The easiest way to do this is to simply save and then refresh the game. Alternatively,
|
||||
you can open up all the scripts that need to be "refreshed" in the script editor
|
||||
and then simply re-save them.
|
||||
|
||||
Standard, Built-In JavaScript Objects
|
||||
-------------------------------------
|
||||
|
@ -11,7 +11,8 @@ import {createProgressBarText} from "../utils/helpers/createProgressBarText"
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {getElementById} from "../utils/uiHelpers/getElementById";
|
||||
import {logBoxCreate} from "../utils/LogBox";
|
||||
import {formatNumber} from "../utils/StringHelperFunctions";
|
||||
import {formatNumber,
|
||||
convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
|
||||
import {removeElement} from "../utils/uiHelpers/removeElement";
|
||||
import {roundToTwo} from "../utils/helpers/roundToTwo";
|
||||
@ -242,9 +243,9 @@ function updateActiveScriptsItems(maxTasks=150) {
|
||||
}
|
||||
}
|
||||
|
||||
getElementById("active-scripts-total-production-active").innerText = numeralWrapper.format(total, '$0.000a');
|
||||
getElementById("active-scripts-total-prod-aug-total").innerText = numeralWrapper.format(Player.scriptProdSinceLastAug, '$0.000a');
|
||||
getElementById("active-scripts-total-prod-aug-avg").innerText = numeralWrapper.format(Player.scriptProdSinceLastAug / (Player.playtimeSinceLastAug/1000), '$0.000a');
|
||||
getElementById("active-scripts-total-production-active").innerText = numeralWrapper.formatMoney(total);
|
||||
getElementById("active-scripts-total-prod-aug-total").innerText = numeralWrapper.formatMoney(Player.scriptProdSinceLastAug);
|
||||
getElementById("active-scripts-total-prod-aug-avg").innerText = numeralWrapper.formatMoney(Player.scriptProdSinceLastAug / (Player.playtimeSinceLastAug/1000));
|
||||
return total;
|
||||
}
|
||||
|
||||
@ -252,7 +253,7 @@ function updateActiveScriptsItems(maxTasks=150) {
|
||||
function updateActiveScriptsItemContent(workerscript) {
|
||||
var server = getServer(workerscript.serverIp);
|
||||
if (server == null) {
|
||||
console.log("ERROR: Invalid server IP for workerscript.");
|
||||
console.log("ERROR: Invalid server IP for workerscript in updateActiveScriptsItemContent().");
|
||||
return;
|
||||
}
|
||||
let hostname = server.hostname;
|
||||
@ -280,7 +281,7 @@ function updateActiveScriptsItemContent(workerscript) {
|
||||
function updateActiveScriptsText(workerscript, item, itemName) {
|
||||
var server = getServer(workerscript.serverIp);
|
||||
if (server == null) {
|
||||
console.log("ERROR: Invalid server IP for workerscript.");
|
||||
console.log("ERROR: Invalid server IP for workerscript for updateActiveScriptsText()");
|
||||
return;
|
||||
}
|
||||
let hostname = server.hostname;
|
||||
@ -298,24 +299,27 @@ function updateActiveScriptsText(workerscript, item, itemName) {
|
||||
|
||||
removeChildrenFromElement(item);
|
||||
|
||||
//Online
|
||||
var onlineTotalMoneyMade = "Total online production: $" + formatNumber(workerscript.scriptRef.onlineMoneyMade, 2);
|
||||
var onlineTotalExpEarned = (Array(26).join(" ") + formatNumber(workerscript.scriptRef.onlineExpGained, 2) + " hacking exp").replace( / /g, " ");
|
||||
var onlineTime = "Online Time: " + convertTimeMsToTimeElapsedString(workerscript.scriptRef.onlineRunningTime * 1e3);
|
||||
var offlineTime = "Offline Time: " + convertTimeMsToTimeElapsedString(workerscript.scriptRef.offlineRunningTime * 1e3);
|
||||
|
||||
var onlineMpsText = "Online production rate: $" + formatNumber(onlineMps, 2) + "/second";
|
||||
//Online
|
||||
var onlineTotalMoneyMade = "Total online production: " + numeralWrapper.formatMoney(workerscript.scriptRef.onlineMoneyMade);
|
||||
var onlineTotalExpEarned = (Array(26).join(" ") + numeralWrapper.formatBigNumber(workerscript.scriptRef.onlineExpGained) + " hacking exp").replace( / /g, " ");
|
||||
|
||||
var onlineMpsText = "Online production rate: " + numeralWrapper.formatMoney(onlineMps) + " / second";
|
||||
var onlineEps = workerscript.scriptRef.onlineExpGained / workerscript.scriptRef.onlineRunningTime;
|
||||
var onlineEpsText = (Array(25).join(" ") + formatNumber(onlineEps, 4) + " hacking exp/second").replace( / /g, " ");
|
||||
var onlineEpsText = (Array(25).join(" ") + numeralWrapper.formatBigNumber(onlineEps) + " hacking exp / second").replace( / /g, " ");
|
||||
|
||||
//Offline
|
||||
var offlineTotalMoneyMade = "Total offline production: $" + formatNumber(workerscript.scriptRef.offlineMoneyMade, 2);
|
||||
var offlineTotalExpEarned = (Array(27).join(" ") + formatNumber(workerscript.scriptRef.offlineExpGained, 2) + " hacking exp").replace( / /g, " ");
|
||||
var offlineTotalMoneyMade = "Total offline production: " + numeralWrapper.formatMoney(workerscript.scriptRef.offlineMoneyMade);
|
||||
var offlineTotalExpEarned = (Array(27).join(" ") + numeralWrapper.formatBigNumber(workerscript.scriptRef.offlineExpGained) + " hacking exp").replace( / /g, " ");
|
||||
|
||||
var offlineMps = workerscript.scriptRef.offlineMoneyMade / workerscript.scriptRef.offlineRunningTime;
|
||||
var offlineMpsText = "Offline production rate: $" + formatNumber(offlineMps, 2) + "/second";
|
||||
var offlineMpsText = "Offline production rate: " + numeralWrapper.formatMoney(offlineMps) + " / second";
|
||||
var offlineEps = workerscript.scriptRef.offlineExpGained / workerscript.scriptRef.offlineRunningTime;
|
||||
var offlineEpsText = (Array(26).join(" ") + formatNumber(offlineEps, 4) + " hacking exp/second").replace( / /g, " ");
|
||||
var offlineEpsText = (Array(26).join(" ") + numeralWrapper.formatBigNumber(offlineEps) + " hacking exp / second").replace( / /g, " ");
|
||||
|
||||
item.innerHTML = onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" +
|
||||
item.innerHTML = onlineTime + "<br>" + offlineTime + "<br>" + onlineTotalMoneyMade + "<br>" + onlineTotalExpEarned + "<br>" +
|
||||
onlineMpsText + "<br>" + onlineEpsText + "<br>" + offlineTotalMoneyMade + "<br>" + offlineTotalExpEarned + "<br>" +
|
||||
offlineMpsText + "<br>" + offlineEpsText + "<br>";
|
||||
return onlineMps;
|
||||
|
@ -78,6 +78,9 @@ export class Augmentation {
|
||||
// The Player/Person classes
|
||||
mults: IMap<number> = {}
|
||||
|
||||
// Initial cost. Doesn't change when you purchase multiple Augmentation
|
||||
startingCost: number = 0;
|
||||
|
||||
constructor(params: IConstructorParams={ info: "", moneyCost: 0, name: "", repCost: 0 }) {
|
||||
this.name = params.name;
|
||||
this.info = params.info;
|
||||
@ -85,6 +88,7 @@ export class Augmentation {
|
||||
|
||||
this.baseRepRequirement = params.repCost * CONSTANTS.AugmentationRepMultiplier * BitNodeMultipliers.AugmentationRepCost;
|
||||
this.baseCost = params.moneyCost * CONSTANTS.AugmentationCostMultiplier * BitNodeMultipliers.AugmentationMoneyCost;
|
||||
this.startingCost = this.baseCost;
|
||||
|
||||
this.level = 0;
|
||||
|
||||
|
@ -512,17 +512,22 @@ export let CONSTANTS: IMap<any> = {
|
||||
`
|
||||
v0.43.1
|
||||
* Terminal changes:
|
||||
** Quoted arguments are now properly parsed. (e.g. run f.script "this is one argument" will be correctly parsed)
|
||||
** Quoted arguments are now properly parsed. (e.g. 'run f.script "this is one argument"' will be correctly parsed)
|
||||
** Errors are now shown in red text
|
||||
** 'unalias' command now has a different format and no longer needs the quotations
|
||||
** Bug Fix: Fixed several edge cases where autocomplete wasnt working properly
|
||||
|
||||
* Added two new Bladeburner skills for increasing money and experience gain
|
||||
* Made some minor adjustments to Bladeburner UI
|
||||
* Corporation "Smart Factories" and "Smart Storage" upgrades have slightly lower price multipliers
|
||||
* Added nFormat Netscript function
|
||||
* Added 6 new Coding Contract problems
|
||||
* Updated documentation with list of all Coding Contract problems
|
||||
* Minor improvements for 'Active Scripts' UI
|
||||
* Implemented several optimizations for active scripts. The game should now use less memory and the savefile should be slightly smaller when there are many scripts running
|
||||
* Bug Fix: A Stock Forecast should no longer go above 1 (i.e. 100%)
|
||||
* Bug Fix: The cost of Resleeves should no longer be affected by buying Augs
|
||||
* Bug Fix: You can now call the prompt() Netscript function from multiple scripts simultaneously
|
||||
`
|
||||
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ import {StockMarket, StockSymbols, SymbolToStockMap,
|
||||
sellStock, updateStockPlayerPosition,
|
||||
shortStock, sellShort, OrderTypes,
|
||||
PositionTypes, placeOrder, cancelOrder} from "./StockMarket/StockMarket";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {post} from "./ui/postToTerminal";
|
||||
import {TextFile, getTextFile, createTextFile} from "./TextFile";
|
||||
|
||||
@ -76,6 +77,10 @@ import {yesNoBoxClose, yesNoBoxGetYesButton,
|
||||
yesNoBoxGetNoButton, yesNoBoxCreate,
|
||||
yesNoBoxOpen} from "../utils/YesNoBox";
|
||||
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
|
||||
var hasCorporationSF = false, //Source-File 3
|
||||
hasSingularitySF = false, //Source-File 4
|
||||
hasAISF = false, //Source-File 5
|
||||
@ -2453,6 +2458,14 @@ function NetscriptFunctions(workerScript) {
|
||||
return runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime;
|
||||
}
|
||||
},
|
||||
nFormat : function(n, format) {
|
||||
if (workerScript.checkingRam) { return 0; }
|
||||
if (isNaN(n) || isNaN(parseFloat(n)) || typeof format !== "string") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return numeralWrapper.format(parseFloat(n), format);
|
||||
},
|
||||
getTimeSinceLastAug : function() {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getTimeSinceLastAug", CONSTANTS.ScriptGetHackTimeRamCost);
|
||||
@ -2467,19 +2480,32 @@ function NetscriptFunctions(workerScript) {
|
||||
return false;
|
||||
}
|
||||
if (!isString(txt)) {txt = String(txt);}
|
||||
var yesBtn = yesNoBoxGetYesButton(), noBtn = yesNoBoxGetNoButton();
|
||||
yesBtn.innerHTML = "Yes";
|
||||
noBtn.innerHTML = "No";
|
||||
|
||||
// The id for this popup will consist of the first 20 characters of the prompt string..
|
||||
// Thats hopefully good enough to be unique
|
||||
const popupId = `prompt-popup-${txt.slice(0, 20)}`;
|
||||
const textElement = createElement("p", { innerHTML: txt });
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
yesBtn.addEventListener("click", ()=>{
|
||||
yesNoBoxClose();
|
||||
const yesBtn = createElement("button", {
|
||||
class: "popup-box-button",
|
||||
innerText: "Yes",
|
||||
clickListener: () => {
|
||||
removeElementById(popupId);
|
||||
resolve(true);
|
||||
},
|
||||
});
|
||||
noBtn.addEventListener("click", ()=>{
|
||||
yesNoBoxClose();
|
||||
|
||||
const noBtn = createElement("button", {
|
||||
class: "popup-box-button",
|
||||
innerText: "No",
|
||||
clickListener: () => {
|
||||
removeElementById(popupId);
|
||||
resolve(false);
|
||||
},
|
||||
});
|
||||
yesNoBoxCreate(txt);
|
||||
|
||||
createPopup(popupId, [textElement, yesBtn, noBtn]);
|
||||
});
|
||||
},
|
||||
wget : async function(url, target, ip=workerScript.serverIp) {
|
||||
|
@ -219,6 +219,8 @@ function startNetscript1Script(workerScript) {
|
||||
let fnPromise = entry.apply(null, fnArgs);
|
||||
fnPromise.then(function(res) {
|
||||
cb(res);
|
||||
}).catch(function(e) {
|
||||
// Do nothing?
|
||||
});
|
||||
}
|
||||
int.setProperty(scope, name, int.createAsyncFunction(tempWrapper));
|
||||
@ -278,7 +280,7 @@ function startNetscript1Script(workerScript) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
function runInterpreter() {
|
||||
try {
|
||||
if (workerScript.env.stopFlag) {return reject(workerScript);}
|
||||
if (workerScript.env.stopFlag) { return reject(workerScript); }
|
||||
|
||||
if (interpreter.step()) {
|
||||
window.setTimeout(runInterpreter, Settings.CodeInstructionRunTime);
|
||||
@ -498,7 +500,7 @@ function runScriptsLoop() {
|
||||
p = startNetscript2Script(workerScripts[i]);
|
||||
} else {
|
||||
p = startNetscript1Script(workerScripts[i]);
|
||||
if (!(p instanceof Promise)) {continue;}
|
||||
if (!(p instanceof Promise)) { continue; }
|
||||
}
|
||||
|
||||
//Once the code finishes (either resolved or rejected, doesnt matter), set its
|
||||
@ -539,7 +541,6 @@ function runScriptsLoop() {
|
||||
}
|
||||
w.running = false;
|
||||
w.env.stopFlag = true;
|
||||
|
||||
} else if (isScriptErrorMessage(w)) {
|
||||
dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer");
|
||||
console.log("ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN: " + w.toString());
|
||||
|
@ -44,7 +44,7 @@ export class Resleeve extends Person {
|
||||
console.error(`Could not find Augmentation ${this.augmentations[i].name}`);
|
||||
continue;
|
||||
}
|
||||
totalAugmentationCost += aug!.baseCost;
|
||||
totalAugmentationCost += aug!.startingCost;
|
||||
}
|
||||
|
||||
return (totalExp * CostPerExp) + (totalAugmentationCost * Math.pow(NumAugsExponent, this.augmentations.length));
|
||||
|
@ -34,6 +34,9 @@ import {initStockMarket, initSymbolToStockMap,
|
||||
stockMarketContentCreated,
|
||||
setStockMarketContentCreated} from "./StockMarket/StockMarket";
|
||||
import {Terminal, postNetburnerText} from "./Terminal";
|
||||
|
||||
import {Page, routing} from "./ui/navigationTracking";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {removeElementById} from "../utils/uiHelpers/removeElementById";
|
||||
@ -45,6 +48,13 @@ let BitNode8StartingMoney = 250e6;
|
||||
|
||||
//Prestige by purchasing augmentation
|
||||
function prestigeAugmentation() {
|
||||
// Load Terminal Screen
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
Terminal.resetTerminalInput();
|
||||
Engine.loadTerminalContent();
|
||||
routing.navigateTo(Page.Terminal);
|
||||
|
||||
initBitNodeMultipliers();
|
||||
|
||||
Player.prestigeAugmentation();
|
||||
@ -146,12 +156,6 @@ function prestigeAugmentation() {
|
||||
var watchlist = document.getElementById("stock-market-watchlist-filter");
|
||||
watchlist.value = ""; //Reset watchlist filter
|
||||
|
||||
//Load Terminal Screen
|
||||
var mainMenu = document.getElementById("mainmenu-container");
|
||||
mainMenu.style.visibility = "visible";
|
||||
Terminal.resetTerminalInput();
|
||||
Engine.loadTerminalContent();
|
||||
|
||||
// Refresh Main Menu (the 'World' menu, specifically)
|
||||
document.getElementById("world-menu-header").click();
|
||||
document.getElementById("world-menu-header").click();
|
||||
|
@ -165,7 +165,7 @@ $(document).keydown(function(event) {
|
||||
|
||||
const semiColonIndex = input.lastIndexOf(";");
|
||||
if(semiColonIndex !== -1) {
|
||||
input = input.slice(semiColonIndex+1);
|
||||
input = input.slice(semiColonIndex + 1);
|
||||
}
|
||||
|
||||
input = input.trim();
|
||||
@ -310,6 +310,14 @@ function tabCompletion(command, arg, allPossibilities, index=0) {
|
||||
}
|
||||
}
|
||||
|
||||
const textBox = document.getElementById("terminal-input-text-box");
|
||||
if (textBox == null) {
|
||||
console.warn(`Couldn't find terminal input DOM element (id=terminal-input-text-box) when trying to autocomplete`);
|
||||
return;
|
||||
}
|
||||
const oldValue = textBox.value;
|
||||
const semiColonIndex = oldValue.lastIndexOf(";");
|
||||
|
||||
var val = "";
|
||||
if (allPossibilities.length == 0) {
|
||||
return;
|
||||
@ -321,10 +329,7 @@ function tabCompletion(command, arg, allPossibilities, index=0) {
|
||||
val = command + " " + allPossibilities[0];
|
||||
}
|
||||
|
||||
const textBox = document.getElementById("terminal-input-text-box");
|
||||
const oldValue = textBox.value;
|
||||
const semiColonIndex = oldValue.lastIndexOf(";");
|
||||
if(semiColonIndex === -1) {
|
||||
if (semiColonIndex === -1) {
|
||||
// no ; replace the whole thing.
|
||||
textBox.value = val;
|
||||
} else {
|
||||
@ -332,7 +337,7 @@ function tabCompletion(command, arg, allPossibilities, index=0) {
|
||||
textBox.value = textBox.value.slice(0, semiColonIndex+1)+" "+val;
|
||||
}
|
||||
|
||||
document.getElementById("terminal-input-text-box").focus();
|
||||
textBox.focus();
|
||||
} else {
|
||||
var longestStartSubstr = longestCommonStart(allPossibilities);
|
||||
//If the longest common starting substring of remaining possibilities is the same
|
||||
@ -348,8 +353,15 @@ function tabCompletion(command, arg, allPossibilities, index=0) {
|
||||
post("> " + command);
|
||||
post(allOptionsStr);
|
||||
} else {
|
||||
document.getElementById("terminal-input-text-box").value = longestStartSubstr;
|
||||
document.getElementById("terminal-input-text-box").focus();
|
||||
if (semiColonIndex === -1) {
|
||||
// No ; just replace the whole thing
|
||||
textBox.value = longestStartSubstr;
|
||||
} else {
|
||||
// Multiple commands, so only replace after the last semicolon
|
||||
textBox.value = textBox.value.slice(0, semiColonIndex + 1) + " " + longestStartSubstr;
|
||||
}
|
||||
|
||||
textBox.focus();
|
||||
}
|
||||
} else {
|
||||
if (longestStartSubstr == arg) {
|
||||
@ -357,8 +369,15 @@ function tabCompletion(command, arg, allPossibilities, index=0) {
|
||||
post("> " + command + " " + arg);
|
||||
post(allOptionsStr);
|
||||
} else {
|
||||
document.getElementById("terminal-input-text-box").value = command + " " + longestStartSubstr;
|
||||
document.getElementById("terminal-input-text-box").focus();
|
||||
if (semiColonIndex == -1) {
|
||||
// No ; so just replace the whole thing
|
||||
textBox.value = command + " " + longestStartSubstr;
|
||||
} else {
|
||||
// Multiple commands, so only replace after the last semiclon
|
||||
textBox.value = textBox.value.slice(0, semiColonIndex + 1) + " " + command + " " + longestStartSubstr;
|
||||
}
|
||||
|
||||
textBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1032,7 +1032,6 @@ const Engine = {
|
||||
//is necessary and then resets the counter
|
||||
checkCounters: function() {
|
||||
if (Engine.Counters.autoSaveCounter <= 0) {
|
||||
saveObject.saveGame(indexedDb);
|
||||
if (Settings.AutosaveInterval == null) {
|
||||
Settings.AutosaveInterval = 60;
|
||||
}
|
||||
@ -1040,6 +1039,7 @@ const Engine = {
|
||||
Engine.Counters.autoSaveCounter = Infinity;
|
||||
} else {
|
||||
Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5;
|
||||
saveObject.saveGame(indexedDb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ function replaceAt(base: string, index: number, character: string): string {
|
||||
|
||||
/*
|
||||
Converts a date representing time in milliseconds to a string with the format H hours M minutes and S seconds
|
||||
e.g. 10000 -> "0 hours 0 minutes and 10 seconds"
|
||||
120000 -> "0 0 hours 2 minutes and 0 seconds"
|
||||
e.g. 10000 -> "10 seconds"
|
||||
120000 -> "2 minutes and 0 seconds"
|
||||
*/
|
||||
function convertTimeMsToTimeElapsedString(time: number): string {
|
||||
const millisecondsPerSecond: number = 1000;
|
||||
|
@ -1,6 +1,19 @@
|
||||
/**
|
||||
* Returns the input array as a comma separated string.
|
||||
*
|
||||
* Does several things that Array.toString() doesn't do
|
||||
* - Adds brackets around the array
|
||||
* - Adds quotation marks around strings
|
||||
*/
|
||||
export function arrayToString<T>(a: T[]) {
|
||||
return `[${a.join(", ")}]`;
|
||||
const vals: any[] = [];
|
||||
for (let i = 0; i < a.length; ++i) {
|
||||
let elem: any = a[i];
|
||||
if (typeof elem === "string") {
|
||||
elem = `"${elem}"`;
|
||||
}
|
||||
vals.push(elem);
|
||||
}
|
||||
|
||||
return `[${vals.join(", ")}]`;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user