diff --git a/css/popupboxes.css b/css/popupboxes.css index 9a6ce8843..708102496 100644 --- a/css/popupboxes.css +++ b/css/popupboxes.css @@ -296,4 +296,8 @@ color: white; text-decoration: none; cursor: pointer; +} + +#import-game-file-selector { + display:none; } \ No newline at end of file diff --git a/index.html b/index.html index 5067e3572..d2c40cd7f 100644 --- a/index.html +++ b/index.html @@ -749,6 +749,9 @@
Changelog Save Game + (BETA) Export Game + + (BETA) Import Game Delete Game (DEBUG) Delete Active Scripts diff --git a/src/Constants.js b/src/Constants.js index 538b41c93..fb63dd449 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -1,5 +1,5 @@ CONSTANTS = { - Version: "0.20.0", + Version: "0.20.1", //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 @@ -535,6 +535,13 @@ CONSTANTS = { "RAM Upgrades on your home computer", Changelog: + "v0.20.1
" + + "-Fixed bug where sometimes scripts would crash without showing the error
" + + "-Added Deepscan programs to Dark Web
" + + "-Declining a faction invite will stop you from receiving invitations from that faction for the rest of the run
" + + "-(BETA) Added functionality to export/import saves. WARNING This is only lightly tested. You cannot choose where to save your file " + + "it just goes to the default save location. Also I have no idea what will happen if you try to import a file " + + "that is not a valid save. I will address these in later updates

" + "v0.20.0
" + "-Refactored Netscript Interpreter code. Operations in Netscript should now run significantly faster (Every operation " + "such as a variable assignment, a function call, a binary operator, getting a variable's value, etc. used to take up to several seconds, " + @@ -645,6 +652,13 @@ CONSTANTS = { "-You can now see what an Augmentation does and its price even while its locked

", LatestUpdate: + "v0.20.1
" + + "-Fixed bug where sometimes scripts would crash without showing the error
" + + "-Added Deepscan programs to Dark Web
" + + "-Declining a faction invite will stop you from receiving invitations from that faction for the rest of the run
" + + "-(BETA) Added functionality to export/import saves. WARNING This is only lightly tested. You cannot choose where to save your file " + + "it just goes to the default save location. Also I have no idea what will happen if you try to import a file " + + "that is not a valid save. I will address these in later updates

" + "v0.20.0
" + "-Refactored Netscript Interpreter code. Operations in Netscript should now run significantly faster (Every operation " + "such as a variable assignment, a function call, a binary operator, getting a variable's value, etc. used to take up to several seconds, " + diff --git a/src/DarkWeb.js b/src/DarkWeb.js index 6d0299f0c..9c3bfd377 100644 --- a/src/DarkWeb.js +++ b/src/DarkWeb.js @@ -47,7 +47,7 @@ listAllDarkwebItems = function() { } buyDarkwebItem = function(itemName) { - if (itemName.toLowerCase() == "brutessh.exe") { + if (itemName.toLowerCase() == Programs.BruteSSHProgram.toLowerCase()) { var price = parseDarkwebItemPrice(DarkWebItems.BruteSSHProgram); if (price > 0 && Player.money >= price) { Player.loseMoney(price); @@ -57,7 +57,7 @@ buyDarkwebItem = function(itemName) { } else { post("Not enough money to purchase " + itemName); } - } else if (itemName.toLowerCase() == "ftpcrack.exe") { + } else if (itemName.toLowerCase() == Programs.FTPCrackProgram.toLowerCase()) { var price = parseDarkwebItemPrice(DarkWebItems.FTPCrackProgram); if (price > 0 && Player.money >= price) { Player.loseMoney(price); @@ -67,7 +67,7 @@ buyDarkwebItem = function(itemName) { } else { post("Not enough money to purchase " + itemName); } - } else if (itemName.toLowerCase() == "relaysmtp.exe") { + } else if (itemName.toLowerCase() == Programs.RelaySMTPProgram.toLowerCase()) { var price = parseDarkwebItemPrice(DarkWebItems.RelaySMTPProgram); if (price > 0 && Player.money >= price) { Player.loseMoney(price); @@ -77,7 +77,7 @@ buyDarkwebItem = function(itemName) { } else { post("Not enough money to purchase " + itemName); } - } else if (itemName.toLowerCase() == "httpworm.exe") { + } else if (itemName.toLowerCase() == Programs.HTTPWormProgram.toLowerCase()) { var price = parseDarkwebItemPrice(DarkWebItems.HTTPWormProgram); if (price > 0 && Player.money >= price) { Player.loseMoney(price); @@ -87,7 +87,7 @@ buyDarkwebItem = function(itemName) { } else { post("Not enough money to purchase " + itemName); } - } else if (itemName.toLowerCase() == "sqlinject.exe") { + } else if (itemName.toLowerCase() == Programs.SQLInjectProgram.toLowerCase()) { var price = parseDarkwebItemPrice(DarkWebItems.SQLInjectProgram); if (price > 0 && Player.money >= price) { Player.loseMoney(price); @@ -97,6 +97,26 @@ buyDarkwebItem = function(itemName) { } else { post("Not enough money to purchase " + itemName); } + } else if (itemName.toLowerCase() == Programs.DeepscanV1.toLowerCase()) { + var price = parseDarkwebItemPrice(DarkWebItems.DeepScanV1Program); + if (price > 0 && Player.money >= price) { + Player.loseMoney(price); + Player.getHomeComputer().programs.push(Programs.DeepscanV1); + post("You have purchased the DeepscanV1.exe program. The new program " + + "can be found on your home computer."); + } else { + post("Not enough money to purchase " + itemName); + } + } else if (itemName.toLowerCase() == Programs.DeepscanV2.toLowerCase()) { + var price = parseDarkwebItemPrice(DarkWebItems.DeepScanV2Program); + if (price > 0 && Player.money >= price) { + Player.loseMoney(price); + Player.getHomeComputer().programs.push(Programs.DeepscanV2); + post("You have purchased the DeepscanV2.exe program. The new program " + + "can be found on your home computer."); + } else { + post("Not enough money to purchase " + itemName); + } } else { post("Unrecognized item"); } @@ -129,4 +149,6 @@ DarkWebItems = { RelaySMTPProgram: Programs.RelaySMTPProgram + " - $5,000,000 - Opens up SMTP Ports", HTTPWormProgram: Programs.HTTPWormProgram + " - $30,000,000 - Opens up HTTP Ports", SQLInjectProgram: Programs.SQLInjectProgram + " - $250,000,000 - Opens up SQL Ports", + DeepScanV1Program: Programs.DeepscanV1 + " - $500,000 - Enables 'scan-analyze' with a depth up to 5", + DeepScanV2Program: Programs.DeepscanV2 + " - $25,000,000 - Enables 'scan-analyze' with a depth up to 10", } \ No newline at end of file diff --git a/src/Faction.js b/src/Faction.js index 2dbe9f982..30d9a6f7e 100644 --- a/src/Faction.js +++ b/src/Faction.js @@ -25,6 +25,7 @@ function Faction(name) { this.isMember = false; //Whether player is member this.isBanned = false; //Whether or not player is banned from joining this faction this.playerReputation = 0; //"Reputation" within faction + this.alreadyInvited = false; //Multipliers for unlocking and purchasing augmentations this.augmentationPriceMult = 1; @@ -188,7 +189,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //Illuminati var illuminatiFac = Factions["Illuminati"]; - if (illuminatiFac.isBanned == false && illuminatiFac.isMember == false && + if (!illuminatiFac.isBanned && !illuminatiFac.isMember && !illuminatiFac.alreadyInvited && this.numAugmentations >= 10 && this.money >= 10000000000 && this.total_money >= 20000000000 && this.hacking_skill >= 800 && this.total_hacking >= 7000 && @@ -201,7 +202,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //Daedalus var daedalusFac = Factions["Daedalus"]; - if (daedalusFac.isBanned == false && daedalusFac.isMember == false && + if (!daedalusFac.isBanned && !daedalusFac.isMember && !daedalusFac.alreadyInvited && this.numAugmentations >= 15 && this.money >= 1000000000 && this.total_money >= 10000000000 && this.hacking_skill >= 1000 && this.total_hacking >= 10000 && @@ -214,7 +215,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //The Covenant var covenantFac = Factions["The Covenant"]; - if (covenantFac.isBanned == false && covenantFac.isMember == false && + if (!covenantFac.isBanned && !covenantFac.isMember && !covenantFac.alreadyInvited && this.numAugmentations >= 12 && this.money >= 5000000000 && this.total_money >= 10000000000 && this.hacking_skill >= 850 && this.total_hack >= 5000 && @@ -227,63 +228,65 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //ECorp var ecorpFac = Factions["ECorp"]; - if (ecorpFac.isBanned == false && ecorpFac.isMember == false && + if (!ecorpFac.isBanned && !ecorpFac.isMember && !ecorpFac.alreadyInvited && this.companyName == Locations.AevumECorp && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(ecorpFac); } //MegaCorp var megacorpFac = Factions["MegaCorp"]; - if (megacorpFac.isBanned == false && megacorpFac.isMember == false && + if (!megacorpFac.isBanned && !megacorpFac.isMember && !megacorpFac.alreadyInvited && this.companyName == Locations.Sector12MegaCorp && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(megacorpFac); } //Bachman & Associates var bachmanandassociatesFac = Factions["Bachman & Associates"]; - if (bachmanandassociatesFac.isBanned == false && bachmanandassociatesFac.isMember == false && + if (!bachmanandassociatesFac.isBanned && !bachmanandassociatesFac.isMember && + !bachmanandassociatesFac.alreadyInvited && this.companyName == Locations.AevumBachmanAndAssociates && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(bachmanandassociatesFac); } //Blade Industries var bladeindustriesFac = Factions["Blade Industries"]; - if (bladeindustriesFac.isBanned == false && bladeindustriesFac.isMember == false && + if (!bladeindustriesFac.isBanned && !bladeindustriesFac.isMember && !bladeindustriesFac.alreadyInvited && this.companyName == Locations.Sector12BladeIndustries && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(bladeindustriesFac); } //NWO var nwoFac = Factions["NWO"]; - if (nwoFac.isBanned == false && nwoFac.isMember == false && + if (!nwoFac.isBanned && !nwoFac.isMember && !nwoFac.alreadyInvited && this.companyName == Locations.VolhavenNWO && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(nwoFac); } //Clarke Incorporated var clarkeincorporatedFac = Factions["Clarke Incorporated"]; - if (clarkeincorporatedFac.isBanned == false && clarkeincorporatedFac.isMember == false && + if (!clarkeincorporatedFac.isBanned && !clarkeincorporatedFac.isMember && !clarkeincorporatedFac.alreadyInvited && this.companyName == Locations.AevumClarkeIncorporated && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(clarkeincorporatedFac); } //OmniTek Incorporated var omnitekincorporatedFac = Factions["OmniTek Incorporated"]; - if (omnitekincorporatedFac.isBanned == false && omnitekincorporatedFac.isMember == false && + if (!omnitekincorporatedFac.isBanned && !omnitekincorporatedFac.isMember && !omnitekincorporatedFac.alreadyInvited && this.companyName == Locations.VolhavenOmniTekIncorporated && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(omnitekincorporatedFac); } //Four Sigma var foursigmaFac = Factions["Four Sigma"]; - if (foursigmaFac.isBanned == false && foursigmaFac.isMember == false && + if (!foursigmaFac.isBanned && !foursigmaFac.isMember && !foursigmaFac.alreadyInvited && this.companyName == Locations.Sector12FourSigma && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(foursigmaFac); } //KuaiGong International var kuaigonginternationalFac = Factions["KuaiGong International"]; - if (kuaigonginternationalFac.isBanned == false && kuaigonginternationalFac.isMember == false && + if (!kuaigonginternationalFac.isBanned && !kuaigonginternationalFac.isMember && + !kuaigonginternationalFac.alreadyInvited && this.companyName == Locations.ChongqingKuaiGongInternational && companyRep >= CONSTANTS.CorpFactionRepRequirement) { invitedFactions.push(kuaigonginternationalFac); } @@ -294,7 +297,8 @@ PlayerObject.prototype.checkForFactionInvitations = function() { if (fulcrumSecretServer == null) { console.log("ERROR: Could not find Fulcrum Secret Technologies Server"); } else { - if (fulcrumsecrettechonologiesFac.isBanned == false && fulcrumsecrettechonologiesFac.isMember == false && + if (!fulcrumsecrettechonologiesFac.isBanned && !fulcrumsecrettechonologiesFac.isMember && + !fulcrumsecrettechonologiesFac.alreadyInvited && fulcrumSecretServer.manuallyHacked && this.companyName == Locations.AevumFulcrumTechnologies && companyRep >= 250000) { invitedFactions.push(fulcrumsecrettechonologiesFac); @@ -307,8 +311,8 @@ PlayerObject.prototype.checkForFactionInvitations = function() { var bitrunnersServer = AllServers[SpecialServerIps[SpecialServerNames.BitRunnersServer]]; if (bitrunnersServer == null) { console.log("ERROR: Could not find BitRunners Server"); - } else if (bitrunnersFac.isBanned == false && bitrunnersFac.isMember == false && bitrunnersServer.manuallyHacked && - this.hacking_skill >= 500 && homeComp.maxRam >= 128) { + } else if (!bitrunnersFac.isBanned && !bitrunnersFac.isMember && bitrunnersServer.manuallyHacked && + !bitrunnersFac.alreadyInvited && this.hacking_skill >= 500 && homeComp.maxRam >= 128) { invitedFactions.push(bitrunnersFac); } @@ -318,7 +322,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { if (blackhandServer == null) { console.log("ERROR: Could not find The Black Hand Server"); } else if (!theblackhandFac.isBanned && !theblackhandFac.isMember && blackhandServer.manuallyHacked && - this.hacking_skill >= 350 && homeComp.maxRam >= 64) { + !theblackhandFac.alreadyInvited && this.hacking_skill >= 350 && homeComp.maxRam >= 64) { invitedFactions.push(theblackhandFac); } @@ -328,55 +332,55 @@ PlayerObject.prototype.checkForFactionInvitations = function() { if (nitesecServer == null) { console.log("ERROR: Could not find NiteSec Server"); } else if (!nitesecFac.isBanned && !nitesecFac.isMember && nitesecServer.manuallyHacked && - this.hacking_skill >= 200 && homeComp.maxRam >= 32) { + !nitesecFac.alreadyInvited && this.hacking_skill >= 200 && homeComp.maxRam >= 32) { invitedFactions.push(nitesecFac); } //Chongqing var chongqingFac = Factions["Chongqing"]; - if (chongqingFac.isBanned == false && chongqingFac.isMember == false && + if (!chongqingFac.isBanned && !chongqingFac.isMember && !chongqingFac.alreadyInvited && this.money >= 20000000 && this.city == Locations.Chongqing) { invitedFactions.push(chongqingFac); } //Sector-12 var sector12Fac = Factions["Sector-12"]; - if (sector12Fac.isBanned == false && sector12Fac.isMember == false && + if (!sector12Fac.isBanned && !sector12Fac.isMember && !sector12Fac.alreadyInvited && this.money >= 15000000 && this.city == Locations.Sector12) { invitedFactions.push(sector12Fac); } //New Tokyo var newtokyoFac = Factions["New Tokyo"]; - if (newtokyoFac.isBanned == false && newtokyoFac.isMember == false && + if (!newtokyoFac.isBanned && !newtokyoFac.isMember && !newtokyoFac.alreadyInvited && this.money >= 20000000 && this.city == Locations.NewTokyo) { invitedFactions.push(newtokyoFac); } //Aevum var aevumFac = Factions["Aevum"]; - if (aevumFac.isBanned == false && aevumFac.isMember == false && + if (!aevumFac.isBanned && !aevumFac.isMember && !aevumFac.alreadyInvited && this.money >= 40000000 && this.city == Locations.Aevum) { invitedFactions.push(aevumFac); } //Ishima var ishimaFac = Factions["Ishima"]; - if (ishimaFac.isBanned == false && ishimaFac.isMember == false && + if (!ishimaFac.isBanned && !ishimaFac.isMember && !ishimaFac.alreadyInvited && this.money >= 30000000 && this.city == Locations.Ishima) { invitedFactions.push(ishimaFac); } //Volhaven var volhavenFac = Factions["Volhaven"]; - if (volhavenFac.isBanned == false && volhavenFac.isMember == false && + if (!volhavenFac.isBanned && !volhavenFac.isMember && !volhavenFac.alreadyInvited && this.money >= 50000000 && this.city == Locations.Volhaven) { invitedFactions.push(volhavenFac); } //Speakers for the Dead var speakersforthedeadFac = Factions["Speakers for the Dead"]; - if (speakersforthedeadFac.isBanned == false && speakersforthedeadFac.isMember == false && + if (!speakersforthedeadFac.isBanned && !speakersforthedeadFac.isMember && !speakersforthedeadFac.alreadyInvited && this.hacking_skill >= 100 && this.strength >= 300 && this.defense >= 300 && this.dexterity >= 300 && this.agility >= 300 && this.numPeopleKilled >= 10 && this.numPeopleKilledTotal >= 100 && this.karma <= -45 && this.companyName != Locations.Sector12CIA && @@ -386,7 +390,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //The Dark Army var thedarkarmyFac = Factions["The Dark Army"]; - if (thedarkarmyFac.isBanned == false && thedarkarmyFac.isMember == false && + if (!thedarkarmyFac.isBanned && !thedarkarmyFac.isMember && !thedarkarmyFac.alreadyInvited && this.hacking_skill >= 300 && this.strength >= 300 && this.defense >= 300 && this.dexterity >= 300 && this.agility >= 300 && this.city == Locations.Chongqing && this.numPeopleKilled >= 5 && this.karma <= -45 && this.companyName != Locations.Sector12CIA && @@ -396,7 +400,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //The Syndicate var thesyndicateFac = Factions["The Syndicate"]; - if (thesyndicateFac.isBanned == false && thesyndicateFac.isMember == false && + if (!thesyndicateFac.isBanned && !thesyndicateFac.isMember && !thesyndicateFac.alreadyInvited && this.hacking_skill >= 200 && this.strength >= 200 && this.defense >= 200 && this.dexterity >= 200 && this.agility >= 200 && (this.city == Locations.Aevum || this.city == Locations.Sector12) && @@ -407,7 +411,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //Silhouette var silhouetteFac = Factions["Silhouette"]; - if (silhouetteFac.isBanned == false && silhouetteFac.isMember == false && + if (!silhouetteFac.isBanned && !silhouetteFac.isMember && !silhouetteFac.alreadyInvited && (this.companyPosition.positionName == CompanyPositions.CTO.positionName || this.companyPosition.positionName == CompanyPositions.CFO.positionName || this.companyPosition.positionName == CompanyPositions.CEO.positionName) && @@ -417,7 +421,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //Tetrads var tetradsFac = Factions["Tetrads"]; - if (tetradsFac.isBanned == false && tetradsFac.isMember == false && + if (!tetradsFac.isBanned && !tetradsFac.isMember && !tetradsFac.alreadyInvited && (this.city == Locations.Chongqing || this.city == Locations.NewTokyo || this.city == Locations.Ishima) && this.strength >= 75 && this.defense >= 75 && this.dexterity >= 75 && this.agility >= 75 && this.karma <= -18) { @@ -426,7 +430,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //SlumSnakes var slumsnakesFac = Factions["Slum Snakes"]; - if (slumsnakesFac.isBanned == false && slumsnakesFac.isMember == false && + if (!slumsnakesFac.isBanned && !slumsnakesFac.isMember && !slumsnakesFac.alreadyInvited && this.strength >= 30 && this.defense >= 30 && this.dexterity >= 30 && this.agility >= 30 && this.karma <= -9 && this.money >= 1000000) { invitedFactions.push(slumsnakesFac); @@ -442,7 +446,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { totalHacknetRam += Player.hacknetNodes[i].ram; totalHacknetCores += Player.hacknetNodes[i].numCores; } - if (netburnersFac.isBanned == false && netburnersFac.isMember == false && + if (!netburnersFac.isBanned && !netburnersFac.isMember && !netburnersFac.alreadyInvited && this.hacking_skill >= 80 && totalHacknetRam >= 8 && totalHacknetCores >= 4 && totalHacknetLevels >= 100) { invitedFactions.push(netburnersFac); @@ -450,7 +454,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() { //Tian Di Hui var tiandihuiFac = Factions["Tian Di Hui"]; - if (tiandihuiFac.isBanned == false && tiandihuiFac.isMember == false && + if (!tiandihuiFac.isBanned && !tiandihuiFac.isMember && !tiandihuiFac.alreadyInvited && this.money >= 1000000 && this.hacking_skill >= 50 && (this.city == Locations.Chongqing || this.city == Locations.NewTokyo || this.city == Locations.Ishima)) { @@ -463,18 +467,14 @@ PlayerObject.prototype.checkForFactionInvitations = function() { if (cybersecServer == null) { console.log("ERROR: Could not find CyberSec Server"); } else if (!cybersecFac.isBanned && !cybersecFac.isMember && cybersecServer.manuallyHacked && - this.hacking_skill >= 50) { + !cybersecFac.alreadyInvited && this.hacking_skill >= 50) { invitedFactions.push(cybersecFac); } - console.log("invited factions: " + invitedFactions); return invitedFactions; } inviteToFaction = function(faction) { - if (Engine.Debug) { - console.log("inviteToFaction() called with faction: " + faction.name); - } factionInvitationBoxCreate(faction); } diff --git a/src/Message.js b/src/Message.js index 64c1fa533..0adbd7dee 100644 --- a/src/Message.js +++ b/src/Message.js @@ -71,7 +71,7 @@ function checkForMessagesToSend() { sendMessage(bitrunnersTest); } if (jumper5 && !jumper5.recvd && Player.hacking_skill >= 900) { sendMessage(jumper5); - Player.getHomeComputer.programs.push(Programs.Flight); + Player.getHomeComputer().programs.push(Programs.Flight); } } diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index d478a4240..6b0304be3 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -104,8 +104,14 @@ function evaluate(exp, workerScript) { evaluateProgPromise.then(function(w) { resolve(workerScript); }, function(e) { - workerScript.errorMessage = e.toString(); - reject(workerScript); + if (typeof e === 'string' || e instanceof String) { + workerScript.errorMessage = e; + reject(workerScript); + } else if (e instanceof WorkerScript) { + reject(e); + } else { + reject(workerScript); + } }); break; case "call": diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 9f13539b5..8af360425 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -212,7 +212,7 @@ function netscriptRunProgram(exp, workerScript, programName) { var env = workerScript.env; if (env.stopFlag) {return Promise.reject(workerScript);} if (exp.args.length != 1) { - return Promise.reject(makeRuntimeRejectMsg(workerScript, "nuke() call has incorrect number of arguments. Takes 1 argument")); + return Promise.reject(makeRuntimeRejectMsg(workerScript, "Program call has incorrect number of arguments. Takes 1 argument")); } var ipPromise = evaluate(exp.args[0], workerScript); return ipPromise.then(function(ip) { diff --git a/src/SaveObject.js b/src/SaveObject.js index 7bc88c30b..1cdf2b6f1 100644 --- a/src/SaveObject.js +++ b/src/SaveObject.js @@ -81,6 +81,176 @@ loadGame = function(saveObj) { return true; } +loadImportedGame = function(saveObj, saveString) { + var tempSaveObj = null; + var tempPlayer = null; + var tempAllServers = null; + var tempCompanies = null; + var tempFactions = null; + var tempSpecialServerIps = null; + var tempAugmentations = null; + var tempAliases = null; + var tempMessages = null; + try { + saveString = decodeURIComponent(escape(atob(saveString))); + tempSaveObj = new BitburnerSaveObject(); + tempSaveObj = JSON.parse(saveString, Reviver); + + tempPlayer = JSON.parse(tempSaveObj.PlayerSave, Reviver); + tempAllServers = JSON.parse(tempSaveObj.AllServersSave, Reviver); + tempCompanies = JSON.parse(tempSaveObj.CompaniesSave, Reviver); + tempFactions = JSON.parse(tempSaveObj.FactionsSave, Reviver); + tempSpecialServerIps = JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver); + tempAugmentations = JSON.parse(tempSaveObj.AugmentationsSave, Reviver); + if (tempSaveObj.hasOwnProperty("AliasesSave")) { + try { + tempAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver); + } catch(e) { + tempAliases = {}; + } + } else { + tempAliases = {}; + } + if (tempSaveObj.hasOwnProperty("MessagesSave")) { + try { + tempMessages = JSON.parse(tempSaveObj.MessagesSave, Reviver); + } catch(e) { + initMessages(); + } + } else { + initMessages(); + } + if (tempSaveObj.hasOwnProperty("VersionSave")) { + try { + var ver = JSON.parse(tempSaveObj.VersionSave, Reviver); + if (ver != CONSTANTS.Version) { + createNewUpdateText(); + } + } catch(e) { + createNewUpdateText(); + } + } else { + createNewUpdateText(); + } + } catch(e) { + dialogBoxCreate("Error importing game"); + return false; + } + + saveObj = tempSaveObj; + Player = tempPlayer; + AllServers = tempAllServers; + Companies = tempCompanies; + Factions = tempFactions; + SpecialServerIps = tempSpecialServerIps; + Augmentations = tempAugmentations; + if (tempAliases) { + Aliases = tempAliases; + } + + if (tempMessages) { + Messages = tempMessages; + } + + dialogBoxCreate("Imported game"); + gameOptionsBoxClose(); + + //Re-start game + console.log("Importing game"); + Engine.setDisplayElements(); //Sets variables for important DOM elements + Engine.init(); //Initialize buttons, work, etc. + CompanyPositions.init(); + + //Calculate the number of cycles have elapsed while offline + Engine._lastUpdate = new Date().getTime(); + var lastUpdate = Player.lastUpdate; + var numCyclesOffline = Math.floor((Engine._lastUpdate - lastUpdate) / Engine._idleSpeed); + + /* Process offline progress */ + var offlineProductionFromScripts = loadAllRunningScripts(); //This also takes care of offline production for those scripts + if (Player.isWorking) { + console.log("work() called in load() for " + numCyclesOffline * Engine._idleSpeed + " milliseconds"); + if (Player.workType == CONSTANTS.WorkTypeFaction) { + Player.workForFaction(numCyclesOffline); + } else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) { + Player.createProgramWork(numCyclesOffline); + } else if (Player.workType == CONSTANTS.WorkTypeStudyClass) { + Player.takeClass(numCyclesOffline); + } else if (Player.workType == CONSTANTS.WorkTypeCrime) { + Player.commitCrime(numCyclesOffline); + } else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) { + Player.workPartTime(numCyclesOffline); + } else { + Player.work(numCyclesOffline); + } + } + + //Hacknet Nodes offline progress + var offlineProductionFromHacknetNodes = processAllHacknetNodeEarnings(numCyclesOffline); + + //Passive faction rep gain offline + processPassiveFactionRepGain(numCyclesOffline); + + //Update total playtime + var time = numCyclesOffline * Engine._idleSpeed; + if (Player.totalPlaytime == null) {Player.totalPlaytime = 0;} + Player.totalPlaytime += time; + + //Re-apply augmentations + Player.reapplyAllAugmentations(); + + //Clear terminal + $("#terminal tr:not(:last)").remove(); + + Player.lastUpdate = Engine._lastUpdate; + Engine.start(); //Run main game loop and Scripts loop + dialogBoxCreate("While you were offline, your scripts generated $" + + formatNumber(offlineProductionFromScripts, 2) + " and your Hacknet Nodes generated $" + + formatNumber(offlineProductionFromHacknetNodes, 2)); + return true; +} + +BitburnerSaveObject.prototype.exportGame = function() { + this.PlayerSave = JSON.stringify(Player); + this.AllServersSave = JSON.stringify(AllServers); + this.CompaniesSave = JSON.stringify(Companies); + this.FactionsSave = JSON.stringify(Factions); + this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps); + this.AugmentationsSave = JSON.stringify(Augmentations); + this.AliasesSave = JSON.stringify(Aliases); + this.MessagesSave = JSON.stringify(Messages); + this.VersionSave = JSON.stringify(CONSTANTS.Version); + + var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this)))); + + var file = new Blob([saveString], {type: 'text/plain'}); + if (window.navigator.msSaveOrOpenBlob) {// IE10+ + window.navigator.msSaveOrOpenBlob(file, filename); + } else { // Others + var a = document.createElement("a"), + url = URL.createObjectURL(file); + a.href = url; + a.download = "bitburnerSave.json"; + document.body.appendChild(a); + a.click(); + setTimeout(function() { + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + }, 0); + } +} + +BitburnerSaveObject.prototype.importGame = function() { + if (window.File && window.FileReader && window.FileList && window.Blob) { + var fileSelector = clearEventListeners("import-game-file-selector"); + fileSelector.addEventListener("change", openImportFileHandler, false); + $("#import-game-file-selector").click(); + } else { + dialogBoxCreate("ERR: Your browser does not support HTML5 File API. Cannot import."); + } + +} + BitburnerSaveObject.prototype.deleteGame = function() { if (window.localStorage.getItem("bitburnerSave")) { window.localStorage.removeItem("bitburnerSave"); @@ -104,4 +274,21 @@ BitburnerSaveObject.fromJSON = function(value) { return Generic_fromJSON(BitburnerSaveObject, value.data); } -Reviver.constructors.BitburnerSaveObject = BitburnerSaveObject; \ No newline at end of file +Reviver.constructors.BitburnerSaveObject = BitburnerSaveObject; + +//Import game + +function openImportFileHandler(evt) { + var file = evt.target.files[0]; + if (!file) { + dialogBoxCreate("Invalid file selected"); + return; + } + + var reader = new FileReader(); + reader.onload = function(e) { + var contents = e.target.result; + loadImportedGame(saveObject, contents); + }; + reader.readAsText(file); +} \ No newline at end of file diff --git a/src/Server.js b/src/Server.js index a072fa058..5cc514a75 100644 --- a/src/Server.js +++ b/src/Server.js @@ -37,6 +37,8 @@ function Server() { //Parameters used in formulas that dictate how moneyAvailable and requiredHackingSkill change. this.hackDifficulty = 1; //Affects hack success rate and how the requiredHackingSkill increases over time (1-100) + this.baseDifficulty = 1; //Starting difficulty + this.minDifficulty = 1; this.serverGrowth = 0; //Affects how the moneyAvailable increases (0-100) this.timesHacked = 0; @@ -80,6 +82,8 @@ Server.prototype.setHackingParameters = function(requiredHackingSkill, moneyAvai this.moneyAvailable = moneyAvailable; this.moneyMax = 50 * moneyAvailable; this.hackDifficulty = hackDifficulty; + this.baseDifficulty = hackDifficulty; + this.minDifficulty = Math.max(1, hackDifficulty - 25); this.serverGrowth = serverGrowth; } diff --git a/src/engine.js b/src/engine.js index f96c399eb..c92d5865d 100644 --- a/src/engine.js +++ b/src/engine.js @@ -890,7 +890,7 @@ var Engine = { //Active scripts list Engine.ActiveScriptsList = document.getElementById("active-scripts-list"); - //Save and Delete buttons + //Save, Delete, Import/Export buttons Engine.Clickables.saveMainMenuButton = document.getElementById("save-game-link"); Engine.Clickables.saveMainMenuButton.addEventListener("click", function() { saveObject.saveGame(); @@ -903,6 +903,11 @@ var Engine = { return false; }); + document.getElementById("export-game-link").addEventListener("click", function() { + saveObject.exportGame(); + return false; + }); + //Character Overview Save button var charOverviewSaveButton = document.getElementById("character-overview-save-button"); charOverviewSaveButton.addEventListener("click", function() { @@ -1011,6 +1016,7 @@ var Engine = { console.log("Deleting running scripts on home computer"); Player.getHomeComputer().runningScripts = []; dialogBoxCreate("Forcefully deleted all running scripts on home computer. Please save and refresh page"); + gameOptionsBoxClose(); return false; }); @@ -1018,6 +1024,7 @@ var Engine = { document.getElementById("debug-soft-reset").addEventListener("click", function() { dialogBoxCreate("Soft Reset!"); prestigeAugmentation(); + gameOptionsBoxClose(); return false; }); }, diff --git a/utils/FactionInvitationBox.js b/utils/FactionInvitationBox.js index e32a64ccf..2c7912969 100644 --- a/utils/FactionInvitationBox.js +++ b/utils/FactionInvitationBox.js @@ -1,16 +1,4 @@ /* Faction Invitation Pop-up box */ -function factionInvitationBoxInit() { - var cancelButton = document.getElementById("faction-invitation-box-no"); - - //Close Dialog box - cancelButton.addEventListener("click", function() { - factionInvitationBoxClose(); - return false; - }); -}; - -document.addEventListener("DOMContentLoaded", factionInvitationBoxInit, false); - factionInvitationBoxClose = function() { var factionInvitationBox = document.getElementById("faction-invitation-box-container"); factionInvitationBox.style.display = "none"; @@ -37,15 +25,18 @@ factionInvitationBoxCreate = function(faction) { //TODO Faction invitation message var newYesButton = clearEventListeners("faction-invitation-box-yes"); - //var yesButton = document.getElementById("faction-invitation-box-yes"); - //var newYesButton = yesButton.cloneNode(true); - //yesButton.parentNode.replaceChild(newYesButton, yesButton); - newYesButton.addEventListener("click", function() { joinFaction(faction); factionInvitationBoxClose(); return false; }); + var noButton = clearEventListeners("faction-invitation-box-no"); + noButton.addEventListener("click", function() { + factionInvitationBoxClose(); + faction.alreadyInvited = true; + return false; + }); + factionInvitationBoxOpen(); } \ No newline at end of file