mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-18 05:33:54 +01:00
v0.29.3 Changed - Bug fixes for new player-defined Netscript functions. Rebalancing/bug fixes for Infiltration and Hacking Mission. Added function name autocompletion in Script Editor
This commit is contained in:
parent
51c37176f1
commit
0927c4251e
6451
dist/bundle.js
vendored
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-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-cores" class="a-link-button"> Purchase additional Core for Home computer </a>-->
|
||||
|
||||
<!-- Infiltrate -->
|
||||
<a id="location-infiltrate" class="a-link-button tooltip"> Infiltrate Company
|
||||
|
@ -1,5 +1,5 @@
|
||||
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
|
||||
//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
|
||||
IntelligenceInfiltrationWeight: 0.1, //Weight for how much int affects infiltration success rates
|
||||
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
|
||||
IntelligenceSingFnBaseExpGain: 0.0005,
|
||||
IntelligenceClassBaseExpGain: 0.0000001,
|
||||
IntelligenceClassBaseExpGain: 0.0000005,
|
||||
|
||||
//Hacking Missions
|
||||
HackingMissionRepToDiffConversion: 10000, //Faction rep is divided by this to get mission difficulty
|
||||
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)
|
||||
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>" +
|
||||
"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 " +
|
||||
@ -168,7 +169,7 @@ let CONSTANTS = {
|
||||
"or press 'd'.<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 " +
|
||||
"by a smal fixed amount.",
|
||||
"by a fixed percentage.",
|
||||
|
||||
|
||||
//Gang constants
|
||||
@ -1019,6 +1020,10 @@ let CONSTANTS = {
|
||||
"World Stock Exchange account and TIX API Access<br>",
|
||||
|
||||
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>" +
|
||||
"-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, " +
|
||||
|
@ -601,7 +601,7 @@ function getInfiltrationKillChance(inst) {
|
||||
return Math.min(0.95,
|
||||
(Player.strength +
|
||||
Player.dexterity +
|
||||
Player.agility) / (1.5 * lvl));
|
||||
Player.agility) / (1.45 * lvl));
|
||||
}
|
||||
|
||||
|
||||
@ -627,7 +627,7 @@ function getInfiltrationKnockoutChance(inst) {
|
||||
return Math.min(0.95,
|
||||
(Player.strength +
|
||||
Player.dexterity +
|
||||
Player.agility) / (1.75 * lvl));
|
||||
Player.agility) / (1.7 * lvl));
|
||||
}
|
||||
|
||||
//Stealth knockout
|
||||
@ -648,7 +648,7 @@ function attemptInfiltrationStealthKnockout(inst) {
|
||||
function getInfiltrationStealthKnockoutChance(inst) {
|
||||
var lvl = inst.securityLevel;
|
||||
return Math.min(0.95,
|
||||
(0.5 * Player.strength +
|
||||
(0.55 * Player.strength +
|
||||
2 * Player.dexterity +
|
||||
2 * Player.agility +
|
||||
intWgt * Player.intelligence) / (3 * lvl));
|
||||
|
@ -203,7 +203,7 @@ HackingMission.prototype.init = function() {
|
||||
var home = Player.getHomeComputer()
|
||||
for (var i = 0; i < home.cpuCores; ++i) {
|
||||
var stats = {
|
||||
atk: (Player.hacking_skill / 6),
|
||||
atk: (Player.hacking_skill / 5),
|
||||
def: (Player.hacking_skill / 20),
|
||||
hp: (Player.hacking_skill / 5),
|
||||
};
|
||||
@ -214,7 +214,7 @@ HackingMission.prototype.init = function() {
|
||||
}
|
||||
|
||||
//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 numDatabases = getRandomInt(this.difficulty, this.difficulty + 1);
|
||||
var totalNodes = numNodes + numFirewalls + numDatabases;
|
||||
@ -223,10 +223,11 @@ HackingMission.prototype.init = function() {
|
||||
console.log("numFirewalls: " + numFirewalls);
|
||||
console.log("numDatabases: " + numDatabases);
|
||||
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) {
|
||||
var stats = {
|
||||
atk: randMult * getRandomInt(40, 60),
|
||||
atk: randMult * getRandomInt(50, 75),
|
||||
def: randMult * getRandomInt(20, 40),
|
||||
hp: randMult * getRandomInt(100, 120)
|
||||
}
|
||||
@ -246,7 +247,7 @@ HackingMission.prototype.init = function() {
|
||||
}
|
||||
for (var i = 0; i < numDatabases; ++i) {
|
||||
var stats = {
|
||||
atk: randMult * getRandomInt(10, 20),
|
||||
atk: 0,
|
||||
def: randMult * getRandomInt(20, 30),
|
||||
hp: randMult * getRandomInt(120, 150)
|
||||
}
|
||||
@ -586,6 +587,10 @@ HackingMission.prototype.setNodePosition = function(nodeObj, x, y) {
|
||||
|
||||
HackingMission.prototype.setNodeRandomPosition = function(nodeObj, xlimit=0) {
|
||||
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);
|
||||
pos = pos[0];
|
||||
this.setNodePosition(nodeObj, pos[0], pos[1]);
|
||||
@ -604,7 +609,7 @@ HackingMission.prototype.createMap = function() {
|
||||
for (var y = 0; y < 8; ++y) {
|
||||
if (!(this.map[x][y] instanceof Node)) {
|
||||
var node, type = getRandomInt(0, 2);
|
||||
var randMult = addOffset(this.difficulty, 20);
|
||||
var randMult = addOffset(0.75 + (this.difficulty / 3), 20);
|
||||
switch (type) {
|
||||
case 0: //Spam
|
||||
var stats = {
|
||||
@ -828,6 +833,7 @@ HackingMission.prototype.nodeReachable = function(node) {
|
||||
}
|
||||
|
||||
HackingMission.prototype.nodeReachableByEnemy = function(node) {
|
||||
if (node === null) {return false;}
|
||||
var x = node.pos[0], y = node.pos[1];
|
||||
if (x > 0 && 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();
|
||||
}
|
||||
|
||||
//Win if all enemy databases are conquered
|
||||
if (this.enemyDatabases.length === 0) {
|
||||
this.finishMission(true);
|
||||
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
|
||||
this.miscNodes.forEach((node)=>{
|
||||
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
|
||||
var calcStats = false;
|
||||
var calcStats = false, plyr = nodeObj.plyrCtrl;
|
||||
var enmyHacking = this.difficulty * CONSTANTS.HackingMissionDifficultyToHacking;
|
||||
switch(nodeObj.action) {
|
||||
case NodeActions.Attack:
|
||||
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);
|
||||
break;
|
||||
case NodeActions.Scan:
|
||||
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);
|
||||
calcStats = true;
|
||||
break;
|
||||
case NodeActions.Weaken:
|
||||
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);
|
||||
calcStats = true;
|
||||
break;
|
||||
@ -1086,7 +1100,7 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
|
||||
targetNode.action = null;
|
||||
targetNode.conn = null;
|
||||
if (this.selectedNode == targetNode) {
|
||||
targetNode.deselect();
|
||||
targetNode.deselect(this.actionButtons);
|
||||
}
|
||||
|
||||
//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
|
||||
this.miscNodes.forEach((node)=>{
|
||||
node.def += CONSTANTS.HackingMissionMiscDefenseIncrease;
|
||||
});
|
||||
if (isMiscNode && conqueredByPlayer) {
|
||||
this.miscNodes.forEach((node)=>{
|
||||
node.def *= CONSTANTS.HackingMissionMiscDefenseIncrease;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//Update node DOMs
|
||||
@ -1214,7 +1230,12 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
|
||||
if (this.miscNodes.length === 0) {
|
||||
//Randomly pick a player node and attack it if its reachable
|
||||
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)) {
|
||||
//Create connection
|
||||
console.log("Enemy core selected a Player Node as target");
|
||||
@ -1225,7 +1246,12 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
|
||||
} else {
|
||||
//Randomly pick a player core and attack it if its reachable
|
||||
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)) {
|
||||
//Create connection
|
||||
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
|
||||
nodeObj.action = NodeActions.Fortify;
|
||||
} else {
|
||||
//If this node has a selected target
|
||||
var targetNode;
|
||||
if (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()");
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
nodeObj.action = NodeActions.Attack;
|
||||
@ -1291,11 +1324,11 @@ HackingMission.prototype.calculateAttackDamage = 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) {
|
||||
return Math.max((atk/2) + hacking / hackEffWeightTarget - def, 1);
|
||||
return Math.max((atk) + hacking / hackEffWeightTarget - def, 1);
|
||||
}
|
||||
|
||||
HackingMission.prototype.calculateFortifyEffect = function(hacking=0) {
|
||||
|
@ -84,8 +84,6 @@ function evaluate(exp, workerScript) {
|
||||
//Create new Environment for the function
|
||||
//Should be automatically garbage collected...
|
||||
var funcEnv = env.extend();
|
||||
console.log("Printing new environment for function:");
|
||||
console.log(funcEnv);
|
||||
|
||||
//Define function arguments in this new environment
|
||||
for (var i = 0; i < func.params.length; ++i) {
|
||||
@ -105,7 +103,23 @@ function evaluate(exp, workerScript) {
|
||||
evaluate(func.body, funcWorkerScript).then(function(res) {
|
||||
resolve(res);
|
||||
}).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"){
|
||||
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> " +
|
||||
"Since you cancelled your work early, you only gained half of the reputation you earned. <br><br>" + txt;
|
||||
} else {
|
||||
txt = "You worked a full shift of 8 hours! <br><br> " +
|
||||
"You earned a total of: <br>" + txt;
|
||||
txt = "You worked a full shift of 8 hours! <br><br> " + txt;
|
||||
}
|
||||
if (!sing) {dialogBoxCreate(txt);}
|
||||
|
||||
@ -1483,16 +1482,16 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
|
||||
break;
|
||||
case CONSTANTS.CrimeKidnap:
|
||||
this.karma -= 6;
|
||||
this.gainIntelligenceExp(CONSTANTS.IntelligenceCrimeBaseExpGain);
|
||||
this.gainIntelligenceExp(2 * CONSTANTS.IntelligenceCrimeBaseExpGain);
|
||||
break;
|
||||
case CONSTANTS.CrimeAssassination:
|
||||
++this.numPeopleKilled;
|
||||
this.karma -= 10;
|
||||
this.gainIntelligenceExp(CONSTANTS.IntelligenceCrimeBaseExpGain);
|
||||
this.gainIntelligenceExp(5 * CONSTANTS.IntelligenceCrimeBaseExpGain);
|
||||
break;
|
||||
case CONSTANTS.CrimeHeist:
|
||||
this.karma -= 15;
|
||||
this.gainIntelligenceExp(5 * CONSTANTS.IntelligenceCrimeBaseExpGain);
|
||||
this.gainIntelligenceExp(10 * CONSTANTS.IntelligenceCrimeBaseExpGain);
|
||||
break;
|
||||
default:
|
||||
console.log(this.crimeType);
|
||||
|
@ -11,11 +11,13 @@ require('brace/theme/twilight');
|
||||
require('brace/theme/xcode');
|
||||
require("brace/keybinding/vim");
|
||||
require("brace/keybinding/emacs");
|
||||
require("brace/ext/language_tools");
|
||||
|
||||
import {CONSTANTS} from "./Constants.js";
|
||||
import {Engine} from "./engine.js";
|
||||
import {iTutorialSteps, iTutorialNextStep,
|
||||
iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js";
|
||||
import {NetscriptFunctions} from "./NetscriptFunctions.js";
|
||||
import {addWorkerScript, killWorkerScript} from "./NetscriptWorker.js";
|
||||
import {Player} from "./Player.js";
|
||||
import {AllServers, processSingleServerGrowth} from "./Server.js";
|
||||
@ -101,6 +103,26 @@ function scriptEditorInit() {
|
||||
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);
|
||||
|
||||
|
@ -508,7 +508,7 @@ let Engine = {
|
||||
" (" + numeral(Player.agility_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
'Charisma: ' + (Player.charisma).toLocaleString() +
|
||||
" (" + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)<br>' +
|
||||
intText +
|
||||
intText +
|
||||
'<b>Multipliers</b><br><br>' +
|
||||
'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%<br>' +
|
||||
'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%<br>' +
|
||||
@ -1146,6 +1146,8 @@ let Engine = {
|
||||
initLiterature();
|
||||
initSingularitySFFlags();
|
||||
|
||||
console.log(Player.intelligence_exp);
|
||||
|
||||
//Calculate the number of cycles have elapsed while offline
|
||||
Engine._lastUpdate = new Date().getTime();
|
||||
var lastUpdate = Player.lastUpdate;
|
||||
|
Loading…
Reference in New Issue
Block a user