From a1da58f2a9284239d330707d1c0953b2c7f97356 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Tue, 5 Jun 2018 01:27:18 -0400 Subject: [PATCH 1/5] fix faction reputation --- src/Faction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Faction.js b/src/Faction.js index b349aaa32..261b7b254 100644 --- a/src/Faction.js +++ b/src/Faction.js @@ -599,7 +599,7 @@ function createFactionAugmentationDisplayElements(augmentationsList, augs, facti var pElem = createElement("p", { display:"inline", }) - var req = aug.baseRepRequirement * faction.augmentationRepRequirementMult; + var req = aug.baseRepRequirement * factionInfo.augmentationRepRequirementMult; var hasPrereqs = hasAugmentationPrereqs(aug); if (!hasPrereqs) { aElem.setAttribute("class", "a-link-button-inactive"); From 3e429e30bee5a0cc57d574b2d505cfb51aad25e6 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Tue, 5 Jun 2018 01:58:34 -0400 Subject: [PATCH 2/5] bn12 plus faction fix from my last pr --- src/Augmentations.js | 3 ++- src/BitNode.js | 50 +++++++++++++++++++++++++++++++++++++++++--- src/Faction.js | 9 ++++---- src/RedPill.js | 2 +- src/SourceFile.js | 38 ++++++++++++++++++++++++++++++++- 5 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/Augmentations.js b/src/Augmentations.js index df36c6e81..3ea75815c 100644 --- a/src/Augmentations.js +++ b/src/Augmentations.js @@ -2594,8 +2594,9 @@ function displaySourceFiles(listElement, sourceFiles) { console.log("ERROR: Invalid source file number: " + sourceFiles[i].n); continue; } + const maxLevel = sourceFiles[i].n == 12 ? "∞" : "3"; var accordion = createAccordionElement({ - hdrText:sourceFileObject.name + "
" + "Level " + (sourceFiles[i].lvl) + " / 3", + hdrText:sourceFileObject.name + "
" + "Level " + (sourceFiles[i].lvl) + " / "+maxLevel, panelText:sourceFileObject.info }); diff --git a/src/BitNode.js b/src/BitNode.js index 619caa90c..52a65f917 100644 --- a/src/BitNode.js +++ b/src/BitNode.js @@ -156,10 +156,9 @@ function initBitNodes() { "Level 1: 24%
" + "Level 2: 36%
" + "Level 3: 42%"); - + BitNodes["BitNode12"] = new BitNode(12, "The testing ground", "Ender improvement center", "Something about this bitnode being the testing ground for the enders security. This bitnode is infinitely repeatable but gets harder each time. This awards Source-File 12 which awards 1% to all stats each time this bitnode is destroyed."); //Books: Frontera, Shiner - BitNodes["BitNode12"] = new BitNode(12, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes - BitNodes["BitNode13"] = new BitNode(13, "", "COMING SOON"); + BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON"); BitNodes["BitNode15"] = new BitNode(15, "", "COMING SOON"); BitNodes["BitNode16"] = new BitNode(16, "", "COMING SOON"); @@ -304,6 +303,51 @@ function initBitNodeMultipliers() { BitNodeMultipliers.InfiltrationRep = 2.5; BitNodeMultipliers.CorporationValuation = 0.01; break; + case 12: //The Testing Ground + let sf12Lvl = 0; + for(let i = 0; i < Player.sourceFiles.length; i++) { + if(Player.sourceFiles[i].n == 12) { + sf12Lvl = Player.sourceFiles[i].lvl; + } + } + const inc = Math.pow(1.01, sf12Lvl); + const dec = Math.pow(0.99, sf12Lvl); + BitNodeMultipliers.HackingLevelMultiplier = dec; + + BitNodeMultipliers.ServerMaxMoney = dec; + BitNodeMultipliers.ServerStartingMoney = dec; + BitNodeMultipliers.ServerGrowthRate = dec; + BitNodeMultipliers.ServerWeakenRate = dec; + + //this one is special because it can cause the min + //security to go over 100 and make it impossible to + //get money through hacking. This stat should not be + + //BitNodeMultipliers.ServerStartingSecurity = inc; + + BitNodeMultipliers.ManualHackMoney = dec; + BitNodeMultipliers.ScriptHackMoney = dec; + BitNodeMultipliers.CompanyWorkMoney = dec; + BitNodeMultipliers.CrimeMoney = dec; + BitNodeMultipliers.HacknetNodeMoney = dec; + + BitNodeMultipliers.CompanyWorkExpGain = dec; + BitNodeMultipliers.ClassGymExpGain = dec; + BitNodeMultipliers.FactionWorkExpGain = dec; + BitNodeMultipliers.HackExpGain = dec; + BitNodeMultipliers.CrimeExpGain = dec; + + BitNodeMultipliers.FactionWorkRepGain = dec; + BitNodeMultipliers.FactionPassiveRepGain = dec; + BitNodeMultipliers.RepToDonateToFaction = inc; + + BitNodeMultipliers.AugmentationRepCost = inc; + BitNodeMultipliers.AugmentationMoneyCost = inc; + + BitNodeMultipliers.InfiltrationMoney = dec; + BitNodeMultipliers.InfiltrationRep = dec; + + BitNodeMultipliers.CorporationValuation = dec; default: console.log("WARNING: Player.bitNodeN invalid"); break; diff --git a/src/Faction.js b/src/Faction.js index 261b7b254..034b27678 100644 --- a/src/Faction.js +++ b/src/Faction.js @@ -626,7 +626,7 @@ function createFactionAugmentationDisplayElements(augmentationsList, augs, facti } function purchaseAugmentationBoxCreate(aug, fac) { - const factionInfo = fac.info(); + const factionInfo = fac.getInfo(); var yesBtn = yesNoBoxGetYesButton(), noBtn = yesNoBoxGetNoButton(); yesBtn.innerHTML = "Purchase"; noBtn.innerHTML = "Cancel"; @@ -671,12 +671,13 @@ function hasAugmentationPrereqs(aug) { } function purchaseAugmentation(aug, fac, sing=false) { + const factionInfo = fac.getInfo(); var hasPrereqs = hasAugmentationPrereqs(aug); if (!hasPrereqs) { var txt = "You must first purchase or install " + aug.prereqs.join(",") + " before you can " + "purchase this one."; if (sing) {return txt;} else {dialogBoxCreate(txt);} - } else if (Player.money.lt(aug.baseCost * fac.augmentationPriceMult)) { + } else if (Player.money.lt(aug.baseCost * factionInfo.augmentationPriceMult)) { let txt = "You don't have enough money to purchase " + aug.name; if (sing) {return txt;} dialogBoxCreate(txt); @@ -684,7 +685,7 @@ function purchaseAugmentation(aug, fac, sing=false) { let txt = "You don't have enough faction reputation to purchase " + aug.name; if (sing) {return txt;} dialogBoxCreate(txt); - } else if (Player.money.gte(aug.baseCost * fac.augmentationPriceMult)) { + } else if (Player.money.gte(aug.baseCost * factionInfo.augmentationPriceMult)) { if (Player.firstAugPurchased === false) { Player.firstAugPurchased = true; document.getElementById("augmentations-tab").style.display = "list-item"; @@ -698,7 +699,7 @@ function purchaseAugmentation(aug, fac, sing=false) { } Player.queuedAugmentations.push(queuedAugmentation); - Player.loseMoney((aug.baseCost * fac.augmentationPriceMult)); + Player.loseMoney((aug.baseCost * factionInfo.augmentationPriceMult)); //If you just purchased Neuroflux Governor, recalculate the cost if (aug.name == AugmentationNames.NeuroFluxGovernor) { diff --git a/src/RedPill.js b/src/RedPill.js index 9a35bf04f..ffa550eb2 100644 --- a/src/RedPill.js +++ b/src/RedPill.js @@ -208,7 +208,7 @@ function loadBitVerse(destroyedBitNodeNum, flume=false) { var elemId = "bitnode-" + i.toString(); var elem = clearEventListeners(elemId); if (elem == null) {return;} - if (i === 1 || i === 2 || i === 3 || i === 4 || i === 5 || i === 6 || i === 8 || i === 11) { + if (i === 1 || i === 2 || i === 3 || i === 4 || i === 5 || i === 6 || i === 8 || i === 11 || i === 12) { elem.addEventListener("click", function() { var bitNodeKey = "BitNode" + i; var bitNode = BitNodes[bitNodeKey]; diff --git a/src/SourceFile.js b/src/SourceFile.js index 80a5132fb..ab9796116 100644 --- a/src/SourceFile.js +++ b/src/SourceFile.js @@ -66,7 +66,7 @@ function initSourceFiles() { "Level 1: 24%
" + "Level 2: 36%
" + "Level 3: 42%
"); - SourceFiles["SourceFile12"] = new SourceFile(12); + SourceFiles["SourceFile12"] = new SourceFile(12, "This Source-File increases all your multipliers by 1% per level"); } function PlayerOwnedSourceFile(number, level) { @@ -181,6 +181,42 @@ function applySourceFile(srcFile) { Player.work_money_mult *= incMult; Player.company_rep_mult *= incMult; break; + case 12: //The testing ground + const inc = Math.pow(1.01, srcFile.lvl); + const dec = Math.pow(0.99, srcFile.lvl); + + Player.hacking_chance_mult *= inc; + Player.hacking_speed_mult *= inc; + Player.hacking_money_mult *= inc; + Player.hacking_grow_mult *= inc; + Player.hacking_mult *= inc; + + Player.strength_mult *= inc; + Player.defense_mult *= inc; + Player.dexterity_mult *= inc; + Player.agility_mult *= inc; + Player.charisma_mult *= inc; + + Player.hacking_exp_mult *= inc; + Player.strength_exp_mult *= inc; + Player.defense_exp_mult *= inc; + Player.dexterity_exp_mult *= inc; + Player.agility_exp_mult *= inc; + Player.charisma_exp_mult *= inc; + + Player.company_rep_mult *= inc; + Player.faction_rep_mult *= inc; + + Player.crime_money_mult *= inc; + Player.crime_success_mult *= inc; + + Player.hacknet_node_money_mult *= inc; + Player.hacknet_node_purchase_cost_mult *= dec; + Player.hacknet_node_ram_cost_mult *= dec; + Player.hacknet_node_core_cost_mult *= dec; + Player.hacknet_node_level_cost_mult *= dec; + + Player.work_money_mult *= inc; default: console.log("ERROR: Invalid source file number: " + srcFile.n); break; From bcabc72c353ba49b5cf8fec7b76cbf79f7eed7c7 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Tue, 5 Jun 2018 02:52:59 -0400 Subject: [PATCH 3/5] Update RedPill.js --- src/RedPill.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RedPill.js b/src/RedPill.js index ffa550eb2..60ad4104e 100644 --- a/src/RedPill.js +++ b/src/RedPill.js @@ -113,7 +113,7 @@ function giveSourceFile(bitNodeNumber) { } if (alreadyOwned && ownedSourceFile) { - if (ownedSourceFile.lvl >= 3) { + if (ownedSourceFile.lvl >= 3 && ownedSourceFile.n !== 12) { dialogBoxCreate("The Source-File for the BitNode you just destroyed, " + sourceFile.name + ", " + "is already at max level!"); } else { From 720478377f5169618e1a143567c1e103035af62b Mon Sep 17 00:00:00 2001 From: Steven Evans Date: Tue, 5 Jun 2018 13:19:33 -0400 Subject: [PATCH 4/5] [feat] Shrunk the UI of Hacknet Nodes to view more at a time on screen. The UI of a single Hacknet Node now only takes up ~50% of the screen. This allows two nodes to be displayed per "row" when the screen is wide enough. Also repositioned the buttons for the nodes so they are inline with the information each updates. This visual correlation lets us reduce the text that needs to be in each button. Also reduced the amount of DOM that needs to be continuously garbage collected by updating specific text rather than throwing out entire HTML elements. --- css/menupages.css | 41 +++-- css/styles.css | 5 +- index.html | 7 +- src/HacknetNode.js | 321 ++++++++++++++++++++++++--------------- utils/HelperFunctions.js | 17 ++- 5 files changed, 253 insertions(+), 138 deletions(-) diff --git a/css/menupages.css b/css/menupages.css index 93bdf5638..adce7407f 100644 --- a/css/menupages.css +++ b/css/menupages.css @@ -288,30 +288,39 @@ } #hacknet-nodes-text, -#hacknet-nodes-money, #hacknet-nodes-container li { - width: 70%; margin: 10px; padding: 10px; } -#hacknet-nodes-purchase-button { - display: inline-block; +#hacknet-nodes-container li { + float: left; + overflow: hidden; + white-space: nowrap; +} + +#hacknet-nodes-money { + margin: 10px; + float: left; } #hacknet-nodes-money-multipliers-div { display: inline-block; - width: 70%; + width: 80%; } #hacknet-nodes-multipliers { float: right; } +#hacknet-nodes-purchase-button { + display: inline-block; +} + .hacknet-node { margin: 6px; padding: 6px; - width: 85%; + width: 40%; border: 2px solid var(--my-highlight-color); -webkit-box-shadow: inset 0 0 8px rgba(0,0,0,0.1), @@ -324,12 +333,24 @@ 0 0 16px rgba(0,0,0,0.1); } -.hacknet-node-button-div a { - display: block; +.hacknet-node-container { + display: inline-table; } -.hacknet-node-button-div:not(:last-child) { - border-bottom: none; +.hacknet-node-container .row { + display: table-row; + height: 30px; +} + +.hacknet-node-container .row p { + display: table-cell; +} + +.hacknet-node-container .upgradable-info { + display: inline-block; + margin: 0 4px; /* Don't want the vertical margin/padding, just left & right */ + padding: 0 4px; + width: 48px; /* Four times font-size */ } /* World */ diff --git a/css/styles.css b/css/styles.css index a1b46268c..7928f8446 100644 --- a/css/styles.css +++ b/css/styles.css @@ -15,7 +15,10 @@ body { background-color: var(--my-background-color); } -p, pre, h2 { +p, +pre, +h2, +.text { color: var(--my-font-color); } diff --git a/index.html b/index.html index ad7741b63..63c4c0c80 100644 --- a/index.html +++ b/index.html @@ -199,8 +199,11 @@

Purchase Hacknet Node
-
" -

+
+

+ Money:
+ Total Hacknet Node Prodution: +

x1 x5 diff --git a/src/HacknetNode.js b/src/HacknetNode.js index 8461dd58a..9b833df05 100644 --- a/src/HacknetNode.js +++ b/src/HacknetNode.js @@ -5,42 +5,48 @@ import {iTutorialSteps, iTutorialNextStep, iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial.js"; import {Player} from "./Player.js"; import {dialogBoxCreate} from "../utils/DialogBox.js"; -import {clearEventListeners} from "../utils/HelperFunctions.js"; +import {clearEventListeners, createElement, + getElementById} from "../utils/HelperFunctions.js"; import {Reviver, Generic_toJSON, Generic_fromJSON} from "../utils/JSONReviver.js"; import {formatNumber} from "../utils/StringHelperFunctions.js"; +/** + * Overwrites the inner text of the specified HTML element if it is different from what currently exists. + * @param {string} elementId The HTML ID to find the first instance of. + * @param {string} text The inner text that should be set. + */ +function updateText(elementId, text) { + var el = getElementById(elementId); + if (el.innerText != text) { + el.innerText = text; + } +}; + /* HacknetNode.js */ function hacknetNodesInit() { - var mult1x = document.getElementById("hacknet-nodes-1x-multiplier"); - mult1x.addEventListener("click", function() { - hacknetNodePurchaseMultiplier = 1; - updateHacknetNodesMultiplierButtons(); - updateHacknetNodesContent(); - return false; - }); - var mult5x = document.getElementById("hacknet-nodes-5x-multiplier"); - mult5x.addEventListener("click", function() { - hacknetNodePurchaseMultiplier = 5; - updateHacknetNodesMultiplierButtons(); - updateHacknetNodesContent(); - return false; - }); - var mult10x = document.getElementById("hacknet-nodes-10x-multiplier"); - mult10x.addEventListener("click", function() { - hacknetNodePurchaseMultiplier = 10; - updateHacknetNodesMultiplierButtons(); - updateHacknetNodesContent(); - return false; - }); - var multMax = document.getElementById("hacknet-nodes-max-multiplier"); - multMax.addEventListener("click", function() { - hacknetNodePurchaseMultiplier = 0; - updateHacknetNodesMultiplierButtons(); - updateHacknetNodesContent(); - return false; - }); + var performMapping = function(x) { + getElementById("hacknet-nodes-" + x.id + "-multiplier") + .addEventListener("click", function() { + hacknetNodePurchaseMultiplier = x.multiplier; + updateHacknetNodesMultiplierButtons(); + updateHacknetNodesContent(); + return false; + }); + }; + + var mappings = [ + { id: "1x", multiplier: 1 }, + { id: "5x", multiplier: 5 }, + { id: "10x", multiplier: 10 }, + { id: "max", multiplier: 0 } + ]; + for (var elem of mappings) { + // Encapsulate in a function so that the appropriate scope is kept in the click handler. + performMapping(elem); + } } + document.addEventListener("DOMContentLoaded", hacknetNodesInit, false); function HacknetNode(name) { @@ -76,7 +82,10 @@ HacknetNode.prototype.updateMoneyGainRate = function() { HacknetNode.prototype.calculateLevelUpgradeCost = function(levels=1) { levels = Math.round(levels); - if (isNaN(levels) || levels < 1) {return 0;} + if (isNaN(levels) || levels < 1) { + return 0; + } + var mult = CONSTANTS.HacknetNodeUpgradeLevelMult; var totalMultiplier = 0; //Summed var currLevel = this.level; @@ -84,6 +93,7 @@ HacknetNode.prototype.calculateLevelUpgradeCost = function(levels=1) { totalMultiplier += Math.pow(mult, currLevel); ++currLevel; } + return CONSTANTS.BaseCostForHacknetNode / 2 * totalMultiplier * Player.hacknet_node_level_cost_mult; } @@ -95,12 +105,19 @@ HacknetNode.prototype.getLevelUpgradeCost = function(levels=1) { HacknetNode.prototype.purchaseLevelUpgrade = function(levels=1) { levels = Math.round(levels); var cost = this.calculateLevelUpgradeCost(levels); - if (isNaN(cost) || levels < 0) {return false;} + if (isNaN(cost) || levels < 0) { + return false; + } + if (this.level + levels > CONSTANTS.HacknetNodeMaxLevel) { var diff = Math.max(0, CONSTANTS.HacknetNodeMaxLevel - this.level); return this.purchaseLevelUpgrade(diff); } - if (Player.money.lt(cost)) {return false;} + + if (Player.money.lt(cost)) { + return false; + } + Player.loseMoney(cost); this.level += levels; this.updateMoneyGainRate(); @@ -129,9 +146,18 @@ HacknetNode.prototype.getRamUpgradeCost = function() { HacknetNode.prototype.purchaseRamUpgrade = function() { var cost = this.calculateRamUpgradeCost(); - if (isNaN(cost)) {return false;} - if (Player.money.lt(cost)) {return false;} - if (this.ram >= CONSTANTS.HacknetNodeMaxRam) {return false;} + if (isNaN(cost)) { + return false; + } + + if (Player.money.lt(cost)) { + return false; + } + + if (this.ram >= CONSTANTS.HacknetNodeMaxRam) { + return false; + } + Player.loseMoney(cost); this.ram *= 2; //Ram is always doubled this.updateMoneyGainRate(); @@ -146,7 +172,7 @@ HacknetNode.prototype.upgradeRam = function() { HacknetNode.prototype.calculateCoreUpgradeCost = function() { var coreBaseCost = CONSTANTS.BaseCostForHacknetNodeCore; var mult = CONSTANTS.HacknetNodeUpgradeCoreMult; - return coreBaseCost * Math.pow(mult, this.cores-1) * Player.hacknet_node_core_cost_mult; + return coreBaseCost * Math.pow(mult, this.cores - 1) * Player.hacknet_node_core_cost_mult; } //Wrapper function for Netscript @@ -156,9 +182,18 @@ HacknetNode.prototype.getCoreUpgradeCost = function() { HacknetNode.prototype.purchaseCoreUpgrade = function() { var cost = this.calculateCoreUpgradeCost(); - if (isNaN(cost)) {return false;} - if (Player.money.lt(cost)) {return false;} - if (this.cores >= CONSTANTS.HacknetNodeMaxCores) {return false;} + if (isNaN(cost)) { + return false; + } + + if (Player.money.lt(cost)) { + return false; + } + + if (this.cores >= CONSTANTS.HacknetNodeMaxCores) { + return false; + } + Player.loseMoney(cost); ++this.cores; this.updateMoneyGainRate(); @@ -225,7 +260,10 @@ function purchaseHacknet() { /* END INTERACTIVE TUTORIAL */ var cost = getCostOfNextHacknetNode(); - if (isNaN(cost)) {throw new Error("Cost is NaN"); return;} + if (isNaN(cost)) { + throw new Error("Cost is NaN"); + } + if (Player.money.lt(cost)) { //dialogBoxCreate("You cannot afford to purchase a Hacknet Node!"); return false; @@ -290,9 +328,12 @@ function updateHacknetNodesMultiplierButtons() { //Calculate the maximum number of times the Player can afford to upgrade //a Hacknet Node's level" function getMaxNumberLevelUpgrades(nodeObj) { - if (Player.money.lt(nodeObj.calculateLevelUpgradeCost(1))) {return 0;} + if (Player.money.lt(nodeObj.calculateLevelUpgradeCost(1))) { + return 0; + } + var min = 1; - var max = CONSTANTS.HacknetNodeMaxLevel-1; + var max = CONSTANTS.HacknetNodeMaxLevel - 1; var levelsToMax = CONSTANTS.HacknetNodeMaxLevel - nodeObj.level; if (Player.money.gt(nodeObj.calculateLevelUpgradeCost(levelsToMax))) { return levelsToMax; @@ -302,7 +343,7 @@ function getMaxNumberLevelUpgrades(nodeObj) { var curr = (min + max) / 2 | 0; if (curr != CONSTANTS.HacknetNodeMaxLevel && Player.money.gt(nodeObj.calculateLevelUpgradeCost(curr)) && - Player.money.lt(nodeObj.calculateLevelUpgradeCost(curr+1))) { + Player.money.lt(nodeObj.calculateLevelUpgradeCost(curr + 1))) { return Math.min(levelsToMax, curr); } else if (Player.money.lt(nodeObj.calculateLevelUpgradeCost(curr))) { max = curr - 1; @@ -329,7 +370,7 @@ function displayHacknetNodesContent() { //Remove all old hacknet Node DOM elements var hacknetNodesList = document.getElementById("hacknet-nodes-list"); - while (hacknetNodesList.firstChild) { + while (hacknetNodesList.firstChild) { hacknetNodesList.removeChild(hacknetNodesList.firstChild); } @@ -337,6 +378,7 @@ function displayHacknetNodesContent() { for (var i = 0; i < Player.hacknetNodes.length; ++i) { createHacknetNodeDomElement(Player.hacknetNodes[i]); } + updateHacknetNodesContent(); } @@ -344,8 +386,11 @@ function displayHacknetNodesContent() { function updateHacknetNodesContent() { //Set purchase button to inactive if not enough money, and update its price display var cost = getCostOfNextHacknetNode(); - var purchaseButton = document.getElementById("hacknet-nodes-purchase-button"); - purchaseButton.innerHTML = "Purchase Hacknet Node - $" + formatNumber(cost, 2); + var purchaseButton = getElementById("hacknet-nodes-purchase-button"); + var formattedCost = formatNumber(cost, 2); + + updateText("hacknet-nodes-purchase-button", "Purchase Hacknet Node - $" + formattedCost); + if (Player.money.lt(cost)) { purchaseButton.setAttribute("class", "a-link-button-inactive"); } else { @@ -353,9 +398,8 @@ function updateHacknetNodesContent() { } //Update player's money - var moneyElem = document.getElementById("hacknet-nodes-money"); - moneyElem.innerHTML = "Money: $" + formatNumber(Player.money.toNumber(), 2) + "
" + - "Total production from all Hacknet Nodes: $" + formatNumber(Player.totalHacknetNodeProduction, 2) + " / second"; + updateText("hacknet-nodes-player-money", "$" + formatNumber(Player.money.toNumber(), 2)); + updateText("hacknet-nodes-total-production", "$" + formatNumber(Player.totalHacknetNodeProduction, 2) + " / second"); //Update information in each owned hacknet node for (var i = 0; i < Player.hacknetNodes.length; ++i) { @@ -367,61 +411,75 @@ function updateHacknetNodesContent() { function createHacknetNodeDomElement(nodeObj) { var nodeName = nodeObj.name; - var listItem = document.createElement("li"); - listItem.setAttribute("class", "hacknet-node"); + var nodeLevelContainer = createElement("div", { + class: "hacknet-node-level-container row", + innerHTML: "

Level:

" + }); - var span = document.createElement("span"); - span.style.display = "inline"; + var nodeRamContainer = createElement("div", { + class: "hacknet-node-ram-container row", + innerHTML: "

RAM:

" + }); - var buttonDiv = document.createElement("div"); - buttonDiv.setAttribute("class", "hacknet-node-button-div"); + var nodeCoresContainer = createElement("div", { + class: "hacknet-node-cores-container row", + innerHTML: "

Cores:

" + }) + var containingDiv = createElement("div", { + class: "hacknet-node-container", + innerHTML: "
" + + "

Node name:

" + + "" + + "
" + + "
" + + "

Production:

" + + "" + + "" + + "
" + }); + containingDiv.appendChild(nodeLevelContainer); + containingDiv.appendChild(nodeRamContainer); + containingDiv.appendChild(nodeCoresContainer); - //Text - var txt = document.createElement("p"); - //txt.setAttribute("id", "hacknet-node-text-" + nodeName); - txt.id = "hacknet-node-text-" + nodeName; + var listItem = createElement("li", { + class: "hacknet-node" + }); + listItem.appendChild(containingDiv); //Upgrade buttons - var upgradeLevelButton = document.createElement("a"); - var upgradeRamButton = document.createElement("a"); - var upgradeCoreButton = document.createElement("a"); - - //upgradeLevelButton.setAttribute("id", "hacknet-node-upgrade-level-" + nodeName); - upgradeLevelButton.id = "hacknet-node-upgrade-level-" + nodeName; - upgradeLevelButton.setAttribute("class", "a-link-button-inactive"); - upgradeLevelButton.addEventListener("click", function() { - var numUpgrades = hacknetNodePurchaseMultiplier; - if (hacknetNodePurchaseMultiplier == 0) { - numUpgrades = getMaxNumberLevelUpgrades(nodeObj); + nodeLevelContainer.appendChild(createElement("a", { + id: "hacknet-node-upgrade-level-" + nodeName, + class: "a-link-button-inactive", + clickListener: function() { + var numUpgrades = hacknetNodePurchaseMultiplier; + if (hacknetNodePurchaseMultiplier == 0) { + numUpgrades = getMaxNumberLevelUpgrades(nodeObj); + } + nodeObj.purchaseLevelUpgrade(numUpgrades); + updateHacknetNodesContent(); + return false; } - nodeObj.purchaseLevelUpgrade(numUpgrades); - updateHacknetNodesContent(); - return false; - }); - //upgradeRamButton.setAttribute("id", "hacknet-node-upgrade-ram-" + nodeName); - upgradeRamButton.id = "hacknet-node-upgrade-ram-" + nodeName; - upgradeRamButton.setAttribute("class", "a-link-button-inactive"); - upgradeRamButton.addEventListener("click", function() { - nodeObj.purchaseRamUpgrade(); - updateHacknetNodesContent(); - return false; - }); - //upgradeCoreButton.setAttribute("id", "hacknet-node-upgrade-core-" + nodeName); - upgradeCoreButton.id = "hacknet-node-upgrade-core-" + nodeName; - upgradeCoreButton.setAttribute("class", "a-link-button-inactive"); - upgradeCoreButton.addEventListener("click", function() { - nodeObj.purchaseCoreUpgrade(); - updateHacknetNodesContent(); - return false; - }); + })); - //Put all the components together in the li element - span.appendChild(txt); - buttonDiv.appendChild(upgradeLevelButton); - buttonDiv.appendChild(upgradeRamButton); - buttonDiv.appendChild(upgradeCoreButton); - span.appendChild(buttonDiv); - listItem.appendChild(span); + nodeRamContainer.appendChild(createElement("a", { + id: "hacknet-node-upgrade-ram-" + nodeName, + class: "a-link-button-inactive", + clickListener: function() { + nodeObj.purchaseRamUpgrade(); + updateHacknetNodesContent(); + return false; + } + })); + + nodeCoresContainer.appendChild(createElement("a", { + id: "hacknet-node-upgrade-core-" + nodeName, + class: "a-link-button-inactive", + clickListener: function() { + nodeObj.purchaseCoreUpgrade(); + updateHacknetNodesContent(); + return false; + } + })); document.getElementById("hacknet-nodes-list").appendChild(listItem); @@ -432,20 +490,19 @@ function createHacknetNodeDomElement(nodeObj) { //Updates information on a single hacknet node DOM element function updateHacknetNodeDomElement(nodeObj) { var nodeName = nodeObj.name; - var txt = document.getElementById("hacknet-node-text-" + nodeName); - if (txt == null) {throw new Error("Cannot find text element");} - txt.innerHTML = "Node name: " + nodeName + "
" + - "Production: $" + formatNumber(nodeObj.totalMoneyGenerated, 2) + - " ($" + formatNumber(nodeObj.moneyGainRatePerSecond, 2) + " / second)
" + - "Level: " + nodeObj.level + "
" + - "RAM: " + nodeObj.ram + "GB
" + - "Cores: " + nodeObj.cores; + + updateText("hacknet-node-name-" + nodeName, nodeName); + updateText("hacknet-node-total-production-" + nodeName, "$" + formatNumber(nodeObj.totalMoneyGenerated, 2)); + updateText("hacknet-node-production-rate-" + nodeName, "($" + formatNumber(nodeObj.moneyGainRatePerSecond, 2) + " / second)"); + updateText("hacknet-node-level-" + nodeName, nodeObj.level); + updateText("hacknet-node-ram-" + nodeName, nodeObj.ram + "GB"); + updateText("hacknet-node-cores-" + nodeName, nodeObj.cores); //Upgrade level - var upgradeLevelButton = document.getElementById("hacknet-node-upgrade-level-" + nodeName); - if (upgradeLevelButton == null) {throw new Error("Cannot find upgrade level button element");} + var upgradeLevelButton = getElementById("hacknet-node-upgrade-level-" + nodeName); + if (nodeObj.level >= CONSTANTS.HacknetNodeMaxLevel) { - upgradeLevelButton.innerHTML = "MAX LEVEL"; + updateText("hacknet-node-upgrade-level-" + nodeName, "MAX LEVEL"); upgradeLevelButton.setAttribute("class", "a-link-button-inactive"); } else { var multiplier = 0; @@ -458,8 +515,7 @@ function updateHacknetNodeDomElement(nodeObj) { } var upgradeLevelCost = nodeObj.calculateLevelUpgradeCost(multiplier); - upgradeLevelButton.innerHTML = "Upgrade Hacknet Node Level x" + multiplier + - " - $" + formatNumber(upgradeLevelCost, 2); + updateText("hacknet-node-upgrade-level-" + nodeName, "Upgrade x" + multiplier + " - $" + formatNumber(upgradeLevelCost, 2)) if (Player.money.lt(upgradeLevelCost)) { upgradeLevelButton.setAttribute("class", "a-link-button-inactive"); } else { @@ -468,14 +524,14 @@ function updateHacknetNodeDomElement(nodeObj) { } //Upgrade RAM - var upgradeRamButton = document.getElementById("hacknet-node-upgrade-ram-" + nodeName); - if (upgradeRamButton == null) {throw new Error("Cannot find upgrade ram button element");} + var upgradeRamButton = getElementById("hacknet-node-upgrade-ram-" + nodeName); + if (nodeObj.ram >= CONSTANTS.HacknetNodeMaxRam) { - upgradeRamButton.innerHTML = "MAX RAM"; + updateText("hacknet-node-upgrade-ram-" + nodeName, "MAX RAM"); upgradeRamButton.setAttribute("class", "a-link-button-inactive"); } else { var upgradeRamCost = nodeObj.calculateRamUpgradeCost(); - upgradeRamButton.innerHTML = "Upgrade Hacknet Node RAM - $" + formatNumber(upgradeRamCost, 2); + updateText("hacknet-node-upgrade-ram-" + nodeName, "Upgrade - $" + formatNumber(upgradeRamCost, 2)); if (Player.money.lt(upgradeRamCost)) { upgradeRamButton.setAttribute("class", "a-link-button-inactive"); } else { @@ -484,14 +540,14 @@ function updateHacknetNodeDomElement(nodeObj) { } //Upgrade Cores - var upgradeCoreButton = document.getElementById("hacknet-node-upgrade-core-" + nodeName); - if (upgradeCoreButton == null) {throw new Error("Cannot find upgrade cores button element");} + var upgradeCoreButton = getElementById("hacknet-node-upgrade-core-" + nodeName); + if (nodeObj.cores >= CONSTANTS.HacknetNodeMaxCores) { - upgradeCoreButton.innerHTML = "MAX CORES"; + updateText("hacknet-node-upgrade-core-" + nodeName, "MAX CORES"); upgradeCoreButton.setAttribute("class", "a-link-button-inactive"); } else { var upgradeCoreCost = nodeObj.calculateCoreUpgradeCost(); - upgradeCoreButton.innerHTML = "Purchase additional CPU Core - $" + formatNumber(upgradeCoreCost, 2); + updateText("hacknet-node-upgrade-core-" + nodeName, "Upgrade - $" + formatNumber(upgradeCoreCost, 2)); if (Player.money.lt(upgradeCoreCost)) { upgradeCoreButton.setAttribute("class", "a-link-button-inactive"); } else { @@ -511,8 +567,12 @@ function updatePlayerHacknetNodeWrappers() { if (Player.hacknetNodeWrappers.length !== Player.hacknetNodes.length) { return createPlayerHacknetNodeWrappers(); } + for (var i = 0; i < Player.hacknetNodeWrappers.length; ++i) { - if (!(Player.hacknetNodeWrappers[i] instanceof HacknetNodeWrapper)) {return createPlayerHacknetNodeWrappers();} + if (!(Player.hacknetNodeWrappers[i] instanceof HacknetNodeWrapper)) { + return createPlayerHacknetNodeWrappers(); + } + Player.hacknetNodeWrappers[i].level = Player.hacknetNodes[i].level; Player.hacknetNodeWrappers[i].ram = Player.hacknetNodes[i].ram; Player.hacknetNodeWrappers[i].cores = Player.hacknetNodes[i].cores; @@ -528,6 +588,7 @@ function processAllHacknetNodeEarnings(numCycles) { for (var i = 0; i < Player.hacknetNodes.length; ++i) { total += processSingleHacknetNodeEarnings(numCycles, Player.hacknetNodes[i]); } + return total; } @@ -535,9 +596,10 @@ function processSingleHacknetNodeEarnings(numCycles, nodeObj) { var cyclesPerSecond = 1000 / Engine._idleSpeed; var earningPerCycle = nodeObj.moneyGainRatePerSecond / cyclesPerSecond; if (isNaN(earningPerCycle)) { - console.log("ERROR: Hacknet Node Calculated earnings is NaN"); + console.error("Hacknet Node '" + nodeObj.name + "' Calculated earnings is NaN"); earningPerCycle = 0; } + var totalEarnings = numCycles * earningPerCycle; nodeObj.totalMoneyGenerated += totalEarnings; nodeObj.onlineTimeSeconds += (numCycles * (Engine._idleSpeed / 1000)); @@ -551,10 +613,21 @@ function getHacknetNode(name) { return Player.hacknetNodes[i]; } } + return null; } -export {hacknetNodesInit, HacknetNode, purchaseHacknet, updateTotalHacknetProduction, - getCostOfNextHacknetNode, updateHacknetNodesMultiplierButtons, getMaxNumberLevelUpgrades, - displayHacknetNodesContent, updateHacknetNodesContent, processAllHacknetNodeEarnings, - getHacknetNode, createPlayerHacknetNodeWrappers}; +export { + HacknetNode, + createPlayerHacknetNodeWrappers, + displayHacknetNodesContent, + getCostOfNextHacknetNode, + getHacknetNode, + getMaxNumberLevelUpgrades, + hacknetNodesInit, + processAllHacknetNodeEarnings, + purchaseHacknet, + updateHacknetNodesContent, + updateHacknetNodesMultiplierButtons, + updateTotalHacknetProduction +}; diff --git a/utils/HelperFunctions.js b/utils/HelperFunctions.js index 9a3a658e1..3e682fe5b 100644 --- a/utils/HelperFunctions.js +++ b/utils/HelperFunctions.js @@ -74,6 +74,21 @@ function removeChildrenFromElement(el) { } } +/** + * Returns a reference to the first object with the specified value of the ID or NAME attribute, throwing an error if it is unable to find it. + * @param {string} elementId The HTML ID to retrieve the element by. + * @returns {HTMLElement} The single element. + * @throws {Error} When the 'idString' cannot be found. + */ +function getElementById(elementId) { + var el = document.getElementById(elementId); + if (el == null) { + throw new Error("Unable to find element with id '" + elementId + "'"); + } + + return el; +} + function createElement(type, params={}) { var el = document.createElement(type); if (params.id) {el.id = params.id;} @@ -260,4 +275,4 @@ export {sizeOfObject, clearObject, addOffset, clearEventListeners, getRandomInt, removeElementById, removeElement, createElement, createAccordionElement, appendLineBreaks, removeChildrenFromElement, createPopup, clearSelector, exceptionAlert, - createProgressBarText}; + createProgressBarText, getElementById}; From 2cbc728baf3cc88e8522f840ecc5fb4ac818ff41 Mon Sep 17 00:00:00 2001 From: Steven Evans Date: Tue, 5 Jun 2018 23:49:06 -0400 Subject: [PATCH 5/5] [fix] UI layout of hacknet nodes no longer overflows player info --- css/menupages.css | 13 +++++++++++-- index.html | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/css/menupages.css b/css/menupages.css index adce7407f..fe23d4c2b 100644 --- a/css/menupages.css +++ b/css/menupages.css @@ -299,6 +299,11 @@ white-space: nowrap; } +#hacknet-nodes-list { + list-style: none; + width: 82vw; +} + #hacknet-nodes-money { margin: 10px; float: left; @@ -306,7 +311,7 @@ #hacknet-nodes-money-multipliers-div { display: inline-block; - width: 80%; + width: 70vw; } #hacknet-nodes-multipliers { @@ -320,7 +325,7 @@ .hacknet-node { margin: 6px; padding: 6px; - width: 40%; + width: 34vw; border: 2px solid var(--my-highlight-color); -webkit-box-shadow: inset 0 0 8px rgba(0,0,0,0.1), @@ -353,6 +358,10 @@ width: 48px; /* Four times font-size */ } +.menu-page-text { + width: 70vw; +} + /* World */ #world-container { position: fixed; diff --git a/index.html b/index.html index 63c4c0c80..f20f55fff 100644 --- a/index.html +++ b/index.html @@ -185,7 +185,7 @@

Hacknet Nodes

-

+

-
    +