From 0e64359814c4f27ca4087239243be5d10314a1fa Mon Sep 17 00:00:00 2001 From: danielyxie Date: Wed, 26 Jul 2017 21:56:14 -0500 Subject: [PATCH] Lowered hacking exp gain. Added deleteServer(). Maximum of 25 purchaseable servers. Added autocompletion for ./ command. Oustanding faction invitations. Suppress Faction invites and messages --- index.html | 34 ++- src/Constants.js | 19 +- src/DarkWeb.js | 54 +++- src/Faction.js | 7 +- src/Message.js | 70 ++--- src/NetscriptEvaluator.js | 194 ++----------- src/NetscriptFunctions.js | 56 ++++ src/NetscriptWorker.js | 42 +-- src/Player.js | 518 +++++++++++++++++----------------- src/Prestige.js | 81 +++--- src/Script.js | 17 +- src/ServerPurchases.js | 32 ++- src/Settings.js | 10 +- src/Terminal.js | 24 +- src/engine.js | 52 +++- utils/FactionInvitationBox.js | 9 +- 16 files changed, 644 insertions(+), 575 deletions(-) diff --git a/index.html b/index.html index 81b29d3f4..f177f0c85 100644 --- a/index.html +++ b/index.html @@ -502,6 +502,11 @@

Factions

Lists all factions you have joined

+

+

Outstanding Faction Invitations

+

Lists factions you have been invited to, as well as factions you have previously rejected. + You can accept these faction invitations at any times

+ @@ -928,7 +933,7 @@ - @@ -946,7 +951,7 @@ - @@ -954,6 +959,31 @@ + +
+ + +
+ + +
+ + +
+
diff --git a/src/Constants.js b/src/Constants.js index 47a51f977..79591edae 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -61,9 +61,7 @@ CONSTANTS = { ScriptHasRootAccessRamCost: 0.05, ScriptGetHostnameRamCost: 0.05, ScriptGetHackingLevelRamCost: 0.05, - ScriptGetServerMoneyRamCost: 0.1, - ScriptGetServerSecurityRamCost: 0.1, - ScriptGetServerReqdHackRamCost: 0.1, + ScriptGetServerCost: 0.1, ScriptFileExistsRamCost: 0.1, ScriptIsRunningRamCost: 0.1, ScriptOperatorRamCost: 0.01, @@ -86,6 +84,8 @@ CONSTANTS = { ServerFortifyAmount: 0.002, //Amount by which server's security increases when its hacked/grown ServerWeakenAmount: 0.05, //Amount by which server's security decreases when weakened + PurchasedServerLimit: 25, + //Augmentation Constants AugmentationCostMultiplier: 5, //Used for balancing costs without having to readjust every Augmentation cost AugmentationRepMultiplier: 2.5, //Used for balancing rep cost without having to readjust every value @@ -678,7 +678,18 @@ CONSTANTS = { "World Stock Exchange account and TIX API Access
", LatestUpdate: - "V0.26.1
" + + "v0.26.2
" + + "-Significantly lowered hacking exp gain from hacking servers. The exp gain for higher-level servers was lowered more than " + + "that of low level servers. (~16% for lower level servers, up to ~25% for higher-level servers)
" + + "-Added deleteServer() Netscript function
" + + "-You can now purchase a maximum of 25 servers each run (Deleting a server will allow you to purchase a new one)
" + + "-Added autocompletion for './' Terminal command
" + + "-Darkweb prices now displayed properly using toLocaleString()
" + + "-Added NOT operator (!) and negation operator(-), so negative numbers should be functional now
" + + "-Rejected faction invitations will now show up as 'Outstanding Faction Invites' in the Factions page. These " + + "can be accepted at any point in the future
" + + "-Added a few more configurable game settings for suppressing messages and faction invitations
" + + "v0.26.1
" + "-Added autocompletion for aliases
" + "-Added getServerRam() Netscript function()
" + "-Added getLevelUpgradeCost(n), getRamUpgradeCost(), getCoreUpgradeCost() functions for Netscript Hacknet Node API
" + diff --git a/src/DarkWeb.js b/src/DarkWeb.js index 9c3bfd377..25c574dd7 100644 --- a/src/DarkWeb.js +++ b/src/DarkWeb.js @@ -6,11 +6,11 @@ checkIfConnectedToDarkweb = function() { if (!isValidIPAddress(darkwebIp)) {return;} if (darkwebIp == Player.getCurrentServer().ip) { post("You are now connected to the dark web. From the dark web you can purchase illegal items. " + - "Use the 'buy -l' command to display a list of all the items you can buy. Use 'buy [item-name] " + + "Use the 'buy -l' command to display a list of all the items you can buy. Use 'buy [item-name] " + "to purchase an item"); } } - + } //Handler for dark web commands. The terminal's executeCommand() function will pass @@ -41,9 +41,39 @@ executeDarkwebTerminalCommand = function(commandArray) { listAllDarkwebItems = function() { for (var item in DarkWebItems) { if (DarkWebItems.hasOwnProperty(item)) { - post(DarkWebItems[item]); + var item = DarkWebItems[item]; + //Convert string using toLocaleString + var split = item.split(" - "); + if (split.length == 3 && split[1].charAt(0) == '$') { + split[1] = split[1].slice(1); + split[1] = split[1].replace(/,/g, ''); + var price = parseFloat(split[1]); + if (isNaN(price)) { + post(item); + return; + } + price = formatNumber(price, 0); + split[1] = "$" + price.toString(); + post(split.join(" - ")); + } else { + post(item); + } } } + + var priceString = split[1]; + //Check for errors + if (priceString.length == 0 || priceString.charAt(0) != '$') { + return -1; + } + //Remove dollar sign and commas + priceString = priceString.slice(1); + priceString = priceString.replace(/,/g, ''); + + //Convert string to numeric + var price = parseFloat(priceString); + if (isNaN(price)) {return -1;} + else {return price;} } buyDarkwebItem = function(itemName) { @@ -52,7 +82,7 @@ buyDarkwebItem = function(itemName) { if (price > 0 && Player.money >= price) { Player.loseMoney(price); Player.getHomeComputer().programs.push(Programs.BruteSSHProgram); - post("You have purchased the BruteSSH.exe program. The new program " + + post("You have purchased the BruteSSH.exe program. The new program " + "can be found on your home computer."); } else { post("Not enough money to purchase " + itemName); @@ -62,7 +92,7 @@ buyDarkwebItem = function(itemName) { if (price > 0 && Player.money >= price) { Player.loseMoney(price); Player.getHomeComputer().programs.push(Programs.FTPCrackProgram); - post("You have purchased the FTPCrack.exe program. The new program " + + post("You have purchased the FTPCrack.exe program. The new program " + "can be found on your home computer."); } else { post("Not enough money to purchase " + itemName); @@ -72,7 +102,7 @@ buyDarkwebItem = function(itemName) { if (price > 0 && Player.money >= price) { Player.loseMoney(price); Player.getHomeComputer().programs.push(Programs.RelaySMTPProgram); - post("You have purchased the relaySMTP.exe program. The new program " + + post("You have purchased the relaySMTP.exe program. The new program " + "can be found on your home computer."); } else { post("Not enough money to purchase " + itemName); @@ -82,7 +112,7 @@ buyDarkwebItem = function(itemName) { if (price > 0 && Player.money >= price) { Player.loseMoney(price); Player.getHomeComputer().programs.push(Programs.HTTPWormProgram); - post("You have purchased the HTTPWorm.exe program. The new program " + + post("You have purchased the HTTPWorm.exe program. The new program " + "can be found on your home computer."); } else { post("Not enough money to purchase " + itemName); @@ -92,7 +122,7 @@ buyDarkwebItem = function(itemName) { if (price > 0 && Player.money >= price) { Player.loseMoney(price); Player.getHomeComputer().programs.push(Programs.SQLInjectProgram); - post("You have purchased the SQLInject.exe program. The new program " + + post("You have purchased the SQLInject.exe program. The new program " + "can be found on your home computer."); } else { post("Not enough money to purchase " + itemName); @@ -102,7 +132,7 @@ buyDarkwebItem = function(itemName) { 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 " + + 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); @@ -112,7 +142,7 @@ buyDarkwebItem = function(itemName) { 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 " + + 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); @@ -133,7 +163,7 @@ parseDarkwebItemPrice = function(itemDesc) { //Remove dollar sign and commas priceString = priceString.slice(1); priceString = priceString.replace(/,/g, ''); - + //Convert string to numeric var price = parseFloat(priceString); if (isNaN(price)) {return -1;} @@ -151,4 +181,4 @@ DarkWebItems = { 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 c07041e91..af23322f3 100644 --- a/src/Faction.js +++ b/src/Faction.js @@ -630,7 +630,12 @@ PlayerObject.prototype.checkForFactionInvitations = function() { } inviteToFaction = function(faction) { - factionInvitationBoxCreate(faction); + if (Settings.SuppressFactionInvites) { + faction.alreadyInvited = true; + Player.factionInvitations.push(faction.name); + } else { + factionInvitationBoxCreate(faction); + } } joinFaction = function(faction) { diff --git a/src/Message.js b/src/Message.js index 3f8eb2c02..14732845d 100644 --- a/src/Message.js +++ b/src/Message.js @@ -20,13 +20,15 @@ Reviver.constructors.Message = Message; function sendMessage(msg) { console.log("sending message: " + msg.filename); msg.recvd = true; - showMessage(msg); + if (!Settings.SuppressMessages) { + showMessage(msg); + } addMessageToServer(msg, "home"); } function showMessage(msg) { - var txt = "Message received from unknown sender:

" + - "" + msg.msg + "

" + + var txt = "Message received from unknown sender:

" + + "" + msg.msg + "

" + "This message was saved as " + msg.filename + " onto your home computer."; dialogBoxCreate(txt); } @@ -53,7 +55,7 @@ function checkForMessagesToSend() { var nitesecTest = Messages[MessageFilenames.NiteSecTest]; var bitrunnersTest = Messages[MessageFilenames.BitRunnersTest]; var redpill = Messages[MessageFilenames.RedPill]; - + if (jumper0 && !jumper0.recvd && Player.hacking_skill >= 25) { sendMessage(jumper0); } else if (jumper1 && !jumper1.recvd && Player.hacking_skill >= 40) { @@ -100,61 +102,61 @@ MessageFilenames = { function initMessages() { //Reset Messages = {}; - + //jump3R Messages AddToAllMessages(new Message(MessageFilenames.Jumper0, - "I know you can sense it. I know you're searching for it. " + - "It's why you spend night after " + - "night at your computer.

It's real, I've seen it. And I can " + + "I know you can sense it. I know you're searching for it. " + + "It's why you spend night after " + + "night at your computer.

It's real, I've seen it. And I can " + "help you find it. But not right now. You're not ready yet.

-jump3R")); AddToAllMessages(new Message(MessageFilenames.Jumper1, "Soon you will be contacted by a hacking group known as CyberSec. " + "They can help you with your search.

" + - "You should join them, garner their favor, and " + - "exploit them for their Augmentations. But do not trust them. " + - "They are not what they seem. No one is.

" + + "You should join them, garner their favor, and " + + "exploit them for their Augmentations. But do not trust them. " + + "They are not what they seem. No one is.

" + "-jump3R")); AddToAllMessages(new Message(MessageFilenames.Jumper2, - "Do not try to save the world. There is no world to save. If " + - "you want to find the truth, worry only about yourself. Ethics and " + - "morals will get you killed.

Watch out for a hacking group known as NiteSec." + + "Do not try to save the world. There is no world to save. If " + + "you want to find the truth, worry only about yourself. Ethics and " + + "morals will get you killed.

Watch out for a hacking group known as NiteSec." + "

-jump3R")); AddToAllMessages(new Message(MessageFilenames.Jumper3, - "You must learn to walk before you can run. And you must " + - "run before you can fly. Look for the black hand.

" + + "You must learn to walk before you can run. And you must " + + "run before you can fly. Look for the black hand.

" + "I.I.I.I

-jump3R")); AddToAllMessages(new Message(MessageFilenames.Jumper4, - "To find what you are searching for, you must understand the bits. " + - "The bits are all around us. The runners will help you.

" + + "To find what you are searching for, you must understand the bits. " + + "The bits are all around us. The runners will help you.

" + "-jump3R")); AddToAllMessages(new Message(MessageFilenames.Jumper5, "Build your wings and fly

-jump3R

" + "The fl1ght.exe program was added to your home computer")); - + //Messages from hacking factions AddToAllMessages(new Message(MessageFilenames.CyberSecTest, "We've been watching you. Your skills are very impressive. But you're wasting " + "your talents. If you join us, you can put your skills to good use and change " + - "the world for the better. If you join us, we can unlock your full potential.

" + - "But first, you must pass our test. Find and hack our server using the Terminal.

" + + "the world for the better. If you join us, we can unlock your full potential.

" + + "But first, you must pass our test. Find and hack our server using the Terminal.

" + "-CyberSec")); AddToAllMessages(new Message(MessageFilenames.NiteSecTest, - "People say that the corrupted governments and corporations rule the world. " + - "Yes, maybe they do. But do you know who everyone really fears? People " + + "People say that the corrupted governments and corporations rule the world. " + + "Yes, maybe they do. But do you know who everyone really fears? People " + "like us. Because they can't hide from us. Because they can't fight shadows " + - "and ideas with bullets.

" + - "Join us, and people will fear you, too.

" + - "Find and hack our hidden server using the Terminal. Then, we will contact you again." + + "and ideas with bullets.

" + + "Join us, and people will fear you, too.

" + + "Find and hack our hidden server using the Terminal. Then, we will contact you again." + "

-NiteSec")); AddToAllMessages(new Message(MessageFilenames.BitRunnersTest, - "We know what you are doing. We know what drives you. We know " + - "what you are looking for.

" + - "We can help you find the answers.

" + + "We know what you are doing. We know what drives you. We know " + + "what you are looking for.

" + + "We can help you find the answers.

" + "run4theh111z")); - + AddToAllMessages(new Message(MessageFilenames.RedPill, - "@)(#V%*N)@(#*)*C)@#%*)*V)@#(*%V@)(#VN%*)@#(*%
" + - ")@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)
" + - "@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB
" + + "@)(#V%*N)@(#*)*C)@#%*)*V)@#(*%V@)(#VN%*)@#(*%
" + + ")@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)
" + + "@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB
" + "DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)")); -} \ No newline at end of file +} diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index f8cc5fba5..3462cafa2 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -131,6 +131,14 @@ function evaluate(exp, workerScript) { reject(e); }); break; + case "UnaryExpression": + var p = evalUnary(exp, workerScript, resolve, reject); + p.then(function(res) { + resolve(res); + }).catch(function(e) { + reject(e); + }); + break; case "AssignmentExpression": var p = evalAssignment(exp, workerScript); p.then(function(res) { @@ -210,58 +218,6 @@ function evaluate(exp, workerScript) { }); // End Promise } -/* -function evalFunction(exp, workerScript){ - return new Promise(function(resolve, reject) { - if (exp.callee.type!="Identifier"){ - reject(makeRuntimeRejectMsg(workerScript, "callee must be an Identifier")); - return; - } - switch(exp.callee.name){ - case "print": - if (exp.arguments.length != 1) { - return reject(makeRuntimeRejectMsg(workerScript, "print() call has incorrect number of arguments. Takes 1 argument")); - } - var evaluatePromise = evaluate(exp.arguments[0], workerScript); - evaluatePromise.then(function(res) { - workerScript.scriptRef.log(res.toString()); - resolve(true); - }).catch(function(e) { - reject(e); - }); - break; - case "scan": - if (exp.arguments.length != 1) { - exp.arguments = [{value:Player.getCurrentServer().hostname,type:"Literal"}]; - } - var ipPromise = evaluate(exp.arguments[0], workerScript); - ipPromise.then(function (ip) { - var server = getServer(ip); - if (server == null) { - workerScript.scriptRef.log('getServerOpenPortsCount() failed. Invalid IP or hostname passed in: ' + ip); - return reject(makeRuntimeRejectMsg(workerScript, 'Invalid IP or hostname passed into getServerOpenPortsCount() command')); - } - var out = []; - for (var i = 0; i < server.serversOnNetwork.length; i++) { - var entry = server.getServerOnNetwork(i).hostname; - if (entry == null) { - continue; - } - out.push(entry); - } - workerScript.scriptRef.log('scan() returned ' + server.serversOnNetwork.length + ' connections for ' + server.hostname); - resolve(out); - }).catch(function(e) { - reject(e); - }); - break; - default: - reject(makeRuntimeRejectMsg(workerScript, "Invalid function: " + exp.callee)); - } - }); -} -*/ - function evalBinary(exp, workerScript){ return new Promise(function(resolve, reject) { var expLeftPromise = evaluate(exp.left, workerScript); @@ -329,17 +285,24 @@ function evalBinary(exp, workerScript){ } function evalUnary(exp, workerScript){ + var env = workerScript.env; return new Promise(function(resolve, reject) { - var expLeftPromise = evaluate(exp.left, workerScript); - expLeftPromise.then(function(expLeft) { - switch(exp.operator){ - case "++": - break - case "--": - break; + if (env.stopFlag) {return reject(workerScript);} + var p = evaluate(exp.argument, workerScript); + p.then(function(res) { + if (exp.operator == "!") { + resolve(!res); + } else if (exp.operator == "-") { + if (isNaN(res)) { + resolve(res); + } else { + resolve(-1 * res); + } + } else { + reject(makeRuntimeRejectMsg(workerScript, "Unimplemented unary operator: " + exp.operator)); } - }, function(e) { - reject(e); + }).catch(function(e) { + reject(e); }); }); } @@ -534,113 +497,6 @@ function evaluateWhile(exp, workerScript) { }); } -/* -function evaluateHacknetNode(exp, workerScript) { - console.log("here"); - var env = workerScript.env; - return new Promise(function(resolve, reject) { - setTimeout(function() { - if (exp.index == null) { - if ((exp.op.type == "call" && exp.op.func.value == "length") || - (exp.op.type == "var" && exp.op.value == "length")) { - resolve(Player.hacknetNodes.length); - workerScript.scriptRef.log("hacknetnodes.length returned " + Player.hacknetNodes.length); - return; - } else { - workerScript.scriptRef.log("Invalid/null index for hacknetnodes"); - reject(makeRuntimeRejectMsg(workerScript, "Invalid/null index. hacknetnodes array must be accessed with an index")); - return; - } - - } - var indexPromise = evaluate(exp.index.value, workerScript); - indexPromise.then(function(index) { - if (isNaN(index) || index >= Player.hacknetNodes.length || index < 0) { - workerScript.scriptRef.log("Invalid index value for hacknetnodes[]"); - reject(makeRuntimeRejectMsg(workerScript, "Invalid index value for hacknetnodes[].")); - return; - } - var nodeObj = Player.hacknetNodes[index]; - if (exp.op == null) { - reject(makeRuntimeRejectMsg(workerScript, "No operator or property called for hacknetnodes. Usage: hacknetnodes[i].property/operator")); - return; - } else if (exp.op.type == "var") { - //Get properties: level, ram, cores - switch(exp.op.value) { - case "level": - resolve(nodeObj.level); - break; - case "ram": - resolve(nodeObj.ram); - break; - case "cores": - resolve(nodeObj.numCores); - break; - default: - reject(makeRuntimeRejectMsg(workerScript, "Unrecognized property for Hacknet Node. Valid properties: ram, cores, level")); - break; - } - - } else if (exp.op.type == "call") { - switch(exp.op.func.value) { - case "upgradeLevel": - if (exp.op.args.length == 1) { - var argPromise = evaluate(exp.op.args[0], workerScript); - argPromise.then(function(arg) { - if (isNaN(arg) || arg < 0) { - reject(makeRuntimeRejectMsg(workerScript, "Invalid argument passed into upgradeLevel()")); - return; - } - arg = Math.round(arg); - var res = nodeObj.purchaseLevelUpgrade(arg); - if (res) { - workerScript.scriptRef.log("Upgraded " + nodeObj.name + " " + arg + " times to level " + nodeObj.level); - } - resolve(res); - }, function(e) { - reject(e); - }); - } else { - var res = nodeObj.purchaseLevelUpgrade(1); - if (res) { - workerScript.scriptRef.log("Upgraded " + nodeObj.name + " once to level " + nodeObj.level); - } - resolve(res); - } - break; - case "upgradeRam": - var res = nodeObj.purchaseRamUpgrade(); - if (res) { - workerScript.scriptRef.log("Upgraded " + nodeObj.name + "'s RAM to " + nodeObj.ram + "GB"); - } - resolve(res); - break; - case "upgradeCore": - var res = nodeObj.purchaseCoreUpgrade(); - if (res) { - workerScript.scriptRef.log("Upgraded " + nodeObj.name + "'s number of cores to " + nodeObj.numCores); - } - resolve(res); - break; - default: - reject(makeRuntimeRejectMsg(workerScript, "Unrecognized function/operator for hacknet node. Valid functions: upgradeLevel(n), upgradeRam(), upgradeCore()")); - break; - } - } else { - reject(makeRuntimeRejectMsg(workerScript, "Unrecognized operation for hacknet node")); - return; - } - }, function(e) { - reject(e); - }); - - }, CONSTANTS.CodeInstructionRunTime); - }, function(e) { - reject(e); - }); -} -*/ - function evaluateProg(exp, workerScript, index) { var env = workerScript.env; @@ -791,7 +647,7 @@ function scriptCalculateExpGain(server) { if (server.baseDifficulty == null) { server.baseDifficulty = server.hackDifficulty; } - return (server.baseDifficulty * Player.hacking_exp_mult * 0.4 + 2); + return (server.baseDifficulty * Player.hacking_exp_mult * 0.3 + 2); } //The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 4e665bcfd..160694ef4 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -654,6 +654,12 @@ function NetscriptFunctions(workerScript) { return ""; } + if (Player.purchasedServers.length >= CONSTANTS.PurchasedServerLimit) { + workerScript.scriptRef.log("Error: You have reached the maximum limit of " + CONSTANTS.PurchasedServerLimit + + " servers. You cannot purchase any more."); + return ""; + } + ram = Math.round(ram); if (isNaN(ram) || !powerOfTwo(ram)) { workerScript.scriptRef.log("Error: Invalid ram argument passed to purchaseServer(). Must be numeric and a power of 2"); @@ -677,6 +683,56 @@ function NetscriptFunctions(workerScript) { workerScript.scriptRef.log("Purchased new server with hostname " + newServ.hostname + " for $" + formatNumber(cost, 2)); return newServ.hostname; }, + deleteServer : function(hostname) { + var hostnameStr = String(hostname); + hostnameStr = hostnameStr.replace(/\s\s+/g, ''); + var server = GetServerByHostname(hostnameStr); + if (server == null) { + workerScript.scriptRef.log("Error: Could not find server with hostname " + hostnameStr + ". deleteServer() failed"); + return false; + } + + if (!server.purchasedByPlayer) { + workerScript.scriptRef.log("Error: Server " + server.hostname + " is not a purchased server. " + + "Cannot be deleted. deleteSErver failed"); + return false; + } + var ip = server.ip; + + //Delete from all servers + delete AllServers[ip]; + + //Delete from player's purchasedServers array + var found = false; + for (var i = 0; i < Player.purchasedServers.length; ++i) { + if (ip == Player.purchasedServers[i]) { + found = true; + Player.purchasedServers.splice(i, 1); + break; + } + } + + if (!found) { + workerScript.scriptRef.log("Error: Could not identify server " + server.hostname + + "as a purchased server. This is likely a bug please contact game dev"); + return false; + } + + //Delete from home computer + found = false; + var homeComputer = Player.getHomeComputer(); + for (var i = 0; i < homeComputer.serversOnNetwork.length; ++i) { + if (ip == homeComputer.serversOnNetwork[i]) { + homeComputer.serversOnNetwork.splice(i, 1); + workerScript.scriptRef.log("Deleted server " + hostnameStr); + return true; + } + } + //Wasn't found on home computer + workerScript.scriptRef.log("Error: Could not find server " + server.hostname + + "as a purchased server. This is likely a bug please contact game dev"); + return false; + }, round : function(n) { if (isNaN(n)) {return 0;} return Math.round(n); diff --git a/src/NetscriptWorker.js b/src/NetscriptWorker.js index c3a3684e1..f90703b0d 100644 --- a/src/NetscriptWorker.js +++ b/src/NetscriptWorker.js @@ -1,6 +1,6 @@ -/* Worker code, contains Netscript scripts that are actually running */ - -//TODO Tested For and while and generic call statements. Have not tested if statements +/* Worker code, contains Netscript scripts that are actually running */ + +//TODO Tested For and while and generic call statements. Have not tested if statements /* Actual Worker Code */ function WorkerScript(runningScriptObj) { @@ -53,7 +53,7 @@ function runScriptsLoop() { workerScripts[i].env.stopFlag = true; continue; } - + workerScripts[i].running = true; var p = evaluate(ast, workerScripts[i]); //Once the code finishes (either resolved or rejected, doesnt matter), set its @@ -79,9 +79,9 @@ function runScriptsLoop() { var serverIp = errorTextArray[1]; var scriptName = errorTextArray[2]; var errorMsg = errorTextArray[3]; - - dialogBoxCreate("Script runtime error:
Server Ip: " + serverIp + - "
Script name: " + scriptName + + + dialogBoxCreate("Script runtime error:
Server Ip: " + serverIp + + "
Script name: " + scriptName + "
Args:" + printArray(w.args) + "
" + errorMsg); w.scriptRef.log("Script crashed with runtime error"); } else { @@ -89,7 +89,7 @@ function runScriptsLoop() { } w.running = false; w.env.stopFlag = true; - + } else if (isScriptErrorMessage(w)) { dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer"); console.log("ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN"); @@ -100,13 +100,13 @@ function runScriptsLoop() { }); } } - + //Delete any scripts that finished or have been killed. Loop backwards bc removing //items fucks up the indexing for (var i = workerScripts.length - 1; i >= 0; i--) { if (workerScripts[i].running == false && workerScripts[i].env.stopFlag == true) { console.log("Deleting script: " + workerScripts[i].name); - //Delete script from the runningScripts array on its host serverIp + //Delete script from the runningScripts array on its host serverIp var ip = workerScripts[i].serverIp; var name = workerScripts[i].name; for (var j = 0; j < AllServers[ip].runningScripts.length; j++) { @@ -116,18 +116,18 @@ function runScriptsLoop() { break; } } - + //Free RAM AllServers[ip].ramUsed -= workerScripts[i].ramUsage; - + //Delete script from Active Scripts deleteActiveScriptsItem(workerScripts[i]); - + //Delete script from workerScripts workerScripts.splice(i, 1); } } - + setTimeout(runScriptsLoop, 10000); } @@ -145,10 +145,10 @@ function killWorkerScript(runningScriptObj, serverIp) { return false; } -//Queues a script to be run +//Queues a script to be run function addWorkerScript(runningScriptObj, server) { var filename = runningScriptObj.filename; - + //Update server's ram usage var threads = 1; if (runningScriptObj.threads && !isNaN(runningScriptObj.threads)) { @@ -156,18 +156,18 @@ function addWorkerScript(runningScriptObj, server) { } else { runningScriptObj.threads = 1; } - var ramUsage = runningScriptObj.scriptRef.ramUsage * threads + var ramUsage = runningScriptObj.scriptRef.ramUsage * threads * Math.pow(CONSTANTS.MultithreadingRAMCost, threads-1); server.ramUsed += ramUsage; - + //Create the WorkerScript var s = new WorkerScript(runningScriptObj); s.serverIp = server.ip; s.ramUsage = ramUsage; - + //Add the WorkerScript to the Active Scripts list addActiveScriptsItem(s); - + //Add the WorkerScript workerScripts.push(s); return; @@ -181,4 +181,4 @@ function updateOnlineScriptTimes(numCycles = 1) { } } -runScriptsLoop(); \ No newline at end of file +runScriptsLoop(); diff --git a/src/Player.js b/src/Player.js index 7cecca84b..41e494079 100644 --- a/src/Player.js +++ b/src/Player.js @@ -2,7 +2,7 @@ function PlayerObject() { //Skills and stats this.hacking_skill = 1; - + //Fighting this.hp = 10; this.max_hp = 10; @@ -10,17 +10,17 @@ function PlayerObject() { this.defense = 1; //Damage received this.dexterity = 1; //Accuracy this.agility = 1; //Dodge % - + //Labor stats this.charisma = 1; //Intelligence, perhaps? - + //Hacking multipliers this.hacking_chance_mult = 1; //Increase through ascensions/augmentations this.hacking_speed_mult = 1; //Decrease through ascensions/augmentations this.hacking_money_mult = 1; //Increase through ascensions/augmentations. Can't go above 1 this.hacking_grow_mult = 1; - + //Note: "Lifetime" refers to current ascension, "total" refers to the entire game history //Accumulative stats and skills this.total_hacking = 1; @@ -35,7 +35,7 @@ function PlayerObject() { this.lifetime_dexterity = 1; this.lifetime_agility = 1; this.lifetime_charisma = 1; - + //Experience and multipliers this.hacking_exp = 0; this.strength_exp = 0; @@ -43,14 +43,14 @@ function PlayerObject() { this.dexterity_exp = 0; this.agility_exp = 0; this.charisma_exp = 0; - + this.hacking_mult = 1; this.strength_mult = 1; this.defense_mult = 1; this.dexterity_mult = 1; this.agility_mult = 1; this.charisma_mult = 1; - + this.hacking_exp_mult = 1; this.strength_exp_mult = 1; this.defense_exp_mult = 1; @@ -59,38 +59,39 @@ function PlayerObject() { this.charisma_exp_mult = 1; this.company_rep_mult = 1; - this.faction_rep_mult = 1; - + this.faction_rep_mult = 1; + //Money this.money = 1000; this.total_money = 0; //Total money ever earned in this "simulation" this.lifetime_money = 0; //Total money ever earned - + //IP Address of Starting (home) computer this.homeComputer = ""; - + //Location information this.city = Locations.Sector12; this.location = ""; - + //Company Information this.companyName = ""; //Name of Company, equivalent to an object from Locations this.companyPosition = ""; //CompanyPosition object - + //Servers this.currentServer = ""; //IP address of Server currently being accessed through terminal this.discoveredServers = []; //IP addresses of secret servers not in the network that you have discovered this.purchasedServers = []; this.hacknetNodes = []; - this.totalHacknetNodeProduction = 0; - + this.totalHacknetNodeProduction = 0; + //Factions - this.factions = []; //Names of all factions player has joined - + this.factions = []; //Names of all factions player has joined + this.factionInvitations = []; //Outstanding faction invitations + //Augmentations this.queuedAugmentations = []; //Purchased but not installed, names only this.augmentations = []; //Names of all installed augmentations - + //Crime statistics (Total refers to this 'simulation'. Lifetime is forever) this.karma = 0; this.numTimesShoplifted = 0; @@ -117,22 +118,22 @@ function PlayerObject() { this.numTimesHeist = 0; this.numTimesHeistTotal = 0; this.numTimesHeistLifetime = 0; - + this.crime_money_mult = 1; this.crime_success_mult = 1; - + //Flag to let the engine know the player is starting an action // Current actions: hack, analyze this.startAction = false; this.actionTime = 0; - - //Flags/variables for working (Company, Faction, Creating Program, Taking Class) + + //Flags/variables for working (Company, Faction, Creating Program, Taking Class) this.isWorking = false; this.workType = ""; - + this.currentWorkFactionName = ""; this.currentWorkFactionDescription = ""; - + this.workHackExpGainRate = 0; this.workStrExpGainRate = 0; this.workDefExpGainRate = 0; @@ -142,7 +143,7 @@ function PlayerObject() { this.workRepGainRate = 0; this.workMoneyGainRate = 0; this.workMoneyLossRate = 0; - + this.workHackExpGained = 0; this.workStrExpGained = 0; this.workDefExpGained = 0; @@ -151,30 +152,30 @@ function PlayerObject() { this.workChaExpGained = 0; this.workRepGained = 0; this.workMoneyGained = 0; - + this.createProgramName = ""; - + this.className = ""; - + this.crimeType = ""; - + this.timeWorked = 0; //in ms this.timeNeededToCompleteWork = 0; - + this.work_money_mult = 1; - + //Hacknet Node multipliers this.hacknet_node_money_mult = 1; this.hacknet_node_purchase_cost_mult = 1; this.hacknet_node_ram_cost_mult = 1; this.hacknet_node_core_cost_mult = 1; this.hacknet_node_level_cost_mult = 1; - + //Stock Market this.hasWseAccount = false; this.hasTixApiAccess = false; - - //Used to store the last update time. + + //Used to store the last update time. this.lastUpdate = 0; this.totalPlaytime = 0; this.playtimeSinceLastAug = 0; @@ -187,7 +188,7 @@ PlayerObject.prototype.init = function() { this.homeComputer = t_homeComp.ip; this.currentServer = t_homeComp.ip; AddToAllServers(t_homeComp); - + this.getHomeComputer().programs.push(Programs.NukeProgram); } @@ -213,7 +214,7 @@ PlayerObject.prototype.updateSkillLevels = function() { this.dexterity = Math.floor(this.calculateSkill(this.dexterity_exp) * this.dexterity_mult); this.agility = Math.floor(this.calculateSkill(this.agility_exp) * this.agility_mult); this.charisma = Math.floor(this.calculateSkill(this.charisma_exp) * this.charisma_mult); - + var ratio = this.hp / this.max_hp; this.max_hp = Math.floor(10 + this.defense / 10); Player.hp = Math.round(this.max_hp * ratio); @@ -221,7 +222,7 @@ PlayerObject.prototype.updateSkillLevels = function() { //Calculates the chance of hacking a server //The formula is: -// (2 * hacking_chance_multiplier * hacking_skill - requiredLevel) 100 - difficulty +// (2 * hacking_chance_multiplier * hacking_skill - requiredLevel) 100 - difficulty // ----------------------------------------------------------- * ----------------- // (2 * hacking_chance_multiplier * hacking_skill) 100 PlayerObject.prototype.calculateHackingChance = function() { @@ -230,15 +231,15 @@ PlayerObject.prototype.calculateHackingChance = function() { var skillChance = (skillMult - this.getCurrentServer().requiredHackingSkill) / skillMult; var chance = skillChance * difficultyMult * this.hacking_chance_mult; if (chance > 1) {return 1;} - if (chance < 0) {return 0;} + if (chance < 0) {return 0;} return chance; } //Calculate the time it takes to hack a server in seconds. Returns the time //The formula is: -// (2.5 * requiredLevel * difficulty + 200) +// (2.5 * requiredLevel * difficulty + 200) // ----------------------------------- * hacking_speed_multiplier -// hacking_skill + 100 +// hacking_skill + 100 PlayerObject.prototype.calculateHackingTime = function() { var difficultyMult = this.getCurrentServer().requiredHackingSkill * this.getCurrentServer().hackDifficulty; var skillFactor = (2.5 * difficultyMult + 200) / (this.hacking_skill + 100); @@ -247,7 +248,7 @@ PlayerObject.prototype.calculateHackingTime = function() { //Calculates the PERCENTAGE of a server's money that the player will hack from the server if successful //The formula is: -// (hacking_skill - (requiredLevel-1)) 100 - difficulty +// (hacking_skill - (requiredLevel-1)) 100 - difficulty // --------------------------------------* ----------------------- * hacking_money_multiplier // hacking_skill 100 PlayerObject.prototype.calculatePercentMoneyHacked = function() { @@ -268,7 +269,7 @@ PlayerObject.prototype.calculateExpGain = function() { if (s.baseDifficulty == null) { s.baseDifficulty = s.hackDifficulty; } - return (s.baseDifficulty * this.hacking_exp_mult * 0.4 + 2); + return (s.baseDifficulty * this.hacking_exp_mult * 0.3 + 2); } //Hack/Analyze a server. Return the amount of time the hack will take. This lets the Terminal object know how long to disable itself for @@ -349,7 +350,7 @@ PlayerObject.prototype.gainCharismaExp = function(exp) { console.log("ERR: NaN passed into Player.gainCharismaExp()"); return; } this.charisma_exp += exp; -} +} /******* Working functions *******/ PlayerObject.prototype.resetWorkStatus = function() { @@ -361,7 +362,7 @@ PlayerObject.prototype.resetWorkStatus = function() { this.workChaExpGainRate = 0; this.workRepGainRate = 0; this.workMoneyGainRate = 0; - + this.workHackExpGained = 0; this.workStrExpGained = 0; this.workDefExpGained = 0; @@ -370,14 +371,14 @@ PlayerObject.prototype.resetWorkStatus = function() { this.workChaExpGained = 0; this.workRepGained = 0; this.workMoneyGained = 0; - + this.timeWorked = 0; - + this.currentWorkFactionName = ""; this.currentWorkFactionDescription = ""; this.createProgramName = ""; this.className = ""; - + document.getElementById("work-in-progress-text").innerHTML = ""; } @@ -398,33 +399,33 @@ PlayerObject.prototype.finishWork = function(cancelled) { } this.gainWorkExp(); - + var company = Companies[this.companyName]; company.playerReputation += (this.workRepGained); - + this.gainMoney(this.workMoneyGained); - + this.updateSkillLevels(); - - var txt = "You earned a total of:
" + - "$" + formatNumber(this.workMoneyGained, 2) + "
" + - formatNumber(this.workRepGained, 4) + " reputation for the company
" + - formatNumber(this.workHackExpGained, 4) + " hacking exp
" + - formatNumber(this.workStrExpGained, 4) + " strength exp
" + + + var txt = "You earned a total of:
" + + "$" + formatNumber(this.workMoneyGained, 2) + "
" + + formatNumber(this.workRepGained, 4) + " reputation for the company
" + + formatNumber(this.workHackExpGained, 4) + " hacking exp
" + + formatNumber(this.workStrExpGained, 4) + " strength exp
" + formatNumber(this.workDefExpGained, 4) + " defense exp
" + - formatNumber(this.workDexExpGained, 4) + " dexterity exp
" + - formatNumber(this.workAgiExpGained, 4) + " agility exp
" + + formatNumber(this.workDexExpGained, 4) + " dexterity exp
" + + formatNumber(this.workAgiExpGained, 4) + " agility exp
" + formatNumber(this.workChaExpGained, 4) + " charisma exp
"; - + if (cancelled) { txt = "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

" + - "Since you cancelled your work early, you only gained half of the reputation you earned.

" + txt; + "Since you cancelled your work early, you only gained half of the reputation you earned.

" + txt; } else { txt = "You worked a full shift of 8 hours!

" + "You earned a total of:
" + txt; } dialogBoxCreate(txt); - + var mainMenu = document.getElementById("mainmenu-container"); mainMenu.style.visibility = "visible"; this.isWorking = false; @@ -435,7 +436,7 @@ PlayerObject.prototype.startWork = function() { this.resetWorkStatus(); this.isWorking = true; this.workType = CONSTANTS.WorkTypeCompany; - + this.workHackExpGainRate = this.getWorkHackExpGain(); this.workStrExpGainRate = this.getWorkStrExpGain(); this.workDefExpGainRate = this.getWorkDefExpGain(); @@ -444,9 +445,9 @@ PlayerObject.prototype.startWork = function() { this.workChaExpGainRate = this.getWorkChaExpGain(); this.workRepGainRate = this.getWorkRepGain(); this.workMoneyGainRate = this.getWorkMoneyGain(); - + this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours; - + //Remove all old event listeners from Cancel button var newCancelButton = clearEventListeners("work-in-progress-cancel-button"); newCancelButton.innerHTML = "Cancel Work"; @@ -454,14 +455,14 @@ PlayerObject.prototype.startWork = function() { Player.finishWork(true); return false; }); - + //Display Work In Progress Screen Engine.loadWorkInProgressContent(); } - + PlayerObject.prototype.work = function(numCycles) { this.workRepGainRate = this.getWorkRepGain(); - + this.workHackExpGained += this.workHackExpGainRate * numCycles; this.workStrExpGained += this.workStrExpGainRate * numCycles; this.workDefExpGained += this.workDefExpGainRate * numCycles; @@ -470,11 +471,11 @@ PlayerObject.prototype.work = function(numCycles) { this.workChaExpGained += this.workChaExpGainRate * numCycles; this.workRepGained += this.workRepGainRate * numCycles; this.workMoneyGained += this.workMoneyGainRate * numCycles; - + var cyclesPerSec = 1000 / Engine._idleSpeed; - + this.timeWorked += Engine._idleSpeed * numCycles; - + //If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money if (this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) { var maxCycles = CONSTANTS.GameCyclesPer8Hours; @@ -489,30 +490,30 @@ PlayerObject.prototype.work = function(numCycles) { this.finishWork(false); return; } - + var txt = document.getElementById("work-in-progress-text"); - txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName + - " at " + Player.companyName + "

" + + txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName + + " at " + Player.companyName + "

" + "You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

" + - "You have earned:

" + - "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec)

" + - formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company

" + - formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp

" + - formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp
" + - formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp
" + - formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp
" + + "You have earned:

" + + "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec)

" + + formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company

" + + formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp

" + + formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp
" + + formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp
" + + formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp
" + formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp

" + - formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp

" + - "You will automatically finish after working for 8 hours. You can cancel earlier if you wish, " + + formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp

" + + "You will automatically finish after working for 8 hours. You can cancel earlier if you wish, " + "but you will only gain half of the reputation you've earned so far." - + } PlayerObject.prototype.startWorkPartTime = function() { this.resetWorkStatus(); this.isWorking = true; this.workType = CONSTANTS.WorkTypeCompanyPartTime; - + this.workHackExpGainRate = this.getWorkHackExpGain(); this.workStrExpGainRate = this.getWorkStrExpGain(); this.workDefExpGainRate = this.getWorkDefExpGain(); @@ -521,23 +522,23 @@ PlayerObject.prototype.startWorkPartTime = function() { this.workChaExpGainRate = this.getWorkChaExpGain(); this.workRepGainRate = this.getWorkRepGain(); this.workMoneyGainRate = this.getWorkMoneyGain(); - + this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours; - + var newCancelButton = clearEventListeners("work-in-progress-cancel-button"); newCancelButton.innerHTML = "Stop Working"; newCancelButton.addEventListener("click", function() { Player.finishWorkPartTime(); return false; }); - + //Display Work In Progress Screen Engine.loadWorkInProgressContent(); } PlayerObject.prototype.workPartTime = function(numCycles) { this.workRepGainRate = this.getWorkRepGain(); - + this.workHackExpGained += this.workHackExpGainRate * numCycles; this.workStrExpGained += this.workStrExpGainRate * numCycles; this.workDefExpGained += this.workDefExpGainRate * numCycles; @@ -546,11 +547,11 @@ PlayerObject.prototype.workPartTime = function(numCycles) { this.workChaExpGained += this.workChaExpGainRate * numCycles; this.workRepGained += this.workRepGainRate * numCycles; this.workMoneyGained += this.workMoneyGainRate * numCycles; - + var cyclesPerSec = 1000 / Engine._idleSpeed; - + this.timeWorked += Engine._idleSpeed * numCycles; - + //If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money if (this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) { var maxCycles = CONSTANTS.GameCyclesPer8Hours; @@ -565,47 +566,47 @@ PlayerObject.prototype.workPartTime = function(numCycles) { this.finishWorkPartTime(); return; } - + var txt = document.getElementById("work-in-progress-text"); - txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName + - " at " + Player.companyName + "

" + + txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName + + " at " + Player.companyName + "

" + "You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

" + - "You have earned:

" + - "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec)

" + - formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company

" + - formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp

" + - formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp
" + - formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp
" + - formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp
" + + "You have earned:

" + + "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec)

" + + formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company

" + + formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp

" + + formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp
" + + formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp
" + + formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp
" + formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp

" + - formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp

" + - "You will automatically finish after working for 8 hours. You can cancel earlier if you wish,
" + + formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp

" + + "You will automatically finish after working for 8 hours. You can cancel earlier if you wish,
" + "and there will be no penalty because this is a part-time job."; - + } PlayerObject.prototype.finishWorkPartTime = function() { this.gainWorkExp(); - + var company = Companies[this.companyName]; company.playerReputation += (this.workRepGained); - + this.gainMoney(this.workMoneyGained); - + this.updateSkillLevels(); - - var txt = "You earned a total of:
" + - "$" + formatNumber(this.workMoneyGained, 2) + "
" + - formatNumber(this.workRepGained, 4) + " reputation for the company
" + - formatNumber(this.workHackExpGained, 4) + " hacking exp
" + - formatNumber(this.workStrExpGained, 4) + " strength exp
" + + + var txt = "You earned a total of:
" + + "$" + formatNumber(this.workMoneyGained, 2) + "
" + + formatNumber(this.workRepGained, 4) + " reputation for the company
" + + formatNumber(this.workHackExpGained, 4) + " hacking exp
" + + formatNumber(this.workStrExpGained, 4) + " strength exp
" + formatNumber(this.workDefExpGained, 4) + " defense exp
" + - formatNumber(this.workDexExpGained, 4) + " dexterity exp
" + - formatNumber(this.workAgiExpGained, 4) + " agility exp
" + + formatNumber(this.workDexExpGained, 4) + " dexterity exp
" + + formatNumber(this.workAgiExpGained, 4) + " agility exp
" + formatNumber(this.workChaExpGained, 4) + " charisma exp
"; txt = "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

" + txt; dialogBoxCreate(txt); - + var mainMenu = document.getElementById("mainmenu-container"); mainMenu.style.visibility = "visible"; this.isWorking = false; @@ -615,31 +616,31 @@ PlayerObject.prototype.finishWorkPartTime = function() { /* Working for Faction */ PlayerObject.prototype.finishFactionWork = function(cancelled, faction) { this.gainWorkExp(); - + var faction = Factions[this.currentWorkFactionName]; faction.playerReputation += (this.workRepGained); - + this.gainMoney(this.workMoneyGained); - + this.updateSkillLevels(); - + var txt = "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

" + - "You earned a total of:
" + - "$" + formatNumber(this.workMoneyGained, 2) + "
" + - formatNumber(this.workRepGained, 4) + " reputation for the faction
" + - formatNumber(this.workHackExpGained, 4) + " hacking exp
" + - formatNumber(this.workStrExpGained, 4) + " strength exp
" + + "You earned a total of:
" + + "$" + formatNumber(this.workMoneyGained, 2) + "
" + + formatNumber(this.workRepGained, 4) + " reputation for the faction
" + + formatNumber(this.workHackExpGained, 4) + " hacking exp
" + + formatNumber(this.workStrExpGained, 4) + " strength exp
" + formatNumber(this.workDefExpGained, 4) + " defense exp
" + - formatNumber(this.workDexExpGained, 4) + " dexterity exp
" + - formatNumber(this.workAgiExpGained, 4) + " agility exp
" + + formatNumber(this.workDexExpGained, 4) + " dexterity exp
" + + formatNumber(this.workAgiExpGained, 4) + " agility exp
" + formatNumber(this.workChaExpGained, 4) + " charisma exp
"; dialogBoxCreate(txt); - + var mainMenu = document.getElementById("mainmenu-container"); mainMenu.style.visibility = "visible"; - + this.isWorking = false; - + Engine.loadTerminalContent(); } @@ -648,39 +649,39 @@ PlayerObject.prototype.startFactionWork = function(faction) { var favorMult = 1 + (faction.favor / 100); if (isNaN(favorMult)) {favorMult = 1;} this.workRepGainRate *= favorMult; - + this.isWorking = true; this.workType = CONSTANTS.WorkTypeFaction; this.currentWorkFactionName = faction.name; - + this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours; - - var cancelButton = clearEventListeners("work-in-progress-cancel-button"); + + var cancelButton = clearEventListeners("work-in-progress-cancel-button"); cancelButton.innerHTML = "Stop Faction Work"; cancelButton.addEventListener("click", function() { Player.finishFactionWork(true, faction); return false; }); - + //Display Work In Progress Screen Engine.loadWorkInProgressContent(); } PlayerObject.prototype.startFactionHackWork = function(faction) { this.resetWorkStatus(); - + this.workHackExpGainRate = .15 * this.hacking_exp_mult; this.workRepGainRate = 0.9 * this.hacking_skill / CONSTANTS.MaxSkillLevel * this.faction_rep_mult; - + this.factionWorkType = CONSTANTS.FactionWorkHacking; this.currentWorkFactionDescription = "carrying out hacking contracts"; - + this.startFactionWork(faction); } PlayerObject.prototype.startFactionFieldWork = function(faction) { this.resetWorkStatus(); - + this.workHackExpGainRate = .1 * this.hacking_exp_mult; this.workStrExpGainRate = .1 * this.strength_exp_mult; this.workDefExpGainRate = .1 * this.defense_exp_mult; @@ -688,10 +689,10 @@ PlayerObject.prototype.startFactionFieldWork = function(faction) { this.workAgiExpGainRate = .1 * this.agility_exp_mult; this.workChaExpGainRate = .1 * this.charisma_exp_mult; this.workRepGainRate = this.getFactionFieldWorkRepGain(); - + this.factionWorkType = CONSTANTS.FactionWorkField; this.currentWorkFactionDescription = "carrying out field missions" - + this.startFactionWork(faction); } @@ -705,16 +706,16 @@ PlayerObject.prototype.startFactionSecurityWork = function(faction) { this.workAgiExpGainRate = 0.15 * this.agility_exp_mult; this.workChaExpGainRate = 0.00 * this.charisma_exp_mult; this.workRepGainRate = this.getFactionSecurityWorkRepGain(); - + this.factionWorkType = CONSTANTS.FactionWorkSecurity; this.currentWorkFactionDescription = "performing security detail" - + this.startFactionWork(faction); } - + PlayerObject.prototype.workForFaction = function(numCycles) { var faction = Factions[this.currentWorkFactionName]; - + //Constantly update the rep gain rate switch (this.factionWorkType) { case CONSTANTS.FactionWorkHacking: @@ -729,12 +730,12 @@ PlayerObject.prototype.workForFaction = function(numCycles) { default: break; } - + //Update reputation gain rate to account for faction favor var favorMult = 1 + (faction.favor / 100); if (isNaN(favorMult)) {favorMult = 1;} this.workRepGainRate *= favorMult; - + this.workHackExpGained += this.workHackExpGainRate * numCycles; this.workStrExpGained += this.workStrExpGainRate * numCycles; this.workDefExpGained += this.workDefExpGainRate * numCycles; @@ -743,11 +744,11 @@ PlayerObject.prototype.workForFaction = function(numCycles) { this.workChaExpGained += this.workChaExpGainRate * numCycles; this.workRepGained += this.workRepGainRate * numCycles; this.workMoneyGained += this.workMoneyGainRate * numCycles; - + var cyclesPerSec = 1000 / Engine._idleSpeed; - + this.timeWorked += Engine._idleSpeed * numCycles; - + //If timeWorked == 20 hours, then finish. You can only work for the faction for 20 hours if (this.timeWorked >= CONSTANTS.MillisecondsPer20Hours) { var maxCycles = CONSTANTS.GameCyclesPer20Hours; @@ -761,22 +762,22 @@ PlayerObject.prototype.workForFaction = function(numCycles) { this.workMoneyGained = this.workMoneyGainRate * maxCycles; this.finishFactionWork(false, faction); } - + var txt = document.getElementById("work-in-progress-text"); - txt.innerHTML = "You are currently " + this.currentWorkFactionDescription + " for your faction " + faction.name + "." + + txt.innerHTML = "You are currently " + this.currentWorkFactionDescription + " for your faction " + faction.name + "." + " You have been doing this for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

" + - "You have earned:

" + - "$" + formatNumber(this.workMoneyGained, 2) + " (" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec)

" + - formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this faction

" + - formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp

" + - formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp
" + - formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp
" + - formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp
" + + "You have earned:

" + + "$" + formatNumber(this.workMoneyGained, 2) + " (" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec)

" + + formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this faction

" + + formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp

" + + formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp
" + + formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp
" + + formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp
" + formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp

" + - formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp

" + - - "You will automatically finish after working for 20 hours. You can cancel earlier if you wish.
" + - "There is no penalty for cancelling earlier."; + formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp

" + + + "You will automatically finish after working for 20 hours. You can cancel earlier if you wish.
" + + "There is no penalty for cancelling earlier."; } @@ -827,28 +828,28 @@ PlayerObject.prototype.getWorkRepGain = function() { var company = Companies[this.companyName]; var jobPerformance = this.companyPosition.calculateJobPerformance(this.hacking_skill, this.strength, this.defense, this.dexterity, - this.agility, this.charisma); + this.agility, this.charisma); //Update reputation gain rate to account for company favor var favorMult = 1 + (company.favor / 100); if (isNaN(favorMult)) {favorMult = 1;} - return jobPerformance * this.company_rep_mult * favorMult; + return jobPerformance * this.company_rep_mult * favorMult; } PlayerObject.prototype.getFactionSecurityWorkRepGain = function() { - var t = 0.9 * (this.hacking_skill / CONSTANTS.MaxSkillLevel + - this.strength / CONSTANTS.MaxSkillLevel + - this.defense / CONSTANTS.MaxSkillLevel + - this.dexterity / CONSTANTS.MaxSkillLevel + + var t = 0.9 * (this.hacking_skill / CONSTANTS.MaxSkillLevel + + this.strength / CONSTANTS.MaxSkillLevel + + this.defense / CONSTANTS.MaxSkillLevel + + this.dexterity / CONSTANTS.MaxSkillLevel + this.agility / CONSTANTS.MaxSkillLevel) / 5; return t * this.faction_rep_mult; } PlayerObject.prototype.getFactionFieldWorkRepGain = function() { - var t = 0.9 * (this.hacking_skill / CONSTANTS.MaxSkillLevel + - this.strength / CONSTANTS.MaxSkillLevel + - this.defense / CONSTANTS.MaxSkillLevel + - this.dexterity / CONSTANTS.MaxSkillLevel + - this.agility / CONSTANTS.MaxSkillLevel + + var t = 0.9 * (this.hacking_skill / CONSTANTS.MaxSkillLevel + + this.strength / CONSTANTS.MaxSkillLevel + + this.defense / CONSTANTS.MaxSkillLevel + + this.dexterity / CONSTANTS.MaxSkillLevel + + this.agility / CONSTANTS.MaxSkillLevel + this.charisma / CONSTANTS.MaxSkillLevel) / 6; return t * this.faction_rep_mult; } @@ -858,13 +859,13 @@ PlayerObject.prototype.startCreateProgramWork = function(programName, time, reqL this.resetWorkStatus(); this.isWorking = true; this.workType = CONSTANTS.WorkTypeCreateProgram; - + //Time needed to complete work affected by hacking skill (linearly based on //ratio of (your skill - required level) to MAX skill) var timeMultiplier = (CONSTANTS.MaxSkillLevel - (this.hacking_skill - reqLevel)) / CONSTANTS.MaxSkillLevel; if (timeMultiplier > 1) {timeMultiplier = 1;} if (timeMultiplier < 0.01) {timeMultiplier = 0.01;} - + this.timeNeededToCompleteWork = timeMultiplier * time; //Check for incomplete program for (var i = 0; i < Player.getHomeComputer().programs.length; ++i) { @@ -878,16 +879,16 @@ PlayerObject.prototype.startCreateProgramWork = function(programName, time, reqL Player.getHomeComputer().programs.splice(i, 1); } } - + this.createProgramName = programName; - + var cancelButton = clearEventListeners("work-in-progress-cancel-button"); cancelButton.innerHTML = "Cancel work on creating program"; cancelButton.addEventListener("click", function() { Player.finishCreateProgramWork(true, programName); return false; }); - + //Display Work In Progress Screen Engine.loadWorkInProgressContent(); } @@ -895,35 +896,35 @@ PlayerObject.prototype.startCreateProgramWork = function(programName, time, reqL PlayerObject.prototype.createProgramWork = function(numCycles) { this.timeWorked += Engine._idleSpeed * numCycles; var programName = this.createProgramName; - + if (this.timeWorked >= this.timeNeededToCompleteWork) { this.finishCreateProgramWork(false, programName); } - + var txt = document.getElementById("work-in-progress-text"); - txt.innerHTML = "You are currently working on coding " + programName + ".

" + + txt.innerHTML = "You are currently working on coding " + programName + ".

" + "You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

" + - "The program is " + (this.timeWorked / this.timeNeededToCompleteWork * 100).toFixed(2) + "% complete.
" + - "If you cancel, your work will be saved and you can come back to complete the program later."; + "The program is " + (this.timeWorked / this.timeNeededToCompleteWork * 100).toFixed(2) + "% complete.
" + + "If you cancel, your work will be saved and you can come back to complete the program later."; } PlayerObject.prototype.finishCreateProgramWork = function(cancelled, programName) { if (cancelled == false) { - dialogBoxCreate("You've finished creating " + programName + "!
" + + dialogBoxCreate("You've finished creating " + programName + "!
" + "The new program can be found on your home computer."); - + Player.getHomeComputer().programs.push(programName); } else { var perc = Math.floor(this.timeWorked / this.timeNeededToCompleteWork * 100).toString(); var incompleteName = programName + "-" + perc + "%-INC"; Player.getHomeComputer().programs.push(incompleteName); } - + var mainMenu = document.getElementById("mainmenu-container"); mainMenu.style.visibility = "visible"; - + Player.isWorking = false; - + Engine.loadTerminalContent(); } @@ -932,11 +933,11 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) { this.resetWorkStatus(); this.isWorking = true; this.workType = CONSTANTS.WorkTypeStudyClass; - + this.className = className; - + var gameCPS = 1000 / Engine._idleSpeed; - + //Base exp gains per second var baseStudyComputerScienceExp = 0.25; var baseDataStructuresExp = 0.5; @@ -945,7 +946,7 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) { var baseManagementExp = 1; var baseLeadershipExp = 2; var baseGymExp = 1; - + //Find cost and exp gain per game cycle var cost = 0; var hackExp = 0, strExp = 0, defExp = 0, dexExp = 0, agiExp = 0, chaExp = 0; @@ -958,7 +959,7 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) { hackExp = baseDataStructuresExp * expMult / gameCPS; break; case CONSTANTS.ClassNetworks: - cost = CONSTANTS.ClassNetworksBaseCost * costMult / gameCPS; + cost = CONSTANTS.ClassNetworksBaseCost * costMult / gameCPS; hackExp = baseNetworksExp * expMult / gameCPS; break; case CONSTANTS.ClassAlgorithms: @@ -993,7 +994,7 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) { throw new Error("ERR: Invalid/unregocnized class name"); return; } - + this.workMoneyLossRate = cost; this.workHackExpGainRate = hackExp * this.hacking_exp_mult; this.workStrExpGainRate = strExp * this.strength_exp_mult; @@ -1001,11 +1002,11 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) { this.workDexExpGainRate = dexExp * this.dexterity_exp_mult; this.workAgiExpGainRate = agiExp * this.agility_exp_mult; this.workChaExpGainRate = chaExp * this.charisma_exp_mult; - + var cancelButton = clearEventListeners("work-in-progress-cancel-button"); - if (className == CONSTANTS.ClassGymStrength || - className == CONSTANTS.ClassGymDefense || - className == CONSTANTS.ClassGymDexterity || + if (className == CONSTANTS.ClassGymStrength || + className == CONSTANTS.ClassGymDefense || + className == CONSTANTS.ClassGymDexterity || className == CONSTANTS.ClassGymAgility) { cancelButton.innerHTML = "Stop training at gym"; } else { @@ -1015,7 +1016,7 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) { Player.finishClass(); return false; }); - + //Display Work In Progress Screen Engine.loadWorkInProgressContent(); } @@ -1023,7 +1024,7 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) { PlayerObject.prototype.takeClass = function(numCycles) { this.timeWorked += Engine._idleSpeed * numCycles; var className = this.className; - + this.workHackExpGained += this.workHackExpGainRate * numCycles; this.workStrExpGained += this.workStrExpGainRate * numCycles; this.workDefExpGained += this.workDefExpGainRate * numCycles; @@ -1033,49 +1034,49 @@ PlayerObject.prototype.takeClass = function(numCycles) { this.workRepGained += this.workRepGainRate * numCycles; this.workMoneyGained += this.workMoneyGainRate * numCycles; this.workMoneyGained -= this.workMoneyLossRate * numCycles; - + var cyclesPerSec = 1000 / Engine._idleSpeed; - + var txt = document.getElementById("work-in-progress-text"); txt.innerHTML = "You have been " + className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "

" + - "This has cost you:
" + - "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * cyclesPerSec, 2) + " / sec)

" + - "You have gained:
" + - formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp
" + - formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp
" + - formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp
" + - formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp
" + + "This has cost you:
" + + "$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyLossRate * cyclesPerSec, 2) + " / sec)

" + + "You have gained:
" + + formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp
" + + formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp
" + + formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp
" + + formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp
" + formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp
" + - formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp
" + - "You may cancel at any time"; + formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp
" + + "You may cancel at any time"; } PlayerObject.prototype.finishClass = function() { this.gainWorkExp(); - + if (this.workMoneyGained > 0) { throw new Error("ERR: Somehow gained money while taking class"); } this.loseMoney(this.workMoneyGained * -1); - + this.updateSkillLevels(); var txt = "After " + this.className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + ",
" + - "you spent a total of $" + formatNumber(this.workMoneyGained * -1, 2) + ".

" + - "You earned a total of:
" + - formatNumber(this.workHackExpGained, 4) + " hacking exp
" + - formatNumber(this.workStrExpGained, 4) + " strength exp
" + + "you spent a total of $" + formatNumber(this.workMoneyGained * -1, 2) + ".

" + + "You earned a total of:
" + + formatNumber(this.workHackExpGained, 4) + " hacking exp
" + + formatNumber(this.workStrExpGained, 4) + " strength exp
" + formatNumber(this.workDefExpGained, 4) + " defense exp
" + - formatNumber(this.workDexExpGained, 4) + " dexterity exp
" + - formatNumber(this.workAgiExpGained, 4) + " agility exp
" + + formatNumber(this.workDexExpGained, 4) + " dexterity exp
" + + formatNumber(this.workAgiExpGained, 4) + " agility exp
" + formatNumber(this.workChaExpGained, 4) + " charisma exp
"; dialogBoxCreate(txt); - + var mainMenu = document.getElementById("mainmenu-container"); mainMenu.style.visibility = "visible"; - + this.isWorking = false; - + Engine.loadLocationContent(); } @@ -1084,7 +1085,7 @@ PlayerObject.prototype.startCrime = function(hackExp, strExp, defExp, dexExp, ag this.resetWorkStatus(); this.isWorking = true; this.workType = CONSTANTS.WorkTypeCrime; - + this.workHackExpGained = hackExp * this.hacking_exp_mult; this.workStrExpGained = strExp * this.strength_exp_mult; this.workDefExpGained = defExp * this.defense_exp_mult; @@ -1092,9 +1093,9 @@ PlayerObject.prototype.startCrime = function(hackExp, strExp, defExp, dexExp, ag this.workAgiExpGained = agiExp * this.agility_exp_mult; this.workChaExpGained = chaExp * this.charisma_exp_mult; this.workMoneyGained = money * this.crime_money_mult; - + this.timeNeededToCompleteWork = time; - + //Remove all old event listeners from Cancel button var newCancelButton = clearEventListeners("work-in-progress-cancel-button") newCancelButton.innerHTML = "Cancel crime" @@ -1102,25 +1103,25 @@ PlayerObject.prototype.startCrime = function(hackExp, strExp, defExp, dexExp, ag Player.finishCrime(true); return false; }); - + //Display Work In Progress Screen Engine.loadWorkInProgressContent(); } PlayerObject.prototype.commitCrime = function (numCycles) { this.timeWorked += Engine._idleSpeed * numCycles; - + if (this.timeWorked >= this.timeNeededToCompleteWork) {Player.finishCrime(false); return;} - + var percent = Math.round(Player.timeWorked / Player.timeNeededToCompleteWork * 100); var numBars = Math.round(percent / 5); if (numBars < 0) {numBars = 0;} if (numBars > 20) {numBars = 20;} var progressBar = "[" + Array(numBars+1).join("|") + Array(20 - numBars + 1).join(" ") + "]"; - + var txt = document.getElementById("work-in-progress-text"); - txt.innerHTML = "You are attempting to " + Player.crimeType + ".
" + - "Time remaining: " + convertTimeMsToTimeElapsedString(this.timeNeededToCompleteWork - this.timeWorked) + "
" + + txt.innerHTML = "You are attempting to " + Player.crimeType + ".
" + + "Time remaining: " + convertTimeMsToTimeElapsedString(this.timeNeededToCompleteWork - this.timeWorked) + "
" + progressBar.replace( / /g, " " ); } @@ -1141,7 +1142,7 @@ PlayerObject.prototype.finishCrime = function(cancelled) { break; case CONSTANTS.CrimeDrugs: ++this.numTimesDealtDrugs; - this.karma -= 0.5; + this.karma -= 0.5; break; case CONSTANTS.CrimeTraffickArms: ++this.numTimesTraffickArms; @@ -1171,7 +1172,7 @@ PlayerObject.prototype.finishCrime = function(cancelled) { dialogBoxCreate("ERR: Unrecognized crime type. This is probably a bug please contact the developer"); return; } - + //On a crime success, gain 2x exp this.workHackExpGained *= 2; this.workStrExpGained *= 2; @@ -1179,32 +1180,32 @@ PlayerObject.prototype.finishCrime = function(cancelled) { this.workDexExpGained *= 2; this.workAgiExpGained *= 2; this.workChaExpGained *= 2; - - dialogBoxCreate("Crime successful!

" + - "You gained:
"+ - "$" + formatNumber(this.workMoneyGained, 2) + "
" + - formatNumber(this.workHackExpGained, 4) + " hacking experience
" + - formatNumber(this.workStrExpGained, 4) + " strength experience
" + - formatNumber(this.workDefExpGained, 4) + " defense experience
" + - formatNumber(this.workDexExpGained, 4) + " dexterity experience
" + - formatNumber(this.workAgiExpGained, 4) + " agility experience
" + + + dialogBoxCreate("Crime successful!

" + + "You gained:
"+ + "$" + formatNumber(this.workMoneyGained, 2) + "
" + + formatNumber(this.workHackExpGained, 4) + " hacking experience
" + + formatNumber(this.workStrExpGained, 4) + " strength experience
" + + formatNumber(this.workDefExpGained, 4) + " defense experience
" + + formatNumber(this.workDexExpGained, 4) + " dexterity experience
" + + formatNumber(this.workAgiExpGained, 4) + " agility experience
" + formatNumber(this.workChaExpGained, 4) + " charisma experience"); } else { - dialogBoxCreate("Crime failed!

" + - "You gained:
"+ - formatNumber(this.workHackExpGained, 4) + " hacking experience
" + - formatNumber(this.workStrExpGained, 4) + " strength experience
" + - formatNumber(this.workDefExpGained, 4) + " defense experience
" + - formatNumber(this.workDexExpGained, 4) + " dexterity experience
" + - formatNumber(this.workAgiExpGained, 4) + " agility experience
" + + dialogBoxCreate("Crime failed!

" + + "You gained:
"+ + formatNumber(this.workHackExpGained, 4) + " hacking experience
" + + formatNumber(this.workStrExpGained, 4) + " strength experience
" + + formatNumber(this.workDefExpGained, 4) + " defense experience
" + + formatNumber(this.workDexExpGained, 4) + " dexterity experience
" + + formatNumber(this.workAgiExpGained, 4) + " agility experience
" + formatNumber(this.workChaExpGained, 4) + " charisma experience"); } - + this.gainWorkExp(); } - - - + + + var mainMenu = document.getElementById("mainmenu-container"); mainMenu.style.visibility = "visible"; this.isWorking = false; @@ -1224,8 +1225,8 @@ PlayerObject.prototype.takeDamage = function(amt) { } PlayerObject.prototype.hospitalize = function() { - dialogBoxCreate("You were in critical condition! You were taken to the hospital where " + - "luckily they were able to save your life. You were charged $" + + dialogBoxCreate("You were in critical condition! You were taken to the hospital where " + + "luckily they were able to save your life. You were charged $" + formatNumber(this.max_hp * CONSTANTS.HospitalCostPerHp, 2)); Player.loseMoney(this.max_hp * CONSTANTS.HospitalCostPerHp); this.hp = this.max_hp; @@ -1238,11 +1239,8 @@ PlayerObject.prototype.toJSON = function() { PlayerObject.fromJSON = function(value) { return Generic_fromJSON(PlayerObject, value.data); -} +} Reviver.constructors.PlayerObject = PlayerObject; Player = new PlayerObject(); - - - diff --git a/src/Prestige.js b/src/Prestige.js index 890b92ae7..26a4eb8d5 100644 --- a/src/Prestige.js +++ b/src/Prestige.js @@ -15,7 +15,7 @@ function prestigeAugmentation() { Player.lifetime_agility += Player.agility; Player.total_charisma += Player.charisma; Player.lifetime_charisma += Player.charisma; - + //Crime statistics Player.numTimesShopliftedTotal += Player.numTimesShoplifted; Player.numTimesShopliftedLifetime += Player.numTimesShoplifted; @@ -41,52 +41,53 @@ function prestigeAugmentation() { Player.numTimesHeistTotal += Player.numTimesHeist; Player.numTimesHeistLifetime += Player.numTimesHeist; Player.numTimesHeist = 0; - + Player.karma = 0; - + //Reset stats Player.hacking_skill = 1; - + Player.strength = 1; Player.defense = 1; Player.dexterity = 1; Player.agility = 1; - + Player.charisma = 1; - + Player.hacking_exp = 0; Player.strength_exp = 0; Player.defense_exp = 0; Player.dexterity_exp = 0; Player.agility_exp = 0; Player.charisma_exp = 0; - + Player.money = 1000; - + Player.city = Locations.Sector12; Player.location = ""; - + Player.companyName = ""; Player.companyPosition = ""; - + Player.currentServer = ""; Player.discoveredServers = []; Player.purchasedServers = []; - + Player.factions = []; - + Player.factionInvitations = []; + Player.queuedAugmentations = []; - + Player.startAction = false; Player.actionTime = 0; - + Player.isWorking = false; Player.currentWorkFactionName = ""; Player.currentWorkFactionDescription = ""; this.createProgramName = ""; this.className = ""; this.crimeType = ""; - + Player.workHackExpGainRate = 0; Player.workStrExpGainRate = 0; Player.workDefExpGainRate = 0; @@ -95,7 +96,7 @@ function prestigeAugmentation() { Player.workChaExpGainRate = 0; Player.workRepGainRate = 0; Player.workMoneyGainRate = 0; - + Player.workHackExpGained = 0; Player.workStrExpGained = 0; Player.workDefExpGained = 0; @@ -104,18 +105,18 @@ function prestigeAugmentation() { Player.workChaExpGained = 0; Player.workRepGained = 0; Player.workMoneyGained = 0; - + Player.timeWorked = 0; - + Player.lastUpdate = new Date().getTime(); - + //Delete all Worker Scripts objects for (var i = 0; i < workerScripts.length; ++i) { deleteActiveScriptsItem(workerScripts[i]); workerScripts[i].env.stopFlag = true; } workerScripts.length = 0; - + var homeComp = Player.getHomeComputer(); //Delete all servers except home computer for (var member in AllServers) { @@ -127,7 +128,7 @@ function prestigeAugmentation() { delete SpecialServerIps[member]; } SpecialServersIps = null; - + //Reset home computer (only the programs) and add to AllServers homeComp.programs.length = 0; homeComp.runningScripts = []; @@ -136,12 +137,12 @@ function prestigeAugmentation() { homeComp.isOnline = true; homeComp.ramUsed = 0; homeComp.programs.push(Programs.NukeProgram); - if (augmentationExists(AugmentationNames.Neurolink) && + if (augmentationExists(AugmentationNames.Neurolink) && Augmentations[AugmentationNames.Neurolink].owned) { homeComp.programs.push(Programs.FTPCrackProgram); homeComp.programs.push(Programs.RelaySMTPProgram); - } - if (augmentationExists(AugmentationNames.CashRoot) && + } + if (augmentationExists(AugmentationNames.CashRoot) && Augmentations[AugmentationNames.CashRoot].owned) { Player.money = 1000000; homeComp.programs.push(Programs.BruteSSHProgram); @@ -149,57 +150,57 @@ function prestigeAugmentation() { Player.currentServer = homeComp.ip; Player.homeComputer = homeComp.ip; AddToAllServers(homeComp); - + //Re-create foreign servers SpecialServerIps = new SpecialServerIpsMap(); //Must be done before initForeignServers() initForeignServers(); - + //Darkweb is purchase-able document.getElementById("location-purchase-tor").setAttribute("class", "a-link-button"); - + //Reset statistics of all scripts on home computer for (var i = 0; i < homeComp.scripts.length; ++i) { var s = homeComp.scripts[i]; } //Delete messages on home computer homeComp.messages.length = 0; - + //Delete Hacknet Nodes Player.hacknetNodes.length = 0; Player.totalHacknetNodeProduction = 0; - + //Gain favor for Companies for (var member in Companies) { if (Companies.hasOwnProperty(member)) { Companies[member].gainFavor(); } } - + //Gain favor for factions for (var member in Factions) { if (Factions.hasOwnProperty(member)) { Factions[member].gainFavor(); } } - + //Stop a Terminal action if there is onerror if (Engine._actionInProgress) { Engine._actionInProgress = false; Terminal.finishAction(true); } - - //Re-initialize things - This will update any changes + + //Re-initialize things - This will update any changes initFactions(); //Factions must be initialized before augmentations initAugmentations(); initCompanies(); - + //Clear terminal $("#terminal tr:not(:last)").remove(); postNetburnerText(); - + //Messages initMessages(); - + //Reset Stock market if (Player.hasWseAccount) { initStockMarket(); @@ -210,13 +211,13 @@ function prestigeAugmentation() { stockMarketList.removeChild(stockMarketList.firstChild); } } - + Player.playtimeSinceLastAug = 0; - + var mainMenu = document.getElementById("mainmenu-container"); mainMenu.style.visibility = "visible"; Engine.loadTerminalContent(); - + //Red Pill if (augmentationExists(AugmentationNames.TheRedPill) && Augmentations[AugmentationNames.TheRedPill].owned) { @@ -227,4 +228,4 @@ function prestigeAugmentation() { DaedalusServer.serversOnNetwork.push(WorldDaemon.ip); } } -} \ No newline at end of file +} diff --git a/src/Script.js b/src/Script.js index eff6916bb..7a8fcacbc 100644 --- a/src/Script.js +++ b/src/Script.js @@ -173,6 +173,8 @@ function calculateRamUsage(codeCopy) { var getServerSecurityCount = numOccurrences(codeCopy, "getServerSecurityLevel("); var getServerBaseSecurityCount = numOccurrences(codeCopy, "getServerBaseSecurityLevel("); var getServerReqdHackingCount = numOccurrences(codeCopy, "getServerRequiredHackingLevel("); + var getServerNumPortsReqdCount = numOccurrences(codeCopy, "getServerNumPortsRequired("); + var getServerRamCount = numOccurrences(codeCopy, "getServerRam("); var fileExistsCount = numOccurrences(codeCopy, "fileExists("); var isRunningCount = numOccurrences(codeCopy, "isRunning("); var numOperators = numNetscriptOperators(codeCopy); @@ -185,7 +187,8 @@ function calculateRamUsage(codeCopy) { numOccurrences(codeCopy, "getStockPosition("); var scriptBuySellStockCount = numOccurrences(codeCopy, "buyStock(") + numOccurrences(codeCopy, "sellStock("); - var scriptPurchaseServerCount = numOccurrences(codeCopy, "purchaseServer("); + var scriptPurchaseServerCount = numOccurrences(codeCopy, "purchaseServer(") + + numOccurrences(codeCopy, "deleteServer("); var scriptRoundCount = numOccurrences(codeCopy, "round("); var scriptWriteCount = numOccurrences(codeCopy, "write("); var scriptReadCount = numOccurrences(codeCopy, "read("); @@ -210,11 +213,13 @@ function calculateRamUsage(codeCopy) { (hasRootAccessCount * CONSTANTS.ScriptHasRootAccessRamCost) + (getHostnameCount * CONSTANTS.ScriptGetHostnameRamCost) + (getHackingLevelCount * CONSTANTS.ScriptGetHackingLevelRamCost) + - (getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerMoneyRamCost) + - (getServerMaxMoneyCount * CONSTANTS.ScriptGetServerMoneyRamCost) + - (getServerSecurityCount * CONSTANTS.ScriptGetServerSecurityRamCost) + - (getServerBaseSecurityCount * CONSTANTS.ScriptGetServerSecurityRamCost) + - (getServerReqdHackingCount * CONSTANTS.ScriptGetServerReqdHackRamCost) + + (getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerCost) + + (getServerMaxMoneyCount * CONSTANTS.ScriptGetServerCost) + + (getServerSecurityCount * CONSTANTS.ScriptGetServerCost) + + (getServerBaseSecurityCount * CONSTANTS.ScriptGetServerCost) + + (getServerReqdHackingCount * CONSTANTS.ScriptGetServerCost) + + (getServerNumPortsReqdCount * CONSTANTS.ScriptGetServerCost) + + (getServerRamCount * CONSTANTS.ScriptGetServerCost) + (fileExistsCount * CONSTANTS.ScriptFileExistsRamCost) + (isRunningCount * CONSTANTS.ScriptIsRunningRamCost) + (numOperators * CONSTANTS.ScriptOperatorRamCost) + diff --git a/src/ServerPurchases.js b/src/ServerPurchases.js index a04785585..e3a1e0d9d 100644 --- a/src/ServerPurchases.js +++ b/src/ServerPurchases.js @@ -8,7 +8,15 @@ purchaseServer = function(ram, cost) { dialogBoxCreate("You don't have enough money to purchase this server!"); return; } - + + //Maximum of 30 servers + if (Player.purchasedServers.length >= CONSTANTS.PurchasedServerLimit) { + dialogBoxCreate("You have reached the maximum limit of " + CONSTANTS.PurchasedServerLimit + " servers. " + + "You cannot purchase any more. You can " + + "delete some of your purchased servers using the deleteServer() Netscript function in a script"); + return; + } + var newServ = new Server(); var hostname = document.getElementById("purchase-server-box-input").value; hostname = hostname.replace(/\s\s+/g, ''); @@ -16,21 +24,21 @@ purchaseServer = function(ram, cost) { dialogBoxCreate("You must enter a hostname for your new server!"); return; } - + //Create server newServ.init(createRandomIp(), hostname, "", true, false, true, true, ram); AddToAllServers(newServ); - + //Add to Player's purchasedServers array Player.purchasedServers.push(newServ.ip); - + //Connect new server to home computer var homeComputer = Player.getHomeComputer(); homeComputer.serversOnNetwork.push(newServ.ip); newServ.serversOnNetwork.push(homeComputer.ip); - - Player.loseMoney(cost); - + + Player.loseMoney(cost); + dialogBoxCreate("Server successfully purchased with hostname " + hostname); } @@ -40,11 +48,11 @@ purchaseRamForHomeComputer = function(cost) { dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer"); return; } - + var homeComputer = Player.getHomeComputer(); homeComputer.maxRam *= 2; - - Player.loseMoney(cost); - + + Player.loseMoney(cost); + dialogBoxCreate("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM."); -} \ No newline at end of file +} diff --git a/src/Settings.js b/src/Settings.js index 13e4119e3..f9aa4a127 100644 --- a/src/Settings.js +++ b/src/Settings.js @@ -1,16 +1,18 @@ /* Settings.js */ Settings = { CodeInstructionRunTime: 100, - suppressMessages: false, MaxLogCapacity: 50, MaxPortCapacity: 50, + SuppressMessages: false, + SuppressFactionInvites: false, } function initSettings() { Settings.CodeInstructionRunTime = 100; - Settings.suppressMessages = false; Settings.MaxLogCapacity = 50; Settings.MaxPortCapacity = 50; + Settings.SuppressMessages = false; + Settings.SuppressFactionInvites = false; } function setSettingsLabels() { @@ -20,4 +22,8 @@ function setSettingsLabels() { = Settings.MaxLogCapacity; document.getElementById("settingsNSPortRangeValLabel").innerHTML = Settings.MaxPortCapacity; + document.getElementById("settingsSuppressMessages").checked + = Settings.SuppressMessages; + document.getElementById("settingsSuppressFactionInvites").checked + = Settings.SuppressFactionInvites; } diff --git a/src/Terminal.js b/src/Terminal.js index 95c6acfef..0e10e0737 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -175,7 +175,9 @@ function tabCompletion(command, arg, allPossibilities, index=0) { if (!(allPossibilities.constructor === Array)) {return;} if (!containsAllStrings(allPossibilities)) {return;} - command = command.toLowerCase(); + if (!command.startsWith("./")) { + command = command.toLowerCase(); + } //Remove all options in allPossibilities that do not match the current string //that we are attempting to autocomplete @@ -243,6 +245,23 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) { var currServ = Player.getCurrentServer(); input = input.toLowerCase(); + //If the command starts with './' and the index == -1, then the user + //has input ./partialexecutablename so autocomplete the script or program + //Put './' in front of each script/executable + if (input.startsWith("./") && index == -1) { + //All programs and scripts + for (var i = 0; i < currServ.scripts.length; ++i) { + allPos.push("./" + currServ.scripts[i].filename); + } + + //Programs are on home computer + var homeComputer = Player.getHomeComputer(); + for(var i = 0; i < homeComputer.programs.length; ++i) { + allPos.push("./" + homeComputer.programs[i]); + } + return allPos; + } + //Autocomplete the command if (index == -1) { return ["alias", "analyze", "cat", "check", "clear", "cls", "connect", "free", @@ -447,7 +466,7 @@ var Terminal = { //Allow usage of ./ if (command.startsWith("./")) { - command = command.slice(0, 2) + " " + command.slice(2); + command = "run " + command.slice(2); } //Only split the first space @@ -895,7 +914,6 @@ var Terminal = { post("No such file exists"); break; case "run": - case "./": //Run a program or a script if (commandArray.length != 2) { post("Incorrect number of arguments. Usage: run [program/script] [-t] [num threads] [arg1] [arg2]..."); diff --git a/src/engine.js b/src/engine.js index 1d2ce0d4b..385d841c0 100644 --- a/src/engine.js +++ b/src/engine.js @@ -485,9 +485,8 @@ var Engine = { }, displayFactionsInfo: function() { + //Clear the list of joined factions var factionsList = document.getElementById("factions-list"); - - //Clear the list while (factionsList.firstChild) { factionsList.removeChild(factionsList.firstChild); } @@ -500,7 +499,6 @@ var Engine = { //Add the faction to the Factions page content var item = document.createElement("li"); var aElem = document.createElement("a"); - aElem.setAttribute("href", "#"); aElem.setAttribute("class", "a-link-button"); aElem.innerHTML = factionName; aElem.addEventListener("click", function() { @@ -509,10 +507,54 @@ var Engine = { return false; }); item.appendChild(aElem); - factionsList.appendChild(item); }()); //Immediate invocation } + + //Clear the list of invitations + var invitationsList = document.getElementById("outstanding-faction-invitations-list"); + while (invitationsList.firstChild) { + invitationsList.removeChild(invitationsList.firstChild); + } + + //Add a link to accept for each faction you have invitiations for + for (var i = 0; i < Player.factionInvitations.length; ++i) { + (function () { + var factionName = Player.factionInvitations[i]; + + var item = document.createElement("li"); + + var pElem = document.createElement("p"); + pElem.innerText = factionName; + pElem.style.display = "inline"; + pElem.style.margin = "4px"; + pElem.style.padding = "4px"; + + var aElem = document.createElement("a"); + aElem.innerText = "Accept Faction Invitation"; + aElem.setAttribute("class", "a-link-button"); + aElem.style.display = "inline"; + aElem.style.margin = "4px"; + aElem.style.padding = "4px"; + aElem.addEventListener("click", function() { + joinFaction(Factions[factionName]); + for (var i = 0; i < Player.factionInvitations.length; ++i) { + if (Player.factionInvitations[i] == factionName) { + Player.factionInvitations.splice(i, 1); + break; + } + } + Engine.displayFactionsInfo(); + return false; + }); + + item.appendChild(pElem); + item.appendChild(aElem); + item.style.margin = "6px"; + item.style.padding = "6px"; + invitationsList.appendChild(item); + }()); + } }, displayAugmentationsContent: function() { @@ -693,7 +735,7 @@ var Engine = { updateSkillLevelsCounter: 10, //Only update skill levels every 2 seconds. Might improve performance updateDisplays: 3, //Update displays such as Active Scripts display and character display createProgramNotifications: 10, //Checks whether any programs can be created and notifies - checkFactionInvitations: 100, //Check whether you qualify for any faction invitations every 5 minutes + checkFactionInvitations: 100, //Check whether you qualify for any faction invitations passiveFactionGrowth: 600, messages: 150, stockTick: 30, //Update stock prices diff --git a/utils/FactionInvitationBox.js b/utils/FactionInvitationBox.js index 2c7912969..65832f01e 100644 --- a/utils/FactionInvitationBox.js +++ b/utils/FactionInvitationBox.js @@ -23,20 +23,21 @@ factionInvitationSetMessage = function(msg) { factionInvitationBoxCreate = function(faction) { factionInvitationSetText("You have received a faction invitation from " + faction.name); //TODO Faction invitation message - + var newYesButton = clearEventListeners("faction-invitation-box-yes"); newYesButton.addEventListener("click", function() { joinFaction(faction); factionInvitationBoxClose(); return false; }); - + var noButton = clearEventListeners("faction-invitation-box-no"); noButton.addEventListener("click", function() { factionInvitationBoxClose(); faction.alreadyInvited = true; + Player.factionInvitations.push(faction.name); return false; }); - + factionInvitationBoxOpen(); -} \ No newline at end of file +}