v0.28.6 changes

This commit is contained in:
danielyxie 2017-09-15 09:06:59 -05:00
parent c0369bc937
commit e3991b8795
17 changed files with 983 additions and 566 deletions

999
dist/bundle.js vendored

File diff suppressed because it is too large Load Diff

@ -53,7 +53,20 @@ function initBitNodes() {
"upgrade its level up to a maximum of 3. This Source-File lets you access and use the Singularity " + "upgrade its level up to a maximum of 3. This Source-File lets you access and use the Singularity " +
"Functions in other BitNodes. Each level of this Source-File will open up more Singularity Functions " + "Functions in other BitNodes. Each level of this Source-File will open up more Singularity Functions " +
"that you can use."); "that you can use.");
BitNodes["BitNode5"] = new BitNode(5, "Artificial Intelligence", "COMING SOON"); //Int BitNodes["BitNode5"] = new BitNode(5, "Artificial Intelligence", "Posthuman", "They said it couldn't be done. They said the human brain, " +
"along with its consciousness and intelligence, couldn't be replicated. They said the complexity " +
"of the brain results from unpredictable, nonlinear interactions that couldn't be modeled " +
"by 1's and 0's. They were wrong.<br><br>" +
"In this BitNode <br><br>" +
"Destroying this BitNode will give you Source-File 5, or if you already have this Source-File it will " +
"upgrade its level up to a maximum of 3. This Source-File grants you a special new stat called Intelligence. " +
"Intelligence is unique because it is permanent and persistent (it never gets reset back to 1). However " +
"gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't know " +
"when you gain experience and how much). Higher Intelligence levels will boost your production for many actions " +
"in the game. This source file will also raise all of your hacking-related multipliers by:<br><br>" +
"Level 1: 4%<br>" +
"Level 2: 6%<br>" +
"Level 3: 7%");
BitNodes["BitNode6"] = new BitNode(6, "Hacktocracy", "COMING SOON"); //Healthy Hacknet balancing mechanic BitNodes["BitNode6"] = new BitNode(6, "Hacktocracy", "COMING SOON"); //Healthy Hacknet balancing mechanic
BitNodes["BitNode7"] = new BitNode(7, "Do Androids Dream?", "COMING SOON"); //Build androids for automation BitNodes["BitNode7"] = new BitNode(7, "Do Androids Dream?", "COMING SOON"); //Build androids for automation
BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "COMING SOON"); //Trading only viable strategy BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "COMING SOON"); //Trading only viable strategy

@ -1,5 +1,5 @@
let CONSTANTS = { let CONSTANTS = {
Version: "0.28.5", Version: "0.28.6",
//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
@ -86,9 +86,9 @@ let CONSTANTS = {
//Server constants //Server constants
ServerBaseGrowthRate: 1.03, //Unadjusted Growth rate ServerBaseGrowthRate: 1.03, //Unadjusted Growth rate
ServerMaxGrowthRate: 1.0035, //Maximum possible growth rate (max rate accounting for server security) ServerMaxGrowthRate: 1.0035, //Maximum possible growth rate (max rate accounting for server security)
ServerFortifyAmount: 0.002, //Amount by which server's security increases when its hacked/grown ServerFortifyAmount: 0.002, //Amount by which server's security increases when its hacked/grown
ServerWeakenAmount: 0.05, //Amount by which server's security decreases when weakened ServerWeakenAmount: 0.05, //Amount by which server's security decreases when weakened
PurchasedServerLimit: 25, PurchasedServerLimit: 25,
@ -112,6 +112,13 @@ let CONSTANTS = {
//Hospital/Health //Hospital/Health
HospitalCostPerHp: 100000, HospitalCostPerHp: 100000,
//Intelligence-related 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.0001,
IntelligenceProgramBaseExpGain: 1000, //Program required hack level divided by this to determine int exp gain
IntelligenceTerminalHackBaseExpGain: 200, //Hacking exp divided by this to determine int exp gain
//Gang constants //Gang constants
GangRespectToReputationRatio: 2, //Respect is divided by this to get rep gain GangRespectToReputationRatio: 2, //Respect is divided by this to get rep gain
MaximumGangMembers: 20, MaximumGangMembers: 20,
@ -231,7 +238,8 @@ let CONSTANTS = {
"encounter diminishing returns in your hacking (since you are only hacking a certain percentage). You can " + "encounter diminishing returns in your hacking (since you are only hacking a certain percentage). You can " +
"increase the amount of money on a server using a script and the grow() function in Netscript.<br><br>" + "increase the amount of money on a server using a script and the grow() function in Netscript.<br><br>" +
"<h1>Server Security</h1><br>" + "<h1>Server Security</h1><br>" +
"Each server has a security level, which is denoted by a number between 1 and 100. A higher number means " + "Each server has a security level, typically between 1 and 100. It is possible for a server to have a security " +
"level 100 or higher, in which case hacking a server will become impossible. A higher number means " +
"the server has stronger security. As mentioned above, a server's security level is an important factor " + "the server has stronger security. As mentioned above, a server's security level is an important factor " +
"to consider when hacking. You can check a server's security level using the 'analyze' command, although this " + "to consider when hacking. You can check a server's security level using the 'analyze' command, although this " +
"only gives an estimate (with 5% uncertainty). You can also check a server's security in a script, using the " + "only gives an estimate (with 5% uncertainty). You can also check a server's security in a script, using the " +
@ -482,6 +490,8 @@ let CONSTANTS = {
"<i>getServerRam(hostname/ip)</i><br>Returns an array with two elements that gives information about the target server's RAM. The first " + "<i>getServerRam(hostname/ip)</i><br>Returns an array with two elements that gives information about the target server's RAM. The first " +
"element in the array is the amount of RAM that the server has (in GB). The second element in the array is the amount of RAM that " + "element in the array is the amount of RAM that the server has (in GB). The second element in the array is the amount of RAM that " +
"is currently being used on the server.<br><br>" + "is currently being used on the server.<br><br>" +
"<i>serverExists(hostname/ip)</i><br>Returns a boolean denoting whether or not the specified server exists. The argument " +
"must be a string with the hostname or IP of the target server.<br><br>" +
"<i>fileExists(filename, [hostname/ip])</i><br> Returns a boolean (true or false) indicating whether the specified file exists on a server. " + "<i>fileExists(filename, [hostname/ip])</i><br> Returns a boolean (true or false) indicating whether the specified file exists on a server. " +
"The first argument must be a string with the name of the file. A file can either be a script or a program. A script name is case-sensitive, but a " + "The first argument must be a string with the name of the file. A file can either be a script or a program. A script name is case-sensitive, but a " +
"program is not. For example, fileExists('brutessh.exe') will work fine, even though the actual program is named BruteSSH.exe. <br><br> " + "program is not. For example, fileExists('brutessh.exe') will work fine, even though the actual program is named BruteSSH.exe. <br><br> " +
@ -547,6 +557,17 @@ let CONSTANTS = {
"The second argument must be a string with the hostname/IP of the target server. If the first argument is specified " + "The second argument must be a string with the hostname/IP of the target server. If the first argument is specified " +
"then the second argument must be specified as well. Any additional arguments passed to the function will specify " + "then the second argument must be specified as well. Any additional arguments passed to the function will specify " +
"the arguments passed into the target script.<br><br>" + "the arguments passed into the target script.<br><br>" +
"<i>getScriptExpGain([scriptname], [hostname/ip], [args...])</i><br>" +
"Returns the amount of hacking experience the specified script generates while online (when the game is open, does not apply for " +
"offline experience gains). This function can also return the total experience gain rate of all of your active scripts by running the function " +
"with no arguments.<br><br>" +
"Remember that a script is uniquely identified by both its name and its arguments. So for example if you ran a script " +
"with the arguments 'foodnstuff' and '5' then in order to use this function to get that script's income you must " +
"specify those arguments in this function call.<br><br>" +
"The first argument, if specified, must be a string with the name of the script (including the .script extension). " +
"The second argument must be a string with the hostname/IP of the target server. If the first argument is specified " +
"then the second argument must be specified as well. Any additional arguments passed to the function will specify " +
"the arguments passed into the target script.<br><br>" +
"<u><h1>Hacknet Nodes API</h1></u><br>" + "<u><h1>Hacknet Nodes API</h1></u><br>" +
"Netscript provides the following API for accessing and upgrading your Hacknet Nodes through scripts. This API does NOT work offline.<br><br>" + "Netscript provides the following API for accessing and upgrading your Hacknet Nodes through scripts. This API does NOT work offline.<br><br>" +
"<i>hacknetnodes</i><br> A special variable. This is an array that maps to the Player's Hacknet Nodes. The Hacknet Nodes are accessed through " + "<i>hacknetnodes</i><br> A special variable. This is an array that maps to the Player's Hacknet Nodes. The Hacknet Nodes are accessed through " +
@ -875,41 +896,17 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.28.5<br>" + "v0.28.6<br>" +
"-The fl1ght.exe program that is received from jump3r is now sent very early on in the game, rather " + "-Time required to create programs now scales better with hacking level, and should generally be much faster<br>" +
"than at hacking level 1000<br>" + "-Added serverExists(hostname/ip) and getScriptExpGain(scriptname, ip, args...) Netscript functions<br>" +
"-Hostname is now displayed in Terminal<br>" + "-Short circuiting && and || logical operators should now work<br>" +
"-Syntax highlighting now works for all Netscript functions<br>" + "-Assigning to multidimensional arrays should now work<br>" +
"-Export should now work on Edge/IE<br><br>" + "-Scripts will no longer wait for hack/grow/weaken functions to finish if they are killed. They will die immediately<br>" +
"v0.28.4<br>" + "-The script loop that checks whether any scripts need to be started/stopped now runs every 6 seconds rather than 10 " +
"-Added getScriptIncome() Netscript function<br>" + "(resulting in less delays when stopping/starting scripts)<br>" +
"-Added Javascript's Math module to Netscript. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math<br>" + "-Fixed several bugs/exploits<br>" +
"-Added several member variables for the Hacknet Node API that allow you to access info about their income<br>" + "-Added some description for BitNode-5 (not implemented yet, should be soon though)<br>",
"-All valid Netscript functions are now syntax highlighted as keywords in the editor. This means they will a different " +
"color than invalid netscript functions. The color will depend on your theme. " +
"Note that right now, this only applies for normal Netscript functions, not " +
"functions in the TIX API, Hacknet Node API, or Singularity Functions.<br><br>" +
"-Comments and operators no longer count towards RAM usage in scripts.<br>" +
"-Variety of bug fixes and updates to informational text in the game<br><br>" +
"v0.28.3<br>" +
"-Added ls() Netscript function<br>" +
"-Increased company wages by about ~10% across the board<br>" +
"-The scp() Netsction function and Terminal command now works for .lit files<br>" +
"-Increased the amount of RAM on many lower level servers (up to level 200 hacking level required).<br><br>" +
"v0.28.2<br>" +
"-Added a few script editor configuration options. Includes key bindings, themes, etc.<br>" +
"-Certain menu options will now be hidden until their relevant gameplay is unlocked. This " +
"really only affects new players<br>" +
"-Most unrecognized or un-implemented syntax errors in a script will now include line number in error message<br>" +
"-Various bug fixes<br><br>" +
"v0.28.1<br>" +
"-The script editor now uses the open-source Ace editor, which provides a much better experience when coding!<br>" +
"-Added tprint() Netscript function<br><br>" +
"v0.28.0<br>" +
"-Added BitNode-4: The Singularity<br>" +
"-Added BitNode-11: The Big Crash<br>" +
"-Migrated the codebase to use webpack (doesn't affect any in game content, except maybe some slight " +
"performance improvements and there may be bugs that result from dependency errors)"
} }
export {CONSTANTS}; export {CONSTANTS};

@ -110,99 +110,113 @@ function determineCrimeSuccess(crime, moneyGained) {
} }
} }
let intWgt = CONSTANTS.IntelligenceCrimeWeight;
let maxLvl = CONSTANTS.MaxSkillLevel;
function determineCrimeChanceShoplift() { function determineCrimeChanceShoplift() {
var chance = ((Player.dexterity / CONSTANTS.MaxSkillLevel + var chance = (Player.dexterity / maxLvl +
Player.agility / CONSTANTS.MaxSkillLevel)) * 20; Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl) * 20;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceRobStore() { function determineCrimeChanceRobStore() {
var chance = ((0.5 * Player.hacking_skill / CONSTANTS.MaxSkillLevel + var chance = (0.5 * Player.hacking_skill / maxLvl +
2 * Player.dexterity / CONSTANTS.MaxSkillLevel + 2 * Player.dexterity / maxLvl +
1 * Player.agility / CONSTANTS.MaxSkillLevel)) * 5; 1 * Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl) * 5;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceMug() { function determineCrimeChanceMug() {
var chance = ((1.5 * Player.strength / CONSTANTS.MaxSkillLevel + var chance = (1.5 * Player.strength / maxLvl +
0.5 * Player.defense / CONSTANTS.MaxSkillLevel + 0.5 * Player.defense / maxLvl +
1.5 * Player.dexterity / CONSTANTS.MaxSkillLevel + 1.5 * Player.dexterity / maxLvl +
0.5 * Player.agility / CONSTANTS.MaxSkillLevel)) * 5; 0.5 * Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl) * 5;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceLarceny() { function determineCrimeChanceLarceny() {
var chance = ((0.5 * Player.hacking_skill / CONSTANTS.MaxSkillLevel + var chance = (0.5 * Player.hacking_skill / maxLvl +
Player.dexterity / CONSTANTS.MaxSkillLevel + Player.dexterity / maxLvl +
Player.agility / CONSTANTS.MaxSkillLevel)) * 3; Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl) * 3;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceDealDrugs() { function determineCrimeChanceDealDrugs() {
var chance = ((3*Player.charisma / CONSTANTS.MaxSkillLevel + var chance = (3*Player.charisma / maxLvl +
2*Player.dexterity / CONSTANTS.MaxSkillLevel + 2*Player.dexterity / maxLvl +
Player.agility / CONSTANTS.MaxSkillLevel)); Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl);
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceTraffickArms() { function determineCrimeChanceTraffickArms() {
var chance = ((Player.charisma / CONSTANTS.MaxSkillLevel + var chance = (Player.charisma / maxLvl +
Player.strength / CONSTANTS.MaxSkillLevel + Player.strength / maxLvl +
Player.defense / CONSTANTS.MaxSkillLevel + Player.defense / maxLvl +
Player.dexterity / CONSTANTS.MaxSkillLevel + Player.dexterity / maxLvl +
Player.agility / CONSTANTS.MaxSkillLevel)) / 2; Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl) / 2;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceHomicide() { function determineCrimeChanceHomicide() {
var chance = ((2 * Player.strength / CONSTANTS.MaxSkillLevel + var chance = (2 * Player.strength / maxLvl +
2 * Player.defense / CONSTANTS.MaxSkillLevel + 2 * Player.defense / maxLvl +
0.5 * Player.dexterity / CONSTANTS.MaxSkillLevel + 0.5 * Player.dexterity / maxLvl +
0.5 * Player.agility / CONSTANTS.MaxSkillLevel)); 0.5 * Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl);
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceGrandTheftAuto() { function determineCrimeChanceGrandTheftAuto() {
var chance = ((Player.hacking_skill / CONSTANTS.MaxSkillLevel + var chance = (Player.hacking_skill / maxLvl +
Player.strength / CONSTANTS.MaxSkillLevel + Player.strength / maxLvl +
4 * Player.dexterity / CONSTANTS.MaxSkillLevel + 4 * Player.dexterity / maxLvl +
2 * Player.agility / CONSTANTS.MaxSkillLevel + 2 * Player.agility / maxLvl +
2 * Player.charisma / CONSTANTS.MaxSkillLevel)) / 8; 2 * Player.charisma / maxLvl +
intWgt * Player.intelligence / maxLvl) / 8;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceKidnap() { function determineCrimeChanceKidnap() {
var chance = ((Player.charisma / CONSTANTS.MaxSkillLevel + var chance = (Player.charisma / maxLvl +
Player.strength / CONSTANTS.MaxSkillLevel + Player.strength / maxLvl +
Player.dexterity / CONSTANTS.MaxSkillLevel + Player.dexterity / maxLvl +
Player.agility / CONSTANTS.MaxSkillLevel)) / 5; Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl) / 5;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceAssassination() { function determineCrimeChanceAssassination() {
var chance = ((Player.strength / CONSTANTS.MaxSkillLevel + var chance = (Player.strength / maxLvl +
2 * Player.dexterity / CONSTANTS.MaxSkillLevel + 2 * Player.dexterity / maxLvl +
Player.agility / CONSTANTS.MaxSkillLevel)) / 8; Player.agility / maxLvl +
intWgt * Player.intelligence / maxLvl) / 8;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceHeist() { function determineCrimeChanceHeist() {
var chance = ((Player.hacking_skill / CONSTANTS.MaxSkillLevel + var chance = (Player.hacking_skill / maxLvl +
Player.strength / CONSTANTS.MaxSkillLevel + Player.strength / maxLvl +
Player.defense / CONSTANTS.MaxSkillLevel + Player.defense / maxLvl +
Player.dexterity / CONSTANTS.MaxSkillLevel + Player.dexterity / maxLvl +
Player.agility / CONSTANTS.MaxSkillLevel + Player.agility / maxLvl +
Player.charisma / CONSTANTS.MaxSkillLevel)) / 18; Player.charisma / maxLvl +
intWgt * Player.intelligence / maxLvl) / 18;
chance *= Player.crime_success_mult; chance *= Player.crime_success_mult;
return Math.min(chance, 1); return Math.min(chance, 1);
} }

@ -130,7 +130,7 @@ function processAllGangPowerGains(numCycles=1) {
if (name == playerGangName) { if (name == playerGangName) {
AllGangs[name].power += Player.gang.calculatePower(); AllGangs[name].power += Player.gang.calculatePower();
} else { } else {
var gain = Math.random() * 0.01; //TODO Adjust as necessary var gain = Math.random() * 0.02; //TODO Adjust as necessary
AllGangs[name].power += (gain); AllGangs[name].power += (gain);
} }
} }

@ -441,7 +441,7 @@ function updateInfiltrationLevelText(inst) {
var totalValue = 0; var totalValue = 0;
var totalMoneyValue = 0; var totalMoneyValue = 0;
for (var i = 0; i < inst.secretsStolen.length; ++i) { for (var i = 0; i < inst.secretsStolen.length; ++i) {
totalValue += inst.secretsStolen[i]; totalValue += (inst.secretsStolen[i] * Player.faction_rep_mult * 1.25);
totalMoneyValue += inst.secretsStolen[i] * CONSTANTS.InfiltrationMoneyValue; totalMoneyValue += inst.secretsStolen[i] * CONSTANTS.InfiltrationMoneyValue;
} }
document.getElementById("infiltration-level-text").innerHTML = document.getElementById("infiltration-level-text").innerHTML =
@ -577,6 +577,7 @@ function updateInfiltrationButtons(inst, scenario) {
} }
} }
let intWgt = CONSTANTS.IntelligenceInfiltrationWeight;
//Kill //Kill
//Success: 5%, Failure 10%, -Karma //Success: 5%, Failure 10%, -Karma
@ -649,7 +650,8 @@ function getInfiltrationStealthKnockoutChance(inst) {
return Math.min(0.95, return Math.min(0.95,
(0.5 * Player.strength + (0.5 * Player.strength +
2 * Player.dexterity + 2 * Player.dexterity +
2 * Player.agility) / (3 * lvl)); 2 * Player.agility +
intWgt * Player.intelligence) / (3 * lvl));
} }
//Assassination //Assassination
@ -671,7 +673,8 @@ function getInfiltrationAssassinateChance(inst) {
var lvl = inst.securityLevel; var lvl = inst.securityLevel;
return Math.min(0.95, return Math.min(0.95,
(Player.dexterity + (Player.dexterity +
0.5 * Player.agility) / (2 * lvl)); 0.5 * Player.agility +
intWgt * Player.intelligence) / (2 * lvl));
} }
@ -720,7 +723,8 @@ function attemptInfiltrationHack(inst) {
function getInfiltrationHackChance(inst) { function getInfiltrationHackChance(inst) {
var lvl = inst.securityLevel; var lvl = inst.securityLevel;
return Math.min(0.95, return Math.min(0.95,
(Player.hacking_skill) / lvl); (Player.hacking_skill +
(intWgt * Player.intelligence)) / lvl);
} }
//Sneak past security //Sneak past security
@ -740,7 +744,8 @@ function getInfiltrationSneakChance(inst) {
var lvl = inst.securityLevel; var lvl = inst.securityLevel;
return Math.min(0.95, return Math.min(0.95,
(Player.agility + (Player.agility +
0.5 * Player.dexterity) / (2 * lvl)); 0.5 * Player.dexterity +
intWgt * Player.intelligence) / (2 * lvl));
} }
//Pick locked door //Pick locked door
@ -760,7 +765,8 @@ function attemptInfiltrationPickLockedDoor(inst) {
function getInfiltrationPickLockedDoorChance(inst) { function getInfiltrationPickLockedDoorChance(inst) {
var lvl = inst.securityLevel; var lvl = inst.securityLevel;
return Math.min(0.95, return Math.min(0.95,
(Player.dexterity) / lvl); (Player.dexterity +
intWgt * Player.intelligence) / lvl);
} }
//Bribe //Bribe
@ -800,7 +806,8 @@ function getInfiltrationEscapeChance(inst) {
var lvl = inst.securityLevel; var lvl = inst.securityLevel;
return Math.min(0.95, return Math.min(0.95,
(2 * Player.agility + (2 * Player.agility +
Player.dexterity) / lvl); Player.dexterity +
intWgt * Player.intelligence) / lvl);
} }
export {beginInfiltration}; export {beginInfiltration};

@ -50,6 +50,30 @@ Environment.prototype = {
return (scope || this).vars[name] = value; return (scope || this).vars[name] = value;
}, },
setArrayElement: function(name, idx, value) {
if (!(idx instanceof Array)) {
throw new Error("idx parameter is not an Array");
}
var scope = this.lookup(name);
if (!scope && this.parent) {
console.log("Here");
throw new Error("Undefined variable " + name);
}
var arr = (scope || this).vars[name];
if (!(arr.constructor === Array || arr instanceof Array)) {
throw new Error("Variable is not an array: " + name);
}
var res = arr;
for (var iterator = 0; iterator < idx.length-1; ++iterator) {
var i = idx[iterator];
if (!(res instanceof Array) || i >= res.length) {
throw new Error("Out-of-bounds array access");
}
res = res[i];
}
return res[idx[idx.length-1]] = value;
},
/*
setArrayElement: function(name, idx, value) { setArrayElement: function(name, idx, value) {
var scope = this.lookup(name); var scope = this.lookup(name);
if (!scope && this.parent) { if (!scope && this.parent) {
@ -61,7 +85,7 @@ Environment.prototype = {
throw new Error("Variable is not an array: " + name); throw new Error("Variable is not an array: " + name);
} }
return (scope || this).vars[name][idx] = value; return (scope || this).vars[name][idx] = value;
}, },*/
//Creates (or overwrites) a variable in the current scope //Creates (or overwrites) a variable in the current scope
def: function(name, value) { def: function(name, value) {

@ -252,6 +252,12 @@ function evalBinary(exp, workerScript){
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
var expLeftPromise = evaluate(exp.left, workerScript); var expLeftPromise = evaluate(exp.left, workerScript);
expLeftPromise.then(function(expLeft) { expLeftPromise.then(function(expLeft) {
if (expLeft == true && exp.operator === "||") {
return resolve(true);
}
if (expLeft == false && exp.operator === "&&") {
return resolve(false);
}
var expRightPromise = evaluate(exp.right, workerScript); var expRightPromise = evaluate(exp.right, workerScript);
expRightPromise.then(function(expRight) { expRightPromise.then(function(expRight) {
switch (exp.operator){ switch (exp.operator){
@ -307,7 +313,7 @@ function evalBinary(exp, workerScript){
resolve(expLeft && expRight); resolve(expLeft && expRight);
break; break;
default: default:
reject(makeRuntimeRejectMsg(workerScript, "Bitwise operators are not implemented")); reject(makeRuntimeRejectMsg(workerScript, "Unsupported operator: " + exp.operator));
} }
}, function(e) { }, function(e) {
reject(e); reject(e);
@ -341,6 +347,40 @@ function evalUnary(exp, workerScript){
}); });
} }
//Takes in a MemberExpression that should represent a Netscript array (possible multidimensional)
//The return value is an array of the form:
// [0th index (leftmost), array name, 1st index, 2nd index, ...]
function getArrayElement(exp, workerScript) {
return new Promise(function(resolve, reject) {
var indices = [];
var iPromise = evaluate(exp.property, workerScript);
iPromise.then(function(idx) {
if (isNaN(idx)) {
return reject(makeRuntimeRejectMsg(workerScript, "Invalid access to array. Index is not a number: " + idx));
} else {
if (exp.object.name === undefined && exp.object.object) {
var recursePromise = getArrayElement(exp.object, workerScript);
recursePromise.then(function(res) {
res.push(idx);
indices = res;
return resolve(indices);
}).catch(function(e) {
return reject(e);
});
} else {
indices.push(idx);
indices.push(exp.object.name);
return resolve(indices);
}
}
}).catch(function(e) {
console.log(e);
console.log("Error getting index in getArrayElement: " + e.toString());
return reject(e);
});
});
}
function evalAssignment(exp, workerScript) { function evalAssignment(exp, workerScript) {
var env = workerScript.env; var env = workerScript.env;
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
@ -360,6 +400,22 @@ function evalAssignment(exp, workerScript) {
//Assign to array element //Assign to array element
//Array object designed by exp.left.object.name //Array object designed by exp.left.object.name
//Index designated by exp.left.property //Index designated by exp.left.property
var getArrayElementPromise = getArrayElement(exp.left, workerScript);
getArrayElementPromise.then(function(res) {
if (!(res instanceof Array) || res.length < 2) {
return reject(makeRuntimeRejectMsg(workerScript, "Error evaluating array assignment. This is (probably) a bug please report to game dev"));
}
//The array name is the second value
var arrName = res.splice(1, 1);
arrName = arrName[0];
env.setArrayElement(arrName, res, expRight);
return resolve(false);
}).catch(function(e) {
return reject(e);
});
/*
var name = exp.left.object.name; var name = exp.left.object.name;
if (!(name in env.vars)){ if (!(name in env.vars)){
reject(makeRuntimeRejectMsg(workerScript, "variable " + name + " not defined")); reject(makeRuntimeRejectMsg(workerScript, "variable " + name + " not defined"));
@ -380,7 +436,7 @@ function evalAssignment(exp, workerScript) {
}); });
} else { } else {
return reject(makeRuntimeRejectMsg(workerScript, "Trying to access a non-array variable using the [] operator")); return reject(makeRuntimeRejectMsg(workerScript, "Trying to access a non-array variable using the [] operator"));
} }*/
} else { } else {
//Other assignments //Other assignments
try { try {
@ -406,11 +462,12 @@ function evalAssignment(exp, workerScript) {
default: default:
reject(makeRuntimeRejectMsg(workerScript, "Bitwise assignment is not implemented")); reject(makeRuntimeRejectMsg(workerScript, "Bitwise assignment is not implemented"));
} }
resolve(false);
} catch (e) { } catch (e) {
return reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString())); return reject(makeRuntimeRejectMsg(workerScript, "Failed to set environment variable: " + e.toString()));
} }
} }
resolve(false); //Return false so this doesnt cause conditionals to evaluate //resolve(false); //Return false so this doesnt cause conditionals to evaluate
}, function(e) { }, function(e) {
reject(e); reject(e);
}); });
@ -567,9 +624,13 @@ function evaluateProg(exp, workerScript, index) {
}); });
} }
function netscriptDelay(time) { function netscriptDelay(time, workerScript) {
return new Promise(function(resolve) { return new Promise(function(resolve) {
setTimeout(resolve, time); var delay = setTimeout(resolve, time);
workerScript.killTrigger = function() {
clearTimeout(delay);
resolve();
};
}); });
} }
@ -577,6 +638,7 @@ function makeRuntimeRejectMsg(workerScript, msg) {
return "|"+workerScript.serverIp+"|"+workerScript.name+"|" + msg; return "|"+workerScript.serverIp+"|"+workerScript.name+"|" + msg;
} }
/*
function apply_op(op, a, b) { function apply_op(op, a, b) {
function num(x) { function num(x) {
if (typeof x != "number") if (typeof x != "number")
@ -605,6 +667,7 @@ function apply_op(op, a, b) {
} }
throw new Error("Can't apply operator " + op); throw new Error("Can't apply operator " + op);
} }
*/
//Run a script from inside a script using run() command //Run a script from inside a script using run() command
function runScriptFromScript(server, scriptname, args, workerScript, threads=1) { function runScriptFromScript(server, scriptname, args, workerScript, threads=1) {
@ -671,7 +734,7 @@ function isScriptErrorMessage(msg) {
//The same as Player's calculateHackingChance() function but takes in the server as an argument //The same as Player's calculateHackingChance() function but takes in the server as an argument
function scriptCalculateHackingChance(server) { function scriptCalculateHackingChance(server) {
var difficultyMult = (100 - server.hackDifficulty) / 100; var difficultyMult = (100 - server.hackDifficulty) / 100;
var skillMult = (1.75 * Player.hacking_skill); var skillMult = (1.75 * Player.hacking_skill) + (0.2 * Player.intelligence);
var skillChance = (skillMult - server.requiredHackingSkill) / skillMult; var skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
var chance = skillChance * difficultyMult * Player.hacking_chance_mult; var chance = skillChance * difficultyMult * Player.hacking_chance_mult;
if (chance > 1) {return 1;} if (chance > 1) {return 1;}
@ -682,7 +745,7 @@ function scriptCalculateHackingChance(server) {
//The same as Player's calculateHackingTime() function but takes in the server as an argument //The same as Player's calculateHackingTime() function but takes in the server as an argument
function scriptCalculateHackingTime(server) { function scriptCalculateHackingTime(server) {
var difficultyMult = server.requiredHackingSkill * server.hackDifficulty; var difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50); var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence));
var hackingTime = 5 * skillFactor / Player.hacking_speed_mult; //This is in seconds var hackingTime = 5 * skillFactor / Player.hacking_speed_mult; //This is in seconds
return hackingTime; return hackingTime;
} }
@ -708,7 +771,7 @@ function scriptCalculatePercentMoneyHacked(server) {
//Amount of time to execute grow() in milliseconds //Amount of time to execute grow() in milliseconds
function scriptCalculateGrowTime(server) { function scriptCalculateGrowTime(server) {
var difficultyMult = server.requiredHackingSkill * server.hackDifficulty; var difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50); var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence));
var growTime = 16 * skillFactor / Player.hacking_speed_mult; //This is in seconds var growTime = 16 * skillFactor / Player.hacking_speed_mult; //This is in seconds
return growTime * 1000; return growTime * 1000;
} }
@ -716,7 +779,7 @@ function scriptCalculateGrowTime(server) {
//Amount of time to execute weaken() in milliseconds //Amount of time to execute weaken() in milliseconds
function scriptCalculateWeakenTime(server) { function scriptCalculateWeakenTime(server) {
var difficultyMult = server.requiredHackingSkill * server.hackDifficulty; var difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50); var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence));
var weakenTime = 20 * skillFactor / Player.hacking_speed_mult; //This is in seconds var weakenTime = 20 * skillFactor / Player.hacking_speed_mult; //This is in seconds
return weakenTime * 1000; return weakenTime * 1000;
} }

@ -37,9 +37,10 @@ import {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript,
import {Environment} from "./NetscriptEnvironment.js"; import {Environment} from "./NetscriptEnvironment.js";
import Decimal from '../utils/decimal.js'; import Decimal from '../utils/decimal.js';
import {dialogBoxCreate} from "../utils/DialogBox.js";
import {printArray, powerOfTwo} from "../utils/HelperFunctions.js"; import {printArray, powerOfTwo} from "../utils/HelperFunctions.js";
import {createRandomIp} from "../utils/IPAddress.js"; import {createRandomIp} from "../utils/IPAddress.js";
import {formatNumber, isString} from "../utils/StringHelperFunctions.js"; import {formatNumber, isString, isHTML} from "../utils/StringHelperFunctions.js";
var hasSingularitySF = false; var hasSingularitySF = false;
var singularitySFLvl = 1; var singularitySFLvl = 1;
@ -101,7 +102,7 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("Attempting to hack " + ip + " in " + hackingTime.toFixed(3) + " seconds (t=" + threads + ")"); workerScript.scriptRef.log("Attempting to hack " + ip + " in " + hackingTime.toFixed(3) + " seconds (t=" + threads + ")");
//console.log("Hacking " + server.hostname + " after " + hackingTime.toString() + " seconds (t=" + threads + ")"); //console.log("Hacking " + server.hostname + " after " + hackingTime.toString() + " seconds (t=" + threads + ")");
return netscriptDelay(hackingTime* 1000).then(function() { return netscriptDelay(hackingTime* 1000, workerScript).then(function() {
if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} if (workerScript.env.stopFlag) {return Promise.reject(workerScript);}
var hackChance = scriptCalculateHackingChance(server); var hackChance = scriptCalculateHackingChance(server);
var rand = Math.random(); var rand = Math.random();
@ -146,7 +147,7 @@ function NetscriptFunctions(workerScript) {
if (log) { if (log) {
workerScript.scriptRef.log("Sleeping for " + time + " milliseconds"); workerScript.scriptRef.log("Sleeping for " + time + " milliseconds");
} }
return netscriptDelay(time).then(function() { return netscriptDelay(time, workerScript).then(function() {
return Promise.resolve(true); return Promise.resolve(true);
}); });
}, },
@ -171,7 +172,7 @@ function NetscriptFunctions(workerScript) {
var growTime = scriptCalculateGrowTime(server); var growTime = scriptCalculateGrowTime(server);
//console.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds") //console.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds")
workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds (t=" + threads + ")"); workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds (t=" + threads + ")");
return netscriptDelay(growTime).then(function() { return netscriptDelay(growTime, workerScript).then(function() {
if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} if (workerScript.env.stopFlag) {return Promise.reject(workerScript);}
server.moneyAvailable += (1 * threads); //It can be grown even if it has no money server.moneyAvailable += (1 * threads); //It can be grown even if it has no money
var growthPercentage = processSingleServerGrowth(server, 450 * threads); var growthPercentage = processSingleServerGrowth(server, 450 * threads);
@ -207,10 +208,9 @@ function NetscriptFunctions(workerScript) {
} }
var weakenTime = scriptCalculateWeakenTime(server); var weakenTime = scriptCalculateWeakenTime(server);
//console.log("Executing weaken() on server " + server.hostname + " in " + formatNumber(weakenTime/1000, 3) + " seconds")
workerScript.scriptRef.log("Executing weaken() on server " + server.hostname + " in " + workerScript.scriptRef.log("Executing weaken() on server " + server.hostname + " in " +
formatNumber(weakenTime/1000, 3) + " seconds (t=" + threads + ")"); formatNumber(weakenTime/1000, 3) + " seconds (t=" + threads + ")");
return netscriptDelay(weakenTime).then(function() { return netscriptDelay(weakenTime, workerScript).then(function() {
if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} if (workerScript.env.stopFlag) {return Promise.reject(workerScript);}
server.weaken(CONSTANTS.ServerWeakenAmount * threads); server.weaken(CONSTANTS.ServerWeakenAmount * threads);
workerScript.scriptRef.recordWeaken(server.ip, threads); workerScript.scriptRef.recordWeaken(server.ip, threads);
@ -232,6 +232,14 @@ function NetscriptFunctions(workerScript) {
if (args === undefined || args === null) { if (args === undefined || args === null) {
throw makeRuntimeRejectMsg(workerScript, "tprint() call has incorrect number of arguments. Takes 1 argument"); throw makeRuntimeRejectMsg(workerScript, "tprint() call has incorrect number of arguments. Takes 1 argument");
} }
var x = args.toString();
if (isHTML(x)) {
Player.takeDamage(1);
dialogBoxCreate("You suddenly feel a sharp shooting pain through your body as an angry voice in your head exclaims: <br><br>" +
"DON'T USE TPRINT() TO OUTPUT HTML ELEMENTS TO YOUR TERMINAL!!!!<br><br>" +
"(You lost 1 HP)");
return;
}
post(workerScript.scriptRef.filename + ": " + args.toString()); post(workerScript.scriptRef.filename + ": " + args.toString());
}, },
clearLog : function() { clearLog : function() {
@ -678,6 +686,9 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("getServerRam() returned [" + formatNumber(server.maxRam, 2) + "GB, " + formatNumber(server.ramUsed, 2) + "GB]"); workerScript.scriptRef.log("getServerRam() returned [" + formatNumber(server.maxRam, 2) + "GB, " + formatNumber(server.ramUsed, 2) + "GB]");
return [server.maxRam, server.ramUsed]; return [server.maxRam, server.ramUsed];
}, },
serverExists : function(ip) {
return (getServer(ip) !== null);
},
fileExists : function(filename,ip=workerScript.serverIp){ fileExists : function(filename,ip=workerScript.serverIp){
if (filename === undefined) { if (filename === undefined) {
throw makeRuntimeRejectMsg(workerScript, "fileExists() call has incorrect number of arguments. Usage: fileExists(scriptname, [server])"); throw makeRuntimeRejectMsg(workerScript, "fileExists() call has incorrect number of arguments. Usage: fileExists(scriptname, [server])");
@ -1038,6 +1049,32 @@ function NetscriptFunctions(workerScript) {
return runningScriptObj.onlineMoneyMade / runningScriptObj.onlineRunningTime; return runningScriptObj.onlineMoneyMade / runningScriptObj.onlineRunningTime;
} }
}, },
getScriptExpGain : function(scriptname, ip) {
if (arguments.length === 0) {
var total = 0;
for (var i = 0; i < workerScripts.length; ++i) {
total += (workerScripts[i].scriptRef.onlineExpGained / workerScripts[i].scriptRef.onlineRunningTime);
}
return total;
} else {
//Get income for a particular script
var server = getServer(ip);
if (server === null) {
workerScript.scriptRef.log("getScriptExpGain() failed. Invalid IP or hostnamed passed in: " + ip);
throw makeRuntimeRejectMsg(workerScript, "getScriptExpGain() failed. Invalid IP or hostnamed passed in: " + ip);
}
var argsForScript = [];
for (var i = 2; i < arguments.length; ++i) {
argsForScript.push(arguments[i]);
}
var runningScriptObj = findRunningScript(scriptname, argsForScript, server);
if (runningScriptObj == null) {
workerScript.scriptRef.log("getScriptExpGain() failed. No such script "+ scriptname + " on " + server.hostname + " with args: " + printArray(argsForScript));
return -1;
}
return runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime;
}
},
/* Singularity Functions */ /* Singularity Functions */
universityCourse(universityName, className) { universityCourse(universityName, className) {

@ -25,6 +25,7 @@ function WorkerScript(runningScriptObj) {
this.scriptRef = runningScriptObj; this.scriptRef = runningScriptObj;
this.errorMessage = ""; this.errorMessage = "";
this.args = runningScriptObj.args; this.args = runningScriptObj.args;
this.killTrigger = function() {}; //CB func used to clear any delays (netscriptDelay())
} }
//Returns the server on which the workerScript is running //Returns the server on which the workerScript is running
@ -148,7 +149,7 @@ function runScriptsLoop() {
} }
} }
setTimeout(runScriptsLoop, 10000); setTimeout(runScriptsLoop, 6000);
} }
//Queues a script to be killed by settings its stop flag to true. Then, the code will reject //Queues a script to be killed by settings its stop flag to true. Then, the code will reject
@ -159,6 +160,7 @@ function killWorkerScript(runningScriptObj, serverIp) {
if (workerScripts[i].name == runningScriptObj.filename && workerScripts[i].serverIp == serverIp && if (workerScripts[i].name == runningScriptObj.filename && workerScripts[i].serverIp == serverIp &&
compareArrays(workerScripts[i].args, runningScriptObj.args)) { compareArrays(workerScripts[i].args, runningScriptObj.args)) {
workerScripts[i].env.stopFlag = true; workerScripts[i].env.stopFlag = true;
workerScripts[i].killTrigger();
return true; return true;
} }
} }

@ -8,7 +8,8 @@ import {CONSTANTS} from "./Constants.js";
import {Programs} from "./CreateProgram.js"; import {Programs} from "./CreateProgram.js";
import {determineCrimeSuccess} from "./Crimes.js"; import {determineCrimeSuccess} from "./Crimes.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {Factions, Faction} from "./Faction.js"; import {Factions, Faction,
displayFactionContent} from "./Faction.js";
import {Gang, resetGangs} from "./Gang.js"; import {Gang, resetGangs} from "./Gang.js";
import {Locations} from "./Location.js"; import {Locations} from "./Location.js";
import {AllServers, Server, AddToAllServers} from "./Server.js"; import {AllServers, Server, AddToAllServers} from "./Server.js";
@ -146,12 +147,14 @@ function PlayerObject() {
this.workMoneyGained = 0; this.workMoneyGained = 0;
this.createProgramName = ""; this.createProgramName = "";
this.createProgramReqLvl = 0;
this.className = ""; this.className = "";
this.crimeType = ""; this.crimeType = "";
this.timeWorked = 0; //in ms this.timeWorked = 0; //in ms
this.timeWorkedCreateProgram = 0;
this.timeNeededToCompleteWork = 0; this.timeNeededToCompleteWork = 0;
this.work_money_mult = 1; this.work_money_mult = 1;
@ -196,15 +199,6 @@ PlayerObject.prototype.init = function() {
this.getHomeComputer().programs.push(Programs.NukeProgram); this.getHomeComputer().programs.push(Programs.NukeProgram);
} }
PlayerObject.prototype.increaseMultiplier = function(name, val) {
let mult = this[name];
if (mult === null || mult === undefined) {
console.log("ERROR: Could not find this multiplier " + name);
return;
}
mult *= val;
}
PlayerObject.prototype.prestigeAugmentation = function() { PlayerObject.prototype.prestigeAugmentation = function() {
var homeComp = this.getHomeComputer(); var homeComp = this.getHomeComputer();
this.currentServer = homeComp.ip; this.currentServer = homeComp.ip;
@ -395,6 +389,12 @@ PlayerObject.prototype.updateSkillLevels = function() {
this.agility = Math.floor(this.calculateSkill(this.agility_exp) * this.agility_mult); this.agility = Math.floor(this.calculateSkill(this.agility_exp) * this.agility_mult);
this.charisma = Math.floor(this.calculateSkill(this.charisma_exp) * this.charisma_mult); this.charisma = Math.floor(this.calculateSkill(this.charisma_exp) * this.charisma_mult);
if (this.intelligence > 0) {
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp));
} else {
this.intelligence = 0;
}
var ratio = this.hp / this.max_hp; var ratio = this.hp / this.max_hp;
this.max_hp = Math.floor(10 + this.defense / 10); this.max_hp = Math.floor(10 + this.defense / 10);
Player.hp = Math.round(this.max_hp * ratio); Player.hp = Math.round(this.max_hp * ratio);
@ -442,7 +442,7 @@ PlayerObject.prototype.resetMultipliers = function() {
// (2 * hacking_chance_multiplier * hacking_skill) 100 // (2 * hacking_chance_multiplier * hacking_skill) 100
PlayerObject.prototype.calculateHackingChance = function() { PlayerObject.prototype.calculateHackingChance = function() {
var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100; var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100;
var skillMult = (1.75 * this.hacking_skill); var skillMult = (1.75 * this.hacking_skill) + (0.2 * this.intelligence);
var skillChance = (skillMult - this.getCurrentServer().requiredHackingSkill) / skillMult; var skillChance = (skillMult - this.getCurrentServer().requiredHackingSkill) / skillMult;
var chance = skillChance * difficultyMult * this.hacking_chance_mult; var chance = skillChance * difficultyMult * this.hacking_chance_mult;
if (chance > 1) {return 1;} if (chance > 1) {return 1;}
@ -457,7 +457,7 @@ PlayerObject.prototype.calculateHackingChance = function() {
// hacking_skill + 100 // hacking_skill + 100
PlayerObject.prototype.calculateHackingTime = function() { PlayerObject.prototype.calculateHackingTime = function() {
var difficultyMult = this.getCurrentServer().requiredHackingSkill * this.getCurrentServer().hackDifficulty; var difficultyMult = this.getCurrentServer().requiredHackingSkill * this.getCurrentServer().hackDifficulty;
var skillFactor = (2.5 * difficultyMult + 200) / (this.hacking_skill + 100); var skillFactor = (2.5 * difficultyMult + 200) / (this.hacking_skill + 100 + (0.1 * this.intelligence));
return 5 * skillFactor / this.hacking_speed_mult; return 5 * skillFactor / this.hacking_speed_mult;
} }
@ -578,7 +578,18 @@ PlayerObject.prototype.gainIntelligenceExp = function(exp) {
if (isNaN(exp)) { if (isNaN(exp)) {
console.log("ERROR: NaN passed into Player.gainIntelligenceExp()"); return; console.log("ERROR: NaN passed into Player.gainIntelligenceExp()"); return;
} }
//TODO var hasBn = false;
for (var i = 0; i < this.sourceFiles.length; ++i) {
if (this.sourceFiles[i].n === 5) {
hasBn = true;
break;
}
}
if (hasBn || this.intelligence > 0) {
this.intelligence_exp += exp;
} else {
console.log("Not gaining intelligence experience bc it hasn't been unlocked yet");
}
} }
/******* Working functions *******/ /******* Working functions *******/
@ -602,6 +613,7 @@ PlayerObject.prototype.resetWorkStatus = function() {
this.workMoneyGained = 0; this.workMoneyGained = 0;
this.timeWorked = 0; this.timeWorked = 0;
this.timeWorkedCreateProgram = 0;
this.currentWorkFactionName = ""; this.currentWorkFactionName = "";
this.currentWorkFactionDescription = ""; this.currentWorkFactionDescription = "";
@ -658,7 +670,8 @@ PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
var mainMenu = document.getElementById("mainmenu-container"); var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible"; mainMenu.style.visibility = "visible";
this.isWorking = false; this.isWorking = false;
Engine.loadTerminalContent(); //Engine.loadTerminalContent();
Engine.loadLocationContent();
if (sing) { if (sing) {
return "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " and " + return "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " and " +
@ -734,7 +747,7 @@ PlayerObject.prototype.work = function(numCycles) {
var txt = document.getElementById("work-in-progress-text"); var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName + txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
" at " + Player.companyName + "<br><br>" + " at " + this.companyName + "<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" + "You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" + "You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" + "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" +
@ -851,7 +864,8 @@ PlayerObject.prototype.finishWorkPartTime = function(sing=false) {
var mainMenu = document.getElementById("mainmenu-container"); var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible"; mainMenu.style.visibility = "visible";
this.isWorking = false; this.isWorking = false;
Engine.loadTerminalContent(); //Engine.loadTerminalContent();
Engine.loadLocationContent();
if (sing) { if (sing) {
return "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + " and " + return "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + " and " +
"earned a total of " + "earned a total of " +
@ -894,7 +908,9 @@ PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
this.isWorking = false; this.isWorking = false;
Engine.loadTerminalContent(); //Engine.loadTerminalContent();
Engine.loadFactionContent();
displayFactionContent(faction.name);
if (sing) { if (sing) {
return "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + ". " + return "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + ". " +
"You earned " + "You earned " +
@ -936,7 +952,7 @@ PlayerObject.prototype.startFactionHackWork = function(faction) {
this.resetWorkStatus(); this.resetWorkStatus();
this.workHackExpGainRate = .15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workHackExpGainRate = .15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workRepGainRate = this.hacking_skill / CONSTANTS.MaxSkillLevel * this.faction_rep_mult; this.workRepGainRate = this.workRepGainRate = (this.hacking_skill + this.intelligence) / CONSTANTS.MaxSkillLevel * this.faction_rep_mult;
this.factionWorkType = CONSTANTS.FactionWorkHacking; this.factionWorkType = CONSTANTS.FactionWorkHacking;
this.currentWorkFactionDescription = "carrying out hacking contracts"; this.currentWorkFactionDescription = "carrying out hacking contracts";
@ -984,7 +1000,7 @@ PlayerObject.prototype.workForFaction = function(numCycles) {
//Constantly update the rep gain rate //Constantly update the rep gain rate
switch (this.factionWorkType) { switch (this.factionWorkType) {
case CONSTANTS.FactionWorkHacking: case CONSTANTS.FactionWorkHacking:
this.workRepGainRate = this.hacking_skill / CONSTANTS.MaxSkillLevel * this.faction_rep_mult; this.workRepGainRate = (this.hacking_skill + this.intelligence) / CONSTANTS.MaxSkillLevel * this.faction_rep_mult;
break; break;
case CONSTANTS.FactionWorkField: case CONSTANTS.FactionWorkField:
this.workRepGainRate = this.getFactionFieldWorkRepGain(); this.workRepGainRate = this.getFactionFieldWorkRepGain();
@ -1103,6 +1119,10 @@ PlayerObject.prototype.getWorkRepGain = function() {
var jobPerformance = this.companyPosition.calculateJobPerformance(this.hacking_skill, this.strength, var jobPerformance = this.companyPosition.calculateJobPerformance(this.hacking_skill, this.strength,
this.defense, this.dexterity, this.defense, this.dexterity,
this.agility, this.charisma); this.agility, this.charisma);
//Intelligence provides a flat bonus to job performance
jobPerformance += (this.intelligence / CONSTANTS.MaxSkillLevel);
//Update reputation gain rate to account for company favor //Update reputation gain rate to account for company favor
var favorMult = 1 + (company.favor / 100); var favorMult = 1 + (company.favor / 100);
if (isNaN(favorMult)) {favorMult = 1;} if (isNaN(favorMult)) {favorMult = 1;}
@ -1124,7 +1144,8 @@ PlayerObject.prototype.getFactionFieldWorkRepGain = function() {
this.defense / CONSTANTS.MaxSkillLevel + this.defense / CONSTANTS.MaxSkillLevel +
this.dexterity / CONSTANTS.MaxSkillLevel + this.dexterity / CONSTANTS.MaxSkillLevel +
this.agility / CONSTANTS.MaxSkillLevel + this.agility / CONSTANTS.MaxSkillLevel +
this.charisma / CONSTANTS.MaxSkillLevel) / 6; this.charisma / CONSTANTS.MaxSkillLevel +
this.intelligence / CONSTANTS.MaxSkillLevel) / 6;
return t * this.faction_rep_mult; return t * this.faction_rep_mult;
} }
@ -1136,21 +1157,22 @@ PlayerObject.prototype.startCreateProgramWork = function(programName, time, reqL
//Time needed to complete work affected by hacking skill (linearly based on //Time needed to complete work affected by hacking skill (linearly based on
//ratio of (your skill - required level) to MAX skill) //ratio of (your skill - required level) to MAX skill)
var timeMultiplier = (CONSTANTS.MaxSkillLevel - (this.hacking_skill - reqLevel)) / CONSTANTS.MaxSkillLevel; //var timeMultiplier = (CONSTANTS.MaxSkillLevel - (this.hacking_skill - reqLevel)) / CONSTANTS.MaxSkillLevel;
if (timeMultiplier > 1) {timeMultiplier = 1;} //if (timeMultiplier > 1) {timeMultiplier = 1;}
if (timeMultiplier < 0.01) {timeMultiplier = 0.01;} //if (timeMultiplier < 0.01) {timeMultiplier = 0.01;}
this.createProgramReqLvl = reqLevel;
this.timeNeededToCompleteWork = timeMultiplier * time; this.timeNeededToCompleteWork = time;
//Check for incomplete program //Check for incomplete program
for (var i = 0; i < Player.getHomeComputer().programs.length; ++i) { for (var i = 0; i < this.getHomeComputer().programs.length; ++i) {
var programFile = Player.getHomeComputer().programs[i]; var programFile = this.getHomeComputer().programs[i];
if (programFile.startsWith(programName) && programFile.endsWith("%-INC")) { if (programFile.startsWith(programName) && programFile.endsWith("%-INC")) {
var res = programFile.split("-"); var res = programFile.split("-");
if (res.length != 3) {break;} if (res.length != 3) {break;}
var percComplete = Number(res[1].slice(0, -1)); var percComplete = Number(res[1].slice(0, -1));
if (isNaN(percComplete) || percComplete < 0 || percComplete >= 100) {break;} if (isNaN(percComplete) || percComplete < 0 || percComplete >= 100) {break;}
this.timeWorked = percComplete / 100 * this.timeNeededToCompleteWork; this.timeWorkedCreateProgram = percComplete / 100 * this.timeNeededToCompleteWork;
Player.getHomeComputer().programs.splice(i, 1); this.getHomeComputer().programs.splice(i, 1);
} }
} }
@ -1168,17 +1190,24 @@ PlayerObject.prototype.startCreateProgramWork = function(programName, time, reqL
} }
PlayerObject.prototype.createProgramWork = function(numCycles) { PlayerObject.prototype.createProgramWork = function(numCycles) {
this.timeWorked += Engine._idleSpeed * numCycles; //Higher hacking skill will allow you to create programs faster
var reqLvl = this.createProgramReqLvl;
var skillMult = (this.hacking_skill / reqLvl); //This should always be greater than 1;
skillMult = 1 + ((skillMult - 1) / 5); //The divider constant can be adjusted as necessary
//Skill multiplier directly applied to "time worked"
this.timeWorked += (Engine._idleSpeed * numCycles);
this.timeWorkedCreateProgram += (Engine._idleSpeed * numCycles * skillMult);
var programName = this.createProgramName; var programName = this.createProgramName;
if (this.timeWorked >= this.timeNeededToCompleteWork) { if (this.timeWorkedCreateProgram >= this.timeNeededToCompleteWork) {
this.finishCreateProgramWork(false); this.finishCreateProgramWork(false);
} }
var txt = document.getElementById("work-in-progress-text"); var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working on coding " + programName + ".<br><br> " + txt.innerHTML = "You are currently working on coding " + programName + ".<br><br> " +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" + "You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"The program is " + (this.timeWorked / this.timeNeededToCompleteWork * 100).toFixed(2) + "% complete. <br>" + "The program is " + (this.timeWorkedCreateProgram / this.timeNeededToCompleteWork * 100).toFixed(2) + "% complete. <br>" +
"If you cancel, your work will be saved and you can come back to complete the program later."; "If you cancel, your work will be saved and you can come back to complete the program later.";
} }
@ -1188,17 +1217,19 @@ PlayerObject.prototype.finishCreateProgramWork = function(cancelled, sing=false)
dialogBoxCreate("You've finished creating " + programName + "!<br>" + dialogBoxCreate("You've finished creating " + programName + "!<br>" +
"The new program can be found on your home computer."); "The new program can be found on your home computer.");
Player.getHomeComputer().programs.push(programName); this.getHomeComputer().programs.push(programName);
} else { } else {
var perc = Math.floor(this.timeWorked / this.timeNeededToCompleteWork * 100).toString(); var perc = Math.floor(this.timeWorkedCreateProgram / this.timeNeededToCompleteWork * 100).toString();
var incompleteName = programName + "-" + perc + "%-INC"; var incompleteName = programName + "-" + perc + "%-INC";
Player.getHomeComputer().programs.push(incompleteName); this.getHomeComputer().programs.push(incompleteName);
} }
this.gainIntelligenceExp(this.createProgramReqLvl / CONSTANTS.IntelligenceProgramBaseExpGain);
var mainMenu = document.getElementById("mainmenu-container"); var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible"; mainMenu.style.visibility = "visible";
Player.isWorking = false; this.isWorking = false;
Engine.loadTerminalContent(); Engine.loadTerminalContent();
} }
@ -1397,16 +1428,16 @@ PlayerObject.prototype.startCrime = function(hackExp, strExp, defExp, dexExp, ag
PlayerObject.prototype.commitCrime = function (numCycles) { PlayerObject.prototype.commitCrime = function (numCycles) {
this.timeWorked += Engine._idleSpeed * numCycles; this.timeWorked += Engine._idleSpeed * numCycles;
if (this.timeWorked >= this.timeNeededToCompleteWork) {Player.finishCrime(false); return;} if (this.timeWorked >= this.timeNeededToCompleteWork) {this.finishCrime(false); return;}
var percent = Math.round(Player.timeWorked / Player.timeNeededToCompleteWork * 100); var percent = Math.round(this.timeWorked / this.timeNeededToCompleteWork * 100);
var numBars = Math.round(percent / 5); var numBars = Math.round(percent / 5);
if (numBars < 0) {numBars = 0;} if (numBars < 0) {numBars = 0;}
if (numBars > 20) {numBars = 20;} if (numBars > 20) {numBars = 20;}
var progressBar = "[" + Array(numBars+1).join("|") + Array(20 - numBars + 1).join(" ") + "]"; var progressBar = "[" + Array(numBars+1).join("|") + Array(20 - numBars + 1).join(" ") + "]";
var txt = document.getElementById("work-in-progress-text"); var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are attempting to " + Player.crimeType + ".<br>" + txt.innerHTML = "You are attempting to " + this.crimeType + ".<br>" +
"Time remaining: " + convertTimeMsToTimeElapsedString(this.timeNeededToCompleteWork - this.timeWorked) + "<br>" + "Time remaining: " + convertTimeMsToTimeElapsedString(this.timeNeededToCompleteWork - this.timeWorked) + "<br>" +
progressBar.replace( / /g, "&nbsp;" ); progressBar.replace( / /g, "&nbsp;" );
} }
@ -1442,6 +1473,7 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
break; break;
case CONSTANTS.CrimeGrandTheftAuto: case CONSTANTS.CrimeGrandTheftAuto:
this.karma -= 5; this.karma -= 5;
this.gainIntelligenceExp(CONSTANTS.IntelligenceCrimeBaseExpGain);
break; break;
case CONSTANTS.CrimeKidnap: case CONSTANTS.CrimeKidnap:
this.karma -= 6; this.karma -= 6;
@ -1449,9 +1481,11 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
case CONSTANTS.CrimeAssassination: case CONSTANTS.CrimeAssassination:
++this.numPeopleKilled; ++this.numPeopleKilled;
this.karma -= 10; this.karma -= 10;
this.gainIntelligenceExp(CONSTANTS.IntelligenceCrimeBaseExpGain);
break; break;
case CONSTANTS.CrimeHeist: case CONSTANTS.CrimeHeist:
this.karma -= 15; this.karma -= 15;
this.gainIntelligenceExp(5 * CONSTANTS.IntelligenceCrimeBaseExpGain);
break; break;
default: default:
console.log(this.crimeType); console.log(this.crimeType);
@ -1542,7 +1576,7 @@ PlayerObject.prototype.hospitalize = function() {
dialogBoxCreate("You were in critical condition! You were taken to the hospital where " + dialogBoxCreate("You were in critical condition! You were taken to the hospital where " +
"luckily they were able to save your life. You were charged $" + "luckily they were able to save your life. You were charged $" +
formatNumber(this.max_hp * CONSTANTS.HospitalCostPerHp, 2)); formatNumber(this.max_hp * CONSTANTS.HospitalCostPerHp, 2));
Player.loseMoney(this.max_hp * CONSTANTS.HospitalCostPerHp); this.loseMoney(this.max_hp * CONSTANTS.HospitalCostPerHp);
this.hp = this.max_hp; this.hp = this.max_hp;
} }
@ -1626,8 +1660,8 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
this.companyName = company.companyName; this.companyName = company.companyName;
this.companyPosition = pos; this.companyPosition = pos;
if (Player.firstJobRecvd === false) { if (this.firstJobRecvd === false) {
Player.firstJobRecvd = true; this.firstJobRecvd = true;
document.getElementById("job-tab").style.display = "list-item"; document.getElementById("job-tab").style.display = "list-item";
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
@ -1735,8 +1769,8 @@ PlayerObject.prototype.applyForAgentJob = function(sing=false) {
PlayerObject.prototype.applyForEmployeeJob = function(sing=false) { PlayerObject.prototype.applyForEmployeeJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.Employee)) { if (this.isQualified(company, CompanyPositions.Employee)) {
if (Player.firstJobRecvd === false) { if (this.firstJobRecvd === false) {
Player.firstJobRecvd = true; this.firstJobRecvd = true;
document.getElementById("job-tab").style.display = "list-item"; document.getElementById("job-tab").style.display = "list-item";
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
@ -1755,8 +1789,8 @@ PlayerObject.prototype.applyForEmployeeJob = function(sing=false) {
PlayerObject.prototype.applyForPartTimeEmployeeJob = function(sing=false) { PlayerObject.prototype.applyForPartTimeEmployeeJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.PartTimeEmployee)) { if (this.isQualified(company, CompanyPositions.PartTimeEmployee)) {
if (Player.firstJobRecvd === false) { if (this.firstJobRecvd === false) {
Player.firstJobRecvd = true; this.firstJobRecvd = true;
document.getElementById("job-tab").style.display = "list-item"; document.getElementById("job-tab").style.display = "list-item";
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
@ -1775,8 +1809,8 @@ PlayerObject.prototype.applyForPartTimeEmployeeJob = function(sing=false) {
PlayerObject.prototype.applyForWaiterJob = function(sing=false) { PlayerObject.prototype.applyForWaiterJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.Waiter)) { if (this.isQualified(company, CompanyPositions.Waiter)) {
if (Player.firstJobRecvd === false) { if (this.firstJobRecvd === false) {
Player.firstJobRecvd = true; this.firstJobRecvd = true;
document.getElementById("job-tab").style.display = "list-item"; document.getElementById("job-tab").style.display = "list-item";
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
@ -1795,8 +1829,8 @@ PlayerObject.prototype.applyForWaiterJob = function(sing=false) {
PlayerObject.prototype.applyForPartTimeWaiterJob = function(sing=false) { PlayerObject.prototype.applyForPartTimeWaiterJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.PartTimeWaiter)) { if (this.isQualified(company, CompanyPositions.PartTimeWaiter)) {
if (Player.firstJobRecvd === false) { if (this.firstJobRecvd === false) {
Player.firstJobRecvd = true; this.firstJobRecvd = true;
document.getElementById("job-tab").style.display = "list-item"; document.getElementById("job-tab").style.display = "list-item";
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
@ -2149,10 +2183,10 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var totalHacknetRam = 0; var totalHacknetRam = 0;
var totalHacknetCores = 0; var totalHacknetCores = 0;
var totalHacknetLevels = 0; var totalHacknetLevels = 0;
for (var i = 0; i < Player.hacknetNodes.length; ++i) { for (var i = 0; i < this.hacknetNodes.length; ++i) {
totalHacknetLevels += Player.hacknetNodes[i].level; totalHacknetLevels += this.hacknetNodes[i].level;
totalHacknetRam += Player.hacknetNodes[i].ram; totalHacknetRam += this.hacknetNodes[i].ram;
totalHacknetCores += Player.hacknetNodes[i].cores; totalHacknetCores += this.hacknetNodes[i].cores;
} }
if (!netburnersFac.isBanned && !netburnersFac.isMember && !netburnersFac.alreadyInvited && if (!netburnersFac.isBanned && !netburnersFac.isMember && !netburnersFac.alreadyInvited &&
this.hacking_skill >= 80 && totalHacknetRam >= 8 && this.hacking_skill >= 80 && totalHacknetRam >= 8 &&

@ -218,6 +218,9 @@ function prestigeSourceFile() {
mainMenu.style.visibility = "visible"; mainMenu.style.visibility = "visible";
Terminal.resetTerminalInput(); Terminal.resetTerminalInput();
Engine.loadTerminalContent(); Engine.loadTerminalContent();
//Gain int exp
Player.gainIntelligenceExp(5);
} }
export {prestigeAugmentation, prestigeSourceFile}; export {prestigeAugmentation, prestigeSourceFile};

@ -232,7 +232,8 @@ function calculateRamUsage(codeCopy) {
numOccurrences(codeCopy, "getServerGrowth(") + numOccurrences(codeCopy, "getServerGrowth(") +
numOccurrences(codeCopy, "getServerRequiredHackingLevel(") + numOccurrences(codeCopy, "getServerRequiredHackingLevel(") +
numOccurrences(codeCopy, "getServerNumPortsRequired(") + numOccurrences(codeCopy, "getServerNumPortsRequired(") +
numOccurrences(codeCopy, "getServerRam("); numOccurrences(codeCopy, "getServerRam(") +
numOccurrences(codeCopy, "serverExists(");
var fileExistsCount = numOccurrences(codeCopy, "fileExists("); var fileExistsCount = numOccurrences(codeCopy, "fileExists(");
var isRunningCount = numOccurrences(codeCopy, "isRunning("); var isRunningCount = numOccurrences(codeCopy, "isRunning(");
var purchaseHacknetCount = numOccurrences(codeCopy, "purchaseHacknetNode("); var purchaseHacknetCount = numOccurrences(codeCopy, "purchaseHacknetNode(");
@ -251,7 +252,9 @@ function calculateRamUsage(codeCopy) {
var scriptReadCount = numOccurrences(codeCopy, "read("); var scriptReadCount = numOccurrences(codeCopy, "read(");
var arbScriptCount = numOccurrences(codeCopy, "scriptRunning(") + var arbScriptCount = numOccurrences(codeCopy, "scriptRunning(") +
numOccurrences(codeCopy, "scriptKill("); numOccurrences(codeCopy, "scriptKill(");
var getScriptCount = numOccurrences(codeCopy, "getScriptRam("); var getScriptCount = numOccurrences(codeCopy, "getScriptRam(") +
numOccurrences(codeCopy, "getScriptIncome(") +
numOccurrences(codeCopy, "getScriptExpGain(");
var getHackTimeCount = numOccurrences(codeCopy, "getHackTime(") + var getHackTimeCount = numOccurrences(codeCopy, "getHackTime(") +
numOccurrences(codeCopy, "getGrowTime(") + numOccurrences(codeCopy, "getGrowTime(") +
numOccurrences(codeCopy, "getWeakenTime("); numOccurrences(codeCopy, "getWeakenTime(");

@ -669,13 +669,14 @@ function processSingleServerGrowth(server, numCycles) {
serverGrowth = 1; serverGrowth = 1;
} }
var oldMoneyAvailable = server.moneyAvailable;
server.moneyAvailable *= serverGrowth; server.moneyAvailable *= serverGrowth;
if (server.moneyMax && isNaN(server.moneyAvailable)) { if (server.moneyMax && isNaN(server.moneyAvailable)) {
server.moneyAvailable = server.moneyMax; server.moneyAvailable = server.moneyMax;
} }
if (server.moneyMax && server.moneyAvailable > server.moneyMax) { if (server.moneyMax && server.moneyAvailable > server.moneyMax) {
server.moneyAvailable = server.moneyMax; server.moneyAvailable = server.moneyMax;
return 1; return server.moneyAvailable / oldMoneyAvailable;
} }
//Growing increases server security twice as much as hacking //Growing increases server security twice as much as hacking

@ -29,13 +29,13 @@ import {addOffset, printArray} from "../utils/HelperFunctions.js";
import {logBoxCreate} from "../utils/LogBox.js"; import {logBoxCreate} from "../utils/LogBox.js";
/* Write text to terminal */ /* Write text to terminal */
//If replace is true then spaces are replaced with "&nbsp;"
function post(input, replace=true) { function post(input, replace=true) {
if (replace) { if (replace) {
$("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input.replace( / /g, "&nbsp;" ) + '</td></tr>'); $("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input.replace( / /g, "&nbsp;" ) + '</td></tr>');
} else { } else {
$("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>'); $("#terminal-input").before('<tr class="posted"><td class="terminal-line" style="color: var(--my-font-color); background-color: var(--my-background-color);">' + input + '</td></tr>');
} }
updateTerminalScroll(); updateTerminalScroll();
} }
@ -441,13 +441,12 @@ let Terminal = {
var moneyGained = Player.calculatePercentMoneyHacked(); var moneyGained = Player.calculatePercentMoneyHacked();
moneyGained = Math.floor(server.moneyAvailable * moneyGained); moneyGained = Math.floor(server.moneyAvailable * moneyGained);
//Safety check if (moneyGained <= 0) {moneyGained = 0;} //Safety check
if (moneyGained <= 0) {moneyGained = 0;}
server.moneyAvailable -= moneyGained; server.moneyAvailable -= moneyGained;
Player.gainMoney(moneyGained); Player.gainMoney(moneyGained);
Player.gainHackingExp(expGainedOnSuccess) Player.gainHackingExp(expGainedOnSuccess)
Player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain);
server.fortify(CONSTANTS.ServerFortifyAmount); server.fortify(CONSTANTS.ServerFortifyAmount);
@ -1418,6 +1417,7 @@ let Terminal = {
(function() { (function() {
var hostname = links[i].innerHTML.toString(); var hostname = links[i].innerHTML.toString();
links[i].onclick = function() { links[i].onclick = function() {
if (Terminal.analyzeFlag || Terminal.hackFlag) {return;}
Terminal.connectToServer(hostname); Terminal.connectToServer(hostname);
} }
}());//Immediate invocation }());//Immediate invocation

@ -47,7 +47,7 @@ function infiltrationBoxCreate(inst) {
formatNumber(inst.chaExpGained, 3) + " cha exp<br>"); formatNumber(inst.chaExpGained, 3) + " cha exp<br>");
return; return;
} }
var facValue = totalValue * Player.faction_rep_mult * 1.2 var facValue = totalValue * Player.faction_rep_mult * 1.25
var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue; var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue;
infiltrationSetText("You can sell the classified documents and secrets " + infiltrationSetText("You can sell the classified documents and secrets " +
"you stole from " + inst.companyName + " for $" + "you stole from " + inst.companyName + " for $" +

@ -129,6 +129,16 @@ function numNetscriptOperators(string) {
return total; return total;
} }
//Checks if a string contains HTML elements
function isHTML(str) {
var a = document.createElement('div');
a.innerHTML = str;
for (var c = a.childNodes, i = c.length; i--; ) {
if (c[i].nodeType == 1) return true;
}
return false;
}
export {getIndicesOf, convertTimeMsToTimeElapsedString, longestCommonStart, export {getIndicesOf, convertTimeMsToTimeElapsedString, longestCommonStart,
isString, isPositiveNumber, containsAllStrings, formatNumber, isString, isPositiveNumber, containsAllStrings, formatNumber,
numOccurrences, numNetscriptOperators}; numOccurrences, numNetscriptOperators, isHTML};