Merge pull request #24 from danielyxie/dev

Dev v0.16
This commit is contained in:
danielyxie 2017-05-25 11:58:15 -04:00 committed by GitHub
commit eab8c1a3bb
23 changed files with 686 additions and 223 deletions

3
.gitignore vendored Normal file

@ -0,0 +1,3 @@
Changelog.txt
Netburner.txt
README.md

@ -30,18 +30,25 @@
overflow-y: scroll; overflow-y: scroll;
} }
#script-editor-filename-tag { #script-editor-buttons-wrapper {
padding-top: 10px; width: 100%;
padding-bottom: 0px; padding-right: 0xp;
float: left; margin-right: 0px;
} }
#script-editor-save-and-close-button, #script-editor-save-and-close-button,
#script-editor-netscript-doc-button {
display: inline-block;
}
#script-editor-save-and-close-button {
float:left;
}
#script-editor-netscript-doc-button { #script-editor-netscript-doc-button {
float: right; float: right;
display: block; padding-right: 0px;
width: 50%; margin-right: 2px;
margin-right: 25%;
} }
#script-editor-netscript-doc-warning { #script-editor-netscript-doc-warning {
@ -52,13 +59,37 @@
background-color: #666; background-color: #666;
} }
#script-editor-wrapper {
height:100%;
width: 70%;
}
#script-editor-filename-wrapper {
background-color: #555;
margin-left: 6px;
margin-right: 0px;
padding-left: 6px;
width: 100%;
border: 2px solid white;
}
#script-editor-filename-tag {
display: inline-block;
padding-top: 10px;
padding-bottom: 0px;
float:center;
background-color: #555;
}
#script-editor-filename { #script-editor-filename {
float: left; background-color: #555;
display: inline-block;
float: center;
resize: none; resize: none;
color: #66ff33; color: white;
width: 70%; margin: 4px;
margin: 10px;
padding: 5px; padding: 2px;
border: 2px solid white; border: 2px solid white;
-webkit-box-shadow: -webkit-box-shadow:
@ -79,11 +110,14 @@
#script-editor-text { #script-editor-text {
color: #66ff33; color: #66ff33;
width: 70%; height: 80%;
height: 100%; width: 100%;
margin: 10px; margin-left: 6px;
padding: 5px;
padding-left: 6px;
padding-top: 6px;
padding-bottom: 6px;
border: 2px solid white; border: 2px solid white;
-webkit-box-shadow: -webkit-box-shadow:
inset 0 0 8px rgba(0,0,0,0.1), inset 0 0 8px rgba(0,0,0,0.1),
@ -228,6 +262,10 @@
width: 70%; width: 70%;
} }
#create-program-list {
width: 70%;
}
.create-program-a-link-button { .create-program-a-link-button {
text-decoration: none; text-decoration: none;
background-color: #555; background-color: #555;

@ -4,7 +4,7 @@
#dialog-box-container { #dialog-box-container {
display: none; /* Hidden by default */ display: none; /* Hidden by default */
position: fixed; /* Stay in place */ position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */ z-index: 2; /* Sit on top */
left: 0; left: 0;
top: 0; top: 0;
width: 100%; /* Full width */ width: 100%; /* Full width */
@ -15,6 +15,7 @@
} }
#dialog-box-content { #dialog-box-content {
z-index: 2;
background-color: black; background-color: black;
margin: 20% auto; /* 20% from the top and centered */ margin: 20% auto; /* 20% from the top and centered */
padding: 10px; padding: 10px;
@ -285,7 +286,7 @@
color: #66ff33; color: #66ff33;
} }
#trave-l-box-text { #travel-box-text {
margin: 8px; margin: 8px;
} }
@ -312,4 +313,52 @@
color: white; color: white;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
}
/* Game Options */
#game-options-container {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
right: 0;
bottom: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: black; /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
transition: opacity 400ms ease-in;
}
#game-options-content {
background-color: black;
margin: 15% auto; /* 15% from the top and centered */
padding: 10px;
border: 5px solid #FFFFFF;
width: 50%; /* Could be more or less, depending on screen size */
color: #66ff33;
}
#game-options-close-button {
color: #aaa;
float: right;
margin: 4px;
padding: 4px;
font-size: 20px;
font-weight: bold;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px white;
-moz-box-shadow: 1px 1px 3px #000;
-webkit-box-shadow: 1px 1px 3px #000;
box-shadow: 1px 1px 3px #000;
}
#game-options-close-button:hover,
#game-options-close-button:focus {
color: white;
text-decoration: none;
cursor: pointer;
} }

@ -241,7 +241,7 @@ tr:focus {
position: absolute; /* Stay in place */ position: absolute; /* Stay in place */
right: 0; right: 0;
top: 0; top: 0;
height: 150px; /* Full height */ height: 175px; /* Full height */
/*margin: 50% auto;*/ /*margin: 50% auto;*/
padding: 5px; padding: 5px;
border: 2px solid #66ff33; border: 2px solid #66ff33;
@ -257,3 +257,22 @@ tr:focus {
color: white; color: white;
background-color: #444; background-color: #444;
} }
#character-overview-save-button {
color: #aaa;
font-size: 16px;
font-weight: bold;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
-moz-box-shadow: 1px 1px 3px #000;
-webkit-box-shadow: 1px 1px 3px #000;
box-shadow: 1px 1px 3px #000;
}
#character-overview-save-button:hover,
#character-overview-save-button:focus {
color: white;
text-decoration: none;
cursor: pointer;
}

@ -4,10 +4,12 @@
padding-top: 10px; padding-top: 10px;
padding-left: 10px; padding-left: 10px;
height: 100%; height: 100%;
width: 99%;
} }
#work-in-progress-text { #work-in-progress-text {
color: #66ff33; color: #66ff33;
width: 70%;
} }
#work-in-progress-cancel-button { #work-in-progress-cancel-button {

@ -24,6 +24,7 @@
<script src="utils/PurchaseAugmentationBox.js"></script> <script src="utils/PurchaseAugmentationBox.js"></script>
<script src="utils/TravelBox.js"></script> <script src="utils/TravelBox.js"></script>
<script src="utils/PurchaseRamForHomeBox.js"></script> <script src="utils/PurchaseRamForHomeBox.js"></script>
<script src="utils/GameOptions.js"></script>
<!-- Netscript --> <!-- Netscript -->
<script src="src/NetscriptWorker.js"></script> <script src="src/NetscriptWorker.js"></script>
@ -105,19 +106,10 @@
<li class="tutorial-tab"> <li class="tutorial-tab">
<a href="#" id="tutorial-menu-link"> Tutorial </a> <a href="#" id="tutorial-menu-link"> Tutorial </a>
</li> </li>
<li class="save-game-tab">
<a href="#" id="save-game-link"> Save Game </a>
</li>
<li class="delete-game-tab">
<a href="#" id="delete-game-link"> Delete Game </a>
</li>
<li class="debug-delete-scripts-tab"> <li class="options-tab">
<a href="#" id="debug-delete-scripts-link"> (DEBUG) Delete Active Scripts </a> <a id="options-menu-link"> Options </a>
</li> </li>
</ul> </ul>
</div> </div>
@ -143,17 +135,19 @@
<!-- Script editor --> <!-- Script editor -->
<div id="script-editor-container"> <div id="script-editor-container">
<div> <div id="script-editor-wrapper">
<p id="script-editor-filename-tag"> Script name: </p> <div id="script-editor-filename-wrapper">
<span id="script-editor-save-and-close-button" class="a-link-button">Save & Close (Ctrl + b)</span> <p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
<span id="script-editor-netscript-doc-button" class="a-link-button"> Netscript Documentation <input id="script-editor-filename" type="text" maxlength="30" tabindex="1"> </input>
<p id="script-editor-netscript-doc-warning" style="font-size:12px"> Warning: You will lose unsaved content! </p> </span>
</div> </div>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"> </input>
<br>
<br><br>
<textarea id="script-editor-text" tabindex="2" autofocus> </textarea> <textarea id="script-editor-text" tabindex="2" autofocus> </textarea>
<div id="script-editor-buttons-wrapper">
<span id="script-editor-save-and-close-button" class="a-link-button">Save & Close (Ctrl + b)</span>
<span id="script-editor-netscript-doc-button" class="a-link-button"> Netscript Documentation
<p id="script-editor-netscript-doc-warning" style="font-size:12px"> Warning: You will lose unsaved content! </p>
</span>
</div>
</div>
<p> <br><br> </p> <p> <br><br> </p>
</div> </div>
@ -418,16 +412,22 @@
relaySMTP.exe relaySMTP.exe
<span class="tooltiptext"> This program opens SMTP ports by redirecting data </span> <span class="tooltiptext"> This program opens SMTP ports by redirecting data </span>
</a> </a>
<a class="create-program-a-link-button tooltip" id="create-program-httpworm" href="#"> <a class="create-program-a-link-button tooltip" id="create-program-httpworm" href="#">
HTTPWorm.exe HTTPWorm.exe
<span class="tooltiptext"> This virus opens up HTTP ports </span> <span class="tooltiptext"> This virus opens up HTTP ports </span>
</a> </a>
<a class="create-program-a-link-button tooltip" id="create-program-sqlinject" href="#"> <a class="create-program-a-link-button tooltip" id="create-program-sqlinject" href="#">
SQLInject.exe SQLInject.exe
<span class="tooltiptext"> This virus opens SQL ports</span> <span class="tooltiptext"> This virus opens SQL ports</span>
</a> </a>
<a class="create-program-a-link-button tooltip" id="create-program-deepscanv1" href="#">
DeepscanV1.exe
<span class="tooltiptext"> This program allows you to use the scan-analyze command with a depth up to 5</span>
</a>
<a class="create-program-a-link-button tooltip" id="create-program-deepscanv2" href="#">
DeepscanV2.exe
<span class="tooltiptext"> This program allows you to use the scan-analyze command with a depth up to 10</span>
</a>
</ul> </ul>
</div> </div>
@ -633,7 +633,7 @@
<!-- Dialog Box, displays status text only --> <!-- Dialog Box, displays status text only -->
<div id="dialog-box-container"> <div id="dialog-box-container">
<div id="dialog-box-content"> <div id="dialog-box-content" class="dialog-box">
<span id="dialog-box-close-button">&times;</span> <span id="dialog-box-close-button">&times;</span>
<p id="dialog-box-text-1" class="dialog-box-text"> </p> <p id="dialog-box-text-1" class="dialog-box-text"> </p>
<br> <br>
@ -731,6 +731,7 @@
<div id="character-overview-wrapper"> <div id="character-overview-wrapper">
<div id="character-overview-container"> <div id="character-overview-container">
<p id="character-overview-text"> </p> <p id="character-overview-text"> </p>
<span id="character-overview-save-button"> Save Game </span>
</div> </div>
</div> </div>
@ -739,5 +740,17 @@
<p id="status-text">Test </p> <p id="status-text">Test </p>
</div> </div>
<!-- Game Options -->
<div id="game-options-container">
<div id="game-options-content" class="game-options-box">
<span id="game-options-close-button">&times;</span>
<h1> Game Options </h1>
<br>
<a id="save-game-link" class="a-link-button" style="display:block;"> Save Game </a>
<a id="delete-game-link" class="a-link-button" style="display:block;"> Delete Game </a>
<a id="debug-delete-scripts-link" class="a-link-button" style="display:block;"> (DEBUG) Delete Active Scripts </a>
</div>
</div>
</body> </body>
</html> </html>

@ -223,58 +223,58 @@ CompanyPositions = {
//Constructor: CompanyPosition(name, reqHack, reqStr, reqDef, reqDex, reqAgi, reqCha, reqRep, salary) //Constructor: CompanyPosition(name, reqHack, reqStr, reqDef, reqDex, reqAgi, reqCha, reqRep, salary)
//Software //Software
SoftwareIntern: new CompanyPosition("Software Engineering Intern", 1, 0, 0, 0, 0, 0, 0, 8), SoftwareIntern: new CompanyPosition("Software Engineering Intern", 1, 0, 0, 0, 0, 0, 0, 12),
JuniorDev: new CompanyPosition("Junior Software Engineer", 51, 0, 0, 0, 0, 0, 8000, 20), JuniorDev: new CompanyPosition("Junior Software Engineer", 51, 0, 0, 0, 0, 0, 8000, 25),
SeniorDev: new CompanyPosition("Senior Software Engineer", 251, 0, 0, 0, 0, 51, 32000, 40), SeniorDev: new CompanyPosition("Senior Software Engineer", 251, 0, 0, 0, 0, 51, 32000, 50),
LeadDev: new CompanyPosition("Lead Software Developer", 401, 0, 0, 0, 0, 151, 144000, 120), LeadDev: new CompanyPosition("Lead Software Developer", 401, 0, 0, 0, 0, 151, 144000, 150),
//TODO Through darkweb, maybe? //TODO Through darkweb, maybe?
FreelanceDeveloper: new CompanyPosition("Freelance Developer", 0, 0, 0, 0, 0, 0, 0, 0), FreelanceDeveloper: new CompanyPosition("Freelance Developer", 0, 0, 0, 0, 0, 0, 0, 0),
SoftwareConsultant: new CompanyPosition("Software Consultant", 51, 0, 0, 0, 0, 0, 0, 15), SoftwareConsultant: new CompanyPosition("Software Consultant", 51, 0, 0, 0, 0, 0, 0, 16),
SeniorSoftwareConsultant: new CompanyPosition("Senior Software Consultant", 251, 0, 0, 0, 0, 51, 0, 30), SeniorSoftwareConsultant: new CompanyPosition("Senior Software Consultant", 251, 0, 0, 0, 0, 51, 0, 32),
//IT //IT
ITIntern: new CompanyPosition("IT Intern", 1, 0, 0, 0, 0, 0, 0, 1.75), ITIntern: new CompanyPosition("IT Intern", 1, 0, 0, 0, 0, 0, 0, 10),
ITAnalyst: new CompanyPosition("IT Analyst", 26, 0, 0, 0, 0, 0, 6000, 7.5), ITAnalyst: new CompanyPosition("IT Analyst", 26, 0, 0, 0, 0, 0, 6000, 20),
ITManager: new CompanyPosition("IT Manager", 151, 0, 0, 0, 0, 51, 24000, 35), ITManager: new CompanyPosition("IT Manager", 151, 0, 0, 0, 0, 51, 24000, 35),
SysAdmin: new CompanyPosition("Systems Administrator", 251, 0, 0, 0, 0, 76, 120000, 100), SysAdmin: new CompanyPosition("Systems Administrator", 251, 0, 0, 0, 0, 76, 120000, 100),
SecurityEngineer: new CompanyPosition("Security Engineer", 151, 0, 0, 0, 0, 26, 28000, 35), SecurityEngineer: new CompanyPosition("Security Engineer", 151, 0, 0, 0, 0, 26, 28000, 38),
NetworkEngineer: new CompanyPosition("Network Engineer", 151, 0, 0, 0, 0, 26, 28000, 35), NetworkEngineer: new CompanyPosition("Network Engineer", 151, 0, 0, 0, 0, 26, 28000, 38),
NetworkAdministrator: new CompanyPosition("Network Administrator", 251, 0, 0, 0, 0, 76, 120000, 100), NetworkAdministrator: new CompanyPosition("Network Administrator", 251, 0, 0, 0, 0, 76, 120000, 100),
//Technology management //Technology management
HeadOfSoftware: new CompanyPosition("Head of Software", 501, 0, 0, 0, 0, 251, 288000, 250), HeadOfSoftware: new CompanyPosition("Head of Software", 501, 0, 0, 0, 0, 251, 288000, 275),
HeadOfEngineering: new CompanyPosition("Head of Engineering", 501, 0, 0, 0, 0, 251, 576000, 400), HeadOfEngineering: new CompanyPosition("Head of Engineering", 501, 0, 0, 0, 0, 251, 576000, 500),
VicePresident: new CompanyPosition("Vice President of Technology", 601, 0, 0, 0, 0, 401, 1152000, 600), VicePresident: new CompanyPosition("Vice President of Technology", 601, 0, 0, 0, 0, 401, 1152000, 750),
CTO: new CompanyPosition("Chief Technology Officer", 751, 0, 0, 0, 0, 501, 4608000, 750), CTO: new CompanyPosition("Chief Technology Officer", 751, 0, 0, 0, 0, 501, 4608000, 900),
//Business //Business
BusinessIntern: new CompanyPosition("Business Intern", 1, 0, 0, 0, 0, 1, 0, 10), BusinessIntern: new CompanyPosition("Business Intern", 1, 0, 0, 0, 0, 1, 0, 13),
BusinessAnalyst: new CompanyPosition("Business Analyst", 6, 0, 0, 0, 0, 51, 8000, 25), BusinessAnalyst: new CompanyPosition("Business Analyst", 6, 0, 0, 0, 0, 51, 8000, 32),
BusinessManager: new CompanyPosition("Business Manager", 51, 0, 0, 0, 0, 101, 32000, 60), BusinessManager: new CompanyPosition("Business Manager", 51, 0, 0, 0, 0, 101, 32000, 75),
OperationsManager: new CompanyPosition("Operations Manager", 51, 0, 0, 0, 0, 226, 144000, 180), OperationsManager: new CompanyPosition("Operations Manager", 51, 0, 0, 0, 0, 226, 144000, 220),
CFO: new CompanyPosition("Chief Financial Officer", 76, 0, 0, 0, 0, 501, 576000, 600), CFO: new CompanyPosition("Chief Financial Officer", 76, 0, 0, 0, 0, 501, 576000, 675),
CEO: new CompanyPosition("Chief Executive Officer", 101, 0, 0, 0, 0, 751, 4608000, 1000), CEO: new CompanyPosition("Chief Executive Officer", 101, 0, 0, 0, 0, 751, 4608000, 1100),
BusinessConsultant: new CompanyPosition("Business Consultant", 6, 0, 0, 0, 0, 51, 0, 18), BusinessConsultant: new CompanyPosition("Business Consultant", 6, 0, 0, 0, 0, 51, 0, 21),
SeniorBusinessConsultant: new CompanyPosition("Senior Business Consultant", 51, 0, 0, 0, 0, 226, 0, 135), SeniorBusinessConsultant: new CompanyPosition("Senior Business Consultant", 51, 0, 0, 0, 0, 226, 0, 150),
//Non-tech/management jobs //Non-tech/management jobs
PartTimeWaiter: new CompanyPosition("Part-time Waiter", 0, 0, 0, 0, 0, 0, 0, 6), PartTimeWaiter: new CompanyPosition("Part-time Waiter", 0, 0, 0, 0, 0, 0, 0, 7),
PartTimeEmployee: new CompanyPosition("Part-time Employee", 0, 0, 0, 0, 0, 0, 0, 6), PartTimeEmployee: new CompanyPosition("Part-time Employee", 0, 0, 0, 0, 0, 0, 0, 7),
Waiter: new CompanyPosition("Waiter", 0, 0, 0, 0, 0, 0, 0, 9), Waiter: new CompanyPosition("Waiter", 0, 0, 0, 0, 0, 0, 0, 9),
Employee: new CompanyPosition("Employee", 0, 0, 0, 0, 0, 0, 0, 9), Employee: new CompanyPosition("Employee", 0, 0, 0, 0, 0, 0, 0, 9),
PoliceOfficer: new CompanyPosition("Police Officer", 11, 101, 101, 101, 101, 51, 8000, 25), PoliceOfficer: new CompanyPosition("Police Officer", 11, 101, 101, 101, 101, 51, 8000, 28),
PoliceChief: new CompanyPosition("Police Chief", 101, 301, 301, 301, 301, 151, 32000, 100), PoliceChief: new CompanyPosition("Police Chief", 101, 301, 301, 301, 301, 151, 32000, 110),
SecurityGuard: new CompanyPosition("Security Guard", 0, 51, 51, 51, 51, 1, 0, 16), SecurityGuard: new CompanyPosition("Security Guard", 0, 51, 51, 51, 51, 1, 0, 16),
SecurityOfficer: new CompanyPosition("Security Officer", 26, 151, 151, 151, 151, 51, 8000, 40), SecurityOfficer: new CompanyPosition("Security Officer", 26, 151, 151, 151, 151, 51, 8000, 50),
SecuritySupervisor: new CompanyPosition("Security Supervisor", 26, 251, 251, 251, 251, 101, 32000, 80), SecuritySupervisor: new CompanyPosition("Security Supervisor", 26, 251, 251, 251, 251, 101, 32000, 100),
HeadOfSecurity: new CompanyPosition("Head of Security", 51, 501, 501, 501, 501, 151, 144000, 250), HeadOfSecurity: new CompanyPosition("Head of Security", 51, 501, 501, 501, 501, 151, 144000, 250),
FieldAgent: new CompanyPosition("Field Agent", 101, 101, 101, 101, 101, 101, 8000, 30), FieldAgent: new CompanyPosition("Field Agent", 101, 101, 101, 101, 101, 101, 8000, 40),
SecretAgent: new CompanyPosition("Secret Agent", 201, 251, 251, 251, 251, 32000, 120), SecretAgent: new CompanyPosition("Secret Agent", 201, 251, 251, 251, 251, 32000, 150),
SpecialOperative: new CompanyPosition("Special Operative", 251, 501, 501, 501, 501, 144000, 300), SpecialOperative: new CompanyPosition("Special Operative", 251, 501, 501, 501, 501, 144000, 375),
init: function() { init: function() {
//Argument order: hack, str, def, dex, agi, cha //Argument order: hack, str, def, dex, agi, cha

@ -1,5 +1,5 @@
CONSTANTS = { CONSTANTS = {
Version: "0.15", Version: "0.16",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience //Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then //and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -15,14 +15,14 @@ CONSTANTS = {
BaseCostFor1GBOfRamHacknetNode: 30000, BaseCostFor1GBOfRamHacknetNode: 30000,
BaseCostForHacknetNode: 1000, BaseCostForHacknetNode: 1000,
BaseCostForHacknetNodeCore: 400000, BaseCostForHacknetNodeCore: 500000,
/* Hacknet Node constants */ /* Hacknet Node constants */
HacknetNodeMoneyGainPerLevel: 1.25, HacknetNodeMoneyGainPerLevel: 1.75,
HacknetNodePurchaseNextMult: 1.33, //Multiplier when purchasing an additional hacknet node HacknetNodePurchaseNextMult: 1.33, //Multiplier when purchasing an additional hacknet node
HacknetNodeUpgradeLevelMult: 1.04, //Multiplier for cost when upgrading level HacknetNodeUpgradeLevelMult: 1.04, //Multiplier for cost when upgrading level
HacknetNodeUpgradeRamMult: 1.22, //Multiplier for cost when upgrading RAM HacknetNodeUpgradeRamMult: 1.22, //Multiplier for cost when upgrading RAM
HacknetNodeUpgradeCoreMult: 1.42, //Multiplier for cost when buying another core HacknetNodeUpgradeCoreMult: 1.45, //Multiplier for cost when buying another core
HacknetNodeMaxLevel: 200, HacknetNodeMaxLevel: 200,
HacknetNodeMaxRam: 64, HacknetNodeMaxRam: 64,
@ -52,8 +52,11 @@ CONSTANTS = {
ScriptGetHackingLevelRamCost: 0.1, ScriptGetHackingLevelRamCost: 0.1,
ScriptGetServerMoneyRamCost: 0.1, ScriptGetServerMoneyRamCost: 0.1,
ScriptOperatorRamCost: 0.01, ScriptOperatorRamCost: 0.01,
ScriptPurchaseHacknetRamCost: 1.0, ScriptPurchaseHacknetRamCost: 1.5,
ScriptUpgradeHacknetRamCost: 1.0, ScriptHacknetNodesRamCost: 1.0, //Base cost for accessing hacknet nodes array
ScriptHNUpgLevelRamCost: 0.4,
ScriptHNUpgRamRamCost: 0.6,
ScriptHNUpgCoreRamCost: 0.8,
//Server growth rate //Server growth rate
ServerGrowthRate: 1.00075, ServerGrowthRate: 1.00075,
@ -88,6 +91,9 @@ CONSTANTS = {
MillisecondsPerQuarterHour: 900000, MillisecondsPerQuarterHour: 900000,
GameCyclesPerQuarterHour: 900000 / 200, GameCyclesPerQuarterHour: 900000 / 200,
MillisecondsPerFiveMinutes: 300000,
GameCyclesPerFiveMinutes: 300000 / 200,
FactionWorkHacking: "Faction Hacking Work", FactionWorkHacking: "Faction Hacking Work",
FactionWorkField: "Faction Field Work", FactionWorkField: "Faction Field Work",
FactionWorkSecurity: "Faction Security Work", FactionWorkSecurity: "Faction Security Work",
@ -147,7 +153,7 @@ CONSTANTS = {
"rm Delete a script/program from the machine. (WARNING: Permanent)<br>" + "rm Delete a script/program from the machine. (WARNING: Permanent)<br>" +
"run [script/program] Execute a program or a script<br>" + "run [script/program] Execute a program or a script<br>" +
"scan Displays all available network connections<br>" + "scan Displays all available network connections<br>" +
"scan-analyze Displays hacking-related information for all available network connections<br>" + "scan-analyze [depth] Displays hacking-related information for all servers up to <i>depth</i> nodes away<br>" +
"sudov Shows whether or not you have root access on this computer<br>" + "sudov Shows whether or not you have root access on this computer<br>" +
"tail [script] Display script logs (logs contain details about active scripts)<br>" + "tail [script] Display script logs (logs contain details about active scripts)<br>" +
"top Display all running scripts and their RAM usage<br>", "top Display all running scripts and their RAM usage<br>",
@ -280,20 +286,49 @@ CONSTANTS = {
"<i>getHackingLevel() </i><br> Returns the Player's current hacking level. Does NOT work while offline <br><br> " + "<i>getHackingLevel() </i><br> Returns the Player's current hacking level. Does NOT work while offline <br><br> " +
"<i>getServerMoneyAvailable(hostname/ip)</i><br> Returns the amount of money available on a server. The argument passed in must be a string with either the " + "<i>getServerMoneyAvailable(hostname/ip)</i><br> Returns the amount of money available on a server. The argument passed in must be a string with either the " +
"hostname or IP of the target server. Does NOT work while offline <br> Example: getServerMoneyAvailable('foodnstuff');<br><br>" + "hostname or IP of the target server. Does NOT work while offline <br> Example: getServerMoneyAvailable('foodnstuff');<br><br>" +
"<i>purchaseHacknetNode()</i><br> Purchases a new Hacknet Node. Returns a string with the name of the new Hacknet Node. If the player cannot afford to purchase " + "<i>purchaseHacknetNode()</i><br> Purchases a new Hacknet Node. Returns a number with the index of the Hacknet Node. This index is equivalent to the number " +
"a new hacknet node then the function will return an empty string. Does NOT work offline<br><br>" + "at the end of the Hacknet Node's name (e.g The Hacknet Node named 'hacknet-node-4' will have an index of 4). If the player cannot afford to purchase " +
"<i>upgradeHacknetNode(name)</i><br> Upgrades the level of a Hacknet Node. The argument passed in must be a string with the name of the Hacknet Node to upgrade. " + "a new Hacknet Node then the function will return false. Does NOT work offline<br><br>" +
"If the Hacknet Node is successfully upgraded the function will return true. It will return false otherwise. Does NOT work offline. Example: <br>" + "<u><h1>Hacknet Nodes API</h1></u><br>" +
"node = purchaseHacknetNode();<br>" + "Netscript provides the following API for accessing and upgrading your Hacknet Nodes through scripts. This API does NOT work offline.<br><br>" +
"if (node != '') {<br>" + "<i>hacknetnodes</i><br> A special variable. This is an array that maps to the Player's Hacknet Nodes. The Hacknet Nodes are accessed through " +
"&nbsp;&nbsp;&nbsp;&nbsp;i = 0;<br>" + "indexes. These indexes correspond to the number at the end of the name of the Hacknet Node. For example, the first Hacknet Node you purchase " +
"&nbsp;&nbsp;&nbsp;&nbsp;while(i < 10) {<br>" + "will have the same 'hacknet-node-0' and can be accessed with hacknetnodes[0]. The fourth Hacknet Node you purchase will have the name " +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (upgradeHacknetNode(node)) {i = i + 1;}<br>" + "'hacknet-node-3' and can be accessed with hacknetnodes[3]. <br><br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;}; <br>" + "<i>hacknetnodes.length</i><br> Returns the number of Hacknet Nodes that the player owns<br><br>" +
"<i>hacknetnodes[i].level</i><br> Returns the level of the corresponding Hacknet Node<br><br>" +
"<i>hacknetnodes[i].ram</i><br> Returns the amount of RAM on the corresponding Hacknet Node<br><br>" +
"<i>hacknetnodes[i].cores</i><br> Returns the number of cores on the corresponding Hacknet Node<br><br>" +
"<i>hacknetnodes[i].upgradeLevel(n)</i><br> Tries to upgrade the level of the corresponding Hacknet Node n times. The argument n must be a " +
"positive integer. Returns true if the Hacknet Node's level is successfully upgraded n times, and false otherwise.<br><br>" +
"<i>hacknetnodes[i].upgradeRam()</i><br> Tries to upgrade the amount of RAM on the corresponding Hacknet Node. Returns true if the " +
"RAM is successfully upgraded, and false otherwise. <br><br>" +
"<i>hacknetnodes[i].upgradeCore()</i><br> Attempts to purchase an additional core for the corresponding Hacknet Node. Returns true if the " +
"additional core is successfully purchase, and false otherwise. <br><br>" +
"Example: The following is an example of one way a script can be used to automate the purchasing and upgrading of Hacknet Nodes. " +
"This script purchases new Hacknet Nodes until the player has four. Then, it iteratively upgrades each of those four Hacknet Nodes " +
"to a level of at least 75, RAM to at least 8GB, and number of cores to at least 2.<br><br>" +
"while(hacknetnodes.length < 4) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;purchaseHacknetNode();<br>" +
"};<br>" +
"for (i = 0; i < 4; i = i+1) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;while (hacknetnodes[i].level <= 75) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hacknetnodes[i].upgradeLevel(5);<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(10000);<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;};<br>" +
"};<br>" +
"for (i = 0; i < 4; i = i+1) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;while (hacknetnodes[i].ram < 8) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hacknetnodes[i].upgradeRam();<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(10000);<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;};<br>" +
"};<br>" +
"for (i = 0; i < 4; i = i+1) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;while (hacknetnodes[i].cores < 2) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hacknetnodes[i].upgradeCore();<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(10000);<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;};<br>" +
"};<br><br>" + "};<br><br>" +
"The example code above will attempt to purchase a new Hacknet Node. If the Hacknet Node is purchased, then it will " +
"continuously try to level it up until it is leveled up 10 times. <br><br>" +
"<i>getNumHacknetNodes()</i><br> returns the number of Hacknet Nodes that the Player owns. Does NOT work while offline<br><br>" +
"<u><h1>While loops </h1></u><br>" + "<u><h1>While loops </h1></u><br>" +
"A while loop is a control flow statement that repeatedly executes code as long as a condition is met. <br><br> " + "A while loop is a control flow statement that repeatedly executes code as long as a condition is met. <br><br> " +
"<i>while (<i>[cond]</i>) {<br>&nbsp;&nbsp;&nbsp;&nbsp;<i>[code]</i><br>}</i><br><br>" + "<i>while (<i>[cond]</i>) {<br>&nbsp;&nbsp;&nbsp;&nbsp;<i>[code]</i><br>}</i><br><br>" +

@ -1,11 +1,13 @@
/* Create programs */ /* Create programs */
Programs = { Programs = {
NukeProgram: "NUKE.exe", NukeProgram: "NUKE.exe",
BruteSSHProgram: "BruteSSH.exe", BruteSSHProgram: "BruteSSH.exe",
FTPCrackProgram: "FTPCrack.exe", FTPCrackProgram: "FTPCrack.exe",
RelaySMTPProgram: "relaySMTP.exe", RelaySMTPProgram: "relaySMTP.exe",
HTTPWormProgram: "HTTPWorm.exe", HTTPWormProgram: "HTTPWorm.exe",
SQLInjectProgram: "SQLInject.exe", SQLInjectProgram: "SQLInject.exe",
DeepscanV1: "DeepscanV1.exe",
DeepscanV2: "DeepscanV2.exe",
} }
//TODO Right now the times needed to complete work are hard-coded... //TODO Right now the times needed to complete work are hard-coded...
@ -17,6 +19,8 @@ function displayCreateProgramContent() {
var relaySmtpALink = document.getElementById("create-program-relaysmtp"); var relaySmtpALink = document.getElementById("create-program-relaysmtp");
var httpWormALink = document.getElementById("create-program-httpworm"); var httpWormALink = document.getElementById("create-program-httpworm");
var sqlInjectALink = document.getElementById("create-program-sqlinject"); var sqlInjectALink = document.getElementById("create-program-sqlinject");
var deepscanv1ALink = document.getElementById("create-program-deepscanv1");
var deepscanv2ALink = document.getElementById("create-program-deepscanv2");
nukeALink.style.display = "none"; nukeALink.style.display = "none";
bruteSshALink.style.display = "none"; bruteSshALink.style.display = "none";
@ -24,41 +28,45 @@ function displayCreateProgramContent() {
relaySmtpALink.style.display = "none"; relaySmtpALink.style.display = "none";
httpWormALink.style.display = "none"; httpWormALink.style.display = "none";
sqlInjectALink.style.display = "none"; sqlInjectALink.style.display = "none";
deepscanv1ALink.style.display = "none";
deepscanv2ALink.style.display = "none";
//NUKE.exe (in case you delete it lol) //NUKE.exe (in case you delete it lol)
if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) { if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) {
nukeALink.style.display = "inline-block"; nukeALink.style.display = "inline-block";
} }
//BruteSSH //BruteSSH
if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 && if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 &&
Player.hacking_skill >= 50) { Player.hacking_skill >= 50) {
bruteSshALink.style.display = "inline-block"; bruteSshALink.style.display = "inline-block";
} }
//FTPCrack //FTPCrack
if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 && if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 &&
Player.hacking_skill >= 100) { Player.hacking_skill >= 100) {
ftpCrackALink.style.display = "inline-block"; ftpCrackALink.style.display = "inline-block";
} }
//relaySMTP //relaySMTP
if (Player.getHomeComputer().programs.indexOf(Programs.RelaySMTPProgram) == -1 && if (Player.getHomeComputer().programs.indexOf(Programs.RelaySMTPProgram) == -1 &&
Player.hacking_skill >= 250) { Player.hacking_skill >= 250) {
relaySmtpALink.style.display = "inline-block"; relaySmtpALink.style.display = "inline-block";
} }
//HTTPWorm //HTTPWorm
if (Player.getHomeComputer().programs.indexOf(Programs.HTTPWormProgram) == -1 && if (Player.getHomeComputer().programs.indexOf(Programs.HTTPWormProgram) == -1 &&
Player.hacking_skill >= 500) { Player.hacking_skill >= 500) {
httpWormALink.style.display = "inline-block"; httpWormALink.style.display = "inline-block";
} }
//SQLInject //SQLInject
if (Player.getHomeComputer().programs.indexOf(Programs.SQLInjectProgram) == -1 && if (Player.getHomeComputer().programs.indexOf(Programs.SQLInjectProgram) == -1 &&
Player.hacking_skill >= 750) { Player.hacking_skill >= 750) {
sqlInjectALink.style.display = "inline-block"; sqlInjectALink.style.display = "inline-block";
} }
//Deepscan V1 and V2
if (!Player.hasProgram(Programs.DeepscanV1) && Player.hacking_skill >= 75) {
deepscanv1ALink.style.display = "inline-block";
}
if (!Player.hasProgram(Programs.DeepscanV2) && Player.hacking_skill >= 400) {
deepscanv2ALink.style.display = "inline-block";
}
} }
//Returns the number of programs that are currently available to be created //Returns the number of programs that are currently available to be created
@ -99,5 +107,15 @@ function getNumAvailableCreateProgram() {
Player.hacking_skill >= 750) { Player.hacking_skill >= 750) {
++count; ++count;
} }
//Deepscan V1 and V2
if (!Player.hasProgram(Programs.DeepscanV1) && Player.hacking_skill >= 75) {
++count;
}
if (!Player.hasProgram(Programs.DeepscanV2) && Player.hacking_skill >= 400) {
++count;
}
return count; return count;
} }

@ -305,7 +305,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var bitrunnersFac = Factions["BitRunners"]; var bitrunnersFac = Factions["BitRunners"];
var homeComp = Player.getHomeComputer(); var homeComp = Player.getHomeComputer();
if (bitrunnersFac.isBanned == false && bitrunnersFac.isMember == false && if (bitrunnersFac.isBanned == false && bitrunnersFac.isMember == false &&
this.hacking_skill >= 600 && homeComp.maxRam >= 32) { this.hacking_skill >= 600 && homeComp.maxRam >= 128) {
invitedFactions.push(bitrunnersFac); invitedFactions.push(bitrunnersFac);
} }
@ -313,14 +313,14 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var theblackhandFac = Factions["The Black Hand"]; var theblackhandFac = Factions["The Black Hand"];
if (theblackhandFac.isBanned == false && theblackhandFac.isMember == false && if (theblackhandFac.isBanned == false && theblackhandFac.isMember == false &&
this.hacking_skill >= 400 && this.strength >= 200 && this.defense >= 200 && this.hacking_skill >= 400 && this.strength >= 200 && this.defense >= 200 &&
this.agility >= 200 && this.dexterity >= 200 && homeComp.maxRam >= 16) { this.agility >= 200 && this.dexterity >= 200 && homeComp.maxRam >= 64) {
invitedFactions.push(theblackhandFac); invitedFactions.push(theblackhandFac);
} }
//NiteSec //NiteSec
var nitesecFac = Factions["NiteSec"]; var nitesecFac = Factions["NiteSec"];
if (nitesecFac.isBanned == false && nitesecFac.isMember == false && if (nitesecFac.isBanned == false && nitesecFac.isMember == false &&
this.hacking_skill >= 200 && homeComp.maxRam >= 8) { this.hacking_skill >= 200 && homeComp.maxRam >= 32) {
invitedFactions.push(nitesecFac); invitedFactions.push(nitesecFac);
} }

@ -50,7 +50,7 @@ HacknetNode.prototype.updateMoneyGainRate = function() {
this.moneyGainRatePerSecond = (this.level * gainPerLevel) * this.moneyGainRatePerSecond = (this.level * gainPerLevel) *
Math.pow(1.04, this.ram-1) * Math.pow(1.04, this.ram-1) *
((this.numCores + 1) / 2) * Player.hacknet_node_money_mult; ((this.numCores + 3) / 4) * Player.hacknet_node_money_mult;
if (isNaN(this.moneyGainRatePerSecond)) { if (isNaN(this.moneyGainRatePerSecond)) {
this.moneyGainRatePerSecond = 0; this.moneyGainRatePerSecond = 0;
dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer"); dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer");
@ -73,15 +73,16 @@ HacknetNode.prototype.calculateLevelUpgradeCost = function(levels=1) {
HacknetNode.prototype.purchaseLevelUpgrade = function(levels=1) { HacknetNode.prototype.purchaseLevelUpgrade = function(levels=1) {
var cost = this.calculateLevelUpgradeCost(levels); var cost = this.calculateLevelUpgradeCost(levels);
if (isNaN(cost)) {throw new Error("Cost is NaN"); return;} if (isNaN(cost)) {return false;}
if (cost > Player.money) {return;} if (cost > Player.money) {return false;}
Player.loseMoney(cost); Player.loseMoney(cost);
if (this.level + levels >= CONSTANTS.HacknetNodeMaxLevel) { if (this.level + levels >= CONSTANTS.HacknetNodeMaxLevel) {
this.level = CONSTANTS.HacknetNodeMaxLevel; this.level = CONSTANTS.HacknetNodeMaxLevel;
return; return false;
} }
this.level += levels; this.level += levels;
this.updateMoneyGainRate(); this.updateMoneyGainRate();
return true;
} }
HacknetNode.prototype.calculateRamUpgradeCost = function() { HacknetNode.prototype.calculateRamUpgradeCost = function() {
@ -96,12 +97,13 @@ HacknetNode.prototype.calculateRamUpgradeCost = function() {
HacknetNode.prototype.purchaseRamUpgrade = function() { HacknetNode.prototype.purchaseRamUpgrade = function() {
var cost = this.calculateRamUpgradeCost(); var cost = this.calculateRamUpgradeCost();
if (isNaN(cost)) {throw new Error("Cost is NaN"); return;} if (isNaN(cost)) {return false;}
if (cost > Player.money) {return;} if (cost > Player.money) {return false;}
Player.loseMoney(cost); Player.loseMoney(cost);
if (this.ram >= CONSTANTS.HacknetNodeMaxRam) {return;} if (this.ram >= CONSTANTS.HacknetNodeMaxRam) {return false;}
this.ram *= 2; //Ram is always doubled this.ram *= 2; //Ram is always doubled
this.updateMoneyGainRate(); this.updateMoneyGainRate();
return true;
} }
HacknetNode.prototype.calculateCoreUpgradeCost = function() { HacknetNode.prototype.calculateCoreUpgradeCost = function() {
@ -112,12 +114,13 @@ HacknetNode.prototype.calculateCoreUpgradeCost = function() {
HacknetNode.prototype.purchaseCoreUpgrade = function() { HacknetNode.prototype.purchaseCoreUpgrade = function() {
var cost = this.calculateCoreUpgradeCost(); var cost = this.calculateCoreUpgradeCost();
if (isNaN(cost)) {throw new Error("Cost is NaN"); return;} if (isNaN(cost)) {return false;}
if (cost > Player.money) {return;} if (cost > Player.money) {return false;}
Player.loseMoney(cost); Player.loseMoney(cost);
if (this.numCores >= CONSTANTS.HacknetNodeMaxCores) {return;} if (this.numCores >= CONSTANTS.HacknetNodeMaxCores) {return false;}
++this.numCores; ++this.numCores;
this.updateMoneyGainRate(); this.updateMoneyGainRate();
return true;
} }
/* Saving and loading HackNets */ /* Saving and loading HackNets */

@ -8,6 +8,8 @@ iTutorialSteps = {
TerminalHelp: "Using the help command to display all options in terminal", 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", 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", 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", TerminalConnect: "Using the telnet/connect command to connect to another server",
TerminalAnalyze: "Use the analyze command to display details about this server", TerminalAnalyze: "Use the analyze command to display details about this server",
TerminalNuke: "Use the NUKE Program to gain root access to a server", TerminalNuke: "Use the NUKE Program to gain root access to a server",
@ -155,13 +157,29 @@ function iTutorialEvaluateStep() {
"the 'scan' command. "); "the 'scan' command. ");
//next step triggered by terminal command //next step triggered by terminal command
break; break;
case iTutorialSteps.TerminalConnect: case iTutorialSteps.TerminalScanAnalyze1:
iTutorialSetText("The 'scan' command shows all available network connections. In other words, " + 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 " + "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. <br><br> " + "current machine. A server is identified by either its IP or its hostname. <br><br> " +
"To connect to a machine, use the 'connect [ip/hostname]' command. You can type in " + "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
break;
case iTutorialSteps.TerminalScanAnalyze2:
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). <br><br> 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
break;
case iTutorialSteps.TerminalConnect:
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.<br><br>" + "the ip or the hostname, but dont use both.<br><br>" +
"Let's try this now by connecting to the 'foodnstuff' server (connect foodnstuff)"); "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 //next step triggered by terminal command
break; break;
case iTutorialSteps.TerminalAnalyze: case iTutorialSteps.TerminalAnalyze:
@ -228,7 +246,7 @@ function iTutorialEvaluateStep() {
"}<br><br> " + "}<br><br> " +
"For anyone with basic programming experience, this code should be straightforward. " + "For anyone with basic programming experience, this code should be straightforward. " +
"This script will continuously hack the 'foodnstuff' server. <br><br>" + "This script will continuously hack the 'foodnstuff' server. <br><br>" +
"To save and close the script editor, press the button in the top right, or press ctrl + b."); "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) //next step triggered in saveAndCloseScriptEditor() (Script.js)
break; break;
case iTutorialSteps.TerminalFree: case iTutorialSteps.TerminalFree:
@ -406,6 +424,14 @@ function iTutorialNextStep() {
iTutorialEvaluateStep(); iTutorialEvaluateStep();
break; break;
case iTutorialSteps.TerminalScan: case iTutorialSteps.TerminalScan:
currITutorialStep = iTutorialSteps.TerminalScanAnalyze1;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalScanAnalyze1:
currITutorialStep = iTutorialSteps.TerminalScanAnalyze2;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalScanAnalyze2:
currITutorialStep = iTutorialSteps.TerminalConnect; currITutorialStep = iTutorialSteps.TerminalConnect;
iTutorialEvaluateStep(); iTutorialEvaluateStep();
break; break;

@ -23,6 +23,17 @@ function evaluate(exp, workerScript) {
case "var": case "var":
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);} if (env.stopFlag) {reject(workerScript);}
if (exp.value == "hacknetnodes") {
setTimeout(function() {
var pEvaluateHacknetNode = evaluateHacknetNode(exp, workerScript);
pEvaluateHacknetNode.then(function(res) {
resolve(res);
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
return;
}
try { try {
resolve(env.get(exp.value)); resolve(env.get(exp.value));
} catch (e) { } catch (e) {
@ -371,14 +382,17 @@ function evaluate(exp, workerScript) {
return; return;
} }
workerScript.scriptRef.log("Calling grow() on server " + server.hostname + " in 120 seconds"); var growTime = scriptCalculateGrowTime(server);
console.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds")
workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds");
var p = new Promise(function(resolve, reject) { var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);} if (env.stopFlag) {reject(workerScript);}
setTimeout(function() { setTimeout(function() {
server.moneyAvailable += 1; //It can be grown even if it has no money server.moneyAvailable += 1; //It can be grown even if it has no money
var growthPercentage = processSingleServerGrowth(server, 450); var growthPercentage = processSingleServerGrowth(server, 450);
resolve(growthPercentage); resolve(growthPercentage);
}, 120 * 1000); //grow() takes flat 2 minutes right now }, growTime);
}); });
p.then(function(growthPercentage) { p.then(function(growthPercentage) {
@ -744,7 +758,8 @@ function evaluate(exp, workerScript) {
} }
if (cost > Player.money) { if (cost > Player.money) {
workerScript.scriptRef.log("Could not afford to purchase new Hacknet Node"); workerScript.scriptRef.log("Could not afford to purchase new Hacknet Node");
resolve(""); resolve(false);
return;
} }
//Auto generate a name for the node for now...TODO //Auto generate a name for the node for now...TODO
@ -755,63 +770,17 @@ function evaluate(exp, workerScript) {
Player.loseMoney(cost); Player.loseMoney(cost);
Player.hacknetNodes.push(node); Player.hacknetNodes.push(node);
displayHacknetNodesContent();
workerScript.scriptRef.log("Purchased new Hacknet Node with name: " + name); workerScript.scriptRef.log("Purchased new Hacknet Node with name: " + name);
resolve(name); resolve(numOwned);
}, CONSTANTS.CodeInstructionRunTime); }, CONSTANTS.CodeInstructionRunTime);
} else if (exp.func.value == "upgradeHacknetNode") { }
if (exp.args.length != 1) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|upgradeHacknetNode() call has incorrect number of arguments. Takes 1 argument");
return;
}
var namePromise = evaluate(exp.args[0], workerScript);
namePromise.then(function(name) {
var node = getHacknetNode(name);
if (node == null) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|Invalid Hacknet Node name passed into upgradeHacknetNode()");
return;
}
var cost = node.calculateLevelUpgradeCost(1);
if (isNaN(cost)) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|Could not calculate cost in upgradeHacknetNode(). This is a bug please report to game dev");
return;
}
if (cost > Player.money) {
workerScript.scriptRef.log("Could not afford to upgrade Hacknet Node: " + name);
resolve(false);
return;
}
if (node.level >= CONSTANTS.HacknetNodeMaxLevel) {
workerScript.scriptRef.log("Hacknet Node " + name + " already at max level");
node.level = CONSTANTS.HacknetNodeMaxLevel;
resolve(false);
return;
}
Player.loseMoney(cost);
node.level += 1;
node.updateMoneyGainRate();
workerScript.scriptRef.log("Hacknet node " + name + " upgraded to level " + node.level + "!");
resolve(true);
}, function(e) {
reject(e);
});
} else if (exp.func.value == "getNumHacknetNodes") {
if (exp.args.length != 0) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|getNumHacknetNodes() call has incorrect number of arguments. Takes 0 arguments");
return;
}
setTimeout(function() {
if (env.stopFlag) {reject(workerScript);}
workerScript.scriptRef.log("getNumHacknetNodes() returned " + Player.hacknetNodes.length);
resolve(Player.hacknetNodes.length);
}, CONSTANTS.CodeInstructionRunTime);
}
}, CONSTANTS.CodeInstructionRunTime); }, CONSTANTS.CodeInstructionRunTime);
}); });
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Unrecognized function call"); reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Unrecognized function call");
break; break;
default: default:
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Can't evaluate type " + exp.type); break;
} }
} }
@ -975,6 +944,109 @@ function evaluateWhile(exp, workerScript) {
}); });
} }
function evaluateHacknetNode(exp, workerScript) {
var env = workerScript.env;
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (exp.index == null) {
if ((exp.op.type == "call" && exp.op.value == "length") ||
(exp.op.type == "var" && exp.op.value == "length")) {
resolve(Player.hacknetNodes.length);
workerScript.scriptRef.log("hacknetnodes.length returned " + Player.hacknetNodes.length);
return;
} else {
workerScript.scriptRef.log("Invalid/null index for hacknetnodes");
reject(makeRuntimeRejectMsg(workerScript, "Invalid/null index. hacknetnodes array must be accessed with an index"));
return;
}
}
var indexPromise = evaluate(exp.index.value, workerScript);
indexPromise.then(function(index) {
if (isNaN(index) || index >= Player.hacknetNodes.length || index < 0) {
workerScript.scriptRef.log("Invalid index value for hacknetnodes[]");
reject(makeRuntimeRejectMsg(workerScript, "Invalid index value for hacknetnodes[]."));
return;
}
var nodeObj = Player.hacknetNodes[index];
if (exp.op == null) {
reject(makeRuntimeRejectMsg(workerScript, "No operator or property called for hacknetnodes. Usage: hacknetnodes[i].property/operator"));
return;
} else if (exp.op.type == "var") {
//Get properties: level, ram, cores
switch(exp.op.value) {
case "level":
resolve(nodeObj.level);
break;
case "ram":
resolve(nodeObj.ram);
break;
case "cores":
resolve(nodeObj.numCores);
break;
default:
reject(makeRuntimeRejectMsg(workerScript, "Unrecognized property for Hacknet Node. Valid properties: ram, cores, level"));
break;
}
} else if (exp.op.type == "call") {
switch(exp.op.func.value) {
case "upgradeLevel":
if (exp.op.args.length == 1) {
var argPromise = evaluate(exp.op.args[0], workerScript);
argPromise.then(function(arg) {
if (isNaN(arg) || arg < 0) {
reject(makeRuntimeRejectMsg(workerScript, "Invalid argument passed into upgradeLevel()"));
return;
}
var res = nodeObj.purchaseLevelUpgrade(arg);
if (res) {
workerScript.scriptRef.log("Upgraded " + nodeObj.name + " " + arg + " times to level " + nodeObj.level);
}
resolve(res);
}, function(e) {
reject(e);
});
} else {
var res = nodeObj.purchaseLevelUpgrade(1);
if (res) {
workerScript.scriptRef.log("Upgraded " + nodeObj.name + " once to level " + nodeObj.level);
}
resolve(res);
}
break;
case "upgradeRam":
var res = nodeObj.purchaseRamUpgrade();
if (res) {
workerScript.scriptRef.log("Upgraded " + nodeObj.name + "'s RAM to " + nodeObj.ram + "GB");
}
resolve(res);
break;
case "upgradeCore":
var res = nodeObj.purchaseCoreUpgrade();
if (res) {
workerScript.scriptRef.log("Upgraded " + nodeObj.name + "'s number of cores to " + nodeObj.numCores);
}
resolve(res);
break;
default:
reject(makeRuntimeRejectMsg(workerScript, "Unrecognized function/operator for hacknet node. Valid functions: upgradeLevel(n), upgradeRam(), upgradeCore()"));
break;
}
} else {
reject(makeRuntimeRejectMsg(workerScript, "Unrecognized operation for hacknet node"));
return;
}
}, function(e) {
reject(e);
});
}, CONSTANTS.CodeInstructionRunTime);
}, function(e) {
reject(e);
});
}
function evaluateProg(exp, workerScript, index) { function evaluateProg(exp, workerScript, index) {
var env = workerScript.env; var env = workerScript.env;
@ -1011,6 +1083,10 @@ function evaluateProg(exp, workerScript, index) {
}); });
} }
function makeRuntimeRejectMsg(workerScript, msg) {
return "|"+workerScript.serverIp+"|"+workerScript.name+"|" + msg;
}
function apply_op(op, a, b) { function apply_op(op, a, b) {
function num(x) { function num(x) {
if (typeof x != "number") if (typeof x != "number")
@ -1102,9 +1178,9 @@ function isScriptErrorMessage(msg) {
//The same as Player's calculateHackingChance() function but takes in the server as an argument //The same as Player's calculateHackingChance() function but takes in the server as an argument
function scriptCalculateHackingChance(server) { function scriptCalculateHackingChance(server) {
var difficultyMult = (100 - server.hackDifficulty) / 100; var difficultyMult = (100 - server.hackDifficulty) / 100;
var skillMult = (2 * Player.hacking_chance_mult * Player.hacking_skill); var skillMult = (2 * Player.hacking_skill);
var skillChance = (skillMult - server.requiredHackingSkill) / skillMult; var skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
var chance = skillChance * difficultyMult; var chance = skillChance * difficultyMult * Player.hacking_chance_mult;
if (chance < 0) {return 0;} if (chance < 0) {return 0;}
else {return chance;} else {return chance;}
} }
@ -1126,8 +1202,16 @@ function scriptCalculateExpGain(server) {
function scriptCalculatePercentMoneyHacked(server) { function scriptCalculatePercentMoneyHacked(server) {
var difficultyMult = (100 - server.hackDifficulty) / 100; var difficultyMult = (100 - server.hackDifficulty) / 100;
var skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill; var skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill;
var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 950; var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 875;
if (percentMoneyHacked < 0) {return 0;} if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;} if (percentMoneyHacked > 1) {return 1;}
return percentMoneyHacked; return percentMoneyHacked;
}
//Amount of time to execute grow()
function scriptCalculateGrowTime(server) {
var difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50);
var growTime = skillFactor * 16; //This is in seconds
return growTime * 1000;
} }

@ -187,8 +187,48 @@ function Parser(input) {
cond: cond, cond: cond,
code: code code: code
} }
} }
/* hacknetnodes[i].operator
*/
function parse_hacknetnodes() {
var index = null;
if (is_punc("[")) {
index = parse_expression();
if (index.type != "index") {
console.log("Failed here");
unexpected();
}
}
if (is_punc(".")) {
checkPuncAndSkip(".");
var op = maybe_call(function() {
var tok = input.next();
return tok;
});
return {
type: "var",
value: "hacknetnodes",
index: index,
op: op,
}
}
console.log("Failed here");
unexpected();
}
function parse_arrayindex() {
var index = delimited("[", "]", ";", parse_expression);
var val = 0;
if (index.length == 1 && (index[0].type == "num" || index[0].type == "var")) {
val = index[0];
} else {
console.log("WARNING: Extra indices passed in")
}
return { type: "index", value: val };
}
function parse_bool() { function parse_bool() {
return { return {
@ -211,13 +251,16 @@ function Parser(input) {
return exp; return exp;
} }
if (is_punc("{")) return parse_prog(); if (is_punc("{")) return parse_prog();
if (is_punc("[")) return parse_arrayindex();
if (is_kw("if")) return parse_if(); if (is_kw("if")) return parse_if();
if (is_kw("for")) return parse_for(); if (is_kw("for")) return parse_for();
if (is_kw("while")) return parse_while(); if (is_kw("while")) return parse_while();
//if (is_kw("hacknetnodes")) return parse_hacknetnodes();
//Note, let for loops be function calls (call node types) //Note, let for loops be function calls (call node types)
if (is_kw("true") || is_kw("false")) return parse_bool(); if (is_kw("true") || is_kw("false")) return parse_bool();
var tok = input.next(); var tok = input.next();
if (tok.type == "var" && tok.value == "hacknetnodes") return parse_hacknetnodes();
if (tok.type == "var" || tok.type == "num" || tok.type == "str") if (tok.type == "var" || tok.type == "num" || tok.type == "str")
return tok; return tok;
unexpected(); unexpected();

@ -6,7 +6,7 @@
* {type: "punc", value: "(" } // punctuation: parens, comma, semicolon etc. * {type: "punc", value: "(" } // punctuation: parens, comma, semicolon etc.
* {type: "num", value: 5 } // numbers (including floats) * {type: "num", value: 5 } // numbers (including floats)
* {type: "str", value: "Hello World!" } // strings * {type: "str", value: "Hello World!" } // strings
* {type: "kw", value: "for/if/" } // keywords, see defs below * {type: "kw", value: "for/if/..." } // keywords, see defs below
* {type: "var", value: "a" } // identifiers/variables * {type: "var", value: "a" } // identifiers/variables
* {type: "op", value: "!=" } // operator characters * {type: "op", value: "!=" } // operator characters
* {type: "bool", value: "true" } // Booleans * {type: "bool", value: "true" } // Booleans
@ -46,7 +46,7 @@ function Tokenizer(input) {
} }
function is_punc(ch) { function is_punc(ch) {
return ",;(){}[]".indexOf(ch) >= 0; return ",;(){}[].".indexOf(ch) >= 0;
} }
function is_whitespace(ch) { function is_whitespace(ch) {

@ -176,7 +176,7 @@ function PlayerObject() {
PlayerObject.prototype.init = function() { PlayerObject.prototype.init = function() {
/* Initialize Player's home computer */ /* Initialize Player's home computer */
var t_homeComp = new Server(); var t_homeComp = new Server();
t_homeComp.init(createRandomIp(), "home", "Home PC", true, true, true, true, 2); t_homeComp.init(createRandomIp(), "home", "Home PC", true, true, true, true, 8);
this.homeComputer = t_homeComp.ip; this.homeComputer = t_homeComp.ip;
this.currentServer = t_homeComp.ip; this.currentServer = t_homeComp.ip;
AddToAllServers(t_homeComp); AddToAllServers(t_homeComp);
@ -243,7 +243,7 @@ PlayerObject.prototype.calculateHackingTime = function() {
PlayerObject.prototype.calculatePercentMoneyHacked = function() { PlayerObject.prototype.calculatePercentMoneyHacked = function() {
var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100; var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100;
var skillMult = (this.hacking_skill - (this.getCurrentServer().requiredHackingSkill - 1)) / this.hacking_skill; var skillMult = (this.hacking_skill - (this.getCurrentServer().requiredHackingSkill - 1)) / this.hacking_skill;
var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 950; var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 875;
console.log("Percent money hacked calculated to be: " + percentMoneyHacked); console.log("Percent money hacked calculated to be: " + percentMoneyHacked);
if (percentMoneyHacked < 0) {return 0;} if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;} if (percentMoneyHacked > 1) {return 1;}

@ -185,7 +185,10 @@ Script.prototype.updateRamUsage = function() {
var getServerMoneyAvailableCount = numOccurrences(codeCopy, "getServerMoneyAvailable("); var getServerMoneyAvailableCount = numOccurrences(codeCopy, "getServerMoneyAvailable(");
var numOperators = numNetscriptOperators(codeCopy); var numOperators = numNetscriptOperators(codeCopy);
var purchaseHacknetCount = numOccurrences(codeCopy, "purchaseHacknetNode("); var purchaseHacknetCount = numOccurrences(codeCopy, "purchaseHacknetNode(");
var upgradeHacknetCount = numOccurrences(codeCopy, "upgradeHacknetNode("); var hacknetnodesArrayCount = numOccurrences(codeCopy, "hacknetnodes[");
var hnUpgLevelCount = numOccurrences(codeCopy, ".upgradeLevel(");
var hnUpgRamCount = numOccurrences(codeCopy, ".upgradeRam()");
var hnUpgCoreCount = numOccurrences(codeCopy, ".upgradeCore()");
this.ramUsage = baseRam + this.ramUsage = baseRam +
((whileCount * CONSTANTS.ScriptWhileRamCost) + ((whileCount * CONSTANTS.ScriptWhileRamCost) +
@ -204,7 +207,10 @@ Script.prototype.updateRamUsage = function() {
(getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerMoneyRamCost) + (getServerMoneyAvailableCount * CONSTANTS.ScriptGetServerMoneyRamCost) +
(numOperators * CONSTANTS.ScriptOperatorRamCost) + (numOperators * CONSTANTS.ScriptOperatorRamCost) +
(purchaseHacknetCount * CONSTANTS.ScriptPurchaseHacknetRamCost) + (purchaseHacknetCount * CONSTANTS.ScriptPurchaseHacknetRamCost) +
(upgradeHacknetCount * CONSTANTS.ScriptUpgradeHacknetRamCost)); (hacknetnodesArrayCount * CONSTANTS.ScriptHacknetNodesRamCost) +
(hnUpgLevelCount * CONSTANTS.ScriptHNUpgLevelRamCost) +
(hnUpgRamCount * CONSTANTS.ScriptHNUpgRamRamCost) +
(hnUpgCoreCount * CONSTANTS.ScriptHNUpgCoreRamCost));
console.log("ram usage: " + this.ramUsage); console.log("ram usage: " + this.ramUsage);
if (isNaN(this.ramUsage)) { if (isNaN(this.ramUsage)) {
dialogBoxCreate("ERROR in calculating ram usage. This is a bug, please report to game develoepr"); dialogBoxCreate("ERROR in calculating ram usage. This is a bug, please report to game develoepr");

@ -462,7 +462,7 @@ initForeignServers = function() {
AddToAllServers(PhantasyServer); AddToAllServers(PhantasyServer);
var MaxHardwareServer = new Server(); var MaxHardwareServer = new Server();
MaxHardwareServer.init(createRandomIp(), "max-hardware", "Max Hardware Store", true, false, false, false, 0); MaxHardwareServer.init(createRandomIp(), "max-hardware", "Max Hardware Store", true, false, false, false, 2);
MaxHardwareServer.setHackingParameters(80, 11000000, 15, 25); MaxHardwareServer.setHackingParameters(80, 11000000, 15, 25);
MaxHardwareServer.setPortProperties(1); MaxHardwareServer.setPortProperties(1);
AddToAllServers(MaxHardwareServer); AddToAllServers(MaxHardwareServer);
@ -481,7 +481,7 @@ initForeignServers = function() {
AddToAllServers(CrushFitnessGymServer); AddToAllServers(CrushFitnessGymServer);
var IronGymServer = new Server(); var IronGymServer = new Server();
IronGymServer.init(createRandomIp(), "iron-gym", "Iron Gym Network", true, false, false, false, 0); IronGymServer.init(createRandomIp(), "iron-gym", "Iron Gym Network", true, false, false, false, 2);
IronGymServer.setHackingParameters(100, 20000000, 30, 20); IronGymServer.setHackingParameters(100, 20000000, 30, 20);
IronGymServer.setPortProperties(1); IronGymServer.setPortProperties(1);
AddToAllServers(IronGymServer); AddToAllServers(IronGymServer);

@ -27,15 +27,6 @@ var postNetburnerText = function() {
post("Bitburner v" + CONSTANTS.Version); post("Bitburner v" + CONSTANTS.Version);
} }
/*
$(document).keyup(function(event) {
//Enter
if (event.keyCode == 13) {
}
});
*/
//Defines key commands in terminal //Defines key commands in terminal
$(document).keydown(function(event) { $(document).keydown(function(event) {
//Terminal //Terminal
@ -396,10 +387,23 @@ var Terminal = {
iTutorialNextStep(); iTutorialNextStep();
} else {post("Bad command. Please follow the tutorial");} } else {post("Bad command. Please follow the tutorial");}
break; break;
case iTutorialSteps.TerminalScanAnalyze1:
if (commandArray.length == 1 && commandArray[0] == "scan-analyze") {
Terminal.executeScanAnalyzeCommand(1);
iTutorialNextStep();
} else {post("Bad command. Please follow the tutorial");}
break;
case iTutorialSteps.TerminalScanAnalyze2:
if (commandArray.length == 2 && commandArray[0] == "scan-analyze" &&
commandArray[1] == "2") {
Terminal.executeScanAnalyzeCommand(2);
iTutorialNextStep();
} else {post("Bad command. Please follow the tutorial");}
break;
break;
case iTutorialSteps.TerminalConnect: case iTutorialSteps.TerminalConnect:
if (commandArray.length == 2) { if (commandArray.length == 2) {
if ((commandArray[0] == "connect" || commandArray[0] == "telnet") && if ((commandArray[0] == "connect") &&
(commandArray[1] == "foodnstuff" || commandArray[1] == foodnstuffServ.ip)) { (commandArray[1] == "foodnstuff" || commandArray[1] == foodnstuffServ.ip)) {
Player.getCurrentServer().isConnectedTo = false; Player.getCurrentServer().isConnectedTo = false;
Player.currentServer = foodnstuffServ.ip; Player.currentServer = foodnstuffServ.ip;
@ -733,7 +737,29 @@ var Terminal = {
Terminal.executeScanCommand(commandArray); Terminal.executeScanCommand(commandArray);
break; break;
case "scan-analyze": case "scan-analyze":
Terminal.executeScanAnalyzeCommand(commandArray); if (commandArray.length == 1) {
Terminal.executeScanAnalyzeCommand(1);
} else if (commandArray.length == 2) {
var depth = Number(commandArray[1]);
if (isNaN(depth) || depth < 0) {
post("Incorrect usage of scan-analyze command. depth argument must be positive numeric");
return;
}
if (depth > 3 && !Player.hasProgram(Programs.DeepscanV1) &&
!Player.hasProgram(Programs.DeepscanV2)) {
post("You cannot scan-analyze with that high of a depth. Maximum depth is 3");
return;
} else if (depth > 5 && !Player.hasProgram(Programs.DeepscanV2)) {
post("You cannot scan-analyze with that high of a depth. Maximum depth is 5");
return;
} else if (depth > 10) {
post("You cannot scan-analyze with that high of a depth. Maximum depth is 10");
return;
}
Terminal.executeScanAnalyzeCommand(depth);
} else {
post("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]");
}
break; break;
case "scp": case "scp":
//TODO //TODO
@ -838,20 +864,39 @@ var Terminal = {
} }
}, },
executeScanAnalyzeCommand: function(commandArray) { executeScanAnalyzeCommand: function(depth=1) {
if (commandArray.length != 1) { //We'll use the AllServersToMoneyMap as a visited() array
post("Incorrect usage of scan-analyze command. usage: scan-analyze"); return; //TODO Later refactor this to a generic name
} //TODO Using array as stack for now, can make more efficient
post("~~~~~~~~~~ Beginning scan-analyze ~~~~~~~~~~");
post(" ");
var visited = new AllServersToMoneyMap();
var stack = [];
var depthQueue = [0];
var currServ = Player.getCurrentServer(); var currServ = Player.getCurrentServer();
for (var i = 0; i < currServ.serversOnNetwork.length; ++i) { stack.push(currServ);
var serv = currServ.getServerOnNetwork(i); while(stack.length != 0) {
if (serv == null) {continue;} var s = stack.pop();
post("<strong>" + serv.hostname + "</strong>"); var d = depthQueue.pop();
var c = "N"; if (visited[s.ip] || d > depth) {
if (serv.hasAdminRights) {c = "Y";} continue;
post("--Root Access: " + c); } else {
post("--Required hacking skill: " + serv.requiredHackingSkill); visited[s.ip] = 1;
post("--Number open ports required to NUKE: " + serv.numOpenPortsRequired); }
for (var i = s.serversOnNetwork.length-1; i >= 0; --i) {
stack.push(s.getServerOnNetwork(i));
depthQueue.push(d+1);
}
if (d == 0) {continue;} //Don't print current server
var titleDashes = Array((d-1) * 4 + 1).join("-");
post("<strong>" + titleDashes + ">" + s.hostname + "</strong>");
var dashes = titleDashes + "--";
//var dashes = Array(d * 2 + 1).join("-");
var c = "NO";
if (s.hasAdminRights) {c = "YES";}
post(dashes + "Root Access: " + c + ", Required hacking skill: " + s.requiredHackingSkill);
post(dashes + "Number of open ports required to NUKE: " + s.numOpenPortsRequired);
post(dashes + "RAM: " + s.maxRam);
post(" "); post(" ");
} }
}, },

@ -988,6 +988,12 @@ var Engine = {
return false; return false;
}); });
//Character Overview Save button
var charOverviewSaveButton = document.getElementById("character-overview-save-button");
charOverviewSaveButton.addEventListener("click", function() {
saveObject.saveGame();
return false;
});
//Script Editor Netscript documentation button //Script Editor Netscript documentation button
var netscriptDocButton = document.getElementById("script-editor-netscript-doc-button"); var netscriptDocButton = document.getElementById("script-editor-netscript-doc-button");
@ -999,29 +1005,46 @@ var Engine = {
}); });
//Create Program buttons //Create Program buttons
var portHackALink = document.getElementById("create-program-nuke"); var nukeALink = document.getElementById("create-program-nuke");
var bruteSshALink = document.getElementById("create-program-brutessh"); var bruteSshALink = document.getElementById("create-program-brutessh");
var ftpCrackALink = document.getElementById("create-program-ftpcrack"); var ftpCrackALink = document.getElementById("create-program-ftpcrack");
var relaySmtpALink = document.getElementById("create-program-relaysmtp"); var relaySmtpALink = document.getElementById("create-program-relaysmtp");
var httpWormALink = document.getElementById("create-program-httpworm"); var httpWormALink = document.getElementById("create-program-httpworm");
var sqlInjectALink = document.getElementById("create-program-sqlinject"); var sqlInjectALink = document.getElementById("create-program-sqlinject");
portHackALink.addEventListener("click", function() { var deepscanv1ALink = document.getElementById("create-program-deepscanv1");
Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerQuarterHour, 1); var deepscanv2ALink = document.getElementById("create-program-deepscanv2");
nukeALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerFiveMinutes, 1);
return false;
}); });
bruteSshALink.addEventListener("click", function() { bruteSshALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.BruteSSHProgram, CONSTANTS.MillisecondsPerQuarterHour, 50); Player.startCreateProgramWork(Programs.BruteSSHProgram, CONSTANTS.MillisecondsPerFiveMinutes * 2, 50);
return false;
}); });
ftpCrackALink.addEventListener("click", function() { ftpCrackALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.FTPCrackProgram, CONSTANTS.MillisecondsPerHalfHour, 100); Player.startCreateProgramWork(Programs.FTPCrackProgram, CONSTANTS.MillisecondsPerHalfHour, 100);
return false;
}); });
relaySmtpALink.addEventListener("click", function() { relaySmtpALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.RelaySMTPProgram. CONSTANTS.MillisecondsPer2Hours, 250); Player.startCreateProgramWork(Programs.RelaySMTPProgram. CONSTANTS.MillisecondsPer2Hours, 250);
return false;
}); });
httpWormALink.addEventListener("click", function() { httpWormALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.HTTPWormProgram, CONSTANTS.MillisecondsPer4Hours, 500); Player.startCreateProgramWork(Programs.HTTPWormProgram, CONSTANTS.MillisecondsPer4Hours, 500);
return false;
}); });
sqlInjectALink.addEventListener("click", function() { sqlInjectALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.SQLInjectProgram, CONSTANTS.MillisecondsPer8Hours, 750); Player.startCreateProgramWork(Programs.SQLInjectProgram, CONSTANTS.MillisecondsPer8Hours, 750);
return false;
});
deepscanv1ALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.DeepscanV1, CONSTANTS.MillisecondsPerQuarterHour, 75);
return false;
});
deepscanv2ALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.DeepscanV2, CONSTANTS.MillisecondsPer2Hours, 400);
return false;
}); });
//Message at the top of terminal //Message at the top of terminal
@ -1063,6 +1086,7 @@ var Engine = {
//DEBUG //DEBUG
document.getElementById("debug-delete-scripts-link").addEventListener("click", function() { document.getElementById("debug-delete-scripts-link").addEventListener("click", function() {
console.log("Deleting running scripts on home computer");
Player.getHomeComputer().runningScripts = []; Player.getHomeComputer().runningScripts = [];
return false; return false;
}); });

@ -1,7 +1,17 @@
/* Pop up Dialog Box */ /* Pop up Dialog Box */
//Close dialog box when clicking outside
$(document).click(function(event) {
if (dialogBoxOpened) {
if ( $(event.target).closest(".dialog-box").get(0) == null ) {
dialogBoxClose();
}
}
});
var dialogBoxOpened = false;
function dialogBoxInit() { function dialogBoxInit() {
var closeButton = document.getElementById("dialog-box-close-button"); var closeButton = document.getElementById("dialog-box-close-button");
var dialogBox = document.getElementById("dialog-box-container");
//Close Dialog box //Close Dialog box
closeButton.addEventListener("click", function() { closeButton.addEventListener("click", function() {
@ -13,6 +23,7 @@ function dialogBoxInit() {
document.addEventListener("DOMContentLoaded", dialogBoxInit, false); document.addEventListener("DOMContentLoaded", dialogBoxInit, false);
dialogBoxClose = function() { dialogBoxClose = function() {
dialogBoxOpened = false;
var dialogBox = document.getElementById("dialog-box-container"); var dialogBox = document.getElementById("dialog-box-container");
dialogBox.style.display = "none"; dialogBox.style.display = "none";
} }
@ -20,6 +31,10 @@ dialogBoxClose = function() {
dialogBoxOpen = function() { dialogBoxOpen = function() {
var dialogBox = document.getElementById("dialog-box-container"); var dialogBox = document.getElementById("dialog-box-container");
dialogBox.style.display = "block"; dialogBox.style.display = "block";
setTimeout(function() {
dialogBoxOpened = true;
}, 500);
} }
dialogBoxSetText = function(txt1, txt2="", txt3="", txt4="") { dialogBoxSetText = function(txt1, txt2="", txt3="", txt4="") {

43
utils/GameOptions.js Normal file

@ -0,0 +1,43 @@
/* GameOptions.js */
//Close box when clicking outside
$(document).click(function(event) {
if (gameOptionsOpened) {
if ( $(event.target).closest(".game-options-box").get(0) == null ) {
gameOptionsBoxClose();
}
}
});
var gameOptionsOpened = false;
function gameOptionsBoxInit() {
//Menu link button
document.getElementById("options-menu-link").addEventListener("click", function() {
gameOptionsBoxOpen();
return false;
});
//Close button
var closeButton = document.getElementById("game-options-close-button");
closeButton.addEventListener("click", function() {
gameOptionsBoxClose();
return false;
});
};
document.addEventListener("DOMContentLoaded", gameOptionsBoxInit, false);
gameOptionsBoxClose = function() {
gameOptionsOpened = false;
var box = document.getElementById("game-options-container");
box.style.display = "none";
}
gameOptionsBoxOpen = function() {
var box = document.getElementById("game-options-container");
box.style.display = "block";
setTimeout(function() {
gameOptionsOpened = true;
}, 500);
}

@ -27,13 +27,10 @@ travelBoxSetText = function(txt) {
} }
travelBoxCreate = function(destCityName, cost) { travelBoxCreate = function(destCityName, cost) {
travelBoxSetText("Would you like to travel to " + destCityName + "? The trip will cost $" + cost + "."); travelBoxSetText("Would you like to travel to " + destCityName + "? The trip will cost $" + formatNumber(cost, 2) + ".");
//Clear old event listeners from Confirm button //Clear old event listeners from Confirm button
var newConfirmButton = clearEventListeners("travel-box-confirm"); var newConfirmButton = clearEventListeners("travel-box-confirm");
//var confirmButton = document.getElementById("travel-box-confirm");
//var newConfirmButton = confirmButton.cloneNode(true);
//confirmButton.parentNode.replaceChild(newConfirmButton, confirmButton);
newConfirmButton.addEventListener("click", function() { newConfirmButton.addEventListener("click", function() {
travelBoxClose(); travelBoxClose();
travelToCity(destCityName, cost); travelToCity(destCityName, cost);