From e0a193c7cae36cc22bed247a93c7a84bedd9e791 Mon Sep 17 00:00:00 2001 From: Steven Evans Date: Thu, 2 Aug 2018 12:11:03 -0400 Subject: [PATCH 01/20] [bug] 'createProgressBar' - actually possible to fill the entire bar --- utils/helpers/createProgressBarText.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/utils/helpers/createProgressBarText.ts b/utils/helpers/createProgressBarText.ts index 8cd628277..37f433a00 100644 --- a/utils/helpers/createProgressBarText.ts +++ b/utils/helpers/createProgressBarText.ts @@ -34,11 +34,14 @@ export function createProgressBarText(params: IProgressBarConfiguration) { }; // tslint:disable-next-line:prefer-object-spread - const derivedParams: IProgressBarConfigurationMaterialized = Object.assign({}, defaultParams, params); + const derived: IProgressBarConfigurationMaterialized = Object.assign({}, defaultParams, params); + // Ensure it is 0..1 + derived.progress = Math.max(Math.min(derived.progress, 1), 0); - const bars: number = Math.floor(derivedParams.progress / (1 / derivedParams.totalTicks)); - const dashes: number = derivedParams.totalTicks - bars; + // This way there is always at least one bar filled in... + const bars: number = Math.max(Math.floor(derived.progress / (1 / derived.totalTicks)), 1); + const dashes: number = Math.max(derived.totalTicks - bars, 0); // String.prototype.repeat isn't completley supported, but good enough for our purposes - return `[${"|".repeat(bars + 1)}${"-".repeat(dashes + 1)}]`; + return `[${"|".repeat(bars)}${"-".repeat(dashes)}]`; } From 5f13bc63362c57c53afb1acc014095db91693faa Mon Sep 17 00:00:00 2001 From: Mat Jaworski Date: Thu, 30 Aug 2018 01:12:33 +1000 Subject: [PATCH 02/20] UI Enhancements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updates: – Character Overview box (top right corner) – redesigned and added colours to the attributes. – Added prompt colour in the terminal. – Minor copy fixes (grammar and typos). – Code formatting cleanup. – Character > Stats – Fixed spacing issue when Intelligence is not yet available – Main Menu – Adjusted the spacing and changed the border to outline to improve the readability. – Tooltip boxes (Firefox only) – fixed the issue when tooltips were generating additional spacing around the
tags. – Multiple general updates to UI to improve accessibility and readability. Aimed to improve the user experience when playing the game on a smaller screen resolutions. – Accordion/Dropdown buttons – improved the readability of the plus/minus icons. – Added .editorconfig with the most basic settings. --- .editorconfig | 13 ++++++ css/_theme.scss | 10 +++++ css/menupages.scss | 79 +++++++++++++++++---------------- css/popupboxes.scss | 12 ++--- css/styles.scss | 104 ++++++++++++++++++++++++++++++-------------- css/terminal.scss | 1 + index.html | 38 ++++++++-------- src/HacknetNode.js | 4 +- src/Player.js | 2 +- src/engine.js | 22 +++++----- 10 files changed, 177 insertions(+), 108 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..eba264699 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true + +[package.json] +indent_size = 2 + +[md] +trim_trailing_whitespace = false diff --git a/css/_theme.scss b/css/_theme.scss index e9ffd2225..75134be78 100644 --- a/css/_theme.scss +++ b/css/_theme.scss @@ -1,2 +1,12 @@ $fontFamily: 'Lucida Console', 'Lucida Sans Unicode', 'Fira Mono', 'Consolas', 'Courier New', Courier, monospace, 'Times New Roman'; $defaultFontSize: 16px; + +/* COLORS */ +$hacky-green: #adff2f; + +/* Attributes */ +$my-stat-hp-color: #dd3434; +$my-stat-money-color: #ffd700; +$my-stat-hack-color: $hacky-green; +$my-stat-cha-color: #a671d1; +$my-stat-int-color: #6495ed; diff --git a/css/menupages.scss b/css/menupages.scss index 8c9e475a1..64cd82939 100644 --- a/css/menupages.scss +++ b/css/menupages.scss @@ -22,17 +22,15 @@ #script-editor-container { background-color: transparent; } + #javascript-editor { margin: 10px; - height: 80%; width: 100%; margin-left: 6px; - padding-left: 6px; padding-top: 6px; padding-bottom: 6px; - border: 2px solid var(--my-highlight-color); z-index: 1; font-family: $fontFamily; @@ -101,9 +99,7 @@ resize: none; color: #fff; margin: 4px; - padding: 2px; - border: 2px solid var(--my-highlight-color); } @@ -225,15 +221,15 @@ .active-scripts-script-header:after { content: '\02795'; /* "plus" sign (+) */ font-size: $defaultFontSize * 0.8125; - color: var(--my-font-color); float: right; margin-left: 5px; + color: transparent; + text-shadow: 0 0 0 var(--my-font-color); } .active-scripts-script-header.active:after { content: "\2796"; /* "minus" sign (-) */ font-size: $defaultFontSize * 0.8125; - color: var(--my-font-color); float: right; margin-left: 5px; } @@ -291,6 +287,16 @@ float: left; overflow: hidden; white-space: nowrap; + + &.hacknet-node { + $boxShadowArgs: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1); + @include boxShadow($boxShadowArgs); + + margin: 6px; + padding: 7px; + width: 35vw; + border: 2px solid var(--my-highlight-color); + } } #hacknet-nodes-list { @@ -316,16 +322,6 @@ display: inline-block; } -.hacknet-node { - $boxShadowArgs: inset 0 0 8px rgba(0, 0, 0, 0.1), 0 0 16px rgba(0, 0, 0, 0.1); - @include boxShadow($boxShadowArgs); - - margin: 6px; - padding: 6px; - width: 34vw; - border: 2px solid var(--my-highlight-color); -} - .hacknet-node-container { display: inline-table; } @@ -426,17 +422,14 @@ } /* Faction Augmentations */ -#faction-augmentations-container{ +#faction-augmentations-container { position: fixed; padding-top: 10px; -} -#faction-augmentations-container p, -#faction-augmentations-container a, -#faction-augmentations-container ul, -#faction-augmentations-container h1{ - margin: 8px; - padding: 4px; + p, a, ul, h1 { + margin: 8px; + padding: 4px; + } } /* World */ @@ -451,11 +444,20 @@ padding-top: 10px; } -.augmentations-list button, -.augmentations-list div { - color: var(--my-font-color); - padding: 8px; - text-decoration: none; +.augmentations-list { + button, + div { + color: var(--my-font-color); + text-decoration: none; + } + + button { + padding: 2px 5px; + } + + div { + padding: 6px; + } } /* Tutorial */ @@ -510,11 +512,12 @@ padding: 6px; } -#location-container * { +#location-container > * { margin: 10px 5px 10px 5px; } -#location-job-reputation, #location-company-favor { +#location-job-reputation, +#location-company-favor { display: inline; } @@ -523,6 +526,7 @@ position: fixed; padding: 6px; } + #infiltration-left-panel, #infiltration-right-panel { display: inline-block; @@ -552,6 +556,7 @@ #stock-market-container { position: fixed; padding: 6px; + p { font-size: $defaultFontSize * 0.8125; } @@ -559,9 +564,9 @@ font-size: $defaultFontSize * 0.875; } h2 { - margin-top:10px; - margin-left:10px; - display:block; + margin-top: 10px; + margin-left: 10px; + display: block; } } @@ -583,8 +588,8 @@ } #stock-market-watchlist-filter { - width:50%; - margin-left:10px; + width: 50%; + margin-left: 10px; } .stock-market-input { diff --git a/css/popupboxes.scss b/css/popupboxes.scss index 60c18d8ab..453a06e7a 100644 --- a/css/popupboxes.scss +++ b/css/popupboxes.scss @@ -8,8 +8,8 @@ z-index: 10; /* Sit on top */ left: 0; top: 0; - align-items:center; - justify-content:center; + align-items: center; + justify-content: center; width: 100%; height: 100%; overflow: auto; @@ -21,7 +21,7 @@ padding: 12px; border: 5px solid var(--my-highlight-color); width: 70%; - max-height:80%; + max-height: 80%; /* margin: auto; height:auto; @@ -32,7 +32,7 @@ bottom:0; right:0; */ - overflow-y:auto; + overflow-y: auto; color: var(--my-font-color); } @@ -158,8 +158,8 @@ border: 5px solid var(--my-highlight-color); color: var(--my-font-color); width: 80%; - max-height:80%; - overflow-y:auto; + max-height: 80%; + overflow-y: auto; } #game-options-left-panel, diff --git a/css/styles.scss b/css/styles.scss index feebc7177..0f2fead93 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -3,10 +3,11 @@ @import "reset"; -:root{ +:root { --my-font-color: #6f3; --my-background-color: #000; --my-highlight-color: #fff; + --my-prompt-color: #f92672; } body { @@ -83,7 +84,7 @@ tr:focus { display: block; color: #e6e6e6; background-color: #555; - padding: 16px; + padding: 12px 8px; text-decoration: none; } @@ -105,13 +106,23 @@ tr:focus { background-color: #aaa; } +#hacking-menu-header-li, +#character-menu-header-li, +#world-menu-header-li, +#help-menu-header-li { + position: relative; +} + /* Plus and minus signs */ .mainmenu-accordion-header:after { content: '\02795'; - font-size: $defaultFontSize * 0.8125; - color: #fff; float: right; - margin-left: 5px; + font-size: $defaultFontSize * 0.8125; + position: absolute; + bottom: 25%; + right: 3px; + color: transparent; + text-shadow: 0 0 0 #fff; } .mainmenu-accordion-header.opened:after { @@ -129,9 +140,9 @@ tr:focus { transition: max-height 0.2s ease-out; } -/* Borders */ +/* Accordion Outline */ .mainmenu-accordion-header { - border: 2px solid #fff; + outline: 2px solid #fff; } /* Make html links ("a" elements) nice looking buttons with this class */ @@ -144,7 +155,7 @@ a:visited { text-decoration: none; background-color: #555; color: #fff; - padding: 5px; + padding: 3px 5px; margin: 5px; border: 1px solid #333; @@ -167,7 +178,7 @@ a:visited { text-decoration: none; background-color: #333; color: #fff; - padding: 5px; + padding: 3px 5px; margin: 5px; border: 1px solid #333; cursor: default; @@ -188,7 +199,7 @@ a:visited { text-decoration: none; background-color: #0a0; color: #fff; - padding: 5px; + padding: 3px 5px; margin: 5px; border: 1px solid #0a0; cursor: default; @@ -218,9 +229,9 @@ a:visited { #create-program-tab { position: relative; } + #create-program-notification { font-size: $defaultFontSize * 0.625; - position: absolute; /* Position the badge within the relatively positioned button */ top: 0; right: 0; @@ -364,7 +375,7 @@ a:visited { /* Blinking Cursor */ /* ----- blinking cursor animation ----- */ -.typed-cursor{ +.typed-cursor { opacity: 1; -webkit-animation: blink 0.95s infinite; -moz-animation: blink 0.95s infinite; @@ -400,16 +411,16 @@ a:visited { } /* Status text */ -@-webkit-keyframes status-text{ - from{ +@-webkit-keyframes status-text { + from { opacity: 1; } - to{ + to { opacity: 0; } } -.status-text{ +.status-text { display: inline-block; height: 15%; position: fixed; @@ -437,47 +448,78 @@ a:visited { #character-overview-wrapper { position: relative; } + #character-overview-container { display: none; position: absolute; /* Stay in place */ right: 0; top: 0; height: auto; /* Full height */ - padding: 8px; + padding: 10px 2px; border: 2px solid var(--my-highlight-color); - width: 19%; + width: auto; + max-width: 280px; overflow: auto; /* Enable scroll if needed */ - background-color: #444; /* Fallback color */ + background-color: #393636; /* Fallback color */ z-index: 1; } #character-overview-text { - color: #fff; - background-color: #444; + color: #faffdf; + + table { + border-collapse: collapse; + margin: auto; + } + + td { + padding: 2px; + vertical-align: middle; + } } .character-stat-text { color: #fff; background-color: #444; } - .character-stat-cell { + +.character-stat-cell { text-align: right; } +#character-hack-wrapper td, +#character-agi-wrapper td { + border-bottom: 1px #aaa solid; + padding-bottom: 10px; +} + +#character-str-wrapper td, +#character-cha-wrapper td { + padding-top: 10px; +} + +#character-hp-wrapper { color: $my-stat-hp-color; } +#character-money-wrapper { color: $my-stat-money-color; } +#character-hack-wrapper { color: $my-stat-hack-color; } +#character-cha-wrapper { color: $my-stat-cha-color; } +#character-int-wrapper { color: $my-stat-int-color; } + #character-overview-save-button, #character-overview-options-button { @include borderRadius(12px); @include boxShadow(1px 1px 3px #000); - - color: #aaa; + color: #cecece; + display: inline-block; font-size: $defaultFontSize * 0.875; font-weight: bold; - height: 22px; + height: 25px; background-color: #000; + padding: 5px 8px; } .character-quick-options { - padding-top: 5px; + margin-top: 10px; + text-align: center; } #character-overview-save-button:hover, @@ -489,16 +531,13 @@ a:visited { cursor: pointer; } -#character-overview-options-button { - display: inline; -} - /* Scan analyze links from AutoLink */ .scan-analyze-link { cursor: pointer; color: #fff; text-decoration: underline; } + .scan-analyze-link:hover { text-decoration: none; } @@ -509,7 +548,7 @@ a:visited { font-size: $defaultFontSize * 1.25; color: #fff; margin: 6px 6px 0 6px; - padding: 6px; + padding: 4px 6px; cursor: pointer; width: 80%; text-align: left; @@ -529,9 +568,10 @@ a:visited { .accordion-header:after { content: '\02795'; /* "plus" sign (+) */ font-size: $defaultFontSize * 0.8125; - color: #fff; float: right; margin-left: 5px; + color: transparent; + text-shadow: 0 0 0 #fff; } .accordion-header.active:after { diff --git a/css/terminal.scss b/css/terminal.scss index ac26b9b3d..cbc54b782 100644 --- a/css/terminal.scss +++ b/css/terminal.scss @@ -51,6 +51,7 @@ } #terminal-input-header { + color: var(--my-prompt-color); white-space: pre; } diff --git a/index.html b/index.html index 19f370c7f..66439fff0 100644 --- a/index.html +++ b/index.html @@ -110,7 +110,7 @@

Script name:

- +
@@ -160,7 +160,7 @@
- +
@@ -169,11 +169,11 @@
- + - +
$ - +
@@ -215,7 +215,7 @@

Money:
- Total Hacknet Node Prodution: + Total Hacknet Node Production:

x1 @@ -452,7 +452,7 @@

This page displays any programs that you are able to create. Writing the code for a program takes time, which - can vary based on how complex the program is. If you are working on creating on a program you can cancel + can vary based on how complex the program is. If you are working on creating a program you can cancel at any time. Your progress will be saved and you can continue later.

@@ -625,9 +625,9 @@

You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and - other shadowy entities. The city's government and police have neglected this area for years...


- - In the Slums you can commit crimes to earn money and experience. Crime attempts are not always + other shadowy entities. The city's government and police have neglected this area for years... +


+ In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always successful. Your chance at successfully committing a crime is determined by your stats.

Shoplift @@ -744,7 +744,7 @@
- Save Game - Options + Save Game + Options
@@ -868,7 +868,7 @@ - + @@ -882,7 +882,7 @@ - + @@ -896,7 +896,7 @@ - + @@ -908,7 +908,7 @@ - + @@ -994,7 +994,7 @@ Save Game Delete Game Export Game - + Import Game (DEBUG) Delete Active Scripts @@ -1006,7 +1006,7 @@ (DEBUG) Soft Reset - Perform a soft reset. Resets everything as if you had just purchased an Augmentation + Perform a soft reset. Resets everything as if you had just purchased an Augmentation. diff --git a/src/HacknetNode.js b/src/HacknetNode.js index 8f1faa218..60a956ce9 100644 --- a/src/HacknetNode.js +++ b/src/HacknetNode.js @@ -446,7 +446,7 @@ function updateHacknetNodesContent() { //Update player's money updateText("hacknet-nodes-player-money", "$" + formatNumber(Player.money.toNumber(), 2)); - updateText("hacknet-nodes-total-production", "$" + formatNumber(Player.totalHacknetNodeProduction, 2) + " / second"); + updateText("hacknet-nodes-total-production", "$" + formatNumber(Player.totalHacknetNodeProduction, 2) + " / sec"); //Update information in each owned hacknet node for (var i = 0; i < Player.hacknetNodes.length; ++i) { @@ -548,7 +548,7 @@ function updateHacknetNodeDomElement(nodeObj) { 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-production-rate-" + nodeName, "($" + formatNumber(nodeObj.moneyGainRatePerSecond, 2) + " / sec)"); updateText("hacknet-node-level-" + nodeName, nodeObj.level); updateText("hacknet-node-ram-" + nodeName, nodeObj.ram + "GB"); updateText("hacknet-node-cores-" + nodeName, nodeObj.cores); diff --git a/src/Player.js b/src/Player.js index 48d4771a5..03ea14a7c 100644 --- a/src/Player.js +++ b/src/Player.js @@ -2049,7 +2049,7 @@ PlayerObject.prototype.reapplyAllSourceFiles = function() { //those requirements and will return an array of all factions that the Player should //receive an invitation to PlayerObject.prototype.checkForFactionInvitations = function() { - let invitedFactions = []; //Array which will hold all Factions th eplayer should be invited to + let invitedFactions = []; //Array which will hold all Factions the player should be invited to var numAugmentations = this.augmentations.length; diff --git a/src/engine.js b/src/engine.js index 8ea543dcd..e9745dea0 100644 --- a/src/engine.js +++ b/src/engine.js @@ -548,11 +548,11 @@ let Engine = { displayCharacterOverviewInfo: function() { Engine.overview.update(); - + const save = document.getElementById("character-overview-save-button"); const flashClass = "flashing-button"; - if(!Settings.AutosaveInterval) { + if(!Settings.AutosaveInterval) { save.classList.add(flashClass); } else { save.classList.remove(flashClass); @@ -570,7 +570,7 @@ let Engine = { var intText = ""; if (Player.intelligence > 0) { - intText = 'Intelligence: ' + (Player.intelligence).toLocaleString() + "


"; + intText = 'Intelligence: ' + (Player.intelligence).toLocaleString() + '
'; } let bitNodeTimeText = ""; @@ -584,21 +584,21 @@ let Engine = { 'Current City: ' + Player.city + '

' + 'Employer: ' + Player.companyName + '
' + 'Job Title: ' + companyPosition + '

' + - 'Money: $' + formatNumber(Player.money.toNumber(), 2)+ '


' + + 'Money: $' + formatNumber(Player.money.toNumber(), 2) + '


' + 'Stats

' + 'Hacking Level: ' + (Player.hacking_skill).toLocaleString() + - " (" + numeral(Player.hacking_exp).format('(0.000a)') + ' experience)
' + + ' (' + numeral(Player.hacking_exp).format('(0.000a)') + ' experience)
' + 'Strength: ' + (Player.strength).toLocaleString() + - " (" + numeral(Player.strength_exp).format('(0.000a)') + ' experience)
' + + ' (' + numeral(Player.strength_exp).format('(0.000a)') + ' experience)
' + 'Defense: ' + (Player.defense).toLocaleString() + - " (" + numeral(Player.defense_exp).format('(0.000a)')+ ' experience)
' + + ' (' + numeral(Player.defense_exp).format('(0.000a)')+ ' experience)
' + 'Dexterity: ' + (Player.dexterity).toLocaleString() + - " (" + numeral(Player.dexterity_exp).format('(0.000a)') + ' experience)
' + + ' (' + numeral(Player.dexterity_exp).format('(0.000a)') + ' experience)
' + 'Agility: ' + (Player.agility).toLocaleString() + - " (" + numeral(Player.agility_exp).format('(0.000a)') + ' experience)
' + + ' (' + numeral(Player.agility_exp).format('(0.000a)') + ' experience)
' + 'Charisma: ' + (Player.charisma).toLocaleString() + - " (" + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)
' + - intText + + ' (' + numeral(Player.charisma_exp).format('(0.000a)') + ' experience)
' + + intText + '

' + 'Multipliers

' + 'Hacking Chance multiplier: ' + formatNumber(Player.hacking_chance_mult * 100, 2) + '%
' + 'Hacking Speed multiplier: ' + formatNumber(Player.hacking_speed_mult * 100, 2) + '%
' + From dbab0d73a76c9cf536319206d4a60f0a078a2d67 Mon Sep 17 00:00:00 2001 From: Mat Jaworski Date: Thu, 30 Aug 2018 01:48:26 +1000 Subject: [PATCH 03/20] UI Enhancements part 2 A bit more refactoring and cleaning up the code. Updated the Augmentations accordion icons as they were barely visible. --- css/menupages.scss | 53 ++++++++++++++++------------------ css/styles.scss | 71 ++++++++++++++++++++++------------------------ 2 files changed, 59 insertions(+), 65 deletions(-) diff --git a/css/menupages.scss b/css/menupages.scss index 64cd82939..cd35bec4a 100644 --- a/css/menupages.scss +++ b/css/menupages.scss @@ -240,16 +240,13 @@ width: auto; display: none; margin-bottom: 6px; -} -.active-scripts-script-panel p, -.active-scripts-script-panel h2, -.active-scripts-script-panel ul, -.active-scripts-script-panel li { - background-color: #555; - width: auto; - color: #fff; - margin-left: 5%; + p, h2, ul, li { + background-color: #555; + width: auto; + color: #fff; + margin-left: 5%; + } } .active-scripts-button { @@ -262,13 +259,13 @@ margin: 4px; padding: 4px; background-color: #000; -} -.active-scripts-button:hover, -.active-scripts-button:focus { - color: #fff; - text-decoration: none; - cursor: pointer; + &:hover, + &:focus { + color: #fff; + text-decoration: none; + cursor: pointer; + } } /* Hacknet Nodes */ @@ -324,22 +321,22 @@ .hacknet-node-container { display: inline-table; -} -.hacknet-node-container .row { - display: table-row; - height: 30px; -} + .row { + display: table-row; + height: 30px; -.hacknet-node-container .row p { - display: table-cell; -} + 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: $defaultFontSize * 4; + .upgradable-info { + display: inline-block; + margin: 0 4px; /* Don't want the vertical margin/padding, just left & right */ + padding: 0 4px; + width: $defaultFontSize * 4; + } } .menu-page-text { diff --git a/css/styles.scss b/css/styles.scss index 0f2fead93..6daebde94 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -113,6 +113,11 @@ tr:focus { position: relative; } +/* Accordion Outline */ +.mainmenu-accordion-header { + outline: 2px solid #fff; +} + /* Plus and minus signs */ .mainmenu-accordion-header:after { content: '\02795'; @@ -125,12 +130,12 @@ tr:focus { text-shadow: 0 0 0 #fff; } -.mainmenu-accordion-header.opened:after { - content: "\2796"; -} - .mainmenu-accordion-header.opened { background-color: #222; + + &:after { + content: "\2796"; + } } /* Slide down transition */ @@ -140,11 +145,6 @@ tr:focus { transition: max-height 0.2s ease-out; } -/* Accordion Outline */ -.mainmenu-accordion-header { - outline: 2px solid #fff; -} - /* Make html links ("a" elements) nice looking buttons with this class */ a:link, a:visited { @@ -554,32 +554,32 @@ a:visited { text-align: left; border: none; outline: none; -} + position: relative; -.accordion-header.active, -.accordion-header:hover { - background-color: #555; -} + &.active, + &:hover { + background-color: #555; + } -.accordion-header.active:hover { - background-color: #666; -} + &.active:hover { + background-color: #666; + } -.accordion-header:after { - content: '\02795'; /* "plus" sign (+) */ - font-size: $defaultFontSize * 0.8125; - float: right; - margin-left: 5px; - color: transparent; - text-shadow: 0 0 0 #fff; -} + &:after { + content: '\02795'; /* "plus" sign (+) */ + font-size: $defaultFontSize * 0.8125; + float: right; + color: transparent; + text-shadow: 0 0 0 #fff; + position: absolute; + bottom: 3px; + right: 6px; + } + + &.active:after { + content: "\2796"; /* "minus" sign (-) */ + } -.accordion-header.active:after { - content: "\2796"; /* "minus" sign (-) */ - font-size: $defaultFontSize * 0.8125; - color: #fff; - float: right; - margin-left: 5px; } .accordion-panel { @@ -591,13 +591,10 @@ a:visited { background-color: #555; overflow-y: auto; overflow-x: none; -} -.accordion-panel div, -.accordion-panel ul, -.accordion-panel p, -.accordion-panel ul > li { - background-color: #555; + div, ul, p, ul > li { + background-color: #555; + } } /* override the global styling */ From 8b99e46d5e5c50525e89bc6922216e80cd75e178 Mon Sep 17 00:00:00 2001 From: danielyxie Date: Wed, 29 Aug 2018 14:06:21 -0500 Subject: [PATCH 04/20] Updated Interactive Tutorial and added a few helpful links to the hackers-starting-handbook Literature file --- css/interactivetutorial.scss | 22 +- src/HacknetNode.js | 6 +- src/InteractiveTutorial.js | 631 +++++++++++++---------------------- src/Literature.js | 6 +- src/Player.js | 2 + src/Script.js | 25 +- src/Terminal.js | 9 +- 7 files changed, 292 insertions(+), 409 deletions(-) diff --git a/css/interactivetutorial.scss b/css/interactivetutorial.scss index 15b8f3cc9..0c5aa3fdd 100644 --- a/css/interactivetutorial.scss +++ b/css/interactivetutorial.scss @@ -11,11 +11,11 @@ position: absolute; /* Stay in place */ right: 0; top: 0; - height: 400px; /* Full height */ + height: 450px; padding: 10px; border: 5px solid #fff; - width: 20%; - overflow: auto; /* Enable scroll if needed */ + width: 23%; + overflow:hidden; background-color: #444; /* Fallback color */ color: #fff; @@ -29,6 +29,9 @@ margin: 4px; color: #fff; background-color: #444; + font-size: $defaultFontSize * 0.875; + max-height: 350px; + overflow-y: auto; } #interactive-tutorial-exit, @@ -38,7 +41,7 @@ @include boxShadow(1px 1px 3px #000); color: #aaa; - font-size: $defaultFontSize * 1.25; + font-size: $defaultFontSize * 1.125; font-weight: bold; background-color: #000; @@ -50,6 +53,7 @@ } } +/* #interactive-tutorial-exit { float: left; } @@ -58,6 +62,16 @@ margin-right: 20%; float: right; } +*/ +#interactive-tutorial-exit { + position:absolute; + bottom: 0; + left:0; +} + +#interactive-tutorial-back { + float: left; +} #interactive-tutorial-next { float: right; diff --git a/src/HacknetNode.js b/src/HacknetNode.js index 8f1faa218..94c943591 100644 --- a/src/HacknetNode.js +++ b/src/HacknetNode.js @@ -2,7 +2,7 @@ import {BitNodeMultipliers} from "./BitNodeMultipliers"; import {CONSTANTS} from "./Constants"; import {Engine} from "./engine"; import {iTutorialSteps, iTutorialNextStep, - iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial"; + ITutorial} from "./InteractiveTutorial"; import {Player} from "./Player"; import {dialogBoxCreate} from "../utils/DialogBox"; import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners"; @@ -245,8 +245,8 @@ Reviver.constructors.HacknetNode = HacknetNode; function purchaseHacknet() { /* INTERACTIVE TUTORIAL */ - if (iTutorialIsRunning) { - if (currITutorialStep == iTutorialSteps.HacknetNodesIntroduction) { + if (ITutorial.isRunning) { + if (ITutorial.currStep === iTutorialSteps.HacknetNodesIntroduction) { iTutorialNextStep(); } else { return; diff --git a/src/InteractiveTutorial.js b/src/InteractiveTutorial.js index 953b52cb5..5e3affe09 100644 --- a/src/InteractiveTutorial.js +++ b/src/InteractiveTutorial.js @@ -1,55 +1,77 @@ import {Engine} from "./engine"; import {Player} from "./Player"; -import {dialogBoxCreate} from "../utils/DialogBox"; +import {Settings} from "./Settings"; +import {Terminal} from "./Terminal"; import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners"; +import {createElement} from "../utils/uiHelpers/createElement"; +import {createPopup} from "../utils/uiHelpers/createPopup"; +import {removeElementById} from "../utils/uiHelpers/removeElementById"; -/* InteractiveTutorial.js */ -let iTutorialSteps = { - Start: "Start", - GoToCharacterPage: "Click on the Character page menu link", - CharacterPage: "Introduction to Character page", - CharacterGoToTerminalPage: "Click on the Terminal link", - TerminalIntro: "Introduction to terminal interface", - TerminalHelp: "Using the help command to display all options in terminal", - TerminalLs: "Use the ls command to show all programs/scripts. Right now we have NUKE.exe", - TerminalScan: "Using the scan command to display all available connections", - TerminalScanAnalyze1: "Use the scan-analyze command to show hacking related information", - TerminalScanAnalyze2: "Use the scan-analyze command with a depth of 3", - TerminalConnect: "Using the telnet/connect command to connect to another server", - TerminalAnalyze: "Use the analyze command to display details about this server", - TerminalNuke: "Use the NUKE Program to gain root access to a server", - TerminalManualHack: "Use the hack command to manually hack a server", - TerminalHackingMechanics: "Briefly explain hacking mechanics", - TerminalCreateScript: "Create a script using nano", - TerminalTypeScript: "This occurs in the Script Editor page...type the script then save and close", - TerminalFree: "Use the free command to check RAM", - TerminalRunScript: "Use the run command to run a script", - TerminalGoToActiveScriptsPage: "Go to the ActiveScriptsPage", - ActiveScriptsPage: "Introduction to the Active Scripts Page", - ActiveScriptsToTerminal: "Go from Active Scripts Page Back to Terminal", - TerminalTailScript: "Use the tail command to show a script's logs", - GoToHacknetNodesPage: "Go to the Hacknet Nodes page", - HacknetNodesIntroduction: "Introduction to Hacknet Nodesm and have user purchase one", - HacknetNodesGoToWorldPage: "Go to the world page", - WorldDescription: "Tell the user to explore..theres a lot of different stuff to do out there", - TutorialPageInfo: "The tutorial page contains a lot of info on different subjects", - End: "End", +//Ordered array of keys to Interactive Tutorial Steps +const orderedITutorialSteps = [ + "Start", + "GoToCharacterPage", //Click on 'Stats' page + "CharacterPage", //Introduction to 'Stats' page + "CharacterGoToTerminalPage", //Go back to Terminal + "TerminalIntro", //Introduction to Terminal + "TerminalHelp", //Using 'help' Terminal command + "TerminalLs", //Using 'ls' Terminal command + "TerminalScan", //Using 'scan' Terminal command + "TerminalScanAnalyze1", //Using 'scan-analyze' Terminal command + "TerminalScanAnalyze2", //Using 'scan-analyze 3' Terminal command + "TerminalConnect", //Connecting to foodnstuff + "TerminalAnalyze", //Analyzing foodnstuff + "TerminalNuke", //NUKE foodnstuff + "TerminalManualHack", //Hack foodnstuff + "TerminalHackingMechanics", //Explanation of hacking mechanics + "TerminalCreateScript", //Create a script using 'nano' + "TerminalTypeScript", //Script Editor page - Type script and then save & close + "TerminalFree", //Using 'Free' Terminal command + "TerminalRunScript", //Running script using 'run' Terminal command + "TerminalGoToActiveScriptsPage", + "ActiveScriptsPage", + "ActiveScriptsToTerminal", + "TerminalTailScript", + "GoToHacknetNodesPage", + "HacknetNodesIntroduction", + "HacknetNodesGoToWorldPage", + "WorldDescription", + "TutorialPageInfo", + "End" +] + +//Create an 'enum' for the Steps +const iTutorialSteps = {}; +for (let i = 0; i < orderedITutorialSteps.length; ++i) { + iTutorialSteps[orderedITutorialSteps[i]] = i; } -var currITutorialStep = iTutorialSteps.Start; -var iTutorialIsRunning = false; +var ITutorial = { + currStep: 0, //iTutorialSteps.Start + isRunning: false, + + //Keeps track of whether each step has been done + stepIsDone: {}, +} function iTutorialStart() { + //Initialize Interactive Tutorial state by settings 'done' for each state to false + ITutorial.stepIsDone = {}; + for (let i = 0; i < orderedITutorialSteps.length; ++i) { + ITutorial.stepIsDone[i] = false; + } + + Engine.loadTerminalContent(); + Terminal.resetTerminalInput(); + //Don't autosave during this interactive tutorial - Engine.Counters.autoSaveCounter = 999000000000; + Engine.Counters.autoSaveCounter = Infinity; console.log("Interactive Tutorial started"); - currITutorialStep = iTutorialSteps.Start; - iTutorialIsRunning = true; + ITutorial.currStep = 0; + ITutorial.isRunning = true; document.getElementById("interactive-tutorial-container").style.display = "block"; - iTutorialEvaluateStep(); - //Exit tutorial button var exitButton = clearEventListeners("interactive-tutorial-exit"); exitButton.addEventListener("click", function() { @@ -59,142 +81,150 @@ function iTutorialStart() { //Back button var backButton = clearEventListeners("interactive-tutorial-back"); - backButton.style.display = "none"; backButton.addEventListener("click", function() { iTutorialPrevStep(); return false; }); + + //Next button + var nextButton = clearEventListeners("interactive-tutorial-next"); + nextButton.addEventListener("click", function() { + iTutorialNextStep(); + return false; + }); + + iTutorialEvaluateStep(); } function iTutorialEvaluateStep() { - if (!iTutorialIsRunning) {console.log("Interactive Tutorial not running"); return;} - switch(currITutorialStep) { + if (!ITutorial.isRunning) {console.log("Interactive Tutorial not running"); return;} + + //Disable and clear main menu + var terminalMainMenu = clearEventListeners("terminal-menu-link"); + var statsMainMenu = clearEventListeners("stats-menu-link"); + var activeScriptsMainMenu = clearEventListeners("active-scripts-menu-link"); + var hacknetMainMenu = clearEventListeners("hacknet-nodes-menu-link"); + var cityMainMenu = clearEventListeners("city-menu-link"); + var tutorialMainMenu = clearEventListeners("tutorial-menu-link"); + terminalMainMenu.removeAttribute("class"); + statsMainMenu.removeAttribute("class"); + activeScriptsMainMenu.removeAttribute("class"); + hacknetMainMenu.removeAttribute("class"); + cityMainMenu.removeAttribute("class"); + tutorialMainMenu.removeAttribute("class"); + + //Interactive Tutorial Next button + var nextBtn = document.getElementById("interactive-tutorial-next"); + + switch(ITutorial.currStep) { case iTutorialSteps.Start: Engine.loadTerminalContent(); - iTutorialSetText("Welcome to Bitburner, a cyberpunk-themed incremental RPG! " + "The game takes place in a dark, dystopian future...The year is 2077...

" + "This tutorial will show you the basics of the game. " + "You may skip the tutorial at any time."); - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "inline-block"; - next.addEventListener("click", function() { - iTutorialNextStep(); - return false; - }); + nextBtn.style.display = "inline-block"; break; case iTutorialSteps.GoToCharacterPage: + Engine.loadTerminalContent(); iTutorialSetText("Let's start by heading to the Stats page. Click the 'Stats' tab on " + "the main navigation menu (left-hand side of the screen)"); + nextBtn.style.display = "none"; - //No next button - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "none"; - - //Flash Character tab - document.getElementById("stats-menu-link").setAttribute("class", "flashing-button"); - - //Initialize everything necessary to open the "Character" page - var charaterMainMenuButton = document.getElementById("stats-menu-link"); - charaterMainMenuButton.addEventListener("click", function() { + //Flash 'Stats' menu and set its tutorial click handler + statsMainMenu.setAttribute("class", "flashing-button"); + statsMainMenu.addEventListener("click", function() { Engine.loadCharacterContent(); iTutorialNextStep(); //Opening the character page will go to the next step - clearEventListeners("stats-menu-link"); return false; }); break; case iTutorialSteps.CharacterPage: + Engine.loadCharacterContent(); iTutorialSetText("The Stats page shows a lot of important information about your progress, " + "such as your skills, money, and bonuses/multipliers. ") - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "inline-block"; - next.addEventListener("click", function() { - iTutorialNextStep(); - return false; - }); + nextBtn.style.display = "inline-block"; break; case iTutorialSteps.CharacterGoToTerminalPage: + Engine.loadCharacterContent(); iTutorialSetText("Let's head to your computer's terminal by clicking the 'Terminal' tab on the " + "main navigation menu."); - //No next button - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "none"; + nextBtn.style.display = "none"; - document.getElementById("terminal-menu-link").setAttribute("class", "flashing-button"); - - //Initialize everything necessary to open the 'Terminal' Page - var terminalMainMenuButton = document.getElementById("terminal-menu-link"); - terminalMainMenuButton.addEventListener("click", function() { + //Flash 'Terminal' menu and set its tutorial click handler + terminalMainMenu.setAttribute("class", "flashing-button"); + terminalMainMenu.addEventListener("click", function() { Engine.loadTerminalContent(); iTutorialNextStep(); - clearEventListeners("terminal-menu-link"); return false; }); break; case iTutorialSteps.TerminalIntro: + Engine.loadTerminalContent(); iTutorialSetText("The Terminal is used to interface with your home computer as well as " + "all of the other machines around the world."); - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "inline-block"; - next.addEventListener("click", function() { - iTutorialNextStep(); - return false; - }); + nextBtn.style.display = "inline-block"; break; case iTutorialSteps.TerminalHelp: + Engine.loadTerminalContent(); iTutorialSetText("Let's try it out. Start by entering the 'help' command into the Terminal " + "(Don't forget to press Enter after typing the command)"); - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "none"; - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalLs: + Engine.loadTerminalContent(); iTutorialSetText("The 'help' command displays a list of all available Terminal commands, how to use them, " + "and a description of what they do.

Let's try another command. Enter the 'ls' command"); - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalScan: + Engine.loadTerminalContent(); iTutorialSetText("'ls' is a basic command that shows all of the contents (programs/scripts) " + "on the computer. Right now, it shows that you have a program called 'NUKE.exe' on your computer. " + "We'll get to what this does later.

Using your home computer's terminal, you can connect " + "to other machines throughout the world. Let's do that now by first entering " + - "the 'scan' command. "); - //next step triggered by terminal command + "the 'scan' command."); + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalScanAnalyze1: + Engine.loadTerminalContent(); iTutorialSetText("The 'scan' command shows all available network connections. In other words, " + "it displays a list of all servers that can be connected to from your " + "current machine. A server is identified by either its IP or its hostname.

" + "That's great and all, but there's so many servers. Which one should you go to? " + "The 'scan-analyze' command gives some more detailed information about servers on the " + "network. Try it now"); - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalScanAnalyze2: + Engine.loadTerminalContent(); iTutorialSetText("You just ran 'scan-analyze' with a depth of one. This command shows more detailed " + "information about each server that you can connect to (servers that are a distance of " + "one node away).

It is also possible to run 'scan-analyze' with " + "a higher depth. Let's try a depth of two with the following command: 'scan-analyze 2'.") - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalConnect: + Engine.loadTerminalContent(); iTutorialSetText("Now you can see information about all servers that are up to two nodes away, as well " + "as figure out how to navigate to those servers through the network. You can only connect to " + "a server that is one node away. To connect to a machine, use the 'connect [ip/hostname]' command. You can type in " + "the ip or the hostname, but dont use both.

" + "From the results of the 'scan-analyze' command, we can see that the 'foodnstuff' server is " + "only one node away. Let's connect so it now using: 'connect foodnstuff'"); - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalAnalyze: + Engine.loadTerminalContent(); iTutorialSetText("You are now connected to another machine! What can you do now? You can hack it!

In the year 2077, currency has " + "become digital and decentralized. People and corporations store their money " + "on servers and computers. Using your hacking abilities, you can hack servers " + "to steal money and gain experience.

" + "Before you try to hack a server, you should run diagnostics using the 'analyze' command"); - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalNuke: + Engine.loadTerminalContent(); iTutorialSetText("When the 'analyze' command finishes running it will show useful information " + "about hacking the server.

For this server, the required hacking skill is only 1, " + "which means you can hack it right now. However, in order to hack a server " + @@ -203,14 +233,16 @@ function iTutorialEvaluateStep() { "open ports.

The 'analyze' results shows that there do not need to be any open ports " + "on this machine for the NUKE virus to work, so go ahead and run the virus using the " + "'run NUKE.exe' command."); - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalManualHack: + Engine.loadTerminalContent(); iTutorialSetText("You now have root access! You can hack the server using the 'hack' command. " + "Try doing that now."); - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalHackingMechanics: + Engine.loadTerminalContent(); iTutorialSetText("You are now attempting to hack the server. Note that performing a hack takes time and " + "only has a certain percentage chance " + "of success. This time and success chance is determined by a variety of factors, including " + @@ -220,25 +252,20 @@ function iTutorialEvaluateStep() { "the server's security level.

The amount of money on a server is not limitless. So, if " + "you constantly hack a server and deplete its money, then you will encounter " + "diminishing returns in your hacking."); - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "inline-block"; - next.addEventListener("click", function() { - iTutorialNextStep(); - return false; - }); + nextBtn.style.display = "inline-block"; break; case iTutorialSteps.TerminalCreateScript: + Engine.loadTerminalContent(); iTutorialSetText("Hacking is the core mechanic of the game and is necessary for progressing. However, " + "you don't want to be hacking manually the entire time. You can automate your hacking " + "by writing scripts!

To create a new script or edit an existing one, you can use the 'nano' " + "command. Scripts must end with the '.script' extension. Let's make a script now by " + "entering 'nano foodnstuff.script' after the hack command finishes running (Sidenote: Pressing ctrl + c" + " will end a command like hack early)"); - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "none"; - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalTypeScript: + Engine.loadScriptEditorContent("foodnstuff.script", ""); iTutorialSetText("This is the script editor. You can use it to program your scripts. Scripts are " + "written in the Netscript language, a programming language created for " + "this game. There are details about the Netscript language in the documentation, which " + @@ -251,21 +278,24 @@ function iTutorialEvaluateStep() { "For anyone with basic programming experience, this code should be straightforward. " + "This script will continuously hack the 'foodnstuff' server.

" + "To save and close the script editor, press the button in the bottom left, or press ctrl + b."); - //next step triggered in saveAndCloseScriptEditor() (Script.js) + nextBtn.style.display = "none"; //next step triggered in saveAndCloseScriptEditor() (Script.js) break; case iTutorialSteps.TerminalFree: + Engine.loadTerminalContent(); iTutorialSetText("Now we'll run the script. Scripts require a certain amount of RAM to run, and can be " + "run on any machine which you have root access to. Different servers have different " + "amounts of RAM. You can also purchase more RAM for your home server.

To check how much " + "RAM is available on this machine, enter the 'free' command."); - //next step triggered by terminal commmand + nextBtn.style.display = "none"; //next step triggered by terminal commmand break; case iTutorialSteps.TerminalRunScript: + Engine.loadTerminalContent(); iTutorialSetText("We have 16GB of free RAM on this machine, which is enough to run our " + "script. Let's run our script using 'run foodnstuff.script'."); - //next step triggered by terminal commmand + nextBtn.style.display = "none"; //next step triggered by terminal commmand break; case iTutorialSteps.TerminalGoToActiveScriptsPage: + Engine.loadTerminalContent(); iTutorialSetText("Your script is now running! The script might take a few seconds to 'fully start up'. " + "Your scripts will continuously run in the background and will automatically stop if " + "the code ever completes (the 'foodnstuff.script' will never complete because it " + @@ -274,117 +304,114 @@ function iTutorialEvaluateStep() { "much slower rate.

" + "Let's check out some statistics for our running scripts by clicking the " + "'Active Scripts' link in the main navigation menu."); - document.getElementById("active-scripts-menu-link").setAttribute("class", "flashing-button"); - var activeScriptsMainMenuButton = document.getElementById("active-scripts-menu-link"); - activeScriptsMainMenuButton.addEventListener("click", function() { + nextBtn.style.display = "none"; + + //Flash 'Active Scripts' menu and set its tutorial click handler + activeScriptsMainMenu.setAttribute("class", "flashing-button"); + activeScriptsMainMenu.addEventListener("click", function() { Engine.loadActiveScriptsContent(); iTutorialNextStep(); - clearEventListeners("active-scripts-menu-link"); return false; }); break; case iTutorialSteps.ActiveScriptsPage: + Engine.loadActiveScriptsContent(); iTutorialSetText("This page displays stats/information about all of your scripts that are " + "running across every existing server. You can use this to gauge how well " + "your scripts are doing. Let's go back to the Terminal now using the 'Terminal'" + "link."); - document.getElementById("terminal-menu-link").setAttribute("class", "flashing-button"); - //Initialize everything necessary to open the 'Terminal' Page - var terminalMainMenuButton = clearEventListeners("terminal-menu-link"); - terminalMainMenuButton.addEventListener("click", function() { + nextBtn.style.display = "none"; + + //Flash 'Terminal' button and set its tutorial click handler + terminalMainMenu.setAttribute("class", "flashing-button"); + terminalMainMenu.addEventListener("click", function() { Engine.loadTerminalContent(); iTutorialNextStep(); - clearEventListeners("terminal-menu-link"); return false; }); break; case iTutorialSteps.ActiveScriptsToTerminal: + Engine.loadTerminalContent(); iTutorialSetText("One last thing about scripts, each active script contains logs that detail " + "what it's doing. We can check these logs using the 'tail' command. Do that " + "now for the script we just ran by typing 'tail foodnstuff.script'"); - //next step triggered by terminal command + nextBtn.style.display = "none"; //next step triggered by terminal command break; case iTutorialSteps.TerminalTailScript: + Engine.loadTerminalContent(); iTutorialSetText("The log for this script won't show much right now (it might show nothing at all) because it " + "just started running...but check back again in a few minutes!

" + "This pretty much covers the basics of hacking. To learn more about writing " + "scripts using the Netscript language, select the 'Tutorial' link in the " + - "main navigation menu to look at the documentation. For now, let's move on " + - "to something else!"); - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "inline-block"; - next.addEventListener("click", function() { - iTutorialNextStep(); - return false; - }); + "main navigation menu to look at the documentation. " + + "If you are an experienced JavaScript " + + "developer, I would highly suggest you check out the section on " + + "NetscriptJS/Netscript 2.0.

For now, let's move on to something else!"); + nextBtn.style.display = "inline-block"; break; case iTutorialSteps.GoToHacknetNodesPage: + Engine.loadTerminalContent(); iTutorialSetText("Hacking is not the only way to earn money. One other way to passively " + "earn money is by purchasing and upgrading Hacknet Nodes. Let's go to " + "the 'Hacknet Nodes' page through the main navigation menu now."); - document.getElementById("hacknet-nodes-menu-link").setAttribute("class", "flashing-button"); - var hacknetNodesButton = clearEventListeners("hacknet-nodes-menu-link"); - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "none"; - hacknetNodesButton.addEventListener("click", function() { + nextBtn.style.display = "none"; + + //Flash 'Hacknet' menu and set its tutorial click handler + hacknetMainMenu.setAttribute("class", "flashing-button"); + hacknetMainMenu.addEventListener("click", function() { Engine.loadHacknetNodesContent(); iTutorialNextStep(); - clearEventListeners("hacknet-nodes-menu-link"); return false; }); break; case iTutorialSteps.HacknetNodesIntroduction: + Engine.loadHacknetNodesContent(); iTutorialSetText("From this page you can purchase new Hacknet Nodes and upgrade your " + "existing ones. Let's purchase a new one now."); - //Next step triggered by purchaseHacknet() (HacknetNode.js) + nextBtn.style.display = "none"; //Next step triggered by purchaseHacknet() (HacknetNode.js) break; case iTutorialSteps.HacknetNodesGoToWorldPage: + Engine.loadHacknetNodesContent(); iTutorialSetText("You just purchased a Hacknet Node! This Hacknet Node will passively " + "earn you money over time, both online and offline. When you get enough " + " money, you can upgrade " + "your newly-purchased Hacknet Node below.

" + "Let's go to the 'City' page through the main navigation menu."); - document.getElementById("city-menu-link").setAttribute("class", "flashing-button"); - var worldButton = clearEventListeners("city-menu-link"); - worldButton.addEventListener("click", function() { + nextBtn.style.display = "none"; + + //Flash 'City' menu and set its tutorial click handler + cityMainMenu.setAttribute("class", "flashing-button"); + cityMainMenu.addEventListener("click", function() { Engine.loadWorldContent(); iTutorialNextStep(); - clearEventListeners("city-menu-link"); return false; }); break; case iTutorialSteps.WorldDescription: + Engine.loadWorldContent(); iTutorialSetText("This page lists all of the different locations you can currently " + "travel to. Each location has something that you can do. " + "There's a lot of content out in the world, make sure " + "you explore and discover!

" + "Lastly, click on the 'Tutorial' link in the main navigation menu."); - document.getElementById("tutorial-menu-link").setAttribute("class", "flashing-button"); - var tutorialButton = clearEventListeners("tutorial-menu-link"); - tutorialButton.addEventListener("click", function() { + nextBtn.style.display = "none"; + + //Flash 'Tutorial' menu and set its tutorial click handler + tutorialMainMenu.setAttribute("class", "flashing-button"); + tutorialMainMenu.addEventListener("click", function() { Engine.loadTutorialContent(); iTutorialNextStep(); - clearEventListeners("tutorial-menu-link"); return false; }); break; - case iTutorialSteps.TutorialPageInfo: + Engine.loadTutorialContent(); iTutorialSetText("This page contains a lot of different documentation about the game's " + "content and mechanics. I know it's a lot, but I highly suggest you read " + "(or at least skim) through this before you start playing. That's the end of the tutorial. " + "Hope you enjoy the game!"); - var next = clearEventListeners("interactive-tutorial-next"); - next.style.display = "inline-block"; - next.innerHTML = "Finish Tutorial"; - - var backButton = clearEventListeners("interactive-tutorial-back"); - backButton.style.display = "none"; - - next.addEventListener("click", function() { - iTutorialNextStep(); - return false; - }); + nextBtn.style.display = "inline-block"; + nextBtn.innerHTML = "Finish Tutorial"; break; case iTutorialSteps.End: iTutorialEnd(); @@ -392,264 +419,85 @@ function iTutorialEvaluateStep() { default: throw new Error("Invalid tutorial step"); } + + if (ITutorial.stepIsDone[ITutorial.currStep] === true) { + nextBtn.style.display = "inline-block"; + } } //Go to the next step and evaluate it function iTutorialNextStep() { - switch(currITutorialStep) { - case iTutorialSteps.Start: - currITutorialStep = iTutorialSteps.GoToCharacterPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.GoToCharacterPage: + //Special behavior for certain steps + if (ITutorial.currStep === iTutorialSteps.GoToCharacterPage) { document.getElementById("stats-menu-link").removeAttribute("class"); - currITutorialStep = iTutorialSteps.CharacterPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.CharacterPage: - currITutorialStep = iTutorialSteps.CharacterGoToTerminalPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.CharacterGoToTerminalPage: - document.getElementById("terminal-menu-link").removeAttribute("class"); - currITutorialStep = iTutorialSteps.TerminalIntro; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalIntro: - currITutorialStep = iTutorialSteps.TerminalHelp; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalHelp: - currITutorialStep = iTutorialSteps.TerminalLs; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalLs: - currITutorialStep = iTutorialSteps.TerminalScan; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalScan: - currITutorialStep = iTutorialSteps.TerminalScanAnalyze1; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalScanAnalyze1: - currITutorialStep = iTutorialSteps.TerminalScanAnalyze2; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalScanAnalyze2: - currITutorialStep = iTutorialSteps.TerminalConnect; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalConnect: - currITutorialStep = iTutorialSteps.TerminalAnalyze; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalAnalyze: - currITutorialStep = iTutorialSteps.TerminalNuke; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalNuke: - currITutorialStep = iTutorialSteps.TerminalManualHack; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalManualHack: - currITutorialStep = iTutorialSteps.TerminalHackingMechanics; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalHackingMechanics: - currITutorialStep = iTutorialSteps.TerminalCreateScript; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalCreateScript: - currITutorialStep = iTutorialSteps.TerminalTypeScript; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalTypeScript: - currITutorialStep = iTutorialSteps.TerminalFree; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalFree: - currITutorialStep = iTutorialSteps.TerminalRunScript; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalRunScript: - currITutorialStep = iTutorialSteps.TerminalGoToActiveScriptsPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalGoToActiveScriptsPage: - document.getElementById("active-scripts-menu-link").removeAttribute("class"); - currITutorialStep = iTutorialSteps.ActiveScriptsPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.ActiveScriptsPage: - document.getElementById("terminal-menu-link").removeAttribute("class"); - currITutorialStep = iTutorialSteps.ActiveScriptsToTerminal; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.ActiveScriptsToTerminal: - currITutorialStep = iTutorialSteps.TerminalTailScript; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalTailScript: - currITutorialStep = iTutorialSteps.GoToHacknetNodesPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.GoToHacknetNodesPage: - document.getElementById("hacknet-nodes-menu-link").removeAttribute("class"); - currITutorialStep = iTutorialSteps.HacknetNodesIntroduction; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.HacknetNodesIntroduction: - currITutorialStep = iTutorialSteps.HacknetNodesGoToWorldPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.HacknetNodesGoToWorldPage: - document.getElementById("city-menu-link").removeAttribute("class"); - currITutorialStep = iTutorialSteps.WorldDescription; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.WorldDescription: - document.getElementById("tutorial-menu-link").removeAttribute("class"); - currITutorialStep = iTutorialSteps.TutorialPageInfo; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TutorialPageInfo: - currITutorialStep = iTutorialSteps.End; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.End: - break; - default: - throw new Error("Invalid tutorial step"); } + if (ITutorial.currStep === iTutorialSteps.CharacterGoToTerminalPage) { + document.getElementById("terminal-menu-link").removeAttribute("class"); + } + if (ITutorial.currStep === iTutorialSteps.TerminalGoToActiveScriptsPage) { + document.getElementById("active-scripts-menu-link").removeAttribute("class"); + } + if (ITutorial.currStep === iTutorialSteps.ActiveScriptsPage) { + document.getElementById("terminal-menu-link").removeAttribute("class"); + } + if (ITutorial.currStep === iTutorialSteps.GoToHacknetNodesPage) { + document.getElementById("hacknet-nodes-menu-link").removeAttribute("class"); + } + if (ITutorial.currStep === iTutorialSteps.HacknetNodesGoToWorldPage) { + document.getElementById("city-menu-link").removeAttribute("class"); + } + if (ITutorial.currStep === iTutorialSteps.WorldDescription) { + document.getElementById("tutorial-menu-link").removeAttribute("class"); + } + + ITutorial.stepIsDone[ITutorial.currStep] = true; + if (ITutorial.currStep < iTutorialSteps.End) { + ITutorial.currStep += 1; + } + iTutorialEvaluateStep(); } //Go to previous step and evaluate function iTutorialPrevStep() { - switch(currITutorialStep) { - case iTutorialSteps.Start: - currITutorialStep = iTutorialSteps.Start; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.GoToCharacterPage: - currITutorialStep = iTutorialSteps.Start; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.CharacterPage: - currITutorialStep = iTutorialSteps.GoToCharacterPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.CharacterGoToTerminalPage: - currITutorialStep = iTutorialSteps.CharacterPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalIntro: - currITutorialStep = iTutorialSteps.CharacterGoToTerminalPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalHelp: - currITutorialStep = iTutorialSteps.TerminalIntro; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalLs: - currITutorialStep = iTutorialSteps.TerminalHelp; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalScan: - currITutorialStep = iTutorialSteps.TerminalLs; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalConnect: - currITutorialStep = iTutorialSteps.TerminalScan; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalAnalyze: - currITutorialStep = iTutorialSteps.TerminalConnect; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalNuke: - currITutorialStep = iTutorialSteps.TerminalAnalyze; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalManualHack: - currITutorialStep = iTutorialSteps.TerminalNuke; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalHackingMechanics: - currITutorialStep = iTutorialSteps.TerminalManualHack; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalCreateScript: - currITutorialStep = iTutorialSteps.TerminalManualHack; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalTypeScript: - currITutorialStep = iTutorialSteps.TerminalCreateScript; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalFree: - currITutorialStep = iTutorialSteps.TerminalTypeScript; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalRunScript: - currITutorialStep = iTutorialSteps.TerminalFree; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalGoToActiveScriptsPage: - currITutorialStep = iTutorialSteps.TerminalRunScript; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.ActiveScriptsPage: - currITutorialStep = iTutorialSteps.TerminalGoToActiveScriptsPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.ActiveScriptsToTerminal: - currITutorialStep = iTutorialSteps.ActiveScriptsPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TerminalTailScript: - currITutorialStep = iTutorialSteps.ActiveScriptsToTerminal; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.GoToHacknetNodesPage: - currITutorialStep = iTutorialSteps.TerminalTailScript; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.HacknetNodesIntroduction: - currITutorialStep = iTutorialSteps.GoToHacknetNodesPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.HacknetNodesGoToWorldPage: - currITutorialStep = iTutorialSteps.HacknetNodesIntroduction; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.WorldDescription: - currITutorialStep = iTutorialSteps.HacknetNodesGoToWorldPage; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.TutorialPageInfo: - currITutorialStep = iTutorialSteps.WorldDescription; - iTutorialEvaluateStep(); - break; - case iTutorialSteps.End: - break; - default: - throw new Error("Invalid tutorial step"); + if (ITutorial.currStep > iTutorialSteps.Start) { + ITutorial.currStep -= 1; } + iTutorialEvaluateStep(); } function iTutorialEnd() { //Re-enable auto save - Engine.Counters.autoSaveCounter = 300; + if (Settings.AutosaveInterval === 0) { + Engine.Counters.autoSaveCounter = Infinity; + } else { + Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5; + } + console.log("Ending interactive tutorial"); Engine.init(); - currITutorialStep = iTutorialSteps.End; - iTutorialIsRunning = false; + ITutorial.currStep = iTutorialSteps.End; + ITutorial.isRunning = false; document.getElementById("interactive-tutorial-container").style.display = "none"; - dialogBoxCreate("If you are new to the game, the following links may be useful for you!

" + - "Getting Started Guide" + - "Wiki

" + - "The Beginner's Guide to Hacking was added to your home computer! It contains some tips/pointers for starting out with the game. " + - "To read it, go to Terminal and enter

cat hackers-starting-handbook.lit"); + + //Create a popup with final introductory stuff + var popupId = "interactive-tutorial-ending-popup"; + var txt = createElement("p", { + innerHTML: + "If you are new to the game, the following links may be useful for you!

" + + "Getting Started Guide" + + "Wiki" + + "Documentation

" + + "The Beginner's Guide to Hacking was added to your home computer! It contains some tips/pointers for starting out with the game. " + + "To read it, go to Terminal and enter

cat hackers-starting-handbook.lit" + }); + var gotitBtn = createElement("a", { + class:"a-link-button", float:"right", padding:"6px", innerText:"Got it!", + clickListener:()=>{ + removeElementById(popupId); + } + }); + createPopup(popupId, [txt, gotitBtn]); + Player.getHomeComputer().messages.push("hackers-starting-handbook.lit"); } @@ -660,5 +508,4 @@ function iTutorialSetText(txt) { textBox.parentElement.scrollTop = 0; // this resets scroll position } -export {iTutorialSteps, iTutorialEnd, iTutorialStart, iTutorialNextStep, currITutorialStep, - iTutorialIsRunning}; +export {iTutorialSteps, iTutorialEnd, iTutorialStart, iTutorialNextStep, ITutorial}; diff --git a/src/Literature.js b/src/Literature.js index bb80e6a70..c38c2e1b8 100644 --- a/src/Literature.js +++ b/src/Literature.js @@ -23,7 +23,11 @@ function initLiterature() { var title, fn, txt; title = "The Beginner's Guide to Hacking"; fn = "hackers-starting-handbook.lit"; - txt = "When starting out, hacking is the most profitable way to earn money and progress. This " + + txt = "Some resources:

" + + "Learn to Program

" + + "For Experienced JavaScript Developers: NetscriptJS

" + + "Netscript Documentation

" + + "When starting out, hacking is the most profitable way to earn money and progress. This " + "is a brief collection of tips/pointers on how to make the most out of your hacking scripts.

" + "-hack() and grow() both work by percentages. hack() steals a certain percentage of the " + "money on a server, and grow() increases the amount of money on a server by some percentage (multiplicatively)

" + diff --git a/src/Player.js b/src/Player.js index 48d4771a5..b552f144e 100644 --- a/src/Player.js +++ b/src/Player.js @@ -566,6 +566,8 @@ PlayerObject.prototype.analyze = function() { PlayerObject.prototype.hasProgram = function(programName) { var home = Player.getHomeComputer(); + if (home == null) {return false;} + for (var i = 0; i < home.programs.length; ++i) { if (programName.toLowerCase() == home.programs[i].toLowerCase()) {return true;} } diff --git a/src/Script.js b/src/Script.js index fca23dc83..670ff2cd7 100644 --- a/src/Script.js +++ b/src/Script.js @@ -21,7 +21,7 @@ import {CONSTANTS} from "./Constants"; import {Engine} from "./engine"; import {FconfSettings, parseFconfSettings} from "./Fconf"; import {iTutorialSteps, iTutorialNextStep, - iTutorialIsRunning, currITutorialStep} from "./InteractiveTutorial"; + ITutorial} from "./InteractiveTutorial"; import {evaluateImport} from "./NetscriptEvaluator"; import {NetscriptFunctions} from "./NetscriptFunctions"; import {addWorkerScript, @@ -281,8 +281,9 @@ function saveAndCloseScriptEditor() { var filename = document.getElementById("script-editor-filename").value; var editor = ace.edit('javascript-editor'); var code = editor.getValue(); - if (iTutorialIsRunning && currITutorialStep == iTutorialSteps.TerminalTypeScript) { - if (filename != "foodnstuff.script") { + if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) { + //Make sure filename + code properly follow tutorial + if (filename !== "foodnstuff.script") { dialogBoxCreate("Leave the script name as 'foodnstuff'!"); return; } @@ -291,7 +292,23 @@ function saveAndCloseScriptEditor() { dialogBoxCreate("Please copy and paste the code from the tutorial!"); return; } - iTutorialNextStep(); + + //Save the script + let s = Player.getCurrentServer(); + for (var i = 0; i < s.scripts.length; i++) { + if (filename == s.scripts[i].filename) { + s.scripts[i].saveScript(); + Engine.loadTerminalContent(); + return iTutorialNextStep(); + } + } + + //If the current script does NOT exist, create a new one + let script = new Script(); + script.saveScript(); + s.scripts.push(script); + + return iTutorialNextStep(); } if (filename == "") { diff --git a/src/Terminal.js b/src/Terminal.js index 821416ac2..d87277a60 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -12,8 +12,7 @@ import {FconfSettings, parseFconfSettings, createFconf} from "./Fconf"; import {TerminalHelpText, HelpTexts} from "./HelpText"; import {iTutorialNextStep, iTutorialSteps, - iTutorialIsRunning, - currITutorialStep} from "./InteractiveTutorial"; + ITutorial} from "./InteractiveTutorial"; import {showLiterature} from "./Literature"; import {showMessage, Message} from "./Message"; import {scriptCalculateHackingTime, @@ -762,11 +761,11 @@ let Terminal = { if (commandArray.length == 0) {return;} /****************** Interactive Tutorial Terminal Commands ******************/ - if (iTutorialIsRunning) { + if (ITutorial.isRunning) { var foodnstuffServ = GetServerByHostname("foodnstuff"); if (foodnstuffServ == null) {throw new Error("Could not get foodnstuff server"); return;} - switch(currITutorialStep) { + switch(ITutorial.currStep) { case iTutorialSteps.TerminalHelp: if (commandArray[0] == "help") { post(TerminalHelpText); @@ -1809,7 +1808,7 @@ let Terminal = { * @returns {void} */ /** - * @type {Object. { From 63cd269d5ec8c9ce82d2120f6d1adbe49dd7da3b Mon Sep 17 00:00:00 2001 From: danielyxie Date: Wed, 29 Aug 2018 15:25:01 -0500 Subject: [PATCH 05/20] b1t_flume.exe program can now be created instantly (reqd hacking level is 1 instead of 5). Fixed some linting errors --- css/interactivetutorial.scss | 6 +++--- css/styles.scss | 1 - src/CreateProgram.js | 4 ++-- src/Settings.ts | 14 +++++++------- utils/helpers/getTimestamp.ts | 3 +++ 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/css/interactivetutorial.scss b/css/interactivetutorial.scss index 0c5aa3fdd..143260d6d 100644 --- a/css/interactivetutorial.scss +++ b/css/interactivetutorial.scss @@ -15,7 +15,7 @@ padding: 10px; border: 5px solid #fff; width: 23%; - overflow:hidden; + overflow: hidden; background-color: #444; /* Fallback color */ color: #fff; @@ -64,9 +64,9 @@ } */ #interactive-tutorial-exit { - position:absolute; + position: absolute; bottom: 0; - left:0; + left: 0; } #interactive-tutorial-back { diff --git a/css/styles.scss b/css/styles.scss index 6daebde94..b725b4fff 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -579,7 +579,6 @@ a:visited { &.active:after { content: "\2796"; /* "minus" sign (-) */ } - } .accordion-panel { diff --git a/src/CreateProgram.js b/src/CreateProgram.js index dd8159e78..f3a808a54 100644 --- a/src/CreateProgram.js +++ b/src/CreateProgram.js @@ -83,9 +83,9 @@ const Programs = { time: CONSTANTS.MillisecondsPerQuarterHour, }), BitFlume: new Program("b1t_flum3.exe", { - level: 5, + level: 1, tooltip:"This program creates a portal to the BitNode Nexus (allows you to restart and switch BitNodes)", - req: function() {return Player.sourceFiles.length > 0 && Player.hacking_skill >= 5}, + req: function() {return Player.sourceFiles.length > 0 && Player.hacking_skill >= 1}, time: CONSTANTS.MillisecondsPerFiveMinutes / 5, }), // special because you can't create it. diff --git a/src/Settings.ts b/src/Settings.ts index ddf5cb0ac..ac081a236 100644 --- a/src/Settings.ts +++ b/src/Settings.ts @@ -39,6 +39,11 @@ interface IDefaultSettings { */ SuppressFactionInvites: boolean; + /** + * Whether to show a popup message when player is hospitalized from taking too much damage + */ + SuppressHospitalizationPopup: boolean; + /** * Whether the user should be shown a dialog box whenever they receive a new message file. */ @@ -48,11 +53,6 @@ interface IDefaultSettings { * Whether the user should be asked to confirm travelling between cities. */ SuppressTravelConfirmation: boolean; - - /** - * Whether to show a popup message when player is hospitalized from taking too much damage - */ - SuppressHospitalizationPopup: boolean; } /** @@ -95,9 +95,9 @@ const defaultSettings: IDefaultSettings = { MaxPortCapacity: 50, SuppressBuyAugmentationConfirmation: false, SuppressFactionInvites: false, + SuppressHospitalizationPopup: false, SuppressMessages: false, SuppressTravelConfirmation: false, - SuppressHospitalizationPopup: false, }; /** @@ -114,9 +114,9 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = { MaxPortCapacity: defaultSettings.MaxPortCapacity, SuppressBuyAugmentationConfirmation: defaultSettings.SuppressBuyAugmentationConfirmation, SuppressFactionInvites: defaultSettings.SuppressFactionInvites, + SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup, SuppressMessages: defaultSettings.SuppressMessages, SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation, - SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup, ThemeBackgroundColor: "#000000", ThemeFontColor: "#66ff33", ThemeHighlightColor: "#ffffff", diff --git a/utils/helpers/getTimestamp.ts b/utils/helpers/getTimestamp.ts index fd0786166..6e7ee119f 100644 --- a/utils/helpers/getTimestamp.ts +++ b/utils/helpers/getTimestamp.ts @@ -1,3 +1,6 @@ +/** + * Returns a MM/DD HH:MM timestamp for the current time + */ export function getTimestamp() { const d: Date = new Date(); // A negative slice value takes from the end of the string rather than the beginning. From 68527d625810d2ec6ad63ac9a181abea9ad0cf2f Mon Sep 17 00:00:00 2001 From: Steven Evans Date: Mon, 6 Aug 2018 23:36:28 -0400 Subject: [PATCH 06/20] [style] Fixing TSLint violations --- src/FactionInfo.ts | 262 +++++++++++++++++++++++++++------- utils/helpers/getTimestamp.ts | 3 + 2 files changed, 213 insertions(+), 52 deletions(-) diff --git a/src/FactionInfo.ts b/src/FactionInfo.ts index ee0695779..8e9d636cf 100644 --- a/src/FactionInfo.ts +++ b/src/FactionInfo.ts @@ -66,26 +66,43 @@ class FactionInfo { export const FactionInfos: IMap = { // Endgame Illuminati: new FactionInfo( - "Humanity never changes. No matter how civilized society becomes, it will eventually fall back into chaos. And " + - "from this chaos, we are the Invisible hand that guides them to order.", - [], true, true, true, false), + "Humanity never changes. No matter how civilized society becomes, it will eventually fall back into chaos. " + + "And from this chaos, we are the Invisible hand that guides them to order. ", + [], + true, + true, + true, + false), Daedalus: new FactionInfo( "Yesterday we obeyed kings and bent our necks to emperors. Today we kneel only to truth.", - [], true, true, true, false), + [], + true, + true, + true, + false), "The Covenant": new FactionInfo( "Surrender yourself. Give up your empty individuality to become part of something great, something eternal. " + "Become a slave. Submit your mind, body, and soul. Only then can you set yourself free.
" + "
" + "Only then can you discover immortality.", - [], true, true, true, false), + [], + true, + true, + true, + false), // Megacorporations, each forms its own faction ECorp: new FactionInfo( - "ECorp's mission is simple: to connect the world of today with the technology of tomorrow. With our wide range " + - "of Internet-related software and commercial hardware, ECorp makes the world's information universally accessible.", - [], true, true, true, true), + "ECorp's mission is simple: to connect the world of today with the technology of tomorrow. With our wide " + + "range of Internet-related software and commercial hardware, ECorp makes the world's information " + + "universally accessible.", + [], + true, + true, + true, + true), MegaCorp: new FactionInfo( "MegaCorp does things that others don't. We imagine. We create. We invent. We build things that others have " + @@ -93,66 +110,110 @@ export const FactionInfos: IMap = { "unprecendented scale, in ways that no other company can.
" + "
" + "In our labs and factories and on the ground with customers, MegaCorp is ushering in a new era for the world.", - [], true, true, true, true), + [], + true, + true, + true, + true), "Bachman & Associates": new FactionInfo( - "Where Law and Business meet - thats where we are.
" + + "Where Law and Business meet - thats where we are.
" + "
" + "Legal Insight - Business Instinct - Experience Innovation", - [], true, true, true, true), + [], + true, + true, + true, + true), "Blade Industries": new FactionInfo( "Augmentation is salvation", - [], true, true, true, true), + [], + true, + true, + true, + true), NWO: new FactionInfo( - "The human being does not truly desire freedom. It wants to be observed, understood, and judged. It wants to be " + - "given purpose and direction in its life. That is why humans created God. And that is why humans created " + + "The human being does not truly desire freedom. It wants to be observed, understood, and judged. It wants to " + + "be given purpose and direction in its life. That is why humans created God. And that is why humans created " + "civilization - not because of willingness, but because of a need to be incorporated into higher orders of " + "structure and meaning.", - [], true, true, true, true), + [], + true, + true, + true, + true), "Clarke Incorporated": new FactionInfo( "Unlocking the power of the genome", - [], true, true, true, true), + [], + true, + true, + true, + true), "OmniTek Incorporated": new FactionInfo( "Simply put, our mission is to design and build robots that make a difference", - [], true, true, true, true), + [], + true, + true, + true, + true), "Four Sigma": new FactionInfo( - "The scientific method is the best way to approach investing. Big strategies backed up with big data. Driven by " + - "deep learning and innovative ideas. And improved by iteration. That's Four Sigma.", - [], true, true, true, true), + "The scientific method is the best way to approach investing. Big strategies backed up with big data. Driven " + + "by deep learning and innovative ideas. And improved by iteration. That's Four Sigma.", + [], + true, + true, + true, + true), "KuaiGong International": new FactionInfo( "Dream big. Work hard. Make history.", - [], true, true, true, true), + [], + true, + true, + true, + true), // Other Corporations "Fulcrum Secret Technologies": new FactionInfo( "The human organism has an innate desire to worship. That is why they created gods. If there were no gods, it " + "would be necessary to create them. And now we can.", - [], true, true, false, true), + [], + true, + true, + false, + true), // Hacker groups BitRunners: new FactionInfo( - "Our entire lives are controlled by bits. All of our actions, our thoughts, our personal information. It's all " + - "transformed into bits, stored in bits, communicated through bits. It’s impossible for any person to move, to " + - "live, to operate at any level without the use of bits. And when a person moves, lives, and operates, they leave " + - "behind their bits, mere traces of seemingly meaningless fragments of information. But these bits can be " + + "Our entire lives are controlled by bits. All of our actions, our thoughts, our personal information. It's " + + "all transformed into bits, stored in bits, communicated through bits. It’s impossible for any person to move, " + + "to live, to operate at any level without the use of bits. And when a person moves, lives, and operates, they " + + "leave behind their bits, mere traces of seemingly meaningless fragments of information. But these bits can be " + "reconstructed. Transformed. Used.
" + "
" + "Those who run the bits, run the world", - [], true, true, false, false), + [], + true, + true, + false, + false), "The Black Hand": new FactionInfo( - "The world, so afraid of strong government, now has no government. Only power - Digital power. Financial power. " + - "Technological power. And those at the top rule with an invisible hand. They built a society where the rich get " + - "richer, and everyone else suffers.
" + + "The world, so afraid of strong government, now has no government. Only power - Digital power. Financial " + + "power. Technological power. And those at the top rule with an invisible hand. They built a society where the " + + "rich get richer, and everyone else suffers.
" + "
" + "So much pain. So many lives. Their darkness must end.", - [], true, true, true, false), + [], + true, + true, + true, + false), NiteSec: new FactionInfo( " __..__
" + @@ -190,40 +251,108 @@ export const FactionInfos: IMap = { " d .dNITESEC $ |
" + " :bp.__.gNITESEC$$ :$ ;
" + " NITESECNITESECNIT $$b :
", - [], true, true, false, false), + [], + true, + true, + false, + false), // City factions, essentially governments Aevum: new FactionInfo( "The Silicon City", - ["Chongqing", "New Tokyo", "Ishima", "Volhaven"], true, true, true, true), + [ + "Chongqing", + "New Tokyo", + "Ishima", + "Volhaven", + ], + true, + true, + true, + true), Chongqing: new FactionInfo( "Serve the people", - ["Sector-12", "Aevum", "Volhaven"], true, true, true, true), + [ + "Sector-12", + "Aevum", + "Volhaven", + ], + true, + true, + true, + true), Ishima: new FactionInfo( "The East Asian Order of the Future", - ["Sector-12", "Aevum", "Volhaven"], true, true, true, true), + [ + "Sector-12", + "Aevum", + "Volhaven", + ], + true, + true, + true, + true), "New Tokyo": new FactionInfo( "Asia's World City", - ["Sector-12", "Aevum", "Volhaven"], true, true, true, true), + [ + "Sector-12", + "Aevum", + "Volhaven", + ], + true, + true, + true, + true), "Sector-12": new FactionInfo( "The City of the Future", - ["Chongqing", "New Tokyo", "Ishima", "Volhaven"], true, true, true, true), + [ + "Chongqing", + "New Tokyo", + "Ishima", + "Volhaven", + ], + true, + true, + true, + true), Volhaven: new FactionInfo( "Benefit, Honour, and Glory", - ["Chongqing", "Sector-12", "New Tokyo", "Aevum", "Ishima"], true, true, true, true), + [ + "Chongqing", + "Sector-12", + "New Tokyo", + "Aevum", + "Ishima", + ], + true, + true, + true, + true), // Criminal Organizations/Gangs "Speakers for the Dead": new FactionInfo( "It is better to reign in hell than to serve in heaven.", - [], true, true, true, true), + [], + true, + true, + true, + true), "The Dark Army": new FactionInfo( "The World doesn't care about right or wrong. It's all about power.", - [], true, true, true, false), + [], + true, + true, + true, + false), "The Syndicate": new FactionInfo( "Honor holds you back", - [], true, true, true, true), + [], + true, + true, + true, + true), Silhouette: new FactionInfo( "Corporations have filled the void of power left behind by the collapse of Western government. The issue is " + @@ -231,35 +360,64 @@ export const FactionInfos: IMap = { "corporations, you don't even know who you're working for.
" + "
" + "That's terror. Terror, fear, and corruption. All born into the system, all propagated by the system.", - [], true, true, true, false), + [], + true, + true, + true, + false), Tetrads: new FactionInfo( "Following the Mandate of Heaven and Carrying out the Way", - [], false, false, true, true), + [], + false, + false, + true, + true), "Slum Snakes": new FactionInfo( "Slum Snakes rule!", - [], false, false, true, true), + [], + false, + false, + true, + true), // Earlygame factions - factions the player will prestige with early on that don't belong in other categories. Netburners: new FactionInfo( "~~//*>H4CK|\|3T 8URN3R5**>?>\\~~", - [], true, true, false, false), + [], + true, + true, + false, + false), "Tian Di Hui": new FactionInfo( "Obey Heaven and Work Righteousness", - [], true, true, false, true), + [], + true, + true, + false, + true), CyberSec: new FactionInfo( "The Internet is the first thing that humanity has built that humanity doesn’t understand, the largest " + "experiment in anarchy that we have ever had. And as the world becomes increasingly dominated by the internet, " + - "society approaches the brink of total chaos. We serve only to protect society, to protect humanity, to protect " + - "the world from its imminent collapse.", - [], true, true, false, false), + "society approaches the brink of total chaos. We serve only to protect society, to protect humanity, to " + + "protect the world from its imminent collapse.", + [], + true, + true, + false, + false), // Special Factions Bladeburners: new FactionInfo( - "It's too bad they won't live. But then again, who does?

Note that for this faction, reputation can only " + - "be gained through Bladeburner actions. Completing Bladeburner contracts/operations will increase your reputation.", - [], false, false, false, false), + "It's too bad they won't live. But then again, who does?

Note that for this faction, reputation can " + + "only be gained through Bladeburner actions. Completing Bladeburner contracts/operations will increase your " + + "reputation.", + [], + false, + false, + false, + false), }; diff --git a/utils/helpers/getTimestamp.ts b/utils/helpers/getTimestamp.ts index fd0786166..a26d220c1 100644 --- a/utils/helpers/getTimestamp.ts +++ b/utils/helpers/getTimestamp.ts @@ -1,3 +1,6 @@ +/** + * Formats the current time (to the minute). + */ export function getTimestamp() { const d: Date = new Date(); // A negative slice value takes from the end of the string rather than the beginning. From 26b1c434350e5c9228de442de2617001ba6fac7d Mon Sep 17 00:00:00 2001 From: Steven Evans Date: Fri, 24 Aug 2018 11:48:15 -0400 Subject: [PATCH 07/20] [style] Sorting properties alphabetically --- css/interactivetutorial.scss | 6 +++--- css/styles.scss | 1 - src/Settings.ts | 14 +++++++------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/css/interactivetutorial.scss b/css/interactivetutorial.scss index 0c5aa3fdd..143260d6d 100644 --- a/css/interactivetutorial.scss +++ b/css/interactivetutorial.scss @@ -15,7 +15,7 @@ padding: 10px; border: 5px solid #fff; width: 23%; - overflow:hidden; + overflow: hidden; background-color: #444; /* Fallback color */ color: #fff; @@ -64,9 +64,9 @@ } */ #interactive-tutorial-exit { - position:absolute; + position: absolute; bottom: 0; - left:0; + left: 0; } #interactive-tutorial-back { diff --git a/css/styles.scss b/css/styles.scss index 6daebde94..b725b4fff 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -579,7 +579,6 @@ a:visited { &.active:after { content: "\2796"; /* "minus" sign (-) */ } - } .accordion-panel { diff --git a/src/Settings.ts b/src/Settings.ts index ddf5cb0ac..ac081a236 100644 --- a/src/Settings.ts +++ b/src/Settings.ts @@ -39,6 +39,11 @@ interface IDefaultSettings { */ SuppressFactionInvites: boolean; + /** + * Whether to show a popup message when player is hospitalized from taking too much damage + */ + SuppressHospitalizationPopup: boolean; + /** * Whether the user should be shown a dialog box whenever they receive a new message file. */ @@ -48,11 +53,6 @@ interface IDefaultSettings { * Whether the user should be asked to confirm travelling between cities. */ SuppressTravelConfirmation: boolean; - - /** - * Whether to show a popup message when player is hospitalized from taking too much damage - */ - SuppressHospitalizationPopup: boolean; } /** @@ -95,9 +95,9 @@ const defaultSettings: IDefaultSettings = { MaxPortCapacity: 50, SuppressBuyAugmentationConfirmation: false, SuppressFactionInvites: false, + SuppressHospitalizationPopup: false, SuppressMessages: false, SuppressTravelConfirmation: false, - SuppressHospitalizationPopup: false, }; /** @@ -114,9 +114,9 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = { MaxPortCapacity: defaultSettings.MaxPortCapacity, SuppressBuyAugmentationConfirmation: defaultSettings.SuppressBuyAugmentationConfirmation, SuppressFactionInvites: defaultSettings.SuppressFactionInvites, + SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup, SuppressMessages: defaultSettings.SuppressMessages, SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation, - SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup, ThemeBackgroundColor: "#000000", ThemeFontColor: "#66ff33", ThemeHighlightColor: "#ffffff", From 552ce183c1616f940809e1e903d9f10804d1cb92 Mon Sep 17 00:00:00 2001 From: Steven Evans Date: Thu, 30 Aug 2018 10:43:18 -0400 Subject: [PATCH 08/20] [chore] Introduce HTML-Webpack This issue means that any changes to the HTML has to happen in the `.\src\index.html` file rather than the `.\index.html`. This makes the `index.html` in the root now a build artifact the same way that files in `dist\` are. --- index.html | 34 +- package-lock.json | 316 ++++++++++++++ package.json | 1 + src/index.html | 1023 +++++++++++++++++++++++++++++++++++++++++++++ webpack.config.js | 37 ++ 5 files changed, 1392 insertions(+), 19 deletions(-) create mode 100644 src/index.html diff --git a/index.html b/index.html index 66439fff0..a6307476f 100644 --- a/index.html +++ b/index.html @@ -8,13 +8,11 @@ - - - +