Game now uses indexedDb. Added new Bond Forgery crime. Added commitCrime() and getStats() Singularity functions. Removed getIntelligence(). Balance changes to crime/infiltration

This commit is contained in:
danielyxie 2017-10-11 21:00:22 -05:00
parent 4d4542f349
commit 246acf5966
18 changed files with 2432 additions and 1685 deletions

3493
dist/bundle.js vendored

File diff suppressed because it is too large Load Diff

@ -733,8 +733,9 @@
<a id="location-slums-mug" class="a-link-button tooltip"> Mug someone </a> <a id="location-slums-mug" class="a-link-button tooltip"> Mug someone </a>
<a id="location-slums-larceny" class="a-link-button tooltip"> Commit Larceny </a> <a id="location-slums-larceny" class="a-link-button tooltip"> Commit Larceny </a>
<a id="location-slums-deal-drugs" class="a-link-button tooltip"> Deal Drugs </a> <a id="location-slums-deal-drugs" class="a-link-button tooltip"> Deal Drugs </a>
<a id="location-slums-traffic-arms" class="a-link-button tooltip"> Traffick Illegal Arms </a> <a id="location-slums-bond-forgery" class="a-link-button tooltip">Bond Forgery</a>
<a id="location-slums-homicide" class="a-link-button tooltip"> Homicide </a> <a id="location-slums-traffic-arms" class="a-link-button tooltip">Traffick Illegal Arms</a>
<a id="location-slums-homicide" class="a-link-button tooltip">Homicide</a>
<a id="location-slums-gta" class="a-link-button tooltip"> Grand Theft Auto </a> <a id="location-slums-gta" class="a-link-button tooltip"> Grand Theft Auto </a>
<a id="location-slums-kidnap" class="a-link-button tooltip"> Kidnap and Ransom </a> <a id="location-slums-kidnap" class="a-link-button tooltip"> Kidnap and Ransom </a>
<a id="location-slums-assassinate" class="a-link-button tooltip"> Assassinate </a> <a id="location-slums-assassinate" class="a-link-button tooltip"> Assassinate </a>

@ -28,7 +28,7 @@ function initBitNodes() {
"people quickly succumbed to the innate human impulse of evil and savagery. The organized crime " + "people quickly succumbed to the innate human impulse of evil and savagery. The organized crime " +
"factions quickly rose to the top of the modern world.<br><br>" + "factions quickly rose to the top of the modern world.<br><br>" +
"In this BitNode:<br><br>The maximum amount of money available on a server is significantly decreased<br>" + "In this BitNode:<br><br>The maximum amount of money available on a server is significantly decreased<br>" +
"The amount of money gained from crimes is doubled<br>" + "The amount of money gained from crimes and Infiltration is doubled<br>" +
"Certain Factions (Slum Snakes, Tetrads, The Syndicate, The Dark Army, Speakers for the Dead, " + "Certain Factions (Slum Snakes, Tetrads, The Syndicate, The Dark Army, Speakers for the Dead, " +
"NiteSec, The Black Hand) give the player the ability to form and manage their own gangs. These gangs " + "NiteSec, The Black Hand) give the player the ability to form and manage their own gangs. These gangs " +
"will earn the player money and reputation with the corresponding Faction<br>" + "will earn the player money and reputation with the corresponding Faction<br>" +
@ -92,6 +92,7 @@ function initBitNodes() {
"Weakening a server is twice as effective<br>" + "Weakening a server is twice as effective<br>" +
"Company wages are decreased by 50%<br>" + "Company wages are decreased by 50%<br>" +
"Hacknet Node production is significantly decreased<br>" + "Hacknet Node production is significantly decreased<br>" +
"Crime and Infiltration are more lucrative<br>" +
"Augmentations are twice as expensive<br><br>" + "Augmentations are twice as expensive<br><br>" +
"Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will " + "Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will " +
"upgrade its level up to a maximum of 3. This Source-File makes it so that company favor increases BOTH " + "upgrade its level up to a maximum of 3. This Source-File makes it so that company favor increases BOTH " +
@ -149,6 +150,9 @@ let BitNodeMultipliers = {
AugmentationRepCost: 1, AugmentationRepCost: 1,
AugmentationMoneyCost: 1, AugmentationMoneyCost: 1,
InfiltrationMoney: 1,
InfiltrationRep: 1,
} }
function initBitNodeMultipliers() { function initBitNodeMultipliers() {
@ -167,6 +171,7 @@ function initBitNodeMultipliers() {
case 2: //Rise of the Underworld case 2: //Rise of the Underworld
BitNodeMultipliers.ServerMaxMoney = 0.2; BitNodeMultipliers.ServerMaxMoney = 0.2;
BitNodeMultipliers.CrimeMoney = 2; BitNodeMultipliers.CrimeMoney = 2;
BitNodeMultipliers.InfiltrationMoney = 2;
BitNodeMultipliers.FactionWorkRepGain = 0.5; BitNodeMultipliers.FactionWorkRepGain = 0.5;
BitNodeMultipliers.FactionPassiveRepGain = 0; BitNodeMultipliers.FactionPassiveRepGain = 0;
break; break;
@ -198,9 +203,12 @@ function initBitNodeMultipliers() {
BitNodeMultipliers.ServerStartingMoney = 0.1; BitNodeMultipliers.ServerStartingMoney = 0.1;
BitNodeMultipliers.ServerGrowthRate = 0.5; BitNodeMultipliers.ServerGrowthRate = 0.5;
BitNodeMultipliers.ServerWeakenRate = 2; BitNodeMultipliers.ServerWeakenRate = 2;
BitNodeMultipliers.CrimeMoney = 3;
BitNodeMultipliers.CompanyWorkMoney = 0.5; BitNodeMultipliers.CompanyWorkMoney = 0.5;
BitNodeMultipliers.HacknetNodeMoney = 0.1; BitNodeMultipliers.HacknetNodeMoney = 0.1;
BitNodeMultipliers.AugmentationMoneyCost = 2; BitNodeMultipliers.AugmentationMoneyCost = 2;
BitNodeMultipliers.InfiltrationMoney = 2.5;
BitNodeMultipliers.InfiltrationRep = 2.5;
break; break;
default: default:
console.log("WARNING: Player.bitNodeN invalid"); console.log("WARNING: Player.bitNodeN invalid");

@ -58,7 +58,7 @@ let CONSTANTS = {
ScriptKillRamCost: 0.5, //Kill and killall ScriptKillRamCost: 0.5, //Kill and killall
ScriptHasRootAccessRamCost: 0.05, ScriptHasRootAccessRamCost: 0.05,
ScriptGetHostnameRamCost: 0.05, //getHostname() and getIp() ScriptGetHostnameRamCost: 0.05, //getHostname() and getIp()
ScriptGetHackingLevelRamCost: 0.05, //getHackingLevel() and getIntelligence() ScriptGetHackingLevelRamCost: 0.05, //getHackingLevel()
ScriptGetMultipliersRamCost: 4.0, //getHackingMultipliers() and getBitNodeMultipliers() ScriptGetMultipliersRamCost: 4.0, //getHackingMultipliers() and getBitNodeMultipliers()
ScriptGetServerCost: 0.1, ScriptGetServerCost: 0.1,
ScriptFileExistsRamCost: 0.1, ScriptFileExistsRamCost: 0.1,
@ -101,8 +101,9 @@ let CONSTANTS = {
TorRouterCost: 200000, TorRouterCost: 200000,
//Infiltration constants //Infiltration constants
InfiltrationBribeBaseAmount: 100000, //Amount per clearance level InfiltrationBribeBaseAmount: 100000, //Amount per clearance level
InfiltrationMoneyValue: 2000, //Convert "secret" value to money InfiltrationMoneyValue: 2500, //Convert "secret" value to money
InfiltrationRepValue: 1.4, //Convert "secret" value to faction reputation
//Stock market constants //Stock market constants
WSEAccountCost: 200000000, WSEAccountCost: 200000000,
@ -238,11 +239,13 @@ let CONSTANTS = {
ClassLeadershipBaseCost: 320, ClassLeadershipBaseCost: 320,
ClassGymBaseCost: 120, ClassGymBaseCost: 120,
CrimeSingFnDivider: 2, //Factor by which exp/profit is reduced when commiting crime through Sing Fn
CrimeShoplift: "shoplift", CrimeShoplift: "shoplift",
CrimeRobStore: "rob a store", CrimeRobStore: "rob a store",
CrimeMug: "mug someone", CrimeMug: "mug someone",
CrimeLarceny: "commit larceny", CrimeLarceny: "commit larceny",
CrimeDrugs: "deal drugs", CrimeDrugs: "deal drugs",
CrimeBondForgery: "forge corporate bonds",
CrimeTraffickArms: "traffick illegal arms", CrimeTraffickArms: "traffick illegal arms",
CrimeHomicide: "commit homicide", CrimeHomicide: "commit homicide",
CrimeGrandTheftAuto: "commit grand theft auto", CrimeGrandTheftAuto: "commit grand theft auto",
@ -539,7 +542,6 @@ let CONSTANTS = {
"<i>getIp()</i><br>Returns a string with the IP Address of the server that the script is running on <br><br>" + "<i>getIp()</i><br>Returns a string with the IP Address of the server that the script is running on <br><br>" +
"<i>getHostname()</i><br>Returns a string with the hostname of the server that the script is running on<br><br>" + "<i>getHostname()</i><br>Returns a string with the hostname of the server that the script is running on<br><br>" +
"<i>getHackingLevel()</i><br>Returns the Player's current hacking level.<br><br> " + "<i>getHackingLevel()</i><br>Returns the Player's current hacking level.<br><br> " +
"<i>getIntelligence()</i><br>Returns the Player's current intelligence level. Requires Source-File 5 to run<br><br>" +
"<i>getHackingMultipliers()</i><br>Returns an object containing the Player's hacking related multipliers. " + "<i>getHackingMultipliers()</i><br>Returns an object containing the Player's hacking related multipliers. " +
"These multipliers are returned in integer forms, not percentages (e.g. 1.5 instead of 150%). " + "These multipliers are returned in integer forms, not percentages (e.g. 1.5 instead of 150%). " +
"The object has the following structure:<br><br>" + "The object has the following structure:<br><br>" +
@ -844,6 +846,11 @@ let CONSTANTS = {
"The cost of purchasing programs using this function is the same as if you were purchasing them through the Dark Web (using " + "The cost of purchasing programs using this function is the same as if you were purchasing them through the Dark Web (using " +
"the buy Terminal command).<br><br>" + "the buy Terminal command).<br><br>" +
"This function will return true if the specified program is purchased, and false otherwise.<br><br>" + "This function will return true if the specified program is purchased, and false otherwise.<br><br>" +
"<i>getStats()</i><br>If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to run this " +
"function.<br><br>Returns an object with the Player's stats. The object has the following properties:<br><br>" +
"Player.hacking<br>Player.strength<br>Player.defense<br>Player.dexterity<br>Player.agility<br>Player.charisma<br>Player.intelligence<br><br>" +
"Example: <br><br>" +
"res = getStats();<br>print('My charisma level is: ' + res.charisma);<br><br>" +
"<i>upgradeHomeRam()</i><br>" + "<i>upgradeHomeRam()</i><br>" +
"If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" + "If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.<br><br>" +
"This function will upgrade amount of RAM on the player's home computer. The cost is the same as if you were to do it manually.<br><br>" + "This function will upgrade amount of RAM on the player's home computer. The cost is the same as if you were to do it manually.<br><br>" +
@ -905,6 +912,16 @@ let CONSTANTS = {
"BruteSSH.exe: 50<br>FTPCrack.exe: 100<br>relaySMTP.exe: 250<br>HTTPWorm.exe: 500<br>SQLInject.exe: 750<br>" + "BruteSSH.exe: 50<br>FTPCrack.exe: 100<br>relaySMTP.exe: 250<br>HTTPWorm.exe: 500<br>SQLInject.exe: 750<br>" +
"DeepscanV1.exe: 75<br>DeepscanV2.exe: 400<br>ServerProfiler.exe: 75<br>AutoLink.exe: 25<br><br>" + "DeepscanV1.exe: 75<br>DeepscanV2.exe: 400<br>ServerProfiler.exe: 75<br>AutoLink.exe: 25<br><br>" +
"This function returns true if you successfully start working on the specified program, and false otherwise.<br><br>" + "This function returns true if you successfully start working on the specified program, and false otherwise.<br><br>" +
"<i>getOwnedAugmentations(purchased=false)</i><br>" +
"If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" +
"This function returns an array of the names of all Augmentations you own as strings. It takes a single optional " +
"boolean argument that specifies whether the returned array should include Augmentations you have purchased " +
"but not yet installed. If it is true, then the returned array will include these Augmentations. By default, " +
"this argument is false.<br><br>" +
"<i>getAugmentationsFromFaction(facName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" +
"Returns an array containing the names (as strings) of all Augmentations that are available from the specified faction. " +
"The argument must be a string with the faction's name. This argument is case-sensitive.<br><br>" +
"<i>getAugmentationCost(augName)</i><br>" + "<i>getAugmentationCost(augName)</i><br>" +
"If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" + "If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.<br><br>" +
"This function returns an array with two elements that gives the cost for the specified Augmentation" + "This function returns an array with two elements that gives the cost for the specified Augmentation" +
@ -1024,24 +1041,17 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.30.0<br>" + "v0.31.0<br>" +
"-Added getAugmentations() and getAugmentationsFromFaction() Netscript Singularity Functions<br>" + "-Game now saves to IndexedDb (if your browser supports it). This means you should " +
"-Increased the rate of Intelligence exp gain<br>" + "no longer have trouble saving the game when your save file gets too big (from running " +
"-Added a new upgrade for home computers: CPU Cores. Each CPU core on the home computer " + "too many scripts). " +
"grants an additional starting Core Node in Hacking Missions. I may add in other benefits later. Like RAM upgrades, upgrading " + "The game will still be saved to localStorage as well<br>" +
"the CPU Core on your home computer persists until you enter a new BitNode.<br>" + "-Added a new Crime: Bond Forgery. This crime takes 5 minutes to attempt " +
"-Added lscpu Terminal command to check number of CPU Cores<br>" + "and gives $4,500,000 if successful. It is meant for mid game.<br>" +
"-Changed the effect of Source-File 5 and made BitNode-5 a little bit harder<br>" + "-Added commitCrime() Singularity Function.<br>" +
"-Fixed a bug with Netscript functions (the ones you create yourself)<br>" + "-Increased the amount of money gained from infiltration by 20%, and the amount of faction reputation by 12%<br>" +
"-Hacking Missions officially released (they give reputation now). Notable changes in the last few updates:<br><br>" + "-Crime and Infiltration are now more lucrative in BitNodes 11 and 2<br>" +
"---Misc Nodes slowly gain hp/defense over time<br>" + "-Added getStats() Singularity function. Removed getIntelligence() Netscript function.<br>",
"---Conquering a Misc Node will increase the defense of all remaining Misc Nodes that are not being targeted by a certain percentage<br>" +
"---Reputation reward for winning a Mission is now affected by faction favor and Player's faction rep multiplier<br>" +
"---Whenever a Node is conquered, its stats are reduced<br><br>" +
"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 and Hacking Missions<br><br>"
} }
export {CONSTANTS}; export {CONSTANTS};

@ -3,59 +3,76 @@ import {Player} from "./Player.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
/* Crimes.js */ /* Crimes.js */
function commitShopliftCrime() { function commitShopliftCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeShoplift; Player.crimeType = CONSTANTS.CrimeShoplift;
Player.startCrime(0, 0, 0, 2, 2, 0, 15000, 2000); //$7500/s, 1 exp/s Player.startCrime(0, 0, 0, 2/div, 2/div, 0, 15000/div, 2000, singParams); //$7500/s, 1 exp/s
} }
function commitRobStoreCrime() { function commitRobStoreCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeRobStore; Player.crimeType = CONSTANTS.CrimeRobStore;
Player.startCrime(30, 0, 0, 45, 45, 0, 400000, 60000); //$6666,6/2, 0.5exp/s, 0.75exp/s Player.startCrime(30/div, 0, 0, 45/div, 45/div, 0, 400000/div, 60000, singParams); //$6666,6/2, 0.5exp/s, 0.75exp/s
} }
function commitMugCrime() { function commitMugCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeMug; Player.crimeType = CONSTANTS.CrimeMug;
Player.startCrime(0, 3, 3, 3, 3, 0, 36000, 4000); //$9000/s, .66 exp/s Player.startCrime(0, 3/div, 3/div, 3/div, 3/div, 0, 36000/div, 4000, singParams); //$9000/s, .66 exp/s
} }
function commitLarcenyCrime() { function commitLarcenyCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeLarceny; Player.crimeType = CONSTANTS.CrimeLarceny;
Player.startCrime(45, 0, 0, 60, 60, 0, 800000, 90000) // $8888.88/s, .5 exp/s, .66 exp/s Player.startCrime(45/div, 0, 0, 60/div, 60/div, 0, 800000/div, 90000, singParams) // $8888.88/s, .5 exp/s, .66 exp/s
} }
function commitDealDrugsCrime() { function commitDealDrugsCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeDrugs; Player.crimeType = CONSTANTS.CrimeDrugs;
Player.startCrime(0, 0, 0, 5, 5, 10, 120000, 10000); //$12000/s, .5 exp/s, 1 exp/s Player.startCrime(0, 0, 0, 5/div, 5/div, 10/div, 120000/div, 10000, singParams); //$12000/s, .5 exp/s, 1 exp/s
} }
function commitTraffickArmsCrime() { function commitBondForgeryCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeBondForgery;
Player.startCrime(100/div, 0, 0, 150/div, 0, 15/div, 4500000/div, 300000, singParams); //$15000/s, 0.33 hack exp/s, .5 dex exp/s, .05 cha exp
}
function commitTraffickArmsCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeTraffickArms; Player.crimeType = CONSTANTS.CrimeTraffickArms;
Player.startCrime(0, 20, 20, 20, 20, 40, 600000, 40000); //$15000/s, .5 combat exp/s, 1 cha exp/s Player.startCrime(0, 20/div, 20/div, 20/div, 20/div, 40/div, 600000/div, 40000, singParams); //$15000/s, .5 combat exp/s, 1 cha exp/s
} }
function commitHomicideCrime() { function commitHomicideCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeHomicide; Player.crimeType = CONSTANTS.CrimeHomicide;
Player.startCrime(0, 2, 2, 2, 2, 0, 45000, 3000); //$15000/s, 0.66 combat exp/s Player.startCrime(0, 2/div, 2/div, 2/div, 2/div, 0, 45000/div, 3000, singParams); //$15000/s, 0.66 combat exp/s
} }
function commitGrandTheftAutoCrime() { function commitGrandTheftAutoCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeGrandTheftAuto; Player.crimeType = CONSTANTS.CrimeGrandTheftAuto;
Player.startCrime(0, 20, 20, 20, 80, 40, 1600000, 80000); //$20000/s, .25 exp/s, 1 exp/s, .5 exp/s Player.startCrime(0, 20/div, 20/div, 20/div, 80/div, 40/div, 1600000/div, 80000, singParams); //$20000/s, .25 exp/s, 1 exp/s, .5 exp/s
} }
function commitKidnapCrime() { function commitKidnapCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeKidnap; Player.crimeType = CONSTANTS.CrimeKidnap;
Player.startCrime(0, 80, 80, 80, 80, 80, 3600000, 120000); //$30000/s. .66 exp/s Player.startCrime(0, 80/div, 80/div, 80/div, 80/div, 80/div, 3600000/div, 120000, singParams); //$30000/s. .66 exp/s
} }
function commitAssassinationCrime() { function commitAssassinationCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeAssassination; Player.crimeType = CONSTANTS.CrimeAssassination;
Player.startCrime(0, 300, 300, 300, 300, 0, 12000000, 300000); //$40000/s, 1 exp/s Player.startCrime(0, 300/div, 300/div, 300/div, 300/div, 0, 12000000/div, 300000, singParams); //$40000/s, 1 exp/s
} }
function commitHeistCrime() { function commitHeistCrime(div=1, singParams=null) {
if (div <= 0) {div = 1;}
Player.crimeType = CONSTANTS.CrimeHeist; Player.crimeType = CONSTANTS.CrimeHeist;
Player.startCrime(450, 450, 450, 450, 450, 450, 120000000, 600000); //$200000/s, .75exp/s Player.startCrime(450/div, 450/div, 450/div, 450/div, 450/div, 450/div, 120000000/div, 600000, singParams); //$200000/s, .75exp/s
} }
function determineCrimeSuccess(crime, moneyGained) { function determineCrimeSuccess(crime, moneyGained) {
@ -76,6 +93,9 @@ function determineCrimeSuccess(crime, moneyGained) {
case CONSTANTS.CrimeDrugs: case CONSTANTS.CrimeDrugs:
chance = determineCrimeChanceDealDrugs(); chance = determineCrimeChanceDealDrugs();
break; break;
case CONSTANTS.CrimeBondForgery:
chance = determineCrimeChanceBondForgery();
break;
case CONSTANTS.CrimeTraffickArms: case CONSTANTS.CrimeTraffickArms:
chance = determineCrimeChanceTraffickArms(); chance = determineCrimeChanceTraffickArms();
break; break;
@ -158,6 +178,14 @@ function determineCrimeChanceDealDrugs() {
return Math.min(chance, 1); return Math.min(chance, 1);
} }
function determineCrimeChanceBondForgery() {
var chance = (0.1*Player.hacking_skill / maxLvl +
2.5*Player.dexterity / maxLvl +
2*intWgt*Player.intelligence / maxLvl);
chance *= Player.crime_success_mult;
return Math.min(chance, 1);
}
function determineCrimeChanceTraffickArms() { function determineCrimeChanceTraffickArms() {
var chance = (Player.charisma / maxLvl + var chance = (Player.charisma / maxLvl +
Player.strength / maxLvl + Player.strength / maxLvl +
@ -222,12 +250,14 @@ function determineCrimeChanceHeist() {
} }
export {commitShopliftCrime, commitRobStoreCrime, commitMugCrime, export {commitShopliftCrime, commitRobStoreCrime, commitMugCrime,
commitLarcenyCrime, commitDealDrugsCrime, commitTraffickArmsCrime, commitLarcenyCrime, commitDealDrugsCrime, commitBondForgeryCrime,
commitTraffickArmsCrime,
commitHomicideCrime, commitGrandTheftAutoCrime, commitKidnapCrime, commitHomicideCrime, commitGrandTheftAutoCrime, commitKidnapCrime,
commitAssassinationCrime, commitHeistCrime, determineCrimeSuccess, commitAssassinationCrime, commitHeistCrime, determineCrimeSuccess,
determineCrimeChanceShoplift, determineCrimeChanceRobStore, determineCrimeChanceShoplift, determineCrimeChanceRobStore,
determineCrimeChanceMug, determineCrimeChanceLarceny, determineCrimeChanceMug, determineCrimeChanceLarceny,
determineCrimeChanceDealDrugs, determineCrimeChanceTraffickArms, determineCrimeChanceDealDrugs, determineCrimeChanceBondForgery,
determineCrimeChanceTraffickArms,
determineCrimeChanceHomicide, determineCrimeChanceGrandTheftAuto, determineCrimeChanceHomicide, determineCrimeChanceGrandTheftAuto,
determineCrimeChanceKidnap, determineCrimeChanceAssassination, determineCrimeChanceKidnap, determineCrimeChanceAssassination,
determineCrimeChanceHeist}; determineCrimeChanceHeist};

@ -9,6 +9,7 @@ let TerminalHelpText =
"clear Clear all text on the terminal <br>" + "clear Clear all text on the terminal <br>" +
"cls See 'clear' command <br>" + "cls See 'clear' command <br>" +
"connect [ip/hostname] Connects to a remote server<br>" + "connect [ip/hostname] Connects to a remote server<br>" +
"download [text file] Downloads a text (.txt) file to your computer<br>" +
"free Check the machine's memory (RAM) usage<br>" + "free Check the machine's memory (RAM) usage<br>" +
"hack Hack the current machine<br>" + "hack Hack the current machine<br>" +
"help [command] Display this help text, or the help text for a command<br>" + "help [command] Display this help text, or the help text for a command<br>" +
@ -85,6 +86,9 @@ let HelpTexts = {
"Connect to a remote server. The hostname or IP address of the remote server must be given as the argument " + "Connect to a remote server. The hostname or IP address of the remote server must be given as the argument " +
"to this command. Note that only servers that are immediately adjacent to the current server in the network can be connected to. To " + "to this command. Note that only servers that are immediately adjacent to the current server in the network can be connected to. To " +
"see which servers can be connected to, use the 'scan' command.", "see which servers can be connected to, use the 'scan' command.",
download: "download [text file]<br>" +
"Downloads a text file to your computer (like your real life computer). Only works on text files, " +
"which are the ones with a .txt extension.",
free: "free<br>" + free: "free<br>" +
"Display's the memory usage on the current machine. Print the amount of RAM that is available on the current server as well as " + "Display's the memory usage on the current machine. Print the amount of RAM that is available on the current server as well as " +
"how much of it is being used.", "how much of it is being used.",

@ -1,3 +1,4 @@
import {BitNodeMultipliers} from "./BitNode.js";
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
import {Player} from "./Player.js"; import {Player} from "./Player.js";
@ -405,8 +406,10 @@ function endInfiltrationLevel(inst) {
//Check if you gained any secrets //Check if you gained any secrets
if (inst.clearanceLevel % 5 == 0) { if (inst.clearanceLevel % 5 == 0) {
var baseSecretValue = inst.baseValue * inst.clearanceLevel / 2; var baseSecretValue = inst.baseValue * inst.clearanceLevel / 2;
var secretValue = baseSecretValue * Player.faction_rep_mult * 1.25; var secretValue = baseSecretValue * Player.faction_rep_mult *
var secretMoneyValue = baseSecretValue * CONSTANTS.InfiltrationMoneyValue; CONSTANTS.InfiltrationRepValue * BitNodeMultipliers.InfiltrationRep;
var secretMoneyValue = baseSecretValue * CONSTANTS.InfiltrationMoneyValue *
BitNodeMultipliers.InfiltrationMoney;
inst.secretsStolen.push(baseSecretValue); inst.secretsStolen.push(baseSecretValue);
dialogBoxCreate("You found and stole a set of classified documents from the company. " + dialogBoxCreate("You found and stole a set of classified documents from the company. " +
"These classified secrets could probably be sold for money ($" + "These classified secrets could probably be sold for money ($" +
@ -441,8 +444,10 @@ 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] * Player.faction_rep_mult * 1.25); totalValue += (inst.secretsStolen[i] * Player.faction_rep_mult *
totalMoneyValue += inst.secretsStolen[i] * CONSTANTS.InfiltrationMoneyValue; CONSTANTS.InfiltrationRepValue * BitNodeMultipliers.InfiltrationRep);
totalMoneyValue += inst.secretsStolen[i] * CONSTANTS.InfiltrationMoneyValue *
BitNodeMultipliers.InfiltrationMoney;
} }
document.getElementById("infiltration-level-text").innerHTML = document.getElementById("infiltration-level-text").innerHTML =
"Facility name: " + inst.companyName + "<br>" + "Facility name: " + inst.companyName + "<br>" +

@ -2,12 +2,14 @@ import {CompanyPositions, initCompanies,
Companies, getJobRequirementText} from "./Company.js"; Companies, getJobRequirementText} from "./Company.js";
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {commitShopliftCrime, commitRobStoreCrime, commitMugCrime, import {commitShopliftCrime, commitRobStoreCrime, commitMugCrime,
commitLarcenyCrime, commitDealDrugsCrime, commitTraffickArmsCrime, commitLarcenyCrime, commitDealDrugsCrime, commitBondForgeryCrime,
commitTraffickArmsCrime,
commitHomicideCrime, commitGrandTheftAutoCrime, commitKidnapCrime, commitHomicideCrime, commitGrandTheftAutoCrime, commitKidnapCrime,
commitAssassinationCrime, commitHeistCrime, determineCrimeSuccess, commitAssassinationCrime, commitHeistCrime, determineCrimeSuccess,
determineCrimeChanceShoplift, determineCrimeChanceRobStore, determineCrimeChanceShoplift, determineCrimeChanceRobStore,
determineCrimeChanceMug, determineCrimeChanceLarceny, determineCrimeChanceMug, determineCrimeChanceLarceny,
determineCrimeChanceDealDrugs, determineCrimeChanceTraffickArms, determineCrimeChanceDealDrugs, determineCrimeChanceBondForgery,
determineCrimeChanceTraffickArms,
determineCrimeChanceHomicide, determineCrimeChanceGrandTheftAuto, determineCrimeChanceHomicide, determineCrimeChanceGrandTheftAuto,
determineCrimeChanceKidnap, determineCrimeChanceAssassination, determineCrimeChanceKidnap, determineCrimeChanceAssassination,
determineCrimeChanceHeist} from "./Crimes.js"; determineCrimeChanceHeist} from "./Crimes.js";
@ -194,6 +196,7 @@ function displayLocationContent() {
var slumsMug = document.getElementById("location-slums-mug"); var slumsMug = document.getElementById("location-slums-mug");
var slumsLarceny = document.getElementById("location-slums-larceny"); var slumsLarceny = document.getElementById("location-slums-larceny");
var slumsDealDrugs = document.getElementById("location-slums-deal-drugs"); var slumsDealDrugs = document.getElementById("location-slums-deal-drugs");
var slumsBondForgery = document.getElementById("location-slums-bond-forgery");
var slumsTrafficArms = document.getElementById("location-slums-traffic-arms"); var slumsTrafficArms = document.getElementById("location-slums-traffic-arms");
var slumsHomicide = document.getElementById("location-slums-homicide"); var slumsHomicide = document.getElementById("location-slums-homicide");
var slumsGta = document.getElementById("location-slums-gta"); var slumsGta = document.getElementById("location-slums-gta");
@ -298,6 +301,7 @@ function displayLocationContent() {
slumsMug.style.display = "none"; slumsMug.style.display = "none";
slumsLarceny.style.display = "none"; slumsLarceny.style.display = "none";
slumsDealDrugs.style.display = "none"; slumsDealDrugs.style.display = "none";
slumsBondForgery.style.display = "none";
slumsTrafficArms.style.display = "none"; slumsTrafficArms.style.display = "none";
slumsHomicide.style.display = "none"; slumsHomicide.style.display = "none";
slumsGta.style.display = "none"; slumsGta.style.display = "none";
@ -1026,6 +1030,7 @@ function displayLocationContent() {
var mugChance = determineCrimeChanceMug(); var mugChance = determineCrimeChanceMug();
var larcenyChance = determineCrimeChanceLarceny(); var larcenyChance = determineCrimeChanceLarceny();
var drugsChance = determineCrimeChanceDealDrugs(); var drugsChance = determineCrimeChanceDealDrugs();
var bondChance = determineCrimeChanceBondForgery();
var armsChance = determineCrimeChanceTraffickArms(); var armsChance = determineCrimeChanceTraffickArms();
var homicideChance = determineCrimeChanceHomicide(); var homicideChance = determineCrimeChanceHomicide();
var gtaChance = determineCrimeChanceGrandTheftAuto(); var gtaChance = determineCrimeChanceGrandTheftAuto();
@ -1049,6 +1054,9 @@ function displayLocationContent() {
slumsDealDrugs.style.display = "block"; slumsDealDrugs.style.display = "block";
slumsDealDrugs.innerHTML = "Deal Drugs (" + (drugsChance*100).toFixed(3) + "% chance of success)"; slumsDealDrugs.innerHTML = "Deal Drugs (" + (drugsChance*100).toFixed(3) + "% chance of success)";
slumsDealDrugs.innerHTML += '<span class="tooltiptext"> Attempt to deal drugs </span>'; slumsDealDrugs.innerHTML += '<span class="tooltiptext"> Attempt to deal drugs </span>';
slumsBondForgery.style.display = "block";
slumsBondForgery.innerHTML = "Bond Forgery(" + (bondChance*100).toFixed(3) + "% chance of success)";
slumsBondForgery.innerHTML += "<span class='tooltiptext'> Attempt to forge corporate bonds</span>";
slumsTrafficArms.style.display = "block"; slumsTrafficArms.style.display = "block";
slumsTrafficArms.innerHTML = "Traffick Illegal Arms (" + (armsChance*100).toFixed(3) + "% chance of success)"; slumsTrafficArms.innerHTML = "Traffick Illegal Arms (" + (armsChance*100).toFixed(3) + "% chance of success)";
slumsTrafficArms.innerHTML += '<span class="tooltiptext"> Attempt to smuggle illegal arms into the city and sell them to gangs and criminal organizations </span>'; slumsTrafficArms.innerHTML += '<span class="tooltiptext"> Attempt to smuggle illegal arms into the city and sell them to gangs and criminal organizations </span>';
@ -1598,6 +1606,7 @@ function initLocationButtons() {
var slumsMug = document.getElementById("location-slums-mug"); var slumsMug = document.getElementById("location-slums-mug");
var slumsLarceny = document.getElementById("location-slums-larceny"); var slumsLarceny = document.getElementById("location-slums-larceny");
var slumsDealDrugs = document.getElementById("location-slums-deal-drugs"); var slumsDealDrugs = document.getElementById("location-slums-deal-drugs");
var slumsBondForgery = document.getElementById("location-slums-bond-forgery");
var slumsTrafficArms = document.getElementById("location-slums-traffic-arms"); var slumsTrafficArms = document.getElementById("location-slums-traffic-arms");
var slumsHomicide = document.getElementById("location-slums-homicide"); var slumsHomicide = document.getElementById("location-slums-homicide");
var slumsGta = document.getElementById("location-slums-gta"); var slumsGta = document.getElementById("location-slums-gta");
@ -1844,6 +1853,11 @@ function initLocationButtons() {
return false; return false;
}); });
slumsBondForgery.addEventListener("click", function() {
commitBondForgeryCrime();
return false;
});
slumsTrafficArms.addEventListener("click", function() { slumsTrafficArms.addEventListener("click", function() {
commitTraffickArmsCrime(); commitTraffickArmsCrime();
return false; return false;

@ -97,16 +97,20 @@ function evaluate(exp, workerScript) {
//Create a new WorkerScript for this function evaluation //Create a new WorkerScript for this function evaluation
var funcWorkerScript = new WorkerScript(workerScript.scriptRef); var funcWorkerScript = new WorkerScript(workerScript.scriptRef);
funcWorkerScript.serverIp = workerScript.serverIp;
funcWorkerScript.env = funcEnv; funcWorkerScript.env = funcEnv;
workerScript.fnWorker = funcWorkerScript;
evaluate(func.body, funcWorkerScript).then(function(res) { evaluate(func.body, funcWorkerScript).then(function(res) {
//If the function finished successfuly, that means there //If the function finished successfuly, that means there
//was no return statement since a return statement rejects. So resolve to null //was no return statement since a return statement rejects. So resolve to null
resolve(null); resolve(null);
workerScript.fnWorker = null;
}).catch(function(e) { }).catch(function(e) {
if (e.constructor === Array && e.length === 2 && e[0] === "RETURNSTATEMENT") { if (e.constructor === Array && e.length === 2 && e[0] === "RETURNSTATEMENT") {
//Return statement from function //Return statement from function
resolve(e[1]); resolve(e[1]);
workerScript.fnWorker = null;
} else if (isString(e)) { } else if (isString(e)) {
reject(makeRuntimeRejectMsg(workerScript, e)); reject(makeRuntimeRejectMsg(workerScript, e));
} else if (e instanceof WorkerScript) { } else if (e instanceof WorkerScript) {
@ -117,7 +121,11 @@ function evaluate(exp, workerScript) {
errorMsg = errorTextArray[3]; errorMsg = errorTextArray[3];
reject(makeRuntimeRejectMsg(workerScript, errorMsg)); reject(makeRuntimeRejectMsg(workerScript, errorMsg));
} else { } else {
reject(makeRuntimeRejectMsg(workerScript, "Error in one of your functions. Could not identify which function")); if (env.stopFlag) {
reject(workerScript);
} else {
reject(makeRuntimeRejectMsg(workerScript, "Error in one of your functions. Could not identify which function"));
}
} }
} else if (e instanceof Error) { } else if (e instanceof Error) {
reject(makeRuntimeRejectMsg(workerScript, e.toString())); reject(makeRuntimeRejectMsg(workerScript, e.toString()));

@ -3,6 +3,11 @@ import {Augmentations, Augmentation,
augmentationExists, installAugmentations, augmentationExists, installAugmentations,
AugmentationNames} from "./Augmentations.js"; AugmentationNames} from "./Augmentations.js";
import {BitNodeMultipliers} from "./BitNode.js"; import {BitNodeMultipliers} from "./BitNode.js";
import {commitShopliftCrime, commitRobStoreCrime, commitMugCrime,
commitLarcenyCrime, commitDealDrugsCrime, commitBondForgeryCrime,
commitTraffickArmsCrime,
commitHomicideCrime, commitGrandTheftAutoCrime, commitKidnapCrime,
commitAssassinationCrime, commitHeistCrime} from "./Crimes.js";
import {Companies, Company, CompanyPosition, import {Companies, Company, CompanyPosition,
CompanyPositions, companyExists} from "./Company.js"; CompanyPositions, companyExists} from "./Company.js";
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
@ -28,6 +33,7 @@ import {StockMarket, StockSymbols, SymbolToStockMap, initStockSymbols,
updateStockTicker, updateStockPlayerPosition, updateStockTicker, updateStockPlayerPosition,
Stock} from "./StockMarket.js"; Stock} from "./StockMarket.js";
import {post} from "./Terminal.js"; import {post} from "./Terminal.js";
import {TextFile, getTextFile, createTextFile} from "./TextFile.js";
import {WorkerScript, workerScripts, import {WorkerScript, workerScripts,
killWorkerScript, NetscriptPorts} from "./NetscriptWorker.js"; killWorkerScript, NetscriptPorts} from "./NetscriptWorker.js";
@ -662,14 +668,6 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill); workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill);
return Player.hacking_skill; return Player.hacking_skill;
}, },
getIntelligence : function () {
if (!hasAISF) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run getIntelligence(). It requires Source-File 5 to run.");
}
Player.updateSkillLevels();
workerScript.scriptRef.log("getHackingLevel() returned " + Player.intelligence);
return Player.intelligence;
},
getHackingMultipliers : function() { getHackingMultipliers : function() {
return { return {
chance: Player.hacking_chance_mult, chance: Player.hacking_chance_mult,
@ -1026,8 +1024,8 @@ function NetscriptFunctions(workerScript) {
if (isNaN(n)) {return 0;} if (isNaN(n)) {return 0;}
return Math.round(n); return Math.round(n);
}, },
write : function(port, data="") { write : function(port, data="", mode="a") {
if (!isNaN(port)) { if (!isNaN(port)) { //Write to port
//Port 1-10 //Port 1-10
if (port < 1 || port > 10) { if (port < 1 || port > 10) {
throw makeRuntimeRejectMsg(workerScript, "Trying to write to invalid port: " + port + ". Only ports 1-10 are valid."); throw makeRuntimeRejectMsg(workerScript, "Trying to write to invalid port: " + port + ". Only ports 1-10 are valid.");
@ -1043,12 +1041,29 @@ function NetscriptFunctions(workerScript) {
return true; return true;
} }
return false; return false;
} else if (isString(port)) { //Write to text file
var fn = port;
var server = getServer(workerScript.serverIp);
if (server === null) {
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in write(). This is a bug please contact game dev");
}
var txtFile = getTextFile(fn, server);
if (txtFile === null) {
txtFile = createTextFile(fn, data, server);
return true;
}
if (mode === "w") {
txtFile.write(data);
} else {
txtFile.append(data);
}
return true;
} else { } else {
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for port: " + port + ". Must be a number between 1 and 10"); throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for port: " + port + ". Must be a number between 1 and 10");
} }
}, },
read : function(port) { read : function(port) {
if (!isNaN(port)) { if (!isNaN(port)) { //Read from port
//Port 1-10 //Port 1-10
if (port < 1 || port > 10) { if (port < 1 || port > 10) {
throw makeRuntimeRejectMsg(workerScript, "Trying to write to invalid port: " + port + ". Only ports 1-10 are valid."); throw makeRuntimeRejectMsg(workerScript, "Trying to write to invalid port: " + port + ". Only ports 1-10 are valid.");
@ -1063,6 +1078,18 @@ function NetscriptFunctions(workerScript) {
} else { } else {
return port.shift(); return port.shift();
} }
} else if (isString(port)) { //Read from text file
var fn = port;
var server = getServer(workerScript.serverIp);
if (server === null) {
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in read(). This is a bug please contact game dev");
}
var txtFile = getTextFile(fn, server);
if (txtFile !== null) {
return txtFile.text;
} else {
return "";
}
} else { } else {
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for port: " + port + ". Must be a number between 1 and 10"); throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for port: " + port + ". Must be a number between 1 and 10");
} }
@ -1513,6 +1540,24 @@ function NetscriptFunctions(workerScript) {
} }
return true; return true;
}, },
getStats : function() {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 1)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run getStats(). It is a Singularity Function and requires SourceFile-4 (level 2) to run.");
return {};
}
}
return {
hacking: Player.hacking_skill,
strength: Player.strength,
defense: Player.defense,
dexterity: Player.dexterity,
agility: Player.agility,
charisma: Player.charisma,
intelligence: Player.intelligence
}
},
upgradeHomeRam() { upgradeHomeRam() {
if (Player.bitNodeN != 4) { if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 2)) { if (!(hasSingularitySF && singularitySFLvl >= 2)) {
@ -1899,6 +1944,60 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("Began creating program: " + name); workerScript.scriptRef.log("Began creating program: " + name);
return true; return true;
}, },
commitCrime(crime) {
if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 3)) {
throw makeRuntimeRejectMsg(workerScript, "Cannot run commitCrime(). It is a Singularity Function and requires SourceFile-4 (level 3) to run.");
return;
}
}
if (Player.isWorking) {
var txt = Player.singularityStopWork();
workerScript.scriptRef.log(txt);
}
crime = crime.toLowerCase();
if (crime.includes("shoplift")) {
workerScript.scriptRef.log("Attempting to shoplift...");
commitShopliftCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("rob") && crime.includes("store")) {
workerScript.scriptRef.log("Attempting to rob a store...");
commitRobStoreCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("mug")) {
workerScript.scriptRef.log("Attempting to mug someone...");
commitMugCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("larceny")) {
workerScript.scriptRef.log("Attempting to commit larceny...");
commitLarcenyCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("drugs")) {
workerScript.scriptRef.log("Attempting to deal drugs...");
commitDealDrugsCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("bond") && crime.includes("forge")) {
workerScript.scriptRef.log("Attempting to forge corporate bonds...");
commitBondForgeryCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("traffick") && crime.includes("arms")) {
workerScript.scriptRef.log("Attempting to traffick illegal arms...");
commitTraffickArmsCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("homicide")) {
workerScript.scriptRef.log("Attempting to commit homicide...");
commitHomicideCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("grand") && crime.includes("auto")) {
workerScript.scriptRef.log("Attempting to commit grand theft auto...");
commitGrandTheftAutoCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("kidnap")) {
workerScript.scriptRef.log("Attempting to kidnap and ransom a high-profile target...");
commitKidnapCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else if (crime.includes("assassinate")) {
workerScript.scriptRef.log("Attempting to assassinate a high-profile target...");
commitAssassinationCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript})
} else if (crime.includes("heist")) {
workerScript.scriptRef.log("Attempting to pull off a heist...");
commitHeistCrime(CONSTANTS.CrimeSingFnDivider, {workerscript: workerScript});
} else {
throw makeRuntimeRejectMsg(workerScript, "Invalid crime passed into commitCrime(): " + crime);
}
},
getOwnedAugmentations(purchased=false) { getOwnedAugmentations(purchased=false) {
if (Player.bitNodeN != 4) { if (Player.bitNodeN != 4) {
if (!(hasSingularitySF && singularitySFLvl >= 3)) { if (!(hasSingularitySF && singularitySFLvl >= 3)) {

@ -25,6 +25,7 @@ function WorkerScript(runningScriptObj) {
this.errorMessage = ""; this.errorMessage = "";
this.args = runningScriptObj.args; this.args = runningScriptObj.args;
this.killTrigger = function() {}; //CB func used to clear any delays (netscriptDelay()) this.killTrigger = function() {}; //CB func used to clear any delays (netscriptDelay())
this.fnWorker = null; //Workerscript for a function call
} }
//Returns the server on which the workerScript is running //Returns the server on which the workerScript is running
@ -165,6 +166,10 @@ function killWorkerScript(runningScriptObj, 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(); workerScripts[i].killTrigger();
if (workerScripts[i].fnWorker) {
workerScripts[i].fnWorker.env.stopFlag = true;
workerScripts[i].fnWorker.killTrigger();
}
return true; return true;
} }
} }

@ -1408,11 +1408,16 @@ PlayerObject.prototype.finishClass = function(sing=false) {
} }
//The EXP and $ gains are hardcoded. Time is in ms //The EXP and $ gains are hardcoded. Time is in ms
PlayerObject.prototype.startCrime = function(hackExp, strExp, defExp, dexExp, agiExp, chaExp, money, time) { PlayerObject.prototype.startCrime = function(hackExp, strExp, defExp, dexExp, agiExp, chaExp, money, time, singParams=null) {
this.resetWorkStatus(); this.resetWorkStatus();
this.isWorking = true; this.isWorking = true;
this.workType = CONSTANTS.WorkTypeCrime; this.workType = CONSTANTS.WorkTypeCrime;
if (singParams && singParams.workerscript) {
this.committingCrimeThruSingFn = true;
this.singFnCrimeWorkerScript = singParams.workerscript;
}
this.workHackExpGained = hackExp * this.hacking_exp_mult * BitNodeMultipliers.CrimeExpGain; this.workHackExpGained = hackExp * this.hacking_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.workStrExpGained = strExp * this.strength_exp_mult * BitNodeMultipliers.CrimeExpGain; this.workStrExpGained = strExp * this.strength_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.workDefExpGained = defExp * this.defense_exp_mult * BitNodeMultipliers.CrimeExpGain; this.workDefExpGained = defExp * this.defense_exp_mult * BitNodeMultipliers.CrimeExpGain;
@ -1476,6 +1481,10 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
case CONSTANTS.CrimeDrugs: case CONSTANTS.CrimeDrugs:
this.karma -= 0.5; this.karma -= 0.5;
break; break;
case CONSTANTS.CrimeBondForgery:
this.karma -= 0.1;
this.gainIntelligenceExp(2 * CONSTANTS.IntelligenceCrimeBaseExpGain);
break;
case CONSTANTS.CrimeTraffickArms: case CONSTANTS.CrimeTraffickArms:
this.karma -= 1; this.karma -= 1;
break; break;
@ -1513,16 +1522,27 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
this.workDexExpGained *= 2; this.workDexExpGained *= 2;
this.workAgiExpGained *= 2; this.workAgiExpGained *= 2;
this.workChaExpGained *= 2; this.workChaExpGained *= 2;
if (this.committingCrimeThruSingFn) {
this.singFnCrimeWorkerScript.scriptRef.log("Crime successful! Gained " +
numeral(this.workMoneyGained).format("$0.000a") + ", " +
formatNumber(this.workHackExpGained, 3) + " hack exp, " +
formatNumber(this.workStrExpGained, 3) + " str exp, " +
formatNumber(this.workDefExpGained, 3) + " def exp, " +
formatNumber(this.workDexExpGained, 3) + " dex exp, " +
formatNumber(this.workAgiExpGained, 3) + " agi exp, " +
formatNumber(this.workChaExpGained, 3) + " cha exp.");
} else {
dialogBoxCreate("Crime successful! <br><br>" +
"You gained:<br>"+
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workHackExpGained, 4) + " hacking experience <br>" +
formatNumber(this.workStrExpGained, 4) + " strength experience<br>" +
formatNumber(this.workDefExpGained, 4) + " defense experience<br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity experience<br>" +
formatNumber(this.workAgiExpGained, 4) + " agility experience<br>" +
formatNumber(this.workChaExpGained, 4) + " charisma experience");
}
dialogBoxCreate("Crime successful! <br><br>" +
"You gained:<br>"+
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workHackExpGained, 4) + " hacking experience <br>" +
formatNumber(this.workStrExpGained, 4) + " strength experience<br>" +
formatNumber(this.workDefExpGained, 4) + " defense experience<br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity experience<br>" +
formatNumber(this.workAgiExpGained, 4) + " agility experience<br>" +
formatNumber(this.workChaExpGained, 4) + " charisma experience");
} else { } else {
//Exp halved on failure //Exp halved on failure
this.workHackExpGained /= 2; this.workHackExpGained /= 2;
@ -1531,20 +1551,30 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
this.workDexExpGained /= 2; this.workDexExpGained /= 2;
this.workAgiExpGained /= 2; this.workAgiExpGained /= 2;
this.workChaExpGained /= 2; this.workChaExpGained /= 2;
if (this.committingCrimeThruSingFn) {
dialogBoxCreate("Crime failed! <br><br>" + this.singFnCrimeWorkerScript.scriptRef.log("Crime failed! Gained " +
"You gained:<br>"+ formatNumber(this.workHackExpGained, 3) + " hack exp, " +
formatNumber(this.workHackExpGained, 4) + " hacking experience <br>" + formatNumber(this.workStrExpGained, 3) + " str exp, " +
formatNumber(this.workStrExpGained, 4) + " strength experience<br>" + formatNumber(this.workDefExpGained, 3) + " def exp, " +
formatNumber(this.workDefExpGained, 4) + " defense experience<br>" + formatNumber(this.workDexExpGained, 3) + " dex exp, " +
formatNumber(this.workDexExpGained, 4) + " dexterity experience<br>" + formatNumber(this.workAgiExpGained, 3) + " agi exp, " +
formatNumber(this.workAgiExpGained, 4) + " agility experience<br>" + formatNumber(this.workChaExpGained, 3) + " chaexp.");
formatNumber(this.workChaExpGained, 4) + " charisma experience"); } else {
dialogBoxCreate("Crime failed! <br><br>" +
"You gained:<br>"+
formatNumber(this.workHackExpGained, 4) + " hacking experience <br>" +
formatNumber(this.workStrExpGained, 4) + " strength experience<br>" +
formatNumber(this.workDefExpGained, 4) + " defense experience<br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity experience<br>" +
formatNumber(this.workAgiExpGained, 4) + " agility experience<br>" +
formatNumber(this.workChaExpGained, 4) + " charisma experience");
}
} }
this.gainWorkExp(); this.gainWorkExp();
} }
this.committingCrimeThruSingFn = false;
this.singFnCrimeWorkerScript = null;
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;

@ -43,12 +43,11 @@ function BitburnerSaveObject() {
this.VersionSave = ""; this.VersionSave = "";
} }
BitburnerSaveObject.prototype.saveGame = function() { BitburnerSaveObject.prototype.saveGame = function(db) {
this.PlayerSave = JSON.stringify(Player); this.PlayerSave = JSON.stringify(Player);
//Delete all logs from all running scripts //Delete all logs from all running scripts
var TempAllServers = JSON.parse(JSON.stringify(AllServers), Reviver); var TempAllServers = JSON.parse(JSON.stringify(AllServers), Reviver);
//var TempAllServers = jQuery.extend(true, {}, AllServers); //Deep copy
for (var ip in TempAllServers) { for (var ip in TempAllServers) {
var server = TempAllServers[ip]; var server = TempAllServers[ip];
if (server == null) {continue;} if (server == null) {continue;}
@ -73,28 +72,49 @@ BitburnerSaveObject.prototype.saveGame = function() {
this.AllGangsSave = JSON.stringify(AllGangs); this.AllGangsSave = JSON.stringify(AllGangs);
} }
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this)))); var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
//We'll save to both localstorage and indexedDb
var objectStore = db.transaction(["savestring"], "readwrite").objectStore("savestring");
var request = objectStore.put(saveString, "save");
request.onerror = function(e) {
console.log("Error saving game to IndexedDB: " + e);
}
request.onsuccess = function(e) {
console.log("Successfully saved game to IndexedDB!");
}
try { try {
window.localStorage.setItem("bitburnerSave", saveString); window.localStorage.setItem("bitburnerSave", saveString);
} catch(e) { } catch(e) {
if (e.code == 22) { if (e.code == 22) {
dialogBoxCreate("Failed to save game because the size of the save file " + console.log("Failed to save game to localStorage because the size of the save file " +
"is too large. Consider killing several of your scripts to " + "is too large. However, the game will still be saved to IndexedDb if your browser " +
"fix this, or increasing the size of your browsers localStorage"); "supports it. If you would like to save to localStorage as well, then " +
"consider killing several of your scripts to " +
"fix this, or increasing the size of your browsers localStorage");
} }
} }
console.log("Game saved!"); console.log("Game saved!");
Engine.createStatusText("Game saved!"); Engine.createStatusText("Game saved!");
} }
function loadGame(saveObj) { function loadGame(saveString) {
if (!window.localStorage.getItem("bitburnerSave")) { if (saveString === "" || saveString === null || saveString === undefined) {
console.log("No save file to load"); if (!window.localStorage.getItem("bitburnerSave")) {
return false; console.log("No save file to load");
return false;
}
saveString = decodeURIComponent(escape(atob(window.localStorage.getItem("bitburnerSave"))));
console.log("Loading game from localStorage");
} else {
saveString = decodeURIComponent(escape(atob(saveString)));
console.log("Loading game from IndexedDB");
} }
var saveString = decodeURIComponent(escape(atob(window.localStorage.getItem("bitburnerSave"))));
saveObj = JSON.parse(saveString, Reviver); var saveObj = JSON.parse(saveString, Reviver);
loadPlayer(saveObj.PlayerSave); loadPlayer(saveObj.PlayerSave);
loadAllServers(saveObj.AllServersSave); loadAllServers(saveObj.AllServersSave);
@ -504,10 +524,20 @@ BitburnerSaveObject.prototype.importGame = function() {
} }
BitburnerSaveObject.prototype.deleteGame = function() { BitburnerSaveObject.prototype.deleteGame = function(db) {
//Delete from local storage
if (window.localStorage.getItem("bitburnerSave")) { if (window.localStorage.getItem("bitburnerSave")) {
window.localStorage.removeItem("bitburnerSave"); window.localStorage.removeItem("bitburnerSave");
} }
//Delete from indexedDB
var request = db.transaction(["savestring"], "readwrite").objectStore("savestring").delete("save");
request.onsuccess = function(e) {
console.log("Successfully deleted save from indexedDb");
}
request.onerror = function(e) {
console.log("Failed to delete save from indexedDb: " + e);
}
Engine.createStatusText("Game deleted!"); Engine.createStatusText("Game deleted!");
} }

@ -263,8 +263,7 @@ function calculateRamUsage(codeCopy) {
var hasRootAccessCount = numOccurrences(codeCopy, "hasRootAccess("); var hasRootAccessCount = numOccurrences(codeCopy, "hasRootAccess(");
var getHostnameCount = numOccurrences(codeCopy, "getHostname(") + var getHostnameCount = numOccurrences(codeCopy, "getHostname(") +
numOccurrences(codeCopy, "getIp("); numOccurrences(codeCopy, "getIp(");
var getHackingLevelCount = numOccurrences(codeCopy, "getHackingLevel(") + var getHackingLevelCount = numOccurrences(codeCopy, "getHackingLevel(");
numOccurrences(codeCopy, "getIntelligence(");
var getMultipliersCount = numOccurrences(codeCopy, "getHackingMultipliers(") + var getMultipliersCount = numOccurrences(codeCopy, "getHackingMultipliers(") +
numOccurrences(codeCopy, "getBitNodeMultipliers("); numOccurrences(codeCopy, "getBitNodeMultipliers(");
var getServerCount = numOccurrences(codeCopy, "getServerMoneyAvailable(") + var getServerCount = numOccurrences(codeCopy, "getServerMoneyAvailable(") +
@ -307,7 +306,8 @@ function calculateRamUsage(codeCopy) {
numOccurrences(codeCopy, "gymWorkout(") + numOccurrences(codeCopy, "gymWorkout(") +
numOccurrences(codeCopy, "travelToCity(") + numOccurrences(codeCopy, "travelToCity(") +
numOccurrences(codeCopy, "purchaseTor(") + numOccurrences(codeCopy, "purchaseTor(") +
numOccurrences(codeCopy, "purchaseProgram("); numOccurrences(codeCopy, "purchaseProgram(") +
numOccurrences(codeCopy, "getStats(");
var singFn2Count = numOccurrences(codeCopy, "upgradeHomeRam(") + var singFn2Count = numOccurrences(codeCopy, "upgradeHomeRam(") +
numOccurrences(codeCopy, "getUpgradeHomeRamCost(") + numOccurrences(codeCopy, "getUpgradeHomeRamCost(") +
numOccurrences(codeCopy, "workForCompany(") + numOccurrences(codeCopy, "workForCompany(") +
@ -318,6 +318,9 @@ function calculateRamUsage(codeCopy) {
numOccurrences(codeCopy, "workForFaction(") + numOccurrences(codeCopy, "workForFaction(") +
numOccurrences(codeCopy, "getFactionRep("); numOccurrences(codeCopy, "getFactionRep(");
var singFn3Count = numOccurrences(codeCopy, "createProgram(") + var singFn3Count = numOccurrences(codeCopy, "createProgram(") +
numOccurrences(codeCopy, "commitCrime(") +
numOccurrences(codeCopy, "getOwnedAugmentations(") +
numOccurrences(codeCopy, "getAugmentationsFromFaction(") +
numOccurrences(codeCopy, "getAugmentationCost(") + numOccurrences(codeCopy, "getAugmentationCost(") +
numOccurrences(codeCopy, "purchaseAugmentation(") + numOccurrences(codeCopy, "purchaseAugmentation(") +
numOccurrences(codeCopy, "installAugmentations("); numOccurrences(codeCopy, "installAugmentations(");

@ -32,12 +32,13 @@ function Server(ip=createRandomIp(), hostname="", organizationName="",
//RAM, CPU speed and Scripts //RAM, CPU speed and Scripts
this.maxRam = maxRam; //GB this.maxRam = maxRam; //GB
this.ramUsed = 0; this.ramUsed = 0;
this.cpuCores = 1; //Max of 8, affects hacking times and Hacking MIssion starting Cores this.cpuCores = 1; //Max of 8, affects hacking times and Hacking Mission starting Cores
this.scripts = []; this.scripts = [];
this.runningScripts = []; //Stores RunningScript objects this.runningScripts = []; //Stores RunningScript objects
this.programs = []; this.programs = [];
this.messages = []; this.messages = [];
this.textFiles = [];
this.dir = 0; //new Directory(this, null, ""); this.dir = 0; //new Directory(this, null, "");
/* Hacking information (only valid for "foreign" aka non-purchased servers) */ /* Hacking information (only valid for "foreign" aka non-purchased servers) */
@ -54,7 +55,6 @@ function Server(ip=createRandomIp(), hostname="", organizationName="",
this.baseDifficulty = 1; //Starting difficulty this.baseDifficulty = 1; //Starting difficulty
this.minDifficulty = 1; this.minDifficulty = 1;
this.serverGrowth = 0; //Affects how the moneyAvailable increases (0-100) this.serverGrowth = 0; //Affects how the moneyAvailable increases (0-100)
this.timesHacked = 0;
//The IP's of all servers reachable from this one (what shows up if you run scan/netstat) //The IP's of all servers reachable from this one (what shows up if you run scan/netstat)
// NOTE: Only contains IP and not the Server objects themselves // NOTE: Only contains IP and not the Server objects themselves

@ -25,6 +25,8 @@ import {AllServers, GetServerByHostname,
getServer, Server} from "./Server.js"; getServer, Server} from "./Server.js";
import {SpecialServerIps, import {SpecialServerIps,
SpecialServerNames} from "./SpecialServerIps.js"; SpecialServerNames} from "./SpecialServerIps.js";
import {TextFile, getTextFile,
createTextFile} from "./TextFile.js";
import {containsAllStrings, longestCommonStart, import {containsAllStrings, longestCommonStart,
formatNumber, isString} from "../utils/StringHelperFunctions.js"; formatNumber, isString} from "../utils/StringHelperFunctions.js";
@ -295,7 +297,7 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
//Autocomplete the command //Autocomplete the command
if (index == -1) { if (index == -1) {
return ["alias", "analyze", "cat", "check", "clear", "cls", "connect", "free", return ["alias", "analyze", "cat", "check", "clear", "cls", "connect", "download", "free",
"hack", "help", "home", "hostname", "ifconfig", "kill", "killall", "hack", "help", "home", "hostname", "ifconfig", "kill", "killall",
"ls", "lscpu", "mem", "nano", "ps", "rm", "run", "scan", "scan-analyze", "ls", "lscpu", "mem", "nano", "ps", "rm", "run", "scan", "scan-analyze",
"scp", "sudov", "tail", "theme", "top"].concat(Object.keys(Aliases)).concat(Object.keys(GlobalAliases)); "scp", "sudov", "tail", "theme", "top"].concat(Object.keys(Aliases)).concat(Object.keys(GlobalAliases));
@ -362,6 +364,9 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
allPos.push(currServ.messages[i]); allPos.push(currServ.messages[i]);
} }
} }
for (var i = 0; i < currServ.textFiles.length; ++i) {
allPos.push(currServ.textFiles[i].fn);
}
return allPos; return allPos;
} }
@ -386,10 +391,18 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) {
} else { } else {
allPos.push(currServ.messages[i]); allPos.push(currServ.messages[i]);
} }
}
for (var i = 0; i < currServ.textFiles.length; ++i) {
allPos.push(currServ.textFiles[i].fn);
} }
return allPos; return allPos;
} }
if (input.startsWith("download ")) {
for (var i = 0; i < currServ.textFiles.length; ++i) {
allPos.push(currServ.textFiles[i].fn);
}
}
return allPos; return allPos;
} }
@ -739,9 +752,8 @@ let Terminal = {
post("Incorrect usage of cat command. Usage: cat [file]"); return; post("Incorrect usage of cat command. Usage: cat [file]"); return;
} }
var filename = commandArray[1]; var filename = commandArray[1];
//Can only edit script files if (!filename.endsWith(".msg") && !filename.endsWith(".lit") && !filename.endsWith(".txt")) {
if (!filename.endsWith(".msg") && !filename.endsWith(".lit")) { post("Error: Only .msg, .txt, and .lit files are viewable with cat (filename must end with .msg, .txt, or .lit)"); return;
post("Error: Only .msg and .lit files are viewable with cat (filename must end with .msg or .lit)"); return;
} }
for (var i = 0; i < s.messages.length; ++i) { for (var i = 0; i < s.messages.length; ++i) {
if (filename.endsWith(".lit") && s.messages[i] == filename) { if (filename.endsWith(".lit") && s.messages[i] == filename) {
@ -752,6 +764,12 @@ let Terminal = {
return; return;
} }
} }
for (var i = 0; i < s.textFiles.length; ++i) {
if (s.textFiles[i].fn === filename) {
s.textFiles[i].show();
return;
}
}
post("Error: No such file " + filename); post("Error: No such file " + filename);
break; break;
case "check": case "check":
@ -805,6 +823,19 @@ let Terminal = {
post("Host not found"); post("Host not found");
break; break;
case "download":
if (commandArray.length != 2) {
post("Incorrect usage of download command. Usage: download [text file]");
return;
}
var fn = commandArray[1];
var txtFile = getTextFile(fn, s);
if (txtFile !== null) {
txtFile.download();
} else {
post("Error: " + fn + " does not exist");
}
break;
case "free": case "free":
Terminal.executeFreeCommand(commandArray); Terminal.executeFreeCommand(commandArray);
break; break;
@ -978,38 +1009,45 @@ let Terminal = {
//Check programs //Check programs
var delTarget = commandArray[1]; var delTarget = commandArray[1];
for (var i = 0; i < s.programs.length; ++i) {
if (s.programs[i] == delTarget) {
s.programs.splice(i, 1);
return;
}
}
//Check scripts if (delTarget.endsWith(".exe")) {
for (var i = 0; i < s.scripts.length; ++i) { for (var i = 0; i < s.programs.length; ++i) {
if (s.scripts[i].filename == delTarget) { if (s.programs[i] == delTarget) {
//Check that the script isnt currently running s.programs.splice(i, 1);
for (var j = 0; j < s.runningScripts.length; ++j) { return;
if (s.runningScripts[j].filename == delTarget) { }
post("Cannot delete a script that is currently running!"); }
return; } else if (delTarget.endsWith(".script")) {
} for (var i = 0; i < s.scripts.length; ++i) {
if (s.scripts[i].filename == delTarget) {
//Check that the script isnt currently running
for (var j = 0; j < s.runningScripts.length; ++j) {
if (s.runningScripts[j].filename == delTarget) {
post("Cannot delete a script that is currently running!");
return;
}
}
s.scripts.splice(i, 1);
return;
}
}
} else if (delTarget.endsWith(".lit")) {
for (var i = 0; i < s.messages.length; ++i) {
var f = s.messages[i];
if (!(f instanceof Message) && isString(f) && f === delTarget) {
s.messages.splice(i, 1);
return;
}
}
} else if (delTarget.endsWith(".txt")) {
for (var i = 0; i < s.textFiles.length; ++i) {
if (s.textFiles[i].fn === delTarget) {
s.textFiles.splice(i, 1);
return;
} }
s.scripts.splice(i, 1);
return;
} }
} }
post("Error: No such file exists");
//Check literature files
for (var i = 0; i < s.messages.length; ++i) {
var f = s.messages[i];
if (!(f instanceof Message) && isString(f) && f === delTarget) {
s.messages.splice(i, 1);
return;
}
}
post("No such file exists");
break; break;
case "run": case "run":
//Run a program or a script //Run a program or a script
@ -1346,6 +1384,15 @@ let Terminal = {
} }
} }
} }
for (var i = 0; i < s.textFiles.length; ++i) {
if (filter) {
if (s.textFiles[i].fn.includes(filter)) {
allFiles.push(s.textFiles[i].fn);
}
} else {
allFiles.push(s.textFiles[i].fn);
}
}
//Sort the files alphabetically then print each //Sort the files alphabetically then print each
allFiles.sort(); allFiles.sort();

@ -896,7 +896,7 @@ let Engine = {
//is necessary and then resets the counter //is necessary and then resets the counter
checkCounters: function() { checkCounters: function() {
if (Engine.Counters.autoSaveCounter <= 0) { if (Engine.Counters.autoSaveCounter <= 0) {
saveObject.saveGame(); saveObject.saveGame(indexedDb);
Engine.Counters.autoSaveCounter = 300; Engine.Counters.autoSaveCounter = 300;
} }
@ -1112,7 +1112,7 @@ let Engine = {
} }
}, },
load: function() { load: function(saveString) {
//Initialize main menu accordion panels to all start as "open" //Initialize main menu accordion panels to all start as "open"
var terminal = document.getElementById("terminal-tab"); var terminal = document.getElementById("terminal-tab");
var createScript = document.getElementById("create-script-tab"); var createScript = document.getElementById("create-script-tab");
@ -1129,7 +1129,7 @@ let Engine = {
var options = document.getElementById("options-tab"); var options = document.getElementById("options-tab");
//Load game from save or create new game //Load game from save or create new game
if (loadGame(saveObject)) { if (loadGame(saveString)) {
console.log("Loaded game from save"); console.log("Loaded game from save");
initBitNodes(); initBitNodes();
initBitNodeMultipliers(); initBitNodeMultipliers();
@ -1579,13 +1579,13 @@ let Engine = {
//Save, Delete, Import/Export buttons //Save, Delete, Import/Export buttons
Engine.Clickables.saveMainMenuButton = document.getElementById("save-game-link"); Engine.Clickables.saveMainMenuButton = document.getElementById("save-game-link");
Engine.Clickables.saveMainMenuButton.addEventListener("click", function() { Engine.Clickables.saveMainMenuButton.addEventListener("click", function() {
saveObject.saveGame(); saveObject.saveGame(indexedDb);
return false; return false;
}); });
Engine.Clickables.deleteMainMenuButton = document.getElementById("delete-game-link"); Engine.Clickables.deleteMainMenuButton = document.getElementById("delete-game-link");
Engine.Clickables.deleteMainMenuButton.addEventListener("click", function() { Engine.Clickables.deleteMainMenuButton.addEventListener("click", function() {
saveObject.deleteGame(); saveObject.deleteGame(indexedDb);
return false; return false;
}); });
@ -1596,7 +1596,7 @@ let Engine = {
//Character Overview buttons //Character Overview buttons
document.getElementById("character-overview-save-button").addEventListener("click", function() { document.getElementById("character-overview-save-button").addEventListener("click", function() {
saveObject.saveGame(); saveObject.saveGame(indexedDb);
return false; return false;
}); });
@ -1672,8 +1672,42 @@ let Engine = {
} }
}; };
var indexedDb, indexedDbRequest;
window.onload = function() { window.onload = function() {
Engine.load(); if (!window.indexedDB) {
return Engine.load(null); //Will try to load from localstorage
}
//DB is called bitburnerSave
//Object store is called savestring
//key for the Object store is called save
indexedDbRequest = window.indexedDB.open("bitburnerSave", 1);
indexedDbRequest.onerror = function(e) {
console.log("Error opening indexedDB: " + e);
return Engine.load(null); //Try to load from localstorage
};
indexedDbRequest.onsuccess = function(e) {
console.log("Opening bitburnerSave database successful!");
indexedDb = e.target.result;
var transaction = indexedDb.transaction(["savestring"]);
var objectStore = transaction.objectStore("savestring");
var request = objectStore.get("save");
request.onerror = function(e) {
console.log("Error in Database request to get savestring: " + e);
return Engine.load(null); //Try to load from localstorage
}
request.onsuccess = function(e) {
Engine.load(request.result); //Is this right?
}
};
indexedDbRequest.onupgradeneeded = function(e) {
var db = event.target.result;
var objectStore = db.createObjectStore("savestring");
}
}; };
export {Engine}; export {Engine};

@ -1,3 +1,4 @@
import {BitNodeMultipliers} from "../src/BitNode.js";
import {CONSTANTS} from "../src/Constants.js"; import {CONSTANTS} from "../src/Constants.js";
import {Factions, Faction} from "../src/Faction.js"; import {Factions, Faction} from "../src/Faction.js";
import {Player} from "../src/Player.js"; import {Player} from "../src/Player.js";
@ -47,8 +48,9 @@ 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.25 var facValue = totalValue * Player.faction_rep_mult *
var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue; CONSTANTS.InfiltrationRepValue * BitNodeMultipliers.InfiltrationRep;
var moneyValue = totalValue * CONSTANTS.InfiltrationMoneyValue * BitNodeMultipliers.InfiltrationMoney;
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 $" +
formatNumber(moneyValue, 2) + " on the black market or you can give it " + formatNumber(moneyValue, 2) + " on the black market or you can give it " +