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

@ -4,7 +4,7 @@
#dialog-box-container {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
z-index: 2; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
@ -15,6 +15,7 @@
}
#dialog-box-content {
z-index: 2;
background-color: black;
margin: 20% auto; /* 20% from the top and centered */
padding: 10px;
@ -285,7 +286,7 @@
color: #66ff33;
}
#trave-l-box-text {
#travel-box-text {
margin: 8px;
}
@ -312,4 +313,52 @@
color: white;
text-decoration: none;
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 */
right: 0;
top: 0;
height: 150px; /* Full height */
height: 175px; /* Full height */
/*margin: 50% auto;*/
padding: 5px;
border: 2px solid #66ff33;
@ -257,3 +257,22 @@ tr:focus {
color: white;
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-left: 10px;
height: 100%;
width: 99%;
}
#work-in-progress-text {
color: #66ff33;
width: 70%;
}
#work-in-progress-cancel-button {

@ -24,6 +24,7 @@
<script src="utils/PurchaseAugmentationBox.js"></script>
<script src="utils/TravelBox.js"></script>
<script src="utils/PurchaseRamForHomeBox.js"></script>
<script src="utils/GameOptions.js"></script>
<!-- Netscript -->
<script src="src/NetscriptWorker.js"></script>
@ -105,19 +106,10 @@
<li class="tutorial-tab">
<a href="#" id="tutorial-menu-link"> Tutorial </a>
</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">
<a href="#" id="debug-delete-scripts-link"> (DEBUG) Delete Active Scripts </a>
<li class="options-tab">
<a id="options-menu-link"> Options </a>
</li>
</ul>
</div>
@ -143,17 +135,19 @@
<!-- Script editor -->
<div id="script-editor-container">
<div>
<p id="script-editor-filename-tag"> Script name: </p>
<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 id="script-editor-wrapper">
<div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"> </input>
</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>
<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>
</div>
@ -418,16 +412,22 @@
relaySMTP.exe
<span class="tooltiptext"> This program opens SMTP ports by redirecting data </span>
</a>
<a class="create-program-a-link-button tooltip" id="create-program-httpworm" href="#">
HTTPWorm.exe
<span class="tooltiptext"> This virus opens up HTTP ports </span>
</a>
<a class="create-program-a-link-button tooltip" id="create-program-sqlinject" href="#">
SQLInject.exe
<span class="tooltiptext"> This virus opens SQL ports</span>
</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>
</div>
@ -633,7 +633,7 @@
<!-- Dialog Box, displays status text only -->
<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>
<p id="dialog-box-text-1" class="dialog-box-text"> </p>
<br>
@ -731,6 +731,7 @@
<div id="character-overview-wrapper">
<div id="character-overview-container">
<p id="character-overview-text"> </p>
<span id="character-overview-save-button"> Save Game </span>
</div>
</div>
@ -739,5 +740,17 @@
<p id="status-text">Test </p>
</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>
</html>

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

@ -1,5 +1,5 @@
CONSTANTS = {
Version: "0.15",
Version: "0.16",
//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
@ -15,14 +15,14 @@ CONSTANTS = {
BaseCostFor1GBOfRamHacknetNode: 30000,
BaseCostForHacknetNode: 1000,
BaseCostForHacknetNodeCore: 400000,
BaseCostForHacknetNodeCore: 500000,
/* Hacknet Node constants */
HacknetNodeMoneyGainPerLevel: 1.25,
HacknetNodeMoneyGainPerLevel: 1.75,
HacknetNodePurchaseNextMult: 1.33, //Multiplier when purchasing an additional hacknet node
HacknetNodeUpgradeLevelMult: 1.04, //Multiplier for cost when upgrading level
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,
HacknetNodeMaxRam: 64,
@ -52,8 +52,11 @@ CONSTANTS = {
ScriptGetHackingLevelRamCost: 0.1,
ScriptGetServerMoneyRamCost: 0.1,
ScriptOperatorRamCost: 0.01,
ScriptPurchaseHacknetRamCost: 1.0,
ScriptUpgradeHacknetRamCost: 1.0,
ScriptPurchaseHacknetRamCost: 1.5,
ScriptHacknetNodesRamCost: 1.0, //Base cost for accessing hacknet nodes array
ScriptHNUpgLevelRamCost: 0.4,
ScriptHNUpgRamRamCost: 0.6,
ScriptHNUpgCoreRamCost: 0.8,
//Server growth rate
ServerGrowthRate: 1.00075,
@ -88,6 +91,9 @@ CONSTANTS = {
MillisecondsPerQuarterHour: 900000,
GameCyclesPerQuarterHour: 900000 / 200,
MillisecondsPerFiveMinutes: 300000,
GameCyclesPerFiveMinutes: 300000 / 200,
FactionWorkHacking: "Faction Hacking Work",
FactionWorkField: "Faction Field Work",
FactionWorkSecurity: "Faction Security Work",
@ -147,7 +153,7 @@ CONSTANTS = {
"rm Delete a script/program from the machine. (WARNING: Permanent)<br>" +
"run [script/program] Execute a program or a script<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>" +
"tail [script] Display script logs (logs contain details about active scripts)<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>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>" +
"<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 " +
"a new hacknet node then the function will return an empty string. Does NOT work offline<br><br>" +
"<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. " +
"If the Hacknet Node is successfully upgraded the function will return true. It will return false otherwise. Does NOT work offline. Example: <br>" +
"node = purchaseHacknetNode();<br>" +
"if (node != '') {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;i = 0;<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;while(i < 10) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (upgradeHacknetNode(node)) {i = i + 1;}<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;}; <br>" +
"<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 " +
"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 " +
"a new Hacknet Node then the function will return false. Does NOT work offline<br><br>" +
"<u><h1>Hacknet Nodes API</h1></u><br>" +
"Netscript provides the following API for accessing and upgrading your Hacknet Nodes through scripts. This API does NOT work offline.<br><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 " +
"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 " +
"will have the same 'hacknet-node-0' and can be accessed with hacknetnodes[0]. The fourth Hacknet Node you purchase will have the name " +
"'hacknet-node-3' and can be accessed with hacknetnodes[3]. <br><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>" +
"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>" +
"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>" +

@ -1,11 +1,13 @@
/* Create programs */
Programs = {
NukeProgram: "NUKE.exe",
BruteSSHProgram: "BruteSSH.exe",
FTPCrackProgram: "FTPCrack.exe",
RelaySMTPProgram: "relaySMTP.exe",
HTTPWormProgram: "HTTPWorm.exe",
SQLInjectProgram: "SQLInject.exe",
NukeProgram: "NUKE.exe",
BruteSSHProgram: "BruteSSH.exe",
FTPCrackProgram: "FTPCrack.exe",
RelaySMTPProgram: "relaySMTP.exe",
HTTPWormProgram: "HTTPWorm.exe",
SQLInjectProgram: "SQLInject.exe",
DeepscanV1: "DeepscanV1.exe",
DeepscanV2: "DeepscanV2.exe",
}
//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 httpWormALink = document.getElementById("create-program-httpworm");
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";
bruteSshALink.style.display = "none";
@ -24,41 +28,45 @@ function displayCreateProgramContent() {
relaySmtpALink.style.display = "none";
httpWormALink.style.display = "none";
sqlInjectALink.style.display = "none";
deepscanv1ALink.style.display = "none";
deepscanv2ALink.style.display = "none";
//NUKE.exe (in case you delete it lol)
if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) {
nukeALink.style.display = "inline-block";
}
//BruteSSH
if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 &&
Player.hacking_skill >= 50) {
bruteSshALink.style.display = "inline-block";
}
//FTPCrack
if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 &&
Player.hacking_skill >= 100) {
ftpCrackALink.style.display = "inline-block";
}
//relaySMTP
if (Player.getHomeComputer().programs.indexOf(Programs.RelaySMTPProgram) == -1 &&
Player.hacking_skill >= 250) {
relaySmtpALink.style.display = "inline-block";
}
//HTTPWorm
if (Player.getHomeComputer().programs.indexOf(Programs.HTTPWormProgram) == -1 &&
Player.hacking_skill >= 500) {
httpWormALink.style.display = "inline-block";
}
//SQLInject
if (Player.getHomeComputer().programs.indexOf(Programs.SQLInjectProgram) == -1 &&
Player.hacking_skill >= 750) {
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
@ -99,5 +107,15 @@ function getNumAvailableCreateProgram() {
Player.hacking_skill >= 750) {
++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;
}

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

@ -50,7 +50,7 @@ HacknetNode.prototype.updateMoneyGainRate = function() {
this.moneyGainRatePerSecond = (this.level * gainPerLevel) *
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)) {
this.moneyGainRatePerSecond = 0;
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) {
var cost = this.calculateLevelUpgradeCost(levels);
if (isNaN(cost)) {throw new Error("Cost is NaN"); return;}
if (cost > Player.money) {return;}
if (isNaN(cost)) {return false;}
if (cost > Player.money) {return false;}
Player.loseMoney(cost);
if (this.level + levels >= CONSTANTS.HacknetNodeMaxLevel) {
this.level = CONSTANTS.HacknetNodeMaxLevel;
return;
return false;
}
this.level += levels;
this.updateMoneyGainRate();
return true;
}
HacknetNode.prototype.calculateRamUpgradeCost = function() {
@ -96,12 +97,13 @@ HacknetNode.prototype.calculateRamUpgradeCost = function() {
HacknetNode.prototype.purchaseRamUpgrade = function() {
var cost = this.calculateRamUpgradeCost();
if (isNaN(cost)) {throw new Error("Cost is NaN"); return;}
if (cost > Player.money) {return;}
if (isNaN(cost)) {return false;}
if (cost > Player.money) {return false;}
Player.loseMoney(cost);
if (this.ram >= CONSTANTS.HacknetNodeMaxRam) {return;}
if (this.ram >= CONSTANTS.HacknetNodeMaxRam) {return false;}
this.ram *= 2; //Ram is always doubled
this.updateMoneyGainRate();
return true;
}
HacknetNode.prototype.calculateCoreUpgradeCost = function() {
@ -112,12 +114,13 @@ HacknetNode.prototype.calculateCoreUpgradeCost = function() {
HacknetNode.prototype.purchaseCoreUpgrade = function() {
var cost = this.calculateCoreUpgradeCost();
if (isNaN(cost)) {throw new Error("Cost is NaN"); return;}
if (cost > Player.money) {return;}
if (isNaN(cost)) {return false;}
if (cost > Player.money) {return false;}
Player.loseMoney(cost);
if (this.numCores >= CONSTANTS.HacknetNodeMaxCores) {return;}
if (this.numCores >= CONSTANTS.HacknetNodeMaxCores) {return false;}
++this.numCores;
this.updateMoneyGainRate();
return true;
}
/* Saving and loading HackNets */

@ -8,6 +8,8 @@ iTutorialSteps = {
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",
@ -155,13 +157,29 @@ function iTutorialEvaluateStep() {
"the 'scan' command. ");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalConnect:
case iTutorialSteps.TerminalScanAnalyze1:
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. <br><br> " +
"To connect to a machine, use the 'connect [ip/hostname]' command. You can type in " +
"current machine. A server is identified by either its IP or its hostname. <br><br> " +
"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>" +
"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
break;
case iTutorialSteps.TerminalAnalyze:
@ -228,7 +246,7 @@ function iTutorialEvaluateStep() {
"}<br><br> " +
"For anyone with basic programming experience, this code should be straightforward. " +
"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)
break;
case iTutorialSteps.TerminalFree:
@ -406,6 +424,14 @@ function iTutorialNextStep() {
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;

@ -23,6 +23,17 @@ function evaluate(exp, workerScript) {
case "var":
return new Promise(function(resolve, reject) {
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 {
resolve(env.get(exp.value));
} catch (e) {
@ -371,14 +382,17 @@ function evaluate(exp, workerScript) {
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) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
server.moneyAvailable += 1; //It can be grown even if it has no money
var growthPercentage = processSingleServerGrowth(server, 450);
resolve(growthPercentage);
}, 120 * 1000); //grow() takes flat 2 minutes right now
}, growTime);
});
p.then(function(growthPercentage) {
@ -744,7 +758,8 @@ function evaluate(exp, workerScript) {
}
if (cost > Player.money) {
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
@ -755,63 +770,17 @@ function evaluate(exp, workerScript) {
Player.loseMoney(cost);
Player.hacknetNodes.push(node);
displayHacknetNodesContent();
workerScript.scriptRef.log("Purchased new Hacknet Node with name: " + name);
resolve(name);
resolve(numOwned);
}, 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);
});
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Unrecognized function call");
break;
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) {
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 num(x) {
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
function scriptCalculateHackingChance(server) {
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 chance = skillChance * difficultyMult;
var chance = skillChance * difficultyMult * Player.hacking_chance_mult;
if (chance < 0) {return 0;}
else {return chance;}
}
@ -1126,8 +1202,16 @@ function scriptCalculateExpGain(server) {
function scriptCalculatePercentMoneyHacked(server) {
var difficultyMult = (100 - server.hackDifficulty) / 100;
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 > 1) {return 1;}
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,
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() {
return {
@ -211,13 +251,16 @@ function Parser(input) {
return exp;
}
if (is_punc("{")) return parse_prog();
if (is_punc("[")) return parse_arrayindex();
if (is_kw("if")) return parse_if();
if (is_kw("for")) return parse_for();
if (is_kw("while")) return parse_while();
//if (is_kw("hacknetnodes")) return parse_hacknetnodes();
//Note, let for loops be function calls (call node types)
if (is_kw("true") || is_kw("false")) return parse_bool();
var tok = input.next();
if (tok.type == "var" && tok.value == "hacknetnodes") return parse_hacknetnodes();
if (tok.type == "var" || tok.type == "num" || tok.type == "str")
return tok;
unexpected();

@ -6,7 +6,7 @@
* {type: "punc", value: "(" } // punctuation: parens, comma, semicolon etc.
* {type: "num", value: 5 } // numbers (including floats)
* {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: "op", value: "!=" } // operator characters
* {type: "bool", value: "true" } // Booleans
@ -46,7 +46,7 @@ function Tokenizer(input) {
}
function is_punc(ch) {
return ",;(){}[]".indexOf(ch) >= 0;
return ",;(){}[].".indexOf(ch) >= 0;
}
function is_whitespace(ch) {

@ -176,7 +176,7 @@ function PlayerObject() {
PlayerObject.prototype.init = function() {
/* Initialize Player's home computer */
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.currentServer = t_homeComp.ip;
AddToAllServers(t_homeComp);
@ -243,7 +243,7 @@ PlayerObject.prototype.calculateHackingTime = function() {
PlayerObject.prototype.calculatePercentMoneyHacked = function() {
var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100;
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);
if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;}

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

@ -462,7 +462,7 @@ initForeignServers = function() {
AddToAllServers(PhantasyServer);
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.setPortProperties(1);
AddToAllServers(MaxHardwareServer);
@ -481,7 +481,7 @@ initForeignServers = function() {
AddToAllServers(CrushFitnessGymServer);
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.setPortProperties(1);
AddToAllServers(IronGymServer);

@ -27,15 +27,6 @@ var postNetburnerText = function() {
post("Bitburner v" + CONSTANTS.Version);
}
/*
$(document).keyup(function(event) {
//Enter
if (event.keyCode == 13) {
}
});
*/
//Defines key commands in terminal
$(document).keydown(function(event) {
//Terminal
@ -396,10 +387,23 @@ var Terminal = {
iTutorialNextStep();
} else {post("Bad command. Please follow the tutorial");}
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:
if (commandArray.length == 2) {
if ((commandArray[0] == "connect" || commandArray[0] == "telnet") &&
if ((commandArray[0] == "connect") &&
(commandArray[1] == "foodnstuff" || commandArray[1] == foodnstuffServ.ip)) {
Player.getCurrentServer().isConnectedTo = false;
Player.currentServer = foodnstuffServ.ip;
@ -733,7 +737,29 @@ var Terminal = {
Terminal.executeScanCommand(commandArray);
break;
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;
case "scp":
//TODO
@ -838,20 +864,39 @@ var Terminal = {
}
},
executeScanAnalyzeCommand: function(commandArray) {
if (commandArray.length != 1) {
post("Incorrect usage of scan-analyze command. usage: scan-analyze"); return;
}
executeScanAnalyzeCommand: function(depth=1) {
//We'll use the AllServersToMoneyMap as a visited() array
//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();
for (var i = 0; i < currServ.serversOnNetwork.length; ++i) {
var serv = currServ.getServerOnNetwork(i);
if (serv == null) {continue;}
post("<strong>" + serv.hostname + "</strong>");
var c = "N";
if (serv.hasAdminRights) {c = "Y";}
post("--Root Access: " + c);
post("--Required hacking skill: " + serv.requiredHackingSkill);
post("--Number open ports required to NUKE: " + serv.numOpenPortsRequired);
stack.push(currServ);
while(stack.length != 0) {
var s = stack.pop();
var d = depthQueue.pop();
if (visited[s.ip] || d > depth) {
continue;
} else {
visited[s.ip] = 1;
}
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(" ");
}
},

@ -988,6 +988,12 @@ var Engine = {
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
var netscriptDocButton = document.getElementById("script-editor-netscript-doc-button");
@ -999,29 +1005,46 @@ var Engine = {
});
//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 ftpCrackALink = document.getElementById("create-program-ftpcrack");
var relaySmtpALink = document.getElementById("create-program-relaysmtp");
var httpWormALink = document.getElementById("create-program-httpworm");
var sqlInjectALink = document.getElementById("create-program-sqlinject");
portHackALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerQuarterHour, 1);
var deepscanv1ALink = document.getElementById("create-program-deepscanv1");
var deepscanv2ALink = document.getElementById("create-program-deepscanv2");
nukeALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.NukeProgram, CONSTANTS.MillisecondsPerFiveMinutes, 1);
return false;
});
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() {
Player.startCreateProgramWork(Programs.FTPCrackProgram, CONSTANTS.MillisecondsPerHalfHour, 100);
return false;
});
relaySmtpALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.RelaySMTPProgram. CONSTANTS.MillisecondsPer2Hours, 250);
return false;
});
httpWormALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.HTTPWormProgram, CONSTANTS.MillisecondsPer4Hours, 500);
return false;
});
sqlInjectALink.addEventListener("click", function() {
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
@ -1063,6 +1086,7 @@ var Engine = {
//DEBUG
document.getElementById("debug-delete-scripts-link").addEventListener("click", function() {
console.log("Deleting running scripts on home computer");
Player.getHomeComputer().runningScripts = [];
return false;
});

@ -1,7 +1,17 @@
/* 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() {
var closeButton = document.getElementById("dialog-box-close-button");
var dialogBox = document.getElementById("dialog-box-container");
//Close Dialog box
closeButton.addEventListener("click", function() {
@ -13,6 +23,7 @@ function dialogBoxInit() {
document.addEventListener("DOMContentLoaded", dialogBoxInit, false);
dialogBoxClose = function() {
dialogBoxOpened = false;
var dialogBox = document.getElementById("dialog-box-container");
dialogBox.style.display = "none";
}
@ -20,6 +31,10 @@ dialogBoxClose = function() {
dialogBoxOpen = function() {
var dialogBox = document.getElementById("dialog-box-container");
dialogBox.style.display = "block";
setTimeout(function() {
dialogBoxOpened = true;
}, 500);
}
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) {
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
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() {
travelBoxClose();
travelToCity(destCityName, cost);