2019-03-05 02:40:28 +01:00
|
|
|
import { calculateRamUsage } from "./RamCalculations";
|
|
|
|
import { isScriptFilename } from "./ScriptHelpersTS";
|
2018-05-06 00:13:35 +02:00
|
|
|
|
2019-03-05 02:40:28 +01:00
|
|
|
import {CONSTANTS} from "../Constants";
|
|
|
|
import {Engine} from "../engine";
|
|
|
|
import { parseFconfSettings } from "../Fconf/Fconf";
|
|
|
|
import { FconfSettings } from "../Fconf/FconfSettings";
|
2017-08-30 19:44:29 +02:00
|
|
|
import {iTutorialSteps, iTutorialNextStep,
|
2019-03-05 02:40:28 +01:00
|
|
|
ITutorial} from "../InteractiveTutorial";
|
|
|
|
import { addWorkerScript } from "../NetscriptWorker";
|
|
|
|
import { Player } from "../Player";
|
|
|
|
import { AceEditor } from "../ScriptEditor/Ace";
|
|
|
|
import { CodeMirrorEditor } from "../ScriptEditor/CodeMirror";
|
|
|
|
import { AllServers } from "../Server/AllServers";
|
|
|
|
import { processSingleServerGrowth } from "../Server/ServerHelpers";
|
|
|
|
import { Settings } from "../Settings/Settings";
|
|
|
|
import { EditorSetting } from "../Settings/SettingEnums";
|
|
|
|
import {TextFile} from "../TextFile";
|
|
|
|
|
|
|
|
import {Page, routing} from "../ui/navigationTracking";
|
|
|
|
import {numeralWrapper} from "../ui/numeralFormat";
|
|
|
|
|
|
|
|
import {dialogBoxCreate} from "../../utils/DialogBox";
|
2017-08-30 19:44:29 +02:00
|
|
|
import {Reviver, Generic_toJSON,
|
2019-03-05 02:40:28 +01:00
|
|
|
Generic_fromJSON} from "../../utils/JSONReviver";
|
|
|
|
import {compareArrays} from "../../utils/helpers/compareArrays";
|
|
|
|
import {createElement} from "../../utils/uiHelpers/createElement";
|
2018-05-06 00:13:35 +02:00
|
|
|
|
2018-01-27 07:52:39 +01:00
|
|
|
var scriptEditorRamCheck = null, scriptEditorRamText = null;
|
2019-03-05 02:40:28 +01:00
|
|
|
export function scriptEditorInit() {
|
2019-01-27 23:08:45 +01:00
|
|
|
// Wrapper container that holds all the buttons below the script editor
|
|
|
|
const wrapper = document.getElementById("script-editor-buttons-wrapper");
|
2018-01-27 07:52:39 +01:00
|
|
|
if (wrapper == null) {
|
2019-01-27 23:08:45 +01:00
|
|
|
console.error("Could not find 'script-editor-buttons-wrapper'");
|
|
|
|
return false;
|
2018-01-27 07:52:39 +01:00
|
|
|
}
|
2018-06-14 08:26:54 +02:00
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
// Beautify button
|
|
|
|
const beautifyButton = createElement("button", {
|
|
|
|
class: "std-button",
|
|
|
|
display: "inline-block",
|
|
|
|
innerText: "Beautify",
|
2018-01-27 07:52:39 +01:00
|
|
|
clickListener:()=>{
|
2019-01-27 23:08:45 +01:00
|
|
|
let editor = getCurrentEditor();
|
|
|
|
if (editor != null) {
|
|
|
|
editor.beautifyScript();
|
|
|
|
}
|
2018-01-27 07:52:39 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
// Text that displays RAM calculation
|
2018-01-27 07:52:39 +01:00
|
|
|
scriptEditorRamText = createElement("p", {
|
|
|
|
display:"inline-block", margin:"10px", id:"script-editor-status-text"
|
|
|
|
});
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
// Label for checkbox (defined below)
|
|
|
|
const checkboxLabel = createElement("label", {
|
2018-01-27 07:52:39 +01:00
|
|
|
for:"script-editor-ram-check", margin:"4px", marginTop: "8px",
|
|
|
|
innerText:"Dynamic RAM Usage Checker", color:"white",
|
|
|
|
tooltip:"Enable/Disable the dynamic RAM Usage display. You may " +
|
|
|
|
"want to disable it for very long scripts because there may be " +
|
|
|
|
"performance issues"
|
2017-05-03 06:38:58 +02:00
|
|
|
});
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
// Checkbox for enabling/disabling dynamic RAM calculation
|
2018-01-27 07:52:39 +01:00
|
|
|
scriptEditorRamCheck = createElement("input", {
|
|
|
|
type:"checkbox", name:"script-editor-ram-check", id:"script-editor-ram-check",
|
|
|
|
margin:"4px", marginTop: "8px",
|
|
|
|
});
|
|
|
|
scriptEditorRamCheck.checked = true;
|
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
// Link to Netscript documentation
|
|
|
|
const documentationButton = createElement("a", {
|
|
|
|
class: "std-button",
|
|
|
|
display: "inline-block",
|
2018-02-24 23:55:06 +01:00
|
|
|
href:"https://bitburner.readthedocs.io/en/latest/index.html",
|
2019-01-27 23:08:45 +01:00
|
|
|
innerText:"Netscript Documentation",
|
|
|
|
target:"_blank",
|
2018-01-27 07:52:39 +01:00
|
|
|
});
|
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
// Save and Close button
|
|
|
|
const closeButton = createElement("button", {
|
|
|
|
class: "std-button",
|
|
|
|
display: "inline-block",
|
|
|
|
innerText: "Save & Close (Ctrl/Cmd + b)",
|
|
|
|
clickListener:()=>{
|
|
|
|
saveAndCloseScriptEditor();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add all buttons to the UI
|
2018-06-14 08:26:54 +02:00
|
|
|
wrapper.appendChild(beautifyButton);
|
2018-01-27 07:52:39 +01:00
|
|
|
wrapper.appendChild(closeButton);
|
|
|
|
wrapper.appendChild(scriptEditorRamText);
|
|
|
|
wrapper.appendChild(scriptEditorRamCheck);
|
|
|
|
wrapper.appendChild(checkboxLabel);
|
|
|
|
wrapper.appendChild(documentationButton);
|
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
// Initialize editors
|
|
|
|
const initParams = {
|
|
|
|
saveAndCloseFn: saveAndCloseScriptEditor,
|
|
|
|
quitFn: Engine.loadTerminalContent,
|
|
|
|
}
|
|
|
|
|
|
|
|
AceEditor.init(initParams);
|
|
|
|
CodeMirrorEditor.init(initParams);
|
|
|
|
|
|
|
|
// Setup the selector for which Editor to use
|
|
|
|
const editorSelector = document.getElementById("script-editor-option-editor");
|
|
|
|
if (editorSelector == null) {
|
|
|
|
console.error(`Could not find DOM Element for editor selector (id=script-editor-option-editor)`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < editorSelector.options.length; ++i) {
|
|
|
|
if (editorSelector.options[i].value === Settings.Editor) {
|
|
|
|
editorSelector.selectedIndex = i;
|
|
|
|
break;
|
2018-03-03 22:05:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
editorSelector.onchange = () => {
|
|
|
|
const opt = editorSelector.value;
|
|
|
|
switch (opt) {
|
|
|
|
case EditorSetting.Ace:
|
|
|
|
const codeMirrorCode = CodeMirrorEditor.getCode();
|
|
|
|
const codeMirrorFn = CodeMirrorEditor.getFilename();
|
|
|
|
AceEditor.create();
|
|
|
|
CodeMirrorEditor.setInvisible();
|
|
|
|
AceEditor.openScript(codeMirrorFn, codeMirrorCode);
|
2018-03-03 22:05:33 +01:00
|
|
|
break;
|
2019-01-27 23:08:45 +01:00
|
|
|
case EditorSetting.CodeMirror:
|
|
|
|
const aceCode = AceEditor.getCode();
|
|
|
|
const aceFn = AceEditor.getFilename();
|
|
|
|
CodeMirrorEditor.create();
|
|
|
|
AceEditor.setInvisible();
|
|
|
|
CodeMirrorEditor.openScript(aceFn, aceCode);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.error(`Unrecognized Editor Setting: ${opt}`);
|
|
|
|
return;
|
2018-03-03 22:05:33 +01:00
|
|
|
}
|
2019-01-27 23:08:45 +01:00
|
|
|
|
|
|
|
Settings.Editor = opt;
|
2018-02-15 05:26:43 +01:00
|
|
|
}
|
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
editorSelector.onchange(); // Trigger the onchange event handler
|
|
|
|
}
|
2017-10-04 03:50:13 +02:00
|
|
|
|
2019-01-27 23:08:45 +01:00
|
|
|
export function getCurrentEditor() {
|
|
|
|
switch (Settings.Editor) {
|
|
|
|
case EditorSetting.Ace:
|
|
|
|
return AceEditor;
|
|
|
|
case EditorSetting.CodeMirror:
|
|
|
|
return CodeMirrorEditor;
|
|
|
|
default:
|
|
|
|
console.log(`Invalid Editor Setting: ${Settings.Editor}`);
|
|
|
|
throw new Error(`Invalid Editor Setting: ${Settings.Editor}`);
|
|
|
|
return null;
|
2017-10-04 03:50:13 +02:00
|
|
|
}
|
2017-09-19 20:38:03 +02:00
|
|
|
}
|
2017-05-03 06:38:58 +02:00
|
|
|
|
2018-01-27 07:52:39 +01:00
|
|
|
//Updates RAM usage in script
|
2019-01-27 23:08:45 +01:00
|
|
|
export async function updateScriptEditorContent() {
|
2018-03-12 20:39:04 +01:00
|
|
|
var filename = document.getElementById("script-editor-filename").value;
|
2018-05-06 00:13:35 +02:00
|
|
|
if (scriptEditorRamCheck == null || !scriptEditorRamCheck.checked || !isScriptFilename(filename)) {
|
2018-01-27 07:52:39 +01:00
|
|
|
scriptEditorRamText.innerText = "N/A";
|
|
|
|
return;
|
|
|
|
}
|
2019-01-27 23:08:45 +01:00
|
|
|
|
|
|
|
let code;
|
|
|
|
try {
|
|
|
|
code = getCurrentEditor().getCode();
|
|
|
|
} catch(e) {
|
|
|
|
scriptEditorRamText.innerText = "RAM: ERROR";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-13 18:54:29 +02:00
|
|
|
var codeCopy = code.repeat(1);
|
2018-10-03 19:50:39 +02:00
|
|
|
var ramUsage = await calculateRamUsage(codeCopy);
|
2018-01-27 07:52:39 +01:00
|
|
|
if (ramUsage !== -1) {
|
2018-09-12 17:53:08 +02:00
|
|
|
scriptEditorRamText.innerText = "RAM: " + numeralWrapper.format(ramUsage, '0.00') + " GB";
|
2018-03-03 22:05:33 +01:00
|
|
|
} else {
|
|
|
|
scriptEditorRamText.innerText = "RAM: Syntax Error";
|
2018-01-27 07:52:39 +01:00
|
|
|
}
|
2017-07-13 18:54:29 +02:00
|
|
|
}
|
|
|
|
|
2017-05-03 06:38:58 +02:00
|
|
|
//Define key commands in script editor (ctrl o to save + close, etc.)
|
2016-11-24 23:30:33 +01:00
|
|
|
$(document).keydown(function(e) {
|
2018-05-06 22:27:47 +02:00
|
|
|
if (Settings.DisableHotkeys === true) {return;}
|
2018-07-20 03:51:18 +02:00
|
|
|
if (routing.isOn(Page.ScriptEditor)) {
|
2017-05-06 08:24:01 +02:00
|
|
|
//Ctrl + b
|
2018-05-05 22:23:57 +02:00
|
|
|
if (e.keyCode == 66 && (e.ctrlKey || e.metaKey)) {
|
2017-05-30 00:37:38 +02:00
|
|
|
e.preventDefault();
|
2017-05-03 06:38:58 +02:00
|
|
|
saveAndCloseScriptEditor();
|
2016-11-24 23:30:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-05-03 06:38:58 +02:00
|
|
|
function saveAndCloseScriptEditor() {
|
|
|
|
var filename = document.getElementById("script-editor-filename").value;
|
2019-01-27 23:08:45 +01:00
|
|
|
|
2019-01-30 07:02:27 +01:00
|
|
|
let code;
|
2019-01-27 23:08:45 +01:00
|
|
|
try {
|
2019-01-30 07:02:27 +01:00
|
|
|
code = getCurrentEditor().getCode();
|
2019-01-27 23:08:45 +01:00
|
|
|
} catch(e) {
|
|
|
|
dialogBoxCreate("Something went wrong when trying to save (getCurrentEditor().getCode()). Please report to game developer with details");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-29 21:06:21 +02:00
|
|
|
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
|
|
|
//Make sure filename + code properly follow tutorial
|
|
|
|
if (filename !== "foodnstuff.script") {
|
2017-05-06 08:24:01 +02:00
|
|
|
dialogBoxCreate("Leave the script name as 'foodnstuff'!");
|
|
|
|
return;
|
|
|
|
}
|
2017-05-16 05:06:25 +02:00
|
|
|
code = code.replace(/\s/g, "");
|
|
|
|
if (code.indexOf("while(true){hack('foodnstuff');}") == -1) {
|
2017-05-06 08:24:01 +02:00
|
|
|
dialogBoxCreate("Please copy and paste the code from the tutorial!");
|
|
|
|
return;
|
|
|
|
}
|
2018-08-29 21:06:21 +02:00
|
|
|
|
|
|
|
//Save the script
|
|
|
|
let s = Player.getCurrentServer();
|
|
|
|
for (var i = 0; i < s.scripts.length; i++) {
|
|
|
|
if (filename == s.scripts[i].filename) {
|
2019-03-05 02:40:28 +01:00
|
|
|
s.scripts[i].saveScript(getCurrentEditor().getCode(), Player);
|
2018-08-29 21:06:21 +02:00
|
|
|
Engine.loadTerminalContent();
|
|
|
|
return iTutorialNextStep();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//If the current script does NOT exist, create a new one
|
|
|
|
let script = new Script();
|
2019-03-05 02:40:28 +01:00
|
|
|
script.saveScript(getCurrentEditor().getCode(), Player);
|
2018-08-29 21:06:21 +02:00
|
|
|
s.scripts.push(script);
|
|
|
|
|
|
|
|
return iTutorialNextStep();
|
2017-05-06 08:24:01 +02:00
|
|
|
}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2017-05-03 06:38:58 +02:00
|
|
|
if (filename == "") {
|
2017-06-02 19:18:53 +02:00
|
|
|
dialogBoxCreate("You must specify a filename!");
|
2017-05-03 06:38:58 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2017-05-03 06:38:58 +02:00
|
|
|
if (checkValidFilename(filename) == false) {
|
|
|
|
dialogBoxCreate("Script filename can contain only alphanumerics, hyphens, and underscores");
|
|
|
|
return;
|
|
|
|
}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2018-03-12 20:39:04 +01:00
|
|
|
var s = Player.getCurrentServer();
|
|
|
|
if (filename === ".fconf") {
|
|
|
|
try {
|
|
|
|
parseFconfSettings(code);
|
|
|
|
} catch(e) {
|
2018-09-21 21:47:33 +02:00
|
|
|
dialogBoxCreate(`Invalid .fconf file: ${e}`);
|
2017-05-03 06:38:58 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-05-06 00:13:35 +02:00
|
|
|
} else if (isScriptFilename(filename)) {
|
2018-03-12 20:39:04 +01:00
|
|
|
//If the current script already exists on the server, overwrite it
|
|
|
|
for (var i = 0; i < s.scripts.length; i++) {
|
|
|
|
if (filename == s.scripts[i].filename) {
|
2019-03-05 02:40:28 +01:00
|
|
|
s.scripts[i].saveScript(getCurrentEditor().getCode(), Player);
|
2018-03-12 20:39:04 +01:00
|
|
|
Engine.loadTerminalContent();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2018-03-12 20:39:04 +01:00
|
|
|
//If the current script does NOT exist, create a new one
|
|
|
|
var script = new Script();
|
2019-03-05 02:40:28 +01:00
|
|
|
script.saveScript(getCurrentEditor().getCode(), Player);
|
2018-03-12 20:39:04 +01:00
|
|
|
s.scripts.push(script);
|
|
|
|
} else if (filename.endsWith(".txt")) {
|
|
|
|
for (var i = 0; i < s.textFiles.length; ++i) {
|
|
|
|
if (s.textFiles[i].fn === filename) {
|
|
|
|
s.textFiles[i].write(code);
|
|
|
|
Engine.loadTerminalContent();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var textFile = new TextFile(filename, code);
|
|
|
|
s.textFiles.push(textFile);
|
|
|
|
} else {
|
|
|
|
dialogBoxCreate("Invalid filename. Must be either a script (.script) or " +
|
|
|
|
" or text file (.txt)")
|
|
|
|
return;
|
|
|
|
}
|
2017-05-03 06:38:58 +02:00
|
|
|
Engine.loadTerminalContent();
|
|
|
|
}
|
|
|
|
|
2016-11-24 23:30:33 +01:00
|
|
|
//Checks that the string contains only valid characters for a filename, which are alphanumeric,
|
2018-03-12 20:39:04 +01:00
|
|
|
// underscores, hyphens, and dots
|
2016-11-24 23:30:33 +01:00
|
|
|
function checkValidFilename(filename) {
|
2018-03-12 20:39:04 +01:00
|
|
|
var regex = /^[.a-zA-Z0-9_-]+$/;
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2016-11-24 23:30:33 +01:00
|
|
|
if (filename.match(regex)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-12-14 21:29:40 +01:00
|
|
|
//Called when the game is loaded. Loads all running scripts (from all servers)
|
|
|
|
//into worker scripts so that they will start running
|
2019-03-05 02:40:28 +01:00
|
|
|
export function loadAllRunningScripts() {
|
2017-05-20 11:27:42 +02:00
|
|
|
var total = 0;
|
2018-05-17 21:50:27 +02:00
|
|
|
let skipScriptLoad = (window.location.href.toLowerCase().indexOf("?noscripts") !== -1);
|
2019-02-06 08:06:48 +01:00
|
|
|
if (skipScriptLoad) { console.info("Skipping the load of any scripts during startup"); }
|
2016-12-15 18:51:23 +01:00
|
|
|
for (var property in AllServers) {
|
|
|
|
if (AllServers.hasOwnProperty(property)) {
|
|
|
|
var server = AllServers[property];
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2016-12-19 19:20:19 +01:00
|
|
|
//Reset each server's RAM usage to 0
|
|
|
|
server.ramUsed = 0;
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2018-05-13 01:19:49 +02:00
|
|
|
//Reset modules on all scripts
|
|
|
|
for (var i = 0; i < server.scripts.length; ++i) {
|
|
|
|
server.scripts[i].module = "";
|
|
|
|
}
|
|
|
|
|
2018-05-17 21:50:27 +02:00
|
|
|
if (skipScriptLoad) {
|
|
|
|
//Start game with no scripts
|
|
|
|
server.runningScripts.length = 0;
|
|
|
|
} else {
|
|
|
|
for (var j = 0; j < server.runningScripts.length; ++j) {
|
|
|
|
addWorkerScript(server.runningScripts[j], server);
|
|
|
|
|
|
|
|
//Offline production
|
|
|
|
total += scriptCalculateOfflineProduction(server.runningScripts[j]);
|
|
|
|
}
|
|
|
|
}
|
2016-12-14 22:22:12 +01:00
|
|
|
}
|
|
|
|
}
|
2019-02-06 08:06:48 +01:00
|
|
|
|
2017-05-20 11:27:42 +02:00
|
|
|
return total;
|
2016-12-19 21:59:13 +01:00
|
|
|
}
|
|
|
|
|
2017-08-30 19:44:29 +02:00
|
|
|
function scriptCalculateOfflineProduction(runningScriptObj) {
|
2016-12-19 21:59:13 +01:00
|
|
|
//The Player object stores the last update time from when we were online
|
|
|
|
var thisUpdate = new Date().getTime();
|
|
|
|
var lastUpdate = Player.lastUpdate;
|
|
|
|
var timePassed = (thisUpdate - lastUpdate) / 1000; //Seconds
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2016-12-19 21:59:13 +01:00
|
|
|
//Calculate the "confidence" rating of the script's true production. This is based
|
|
|
|
//entirely off of time. We will arbitrarily say that if a script has been running for
|
2017-05-05 03:08:44 +02:00
|
|
|
//4 hours (14400 sec) then we are completely confident in its ability
|
2017-06-17 04:53:57 +02:00
|
|
|
var confidence = (runningScriptObj.onlineRunningTime) / 14400;
|
2016-12-19 21:59:13 +01:00
|
|
|
if (confidence >= 1) {confidence = 1;}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2017-06-19 01:23:50 +02:00
|
|
|
//Data map: [MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken]
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2019-02-06 08:06:48 +01:00
|
|
|
// Grow
|
2017-06-19 01:23:50 +02:00
|
|
|
for (var ip in runningScriptObj.dataMap) {
|
|
|
|
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
|
|
|
|
if (runningScriptObj.dataMap[ip][2] == 0 || runningScriptObj.dataMap[ip][2] == null) {continue;}
|
2017-06-13 17:58:31 +02:00
|
|
|
var serv = AllServers[ip];
|
|
|
|
if (serv == null) {continue;}
|
2017-06-19 01:23:50 +02:00
|
|
|
var timesGrown = Math.round(0.5 * runningScriptObj.dataMap[ip][2] / runningScriptObj.onlineRunningTime * timePassed);
|
2017-06-17 04:53:57 +02:00
|
|
|
console.log(runningScriptObj.filename + " called grow() on " + serv.hostname + " " + timesGrown + " times while offline");
|
|
|
|
runningScriptObj.log("Called grow() on " + serv.hostname + " " + timesGrown + " times while offline");
|
2019-03-05 02:40:28 +01:00
|
|
|
var growth = processSingleServerGrowth(serv, timesGrown * 450, Player);
|
2018-09-12 17:53:08 +02:00
|
|
|
runningScriptObj.log(serv.hostname + " grown by " + numeralWrapper.format(growth * 100 - 100, '0.000000%') + " from grow() calls made while offline");
|
2017-06-13 17:58:31 +02:00
|
|
|
}
|
|
|
|
}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2019-02-06 08:06:48 +01:00
|
|
|
// Money from hacking
|
2017-05-10 19:42:46 +02:00
|
|
|
var totalOfflineProduction = 0;
|
2017-06-19 01:23:50 +02:00
|
|
|
for (var ip in runningScriptObj.dataMap) {
|
|
|
|
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
|
|
|
|
if (runningScriptObj.dataMap[ip][0] == 0 || runningScriptObj.dataMap[ip][0] == null) {continue;}
|
2017-05-10 19:42:46 +02:00
|
|
|
var serv = AllServers[ip];
|
2017-05-10 22:21:15 +02:00
|
|
|
if (serv == null) {continue;}
|
2017-06-19 01:23:50 +02:00
|
|
|
var production = 0.5 * runningScriptObj.dataMap[ip][0] / runningScriptObj.onlineRunningTime * timePassed;
|
2017-05-10 19:42:46 +02:00
|
|
|
production *= confidence;
|
|
|
|
if (production > serv.moneyAvailable) {
|
|
|
|
production = serv.moneyAvailable;
|
|
|
|
}
|
|
|
|
totalOfflineProduction += production;
|
2017-07-25 16:39:56 +02:00
|
|
|
Player.gainMoney(production);
|
2019-02-22 03:26:28 +01:00
|
|
|
Player.recordMoneySource(production, "hacking");
|
2017-06-17 04:53:57 +02:00
|
|
|
console.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname);
|
|
|
|
runningScriptObj.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname);
|
2017-05-10 19:42:46 +02:00
|
|
|
serv.moneyAvailable -= production;
|
|
|
|
if (serv.moneyAvailable < 0) {serv.moneyAvailable = 0;}
|
2017-06-20 18:11:33 +02:00
|
|
|
if (isNaN(serv.moneyAvailable)) {serv.moneyAvailable = 0;}
|
2017-05-10 19:42:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-06 08:06:48 +01:00
|
|
|
// Offline EXP gain
|
|
|
|
// A script's offline production will always be at most half of its online production.
|
2017-06-17 04:53:57 +02:00
|
|
|
var expGain = 0.5 * (runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime) * timePassed;
|
2016-12-19 21:59:13 +01:00
|
|
|
expGain *= confidence;
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2017-05-05 03:08:44 +02:00
|
|
|
Player.gainHackingExp(expGain);
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2019-02-06 08:06:48 +01:00
|
|
|
// Update script stats
|
2017-06-17 04:53:57 +02:00
|
|
|
runningScriptObj.offlineMoneyMade += totalOfflineProduction;
|
|
|
|
runningScriptObj.offlineRunningTime += timePassed;
|
|
|
|
runningScriptObj.offlineExpGained += expGain;
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2019-02-06 08:06:48 +01:00
|
|
|
// Fortify a server's security based on how many times it was hacked
|
2017-06-19 01:23:50 +02:00
|
|
|
for (var ip in runningScriptObj.dataMap) {
|
|
|
|
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
|
|
|
|
if (runningScriptObj.dataMap[ip][1] == 0 || runningScriptObj.dataMap[ip][1] == null) {continue;}
|
2017-06-01 03:57:49 +02:00
|
|
|
var serv = AllServers[ip];
|
|
|
|
if (serv == null) {continue;}
|
2017-06-19 01:23:50 +02:00
|
|
|
var timesHacked = Math.round(0.5 * runningScriptObj.dataMap[ip][1] / runningScriptObj.onlineRunningTime * timePassed);
|
2017-06-17 04:53:57 +02:00
|
|
|
console.log(runningScriptObj.filename + " hacked " + serv.hostname + " " + timesHacked + " times while offline");
|
|
|
|
runningScriptObj.log("Hacked " + serv.hostname + " " + timesHacked + " times while offline");
|
2017-06-01 03:57:49 +02:00
|
|
|
serv.fortify(CONSTANTS.ServerFortifyAmount * timesHacked);
|
|
|
|
}
|
|
|
|
}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2019-02-06 08:06:48 +01:00
|
|
|
// Weaken
|
2017-06-19 01:23:50 +02:00
|
|
|
for (var ip in runningScriptObj.dataMap) {
|
|
|
|
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
|
|
|
|
if (runningScriptObj.dataMap[ip][3] == 0 || runningScriptObj.dataMap[ip][3] == null) {continue;}
|
2017-06-01 03:57:49 +02:00
|
|
|
var serv = AllServers[ip];
|
|
|
|
if (serv == null) {continue;}
|
2017-06-19 01:23:50 +02:00
|
|
|
var timesWeakened = Math.round(0.5 * runningScriptObj.dataMap[ip][3] / runningScriptObj.onlineRunningTime * timePassed);
|
2017-06-17 04:53:57 +02:00
|
|
|
console.log(runningScriptObj.filename + " called weaken() on " + serv.hostname + " " + timesWeakened + " times while offline");
|
|
|
|
runningScriptObj.log("Called weaken() on " + serv.hostname + " " + timesWeakened + " times while offline");
|
2017-06-01 03:57:49 +02:00
|
|
|
serv.weaken(CONSTANTS.ServerWeakenAmount * timesWeakened);
|
|
|
|
}
|
|
|
|
}
|
2017-07-25 16:39:56 +02:00
|
|
|
|
2017-05-20 11:27:42 +02:00
|
|
|
return totalOfflineProduction;
|
2017-05-10 19:42:46 +02:00
|
|
|
}
|
|
|
|
|
2017-06-17 04:53:57 +02:00
|
|
|
//Returns a RunningScript object matching the filename and arguments on the
|
|
|
|
//designated server, and false otherwise
|
2019-03-05 02:40:28 +01:00
|
|
|
export function findRunningScript(filename, args, server) {
|
2017-06-17 04:53:57 +02:00
|
|
|
for (var i = 0; i < server.runningScripts.length; ++i) {
|
|
|
|
if (server.runningScripts[i].filename == filename &&
|
|
|
|
compareArrays(server.runningScripts[i].args, args)) {
|
|
|
|
return server.runningScripts[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|