diff --git a/css/missions.css b/css/missions.css index 0e45b8c79..ee1a22e17 100644 --- a/css/missions.css +++ b/css/missions.css @@ -29,6 +29,10 @@ align-self: center; justify-self: center; display:inline-block; +} + +.hack-mission-node p { + margin-top:8px; color:white; font-size:12px; text-align:center; diff --git a/css/styles.css b/css/styles.css index daf25c4bb..4eabfe0c0 100644 --- a/css/styles.css +++ b/css/styles.css @@ -398,3 +398,59 @@ a:link, a:visited { .scan-analyze-link:hover { text-decoration:none; } + +/* Accordion menus (Header with collapsible panel) */ +.accordion-header { + background-color: #444; + font-size: 20px; + color: white; + margin: 6px 6px 0px 6px; + padding: 6px; + cursor: pointer; + width: 80%; + text-align: left; + border: none; + outline: none; +} + +.accordion-header.active, +.accordion-header:hover { + background-color: #555; +} + +.accordion-header.active:hover { + background-color: #666; +} + +.accordion-header:after { + content: '\02795'; /* "plus" sign (+) */ + font-size: 13px; + color: white; + float: right; + margin-left: 5px; +} + +.accordion-header.active:after { + content: "\2796"; /* "minus" sign (-) */ + font-size: 13px; + color: white; + float: right; + margin-left: 5px; +} + +.accordion-panel { + margin: 0px 6px 6px 6px; + padding: 0px 6px 6px 6px; + width: 75%; + margin-left: 5%; + display: none; + background-color: #555; + overflow:auto; +} + +.accordion-panel div, +.accordion-panel ul, +.accordion-panel p, +.accordion-panel ul > li { + background-color: #555; +} diff --git a/dist/bundle.js b/dist/bundle.js index 57d929e87..e35ec6238 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -3616,7 +3616,8 @@ let CONSTANTS = { "-Rebalanced BitNode-2 so that Crime and Infiltration are more profitable but hacking is less profitable. Infiltration also gives more faction rep
" + "-Rebalanced BitNode-4 so that hacking is slightly less profitable
" + "-Rebalanced BitNode-5 so that Infiltration is more profitable and gives more faction rep
" + - "-Rebalanced BitNode-11 so that Crime and Infiltration are more profitable. Infiltration also gives more faction rep.
" + "-Rebalanced BitNode-11 so that Crime and Infiltration are more profitable. Infiltration also gives more faction rep.
" + + "-Fixed an annoying issue in Hacking Missions where sometimes you would click a Node but it wouldnt actually get selected
" } @@ -36461,12 +36462,12 @@ HackingMission.prototype.createNodeDomElement = function(nodeObj) { var txt; switch (nodeObj.type) { case NodeTypes.Core: - txt = "CPU Core
" + "HP: " + + txt = "

CPU Core
" + "HP: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); nodeDiv.classList.add("hack-mission-cpu-node"); break; case NodeTypes.Firewall: - txt = "Firewall
" + "HP: " + + txt = "

Firewall
" + "HP: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); nodeDiv.classList.add("hack-mission-firewall-node"); break; @@ -36476,7 +36477,7 @@ HackingMission.prototype.createNodeDomElement = function(nodeObj) { nodeDiv.classList.add("hack-mission-database-node"); break; case NodeTypes.Spam: - txt = "Spam
" + "HP: " + + txt = "

Spam
" + "HP: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); nodeDiv.classList.add("hack-mission-spam-node"); break; @@ -36487,14 +36488,14 @@ HackingMission.prototype.createNodeDomElement = function(nodeObj) { break; case NodeTypes.Shield: default: - txt = "
Shield
" + "HP: " + + txt = "

Shield
" + "HP: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); nodeDiv.classList.add("hack-mission-shield-node"); break; } txt += "
Atk: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.atk, 1) + - "
Def: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.def, 1); + "
Def: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.def, 1) + "

"; nodeDiv.innerHTML = txt; } @@ -36512,11 +36513,11 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) { var txt; switch (nodeObj.type) { case NodeTypes.Core: - txt = "CPU Core
" + "HP: " + + txt = "

CPU Core
" + "HP: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); break; case NodeTypes.Firewall: - txt = "Firewall
" + "HP: " + + txt = "

Firewall
" + "HP: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); break; case NodeTypes.Database: @@ -36524,7 +36525,7 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) { Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); break; case NodeTypes.Spam: - txt = "Spam
" + "HP: " + + txt = "

Spam
" + "HP: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); break; case NodeTypes.Transfer: @@ -36533,7 +36534,7 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) { break; case NodeTypes.Shield: default: - txt = "
Shield
" + "HP: " + + txt = "

Shield
" + "HP: " + Object(__WEBPACK_IMPORTED_MODULE_6__utils_StringHelperFunctions_js__["c" /* formatNumber */])(nodeObj.hp, 1); break; } @@ -36543,8 +36544,11 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) { if (nodeObj.action) { txt += "
" + nodeObj.action; } - //txt += "

"; + txt += "

"; nodeDiv.innerHTML = txt; + if (nodeObj.type === NodeTypes.Core || nodeObj.type === NodeTypes.Transfer) { + this.configurePlayerNodeElement(nodeObj.el, true); + } } //Gets a Node DOM element's corresponding Node object using its @@ -36571,23 +36575,38 @@ HackingMission.prototype.getNodeFromElement = function(el) { return this.map[x][y]; } +function selectNode(hackMissionInst, el) { + var nodeObj = hackMissionInst.getNodeFromElement(el); + if (nodeObj === null) {console.log("Error getting Node object");} + if (!nodeObj.plyrCtrl) {return;} + + if (hackMissionInst.selectedNode instanceof Node) { + hackMissionInst.selectedNode.deselect(hackMissionInst.actionButtons); + hackMissionInst.selectedNode = null; + } + console.log("Selecting node :" + el.id); + nodeObj.select(hackMissionInst.actionButtons); + hackMissionInst.selectedNode = nodeObj; +} + //Configures a DOM element representing a player-owned node to //be selectable and actionable //Note: Does NOT change its css class. This is handled by Node.setControlledBy... -HackingMission.prototype.configurePlayerNodeElement = function(el) { +HackingMission.prototype.configurePlayerNodeElement = function(el, reconfigureChildOnly=false) { var nodeObj = this.getNodeFromElement(el); if (nodeObj === null) {console.log("Error getting Node object");} //Add event listener - el.addEventListener("click", ()=>{ - if (this.selectedNode instanceof Node) { - this.selectedNode.deselect(this.actionButtons); - this.selectedNode = null; - } - console.log("Selecting node :" + el.id); - nodeObj.select(this.actionButtons); - this.selectedNode = nodeObj; - }); + function selectNodeWrapper() { + selectNode(this, el); + } + if (!reconfigureChildOnly) { + el.addEventListener("click", selectNodeWrapper); + } + + if (el.firstChild) { + el.firstChild.addEventListener("click", selectNodeWrapper); + } } //Configures a DOM element representing an enemy-node by removing @@ -36598,8 +36617,6 @@ HackingMission.prototype.configureEnemyNodeElement = function(el) { if (this.selectedNode == nodeObj) { nodeObj.deselect(this.actionButtons); } - - //TODO Need to remove event listeners } //Returns bool indicating whether a node is reachable by player diff --git a/src/Constants.js b/src/Constants.js index 8384c1261..24e5a9e32 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -1058,7 +1058,8 @@ let CONSTANTS = { "-Rebalanced BitNode-2 so that Crime and Infiltration are more profitable but hacking is less profitable. Infiltration also gives more faction rep
" + "-Rebalanced BitNode-4 so that hacking is slightly less profitable
" + "-Rebalanced BitNode-5 so that Infiltration is more profitable and gives more faction rep
" + - "-Rebalanced BitNode-11 so that Crime and Infiltration are more profitable. Infiltration also gives more faction rep.
" + "-Rebalanced BitNode-11 so that Crime and Infiltration are more profitable. Infiltration also gives more faction rep.
" + + "-Fixed an annoying issue in Hacking Missions where sometimes you would click a Node but it wouldnt actually get selected
" } export {CONSTANTS}; diff --git a/src/Missions.js b/src/Missions.js index b808669b1..4c8a2fcc2 100644 --- a/src/Missions.js +++ b/src/Missions.js @@ -696,12 +696,12 @@ HackingMission.prototype.createNodeDomElement = function(nodeObj) { var txt; switch (nodeObj.type) { case NodeTypes.Core: - txt = "CPU Core
" + "HP: " + + txt = "

CPU Core
" + "HP: " + formatNumber(nodeObj.hp, 1); nodeDiv.classList.add("hack-mission-cpu-node"); break; case NodeTypes.Firewall: - txt = "Firewall
" + "HP: " + + txt = "

Firewall
" + "HP: " + formatNumber(nodeObj.hp, 1); nodeDiv.classList.add("hack-mission-firewall-node"); break; @@ -711,7 +711,7 @@ HackingMission.prototype.createNodeDomElement = function(nodeObj) { nodeDiv.classList.add("hack-mission-database-node"); break; case NodeTypes.Spam: - txt = "Spam
" + "HP: " + + txt = "

Spam
" + "HP: " + formatNumber(nodeObj.hp, 1); nodeDiv.classList.add("hack-mission-spam-node"); break; @@ -722,14 +722,14 @@ HackingMission.prototype.createNodeDomElement = function(nodeObj) { break; case NodeTypes.Shield: default: - txt = "
Shield
" + "HP: " + + txt = "

Shield
" + "HP: " + formatNumber(nodeObj.hp, 1); nodeDiv.classList.add("hack-mission-shield-node"); break; } txt += "
Atk: " + formatNumber(nodeObj.atk, 1) + - "
Def: " + formatNumber(nodeObj.def, 1); + "
Def: " + formatNumber(nodeObj.def, 1) + "

"; nodeDiv.innerHTML = txt; } @@ -747,11 +747,11 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) { var txt; switch (nodeObj.type) { case NodeTypes.Core: - txt = "CPU Core
" + "HP: " + + txt = "

CPU Core
" + "HP: " + formatNumber(nodeObj.hp, 1); break; case NodeTypes.Firewall: - txt = "Firewall
" + "HP: " + + txt = "

Firewall
" + "HP: " + formatNumber(nodeObj.hp, 1); break; case NodeTypes.Database: @@ -759,7 +759,7 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) { formatNumber(nodeObj.hp, 1); break; case NodeTypes.Spam: - txt = "Spam
" + "HP: " + + txt = "

Spam
" + "HP: " + formatNumber(nodeObj.hp, 1); break; case NodeTypes.Transfer: @@ -768,7 +768,7 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) { break; case NodeTypes.Shield: default: - txt = "
Shield
" + "HP: " + + txt = "

Shield
" + "HP: " + formatNumber(nodeObj.hp, 1); break; } @@ -778,8 +778,11 @@ HackingMission.prototype.updateNodeDomElement = function(nodeObj) { if (nodeObj.action) { txt += "
" + nodeObj.action; } - //txt += "

"; + txt += "

"; nodeDiv.innerHTML = txt; + if (nodeObj.type === NodeTypes.Core || nodeObj.type === NodeTypes.Transfer) { + this.configurePlayerNodeElement(nodeObj.el, true); + } } //Gets a Node DOM element's corresponding Node object using its @@ -806,23 +809,38 @@ HackingMission.prototype.getNodeFromElement = function(el) { return this.map[x][y]; } +function selectNode(hackMissionInst, el) { + var nodeObj = hackMissionInst.getNodeFromElement(el); + if (nodeObj === null) {console.log("Error getting Node object");} + if (!nodeObj.plyrCtrl) {return;} + + if (hackMissionInst.selectedNode instanceof Node) { + hackMissionInst.selectedNode.deselect(hackMissionInst.actionButtons); + hackMissionInst.selectedNode = null; + } + console.log("Selecting node :" + el.id); + nodeObj.select(hackMissionInst.actionButtons); + hackMissionInst.selectedNode = nodeObj; +} + //Configures a DOM element representing a player-owned node to //be selectable and actionable //Note: Does NOT change its css class. This is handled by Node.setControlledBy... -HackingMission.prototype.configurePlayerNodeElement = function(el) { +HackingMission.prototype.configurePlayerNodeElement = function(el, reconfigureChildOnly=false) { var nodeObj = this.getNodeFromElement(el); if (nodeObj === null) {console.log("Error getting Node object");} //Add event listener - el.addEventListener("click", ()=>{ - if (this.selectedNode instanceof Node) { - this.selectedNode.deselect(this.actionButtons); - this.selectedNode = null; - } - console.log("Selecting node :" + el.id); - nodeObj.select(this.actionButtons); - this.selectedNode = nodeObj; - }); + function selectNodeWrapper() { + selectNode(this, el); + } + if (!reconfigureChildOnly) { + el.addEventListener("click", selectNodeWrapper); + } + + if (el.firstChild) { + el.firstChild.addEventListener("click", selectNodeWrapper); + } } //Configures a DOM element representing an enemy-node by removing @@ -833,8 +851,6 @@ HackingMission.prototype.configureEnemyNodeElement = function(el) { if (this.selectedNode == nodeObj) { nodeObj.deselect(this.actionButtons); } - - //TODO Need to remove event listeners } //Returns bool indicating whether a node is reachable by player