Merge pull request #146 from danielyxie/dev

v0.29.3 Changed - Bug fixes for new player-defined Netscript function…
This commit is contained in:
danielyxie 2017-10-03 20:53:52 -05:00 committed by GitHub
commit 98007073b8
9 changed files with 4351 additions and 2248 deletions

6451
dist/bundle.js vendored

File diff suppressed because one or more lines are too long

@ -696,6 +696,7 @@
<a id="location-purchase-1tb" class="a-link-button"> Purchase 1TB Server - $75,000,000</a> <a id="location-purchase-1tb" class="a-link-button"> Purchase 1TB Server - $75,000,000</a>
<a id="location-purchase-tor" class="a-link-button"> Purchase TOR Router - $100,000</a> <a id="location-purchase-tor" class="a-link-button"> Purchase TOR Router - $100,000</a>
<a id="location-purchase-home-ram" class="a-link-button"> Purchase additional RAM for Home computer </a> <a id="location-purchase-home-ram" class="a-link-button"> Purchase additional RAM for Home computer </a>
<!--<a id="location-purchase-home-cores" class="a-link-button"> Purchase additional Core for Home computer </a>-->
<!-- Infiltrate --> <!-- Infiltrate -->
<a id="location-infiltrate" class="a-link-button tooltip"> Infiltrate Company <a id="location-infiltrate" class="a-link-button tooltip"> Infiltrate Company

@ -1,5 +1,5 @@
let CONSTANTS = { let CONSTANTS = {
Version: "0.29.2", Version: "0.29.3",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience //Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then //and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -116,17 +116,18 @@ let CONSTANTS = {
IntelligenceCrimeWeight: 0.05, //Weight for how much int affects crime success rates IntelligenceCrimeWeight: 0.05, //Weight for how much int affects crime success rates
IntelligenceInfiltrationWeight: 0.1, //Weight for how much int affects infiltration success rates IntelligenceInfiltrationWeight: 0.1, //Weight for how much int affects infiltration success rates
IntelligenceCrimeBaseExpGain: 0.001, IntelligenceCrimeBaseExpGain: 0.001,
IntelligenceProgramBaseExpGain: 1000, //Program required hack level divided by this to determine int exp gain IntelligenceProgramBaseExpGain: 500, //Program required hack level divided by this to determine int exp gain
IntelligenceTerminalHackBaseExpGain: 200, //Hacking exp divided by this to determine int exp gain IntelligenceTerminalHackBaseExpGain: 200, //Hacking exp divided by this to determine int exp gain
IntelligenceSingFnBaseExpGain: 0.0005, IntelligenceSingFnBaseExpGain: 0.0005,
IntelligenceClassBaseExpGain: 0.0000001, IntelligenceClassBaseExpGain: 0.0000005,
//Hacking Missions //Hacking Missions
HackingMissionRepToDiffConversion: 10000, //Faction rep is divided by this to get mission difficulty HackingMissionRepToDiffConversion: 10000, //Faction rep is divided by this to get mission difficulty
HackingMissionRepToRewardConversion: 10, //Faction rep divided byt his to get mission rep reward HackingMissionRepToRewardConversion: 10, //Faction rep divided byt his to get mission rep reward
HackingMissionSpamTimeIncrease: 15000, //How much time limit increase is gained when conquering a Spam Node (ms) HackingMissionSpamTimeIncrease: 15000, //How much time limit increase is gained when conquering a Spam Node (ms)
HackingMissionTransferAttackIncrease: 1.05, //Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node HackingMissionTransferAttackIncrease: 1.05, //Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node
HackingMissionMiscDefenseIncrease: 10, //The amount by which every misc node's defense increases when one is conquered HackingMissionMiscDefenseIncrease: 1.12, //The amount by which every misc node's defense is multiplied when one is conquered
HackingMissionDifficultyToHacking: 120, //Difficulty is multiplied by this to determine enemy's "hacking" level (to determine effects of scan/attack, etc)
HackingMissionHowToPlay: "Hacking missions are a minigame that, if won, will reward you with faction reputation.<br><br>" + HackingMissionHowToPlay: "Hacking missions are a minigame that, if won, will reward you with faction reputation.<br><br>" +
"In this game you control a set of Nodes and use them to try and defeat an enemy. Your Nodes " + "In this game you control a set of Nodes and use them to try and defeat an enemy. Your Nodes " +
"are colored blue, while the enemy's are red. There are also other nodes on the map colored gray " + "are colored blue, while the enemy's are red. There are also other nodes on the map colored gray " +
@ -168,7 +169,7 @@ let CONSTANTS = {
"or press 'd'.<br><br>" + "or press 'd'.<br><br>" +
"Other Notes:<br><br>" + "Other Notes:<br><br>" +
"-Whenever you conquer a miscellenaous Node (not owned by the enemy), the defense of all remaining miscellaneous Nodes will increase " + "-Whenever you conquer a miscellenaous Node (not owned by the enemy), the defense of all remaining miscellaneous Nodes will increase " +
"by a smal fixed amount.", "by a fixed percentage.",
//Gang constants //Gang constants
@ -1019,6 +1020,10 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.29.3<br>" +
"-Fixed bug for killing scripts and showing error messages when there are errors in a player-defined function<br>" +
"-Added function name autocompletion in Script Editor. Press Ctrl+space on a prefix to show autocompletion options.<br>" +
"-Minor rebalancing and bug fixes for Infiltration<br><br>" +
"v0.29.2<br>" + "v0.29.2<br>" +
"-installAugmentations() Singularity Function now takes a callback script as an argument. This is a script " + "-installAugmentations() Singularity Function now takes a callback script as an argument. This is a script " +
"that gets ran automatically after Augmentations are installed. The script is run with no arguments and only a single thread, " + "that gets ran automatically after Augmentations are installed. The script is run with no arguments and only a single thread, " +

@ -601,7 +601,7 @@ function getInfiltrationKillChance(inst) {
return Math.min(0.95, return Math.min(0.95,
(Player.strength + (Player.strength +
Player.dexterity + Player.dexterity +
Player.agility) / (1.5 * lvl)); Player.agility) / (1.45 * lvl));
} }
@ -627,7 +627,7 @@ function getInfiltrationKnockoutChance(inst) {
return Math.min(0.95, return Math.min(0.95,
(Player.strength + (Player.strength +
Player.dexterity + Player.dexterity +
Player.agility) / (1.75 * lvl)); Player.agility) / (1.7 * lvl));
} }
//Stealth knockout //Stealth knockout
@ -648,7 +648,7 @@ function attemptInfiltrationStealthKnockout(inst) {
function getInfiltrationStealthKnockoutChance(inst) { function getInfiltrationStealthKnockoutChance(inst) {
var lvl = inst.securityLevel; var lvl = inst.securityLevel;
return Math.min(0.95, return Math.min(0.95,
(0.5 * Player.strength + (0.55 * Player.strength +
2 * Player.dexterity + 2 * Player.dexterity +
2 * Player.agility + 2 * Player.agility +
intWgt * Player.intelligence) / (3 * lvl)); intWgt * Player.intelligence) / (3 * lvl));

@ -203,7 +203,7 @@ HackingMission.prototype.init = function() {
var home = Player.getHomeComputer() var home = Player.getHomeComputer()
for (var i = 0; i < home.cpuCores; ++i) { for (var i = 0; i < home.cpuCores; ++i) {
var stats = { var stats = {
atk: (Player.hacking_skill / 6), atk: (Player.hacking_skill / 5),
def: (Player.hacking_skill / 20), def: (Player.hacking_skill / 20),
hp: (Player.hacking_skill / 5), hp: (Player.hacking_skill / 5),
}; };
@ -214,7 +214,7 @@ HackingMission.prototype.init = function() {
} }
//Randomly generate enemy nodes (CPU and Firewall) based on difficulty //Randomly generate enemy nodes (CPU and Firewall) based on difficulty
var numNodes = this.difficulty; var numNodes = Math.max(1, Math.round(this.difficulty / 3));
var numFirewalls = getRandomInt(this.difficulty, this.difficulty + 1); var numFirewalls = getRandomInt(this.difficulty, this.difficulty + 1);
var numDatabases = getRandomInt(this.difficulty, this.difficulty + 1); var numDatabases = getRandomInt(this.difficulty, this.difficulty + 1);
var totalNodes = numNodes + numFirewalls + numDatabases; var totalNodes = numNodes + numFirewalls + numDatabases;
@ -223,10 +223,11 @@ HackingMission.prototype.init = function() {
console.log("numFirewalls: " + numFirewalls); console.log("numFirewalls: " + numFirewalls);
console.log("numDatabases: " + numDatabases); console.log("numDatabases: " + numDatabases);
console.log("totalNodes: " + totalNodes); console.log("totalNodes: " + totalNodes);
var randMult = addOffset(this.difficulty, 20); console.log("xlimit: " + xlimit);
var randMult = addOffset(0.85 + (this.difficulty / 6), 10);
for (var i = 0; i < numNodes; ++i) { for (var i = 0; i < numNodes; ++i) {
var stats = { var stats = {
atk: randMult * getRandomInt(40, 60), atk: randMult * getRandomInt(50, 75),
def: randMult * getRandomInt(20, 40), def: randMult * getRandomInt(20, 40),
hp: randMult * getRandomInt(100, 120) hp: randMult * getRandomInt(100, 120)
} }
@ -246,7 +247,7 @@ HackingMission.prototype.init = function() {
} }
for (var i = 0; i < numDatabases; ++i) { for (var i = 0; i < numDatabases; ++i) {
var stats = { var stats = {
atk: randMult * getRandomInt(10, 20), atk: 0,
def: randMult * getRandomInt(20, 30), def: randMult * getRandomInt(20, 30),
hp: randMult * getRandomInt(120, 150) hp: randMult * getRandomInt(120, 150)
} }
@ -586,6 +587,10 @@ HackingMission.prototype.setNodePosition = function(nodeObj, x, y) {
HackingMission.prototype.setNodeRandomPosition = function(nodeObj, xlimit=0) { HackingMission.prototype.setNodeRandomPosition = function(nodeObj, xlimit=0) {
var i = getRandomInt(0, this.availablePositions.length - 1); var i = getRandomInt(0, this.availablePositions.length - 1);
if (this.availablePositions[i][1] < xlimit) {
//Recurse if not within limit
return this.setNodeRandomPosition(nodeObj, xlimit);
}
var pos = this.availablePositions.splice(i, 1); var pos = this.availablePositions.splice(i, 1);
pos = pos[0]; pos = pos[0];
this.setNodePosition(nodeObj, pos[0], pos[1]); this.setNodePosition(nodeObj, pos[0], pos[1]);
@ -604,7 +609,7 @@ HackingMission.prototype.createMap = function() {
for (var y = 0; y < 8; ++y) { for (var y = 0; y < 8; ++y) {
if (!(this.map[x][y] instanceof Node)) { if (!(this.map[x][y] instanceof Node)) {
var node, type = getRandomInt(0, 2); var node, type = getRandomInt(0, 2);
var randMult = addOffset(this.difficulty, 20); var randMult = addOffset(0.75 + (this.difficulty / 3), 20);
switch (type) { switch (type) {
case 0: //Spam case 0: //Spam
var stats = { var stats = {
@ -828,6 +833,7 @@ HackingMission.prototype.nodeReachable = function(node) {
} }
HackingMission.prototype.nodeReachableByEnemy = function(node) { HackingMission.prototype.nodeReachableByEnemy = function(node) {
if (node === null) {return false;}
var x = node.pos[0], y = node.pos[1]; var x = node.pos[0], y = node.pos[1];
if (x > 0 && this.map[x-1][y].enmyCtrl) {return true;} if (x > 0 && this.map[x-1][y].enmyCtrl) {return true;}
if (x < 7 && this.map[x+1][y].enmyCtrl) {return true;} if (x < 7 && this.map[x+1][y].enmyCtrl) {return true;}
@ -987,11 +993,18 @@ HackingMission.prototype.process = function(numCycles=1) {
this.calculateDefenses(); this.calculateDefenses();
} }
//Win if all enemy databases are conquered
if (this.enemyDatabases.length === 0) { if (this.enemyDatabases.length === 0) {
this.finishMission(true); this.finishMission(true);
return; return;
} }
//Lose if all your cores are gone
if (this.playerCores.length === 0) {
this.finishMission(false);
return;
}
//Defense of every misc Node increase by 0.5 per second //Defense of every misc Node increase by 0.5 per second
this.miscNodes.forEach((node)=>{ this.miscNodes.forEach((node)=>{
node.def += (0.1 * storedCycles); node.def += (0.1 * storedCycles);
@ -1037,22 +1050,23 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
} }
//Calculations are per second, so divide everything by 5 //Calculations are per second, so divide everything by 5
var calcStats = false; var calcStats = false, plyr = nodeObj.plyrCtrl;
var enmyHacking = this.difficulty * CONSTANTS.HackingMissionDifficultyToHacking;
switch(nodeObj.action) { switch(nodeObj.action) {
case NodeActions.Attack: case NodeActions.Attack:
if (nodeObj.conn === null) {break;} if (nodeObj.conn === null) {break;}
var dmg = this.calculateAttackDamage(atk, def, Player.hacking_skill); var dmg = this.calculateAttackDamage(atk, def, plyr ? Player.hacking_skill : enmyHacking);
targetNode.hp -= (dmg/5 * numCycles); targetNode.hp -= (dmg/5 * numCycles);
break; break;
case NodeActions.Scan: case NodeActions.Scan:
if (nodeObj.conn === null) {break;} if (nodeObj.conn === null) {break;}
var eff = this.calculateScanEffect(atk, def, Player.hacking_skill); var eff = this.calculateScanEffect(atk, def, plyr ? Player.hacking_skill : enmyHacking);
targetNode.def -= (eff/5 * numCycles); targetNode.def -= (eff/5 * numCycles);
calcStats = true; calcStats = true;
break; break;
case NodeActions.Weaken: case NodeActions.Weaken:
if (nodeObj.conn === null) {break;} if (nodeObj.conn === null) {break;}
var eff = this.calculateWeakenEffect(atk, def, Player.hacking_skill); var eff = this.calculateWeakenEffect(atk, def, plyr ? Player.hacking_skill : enmyHacking);
targetNode.atk -= (eff/5 * numCycles); targetNode.atk -= (eff/5 * numCycles);
calcStats = true; calcStats = true;
break; break;
@ -1086,7 +1100,7 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
targetNode.action = null; targetNode.action = null;
targetNode.conn = null; targetNode.conn = null;
if (this.selectedNode == targetNode) { if (this.selectedNode == targetNode) {
targetNode.deselect(); targetNode.deselect(this.actionButtons);
} }
//Flag for whether the target node was a misc node //Flag for whether the target node was a misc node
@ -1191,9 +1205,11 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
} }
//If a misc node was conquered, the defense for all misc nodes increases by some fixed amount //If a misc node was conquered, the defense for all misc nodes increases by some fixed amount
this.miscNodes.forEach((node)=>{ if (isMiscNode && conqueredByPlayer) {
node.def += CONSTANTS.HackingMissionMiscDefenseIncrease; this.miscNodes.forEach((node)=>{
}); node.def *= CONSTANTS.HackingMissionMiscDefenseIncrease;
});
}
} }
//Update node DOMs //Update node DOMs
@ -1214,7 +1230,12 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
if (this.miscNodes.length === 0) { if (this.miscNodes.length === 0) {
//Randomly pick a player node and attack it if its reachable //Randomly pick a player node and attack it if its reachable
var rand = getRandomInt(0, this.playerNodes.length-1); var rand = getRandomInt(0, this.playerNodes.length-1);
var node = this.playerNodes[rand]; var node;
if (this.playerNodes.length === 0) {
node = null;
} else {
node = this.playerNodes[rand];
}
if (this.nodeReachableByEnemy(node)) { if (this.nodeReachableByEnemy(node)) {
//Create connection //Create connection
console.log("Enemy core selected a Player Node as target"); console.log("Enemy core selected a Player Node as target");
@ -1225,7 +1246,12 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
} else { } else {
//Randomly pick a player core and attack it if its reachable //Randomly pick a player core and attack it if its reachable
rand = getRandomInt(0, this.playerCores.length-1); rand = getRandomInt(0, this.playerCores.length-1);
node = this.playerCores[rand]; if (this.playerCores.length === 0) {
return; //No Misc Nodes, no player Nodes, no Player cores. Player lost
} else {
node = this.playerCores[rand];
}
if (this.nodeReachableByEnemy(node)) { if (this.nodeReachableByEnemy(node)) {
//Create connection //Create connection
console.log("Enemy core selected a Player Core as target"); console.log("Enemy core selected a Player Core as target");
@ -1251,6 +1277,7 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
//If no connection was made, set the Core to Fortify //If no connection was made, set the Core to Fortify
nodeObj.action = NodeActions.Fortify; nodeObj.action = NodeActions.Fortify;
} else { } else {
//If this node has a selected target
var targetNode; var targetNode;
if (nodeObj.conn.target) { if (nodeObj.conn.target) {
targetNode = this.getNodeFromElement(nodeObj.conn.target); targetNode = this.getNodeFromElement(nodeObj.conn.target);
@ -1261,7 +1288,13 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
console.log("Error getting Target node Object in enemyAISelectAction()"); console.log("Error getting Target node Object in enemyAISelectAction()");
} }
if (targetNode.def > this.enemyAtk - 25) { if (targetNode.def > this.enemyAtk + 25) {
if (nodeObj.def < 50) {
nodeObj.action = NodeActions.Fortify;
} else {
nodeObj.action = NodeActions.Overflow;
}
} else if (Math.abs(targetNode.def - this.enemyAtk) <= 25) {
nodeObj.action = NodeActions.Scan; nodeObj.action = NodeActions.Scan;
} else { } else {
nodeObj.action = NodeActions.Attack; nodeObj.action = NodeActions.Attack;
@ -1291,11 +1324,11 @@ HackingMission.prototype.calculateAttackDamage = function(atk, def, hacking = 0)
} }
HackingMission.prototype.calculateScanEffect = function(atk, def, hacking=0) { HackingMission.prototype.calculateScanEffect = function(atk, def, hacking=0) {
return Math.max((atk/2) + hacking / hackEffWeightTarget - def, 1); return Math.max((atk) + hacking / hackEffWeightTarget - def, 1);
} }
HackingMission.prototype.calculateWeakenEffect = function(atk, def, hacking=0) { HackingMission.prototype.calculateWeakenEffect = function(atk, def, hacking=0) {
return Math.max((atk/2) + hacking / hackEffWeightTarget - def, 1); return Math.max((atk) + hacking / hackEffWeightTarget - def, 1);
} }
HackingMission.prototype.calculateFortifyEffect = function(hacking=0) { HackingMission.prototype.calculateFortifyEffect = function(hacking=0) {

@ -84,8 +84,6 @@ function evaluate(exp, workerScript) {
//Create new Environment for the function //Create new Environment for the function
//Should be automatically garbage collected... //Should be automatically garbage collected...
var funcEnv = env.extend(); var funcEnv = env.extend();
console.log("Printing new environment for function:");
console.log(funcEnv);
//Define function arguments in this new environment //Define function arguments in this new environment
for (var i = 0; i < func.params.length; ++i) { for (var i = 0; i < func.params.length; ++i) {
@ -105,7 +103,23 @@ function evaluate(exp, workerScript) {
evaluate(func.body, funcWorkerScript).then(function(res) { evaluate(func.body, funcWorkerScript).then(function(res) {
resolve(res); resolve(res);
}).catch(function(e) { }).catch(function(e) {
reject(e); if (isString(e)) {
reject(makeRuntimeRejectMsg(workerScript, e));
} else if (e instanceof WorkerScript) {
//Parse out the err message from the WorkerScript and re-reject
var errorMsg = e.errorMessage;
var errorTextArray = errorMsg.split("|");
console.log("Printing error message from Function:");
console.log(errorMsg);
if (errorTextArray.length === 4) {
errorMsg = errorTextArray[3];
reject(makeRuntimeRejectMsg(workerScript, errorMsg));
} else {
reject(makeRuntimeRejectMsg(workerScript, "Error in one of your functions. Could not identify which function"));
}
} else if (e instanceof Error) {
reject(makeRuntimeRejectMsg(workerScript, e.toString()));
}
}); });
} else if (exp.callee.type == "MemberExpression"){ } else if (exp.callee.type == "MemberExpression"){
evaluate(exp.callee.object, workerScript).then(function(object) { evaluate(exp.callee.object, workerScript).then(function(object) {

@ -665,8 +665,7 @@ PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
txt = "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " + txt = "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
"Since you cancelled your work early, you only gained half of the reputation you earned. <br><br>" + txt; "Since you cancelled your work early, you only gained half of the reputation you earned. <br><br>" + txt;
} else { } else {
txt = "You worked a full shift of 8 hours! <br><br> " + txt = "You worked a full shift of 8 hours! <br><br> " + txt;
"You earned a total of: <br>" + txt;
} }
if (!sing) {dialogBoxCreate(txt);} if (!sing) {dialogBoxCreate(txt);}
@ -1483,16 +1482,16 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
break; break;
case CONSTANTS.CrimeKidnap: case CONSTANTS.CrimeKidnap:
this.karma -= 6; this.karma -= 6;
this.gainIntelligenceExp(CONSTANTS.IntelligenceCrimeBaseExpGain); this.gainIntelligenceExp(2 * CONSTANTS.IntelligenceCrimeBaseExpGain);
break; break;
case CONSTANTS.CrimeAssassination: case CONSTANTS.CrimeAssassination:
++this.numPeopleKilled; ++this.numPeopleKilled;
this.karma -= 10; this.karma -= 10;
this.gainIntelligenceExp(CONSTANTS.IntelligenceCrimeBaseExpGain); this.gainIntelligenceExp(5 * CONSTANTS.IntelligenceCrimeBaseExpGain);
break; break;
case CONSTANTS.CrimeHeist: case CONSTANTS.CrimeHeist:
this.karma -= 15; this.karma -= 15;
this.gainIntelligenceExp(5 * CONSTANTS.IntelligenceCrimeBaseExpGain); this.gainIntelligenceExp(10 * CONSTANTS.IntelligenceCrimeBaseExpGain);
break; break;
default: default:
console.log(this.crimeType); console.log(this.crimeType);

@ -11,11 +11,13 @@ require('brace/theme/twilight');
require('brace/theme/xcode'); require('brace/theme/xcode');
require("brace/keybinding/vim"); require("brace/keybinding/vim");
require("brace/keybinding/emacs"); require("brace/keybinding/emacs");
require("brace/ext/language_tools");
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {iTutorialSteps, iTutorialNextStep, import {iTutorialSteps, iTutorialNextStep,
iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js"; iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js";
import {NetscriptFunctions} from "./NetscriptFunctions.js";
import {addWorkerScript, killWorkerScript} from "./NetscriptWorker.js"; import {addWorkerScript, killWorkerScript} from "./NetscriptWorker.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
import {AllServers, processSingleServerGrowth} from "./Server.js"; import {AllServers, processSingleServerGrowth} from "./Server.js";
@ -101,6 +103,26 @@ function scriptEditorInit() {
saveAndCloseScriptEditor(); saveAndCloseScriptEditor();
}); });
}); });
//Function autocompleter
editor.setOption("enableBasicAutocompletion", true);
var autocompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
if (prefix.length === 0) {callback(null, []); return;}
var words = [];
var fns = NetscriptFunctions(null);
for (var name in fns) {
if (fns.hasOwnProperty(name)) {
words.push({
name: name,
value: name,
});
}
}
callback(null, words);
},
}
editor.completers = [autocompleter];
} }
document.addEventListener("DOMContentLoaded", scriptEditorInit, false); document.addEventListener("DOMContentLoaded", scriptEditorInit, false);

@ -508,7 +508,7 @@ let Engine = {
" (" + numeral(Player.agility_exp).format('(0.000a)') + ' experience)<br>' + " (" + numeral(Player.agility_exp).format('(0.000a)') + ' experience)<br>' +
'Charisma: ' + (Player.charisma).toLocaleString() + 'Charisma: ' + (Player.charisma).toLocaleString() +
" (" + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)<br>' + " (" + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)<br>' +
intText + intText +
'<b>Multipliers</b><br><br>' + '<b>Multipliers</b><br><br>' +
'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%<br>' + 'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%<br>' +
'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%<br>' + 'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%<br>' +
@ -1146,6 +1146,8 @@ let Engine = {
initLiterature(); initLiterature();
initSingularitySFFlags(); initSingularitySFFlags();
console.log(Player.intelligence_exp);
//Calculate the number of cycles have elapsed while offline //Calculate the number of cycles have elapsed while offline
Engine._lastUpdate = new Date().getTime(); Engine._lastUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate; var lastUpdate = Player.lastUpdate;