Merge pull request #3 from danielyxie/dev

Dev
This commit is contained in:
danielyxie 2017-05-13 02:16:25 -05:00 committed by GitHub
commit 72add5b7bd
38 changed files with 3850 additions and 1342 deletions

@ -2,62 +2,22 @@
Netburner Idle Game
TESTING TODO:
hack() and sleep() in a script
hack() seems to be working
Sleep() seems to be working
Creating the foreign server network doesn't seem to be working
--Seems to be fixed
Script RAM Usage and corresponding terminal commands
If a server has no more money available it cannot be hacked anymore
Should work automatically...because your money gained percentage will be multiplied by 0
When the game is loaded re-load all of the scripts in runningScripts
- Seems to be working
Update skill level on cycle
If a script has bad syntax...it fucks everything up when you try to run it so fix that
Try catch for script?
Check that killing scripts still works fine (TESTED - LOoks to work fine)
Check that if script has bad syntax it wont run at all and everthing works normally (Seems to work fine)
Check if script throws during runtime it shuts down correctly (seems to work fine)
Adjust leveling formula. Goes up way too high at first
http://gamedev.stackexchange.com/questions/55151/rpg-logarithmic-leveling-formula
- might be too slow now?
Scripts tab that shows script stats
Seems to work, at least the basics (for online production)
Script offline progress
Delete a script from Active scripts when the WorkerScript is deleted
Seems to work
Server growth
Implemented but it might need to be balance/formula readjusted
ctrl+C functionality for all running command like hack(), analyze(), and tail
Implemented for hack() and analyze(). Seems to work
Saving/Loading factions
No errors thrown when saving/loading game at the start
Scroll all the way down when something is post()ed
Purchasing Servers
Work
Companies
Add possible CompanyPositions for every Company
Applying/working for companies
Factions
Change Company pages to display "apply for promotion" and other stuff when you are already employed there
Augmentations
rm command seems to work
Make it so that a script cannot be edited if it is running
+ Traveling
@ -67,6 +27,8 @@ TESTING TODO:
Seems to work fine
Gyms - Later..don't need for MVP
Tasks TODO:
Adding augmentations for Silhouette fac
@ -76,18 +38,13 @@ Tasks TODO:
New server hostname in Purchase Server Pop-up Box needs limits..don't think the ones set in HTML work
Tutorial and help - INTERACTIVE TUTORIAL
Secret Servers
Hack time formula needs rebalancing I think, so does hack exp formula
Create new menu page for purchased servers
Gyms - Later..don't need for MVP
Update CONSTANTS.HelpText
Account for Max possible int when gaining exp (it will overflow)
Text in script editor that says ("ctrl + x" to save and quit)
OPTIMIZATION
https://gamealchemist.wordpress.com/2013/05/01/lets-get-those-javascript-arrays-to-work-fast/

@ -0,0 +1,53 @@
/* interactivetutorial.css */
#interactive-tutorial-container {
display: none;
position: fixed; /* Stay in place */
right: 0;
top: 0;
height: 100%; /* Full height */
margin: 20% auto;
padding: 10px;
border: 5px solid #FFFFFF;
width: 35%;
overflow: auto; /* Enable scroll if needed */
background-color: #444; /* Fallback color */
color: white;
}
#interactive-tutorial-text {
padding: 4px;
margin: 4px;
color: white;
background-color: #444;
}
#interactive-tutorial-exit,
#interactive-tutorial-next {
color: #aaa;
font-size: 20px;
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;
}
#interactive-tutorial-exit {
float: left;
}
#interactive-tutorial-next {
float: right;
}
#interactive-tutorial-exit:hover,
#interactive-tutorial-exit:focus,
#interactive-tutorial-next:hover,
#interactive-tutorial-next:focus {
color: white;
text-decoration: none;
cursor: pointer;
}

@ -9,14 +9,10 @@
padding-left: 10px;
margin-left: 10%;
width: 99%;
overflow: auto;
overflow-y: scroll;
}
#character-info {
overflow-y: scroll;
}
/* Script Editor */
/* This temp element is used for auto adjusting filename field */
.tmp-element {
@ -104,6 +100,12 @@
overflow-y: scroll;
}
#active-scripts-text {
width: 80%;
margin: 6px;
padding: 4px;
}
.active-scripts-list > li {
margin: 6px;
width: 80%;
@ -183,6 +185,12 @@
width: 99%;
}
#world-city-name,
#world-city-desc {
padding: 4px;
margin: 4px;
}
/* Create program */
#create-program-container {
position: fixed;
@ -193,15 +201,17 @@
width: 99%;
}
#create-program-page-text {
width: 80%;
}
.create-program-a-link-button {
text-decoration: none;
background-color: #555;
color: #FFFFFF;
padding: 4px 4px 4px 4px;
border-top: 1px solid #333333;
border-right: 1px solid #333333;
border-bottom: 1px solid #333333;
border-left: 1px solid #333333;
padding: 4px;
border: 1px solid #333333;
width: 50%;
}
.create-program-a-link-button-inactive {
@ -242,16 +252,28 @@
margin: 6px;
}
#faction-hack-button-div, #faction-hack-text-div {
display:inline-block;
#faction-hack-div,
#faction-fieldwork-div,
#faction-securitywork-div {
overflow: hidden;
height: 100%;
}
#faction-fieldwork-button-div, #faction-fieldwork-text-div {
display:inline-block;
#faction-hack-div-wrapper,
#faction-fieldwork-div-wrapper,
#faction-securitywork-div-wrapper {
float: left;
border: 2px solid #333;
padding: 14px 6px 4px 6px;
margin: 6px;
}
#faction-securitywork-button-div, #faction-securitywork-text-div {
display:inline-block;
#faction-hack-button {
margin: 8px;
}
div.faction-clear {
clear: both;
}
#faction-container p {
@ -293,17 +315,20 @@
margin-left: 10%;
width: 99%;
color: #66ff33;
overflow-y: scroll;
}
#augmentations-list > li {
margin: 6px;
#augmentations-list li {
width: 80%;
background-color: #333;
}
#augmentations-list > li h2{
#augmentations-list h2,
#augmentations-list p {
margin: 4px;
color: #66ff33;
padding-top: 10px;
padding-left: 10px;
padding: 8px;
width: 80%;
background-color: #333;
text-decoration: none;
}
@ -314,13 +339,19 @@
/* Tutorial */
#tutorial-container {
color: #66ff33;
position: fixed;
height: 100%;
padding-top: 10px;
padding-left: 10px;
height: 100%;
margin-left: 10%;
width: 85%;
width: 99%;
overflow: auto;
overflow-y: scroll;
}
#tutorial-text {
width: 80%;
margin: 10px;
}
/* Location */

@ -16,7 +16,7 @@
#dialog-box-content {
background-color: black;
margin: 20% auto; /* 15% from the top and centered */
margin: 20% auto; /* 20% from the top and centered */
padding: 10px;
border: 5px solid #FFFFFF;
width: 40%; /* Could be more or less, depending on screen size */

@ -90,10 +90,8 @@ tr:focus {
color: #FFFFFF;
padding: 6px;
margin: 6px;
border-top: 1px solid #333333;
border-right: 1px solid #333333;
border-bottom: 1px solid #333333;
border-left: 1px solid #333333;
border: 1px solid #333333;
width: 50%;
}
.a-link-button:hover {
@ -113,5 +111,55 @@ tr:focus {
border-left: 1px solid #333333;
pointer-events: none;
cursor: default;
width: 50%;
}
/* Notification icon (for create program right now only) */
.create-program-tab {
position:relative;
}
#create-program-notification {
font-size: 10px;
position: absolute; /* Position the badge within the relatively positioned button */
top: 0;
right: 0;
}
.notification-on {
background-color: #fa3e3e;
color: white;
border-radius: 2px;
padding: 1px 3px;
}
.notification-off {
background-color: #333;
color: #333;
border-radius: 0px;
padding: 0px;
}
/* Tool tips (when hovering over an element */
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 300px;
background-color: black;
border: 2px solid white;
color: white;
text-align: center;
padding: 4px;
position: absolute;
z-index: 1;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}

@ -12,7 +12,7 @@
#work-in-progress-cancel-button {
color: #aaa;
float: right;
float: left;
font-size: 20px;
font-weight: bold;
-webkit-border-radius: 12px;

@ -8,9 +8,9 @@
<link rel="stylesheet" type="text/css" href="css/menupages.css" />
<link rel="stylesheet" type="text/css" href="css/workinprogress.css" />
<link rel="stylesheet" type="text/css" href="css/popupboxes.css" />
<link rel="stylesheet" type="text/css" href="css/interactivetutorial.css" />
<!-- We'll add in the jQuery library here - direct from
the Google CDN (Content Delivery Network). -->
<!--jQuery library-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<!-- Utils -->
@ -53,6 +53,8 @@
<script src="src/Crimes.js"></script>
<script src="src/Prestige.js"></script>
<script src="src/SaveObject.js"></script>
<script src="src/DarkWeb.js"></script>
<script src="src/InteractiveTutorial.js"></script>
<script src="src/engine.js"></script>
@ -88,6 +90,7 @@
<li class="create-program-tab">
<a href="#" id="create-program-menu-link"> Create Program </a>
<span id="create-program-notification" class="notification-off"> </span>
</li>
<li class="factions-tab">
@ -127,8 +130,10 @@
<!-- Character Info page -->
<div id="character-container">
<div id="character-content">
<p id="character-info"> </p>
</div>
</div>
<!-- Script editor -->
<div id="script-editor-container">
@ -145,6 +150,8 @@
<!-- Active scripts info page -->
<div id="active-scripts-container">
<p id="active-scripts-text"> This page displays a list of all scripts that are currently running across every machine. It also gives
information about their production </p>
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;">
</ul>
</div>
@ -172,6 +179,8 @@
<!-- World -->
<div id="world-container" class="world-container">
<h2 id="world-city-name"> </h2>
<p id="world-city-desc"> </p>
<ul id="aevum-locations-list">
<li id="aevum-travelagency-li">
<a href="#" id="aevum-travelagency" class="a-link-button"> Travel Agency </a>
@ -367,31 +376,40 @@
<!-- Create a program(executable) -->
<div id="create-program-container">
<p id="create-program-page-text">
This page displays any programs that you are able to create. Writing the code for a program takes time, which
can vary based on how complex the program is. Once you start working on a program you must see it all the way
through. If you cancel before the program is complete you will lose all your progress and have to start all over
if you want to code it again.
</p>
<ul id="create-program-list">
<a class="create-program-a-link-button" id="create-program-porthack" href="#">
PortHack.exe
<a class="create-program-a-link-button tooltip" id="create-program-nuke" href="#">
NUKE.exe
<span class="tooltiptext"> This virus is used to gain root access to a machine if enough ports are opened. </span>
</a>
<a class="create-program-a-link-button" id="create-program-brutessh" href="#">
<a class="create-program-a-link-button tooltip" id="create-program-brutessh" href="#">
BruteSSH.exe
<span class="tooltiptext"> This program executes a brute force attack that opens SSH ports </span>
</a>
<a class="create-program-a-link-button" id="create-program-ftpcrack" href="#">
<a class="create-program-a-link-button tooltip" id="create-program-ftpcrack" href="#">
FTPCrack.exe
<span class="tooltiptext"> This program cracks open FTP ports</span>
</a>
<a class="create-program-a-link-button" id="create-program-relaysmtp" href="#">
<a class="create-program-a-link-button tooltip" id="create-program-relaysmtp" href="#">
relaySMTP.exe
<span class="tooltiptext"> This program opens SMTP ports by redirecting data </span>
</a>
<a class="create-program-a-link-button" id="create-program-httpworm" href="#">
<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" id="create-program-sqlinject" href="#">
<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>
</ul>
</div>
@ -399,8 +417,7 @@
<div id="factions-container">
<h1> Factions </h1>
<p> Lists all factions you have joined </p>
<ul class="factions-list" id="factions-list">
</ul>
<ul class="factions-list" id="factions-list"></ul>
</div>
<!-- Single Faction info (when you select a faction from the Factions menu) -->
@ -411,48 +428,53 @@
<p id="faction-reputation"></p>
<p id="work-description-text">
Perform work/carry out assignments for your faction to help further its cause! Each
task takes a certain amount of time to complete, which is dependent on your stats. Completing
a task will earn you exp and increase your reputation with the faction. Note that you cannot
use your terminal or create scripts when you are performing a task!
Perform work/carry out assignments for your faction to help further its cause! By doing so
you will gain reputation for your faction. You will also gain reputation passively over time,
although at a very slow rate. Note that you cannot
use your terminal or create scripts when you are performing a task! <br><br><br><br>
</p>
<div id="faction-hack-div">
<div id="faction-hack-div-wrapper">
<a href="#" id="faction-hack-button" class="a-link-button">Hacking Contracts</a>
<p id="faction-hack-text">
Complete hacking contracts for your faction! <br>
Your effectiveness, which determines how much reputation you gain for this faction, is based on your hacking skill. <br>
Gain hacking exp.
You will gain hacking exp.
</p>
<div id="faction-hack-text-div">
</div>
<div class="faction-clear"></div>
</div>
<div id="faction-fieldwork-div">
<div id="faction-fieldwork-div-wrapper">
<a href="#" id="faction-fieldwork-button" class="a-link-button">Field Work</a>
<div id="faction-fieldwork-text-div">
<p id="faction-fieldwork-text">
Carry out field missions for your faction. <br>
Your effectiveness, which determines how much reputation you gain for this faction, is based on all of your stats. <br>
Gains exp for all stats.
You will gain exp for all stats.
</p>
</div>
<div class="faction-clear"></div>
</div>
<div id="faction-securitywork-div">
<div id="faction-securitywork-div-wrapper">
<a href="#" id="faction-securitywork-button" class="a-link-button">Security Work</a>
<div id="faction-securitywork-text-div">
<p id="faction-securitywork-text">
Serve in a security detail for your faction. <br>
Your effectiveness, which determines how much reputation you gain for this faction, is based on your combat stats. <br>
Gains exp for all combat stats.
You will gain exp for all combat stats.
</p>
</div>
<div class="faction-clear"></div>
</div>
<p>
<br><br><br>
As your reputation with this faction rises, you will unlock Augmentations, which you
can purchase to enhance your abilities.
<br><br>
</p>
<a href="#" id="faction-purchase-augmentations" class="a-link-button">Purchase Augmentations</a>
</div>
@ -477,9 +499,10 @@
<!-- Tutorial content -->
<div id="tutorial-container">
<a href="#" id="tutorial-getting-started-link" class="a-link-button"> Getting Started </a>
<a href="#" id="tutorial-networking-link" class="a-link-button"> Networking </a>
<a href="#" id="tutorial-networking-link" class="a-link-button"> Servers & Networking </a>
<a href="#" id="tutorial-hacking-link" class="a-link-button"> Hacking </a>
<a href="#" id="tutorial-scripts-link" class="a-link-button"> Scripts </a>
<a href="#" id="tutorial-netscript-link" class="a-link-button"> Netscript Programming Language </a>
<a href="#" id="tutorial-traveling-link" class="a-link-button"> Traveling </a>
<a href="#" id="tutorial-jobs-link" class="a-link-button"> Jobs </a>
<a href="#" id="tutorial-factions-link" class="a-link-button"> Factions </a>
@ -500,14 +523,18 @@
<!-- Jobs/Work at a company -->
<a href="#" id="location-software-job" class="a-link-button"> Apply for Software Job</a>
<a href="#" id="location-software-consultant-job" class="a-link-button"> Apply for Software Consultant Job</a>
<a href="#" id="location-it-job" class="a-link-button"> Apply for IT Job </a>
<a href="#" id="location-security-engineer-job" class="a-link-button"> Apply for Security Engineer Job</a>
<a href="#" id="location-network-engineer-job" class="a-link-button"> Apply for Network Engineer Job</a>
<a href="#" id="location-business-job" class="a-link-button"> Apply for Business Job</a>
<a href="#" id="location-business-consultant-job" class="a-link-button"> Apply for Business Consultant Job </a>
<a href="#" id="location-security-job" class="a-link-button"> Apply for Security Job</a>
<a href="#" id="location-agent-job" class="a-link-button"> Apply to be an Agent</a>
<a href="#" id="location-employee-job" class="a-link-button"> Apply to be an Employee </a>
<a href="#" id="location-parttime-employee-job" class="a-link-button"> Apply to be a Part-time Employee </a>
<a href="#" id="location-waiter-job" class="a-link-button"> Apply to be a Waiter</a>
<a href="#" id="location-parttime-waiter-job" class="a-link-button"> Apply to be a Part-time Waiter</a>
<a href="#" id="location-work" class="a-link-button"> Work </a>
@ -526,23 +553,23 @@
<a href="#" id="location-leadership-class" class="a-link-button">Take Leadership course</a>
<!-- Purchase servers -->
<a href="#" id="location-purchase-1gb" class="a-link-button"> Purchase 1GB Server - $50,000</a>
<a href="#" id="location-purchase-2gb" class="a-link-button"> Purchase 2GB Server - $100,000</a>
<a href="#" id="location-purchase-4gb" class="a-link-button"> Purchase 4GB Server - $250,000</a>
<a href="#" id="location-purchase-8gb" class="a-link-button"> Purchase 8GB Server - $1,000,000</a>
<a href="#" id="location-purchase-16gb" class="a-link-button"> Purchase 16GB Server - $4,000,000</a>
<a href="#" id="location-purchase-32gb" class="a-link-button"> Purchase 32GB Server - $10,000,000</a>
<a href="#" id="location-purchase-64gb" class="a-link-button"> Purchase 64GB Server - $20,000,000</a>
<a href="#" id="location-purchase-128gb" class="a-link-button"> Purchase 128GB Server - $50,000,000</a>
<a href="#" id="location-purchase-256gb" class="a-link-button"> Purchase 256GB Server - $100,000,000</a>
<a href="#" id="location-purchase-512gb" class="a-link-button"> Purchase 512GB Server - $250,000,000</a>
<a href="#" id="location-purchase-1tb" class="a-link-button"> Purchase 1TB Server - $750,000,000</a>
<a href="#" id="location-purchase-tor" class="a-link-button"> Purchase TOR Router - $2,000,000</a>
<a href="#" id="location-purchase-1gb" class="a-link-button"> Purchase 1GB Server - $75,000</a>
<a href="#" id="location-purchase-2gb" class="a-link-button"> Purchase 2GB Server - $150,000</a>
<a href="#" id="location-purchase-4gb" class="a-link-button"> Purchase 4GB Server - $300,000</a>
<a href="#" id="location-purchase-8gb" class="a-link-button"> Purchase 8GB Server - $600,000</a>
<a href="#" id="location-purchase-16gb" class="a-link-button"> Purchase 16GB Server - $1,200,000</a>
<a href="#" id="location-purchase-32gb" class="a-link-button"> Purchase 32GB Server - $2,400,000</a>
<a href="#" id="location-purchase-64gb" class="a-link-button"> Purchase 64GB Server - $4,800,000</a>
<a href="#" id="location-purchase-128gb" class="a-link-button"> Purchase 128GB Server - $9,600,000</a>
<a href="#" id="location-purchase-256gb" class="a-link-button"> Purchase 256GB Server - $19,200,000</a>
<a href="#" id="location-purchase-512gb" class="a-link-button"> Purchase 512GB Server - $38,400,000</a>
<a href="#" id="location-purchase-1tb" class="a-link-button"> Purchase 1TB Server - $75,000,000</a>
<a href="#" id="location-purchase-tor" class="a-link-button"> Purchase TOR Router - $100,000</a>
<a href="#" id="location-purchase-home-ram" class="a-link-button"> Purchase RAM for Home computer </a>
<!-- Travel agency -->
<p id="location-travel-agency-text">
From here, you can travel to any other city! A ticket costs $1,000,000.
From here, you can travel to any other city! A ticket costs $200,000.
</p>
<a href="#" id="location-travel-to-aevum" class="a-link-button"> Travel to Aevum </a>
<a href="#" id="location-travel-to-chongqing" class="a-link-button"> Travel to Chongqing</a>
@ -559,13 +586,15 @@
In the Slums you can commit crimes to earn money and experience. Crime attempts are not always
successful. Your chance at successfully committing a crime is determined by your stats.
</p>
<a href="#" id="location-slums-shoplift" class="a-link-button"> Shoplift </a>
<a href="#" id="location-slums-mug" class="a-link-button"> Mug someone </a>
<a href="#" id="location-slums-deal-drugs" class="a-link-button"> Deal Drugs </a>
<a href="#" id="location-slums-traffic-arms" class="a-link-button"> Traffick Illegal Arms </a>
<a href="#" id="location-slums-homicide" class="a-link-button"> Homicide </a>
<a href="#" id="location-slums-kidnap" class="a-link-button"> Kidnap and Ransom </a>
<a class="a-link-button tooltip" href="#" id="location-slums-shoplift"> Shoplift </a>
<a href="#" id="location-slums-mug" class="a-link-button tooltip"> Mug someone </a>
<a href="#" id="location-slums-deal-drugs" class="a-link-button tooltip"> Deal Drugs </a>
<a href="#" id="location-slums-traffic-arms" class="a-link-button tooltip"> Traffick Illegal Arms </a>
<a href="#" id="location-slums-homicide" class="a-link-button tooltip"> Homicide </a>
<a href="#" id="location-slums-gta" class="a-link-button tooltip"> Grand Theft Auto </a>
<a href="#" id="location-slums-kidnap" class="a-link-button tooltip"> Kidnap and Ransom </a>
<a href="#" id="location-slums-assassinate" class="a-link-button tooltip"> Assassinate </a>
<a href="#" id="location-slums-heist" class="a-link-button tooltip"> Heist </a>
</div>
<!-- Dialog Box, displays status text only -->
@ -614,15 +643,19 @@
<!-- Purchase Augmentation Pop-up Box -->
<div id="purchase-augmentation-box-container">
<div id="purchase-augmentation-box-content">
<h2 id="purchase-augmentation-box-aug-name"> </h2>
<p id="purchase-augmentation-box-aug-info"> </p>
<p id="purchase-augmentation-box-text"> </p>
<p> <br> WARNING: Purchasing an Augmentation resets most of your progress, including: <br>
<p> <br> WARNING: Purchasing an Augmentation resets most of your progress, including: <br><br>
Stats/Skill levels and Experience <br>
Money <br>
Scripts <br>
Scripts on every computer but your home computer<br>
Purchased servers <br>
Hacknet Nodes <br>
Faction/Company reputation <br><br>
Purchasing an Augmentation lets you start over with the perks and benefits granted by all
of the Augmentations you have ever purchased (purchasing an Augmentation does not reset the benefits
of Augmentations you have previously purchased).
of the Augmentations you have ever purchased. Also, you will keep any scripts and RAM upgrades
on your home computer (but you will lose all programs besides NUKE.exe).
</p>
<span id="purchase-augmentation-box-confirm"> Purchase </span>
<span id="purchase-augmentation-box-cancel"> Cancel </span>
@ -650,5 +683,12 @@
<span id="work-in-progress-cancel-button"> Cancel Work </span>
</div>
<!-- Interactive Tutorial Text Screen -->
<div id="interactive-tutorial-container">
<p id="interactive-tutorial-text"> </p>
<span id="interactive-tutorial-exit"> Exit Tutorial </span>
<span id="interactive-tutorial-next"> Next </span>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

@ -189,6 +189,26 @@ CompanyPosition.prototype.isAgentJob = function() {
return false;
}
CompanyPosition.prototype.isSoftwareConsultantJob = function() {
if (this.positionName == "Software Consultant" ||
this.positionName == "Senior Software Consultant") {return true;}
return false;
}
CompanyPosition.prototype.isBusinessConsultantJob = function() {
if (this.positionName == "Business Consultant" ||
this.positionName == "Senior Business Consultant") {return true;}
return false;
}
CompanyPosition.prototype.isPartTimeJob = function() {
if (this.isSoftwareConsultantJob() ||
this.isBusinessConsultantJob() ||
this.positionName == "Part-time Waiter" ||
this.positionName == "Part-time Employee") {return true;}
return false;
}
CompanyPosition.prototype.toJSON = function() {
return Generic_toJSON("CompanyPosition", this);
}
@ -203,46 +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, 1.2),
JuniorDev: new CompanyPosition("Junior Software Engineer", 51, 0, 0, 0, 0, 0, 9000, 6),
SeniorDev: new CompanyPosition("Senior Software Engineer", 251, 0, 0, 0, 0, 51, 36000, 15),
LeadDev: new CompanyPosition("Lead Software Developer", 401, 0, 0, 0, 0, 151, 144000, 20),
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),
//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),
//IT
ITIntern: new CompanyPosition("IT Intern", 1, 0, 0, 0, 0, 0, 0, 1),
ITAnalyst: new CompanyPosition("IT Analyst", 26, 0, 0, 0, 0, 0, 9000, 4),
ITManager: new CompanyPosition("IT Manager", 151, 0, 0, 0, 0, 51, 36000, 14),
SysAdmin: new CompanyPosition("Systems Administrator", 251, 0, 0, 0, 0, 76, 144000, 14),
SecurityEngineer: new CompanyPosition("Security Engineer", 151, 0, 0, 0, 0, 26, 36000, 12),
NetworkEngineer: new CompanyPosition("Network Engineer", 151, 0, 0, 0, 0, 26, 36000, 12),
NetworkAdministrator: new CompanyPosition("Network Administrator", 251, 0, 0, 0, 0, 76, 144000, 15),
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),
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),
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, 35),
HeadOfEngineering: new CompanyPosition("Head of Engineering", 501, 0, 0, 0, 0, 251, 576000, 40),
VicePresident: new CompanyPosition("Vice President of Technology", 601, 0, 0, 0, 0, 401, 1152000, 45),
CTO: new CompanyPosition("Chief Technology Officer", 751, 0, 0, 0, 0, 501, 4608000, 50),
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),
//Business
BusinessIntern: new CompanyPosition("Business Intern", 1, 0, 0, 0, 0, 1, 0, 1.2),
BusinessAnalyst: new CompanyPosition("Business Analyst", 6, 0, 0, 0, 0, 51, 9000, 10),
BusinessManager: new CompanyPosition("Business Manager", 51, 0, 0, 0, 0, 101, 36000, 18),
OperationsManager: new CompanyPosition("Operations Manager", 51, 0, 0, 0, 0, 201, 144000, 22),
CFO: new CompanyPosition("Chief Financial Officer", 76, 0, 0, 0, 0, 501, 576000, 50),
CEO: new CompanyPosition("Chief Executive Officer", 101, 0, 0, 0, 0, 751, 4608000, 100),
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),
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),
//Non-tech/management jobs
Waiter: new CompanyPosition("Waiter", 0, 0, 0, 0, 0, 0, 0, .75),
Employee: new CompanyPosition("Employee", 0, 0, 0, 0, 0, 0, 0, .75),
PoliceOfficer: new CompanyPosition("Police Officer", 11, 101, 101, 101, 101, 51, 9000, 5),
PoliceChief: new CompanyPosition("Police Chief", 101, 301, 301, 301, 301, 151, 36000, 12),
SecurityGuard: new CompanyPosition("Security Guard", 0, 51, 51, 51, 51, 1, 0, 4),
SecurityOfficer: new CompanyPosition("Security Officer", 26, 151, 151, 151, 151, 51, 9000, 8),
SecuritySupervisor: new CompanyPosition("Security Supervisor", 26, 251, 251, 251, 251, 101, 36000, 15),
HeadOfSecurity: new CompanyPosition("Head of Security", 51, 501, 501, 501, 501, 151, 144000, 22),
FieldAgent: new CompanyPosition("Field Agent", 101, 101, 101, 101, 101, 101, 9000, 6),
SecretAgent: new CompanyPosition("Secret Agent", 201, 251, 251, 251, 251, 36000, 15),
SpecialOperative: new CompanyPosition("Special Operative", 251, 501, 501, 501, 501, 144000, 25),
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),
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),
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),
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),
init: function() {
//Argument order: hack, str, def, dex, agi, cha
@ -256,6 +288,11 @@ CompanyPositions = {
CompanyPositions.LeadDev.setPerformanceParameters(70, 0, 0, 0, 0, 30);
CompanyPositions.LeadDev.setExperienceGains(.5, 0, 0, 0, 0, .1);
CompanyPositions.SoftwareConsultant.setPerformanceParameters(80, 0, 0, 0, 0, 20);
CompanyPositions.SoftwareConsultant.setExperienceGains(.175, 0, 0, 0, 0, .03);
CompanyPositions.SeniorSoftwareConsultant.setPerformanceParameters(75, 0, 0, 0, 0, 25);
CompanyPositions.SeniorSoftwareConsultant.setExperienceGains(.35, 0, 0, 0, 0, .06);
//Security
CompanyPositions.ITIntern.setPerformanceParameters(90, 0, 0, 0, 0, 10);
CompanyPositions.ITIntern.setExperienceGains(.05, 0, 0, 0, 0, .01);
@ -296,12 +333,21 @@ CompanyPositions = {
CompanyPositions.CEO.setPerformanceParameters(10, 0, 0, 0, 0, 90);
CompanyPositions.CEO.setExperienceGains(.1, 0, 0, 0, 0, 1.5);
CompanyPositions.BusinessConsultant.setPerformanceParameters(20, 0, 0, 0, 0, 80);
CompanyPositions.BusinessConsultant.setExperienceGains(.015, 0, 0, 0, 0, .15);
CompanyPositions.SeniorBusinessConsultant.setPerformanceParameters(15, 0, 0, 0, 0, 85);
CompanyPositions.SeniorBusinessConsultant.setExperienceGains(.015, 0, 0, 0, 0, .3);
//Non-tech/management jobs
//TODO These parameters might need to be balanced
CompanyPositions.PartTimeWaiter.setPerformanceParameters(0, 10, 0, 10, 10, 70);
CompanyPositions.PartTimeWaiter.setExperienceGains(0, .0075, .0075, .0075, .0075, .04);
CompanyPositions.PartTimeEmployee.setPerformanceParameters(0, 10, 0, 10, 10, 70);
CompanyPositions.PartTimeEmployee.setExperienceGains(0, .0075, .0075, .0075, .0075, .03);
CompanyPositions.Waiter.setPerformanceParameters(0, 10, 0, 10, 10, 70);
CompanyPositions.Waiter.setExperienceGains(0, .01, .01, .01, .01, .05);
CompanyPositions.Employee.setPerformanceParameters(0, 10, 0, 10, 10, 70);
CompanyPositions.Employee.setExperienceGains(0, .01, .01, .01, .01, .015);
CompanyPositions.Employee.setExperienceGains(0, .01, .01, .01, .01, .04);
CompanyPositions.SecurityGuard.setPerformanceParameters(5, 20, 20, 20, 20, 15);
CompanyPositions.SecurityGuard.setExperienceGains(.01, .02, .02, .02, .02, .01);
CompanyPositions.PoliceOfficer.setPerformanceParameters(5, 20, 20, 20, 20, 15);
@ -340,6 +386,11 @@ getNextCompanyPosition = function(currPos) {
return CompanyPositions.HeadOfSoftware;
}
//Software Consultant
if (currPos.positionName == CompanyPositions.SoftwareConsultant.positionName) {
return CompanyPositions.SeniorSoftwareConsultant;
}
//IT
if (currPos.positionName == CompanyPositions.ITIntern.positionName) {
return CompanyPositions.ITAnalyst;
@ -393,6 +444,11 @@ getNextCompanyPosition = function(currPos) {
return CompanyPositions.CEO;
}
//Business consultant
if (currPos.positionName == CompanyPositions.BusinessConsultant.positionName) {
return CompanyPositions.SeniorBusinessConsultant;
}
//Police
if (currPos.positionName == CompanyPositions.PoliceOffier.positionName) {
return CompanyPositions.PoliceChief;
@ -420,7 +476,7 @@ getNextCompanyPosition = function(currPos) {
return null;
}
/* Initialize all companies. Only called when creating new game. Otherwise companies are
/* Initialize all companies. Only called when creating new game/prestiging. Otherwise companies are
* usually loaded from localStorage */
initCompanies = function() {
/* Companies that also have servers */
@ -570,6 +626,7 @@ initCompanies = function() {
StormTechnologies.addPositions([
CompanyPositions.SoftwareIntern,
CompanyPositions.JuniorDev, CompanyPositions.SeniorDev, CompanyPositions.LeadDev,
CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITAnalyst, CompanyPositions.ITManager, CompanyPositions.SysAdmin,
CompanyPositions.SecurityEngineer, CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator,
CompanyPositions.HeadOfSoftware, CompanyPositions.HeadOfEngineering,
@ -582,7 +639,8 @@ initCompanies = function() {
DefComm.init(Locations.NewTokyoDefComm, 1.75, 1.75, 199);
DefComm.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.CFO, CompanyPositions.CEO]);
@ -592,7 +650,8 @@ initCompanies = function() {
HeliosLabs.init(Locations.VolhavenHeliosLabs, 1.8, 1.8, 199);
HeliosLabs.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.CFO, CompanyPositions.CEO]);
@ -602,7 +661,8 @@ initCompanies = function() {
VitaLife.init(Locations.NewTokyoVitaLife, 1.8, 1.8, 199);
VitaLife.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.BusinessManager,
@ -613,7 +673,8 @@ initCompanies = function() {
IcarusMicrosystems.init(Locations.Sector12IcarusMicrosystems, 1.9, 1.9, 199);
IcarusMicrosystems.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.BusinessManager,
@ -624,7 +685,8 @@ initCompanies = function() {
UniversalEnergy.init(Locations.Sector12UniversalEnergy, 2.0, 2.0, 199);
UniversalEnergy.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.BusinessManager,
@ -635,7 +697,8 @@ initCompanies = function() {
GalacticCybersystems.init(Locations.AevumGalacticCybersystems, 1.9, 1.9, 199);
GalacticCybersystems.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.CTO, CompanyPositions.BusinessManager,
@ -701,6 +764,7 @@ initCompanies = function() {
GlobalPharmaceuticals.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.ITIntern, CompanyPositions.BusinessIntern,
CompanyPositions.JuniorDev, CompanyPositions.SeniorDev, CompanyPositions.LeadDev,
CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITAnalyst, CompanyPositions.ITManager, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator,
CompanyPositions.HeadOfSoftware, CompanyPositions.CTO, CompanyPositions.BusinessAnalyst,
@ -714,6 +778,7 @@ initCompanies = function() {
NovaMedical.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.ITIntern, CompanyPositions.BusinessIntern,
CompanyPositions.JuniorDev, CompanyPositions.SeniorDev, CompanyPositions.LeadDev,
CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITAnalyst, CompanyPositions.ITManager, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator,
CompanyPositions.HeadOfSoftware, CompanyPositions.CTO, CompanyPositions.BusinessAnalyst,
@ -751,7 +816,8 @@ initCompanies = function() {
WatchdogSecurity.init(Locations.AevumWatchdogSecurity, 1.5, 1.5, 124);
WatchdogSecurity.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.SecurityGuard, CompanyPositions.SecurityOfficer,
@ -764,7 +830,8 @@ initCompanies = function() {
LexoCorp.init(Locations.VolhavenLexoCorp, 1.4, 1.4, 99);
LexoCorp.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.HeadOfSoftware, CompanyPositions.CTO,
CompanyPositions.BusinessIntern, CompanyPositions.BusinessAnalyst,
@ -784,7 +851,8 @@ initCompanies = function() {
AlphaEnterprises.init(Locations.Sector12AlphaEnterprises, 1.5, 1.5, 99);
AlphaEnterprises.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.BusinessIntern, CompanyPositions.BusinessAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.BusinessIntern, CompanyPositions.BusinessAnalyst,
CompanyPositions.BusinessManager, CompanyPositions.OperationsManager]);
AddToCompanies(AlphaEnterprises);
@ -809,7 +877,8 @@ initCompanies = function() {
CompuTek.init(Locations.VolhavenCompuTek, 1.2, 1.2, 74);
CompuTek.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.CTO]);
@ -819,7 +888,8 @@ initCompanies = function() {
NetLinkTechnologies.init(Locations.AevumNetLinkTechnologies, 1.2, 1.2, 99);
NetLinkTechnologies.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.CTO]);
@ -829,7 +899,8 @@ initCompanies = function() {
CarmichaelSecurity.init(Locations.Sector12CarmichaelSecurity, 1.2, 1.2, 74);
CarmichaelSecurity.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.SysAdmin, CompanyPositions.SecurityEngineer,
CompanyPositions.NetworkEngineer, CompanyPositions.NetworkAdministrator, CompanyPositions.HeadOfSoftware,
CompanyPositions.HeadOfEngineering, CompanyPositions.SecurityGuard, CompanyPositions.SecurityOfficer,
@ -840,26 +911,27 @@ initCompanies = function() {
//"Low level" companies
var FoodNStuff = new Company();
FoodNStuff.init(Locations.Sector12FoodNStuff, 1, 1, 0);
FoodNStuff.addPositions([CompanyPositions.Employee]);
FoodNStuff.addPositions([CompanyPositions.Employee, CompanyPositions.PartTimeEmployee]);
AddToCompanies(FoodNStuff);
var JoesGuns = new Company();
JoesGuns.init(Locations.Sector12JoesGuns, 1, 1, 0);
JoesGuns.addPositions([CompanyPositions.Employee]);
JoesGuns.addPositions([CompanyPositions.Employee, CompanyPositions.PartTimeEmployee]);
AddToCompanies(JoesGuns);
var OmegaSoftware = new Company();
OmegaSoftware.init(Locations.IshimaOmegaSoftware, 1.1, 1.1, 49);
OmegaSoftware.addPositions([
CompanyPositions.SoftwareIntern, CompanyPositions.JuniorDev, CompanyPositions.SeniorDev,
CompanyPositions.LeadDev, CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.LeadDev, CompanyPositions.SoftwareConsultant, CompanyPositions.SeniorSoftwareConsultant,
CompanyPositions.ITIntern, CompanyPositions.ITAnalyst,
CompanyPositions.ITManager, CompanyPositions.CTO, CompanyPositions.CEO]);
AddToCompanies(OmegaSoftware);
/* Companies that do not have servers */
var NoodleBar = new Company();
NoodleBar.init(Locations.NewTokyoNoodleBar, 1, 1, 0);
NoodleBar.addPositions([CompanyPositions.Waiter]);
NoodleBar.addPositions([CompanyPositions.Waiter, CompanyPositions.PartTimeWaiter]);
AddToCompanies(NoodleBar);
}

@ -125,6 +125,10 @@ PlayerObject.prototype.applyForSoftwareJob = function() {
this.applyForJob(CompanyPositions.SoftwareIntern);
}
PlayerObject.prototype.applyForSoftwareConsultantJob = function() {
this.applyForJob(CompanyPositions.SoftwareConsultant);
}
PlayerObject.prototype.applyForItJob = function() {
this.applyForJob(CompanyPositions.ITIntern);
}
@ -154,6 +158,10 @@ PlayerObject.prototype.applyForBusinessJob = function() {
this.applyForJob(CompanyPositions.BusinessIntern);
}
PlayerObject.prototype.applyForBusinessConsultantJob = function() {
this.applyForJob(CompanyPositions.BusinessConsultant);
}
PlayerObject.prototype.applyForSecurityJob = function() {
//TODO If case for POlice departments
this.applyForJob(CompanyPositions.SecurityGuard);
@ -173,7 +181,19 @@ PlayerObject.prototype.applyForEmployeeJob = function() {
if (this.isQualified(company, CompanyPositions.Employee)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.Employee;
dialogBoxCreate("Congratulations, you are now employed at ", this.companyName, "", "");
dialogBoxCreate("Congratulations, you are now employed at " + this.companyName);
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
PlayerObject.prototype.applyForPartTimeEmployeeJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.PartTimeEmployee)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.PartTimeEmployee;
dialogBoxCreate("Congratulations, you are now employed part-time at " + this.companyName);
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
@ -185,7 +205,19 @@ PlayerObject.prototype.applyForWaiterJob = function() {
if (this.isQualified(company, CompanyPositions.Waiter)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.Waiter;
dialogBoxCreate("Congratulations, you are now employed as a waiter at ", this.companyName, "", "");
dialogBoxCreate("Congratulations, you are now employed as a waiter at " + this.companyName);
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");
}
}
PlayerObject.prototype.applyForPartTimeWaiterJob = function() {
var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.PartTimeWaiter)) {
this.companyName = company.companyName;
this.companyPosition = CompanyPositions.PartTimeWaiter;
dialogBoxCreate("Congratulations, you are now employed as a part-time waiter at " + this.companyName);
Engine.loadLocationContent();
} else {
dialogBoxCreate("Unforunately, you do not qualify for this position");

@ -1,32 +1,50 @@
CONSTANTS = {
Version: "0.1",
//Max level for any skill. Determined by max numerical value in javascript and the skill level
//formula in Player.js
//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
//the player will have this level assuming no multipliers. Multipliers can cause skills to go above this.
MaxSkillLevel: 975,
//How much reputation is needed to join a megacorporation's faction
CorpFactionRepRequirement: 250000,
/* Base costs */
BaseCostFor1GBOfRam: 50000, //1 GB of RAM
BaseCostFor1GBOfRamHome: 50000,
BaseCostFor1GBOfRamServer: 40000, //1 GB of RAM
BaseCostFor1GBOfRamHacknetNode: 25000,
BaseCostForHacknetNode: 1000,
BaseCostForHacknetNodeCore: 1000000,
/* Hacknet Node constants */
HacknetNodeMoneyGainPerLevel: 0.75,
HacknetNodeMoneyGainPerLevel: 1,
HacknetNodePurchaseNextMult: 1.35, //Multiplier when purchasing an additional hacknet node
HacknetNodeUpgradeLevelMult: 1.08, //Multiplier for cost when upgrading level
HacknetNodeUpgradeRamMult: 1.2, //Multiplier for cost when upgrading RAM
HacknetNodeUpgradeCoreMult: 1.5, //Multiplier for cost when buying another core
HacknetNodeUpgradeLevelMult: 1.06, //Multiplier for cost when upgrading level
HacknetNodeUpgradeRamMult: 1.25, //Multiplier for cost when upgrading RAM
HacknetNodeUpgradeCoreMult: 1.45, //Multiplier for cost when buying another core
/* Augmentation */
//NeuroFlux Governor cost multiplier as you level up
NeuroFluxGovernorLevelMult: 1.09,
/* Script related things */
//Time (ms) it takes to run one operation in Netscript.
CodeInstructionRunTime: 1500,
//Time (seconds) it takes to run one operation in Netscript OFFLINE
CodeOfflineExecutionTime: 10,
//RAM Costs for differenc commands
ScriptWhileRamCost: 0.4,
ScriptForRamCost: 0.4,
ScriptIfRamCost: 0.1,
ScriptHackRamCost: 0.25,
ScriptGrowRamCost: 0.25,
ScriptNukeRamCost: 0.05,
ScriptBrutesshRamCost: 0.05,
ScriptFtpcrackRamCost: 0.05,
ScriptRelaysmtpRamCost: 0.05,
ScriptHttpwormRamCost: 0.05,
ScriptSqlinjectRamCost: 0.05,
//Server growth rate
ServerGrowthRate: 1.00075,
@ -35,7 +53,7 @@ CONSTANTS = {
MaxLogCapacity: 20,
//How much a TOR router costs
TorRouterCost: 2000000,
TorRouterCost: 100000,
MillisecondsPer20Hours: 72000000,
GameCyclesPer20Hours: 72000000 / 200,
@ -66,6 +84,7 @@ CONSTANTS = {
FactionWorkSecurity: "Faction Security Work",
WorkTypeCompany: "Working for Company",
WorkTypeCompanyPartTime: "Working for Company part-time",
WorkTypeFaction: "Working for Faction",
WorkTypeCreateProgram: "Working on Create a Program",
WorkTypeStudyClass: "Studying or Taking a class at university",
@ -77,13 +96,27 @@ CONSTANTS = {
ClassAlgorithms: "taking an Algorithms course",
ClassManagement: "taking a Management course",
ClassLeadership: "taking a Leadership course",
ClassGymStrength: "training your strength at a gym",
ClassGymDefense: "training your defense at a gym",
ClassGymDexterity: "training your dexterity at a gym",
ClassGymAgility: "training your agility at a gym",
ClassDataStructuresBaseCost: 1,
ClassNetworksBaseCost: 5,
ClassAlgorithmsBaseCost: 20,
ClassManagementBaseCost: 10,
ClassLeadershipBaseCost: 20,
ClassGymBaseCost: 15,
CrimeShoplift: "shoplift",
CrimeMug: "mug someone",
CrimeDrugs: "deal drugs",
CrimeTraffickArms: "traffick illegal arms",
CrimeHomicide: "commit homicide",
CrimeGrandTheftAuto: "commit grand theft auto",
CrimeKidnap: "kidnap someone for ransom",
CrimeAssassination: "assassinate a high-profile target",
CrimeHeist: "pull off the ultimate heist",
//Text that is displayed when the 'help' command is ran in Terminal
HelpText: "analyze Get statistics and information about current machine <br>" +
@ -104,6 +137,7 @@ CONSTANTS = {
"rm Delete a script/program from the machine. (WARNING: Permanent)<br>" +
"run [script/program] Execute a program or a script<br>" +
"scan See 'netstat' command<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)" +
"telnet [ip/hostname] See 'connect' command<br>" +
"top Display all running scripts and their RAM usage<br>",
@ -124,7 +158,7 @@ CONSTANTS = {
TutorialHackingText: "In the year 2077, currency has become digital and decentralized. People and corporations " +
"store their money on servers. By hacking these servers, you can steal their money and gain " +
"experience. <br><br>" +
"Gaining root access <br>" +
"<strong>Gaining root access</strong> <br>" +
"The key to hacking a server is to gain root access to that server. This can be done using " +
"the NUKE virus (NUKE.exe). You start the game with a copy of the NUKE virus on your home " +
"computer. The NUKE virus attacks the target server's open ports using buffer overflow " +
@ -140,7 +174,7 @@ CONSTANTS = {
"opened. <br>" +
"Once you have enough ports opened and have ran the NUKE virus to gain root access, the server " +
"can then be hacked by simply calling the 'hack' command through terminal, or by using a script.<br><br>" +
"Hacking mechanics <br>" +
"<strong>Hacking mechanics</strong><br>" +
"When you execute the hack command, either manually through the terminal or automatically through " +
"a script, you attempt to hack the server. This action takes time. The more advanced a server's " +
"security is, the more time it will take. Your hacking skill level also affects the hacking time, " +
@ -155,36 +189,96 @@ CONSTANTS = {
"encounter diminishing returns in your hacking (since you are only hacking a certain percentage). A server " +
"will regain money at a slow rate over time. ",
TutorialScriptsText: "Scripts can be used to automate the hacking process. Scripts must be written in the Netscript language " +
"and are saved as a file. Running a script requires RAM. The more complex a script is, the more RAM " +
TutorialScriptsText: "Scripts can be used to automate the hacking process. Scripts must be written in the Netscript language. " +
"Documentation about the Netscript language can be found in the 'Netscript Programming Language' " +
"section of this 'Tutorial' page. <br><br>Running a script requires RAM. The more complex a script is, the more RAM " +
"it requires to run. Scripts can be run on any server you have root access to. <br><br>" +
"Here are some commands that are useful when working with scripts: <br>" +
"Here are some Terminal commands that are useful when working with scripts: <br>" +
"free - Shows the current server's RAM usage <br>" +
"kill [script] - Stops a script that is running <br>" +
"nano [script] - Edit a script <br>" +
"nano [script] - Create/Edit a script <br>" +
"ps - Displays all scripts that are actively running on the current server<br>" +
"run [script] - Run a script <br>" +
"tail [script] - Displays a script's logs<br>" +
"top - Displays all active scripts and their RAM usage <br><br>",
TutorialTravelingText:"There are six major cities in the world that you are able to travel to: <br> " +
TutorialNetscriptText: "Netscript is a very simple programming language implemented for this game. The language has " +
"your basic programming constructs and several built-in commands that are used to hack. <br><br>" +
"<strong> Variables and data types </strong><br>" +
"The following data types are supported by Netscript: <br>" +
"numeric - Integers and floats (6, 10.4999)<br>" +
"string - Encapsulated by single or double quotes ('this is a string')<br>" +
"boolean - true or false<br><br>" +
"To create a variable, use the assign (=) operator. The language is not strongly typed. Examples: <br>" +
"i = 5;<br>" +
"s = 'this game is awesome!';<br><br>" +
"In the first example above, we are creating the variable i and assigning it a value of 5. In the second, " +
"we are creating the variable s and assigning it the value of a string. Note that all expressions must be " +
"ended with a semicolon. <br><br>" +
"<strong> Operators </strong> <br>" +
"The following operators are supported by Netscript: <br>" +
"&nbsp;+<br>" +
"&nbsp;-<br>" +
"&nbsp;*<br>" +
"&nbsp;/<br>" +
"&nbsp;%<br>" +
"&nbsp;&&<br>" +
"&nbsp;||<br>" +
"&nbsp;<<br>" +
"&nbsp;><br>" +
"&nbsp;<=<br>" +
"&nbsp;>=<br>" +
"&nbsp;==<br>" +
"&nbsp;!=<br><br>" +
"<strong> Functions </strong><br>" +
"You can NOT define you own functions in Netscript (yet), but there are several built in functions that " +
"you may use: <br><br> " +
"<i>hack(hostname/ip)</i><br>Core function that is used to hack servers to steal money and gain hacking experience. The argument passed in must be a string with " +
"either the IP or hostname of the server you want to hack. <br>Examples: hack('foodnstuff'); or hack('148.192.0.12');<br><br>" +
"<i>sleep(n)</i><br>Suspends the script for n milliseconds. <br>Example: sleep(5000);<br><br>" +
"<i>grow(hostname/ip)</i><br>Use your hacking skills to increase the amount of money available on a server. The argument passed in " +
"must be a string with either the IP or hostname of the target server. <br> Example: grow('foodnstuff');<br><br>" +
"<i>nuke(hostname/ip)</i><br>Run NUKE.exe on the target server. NUKE.exe must exist on your home computer. <br> Example: nuke('foodnstuff'); <br><br>" +
"<i>brutessh(hostname/ip)</i><br>Run BruteSSH.exe on the target server. BruteSSH.exe must exist on your home computer <br> Example: brutessh('foodnstuff');<br><br>" +
"<i>ftpcrack(hostname/ip)</i><br>Run FTPCrack.exe on the target server. FTPCrack.exe must exist on your home computer <br> Example: ftpcrack('foodnstuff');<br><br>" +
"<i>relaysmtp(hostname/ip)</i><br>Run relaySMTP.exe on the target server. relaySMTP.exe must exist on your home computer <br> Example: relaysmtp('foodnstuff');<br><br>" +
"<i>httpworm(hostname/ip)</i><br>Run HTTPWorm.exe on the target server. HTTPWorm.exe must exist on your home computer <br> Example: httpworm('foodnstuff');<br><br>" +
"<i>sqlinject(hostname/ip)</i><br>Run SQLInject.exe on the target server. SQLInject.exe must exist on your home computer <br> Example: sqlinject('foodnstuff');<br><br>" +
"<strong>While loop </strong><br>" +
"A while loop is a control flow statement that repeatedly executes code as long as a condition is met. <br><br> " +
"while (<i>[cond]</i>) {<br>&nbsp;&nbsp;&nbsp;&nbsp;<i>[code]</i><br>}<br><br>" +
"As long as <i>[cond]</i> remains true, the code block <i>[code]</i> will continuously execute. Example: <br><br>" +
"i = 0; <br> while (i < 10) { <br>&nbsp;&nbsp;&nbsp;&nbsp;hack('foodnstuff');<br>&nbsp;&nbsp;&nbsp;&nbsp;i = i + 1;<br> }; <br><br>" +
"This code repeat the 'hack('foodnstuff')' command 10 times before it stops and exits. " +
"Note that a semicolon is needed at closing bracket of the while loop, UNLESS it is at the end of the code<br><br> " +
"<strong>For loop</strong><br>" +
"A for loop is another control flow statement that allows code to by repeated by iterations. The structure is: <br><br> " +
"for (<i>[init]</i>; <i>[cond]</i>; <i>[post]</i>) {<br>&nbsp;&nbsp;&nbsp;&nbsp;<i>code</i> <br> }<br><br>" +
"The <i>[init]</i> expression evaluates before the for loop begins. The for loop will continue to execute " +
"as long as <i>[cond]</i> is met. The <i>[post]</i> expression will evaluate at the end of every iteration " +
"of the for loop. The following example shows code that will do the same thing as the while loop example above, " +
"except using a for loop instead: <br><br>" +
"for (i = 0; i < 10; i = i+1) { <br>&nbsp;&nbsp;&nbsp;&nbsp;hack('foodnstuff');<br>}; <br><br><br>",
TutorialTravelingText:"There are six major cities in the world that you are able to travel to: <br><br> " +
" Aevum<br>" +
" Chongqing<br>" +
" Sector-12<br>" +
" New Tokyo<br>" +
" Ishima<br>" +
" Volhaven<br>" +
" Volhaven<br><br>" +
"To travel between cities, visit your current city's travel agency through the 'World' page. " +
"From the travel agency you can travel to any other city. Doing so costs money. <br>" +
"Each city has its own set of companies and unique locations. ",
"From the travel agency you can travel to any other city. Doing so costs money. <br><br>" +
"Each city has its own set of companies and unique locations. Also, certain content is only available to you " +
"if you are in certain cities, so get exploring!",
TutorialJobsText: "Hacking is not the only way to gain money and experience! Located around the world are many " +
"different companies which you can work for. By working for a company you can earn money, " +
"train your various labor skills, and unlock powerful passive perks. <br> " +
"train your various labor skills, and unlock powerful passive perks. <br><br> " +
"To apply for a job, visit the company you want to work for through the 'World' menu. The company " +
"page will have options that let you apply to positions in the company. There might be several different" +
"positions you can apply for, ranging from software engineer to business analyst to security officer. <br> " +
"positions you can apply for, ranging from software engineer to business analyst to security officer. <br><br> " +
"When you apply for a job, you will get the offer if your stats are high enough. Your first position at " +
"a company will be an entry-level position such as 'intern'. Once you get the job, an button will appear on " +
"the company page that allows you to work for the company. Click this button to start working. <br>" +
"the company page that allows you to work for the company. Click this button to start working. <br><br>" +
"Working occurs in 8 hour shifts. Once you start working, you will begin earning money, experience, " +
"and reputation. The rate at which you money and experience depends on the company and your position. " +
"The amount of reputation you gain for your company is based on your job performance, which is affected by " +
@ -192,22 +286,23 @@ CONSTANTS = {
"other actions such as using your terminal or visiting other locations (However, note that any scripts you have " +
"running on servers will continue to run as you work!). It is possible to cancel your work shift before the " +
"8 hours is up, but doing so will result in you gaining only half of all of the money, experience, and reputation " +
"that you had earned up to that point. <br>" +
"that you had earned up to that point. <br><br>" +
"As you continue to work at a company, you will gain more and more reputation at that company. When your stats " +
"and reputation are high enough, you can get a promotion. You can apply for a promotion on the company page, just like " +
"you applied for the job originally. Higher positions at a company provide better salaries and stat gains",
"you applied for the job originally. Higher positions at a company provide better salaries and stat gains.",
TutorialFactionsText: "Throughout the game you may receive invitations from factions. There are many different factions, and each faction " +
"has different criteria for determining its potential members. Joining a faction and furthering its cause is crucial " +
"to progressing in the game and unlocking endgame content. <br> " +
"to progressing in the game and unlocking endgame content. <br><br> " +
"It is possible to join multiple factions if you receive invitations from them. However, note that joining a faction " +
"may prevent you from joining other rival factions. <br> " +
"may prevent you from joining other rival factions. <br><br> " +
"The 'Factions' link on the menu brings up a list of all factions that you have joined. " +
"You can select a Faction on this list to go to that Faction page. This page displays general " +
"information about the Faction and also lets you perform work for the faction. " +
"Working for a Faction is similar to working for a company except that you don't get paid a salary. " +
"You will only earn reputation in your Faction and train your stats. Also, cancelling work early " +
"when working for a Faction does not result in reduced experience/reputation earnings. <br>" +
"Earning reputation for a Faction unlocks powerful upgrades. These upgrades vary from faction to faction. ",
"when working for a Faction does NOT result in reduced experience/reputation earnings. <br>" +
"Earning reputation for a Faction unlocks powerful Augmentations. Purchasing and installing these Augmentations will " +
"upgrade your abilities. The Augmentations that are available to unlock vary from faction to faction.",
TutorialAugmentationsText: "Advances in science and medicine have lead to powerful new technologies that allow people to augment themselves " +
"beyond normal human capabilities. There are many different types of Augmentations, ranging from cybernetic to " +
"genetic to biological. Acquiring these Augmentations enhances the user's physical and mental faculties. <br>" +
@ -215,11 +310,23 @@ CONSTANTS = {
"corporations and organizations that create them. Therefore, the only way for the player to obtain Augmentations is " +
"through Factions. After joining a Faction and earning enough reputation in it, you will be able to purchase " +
"its Augmentations. Different Factions offer different Augmentations. Augmentations must be purchased in order to be installed, " +
"and they are fairly expensive. <br>" +
"Unfortunately, installing an Augmentation has side effects. All of your stats and experience will be reset to 1. " +
"You will lose all of your digital assets as well, such as your money, programs, scripts, and purchased servers. " +
"You will lose all of the reputation you have earned from every company and faction and will no longer be an employee " +
"or member of any. The only thing you will keep when you install an Augmentation is all of the past Augmentations " +
"you have installed. ",
"and they are fairly expensive. <br><br>" +
"Unfortunately, installing an Augmentation has side effects. You will lose most of the progress you've made, including your " +
"skills, stats, and money. You will have to start over, but you will have all of the Augmentations you have installed to " +
"help you progress. <br><br> " +
"To summarize, here is a list of everything you will LOSE when you install an Augmentation: <br><br>" +
"Stats/Skills<br>" +
"Money<br>" +
"Scripts on all servers EXCEPT your home computer<br>" +
"Purchased servers<br>" +
"Hacknet Nodes<br>" +
"Company/faction reputation<br>" +
"Jobs and Faction memberships<br>" +
"Programs<br>" +
"TOR router<br><br>" +
"Here is everything you will KEEP when you install an Augmentation: <br><br>" +
"Every Augmentation you have installed<br>" +
"Scripts on your home computer<br>" +
"RAM Upgrades on your home computer",
}

@ -11,72 +11,93 @@ Programs = {
//TODO Right now the times needed to complete work are hard-coded...
//maybe later make this dependent on hacking level or something
function displayCreateProgramContent() {
var portHackALink = document.getElementById("create-program-porthack");
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.style.display = "none";
nukeALink.style.display = "none";
bruteSshALink.style.display = "none";
ftpCrackALink.style.display = "none";
relaySmtpALink.style.display = "none";
httpWormALink.style.display = "none";
sqlInjectALink.style.display = "none";
//TODO These addEventListeners should only happen once so I guess just put them in Engine.init()
//PortHack.exe (in case you delete it lol)
//NUKE.exe (in case you delete it lol)
if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) {
portHackALink.style.display = "block";
portHackALink.addEventListener("click", function() {
createProgram(Programs.PortHackProgram);
});
nukeALink.style.display = "block";
}
//BruteSSH
if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 &&
Player.hacking_skill >= 50) {
bruteSshALink.style.display = "block";
bruteSshALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.BruteSSHProgram, CONSTANTS.MillisecondsPerQuarterHour);
});
}
//FTPCrack
if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 &&
Player.hacking_skill >= 100) {
ftpCrackALink.style.display = "block";
ftpCrackALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.FTPCrackProgram, CONSTANTS.MillisecondsHalfHour);
});
}
//relaySMTP
if (Player.getHomeComputer().programs.indexOf(Programs.RelaySMTPProgram) == -1 &&
Player.hacking_skill >= 250) {
relaySmtpALink.style.display = "block";
relaySmtpAlink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.RelaySMTPProgram. CONSTANTS.MillisecondsPer2Hours);
});
}
//HTTPWorm
if (Player.getHomeComputer().programs.indexOf(Programs.HTTPWormProgram) == -1 &&
Player.hacking_skill >= 500) {
httpWormALink.style.display = "block";
httpWormALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.HTTPWormProgram, CONSTANTS.MillisecondsPer4Hours);
});
}
//SQLInject
if (Player.getHomeComputer().programs.indexOf(Programs.SQLInjectProgram) == -1 &&
Player.hacking_skill >= 750) {
sqlInjectALink.style.display = "block";
sqlInjectALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.SQLInjectProgram, CONSTANTS.MillisecondsPer8Hours);
});
}
}
//Returns the number of programs that are currently available to be created
function getNumAvailableCreateProgram() {
var count = 0;
//PortHack.exe (in case you delete it lol)
if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) {
++count;
}
//BruteSSH
if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 &&
Player.hacking_skill >= 50) {
++count;
}
//FTPCrack
if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 &&
Player.hacking_skill >= 100) {
++count;
}
//relaySMTP
if (Player.getHomeComputer().programs.indexOf(Programs.RelaySMTPProgram) == -1 &&
Player.hacking_skill >= 250) {
++count;
}
//HTTPWorm
if (Player.getHomeComputer().programs.indexOf(Programs.HTTPWormProgram) == -1 &&
Player.hacking_skill >= 500) {
++count;
}
//SQLInject
if (Player.getHomeComputer().programs.indexOf(Programs.SQLInjectProgram) == -1 &&
Player.hacking_skill >= 750) {
++count;
}
return count;
}

@ -1,32 +1,47 @@
/* Crimes.js */
function commitShopliftCrime() {
Player.crimeType = CONSTANTS.CrimeShoplift;
Player.startCrime(0, 1, 1, 1, 1, 0, 100, 3000); //$33.33/s, .333 exp/s
Player.startCrime(0, 0.75, 0.75, 0.75, 0.75, 0, 1000, 2000); //$500/s, .375 exp/s
}
function commitMugCrime() {
Player.crimeType = CONSTANTS.CrimeMug;
Player.startCrime(0, 2, 2, 2, 2, 0, 250, 5000); //$50/s, .4 exp/s
Player.startCrime(0, 1.5, 1.5, 1.5, 1.5, 0, 3000, 4000); //$750/s, .375 exp/s
}
function commitDealDrugsCrime() {
Player.crimeType = CONSTANTS.CrimeDrugs;
Player.startCrime(0, 2, 2, 2, 2, 4, 1000, 10000); //$100/s, .2 combat exp/s, .4 cha exp/s
Player.startCrime(0, 4, 4, 4, 4, 4, 10000, 10000); //$1000/s, .4 exp/s
}
function commitTraffickArmsCrime() {
Player.crimeType = CONSTANTS.CrimeTraffickArms;
Player.startCrime(0, 10, 10, 10, 10, 16, 5000, 40000); //$125/s, .25 combat exp/s, .4 cha exp/s
Player.startCrime(0, 10, 10, 10, 10, 15, 60000, 40000); //$1500/s, .25 combat exp/s, .375 cha exp/s
}
function commitHomicideCrime() {
Player.crimeType = CONSTANTS.CrimeHomicide;
Player.startCrime(0, 3, 3, 3, 3, 0, 300, 3000); //$100/s, 1 combat exp/s
Player.startCrime(0, 2, 2, 2, 2, 0, 1000, 3000); //$333.3/s, 0.66 combat exp/s
}
function commitGrandTheftAutoCrime() {
Player.crimeType = CONSTANTS.CrimeGrandTheftAuto;
Player.startCrime(0, 10, 10, 10, 40, 20, 150000, 80000); //$1875/2, .125 exp/s, .5 exp/s, .25 exp/s
}
function commitKidnapCrime() {
Player.crimeType = CONSTANTS.CrimeKidnap;
Player.startCrime(0, 30, 30, 30, 30, 30, 20000, 120000); //$166.67/s. .25 exp/s
Player.startCrime(0, 30, 30, 30, 30, 30, 300000, 120000); //$2500/s. .25 exp/s
}
function commitAssassinationCrime() {
Player.crimeType = CONSTANTS.CrimeAssassination;
Player.startCrime(0, 75, 75, 75, 75, 0, 1000000, 300000); //$3333.33/s, .25 exp/s
}
function commitHeistCrime() {
Player.crimeType = CONSTANTS.CrimeHeist;
Player.startCrime(120, 120, 120, 120, 120, 120, 25000000, 600000); //$41,666.67/s, .2exp/s
}
function determineCrimeSuccess(crime, moneyGained) {
@ -47,9 +62,18 @@ function determineCrimeSuccess(crime, moneyGained) {
case CONSTANTS.CrimeHomicide:
chance = determineCrimeChanceHomicide();
break;
case CONSTANTS.CrimeGrandTheftAuto:
chance = determineCrimeChanceGrandTheftAuto();
break;
case CONSTANTS.CrimeKidnap:
chance = determineCrimeChanceKidnap();
break;
case CONSTANTS.CrimeAssassination:
chance = determineCrimeChanceAssassination();
break;
case CONSTANTS.CrimeHeist:
chance = determineCrimeChanceHeist();
break;
default:
dialogBoxCreate("ERR: Unrecognized crime type. This is probably a bug please contact the developer");
return;
@ -68,7 +92,7 @@ function determineCrimeChanceShoplift() {
var chance = ((Player.strength / CONSTANTS.MaxSkillLevel +
Player.defense / CONSTANTS.MaxSkillLevel +
Player.dexterity / CONSTANTS.MaxSkillLevel +
Player.agility / CONSTANTS.MaxSkillLevel)) * 8;
Player.agility / CONSTANTS.MaxSkillLevel)) * 10;
return Math.min(chance, 1);
}
@ -77,12 +101,12 @@ function determineCrimeChanceMug() {
var chance = ((Player.strength / CONSTANTS.MaxSkillLevel +
Player.defense / CONSTANTS.MaxSkillLevel +
Player.dexterity / CONSTANTS.MaxSkillLevel +
Player.agility / CONSTANTS.MaxSkillLevel)) * 4;
Player.agility / CONSTANTS.MaxSkillLevel)) * 5;
return Math.min(chance, 1);
}
function determineCrimeChanceDealDrugs() {
var chance = ((1.5*Player.charisma / CONSTANTS.MaxSkillLevel +
var chance = ((2*Player.charisma / CONSTANTS.MaxSkillLevel +
Player.strength / CONSTANTS.MaxSkillLevel +
Player.defense / CONSTANTS.MaxSkillLevel +
Player.dexterity / CONSTANTS.MaxSkillLevel +
@ -95,7 +119,7 @@ function determineCrimeChanceTraffickArms() {
Player.strength / CONSTANTS.MaxSkillLevel +
Player.defense / CONSTANTS.MaxSkillLevel +
Player.dexterity / CONSTANTS.MaxSkillLevel +
Player.agility / CONSTANTS.MaxSkillLevel));
Player.agility / CONSTANTS.MaxSkillLevel)) / 2;
return Math.min(chance, 1);
}
@ -107,11 +131,39 @@ function determineCrimeChanceHomicide() {
return Math.min(chance, 1);
}
function determineCrimeChanceGrandTheftAuto() {
var chance = ((Player.hacking_skill / CONSTANTS.MaxSkillLevel +
Player.strength / CONSTANTS.MaxSkillLevel +
Player.defense / CONSTANTS.MaxSkillLevel +
4 * Player.dexterity / CONSTANTS.MaxSkillLevel +
Player.agility / CONSTANTS.MaxSkillLevel +
2 * Player.charisma / CONSTANTS.MaxSkillLevel)) / 8;
return Math.min(chance, 1);
}
function determineCrimeChanceKidnap() {
return ((Player.charisma / CONSTANTS.MaxSkillLevel +
Player.strength / CONSTANTS.MaxSkillLevel +
Player.defense / CONSTANTS.MaxSkillLevel +
Player.dexterity / CONSTANTS.MaxSkillLevel +
Player.agility / CONSTANTS.MaxSkillLevel)) / 4;
Player.agility / CONSTANTS.MaxSkillLevel)) / 6;
return Math.min(chance, 1);
}
function determineCrimeChanceAssassination() {
var chance = ((Player.strength / CONSTANTS.MaxSkillLevel +
Player.defense / CONSTANTS.MaxSkillLevel +
Player.dexterity / CONSTANTS.MaxSkillLevel +
Player.agility / CONSTANTS.MaxSkillLevel)) / 8;
return Math.min(chance, 1);
}
function determineCrimeChanceHeist() {
var chance = ((Player.hacking_skill / CONSTANTS.MaxSkillLevel +
Player.strength / CONSTANTS.MaxSkillLevel +
Player.defense / CONSTANTS.MaxSkillLevel +
Player.dexterity / CONSTANTS.MaxSkillLevel +
Player.agility / CONSTANTS.MaxSkillLevel +
Player.charisma / CONSTANTS.MaxSkillLevel)) / 18;
return Math.min(chance, 1);
}

@ -1,4 +1,132 @@
/* DarkWeb.js */
executeDarkwebTerminalCommand = function() {
//Posts a "help" message if connected to DarkWeb
checkIfConnectedToDarkweb = function() {
if (SpecialServerIps.hasOwnProperty("Darkweb Server")) {
var darkwebIp = SpecialServerIps["Darkweb Server"];
if (!isValidIPAddress(darkwebIp)) {return;}
if (darkwebIp == Player.getCurrentServer().ip) {
post("You are now connected to the dark web. From the dark web you can purchase illegal items. " +
"Use the 'buy -l' command to display a list of all the items you can buy. Use 'buy [item-name] " +
"to purchase an item");
}
}
}
//Handler for dark web commands. The terminal's executeCommand() function will pass
//dark web-specific commands into this. It will pass in the raw split command array
//rather than the command string
executeDarkwebTerminalCommand = function(commandArray) {
if (commandArray.length == 0) {return;}
switch (commandArray[0]) {
case "buy":
if (commandArray.length != 2) {
post("Incorrect number of arguments. Usage: ");
post("buy -l");
post("buy [item name]");
}
var arg = commandArray[1];
if (arg == "-l") {
listAllDarkwebItems();
} else {
buyDarkwebItem(arg);
}
break;
default:
post("Command not found");
break;
}
}
listAllDarkwebItems = function() {
for (var item in DarkWebItems) {
if (DarkWebItems.hasOwnProperty(item)) {
post(DarkWebItems[item]);
}
}
}
buyDarkwebItem = function(itemName) {
if (itemName.toLowerCase() == "brutessh.exe") {
var price = parseDarkwebItemPrice(DarkWebItems.BruteSSHProgram);
if (price > 0 && Player.money >= price) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.BruteSSHProgram);
post("You have purchased the BruteSSH.exe program. The new program " +
"can be found on your home computer.");
} else {
post("Not enough money to purchase " + itemName);
}
} else if (itemName.toLowerCase() == "ftpcrack.exe") {
var price = parseDarkwebItemPrice(DarkWebItems.FTPCrackProgram);
if (price > 0 && Player.money >= price) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.FTPCrackProgram);
post("You have purchased the FTPCrack.exe program. The new program " +
"can be found on your home computer.");
} else {
post("Not enough money to purchase " + itemName);
}
} else if (itemName.toLowerCase() == "relaysmtp.exe") {
var price = parseDarkwebItemPrice(DarkWebItems.RelaySMTPProgram);
if (price > 0 && Player.money >= price) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.RelaySMTPProgram);
post("You have purchased the relaySMTP.exe program. The new program " +
"can be found on your home computer.");
} else {
post("Not enough money to purchase " + itemName);
}
} else if (itemName.toLowerCase() == "httpworm.exe") {
var price = parseDarkwebItemPrice(DarkWebItems.HTTPWormProgram);
if (price > 0 && Player.money >= price) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.HTTPWormProgram);
post("You have purchased the HTTPWorm.exe program. The new program " +
"can be found on your home computer.");
} else {
post("Not enough money to purchase " + itemName);
}
} else if (itemName.toLowerCase() == "sqlinject.exe") {
var price = parseDarkwebItemPrice(DarkWebItems.SQLInjectProgram);
if (price > 0 && Player.money >= price) {
Player.loseMoney(price);
Player.getHomeComputer().programs.push(Programs.SQLInjectProgram);
post("You have purchased the SQLInject.exe program. The new program " +
"can be found on your home computer.");
} else {
post("Not enough money to purchase " + itemName);
}
} else {
post("Unrecognized item");
}
}
parseDarkwebItemPrice = function(itemDesc) {
var split = itemDesc.split(" - ");
if (split.length == 3) {
var priceString = split[1];
//Check for errors
if (priceString.length == 0 || priceString.charAt(0) != '$') {
return -1;
}
//Remove dollar sign and commas
priceString = priceString.slice(1);
priceString = priceString.replace(/,/g, '');
//Convert string to numeric
var price = parseFloat(priceString);
if (isNaN(price)) {return -1;}
else {return price;}
} else {
return -1;
}
}
DarkWebItems = {
BruteSSHProgram: Programs.BruteSSHProgram + " - $50,000 - Opens up SSH Ports",
FTPCrackProgram: Programs.FTPCrackProgram + " - $150,000 - Opens up FTP Ports",
RelaySMTPProgram: Programs.RelaySMTPProgram + " - $500,000 - Opens up SMTP Ports",
HTTPWormProgram: Programs.HTTPWormProgram + " - $3,000,000 - Opens up HTTP Ports",
SQLInjectProgram: Programs.SQLInjectProgram + " - $25,000,000 - Opens up SQL Ports",
}

@ -133,6 +133,12 @@ initFactions = function() {
var Silhouette = new Faction("Silhouette");
Silhouette.setInfo(FactionInfo.SilhouetteInfo);
AddToFactions(Silhouette);
var Tetrads = new Faction("Tetrads"); //Low-medium level asian crime gang
Tetrads.setInfo(FactionInfo.TetradsInfo);
AddToFactions(Tetrads);
var SlumSnakes = new Faction("Slum Snakes"); //Low level crime gang
SlumSnakes.setInfo(FactionInfo.SlumSnakesInfo);
AddToFactions(SlumSnakes);
//Earlygame factions - factions the player will prestige with early on that don't
//belong in other categories
@ -153,6 +159,7 @@ initFactions = function() {
PlayerObject.prototype.checkForFactionInvitations = function() {
if (Engine.Debug) {
console.log("checkForFactionInvitations() called");
console.log("karma: " + this.karma);
}
invitedFactions = []; //Array which will hold all Factions th eplayer should be invited to
@ -269,12 +276,14 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var fulcrumSecretServer = AllServers[SpecialServerIps["Fulcrum Secret Technologies Server"]];
if (fulcrumSecretServer == null) {
console.log("Error: Could not find Fulcrum Secret Technologies Server");
}
} else {
if (fulcrumsecrettechonologiesFac.isBanned == false && fulcrumsecrettechonologiesFac.isMember == false &&
fulcrumSecretServer.hasAdminRights &&
this.companyName == Locations.AevumFulcrumTechnologies && companyRep >= 250000) {
invitedFactions.push(fulcrumsecrettechonologiesFac);
}
}
//BitRunners
var bitrunnersFac = Factions["BitRunners"];
@ -302,42 +311,42 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
//Chongqing
var chongqingFac = Factions["Chongqing"];
if (chongqingFac.isBanned == false && chongqingFac.isMember == false &&
this.money >= 20000000 && this.location == Locations.Chongqing) {
this.money >= 20000000 && this.city == Locations.Chongqing) {
invitedFactions.push(chongqingFac);
}
//Sector-12
var sector12Fac = Factions["Sector-12"];
if (sector12Fac.isBanned == false && sector12Fac.isMember == false &&
this.money >= 50000000 && this.location == Locations.Sector12) {
this.money >= 15000000 && this.city == Locations.Sector12) {
invitedFactions.push(sector12Fac);
}
//New Tokyo
var newtokyoFac = Factions["New Tokyo"];
if (newtokyoFac.isBanned == false && newtokyoFac.isMember == false &&
this.money >= 20000000 && this.location == Locations.NewTokyo) {
this.money >= 20000000 && this.city == Locations.NewTokyo) {
invitedFactions.push(newtokyoFac);
}
//Aevum
var aevumFac = Factions["Aevum"];
if (aevumFac.isBanned == false && aevumFac.isMember == false &&
this.money >= 40000000 && this.location == Locations.Aevum) {
this.money >= 40000000 && this.city == Locations.Aevum) {
invitedFactions.push(aevumFac);
}
//Ishima
var ishimaFac = Factions["Ishima"];
if (ishimaFac.isBanned == false && ishimaFac.isMember == false &&
this.money >= 30000000 && this.location == Locations.Ishima) {
this.money >= 30000000 && this.city == Locations.Ishima) {
invitedFactions.push(ishimaFac);
}
//Volhaven
var volhavenFac = Factions["Volhaven"];
if (volhavenFac.isBanned == false && volhavenFac.isMember == false &&
this.money >= 50000000 && this.location == Locations.Volhaven) {
this.money >= 50000000 && this.city == Locations.Volhaven) {
invitedFactions.push(volhavenFac);
}
@ -355,7 +364,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
var thedarkarmyFac = Factions["The Dark Army"];
if (thedarkarmyFac.isBanned == false && thedarkarmyFac.isMember == false &&
this.hacking_skill >= 300 && this.strength >= 300 && this.defense >= 300 &&
this.dexterity >= 300 && this.agility >= 300 && this.location == Locations.Chongqing &&
this.dexterity >= 300 && this.agility >= 300 && this.city == Locations.Chongqing &&
this.numPeopleKilled >= 5 && this.karma <= -50 && this.companyName != Locations.Sector12CIA &&
this.companyName != Locations.Sector12NSA) {
invitedFactions.push(thedarkarmyFac);
@ -366,7 +375,7 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
if (thesyndicateFac.isBanned == false && thesyndicateFac.isMember == false &&
this.hacking_skill >= 200 && this.strength >= 200 && this.defense >= 200 &&
this.dexterity >= 200 && this.agility >= 200 &&
(this.location == Locations.Aevum || this.location == Locations.Sector12) &&
(this.city == Locations.Aevum || this.city == Locations.Sector12) &&
this.money >= 10000000 && this.karma <= -100 &&
this.companyName != Locations.Sector12CIA && this.companyName != Locations.Sector12NSA) {
invitedFactions.push(thesyndicateFac);
@ -382,6 +391,23 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
invitedFactions.push(silhouetteFac);
}
//Tetrads
var tetradsFac = Factions["Tetrads"];
if (tetradsFac.isBanned == false && tetradsFac.isMember == false &&
(this.city == Locations.Chongqing || this.city == Locations.NewTokyo ||
this.city == Locations.Ishima) && this.strength >= 75 && this.defense >= 75 &&
this.dexterity >= 75 && this.agility >= 75 && this.karma <= -20) {
invitedFactions.push(tetradsFac);
}
//SlumSnakes
var slumsnakesFac = Factions["Slum Snakes"];
if (slumsnakesFac.isBanned == false && slumsnakesFac.isMember == false &&
this.strength >= 30 && this.defense >= 30 && this.dexterity >= 30 &&
this.agility >= 30 && this.karma <= -15 && this.money >= 1000000) {
invitedFactions.push(slumsnakesFac);
}
//Netburners
var netburnersFac = Factions["Netburners"];
var totalHacknetRam = 0;
@ -393,17 +419,19 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
totalHacknetCores += Player.hacknetNodes[i].numCores;
}
if (netburnersFac.isBanned == false && netburnersFac.isMember == false &&
this.hacking_skill >= 100 && totalHacknetRam >= 10 &&
totalHacknetCores >= 5 && totalHacknetLevels >= 100) {
this.hacking_skill >= 80 && totalHacknetRam >= 8 &&
totalHacknetCores >= 4 && totalHacknetLevels >= 100) {
invitedFactions.push(netburnersFac);
}
//Tian Di Hui
console.log("here");
var tiandihuiFac = Factions["Tian Di Hui"];
if (tiandihuiFac.isBanned == false && tiandihuiFac.isMember == false &&
this.money >= 1000000 && this.hacking_skill >= 50 &&
(this.location == Locations.Chongqing || this.location == Locations.NewTokyo ||
this.location == Locations.Ishima)) {
(this.city == Locations.Chongqing || this.city == Locations.NewTokyo ||
this.city == Locations.Ishima)) {
console.log("invited");
invitedFactions.push(tiandihuiFac);
}
@ -521,26 +549,19 @@ leaveFaction = function(faction) {
displayFactionContent = function(factionName) {
var faction = Factions[factionName];
document.getElementById("faction-name").innerHTML = factionName;
document.getElementById("faction-info").innerHTML = faction.info;
document.getElementById("faction-info").innerHTML = "<i>" + faction.info + "</i>";
document.getElementById("faction-reputation").innerHTML = "Reputation: " + formatNumber(faction.playerReputation, 4);
var hackDiv = document.getElementById("faction-hack-div");
var fieldWorkDiv = document.getElementById("faction-fieldwork-div");
var securityWorkDiv = document.getElementById("faction-securitywork-div");
var hackButton = document.getElementById("faction-hack-button");
var fieldWorkButton = document.getElementById("faction-fieldwork-button");
var securityWorkButton = document.getElementById("faction-securitywork-button");
//Set new event listener for all of the work buttons
//The old buttons need to be replaced to clear the old event listeners
var newHackButton = hackButton.cloneNode(true);
var newFieldWorkButton = fieldWorkButton.cloneNode(true);
var newSecurityWorkButton = securityWorkButton.cloneNode(true);
var newHackButton = clearEventListeners("faction-hack-button");
var newFieldWorkButton = clearEventListeners("faction-fieldwork-button");
var newSecurityWorkButton = clearEventListeners("faction-securitywork-button");
hackButton.parentNode.replaceChild(newHackButton, hackButton);
fieldWorkButton.parentNode.replaceChild(newFieldWorkButton, fieldWorkButton);
securityWorkButton.parentNode.replaceChild(newSecurityWorkButton, securityWorkButton);
newHackButton.addEventListener("click", function() {
Player.startFactionHackWork(faction);
@ -560,17 +581,13 @@ displayFactionContent = function(factionName) {
//Set new event listener for the purchase augmentation buttons
//The old button needs to be replaced to clear the old event listeners
var purchaseAugmentations = document.getElementById("faction-purchase-augmentations");
var newPurchaseAugmentationsButton = purchaseAugmentations.cloneNode(true);
purchaseAugmentations.parentNode.replaceChild(newPurchaseAugmentationsButton, purchaseAugmentations);
var newPurchaseAugmentationsButton = clearEventListeners("faction-purchase-augmentations");
newPurchaseAugmentationsButton.addEventListener("click", function() {
Engine.hideAllContent();
Engine.Display.factionAugmentationsContent.style.visibility = "visible";
var backButton = document.getElementById("faction-augmentations-back-button");
var newBackButton = backButton.cloneNode(true);
backButton.parentNode.replaceChild(newBackButton, backButton);
var newBackButton = clearEventListeners("faction-augmentations-back-button");
newBackButton.addEventListener("click", function() {
Engine.loadFactionContent();
displayFactionContent(factionName);
@ -706,10 +723,22 @@ displayFactionContent = function(factionName) {
hackDiv.style.display = "inline";
fieldWorkDiv.style.display = "inline";
securityWorkDiv.style.display = "none";
break;
case "Tetrads":
hackDiv.style.display = "none";
fieldWorkDiv.style.display = "inline";
securityWorkDiv.style.display = "inline";
break;
case "Slum Snakes":
hackDiv.style.display = "none";
fieldWorkDiv.style.display = "inline";
securityWorkDiv.style.display = "inline";
break;
case "Netburners":
hackDiv.style.display = "inline";
fieldWorkDiv.style.display = "none";
securityWorkDiv.style.display = "none";
break;
case "Tian Di Hui":
hackDiv.style.display = "inline";
fieldWorkDiv.style.display = "none";
@ -730,8 +759,9 @@ displayFactionContent = function(factionName) {
}
displayFactionAugmentations = function(factionName) {
document.getElementById("faction-augmentations-page-desc").innerHTML = "Lists all augmentations that are available to purchase from" + factionName;
document.getElementById("faction-augmentations-page-desc").innerHTML = "Lists all augmentations that are available to purchase from " + factionName;
var faction = Factions[factionName];
console.log("fac augs: " + faction.augmentations);
var augmentationsList = document.getElementById("faction-augmentations-list");
while (augmentationsList.firstChild) {
@ -747,21 +777,27 @@ displayFactionAugmentations = function(factionName) {
var pElem = document.createElement("p");
aElem.setAttribute("href", "#");
var req = aug.baseRepRequirement * faction.augmentationRepRequirementMult;
if (faction.playerReputation >= req) {
aElem.setAttribute("class", "a-link-button");
if (aug.name != AugmentationNames.NeuroFluxGovernor && aug.owned) {
aElem.setAttribute("class", "a-link-button-inactive tooltip");
pElem.innerHTML = "ALREADY OWNED";
} else if (faction.playerReputation >= req) {
aElem.setAttribute("class", "a-link-button tooltip");
pElem.innerHTML = "UNLOCKED - $" + formatNumber(aug.baseCost * faction.augmentationPriceMult, 2);
//TODO Event listener for button to purchase augmentation
} else {
aElem.setAttribute("class", "a-link-button-inactive");
aElem.setAttribute("class", "a-link-button-inactive tooltip");
pElem.innerHTML = "LOCKED (Requires " + formatNumber(req, 4) + " faction reputation)";
pElem.style.color = "red";
}
aElem.style.display = "inline-block";
pElem.style.display = "inline-block";
aElem.innerHTML = aug.name;
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
aElem.innerHTML += " - Level " + (aug.level + 1);
}
aElem.innerHTML += '<span class="tooltiptext">' + aug.info + " </span>";
aElem.addEventListener("click", function() {
console.log("here");
purchaseAugmentationBoxCreate(aug, faction);
});
@ -776,7 +812,7 @@ displayFactionAugmentations = function(factionName) {
}
function processPassiveFactionRepGain(numCycles) {
var numTimesGain = numCycles / 600;
var numTimesGain = (numCycles / 600) * Player.faction_rep_mult;
for (var name in Factions) {
if (Factions.hasOwnProperty(name)) {
var faction = Factions[name];

@ -2,17 +2,17 @@
//of each faction
FactionInfo = {
//Endgame
IlluminatiInfo: "Humanity never changes. No matter how civilized society becomes, it will eventually fall back\n" +
"into chaos. And out of this chaos, we will lead them to order.\n" +
IlluminatiInfo: "Humanity never changes. No matter how civilized society becomes, it will eventually fall back " +
"into chaos. And out of this chaos, we will lead them to order. <br><br>" +
"We are the Invisible Hand. We are forever.",
DaedalusInfo: "If all of human \n" +
"history is but a single lesson, it is that the individual may be remembered, but the organization \n" +
"persists and thrives. A single artist, a single general, a single hero or a single villain may all die,\n" +
"but it is impossible to kill a people, a nation, an idea -- except when that idea has grown weak and is \n" +
"overpowered by one that is stronger. -- The Doctrine of the Mighty\n\n" +
"Surrender yourself. Give up your empty individuality to become part of something great, something eternal.\n" +
"Become a slave. Submit your mind, body, and soul. Only then can you set yourself free.\n\n" +
DaedalusInfo: "If all of human " +
"history is but a single lesson, it is that the individual may be remembered, but the organization " +
"persists and thrives. A single artist, a single general, a single hero or a single villain may all die, " +
"but it is impossible to kill a people, a nation, an idea -- except when that idea has grown weak and is " +
"overpowered by one that is stronger. -- The Doctrine of the Mighty<br><br>" +
"Surrender yourself. Give up your empty individuality to become part of something great, something eternal. " +
"Become a slave. Submit your mind, body, and soul. Only then can you set yourself free.<br><br> " +
"Only then can you discover immortality.",
CovenantInfo: "Yesterday we obeyed kings and bent our necks to emperors. Today we kneel only to truth.",
@ -25,9 +25,10 @@ FactionInfo = {
MegaCorpInfo: "MegaCorp does things that others don't. We imagine. We create. We invent. We build things that\n" +
"others have never even dreamed of. Our work fills the world's needs for food, water, power, and\n" +
"transporation on an unprecendented scale, in ways that no other company can.\n\n" +
"In its labs and factories and on the ground with customers, MegaCorp is ushering in a new era for the world.",
"In our labs and factories and on the ground with customers, MegaCorp is ushering in a new era for the world.",
BachmanAndAssociatesInfo: "TODO",
BachmanAndAssociatesInfo: "Where Law and Business meet - thats where we are. <br><br>" +
"Legal Insight - Business Instinct - Experience Innovation",
BladeIndustriesInfo: "TODO",
@ -39,7 +40,7 @@ FactionInfo = {
FourSigmaInfo: "TODO",
KuaiGongInternationalInfo: "TODO",
KuaiGongInternationalInfo: "Dream big. Work hard. Make history.",
//Other Corporations
FulcrumSecretTechnologiesInfo: "TODO",
@ -113,9 +114,15 @@ FactionInfo = {
SilhouetteInfo: "Corporations are so big, you don't even know who you're working for. That's terror. Terror built into the system.",
TetradsInfo: "Following the Mandate of HEaven and Carrying out the way",
SlumSnakesInfo: "Slum Snakes rule!",
//Earlygame factions - factions the player will prestige with early on that don't
//belong in other categories
NetburnersInfo: "~~HACKNET BURNERS~~",
NetburnersInfo: "~~//*>H4CK|\|3T 8URN3R5**>?>\\~~",
TianDiHuiInfo: "Obey Heaven and Work Righteousness",
CyberSecInfo: "The Internet is the first thing that humanity has built that humanity doesnt understand,\n" +

@ -16,19 +16,21 @@ HacknetNode.prototype.updateMoneyGainRate = function() {
//How much extra $/s is gained per level
var gainPerLevel = CONSTANTS.HacknetNodeMoneyGainPerLevel;
//Each CPU core doubles the speed. Every 1GB of ram adds 10% increase
//Each CPU core doubles the speed. Every 1GB of ram adds 20% increase
this.moneyGainRatePerSecond = (this.level * gainPerLevel) *
Math.pow(1.1, this.ram-1) *
Math.pow(1.2, this.ram-1) *
this.numCores * Player.hacknet_node_money_mult;
if (isNaN(this.moneyGainRatePerSecond)) {
throw new Error("Money gain rate calculated for Hacknet Node is NaN");
}
updateTotalHacknetProduction();
}
HacknetNode.prototype.calculateLevelUpgradeCost = function() {
//Upgrade cost = Base cost * multiplier ^ level
var mult = CONSTANTS.HacknetNodeUpgradeLevelMult;
return CONSTANTS.BaseCostForHacknetNode * Math.pow(mult, this.level) * Player.hacknet_node_level_cost_mult;
return CONSTANTS.BaseCostForHacknetNode / 2 * Math.pow(mult, this.level) * Player.hacknet_node_level_cost_mult;
}
HacknetNode.prototype.purchaseLevelUpgrade = function() {
@ -46,7 +48,7 @@ HacknetNode.prototype.calculateRamUpgradeCost = function() {
//Calculate cost
//Base cost of RAM is 50k per 1GB...but lets have this increase by 10% for every time
//the RAM has been upgraded
var cost = this.ram * CONSTANTS.BaseCostFor1GBOfRam;
var cost = this.ram * CONSTANTS.BaseCostFor1GBOfRamHacknetNode;
var mult = Math.pow(CONSTANTS.HacknetNodeUpgradeRamMult, numUpgrades);
return cost * mult * Player.hacknet_node_ram_cost_mult;
}
@ -88,6 +90,17 @@ Reviver.constructors.HacknetNode = HacknetNode;
purchaseHacknet = function() {
/* INTERACTIVE TUTORIAL */
if (iTutorialIsRunning) {
if (currITutorialStep == iTutorialSteps.HacknetNodesIntroduction) {
iTutorialNextStep();
} else {
return;
}
}
/* END INTERACTIVE TUTORIAL */
var cost = getCostOfNextHacknetNode();
if (isNaN(cost)) {throw new Error("Cost is NaN"); return;}
if (cost > Player.money) {
@ -105,6 +118,16 @@ purchaseHacknet = function() {
Player.hacknetNodes.push(node);
displayHacknetNodesContent();
updateTotalHacknetProduction();
}
//Calculates the total production from all HacknetNodes
updateTotalHacknetProduction = function() {
var total = 0;
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
total += Player.hacknetNodes[i].moneyGainRatePerSecond;
}
Player.totalHacknetNodeProduction = total;
}
getCostOfNextHacknetNode = function() {
@ -117,9 +140,7 @@ getCostOfNextHacknetNode = function() {
//Creates Hacknet Node DOM elements when the page is opened
displayHacknetNodesContent = function() {
//Update Hacknet Nodes button
var purchaseButton = document.getElementById("hacknet-nodes-purchase-button");
var newPurchaseButton = purchaseButton.cloneNode(true);
purchaseButton.parentNode.replaceChild(newPurchaseButton, purchaseButton);
var newPurchaseButton = clearEventListeners("hacknet-nodes-purchase-button");
newPurchaseButton.addEventListener("click", function() {
purchaseHacknet();
@ -152,7 +173,9 @@ updateHacknetNodesContent = function() {
}
//Update player's money
document.getElementById("hacknet-nodes-money").innerHTML = "Money: $" + formatNumber(Player.money, 2);
var moneyElem = document.getElementById("hacknet-nodes-money");
moneyElem.innerHTML = "Money: $" + formatNumber(Player.money, 2) + "<br>" +
"Total production from all Hacknet Nodes: $" + formatNumber(Player.totalHacknetNodeProduction, 2);
//Update information in each owned hacknet node
for (var i = 0; i < Player.hacknetNodes.length; ++i) {

459
src/InteractiveTutorial.js Normal file

@ -0,0 +1,459 @@
/* InteractiveTutorial.js */
iTutorialSteps = {
Start: "Start",
GoToCharacterPage: "Click on the Character page menu link",
CharacterPage: "Introduction to Character page",
CharacterGoToTerminalPage: "Click on the Terminal link",
TerminalIntro: "Introduction to terminal interface",
TerminalHelp: "Using the help command to display all options in terminal",
TerminalLs: "Use the ls command to show all programs/scripts. Right now we have NUKE.exe",
TerminalScan: "Using the scan command to display all available connections",
TerminalConnect: "Using the telnet/connect command to connect to another server",
TerminalAnalyze: "Use the analyze command to display details about this server",
TerminalNuke: "Use the NUKE Program to gain root access to a server",
TerminalManualHack: "Use the hack command to manually hack a server",
TerminalCreateScript: "Create a script using nano",
TerminalTypeScript: "This occurs in the Script Editor page...type the script then save and close",
TerminalFree: "Use the free command to check RAM",
TerminalRunScript: "Use the run command to run a script",
TerminalGoToActiveScriptsPage: "Go to the ActiveScriptsPage",
ActiveScriptsPage: "Introduction to the Active Scripts Page",
ActiveScriptsToTerminal: "Go from Active Scripts Page Back to Terminal",
TerminalTailScript: "Use the tail command to show a script's logs",
GoToHacknetNodesPage: "Go to the Hacknet Nodes page",
HacknetNodesIntroduction: "Introduction to Hacknet Nodesm and have user purchase one",
HacknetNodesGoToWorldPage: "Go to the world page",
WorldDescription: "Tell the user to explore..theres a lot of different stuff to do out there",
TutorialPageInfo: "The tutorial page contains a lot of info on different subjects",
End: "End",
}
var currITutorialStep = iTutorialSteps.Start;
var iTutorialIsRunning = false;
function iTutorialStart() {
//Don't autosave during this interactive tutorial
Engine.Counters.autoSaveCounter = 999000000000;
console.log("Interactive Tutorial started");
currITutorialStep = iTutorialSteps.Start;
iTutorialIsRunning = true;
document.getElementById("interactive-tutorial-container").style.display = "block";
iTutorialEvaluateStep();
//Exit tutorial button
var exitButton = clearEventListeners("interactive-tutorial-exit");
exitButton.addEventListener("click", function() {
iTutorialEnd();
return false;
});
}
function iTutorialEvaluateStep() {
if (!iTutorialIsRunning) {console.log("Interactive Tutorial not running"); return;}
switch(currITutorialStep) {
case iTutorialSteps.Start:
iTutorialSetText("Welcome to Bitburner, a cyberpunk-themed incremental RPG! " +
"The game takes place in a dark, dystopian future...The year is 2077...<br><br>" +
"This tutorial will show you the basics of the game to help you get started. " +
"You may skip the tutorial at any time.");
var next = clearEventListeners("interactive-tutorial-next");
next.addEventListener("click", function() {
iTutorialNextStep();
return false;
});
break;
case iTutorialSteps.GoToCharacterPage:
iTutorialSetText("Let's start by heading to the Character page. Click the 'Character' tab on " +
"the main navigation menu (left-hand side of the screen)");
//No next button
var next = clearEventListeners("interactive-tutorial-next");
next.style.display = "none";
//Initialize everything necessary to open the "Character" page
var charaterMainMenuButton = document.getElementById("character-menu-link");
charaterMainMenuButton.addEventListener("click", function() {
Engine.loadCharacterContent();
iTutorialNextStep(); //Opening the character page will go to the next step
clearEventListeners("character-menu-link");
return false;
});
break;
case iTutorialSteps.CharacterPage:
iTutorialSetText("The Character page shows a lot of important information about your progress, " +
"such as your stats, skills, money, and bonuses/multipliers. ")
var next = clearEventListeners("interactive-tutorial-next");
next.style.display = "inline-block";
next.addEventListener("click", function() {
iTutorialNextStep();
return false;
});
break;
case iTutorialSteps.CharacterGoToTerminalPage:
iTutorialSetText("Let's head to your computer's terminal by clicking the 'Terminal' tab on the " +
"main navigation menu");
//No next button
var next = clearEventListeners("interactive-tutorial-next");
next.style.display = "none";
//Initialize everything necessary to open the 'Terminal' Page
var terminalMainMenuButton = document.getElementById("terminal-menu-link");
terminalMainMenuButton.addEventListener("click", function() {
Engine.loadTerminalContent();
iTutorialNextStep();
clearEventListeners("terminal-menu-link");
return false;
});
break;
case iTutorialSteps.TerminalIntro:
iTutorialSetText("The Terminal is used to interface with your home computer as well as " +
"all of the other machines around the world. A lot of content in the game is " +
"accessible only through the Terminal, and is necessary for progressing. ");
var next = clearEventListeners("interactive-tutorial-next");
next.style.display = "inline-block";
next.addEventListener("click", function() {
iTutorialNextStep();
return false;
});
break;
case iTutorialSteps.TerminalHelp:
iTutorialSetText("Let's try it out. Start by entering the 'help' command into the Terminal " +
"(Don't forget to press Enter after typing the command)");
var next = clearEventListeners("interactive-tutorial-next");
next.style.display = "none";
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalLs:
iTutorialSetText("The 'help' command displays a list of all available commands, how to use them, " +
"and a description of what they do. <br><br>Let's try another command. Enter the 'ls' command");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalScan:
iTutorialSetText("'ls' is a basic command that shows all of the contents (programs/scripts) " +
"on the computer. Right now, it shows that you have a program called 'NUKE.exe' on your computer. " +
"We'll get to what this does later. <br><br> Through your home computer's terminal, you can connect " +
"to other machines throughout the world. Let's do that now by first entering " +
"the 'scan' command (Alternatively, you can also enter the 'netstat' command " +
"which does the same thing). ");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalConnect:
iTutorialSetText("The 'scan/netstat' 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 " +
"the ip or the hostname, but dont use both. (Alternatively, " +
"the 'telnet [ip/hostname]' command does the same thing).<br><br>" +
"Let's try this now by connecting to the 'foodnstuff' server (connect foodnstuff)");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalAnalyze:
iTutorialSetText("You are now connected to another machine! What can you do now? You can hack it!<br><br> In the year 2077, currency has " +
"become digital and decentralized. People and corporations store their money " +
"on servers and computers. Using your hacking abilities, you can hack servers " +
"to steal money and gain experience. <br><br> " +
"Before you try to hack a server, you should run diagnostics using the 'analyze' command");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalNuke:
iTutorialSetText("When the 'analyze' command finishes running it will show useful information " +
"about hacking the server. <br><br> For this server, the required hacking skill is only 1, " +
"which means you are able to hack it right now. However, in order to hack a server " +
"you must first gain root access. The 'NUKE.exe' program that we saw earlier on your " +
"home computer is a virus that will grant you root access to a machine if there are enough " +
"open ports.<br><br> The 'analyze' results shows that there do not need to be any open ports " +
"on this machine for the NUKE virus to work, so go ahead and run the virus using the " +
"'run NUKE.exe' command.");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalManualHack:
iTutorialSetText("You now have root access! You can hack the server using the 'hack' command. " +
"Try doing that now. ");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalCreateScript:
iTutorialSetText("You are now attempting to hack the server. Note that performing a hack takes time and " +
"only has a certain percentage chance " +
"of success. This time and percentage is determined by a variety of factors, including " +
"your hacking skill and the server's security level. <br><br>" +
"Hacking is the core mechanic of the game and is necessary for progressing. However, " +
"you don't want to be hacking manually the entire time. You can automate your hacking " +
"by writing scripts! <br><br>To create a new script or edit an existing one, you can use the 'nano' " +
"command. Scripts must end with the '.script' extension. Let's make a script now by " +
"entering 'nano foodnstuff.script' after the hack command finishes running (Sidenote: Pressing ctrl + c" +
" will end a command like hack early)");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalTypeScript:
iTutorialSetText("This is the script editor. You can use it to program your scripts. Scripts are " +
"written in the Netscript language, a very simple programming language created for " +
"this game. There are details about the Netscript language in the documentation, which " +
"can be accessed in the 'Tutorial' tab on the main navigation menu. For now, just copy " +
"and paste the following code into the script editor: <br><br>" +
"while(true) { <br>" +
"hack('foodnstuff'); <br>" +
"}<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 left, or press ctrl + b.");
//next step triggered in saveAndCloseScriptEditor() (Script.js)
break;
case iTutorialSteps.TerminalFree:
iTutorialSetText("Now we'll run the script. Scripts require a certain amount of RAM to run, and can be " +
"run on any machine which you have root access to. Different servers have different " +
"amounts of RAM. You can also purchase more RAM for your home server. <br><br> To check how much " +
"RAM is available on this machine, enter the 'free' command.");
//next step triggered by terminal commmand
break;
case iTutorialSteps.TerminalRunScript:
iTutorialSetText("We have 2GB of free RAM on this machine, which is enough to run our " +
"script. Let's run our script using 'run foodnstuff.script'.");
//next step triggered by terminal commmand
break;
case iTutorialSteps.TerminalGoToActiveScriptsPage:
iTutorialSetText("Your script is now running! The script might take a few seconds to 'fully start up'. " +
"Your scripts will continuously run in the background and will automatically stop if " +
"the code ever completes (the 'foodnstuff.script' will never complete because it " +
"runs an infinite loop). <br><br>These scripts will passively earn you income and hacking experience. " +
"Your scripts will also earn money and experience while you are offline, although at a " +
"much slower rate. <br><br> " +
"Let's check out some statistics of our active, running scripts by clicking the " +
"'Active Scripts' link in the main navigation menu. ");
var activeScriptsMainMenuButton = document.getElementById("active-scripts-menu-link");
activeScriptsMainMenuButton.addEventListener("click", function() {
Engine.loadActiveScriptsContent();
iTutorialNextStep();
clearEventListeners("active-scripts-menu-link");
return false;
});
break;
case iTutorialSteps.ActiveScriptsPage:
iTutorialSetText("This page displays stats/information about all of your scripts that are " +
"running across every existing server. You can use this to gauge how well " +
"your scripts are doing. Let's go back to the Terminal now using the 'Terminal'" +
"link.");
//Initialize everything necessary to open the 'Terminal' Page
var terminalMainMenuButton = clearEventListeners("terminal-menu-link");
terminalMainMenuButton.addEventListener("click", function() {
Engine.loadTerminalContent();
iTutorialNextStep();
clearEventListeners("terminal-menu-link");
return false;
});
break;
case iTutorialSteps.ActiveScriptsToTerminal:
iTutorialSetText("One last thing about scripts, each active script contains logs that detail " +
"what it's doing. We can check these logs using the 'tail' command. Do that " +
"now for the script we just ran by typing 'tail foodnstuff.script'");
//next step triggered by terminal command
break;
case iTutorialSteps.TerminalTailScript:
iTutorialSetText("The log for this script won't show much right now (it might show nothing at all) because it " +
"just started running...but check back again in a few minutes! <br><br>" +
"This pretty much covers the basics of hacking. To learn more about writing " +
"scripts using the Netscript language, select the 'Tutorial' link in the " +
"main navigation menu to look at the documentation. For now, let's move on " +
"to something else!");
var next = clearEventListeners("interactive-tutorial-next");
next.style.display = "inline-block";
next.addEventListener("click", function() {
iTutorialNextStep();
return false;
});
break;
case iTutorialSteps.GoToHacknetNodesPage:
iTutorialSetText("Hacking is not the only way to earn money. One other way to passively " +
"earn money is by purchasing and upgrading Hacknet Nodes. Let's go to " +
"the 'Hacknet Nodes' page through the main navigation menu now.");
var hacknetNodesButton = clearEventListeners("hacknet-nodes-menu-link");
var next = clearEventListeners("interactive-tutorial-next");
next.style.display = "none";
hacknetNodesButton.addEventListener("click", function() {
Engine.loadHacknetNodesContent();
iTutorialNextStep();
clearEventListeners("hacknet-nodes-menu-link");
return false;
});
break;
case iTutorialSteps.HacknetNodesIntroduction:
iTutorialSetText("From this page you can purchase new Hacknet Nodes and upgrade your " +
"existing ones. Let's purchase a new one now.");
//Next step triggered by purchaseHacknet() (HacknetNode.js)
break;
case iTutorialSteps.HacknetNodesGoToWorldPage:
iTutorialSetText("You just purchase a Hacknet Node! This Hacknet Node will passively " +
"earn you money over time, both online and offline. When you get enough " +
" money, you can upgrade " +
"your newly-purchased Hacknet Node below. <br><br>" +
"Let's go to the 'World' page through the main navigation menu.");
var worldButton = clearEventListeners("world-menu-link");
worldButton.addEventListener("click", function() {
Engine.loadWorldContent();
iTutorialNextStep();
clearEventListeners("world-menu-link");
return false;
});
break;
case iTutorialSteps.WorldDescription:
iTutorialSetText("This page lists all of the different locations you can currently " +
"travel to. Each location has something that can you do. " +
"There's a lot of content out in the world, make sure " +
"you explore and discover!<br><br>" +
"Lastly, click on the 'Tutorial' link in the main navigation menu.");
var tutorialButton = clearEventListeners("tutorial-menu-link");
tutorialButton.addEventListener("click", function() {
Engine.loadTutorialContent();
iTutorialNextStep();
clearEventListeners("tutorial-menu-link");
return false;
});
break;
case iTutorialSteps.TutorialPageInfo:
iTutorialSetText("This page contains a lot of different documentation about the game's " +
"content and mechanics. If you have any questions about how something works " +
"make sure you check this out first. That's the end of the tutorial. " +
"Hope you enjoy the game!");
var next = clearEventListeners("interactive-tutorial-next");
next.style.display = "inline-block";
next.addEventListener("click", function() {
iTutorialNextStep();
return false;
});
break;
case iTutorialSteps.End:
iTutorialEnd();
break;
default:
throw new Error("Invalid tutorial step");
}
}
//Go to the next step and evaluate it
function iTutorialNextStep() {
switch(currITutorialStep) {
case iTutorialSteps.Start:
currITutorialStep = iTutorialSteps.GoToCharacterPage;
iTutorialEvaluateStep();
break;
case iTutorialSteps.GoToCharacterPage:
currITutorialStep = iTutorialSteps.CharacterPage;
iTutorialEvaluateStep();
break;
case iTutorialSteps.CharacterPage:
currITutorialStep = iTutorialSteps.CharacterGoToTerminalPage;
iTutorialEvaluateStep();
break;
case iTutorialSteps.CharacterGoToTerminalPage:
currITutorialStep = iTutorialSteps.TerminalIntro;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalIntro:
currITutorialStep = iTutorialSteps.TerminalHelp;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalHelp:
currITutorialStep = iTutorialSteps.TerminalLs;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalLs:
currITutorialStep = iTutorialSteps.TerminalScan;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalScan:
currITutorialStep = iTutorialSteps.TerminalConnect;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalConnect:
currITutorialStep = iTutorialSteps.TerminalAnalyze;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalAnalyze:
currITutorialStep = iTutorialSteps.TerminalNuke;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalNuke:
currITutorialStep = iTutorialSteps.TerminalManualHack;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalManualHack:
currITutorialStep = iTutorialSteps.TerminalCreateScript;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalCreateScript:
currITutorialStep = iTutorialSteps.TerminalTypeScript;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalTypeScript:
currITutorialStep = iTutorialSteps.TerminalFree;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalFree:
currITutorialStep = iTutorialSteps.TerminalRunScript;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalRunScript:
currITutorialStep = iTutorialSteps.TerminalGoToActiveScriptsPage;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalGoToActiveScriptsPage:
currITutorialStep = iTutorialSteps.ActiveScriptsPage;
iTutorialEvaluateStep();
break;
case iTutorialSteps.ActiveScriptsPage:
currITutorialStep = iTutorialSteps.ActiveScriptsToTerminal;
iTutorialEvaluateStep();
break;
case iTutorialSteps.ActiveScriptsToTerminal:
currITutorialStep = iTutorialSteps.TerminalTailScript;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TerminalTailScript:
currITutorialStep = iTutorialSteps.GoToHacknetNodesPage;
iTutorialEvaluateStep();
break;
case iTutorialSteps.GoToHacknetNodesPage:
currITutorialStep = iTutorialSteps.HacknetNodesIntroduction;
iTutorialEvaluateStep();
break;
case iTutorialSteps.HacknetNodesIntroduction:
currITutorialStep = iTutorialSteps.HacknetNodesGoToWorldPage;
iTutorialEvaluateStep();
break;
case iTutorialSteps.HacknetNodesGoToWorldPage:
currITutorialStep = iTutorialSteps.WorldDescription;
iTutorialEvaluateStep();
break;
case iTutorialSteps.WorldDescription:
currITutorialStep = iTutorialSteps.TutorialPageInfo;
iTutorialEvaluateStep();
break;
case iTutorialSteps.TutorialPageInfo:
currITutorialStep = iTutorialSteps.End;
iTutorialEvaluateStep();
break;
case iTutorialSteps.End:
break;
default:
throw new Error("Invalid tutorial step");
}
}
function iTutorialEnd() {
//Re-enable auto save
Engine.Counters.autoSaveCounter = 1;
console.log("Ending interactive tutorial");
Engine.init();
currITutorialStep = iTutorialSteps.End;
iTutorialIsRunning = false;
document.getElementById("interactive-tutorial-container").style.display = "none";
}
function iTutorialSetText(txt) {
var textBox = document.getElementById("interactive-tutorial-text");
if (textBox == null) {throw new Error("Could not find text box"); return;}
textBox.innerHTML = txt;
}

@ -4,6 +4,7 @@
Locations = {
//Cities
Aevum: "Aevum",
//AevumDesc: ""
Chongqing: "Chongqing",
Sector12: "Sector-12",
NewTokyo: "New Tokyo",
@ -93,16 +94,20 @@ displayLocationContent = function() {
var locationInfo = document.getElementById("location-info");
var softwareJob = document.getElementById("location-software-job");
var softwareConsultantJob = document.getElementById("location-software-consultant-job")
var itJob = document.getElementById("location-it-job");
var securityEngineerJob = document.getElementById("location-security-engineer-job");
var networkEngineerJob = document.getElementById("location-network-engineer-job");
var businessJob = document.getElementById("location-business-job");
var businessConsultantJob = document.getElementById("location-business-consultant-job");
var securityJob = document.getElementById("location-security-job");
var agentJob = document.getElementById("location-agent-job");
var employeeJob = document.getElementById("location-employee-job");
var employeePartTimeJob = document.getElementById("location-parttime-employee-job");
var waiterJob = document.getElementById("location-waiter-job");
var waiterPartTimeJob = document.getElementById("location-parttime-waiter-job");
var work = document.getElementById("location-work");
var work = clearEventListeners("location-work");
var jobTitle = document.getElementById("location-job-title");
var jobReputation = document.getElementById("location-job-reputation");
@ -112,7 +117,7 @@ displayLocationContent = function() {
var gymTrainDex = document.getElementById("location-gym-train-dex");
var gymTrainAgi = document.getElementById("location-gym-train-agi");
var studyComputerScience= document.getElementById("location-study-computer-science");
var studyComputerScience = document.getElementById("location-study-computer-science");
var classDataStructures = document.getElementById("location-data-structures-class");
var classNetworks = document.getElementById("location-networks-class");
var classAlgorithms = document.getElementById("location-algorithms-class");
@ -147,7 +152,10 @@ displayLocationContent = function() {
var slumsDealDrugs = document.getElementById("location-slums-deal-drugs");
var slumsTrafficArms = document.getElementById("location-slums-traffic-arms");
var slumsHomicide = document.getElementById("location-slums-homicide");
var slumsGta = document.getElementById("location-slums-gta");
var slumsKidnap = document.getElementById("location-slums-kidnap");
var slumsAssassinate = document.getElementById("location-slums-assassinate");
var slumsHeist = document.getElementById("location-slums-heist");
var loc = Player.location;
@ -161,14 +169,18 @@ displayLocationContent = function() {
locationInfo.style.display = "block";
softwareJob.style.display = "none";
softwareConsultantJob.style.display = "none";
itJob.style.display = "none";
securityEngineerJob.style.display = "none";
networkEngineerJob.style.display = "none";
businessJob.style.display = "none";
businessConsultantJob.style.display = "none";
securityJob.style.display = "none";
agentJob.style.display = "none";
employeeJob.style.display = "none";
employeePartTimeJob.style.display = "none";
waiterJob.style.display = "none";
waiterPartTimeJob.style.display = "none";
softwareJob.innerHTML = "Apply for Software Job";
itJob.innerHTML = "Apply for IT Job";
@ -222,7 +234,10 @@ displayLocationContent = function() {
slumsDealDrugs.style.display = "none";
slumsTrafficArms.style.display = "none";
slumsHomicide.style.display = "none";
slumsGta.style.display = "none";
slumsKidnap.style.display = "none";
slumsAssassinate.style.display = "none";
slumsHeist.style.display = "none";
//Check if the player is employed at this Location. If he is, display the "Work" button,
//update the job title, etc.
@ -235,16 +250,22 @@ displayLocationContent = function() {
jobReputation.innerHTML = "Company reputation: " + (company.playerReputation.toFixed(4)).toLocaleString();
work.style.display = "block";
var currPos = Player.companyPosition;
work.addEventListener("click", function() {
if (currPos.isPartTimeJob()) {
Player.startWorkPartTime();
} else {
Player.startWork();
}
return false;
});
var currPos = Player.companyPosition;
//Change the text for the corresponding position from "Apply for X Job" to "Apply for promotion"
if (currPos.isSoftwareJob()) {
softwareJob.innerHTML = "Apply for a promotion (Software)";
} else if (currPos.isSoftwareConsultantJob()) {
softwareConsultantJob.innerHTML = "Apply for a promotion (Software Consultant)";
} else if (currPos.isITJob()) {
itJob.innerHTML = "Apply for a promotion (IT)";
} else if (currPos.isSecurityEngineerJob()) {
@ -253,6 +274,8 @@ displayLocationContent = function() {
networkEngineerJob.innerHTML = "Apply for a promotion (Network Engineer)";
} else if (currPos.isBusinessJob()) {
businessJob.innerHTML = "Apply for a promotion (Business)";
} else if (currPos.isBusinessConsultantJob()) {
businessConsultantJob.innerHTML = "Apply for a promotion (Business Consultant)";
} else if (currPos.isSecurityJob()) {
securityJob.innerHTML = "Apply for a promotion (Security)";
} else if (currPos.isAgentJob()) {
@ -274,8 +297,7 @@ displayLocationContent = function() {
break;
case Locations.AevumSummitUniveristy:
var costMult = 3;
var expMult = 2;
var costMult = 4, expMult = 3;
displayUniversityLocationContent(costMult);
setUniversityLocationButtons(costMult, expMult);
break;
@ -352,6 +374,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -362,6 +385,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -387,6 +411,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -400,17 +425,15 @@ displayLocationContent = function() {
break;
case Locations.AevumCrushFitnessGym:
gymTrainStr.style.display = "block";
gymTrainDef.style.display = "block";
gymTrainDex.style.display = "block";
gymTrainAgi.style.display = "block";
var costMult = 2, expMult = 1.5;
displayGymLocationContent(costMult);
setGymLocationButtons(costMult, expMult);
break;
case Locations.AevumSnapFitnessGym:
gymTrainStr.style.display = "block";
gymTrainDef.style.display = "block";
gymTrainDex.style.display = "block";
gymTrainAgi.style.display = "block";
var costMult = 6, expMult = 4;
displayGymLocationContent(costMult);
setGymLocationButtons(costMult, expMult);
break;
case Locations.ChongqingTravelAgency:
@ -455,8 +478,7 @@ displayLocationContent = function() {
break;
case Locations.Sector12RothmanUniversity:
var costMult = 2;
var expMult = 1;
var costMult = 3, expMult = 2;
displayUniversityLocationContent(costMult);
setUniversityLocationButtons(costMult, expMult);
break;
@ -498,6 +520,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -508,6 +531,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -551,6 +575,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
businessJob.style.display = "block";
purchase1gb.style.display = "block";
purchase2gb.style.display = "block";
@ -563,6 +588,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -574,26 +600,26 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
employeeJob.style.display = "block";
employeePartTimeJob.style.display = "block";
break;
case Locations.Sector12JoesGuns:
locationInfo.innerHTML = Companies[loc].info;
employeeJob.style.display = "block";
employeePartTimeJob.style.display = "block";
break;
case Locations.Sector12IronGym:
gymTrainStr.style.display = "block";
gymTrainDef.style.display = "block";
gymTrainDex.style.display = "block";
gymTrainAgi.style.display = "block";
var costMult = 1, expMult = 1;
displayGymLocationContent(costMult);
setGymLocationButtons(costMult, expMult);
break;
case Locations.Sector12PowerhouseGym:
gymTrainStr.style.display = "block";
gymTrainDef.style.display = "block";
gymTrainDex.style.display = "block";
gymTrainAgi.style.display = "block";
var costMult = 10, expMult = 7.5;
displayGymLocationContent(costMult);
setGymLocationButtons(costMult, expMult);
break;
case Locations.NewTokyoTravelAgency:
@ -609,6 +635,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -619,6 +646,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -629,6 +657,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -640,6 +669,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
waiterJob.style.display = "block";
waitPartTimeJob.style.display = "block";
break;
@ -656,6 +686,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -676,6 +707,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -686,6 +718,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
businessJob.style.display = "block";
@ -707,8 +740,7 @@ displayLocationContent = function() {
break;
case Locations.VolhavenZBInstituteOfTechnology:
var costMult = 4;
var expMult = 3;
var costMult = 5, expMult = 4;
displayUniversityLocationContent(costMult);
setUniversityLocationButtons(costMult, expMult);
break;
@ -744,6 +776,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -765,6 +798,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -785,6 +819,7 @@ displayLocationContent = function() {
locationInfo.innerHTML = Companies[loc].info;
softwareJob.style.display = "block";
softwareConsultantJob.style.display = "block";
itJob.style.display = "block";
securityEngineerJob.style.display = "block";
networkEngineerJob.style.display = "block";
@ -800,10 +835,9 @@ displayLocationContent = function() {
break;
case Locations.VolhavenMilleniumFitnessGym:
gymTrainStr.style.display = "block";
gymTrainDef.style.display = "block";
gymTrainDex.style.display = "block";
gymTrainAgi.style.display = "block";
var costMult = 3, expMult = 2.5;
displayGymLocationContent(costMult);
setGymLocationButtons(costMult, expMult);
break;
//All Slums
@ -818,22 +852,39 @@ displayLocationContent = function() {
var drugsChance = determineCrimeChanceDealDrugs();
var armsChance = determineCrimeChanceTraffickArms();
var homicideChance = determineCrimeChanceHomicide();
var gtaChance = determineCrimeChanceGrandTheftAuto();
var kidnapChance = determineCrimeChanceKidnap();
var assassinateChance = determineCrimeChanceAssassination();
var heistChance = determineCrimeChanceHeist();
slumsDescText.style.display = "block";
slumsShoplift.style.display = "block";
slumsShoplift.innerHTML = "Shoplift (" + (shopliftChance*100).toFixed(3) + "% chance of success)";
slumsShoplift.innerHTML += '<span class="tooltiptext"> Attempt to shoplift from a low-end retailers </span>';
slumsMug.style.display = "block";
slumsMug.innerHTML = "Mug someone (" + (mugChance*100).toFixed(3) + "% chance of success)";
slumsMug.innerHTML += '<span class="tooltiptext"> Attempt to mug a random person on the street </span>';
slumsDealDrugs.style.display = "block";
slumsDealDrugs.innerHTML = "Deal Drugs (" + (drugsChance*100).toFixed(3) + "% chance of success)";
slumsDealDrugs.innerHTML += '<span class="tooltiptext"> Attempt to deal drugs </span>';
slumsTrafficArms.style.display = "block";
slumsTrafficArms.innerHTML = "Traffick Illegal Arms (" + (armsChance*100).toFixed(3) + "% chance of success)";
slumsTrafficArms.innerHTML += '<span class="tooltiptext"> Attempt to smuggle illegal arms into the city and sell them to gangs and criminal organizations </span>';
slumsHomicide.style.display = "block";
slumsHomicide.innerHTML = "Homicide (" + (homicideChance*100).toFixed(3) + "% chance of success)";
slumsHomicide.innerHTML += '<span class="tooltiptext"> Attempt to murder a random person on the street</span>';
slumsGta.style.display = "block";
slumsGta.innerHTML = "Grand Theft Auto (" + (gtaChance*100).toFixed(3) + "% chance of success)";
slumsGta.innerHTML += '<span class="tooltiptext"> Attempt to commit grand theft auto </span>';
slumsKidnap.style.display = "block";
slumsKidnap.innerHTML = "Kidnap and Ransom (" + (kidnapChance*100).toFixed(3) + "% chance of success)";
slumsKidnap.innerHTML += '<span class="tooltiptext"> Attempt to kidnap and ransom a high-profile target </span>';
slumsAssassinate.style.display = "block";
slumsAssassinate.innerHTML = "Assassinate (" + (assassinateChance*100).toFixed(3) + "% chance of success)";
slumsAssassinate.innerHTML += '<span class="tooltiptext"> Attempt to assassinate a high-profile target </span>';
slumsHeist.style.display = "block";
slumsHeist.innerHTML = "Heist (" + (heistChance*100).toFixed(3) + "% chance of success)";
slumsHeist.innerHTML += '<span class="tooltiptext"> Attempt to pull off the ultimate heist </span>';
break;
default:
console.log("ERROR: INVALID LOCATION");
@ -841,6 +892,7 @@ displayLocationContent = function() {
}
//Make the "Apply to be Employee and Waiter" texts disappear if you already hold the job
//Includes part-time stuff
if (loc == Player.companyName) {
var currPos = Player.companyPosition;
@ -848,6 +900,10 @@ displayLocationContent = function() {
employeeJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.Waiter.positionName) {
waiterJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.PartTimeEmployee.positionName) {
employeePartTimeJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.PartTimeWaiter.positionName) {
waiterPartTimeJob.style.display = "none";
}
}
}
@ -1264,22 +1320,21 @@ initLocationButtons = function() {
//Buttons to interact at a location (apply for job/promotion, train, purchase, etc.)
var softwareJob = document.getElementById("location-software-job");
var softwareConsultantJob = document.getElementById("location-software-consultant-job")
var itJob = document.getElementById("location-it-job");
var securityEngineerJob = document.getElementById("location-security-engineer-job");
var networkEngineerJob = document.getElementById("location-network-engineer-job");
var businessJob = document.getElementById("location-business-job");
var businessConsultantJob = document.getElementById("location-business-consultant-job");
var securityJob = document.getElementById("location-security-job");
var agentJob = document.getElementById("location-agent-job");
var employeeJob = document.getElementById("location-employee-job");
var employeePartTimeJob = document.getElementById("location-parttime-employee-job");
var waiterJob = document.getElementById("location-waiter-job");
var waiterPartTimeJob = document.getElementById("location-parttime-waiter-job");
var work = document.getElementById("location-work");
var gymTrainStr = document.getElementById("location-gym-train-str");
var gymTrainDef = document.getElementById("location-gym-train-def");
var gymTrainDex = document.getElementById("location-gym-train-dex");
var gymTrainAgi = document.getElementById("location-gym-train-agi");
var purchase1gb = document.getElementById("location-purchase-1gb");
var purchase2gb = document.getElementById("location-purchase-2gb");
var purchase4gb = document.getElementById("location-purchase-4gb");
@ -1306,13 +1361,21 @@ initLocationButtons = function() {
var slumsDealDrugs = document.getElementById("location-slums-deal-drugs");
var slumsTrafficArms = document.getElementById("location-slums-traffic-arms");
var slumsHomicide = document.getElementById("location-slums-homicide");
var slumsGta = document.getElementById("location-slums-gta");
var slumsKidnap = document.getElementById("location-slums-kidnap");
var slumsAssassinate = document.getElementById("location-slums-assassinate");
var slumsHeist = document.getElementById("location-slums-heist");
softwareJob.addEventListener("click", function() {
Player.applyForSoftwareJob();
return false;
});
softwareConsultantJob.addEventListener("click", function() {
Player.applyForSoftwareConsultantJob();
return false;
});
itJob.addEventListener("click", function() {
Player.applyForSoftwareJob()
return false;
@ -1333,6 +1396,11 @@ initLocationButtons = function() {
return false;
});
businessConsultantJob.addEventListener("click", function() {
Player.applyForBusinessConsultantJob();
return false;
});
securityJob.addEventListener("click", function() {
Player.applyForSecurityJob();
return false;
@ -1348,63 +1416,73 @@ initLocationButtons = function() {
return false;
});
employeePartTimeJob.addEventListener("click", function() {
Player.applyForPartTimeEmployeeJob();
return false;
});
waiterJob.addEventListener("click", function() {
Player.applyForWaiterJob();
return false;
});
waiterPartTimeJob.addEventListener("click", function() {
Player.applyForPartTimeWaiterJob();
return false;
});
purchase1gb.addEventListener("click", function() {
purchaseServerBoxCreate(1, 50000);
purchaseServerBoxCreate(1, 1 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase2gb.addEventListener("click", function() {
purchaseServerBoxCreate(2, 100000);
purchaseServerBoxCreate(2, 2 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase4gb.addEventListener("click", function() {
purchaseServerBoxCreate(4, 250000);
purchaseServerBoxCreate(4, 4 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase8gb.addEventListener("click", function() {
purchaseServerBoxCreate(8, 1000000);
purchaseServerBoxCreate(8, 8 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase16gb.addEventListener("click", function() {
purchaseServerBoxCreate(16, 4000000);
purchaseServerBoxCreate(16, 16 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase32gb.addEventListener("click", function() {
purchaseServerBoxCreate(32, 10000000);
purchaseServerBoxCreate(32, 32 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase64gb.addEventListener("click", function() {
purchaseServerBoxCreate(64, 20000000);
purchaseServerBoxCreate(64, 64 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase128gb.addEventListener("click", function() {
purchaseServerBoxCreate(128, 50000000);
purchaseServerBoxCreate(128, 128 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase256gb.addEventListener("click", function() {
purchaseServerBoxCreate(256, 100000000);
purchaseServerBoxCreate(256, 256 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase512gb.addEventListener("click", function() {
purchaseServerBoxCreate(512, 250000000);
purchaseServerBoxCreate(512, 512 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
purchase1tb.addEventListener("click", function() {
purchaseServerBoxCreate(1024, 750000000);
purchaseServerBoxCreate(1024, 1024 * CONSTANTS.BaseCostFor1GBOfRamServer);
return false;
});
@ -1419,32 +1497,32 @@ initLocationButtons = function() {
});
travelToAevum.addEventListener("click", function() {
travelBoxCreate(Locations.Aevum, 1000000);
travelBoxCreate(Locations.Aevum, 200000);
return false;
});
travelToChongqing.addEventListener("click", function() {
travelBoxCreate(Locations.Chongqing, 1000000);
travelBoxCreate(Locations.Chongqing, 200000);
return false;
});
travelToSector12.addEventListener("click", function() {
travelBoxCreate(Locations.Sector12, 1000000);
travelBoxCreate(Locations.Sector12, 200000);
return false;
});
travelToNewTokyo.addEventListener("click", function() {
travelBoxCreate(Locations.NewTokyo, 1000000);
travelBoxCreate(Locations.NewTokyo, 200000);
return false;
});
travelToIshima.addEventListener("click", function() {
travelBoxCreate(Locations.Ishima, 1000000);
travelBoxCreate(Locations.Ishima, 200000);
return false;
});
travelToVolhaven.addEventListener("click", function() {
travelBoxCreate(Locations.Volhaven, 1000000);
travelBoxCreate(Locations.Volhaven, 200000);
return false;
});
@ -1473,10 +1551,25 @@ initLocationButtons = function() {
return false;
});
slumsGta.addEventListener("click", function() {
commitGrandTheftAutoCrime();
return false;
});
slumsKidnap.addEventListener("click", function() {
commitKidnapCrime();
return false;
});
slumsAssassinate.addEventListener("click", function() {
commitAssassinationCrime();
return false;
});
slumsHeist.addEventListener("click", function() {
commitHeistCrime();
return false;
});
}
travelToCity = function(destCityName, cost) {
@ -1496,14 +1589,18 @@ purchaseTorRouter = function() {
dialogBoxCreate("You cannot afford to purchase the Tor router");
return;
}
Player.money -= CONSTANTS.TorRouterCost;
Player.loseMoney(CONSTANTS.TorRouterCost);
var darkweb = new Server();
darkweb.init(createRandomIp(), "darkweb", "", true, false, false, false, 1);
AddToAllServers(darkweb);
SpecialServerIps.addIp("Darkweb Server", darkweb.ip);
document.getElementById("location-purchase-tor").setAttribute("class", "a-link-button-inactive");
Player.getHomeComputer().serversOnNetwork.push(darkweb.ip);
dialogBoxCreate("You have purchased a Tor router!", "You now have access to the dark web from your home computer", "Use the scan/netstat commands to search for the dark web connect.", "");
darkweb.serversOnNetwork.push(Player.getHomeComputer().ip);
dialogBoxCreate("You have purchased a Tor router!", "You now have access to the dark web from your home computer", "Use the scan/netstat commands to search for the dark web connection.");
}
displayUniversityLocationContent = function(costMult) {
@ -1521,74 +1618,100 @@ displayUniversityLocationContent = function(costMult) {
classLeadershipButton.style.display = "block";
//Costs (per second)
var baseDataStructuresCost = 1;
var baseNetworksCost = 5;
var baseAlgorithmsCost = 20;
var baseManagementCost = 10;
var baseLeadershipCost = 20;
var dataStructuresCost = baseDataStructuresCost * costMult;
var networksCost = baseNetworksCost * costMult;
var algorithmsCost = baseAlgorithmsCost * costMult;
var managementCost = baseManagementCost * costMult;
var leadershipCost = baseLeadershipCost * costMult;
var dataStructuresCost = CONSTANTS.ClassDataStructuresBaseCost * costMult;
var networksCost = CONSTANTS.ClassNetworksBaseCost * costMult;
var algorithmsCost = CONSTANTS.ClassAlgorithmsBaseCost * costMult;
var managementCost = CONSTANTS.ClassManagementBaseCost * costMult;
var leadershipCost = CONSTANTS.ClassLeadershipBaseCost * costMult;
//Update button text to show cost
classDataStructuresButton.innerHTML = "Take Data Structures course ($" + dataStructuresCost + " / sec)";
classNetworksButton.innerHTML = "Take Networks course ($" + networksCost + " / second)";
classAlgorithmsButton.innerHTML = "Take Algorithms course ($" + algorithmsCost + " / second)";
classManagementButton.innerHTML = "Take Management course ($" + managementCost + " / second)";
classLeadershipButton.innerHTML = "Take Leadership course ($" + leadershipCost + " / second)";
classNetworksButton.innerHTML = "Take Networks course ($" + networksCost + " / sec)";
classAlgorithmsButton.innerHTML = "Take Algorithms course ($" + algorithmsCost + " / sec)";
classManagementButton.innerHTML = "Take Management course ($" + managementCost + " / sec)";
classLeadershipButton.innerHTML = "Take Leadership course ($" + leadershipCost + " / sec)";
}
setUniversityLocationButtons = function(costMult, expMult) {
var studyComputerScience= document.getElementById("location-study-computer-science");
var classDataStructures = document.getElementById("location-data-structures-class");
var classNetworks = document.getElementById("location-networks-class");
var classAlgorithms = document.getElementById("location-algorithms-class");
var classManagement = document.getElementById("location-management-class");
var classLeadership = document.getElementById("location-leadership-class");
var newStudyCS = studyComputerScience.cloneNode(true);
studyComputerScience.parentNode.replaceChild(newStudyCS, studyComputerScience)
var newStudyCS = clearEventListeners("location-study-computer-science");
newStudyCS.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassStudyComputerScience);
return false;
});
var newClassDataStructures = classDataStructures.cloneNode(true);
classDataStructures.parentNode.replaceChild(newClassDataStructures, classDataStructures);
var newClassDataStructures = clearEventListeners("location-data-structures-class");
newClassDataStructures.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassDataStructures);
return false;
});
var newClassNetworks = classNetworks.cloneNode(true);
classNetworks.parentNode.replaceChild(newClassNetworks, classNetworks);
var newClassNetworks = clearEventListeners("location-networks-class");
newClassNetworks.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassNetworks);
return false;
});
var newClassAlgorithms = classAlgorithms.cloneNode(true);
classAlgorithms.parentNode.replaceChild(newClassAlgorithms, classAlgorithms);
var newClassAlgorithms = clearEventListeners("location-algorithms-class");
newClassAlgorithms.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassAlgorithms);
return false;
});
var newClassManagement = classManagement.cloneNode(true);
classManagement.parentNode.replaceChild(newClassManagement, classManagement);
var newClassManagement = clearEventListeners("location-management-class");
newClassManagement.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassManagement);
return false;
});
var newClassLeadership = classLeadership.cloneNode(true);
classLeadership.parentNode.replaceChild(newClassLeadership, classLeadership);
var newClassLeadership = clearEventListeners("location-leadership-class");
newClassLeadership.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassLeadership);
return false;
});
}
displayGymLocationContent = function(costMult) {
var gymStrButton = document.getElementById("location-gym-train-str");
var gymDefButton = document.getElementById("location-gym-train-def");
var gymDexButton = document.getElementById("location-gym-train-dex");
var gymAgiButton = document.getElementById("location-gym-train-agi");
gymStrButton.style.display = "block";
gymDefButton.style.display = "block";
gymDexButton.style.display = "block";
gymAgiButton.style.display = "block";
//Costs (per second)
var cost = CONSTANTS.ClassGymBaseCost * costMult;
//Update button text to show cost
gymStrButton.innerHTML = "Train Strength ($" + cost + " / sec)";
gymDefButton.innerHTML = "Train Defense ($" + cost + " / sec)";
gymDexButton.innerHTML = "Train Dexterity ($" + cost + " / sec)";
gymAgiButton.innerHTML = "Train Agility ($" + cost + " / sec)";
}
setGymLocationButtons = function(costMult, expMult) {
var gymStr = clearEventListeners("location-gym-train-str");
gymStr.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassGymStrength);
return false;
});
var gymDef = clearEventListeners("location-gym-train-def");
gymDef.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassGymDefense);
return false;
});
var gymDex = clearEventListeners("location-gym-train-dex");
gymDex.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassGymDexterity);
return false;
});
var gymAgi = clearEventListeners("location-gym-train-agi");
gymAgi.addEventListener("click", function() {
Player.startClass(costMult, expMult, CONSTANTS.ClassGymAgility);
return false;
});
}

@ -33,10 +33,11 @@ function evaluate(exp, workerScript) {
//Can currently only assign to "var"s
case "assign":
return new Promise(function(resolve, reject) {
console.log("Evaluating assign");
if (env.stopFlag) {reject(workerScript);}
if (exp.left.type != "var")
throw new Error("|" + workerScript.serverIp + "|" + workerScript.name + "| Cannot assign to " + JSON.stringify(exp.left));
reject("|" + workerScript.serverIp + "|" + workerScript.name + "| Cannot assign to " + JSON.stringify(exp.left));
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
@ -53,9 +54,10 @@ function evaluate(exp, workerScript) {
try {
env.set(exp.left.value, expRight);
} catch (e) {
console.log("here");
throw new Error("|" + workerScript.serverIp + "|" + workerScript.name + "|" + e.toString());
}
resolve("assignFinished");
resolve(false); //Return false so this doesnt cause loops/ifs to evaluate
}, function(e) {
reject(e);
});
@ -105,21 +107,41 @@ function evaluate(exp, workerScript) {
//TODO
case "if":
return new Promise(function(resolve, reject) {
console.log("Evaluating if");
var numConds = exp.cond.length;
var numThens = exp.then.length;
if (numConds == 0 || numThens == 0 || numConds != numThens) {
console.log("Number of ifs and conds dont match. Rejecting");
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Number of conds and thens in if structure don't match (or there are none)");
}
for (var i = 0; i < numConds; i++) {
var cond = evaluate(exp.cond[i], workerScript);
if (cond) return evaluate(exp.then[i], workerScript);
var evalIfPromise = evaluateIf(exp, workerScript, 0);
evalIfPromise.then(function(res) {
if (res) {
//One of the if/elif statements evaluated to true
console.log("done with if");
resolve("if statement done");
} else {
//None of the if/elif statements were true. Evaluate else if there is one
if (exp.else) {
var elseEval = evaluate(exp.else, workerScript);
elseEval.then(function(res) {
console.log("if statement done with else");
resolve("if statement done with else");
}, function(e) {
reject(e);
});
} else {
console.log("no else statement, resolving");
resolve("if statement done");
}
//Evaluate else if it exists, snce none of the conditionals
//were true
return exp.else ? evaluate(exp.else, workerScript) : false;
}
}, function(e) {
reject(e);
});
});
break;
case "for":
return new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
@ -177,10 +199,16 @@ function evaluate(exp, workerScript) {
break;
/* Currently supported function calls:
* hack()
* hack(server)
* sleep(N) - sleep N seconds
* print(x) - Prints a variable or constant
*
* grow(server)
* nuke(server)
* brutessh(server)
* ftpcrack(server)
* relaysmtp(server)
* httpworm(server)
* sqlinject(server)
*/
case "call":
//Define only valid function calls here, like hack() and stuff
@ -196,23 +224,13 @@ function evaluate(exp, workerScript) {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Hack() call has incorrect number of arguments. Takes 1 argument");
}
//IP of server to hack
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
//Check if its a valid IP address. If it's not, assume its a hostname and
//try to get the server. If its not a server, there is an error
var server = null;
if (!isValidIPAddress(ip)) {
//It's not an IP address, so see if its a hostanme
server = GetServerByHostname(ip);
} else {
server = AllServers[ip];
}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into hack() command");
workerScript.scriptRef.log("Cannot hack(). Invalid IP or hostname passed in: " + ip);
workerScript.scriptRef.log("Cannot hack(). Invalid IP or hostname passed in: " + ip + ". Stopping...");
return;
}
@ -238,11 +256,13 @@ function evaluate(exp, workerScript) {
if (env.stopFlag) {reject(workerScript);}
console.log("Hacking " + server.hostname + " after " + hackingTime.toString() + " seconds.");
setTimeout(function() {
if (env.stopFlag) {reject(workerScript);}
var hackChance = scriptCalculateHackingChance(server);
var rand = Math.random();
var expGainedOnSuccess = scriptCalculateExpGain(server);
var expGainedOnFailure = Math.round(expGainedOnSuccess / 4);
var expGainedOnFailure = (expGainedOnSuccess / 4);
if (rand < hackChance) { //Success!
if (env.stopFlag) {reject(workerScript); return;}
var moneyGained = scriptCalculatePercentMoneyHacked(server);
moneyGained = Math.floor(server.moneyAvailable * moneyGained);
@ -252,19 +272,22 @@ function evaluate(exp, workerScript) {
server.moneyAvailable -= moneyGained;
Player.gainMoney(moneyGained);
workerScript.scriptRef.onlineMoneyMade += moneyGained;
console.log("About to add to moneystolenmap for " + server.hostname);
workerScript.scriptRef.moneyStolenMap[server.ip] += moneyGained;
Player.gainHackingExp(expGainedOnSuccess);
workerScript.scriptRef.onlineExpGained += expGainedOnSuccess;
console.log("Script successfully hacked " + server.hostname + " for $" + moneyGained + " and " + expGainedOnSuccess + " exp");
workerScript.scriptRef.log("Script SUCCESSFULLY hacked " + server.hostname + " for $" + moneyGained + " and " + expGainedOnSuccess + " exp");
console.log("Script successfully hacked " + server.hostname + " for $" + formatNumber(moneyGained, 2) + " and " + formatNumber(expGainedOnSuccess, 4) + " exp");
workerScript.scriptRef.log("Script SUCCESSFULLY hacked " + server.hostname + " for $" + formatNumber(moneyGained, 2) + " and " + formatNumber(expGainedOnSuccess, 4) + " exp");
resolve("Hack success");
} else {
if (env.stopFlag) {reject(workerScript); return;}
//Player only gains 25% exp for failure? TODO Can change this later to balance
Player.gainHackingExp(expGainedOnFailure);
workerScript.scriptRef.onlineExpGained += expGainedOnFailure;
console.log("Script unsuccessful to hack " + server.hostname + ". Gained " + expGainedOnFailure + " exp");
workerScript.scriptRef.log("Script FAILED to hack " + server.hostname + ". Gained " + expGainedOnFailure + " exp");
console.log("Script unsuccessful to hack " + server.hostname + ". Gained " + formatNumber(expGainedOnFailure, 4) + " exp");
workerScript.scriptRef.log("Script FAILED to hack " + server.hostname + ". Gained " + formatNumber(expGainedOnFailure, 4) + " exp");
resolve("Hack failure");
}
}, hackingTime * 1000);
@ -282,9 +305,7 @@ function evaluate(exp, workerScript) {
} else if (exp.func.value == "sleep") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|sleep() call has incorrect number of arguments. Takes 1 argument.");
return;
}
var sleepTimePromise = evaluate(exp.args[0], workerScript);
sleepTimePromise.then(function(sleepTime) {
workerScript.scriptRef.log("Sleeping for " + sleepTime + " milliseconds");
@ -328,20 +349,10 @@ function evaluate(exp, workerScript) {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|grow() call has incorrect number of arguments. Takes 1 argument");
}
//IP/hostname of server to hack
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
//Check if its a valid IP address. If it's not, assume its a hostname and
//try to get the server. If its not a server, there is an error
var server = null;
if (!isValidIPAddress(ip)) {
//It's not an IP address, so see if its a hostanme
server = GetServerByHostname(ip);
} else {
server = AllServers[ip];
}
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into grow() command");
workerScript.scriptRef.log("Cannot grow(). Invalid IP or hostname passed in: " + ip);
@ -358,7 +369,6 @@ function evaluate(exp, workerScript) {
workerScript.scriptRef.log("Calling grow() on server " + server.hostname + " in 120 seconds");
var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
console.log("Executing grow on " + server.hostname + " in 2 minutes ");
setTimeout(function() {
var growthPercentage = processSingleServerGrowth(server, 450);
resolve(growthPercentage);
@ -367,7 +377,259 @@ function evaluate(exp, workerScript) {
p.then(function(growthPercentage) {
resolve("hackExecuted");
workerScript.scriptRef.log("Using grow(), the money available on " + server.hostname + " was grown by " + (growthPercentage*100 - 100).toFixed(6) + "%");
workerScript.scriptRef.log("Using grow(), the money available on " + server.hostname + " was grown by " + (growthPercentage*100 - 100).toFixed(6) + "%. Gained 1 hacking exp");
Player.gainHackingExp(1);
workerScript.scriptRef.onlineExpGained += 1;
}, function(e) {
reject(e);
});
}, function(e) {
reject(e);
});
} else if (exp.func.value == "nuke") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|nuke() call has incorrect number of arguments. Takes 1 argument");
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into nuke() command");
workerScript.scriptRef.log("Cannot nuke(). Invalid IP or hostname passed in: " + ip);
return;
}
if (!Player.hasProgram(Programs.NukeProgram)) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Player does not have NUKE program on home computer");
return;
}
if (server.openPortCount < server.numOpenPortsRequired) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Not enough ports opened to use NUKE.exe virus");
return;
}
workerScript.scriptRef.log("Running NUKE.exe on server " + server.hostname + " in 5 seconds");
var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
if (server.hasAdminRights) {
workerScript.scriptRef.log("Already have root access to " + server.hostname);
} else {
server.hasAdminRights = true;
workerScript.scriptRef.log("Executed NUKE.exe virus on " + server.hostname + " to gain root access");
}
resolve("nuke done");
}, 5 * 1000);
});
p.then(function(res) {
resolve("nukeExecuted");
}, function(e) {
reject(e);
});
}, function(e) {
reject(e);
});
} else if (exp.func.value == "brutessh") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|brutessh() call has incorrect number of arguments. Takes 1 argument");
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into brutessh() command");
workerScript.scriptRef.log("Cannot brutessh(). Invalid IP or hostname passed in: " + ip);
return;
}
if (!Player.hasProgram(Programs.BruteSSHProgram)) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Player does not have BruteSSH.exe program on home computer");
return;
}
workerScript.scriptRef.log("Running BruteSSH.exe on server " + server.hostname + " in 10 seconds");
var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
if (!server.sshPortOpen) {
workerScript.scriptRef.log("Executed BruteSSH.exe virus on " + server.hostname + " to open SSH port (22)");
server.sshPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("SSH Port (22) already opened on " + server.hostname);
}
resolve("brutessh done");
}, 10 * 1000);
});
p.then(function(res) {
resolve("bruteSSHExecuted");
}, function(e) {
reject(e);
});
}, function(e) {
reject(e);
});
} else if (exp.func.value == "ftpcrack") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|ftpcrack() call has incorrect number of arguments. Takes 1 argument");
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into ftpcrack() command");
workerScript.scriptRef.log("Cannot ftpcrack(). Invalid IP or hostname passed in: " + ip);
return;
}
if (!Player.hasProgram(Programs.FTPCrackProgram)) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Player does not have FTPCrack.exe program on home computer");
return;
}
workerScript.scriptRef.log("Running FTPCrack.exe on server " + server.hostname + " in 15 seconds");
var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
if (!server.ftpPortOpen) {
workerScript.scriptRef.log("Executed FTPCrack.exe virus on " + server.hostname + " to open FTP port (21)");
server.ftpPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("FTP Port (21) already opened on " + server.hostname);
}
resolve("ftpcrack done");
}, 15 * 1000);
});
p.then(function(res) {
resolve("ftpcrackexecuted");
}, function(e) {
reject(e);
});
}, function(e) {
reject(e);
});
} else if (exp.func.value == "relaysmtp") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|relaysmtp() call has incorrect number of arguments. Takes 1 argument");
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into relaysmtp() command");
workerScript.scriptRef.log("Cannot relaysmtp(). Invalid IP or hostname passed in: " + ip);
return;
}
if (!Player.hasProgram(Programs.RelaySMTPProgram)) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Player does not have relaySMTP.exe program on home computer");
return;
}
workerScript.scriptRef.log("Running relaySMTP.exe on server " + server.hostname + " in 20 seconds");
var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
if (!server.smtpPortOpen) {
workerScript.scriptRef.log("Executed relaySMTP.exe virus on " + server.hostname + " to open SMTP port (25)");
server.smtpPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("SMTP Port (25) already opened on " + server.hostname);
}
resolve("relaysmtp done");
}, 20 * 1000);
});
p.then(function(res) {
resolve("relaysmtpexecuted");
}, function(e) {
reject(e);
});
}, function(e) {
reject(e);
});
} else if (exp.func.value == "httpworm") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|httpworm() call has incorrect number of arguments. Takes 1 argument");
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into relaysmtp() command");
workerScript.scriptRef.log("Cannot httpworm(). Invalid IP or hostname passed in: " + ip);
return;
}
if (!Player.hasProgram(Programs.HTTPWormProgram)) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Player does not have HTTPWorm.exe program on home computer");
return;
}
workerScript.scriptRef.log("Running HTTPWorm.exe on server " + server.hostname + " in 25 seconds");
var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
if (!server.httpPortOpen) {
workerScript.scriptRef.log("Executed HTTPWorm.exe virus on " + server.hostname + " to open HTTP port (25)");
server.httpPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("HTTP Port (80) already opened on " + server.hostname);
}
resolve("httpworm done");
}, 25 * 1000);
});
p.then(function(res) {
resolve("HTTPWormexecuted");
}, function(e) {
reject(e);
});
}, function(e) {
reject(e);
});
} else if (exp.func.value == "sqlinject") {
if (exp.args.length != 1) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|sqlinject() call has incorrect number of arguments. Takes 1 argument");
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into sqlinject() command");
workerScript.scriptRef.log("Cannot sqlinject(). Invalid IP or hostname passed in: " + ip);
return;
}
if (!Player.hasProgram(Programs.SQLInjectProgram)) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Player does not have SQLInject.exe program on home computer");
return;
}
workerScript.scriptRef.log("Running SQLInject.exe on server " + server.hostname + " in 30 seconds");
var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
if (!server.sqlPortOpen) {
workerScript.scriptRef.log("Executed SQLInject.exe virus on " + server.hostname + " to open SQL port (1433)");
server.sqlPortOpen = true;
++server.openPortCount;
} else {
workerScript.scriptRef.log("SQL Port (1433) already opened on " + server.hostname);
}
resolve("sqlinject done");
}, 30 * 1000);
});
p.then(function(res) {
resolve("sqlinjectexecuted");
}, function(e) {
reject(e);
});
@ -384,6 +646,48 @@ function evaluate(exp, workerScript) {
}
}
//Returns true if any of the if statements evaluated, false otherwise. Therefore, the else statement
//should evaluate if this returns false
function evaluateIf(exp, workerScript, i) {
var env = workerScript.env;
return new Promise(function(resolve, reject) {
if (i >= exp.cond.length) {
//Catch out of bounds errors
resolve(false);
} else {
console.log("Evaluating cond " + i + " in if");
var cond = evaluate(exp.cond[i], workerScript);
cond.then(function(condRes) {
console.log("cond evaluated to: " + condRes);
if (condRes) {
console.log("Evaluating then: " + exp.then[i]);
var evalThen = evaluate(exp.then[i], workerScript);
evalThen.then(function(res) {
console.log("If statement done");
resolve(true);
}, function(e) {
reject(e);
});
} else {
//If this if statement isnt true, go on the next elif, or recursively resolve
if (i == exp.cond.length-1) {
resolve(false);
} else {
var recursiveCall = evaluateIf(exp, workerScript, i+1);
recursiveCall.then(function(res) {
resolve(res);
}, function(e) {
reject(e);
});
}
}
}, function(e) {
reject(e);
});
}
});
}
//Evaluate the looping part of a for loop (Initialization block is NOT done in here)
function evaluateFor(exp, workerScript) {
var env = workerScript.env;
@ -599,7 +903,7 @@ function scriptCalculateHackingTime(server) {
//The same as Player's calculateExpGain() function but takes in the server as an argument
function scriptCalculateExpGain(server) {
return Math.round(server.hackDifficulty * Player.hacking_exp_mult);
return (server.hackDifficulty * Player.hacking_exp_mult);
}
//The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument

@ -114,9 +114,11 @@ function Parser(input) {
//Conditional
var cond = parse_expression();
console.log("cond: " + cond);
//Body
var then = parse_expression();
console.log("then: " + then);
var ret = {
type: "if",
cond: [],

@ -2,7 +2,7 @@
* Defines Perks that are unlocked when you gain enough reputation in a
* company or faction
*/
Perks = {
PerkNames = {
FreeCoffeeCompanyPerk: "Free Coffee",
FreeFoodCompanyPerk: "Free Food",
NetworkingCompanyPerk: "Networking",
@ -17,15 +17,38 @@ Perks = {
InsiderKnowledgeFactionPerk: "Insider Knowledge",
}
PerkInfo = {
FreeCoffee: "Your company provides free coffee, improving your focus " +
"and productivity",
FreeFood: "Your company provides free healthy and nutritious food",
NetworkingCompany: "Working at this company provides many opportunities to " +
"build your professional network!",
PersonalTrainer: "Your company provides a free personal trainer to help you train",
KnowledgeBase: "The company has a comprehensive knowledge base that " +
"you can use to learn",
Nootropics: "Your company provides free nootropics, cognitive-enhancing drugs",
NetworkingFaction: "Being a member of this faction provides many opportunities to " +
"build your network of contacts",
SupercomputerFaction: "You are able to use your Faction's private supercomputer, " +
"giving you unparalleled computing power",
VPN: "You are able to use your Faction's high-speed VPN to more securely " +
"access the Internet",
PrivateServer: "You are able to use your Faction's private server",
InsiderKnowledge: "Other members of the faction give you insider information about other " +
"companies and factions"
}
function Perk(name, reqRep, info) {
this.name = name;
this.info = info;
this.requiredRep = reqRep;
//Company/faction specific multipliers
this.mult1 = 1;
this.mult2 = 1;
this.mult3 = 1;
this.money_mult = 1;
this.hacking_mult = 1;
this.combat_stat_mult = 1;
this.labor_stat_mult = 1;
this.repmult = 1;
/* Properties below set when a Perk is gained by the player */
this.applied = false;
@ -65,6 +88,8 @@ Perk.fromJSON = function(value) {
Reviver.constructors.Perk = Perk;
var freeCoffee = new Perk(PerkNames.FreeCoffeeCompanyPerk, 6000, PerkInfo.FreeCoffee);
/* Company Perks */
//Free Coffee - Increased money and hacking exp gain
//Free Food - Increased combat stat gain
@ -81,29 +106,43 @@ Reviver.constructors.Perk = Perk;
//Insider Knowledge - Ppl in faction from other companies have insider information that lets you hack
// other servers easier. Increase in hack chance
applyPerk = function(perk) {
switch (perk.name) {
case Perks.FreeCoffeeCompanyPerk:
case PerkNames.FreeCoffeeCompanyPerk:
//Increase money and hacking exp gain
Player.hacking_money_mult += 1.1;
Player.hacking_exp_mult += 1.1;
break;
case Perks.FreeFoodCompanyPerk:
case PerkNames.FreeFoodCompanyPerk:
Player.strength_exp_mult += 1.05;
Player.defense_exp_mult += 1.05;
Player.dexterity_exp_mult += 1.05;
Player.agility_exp_mult += 1.05;
break;
case Perks.NetworkingCompanyPerk:
case PerkNames.NetworkingCompanyPerk:
Player.company_rep_mult += 1.1;
Player.charisma_exp_mult += 1.2;
break;
case Perks.PersonalTrainerCompanyPerk:
case PerkNames.PersonalTrainerCompanyPerk:
Player.strength_exp_mult += 1.15;
Player.defense_exp_mult += 1.15;
Player.dexterity_exp_mult += 1.15;
Player.agility_exp_mult += 1.15;
break;
case Perks.KnowledgeBaseCompanyPerk:
case PerkNames.KnowledgeBaseCompanyPerk:
break;
case Perks.NootropicsCompanyPerk:
case PerkNames.NootropicsCompanyPerk:
break;
case Perks.NetworkingFactionPerk:
case PerkNames.NetworkingFactionPerk:
break;
case Perks.SupercomputerFactionPerk:
case PerkNames.SupercomputerFactionPerk:
break;
case Perks.VPNFactionPerk:
case PerkNames.VPNFactionPerk:
break;
case Perks.PrivateServerFactionPerk:
case PerkNames.PrivateServerFactionPerk:
break;
case Perks.InsiderKnowledgeFactionPerk:
case PerkNames.InsiderKnowledgeFactionPerk:
break;
default:
console.log("WARNING: Unrecognized perk: " + perk.name);

@ -79,6 +79,7 @@ function PlayerObject() {
this.discoveredServers = []; //IP addresses of secret servers not in the network that you have discovered
this.purchasedServers = [];
this.hacknetNodes = [];
this.totalHacknetNodeProduction = 0;
//Factions
this.factions = []; //Names of all factions player has joined
@ -104,11 +105,17 @@ function PlayerObject() {
this.numPeopleKilled = 0;
this.numPeopleKilledTotal = 0;
this.numPeopleKilledLifetime = 0;
this.numTimesGrandTheftAuto = 0;
this.numTimesGrandTheftAutoTotal = 0;
this.numTimesGrandTheftAutoLifetime = 0;
this.numTimesKidnapped = 0;
this.numTimesKidnappedTotal = 0;
this.numTimesKidnappedLifetime = 0;
this.numTimesHeist = 0;
this.numTimesHeistTotal = 0;
this.numTimesHeistLifetime = 0;
//Achievements and achievement progress
this.crime_money_mult = 1;
//Flag to let the engine know the player is starting an action
// Current actions: hack, analyze
@ -166,7 +173,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, 1);
t_homeComp.init(createRandomIp(), "home", "Home PC", true, true, true, true, 2);
this.homeComputer = t_homeComp.ip;
this.currentServer = t_homeComp.ip;
AddToAllServers(t_homeComp);
@ -242,10 +249,8 @@ PlayerObject.prototype.calculatePercentMoneyHacked = function() {
//Returns how much EXP the player gains on a successful hack
//The formula is:
// difficulty * requiredLevel * hacking_multiplier
//
// Note: Keep it at an integer for now,
PlayerObject.prototype.calculateExpGain = function() {
return Math.round(this.getCurrentServer().hackDifficulty * this.hacking_exp_mult);
return (this.getCurrentServer().hackDifficulty * this.hacking_exp_mult);
}
//Hack/Analyze a server. Return the amount of time the hack will take. This lets the Terminal object know how long to disable itself for
@ -254,16 +259,22 @@ PlayerObject.prototype.calculateExpGain = function() {
PlayerObject.prototype.hack = function() {
this.actionTime = this.calculateHackingTime();
console.log("Hacking time: " + this.actionTime);
//Set the startAction flag so the engine starts the hacking process
this.startAction = true;
this.startAction = true; //Set the startAction flag so the engine starts the hacking process
}
PlayerObject.prototype.analyze = function() {
//TODO Analyze only takes 1 seconds for now..maybe change this in the future?
this.actionTime = 1;
this.startAction = true;
}
PlayerObject.prototype.hasProgram = function(programName) {
var home = Player.getHomeComputer();
for (var i = 0; i < home.programs.length; ++i) {
if (programName == home.programs[i]) {return true;}
}
return false;
}
PlayerObject.prototype.gainMoney = function(money) {
if (isNaN(money)) {
console.log("ERR: NaN passed into Player.gainMoney()"); return;
@ -378,11 +389,7 @@ PlayerObject.prototype.finishWork = function(cancelled) {
this.updateSkillLevels();
var txt = "";
if (cancelled) {
txt = "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
"Since you cancelled your work early, you only gained half of the experience, money, and reputation you earned. <br><br>" +
"You earned a total of: <br>" +
var txt = "You earned a total of: <br>" +
"$" + formatNumber(this.workMoneyGained / cancMult, 2) + "<br>" +
formatNumber(this.workRepGained / cancMult, 4) + " reputation for the company <br>" +
formatNumber(this.workHackExpGained / cancMult, 4) + " hacking exp <br>" +
@ -392,25 +399,18 @@ PlayerObject.prototype.finishWork = function(cancelled) {
formatNumber(this.workAgiExpGained / cancMult, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained / cancMult, 4) + " charisma exp<br>";
if (cancelled) {
txt = "You worked a short shift of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
"Since you cancelled your work early, you only gained half of the experience, money, and reputation you earned. <br><br>" + txt;
} else {
txt = "You worked a full shift of 8 hours! <br><br> " +
"You earned a total of: <br>" +
"$" + formatNumber(this.workMoneyGained / cancMult, 2) + "<br>" +
formatNumber(this.workRepGained / cancMult, 4) + " reputation for the company <br>" +
formatNumber(this.workHackExpGained / cancMult, 4) + " hacking exp <br>" +
formatNumber(this.workStrExpGained / cancMult, 4) + " strength exp <br>" +
formatNumber(this.workDefExpGained / cancMult, 4) + " defense exp <br>" +
formatNumber(this.workDexExpGained / cancMult, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained / cancMult, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained / cancMult, 4) + " charisma exp <br>";
"You earned a total of: <br>" + txt;
}
dialogBoxCreate(txt);
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";
this.isWorking = false;
Engine.loadTerminalContent();
}
@ -430,12 +430,8 @@ PlayerObject.prototype.startWork = function() {
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
var cancelButton = document.getElementById("work-in-progress-cancel-button");
//Remove all old event listeners from Cancel button
var newCancelButton = cancelButton.cloneNode(true);
cancelButton.parentNode.replaceChild(newCancelButton, cancelButton);
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
newCancelButton.addEventListener("click", function() {
Player.finishWork(true);
return false;
@ -473,6 +469,7 @@ PlayerObject.prototype.work = function(numCycles) {
this.workRepGained = this.workRepGainRate * maxCycles;
this.workMoneyGained = this.workMoneyGainRate * maxCycles;
this.finishWork(false);
return;
}
var txt = document.getElementById("work-in-progress-text");
@ -488,13 +485,114 @@ PlayerObject.prototype.work = function(numCycles) {
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, <br>" +
"but you will only gain half of the experience, money, and reputation you've earned so far."
}
PlayerObject.prototype.startWorkPartTime = function() {
this.resetWorkStatus();
this.isWorking = true;
this.workType = CONSTANTS.WorkTypeCompanyPartTime;
this.workHackExpGainRate = this.getWorkHackExpGain();
this.workStrExpGainRate = this.getWorkStrExpGain();
this.workDefExpGainRate = this.getWorkDefExpGain();
this.workDexExpGainRate = this.getWorkDexExpGain();
this.workAgiExpGainRate = this.getWorkAgiExpGain();
this.workChaExpGainRate = this.getWorkChaExpGain();
this.workRepGainRate = this.getWorkRepGain();
this.workMoneyGainRate = this.getWorkMoneyGain();
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
var newCancelButton = clearEventListeners("work-in-progress-cancel-button");
newCancelButton.addEventListener("click", function() {
Player.finishWorkPartTime();
return false;
});
//Display Work In Progress Screen
Engine.loadWorkInProgressContent();
}
PlayerObject.prototype.workPartTime = function(numCycles) {
this.workRepGainRate = this.getWorkRepGain();
this.workHackExpGained += this.workHackExpGainRate * numCycles;
this.workStrExpGained += this.workStrExpGainRate * numCycles;
this.workDefExpGained += this.workDefExpGainRate * numCycles;
this.workDexExpGained += this.workDexExpGainRate * numCycles;
this.workAgiExpGained += this.workAgiExpGainRate * numCycles;
this.workChaExpGained += this.workChaExpGainRate * numCycles;
this.workRepGained += this.workRepGainRate * numCycles;
this.workMoneyGained += this.workMoneyGainRate * numCycles;
var cyclesPerSec = 1000 / Engine._idleSpeed;
this.timeWorked += Engine._idleSpeed * numCycles;
//If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
if (this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
var maxCycles = CONSTANTS.GameCyclesPer8Hours;
this.workHackExpGained = this.workHackExpGainRate * maxCycles;
this.workStrExpGained = this.workStrExpGainRate * maxCycles;
this.workDefExpGained = this.workDefExpGainRate * maxCycles;
this.workDexExpGained = this.workDexExpGainRate * maxCycles;
this.workAgiExpGained = this.workAgiExpGainRate * maxCycles;
this.workChaExpGained = this.workChaExpGainRate * maxCycles;
this.workRepGained = this.workRepGainRate * maxCycles;
this.workMoneyGained = this.workMoneyGainRate * maxCycles;
this.finishWorkPartTime();
return;
}
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
" at " + Player.companyName + "<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " ($" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this company <br><br>" +
formatNumber(this.workHackExpGained, 4) + " (" + formatNumber(this.workHackExpGainRate * cyclesPerSec, 4) + " / sec) hacking exp <br><br>" +
formatNumber(this.workStrExpGained, 4) + " (" + formatNumber(this.workStrExpGainRate * cyclesPerSec, 4) + " / sec) strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " (" + formatNumber(this.workDefExpGainRate * cyclesPerSec, 4) + " / sec) defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " (" + formatNumber(this.workDexExpGainRate * cyclesPerSec, 4) + " / sec) dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " (" + formatNumber(this.workAgiExpGainRate * cyclesPerSec, 4) + " / sec) agility exp <br><br> " +
formatNumber(this.workChaExpGained, 4) + " (" + formatNumber(this.workChaExpGainRate * cyclesPerSec, 4) + " / sec) charisma exp <br><br>" +
"You will automatically finish after working for 8 hours. You can cancel earlier if you wish, <br>" +
"and there will be no penalty because this is a part-time job.";
}
PlayerObject.prototype.finishWorkPartTime = function() {
this.gainWorkExp();
var company = Companies[this.companyName];
company.playerReputation += (this.workRepGained);
this.gainMoney(this.workMoneyGained);
this.updateSkillLevels();
var txt = "You earned a total of: <br>" +
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workRepGained, 4) + " reputation for the company <br>" +
formatNumber(this.workHackExpGained, 4) + " hacking exp <br>" +
formatNumber(this.workStrExpGained, 4) + " strength exp <br>" +
formatNumber(this.workDefExpGained, 4) + " defense exp <br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity exp <br>" +
formatNumber(this.workAgiExpGained, 4) + " agility exp <br>" +
formatNumber(this.workChaExpGained, 4) + " charisma exp<br>";
txt = "You worked for " + convertTimeMsToTimeElapsedString(this.timeWorked) + ".<br><br> " + txt;
dialogBoxCreate(txt);
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";
this.isWorking = false;
Engine.loadTerminalContent();
}
/* Working for Faction */
PlayerObject.prototype.finishFactionWork = function(cancelled, faction) {
this.gainWorkExp();
@ -551,7 +649,7 @@ PlayerObject.prototype.startFactionWork = function(faction) {
PlayerObject.prototype.startFactionHackWork = function(faction) {
this.resetWorkStatus();
this.workHackExpGainRate = .02 * this.hacking_exp_mult;
this.workHackExpGainRate = .175 * this.hacking_exp_mult;
this.workRepGainRate = this.hacking_skill / CONSTANTS.MaxSkillLevel * this.faction_rep_mult;
this.factionWorkType = CONSTANTS.FactionWorkHacking;
@ -563,12 +661,12 @@ PlayerObject.prototype.startFactionHackWork = function(faction) {
PlayerObject.prototype.startFactionFieldWork = function(faction) {
this.resetWorkStatus();
this.workHackExpGainRate = .05 * this.hacking_exp_mult;
this.workStrExpGainRate = .05 * this.strength_exp_mult;
this.workDefExpGainRate = .05 * this.defense_exp_mult;
this.workDexExpGainRate = .05 * this.dexterity_exp_mult;
this.workAgiExpGainRate = .05 * this.agility_exp_mult;
this.workChaExpGainRate = .05 * this.charisma_exp_mult;
this.workHackExpGainRate = .1 * this.hacking_exp_mult;
this.workStrExpGainRate = .1 * this.strength_exp_mult;
this.workDefExpGainRate = .1 * this.defense_exp_mult;
this.workDexExpGainRate = .1 * this.dexterity_exp_mult;
this.workAgiExpGainRate = .1 * this.agility_exp_mult;
this.workChaExpGainRate = .1 * this.charisma_exp_mult;
this.workRepGainRate = this.getFactionFieldWorkRepGain();
this.factionWorkType = CONSTANTS.factionWorkField;
@ -580,12 +678,12 @@ PlayerObject.prototype.startFactionFieldWork = function(faction) {
PlayerObject.prototype.startFactionSecurityWork = function(faction) {
this.resetWorkStatus();
this.workHackExpGainRate = 0.01 * this.hacking_exp_mult;
this.workStrExpGainRate = 0.01 * this.strength_exp_mult;
this.workDefExpGainRate = 0.01 * this.defense_exp_mult;
this.workDexExpGainRate = 0.01 * this.dexterity_exp_mult;
this.workAgiExpGainRate = 0.01 * this.agility_exp_mult;
this.workChaExpGainRate = 0.01 * this.charisma_exp_mult;
this.workHackExpGainRate = 0.05 * this.hacking_exp_mult;
this.workStrExpGainRate = 0.15 * this.strength_exp_mult;
this.workDefExpGainRate = 0.15 * this.defense_exp_mult;
this.workDexExpGainRate = 0.15 * this.dexterity_exp_mult;
this.workAgiExpGainRate = 0.15 * this.agility_exp_mult;
this.workChaExpGainRate = 0.00 * this.charisma_exp_mult;
this.workRepGainRate = this.getFactionSecurityWorkRepGain();
this.factionWorkType = CONSTANTS.FactionWorkSecurity;
@ -641,7 +739,7 @@ PlayerObject.prototype.workForFaction = function(numCycles) {
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently " + this.currentWorkFactionDescription + " for your faction " + faction.name + "." +
"You have been doing this for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
" You have been doing this for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
"You have earned: <br><br>" +
"$" + formatNumber(this.workMoneyGained, 2) + " (" + formatNumber(this.workMoneyGainRate * cyclesPerSec, 2) + " / sec) <br><br>" +
formatNumber(this.workRepGained, 4) + " (" + formatNumber(this.workRepGainRate * cyclesPerSec, 4) + " / sec) reputation for this faction <br><br>" +
@ -792,48 +890,59 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) {
this.className = className;
var gameCPS = 1000 / Engine._idleSpeed;
//Base costs/exp (per second)
var baseDataStructuresCost = 1;
var baseNetworksCost = 5;
var baseAlgorithmsCost = 20;
var baseManagementCost = 10;
var baseLeadershipCost = 20;
var baseStudyComputerScienceExp = 0.02;
var baseDataStructuresExp = 0.1;
var baseNetworksExp = 0.4;
var baseAlgorithmsExp = 1.5;
var baseManagementExp = 0.8;
var baseLeadershipExp = 1.5;
//Base exp gains per second
var baseStudyComputerScienceExp = 0.05;
var baseDataStructuresExp = 0.2;
var baseNetworksExp = 0.8;
var baseAlgorithmsExp = 2.0;
var baseManagementExp = 1.0;
var baseLeadershipExp = 2.0;
var baseGymExp = 1.0;
//Find cost and exp gain per game cycle
var cost = 0;
var hackExp = 0;
var chaExp = 0;
var hackExp = 0, strExp = 0, defExp = 0, dexExp = 0, agiExp = 0, chaExp = 0;
switch (className) {
case CONSTANTS.ClassStudyComputerScience:
hackExp = baseStudyComputerScienceExp * expMult / gameCPS;
break;
case CONSTANTS.ClassDataStructures:
cost = baseDataStructuresCost * costMult / gameCPS;
cost = CONSTANTS.ClassDataStructuresBaseCost * costMult / gameCPS;
hackExp = baseDataStructuresExp * expMult / gameCPS;
break;
case CONSTANTS.ClassNetworks:
cost = baseNetworksCost * costMult / gameCPS;
cost = CONSTANTS.ClassNetworksBaseCost * costMult / gameCPS;
hackExp = baseNetworksExp * expMult / gameCPS;
break;
case CONSTANTS.ClassAlgorithms:
cost = baseAlgorithmsCost * costMult / gameCPS;
cost = CONSTANTS.ClassAlgorithmsBaseCost * costMult / gameCPS;
hackExp = baseAlgorithmsExp * expMult / gameCPS;
break;
case CONSTANTS.ClassManagement:
cost = baseManagementCost * costMult / gameCPS;
cost = CONSTANTS.ClassManagementBaseCost * costMult / gameCPS;
chaExp = baseManagementExp * expMult / gameCPS;
break;
case CONSTANTS.ClassLeadership:
cost = baseLeadershipCost * costMult / gameCPS;
cost = CONSTANTS.ClassLeadershipBaseCost * costMult / gameCPS;
chaExp = baseLeadershipExp * expMult / gameCPS;
break;
case CONSTANTS.ClassGymStrength:
cost = CONSTANTS.ClassGymBaseCost * costMult / gameCPS;
strExp = baseGymExp * expMult / gameCPS;
break;
case CONSTANTS.ClassGymDefense:
cost = CONSTANTS.ClassGymBaseCost * costMult / gameCPS;
defExp = baseGymExp * expMult / gameCPS;
break;
case CONSTANTS.ClassGymDexterity:
cost = CONSTANTS.ClassGymBaseCost * costMult / gameCPS;
dexExp = baseGymExp * expMult / gameCPS;
break;
case CONSTANTS.ClassGymAgility:
cost = CONSTANTS.ClassGymBaseCost * costMult / gameCPS;
agiExp = baseGymExp * expMult / gameCPS;
break;
default:
throw new Error("ERR: Invalid/unregocnized class name");
return;
@ -841,6 +950,10 @@ PlayerObject.prototype.startClass = function(costMult, expMult, className) {
this.workMoneyLossRate = cost;
this.workHackExpGainRate = hackExp * this.hacking_exp_mult;
this.workStrExpGainRate = strExp * this.strength_exp_mult;
this.workDefExpGainRate = defExp * this.defense_exp_mult;
this.workDexExpGainRate = dexExp * this.dexterity_exp_mult;
this.workAgiExpGainRate = agiExp * this.agility_exp_mult;
this.workChaExpGainRate = chaExp * this.charisma_exp_mult;
var cancelButton = document.getElementById("work-in-progress-cancel-button");
@ -929,16 +1042,12 @@ PlayerObject.prototype.startCrime = function(hackExp, strExp, defExp, dexExp, ag
this.workDexExpGained = dexExp * this.dexterity_exp_mult;
this.workAgiExpGained = agiExp * this.agility_exp_mult;
this.workChaExpGained = chaExp * this.charisma_exp_mult;
this.workMoneyGained = money; //TODO multiplier for this?
this.workMoneyGained = money * this.crime_money_mult;
this.timeNeededToCompleteWork = time;
var cancelButton = document.getElementById("work-in-progress-cancel-button");
//Remove all old event listeners from Cancel button
var newCancelButton = cancelButton.cloneNode(true);
cancelButton.parentNode.replaceChild(newCancelButton, cancelButton);
var newCancelButton = clearEventListeners("work-in-progress-cancel-button")
newCancelButton.addEventListener("click", function() {
Player.finishCrime(true);
return false;
@ -951,16 +1060,24 @@ PlayerObject.prototype.startCrime = function(hackExp, strExp, defExp, dexExp, ag
PlayerObject.prototype.commitCrime = function (numCycles) {
this.timeWorked += Engine._idleSpeed * numCycles;
if (this.timeWorked >= this.timeNeededToCompleteWork) {Player.finishCrime(false);}
if (this.timeWorked >= this.timeNeededToCompleteWork) {Player.finishCrime(false); return;}
var percent = Math.round(Player.timeWorked / Player.timeNeededToCompleteWork * 100);
var numBars = Math.round(percent / 5);
if (numBars < 0) {numBars = 0;}
if (numBars > 20) {numBars = 20;}
var progressBar = "[" + Array(numBars+1).join("|") + Array(20 - numBars + 1).join(" ") + "]";
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are attempting to " + Player.crimeType + ".<br>" +
"Time remaining: " + convertTimeMsToTimeElapsedString(this.timeNeededToCompleteWork - this.timeWorked);
"Time remaining: " + convertTimeMsToTimeElapsedString(this.timeNeededToCompleteWork - this.timeWorked) + "<br>" +
progressBar.replace( / /g, "&nbsp;" );
}
PlayerObject.prototype.finishCrime = function(cancelled) {
//Determine crime success/failure
if (!cancelled) {
var statusText = ""; //TODO, unique message for each crime when you succeed
if (determineCrimeSuccess(this.crimeType, this.workMoneyGained)) {
//Handle Karma and crime statistics
switch(this.crimeType) {
@ -984,9 +1101,21 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
++this.numPeopleKilled;
this.karma -= 3;
break;
case CONSTANTS.CrimeGrandTheftAuto:
++this.numTimesGrandTheftAuto;
this.karma -= 5;
break;
case CONSTANTS.CrimeKidnap:
++this.numTimesKidnapped;
this.karma -= 3;
this.karma -= 6;
break;
case CONSTANTS.CrimeAssassination:
++this.numPeopleKilled;
this.karma -= 10;
break;
case CONSTANTS.CrimeHeist:
++this.numTimesHeist;
this.karma -= 15;
break;
default:
dialogBoxCreate("ERR: Unrecognized crime type. This is probably a bug please contact the developer");
@ -1003,26 +1132,28 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
dialogBoxCreate("Crime successful! <br><br>" +
"You gained:<br>"+
"$" + this.workMoneyGained + "<br>" +
this.workHackExpGained + " hacking experience <br>" +
this.workStrExpGained + " strength experience<br>" +
this.workDefExpGained + " defense experience<br>" +
this.workDexExpGained + " dexterity experience<br>" +
this.workAgiExpGained + " agility experience<br>" +
this.workChaExpGained + " charisma experience");
"$" + formatNumber(this.workMoneyGained, 2) + "<br>" +
formatNumber(this.workHackExpGained, 4) + " hacking experience <br>" +
formatNumber(this.workStrExpGained, 4) + " strength experience<br>" +
formatNumber(this.workDefExpGained, 4) + " defense experience<br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity experience<br>" +
formatNumber(this.workAgiExpGained, 4) + " agility experience<br>" +
formatNumber(this.workChaExpGained, 4) + " charisma experience");
} else {
dialogBoxCreate("Crime failed! <br><br>" +
"You gained:<br>"+
this.workHackExpGained + " hacking experience <br>" +
this.workStrExpGained + " strength experience<br>" +
this.workDefExpGained + " defense experience<br>" +
this.workDexExpGained + " dexterity experience<br>" +
this.workAgiExpGained + " agility experience<br>" +
this.workChaExpGained + " charisma experience");
}
formatNumber(this.workHackExpGained, 4) + " hacking experience <br>" +
formatNumber(this.workStrExpGained, 4) + " strength experience<br>" +
formatNumber(this.workDefExpGained, 4) + " defense experience<br>" +
formatNumber(this.workDexExpGained, 4) + " dexterity experience<br>" +
formatNumber(this.workAgiExpGained, 4) + " agility experience<br>" +
formatNumber(this.workChaExpGained, 4) + " charisma experience");
}
this.gainWorkExp();
}
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";

@ -32,9 +32,17 @@ function prestigeAugmentation() {
Player.numPeopleKilledTotal += Player.numPeopleKilled;
Player.numPeopleKilledLifetime += Player.numPeopleKilled;
Player.numPeopleKilled = 0;
Player.numTimesGrandTheftAutoTotal += Player.numTimesGrandTheftAuto;
Player.numTimesGrandTheftAutoLifetime += Player.numTimesGrandTheftAuto;
Player.numTimesGrandTheftAuto = 0;
Player.numTimesKidnappedTotal += Player.numTimesKidnapped;
Player.numTimesKidnappedLifetime += Player.numTimesKidnapped;
Player.numTimesKidnapped = 0;
Player.numTimesHeistTotal += Player.numTimesHeist;
Player.numTimesHeistLifetime += Player.numTimesHeist;
Player.numTimesHeist = 0;
Player.karma = 0;
//Reset stats
Player.hacking_skill = 1;
@ -53,9 +61,7 @@ function prestigeAugmentation() {
Player.agility_exp = 0;
Player.charisma_exp = 0;
Player.money = 0;
Player.homeComputer = "";
Player.money = 1000;
Player.city = Locations.Sector12;
Player.location = "";
@ -101,11 +107,42 @@ function prestigeAugmentation() {
Player.lastUpdate = new Date().getTime();
//Delete all servers
var homeComp = Player.getHomeComputer();
//Delete all servers except home computer
for (var member in AllServers) {
delete AllServers[member];
}
AllServers = {};
//Delete Special Server IPs
for (var member in SpecialServerIps) {
delete SpecialServerIps[member];
}
SpecialServersIps = null;
//Reset home computer (only the programs) and add to AllServers
homeComp.programs.length = 0;
homeComp.runningScripts = [];
homeComp.serversOnNetwork = [];
homeComp.isConnectedTo = true;
homeComp.isOnline = true;
homeComp.ramUsed = 0;
homeComp.programs.push(Programs.NukeProgram);
Player.currentServer = homeComp.ip;
Player.homeComputer = homeComp.ip;
AddToAllServers(homeComp);
//Re-create foreign servers
SpecialServerIps = new SpecialServerIpsMap(); //Must be done before initForeignServers()
initForeignServers();
//Reset statistics of all scripts on home computer
for (var i = 0; i < homeComp.scripts.length; ++i) {
var s = homeComp.scripts[i];
s.reset();
delete s.moneyStolenMap;
s.moneyStolenMap = new AllServersToMoneyMap();
s.moneyStolenMap.printConsole();
}
//Delete all running scripts objects
for (var i = 0; i < workerScripts.length; ++i) {
@ -120,32 +157,34 @@ function prestigeAugmentation() {
//Delete Hacknet Nodes
Player.hacknetNodes.length = 0;
//Delete Special Server IPs
for (var member in SpecialServerIps) {
delete SpecialServerIps[member];
}
SpecialServersIps = null;
Player.totalHacknetNodeProduction = 0;
//Delete Companies
for (var member in Companies) {
if (Companies.hasOwnProperty(member)) {
delete Companies[member];
}
}
Companies = {};
//Delete Factions
//Reset Factions
for (var member in Factions) {
if (Factions.hasOwnProperty(member)) {
delete Factions[member];
}
}
Factions = {};
//Inititialization
SpecialServerIps = new SpecialServerIpsMap();
Player.init();
initForeignServers();
initCompanies();
//Stop a Terminal action if there is onerror
if (Engine._actionInProgress) {
Engine._actionInProgress = false;
Terminal.finishAction(true);
}
//Re-initialize things - This will update any changes
initFactions();
CompanyPositions.init();
initAugmentations();
initCompanies();
Engine.loadTerminalContent();
}

@ -20,7 +20,7 @@ BitburnerSaveObject.prototype.saveGame = function() {
this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps);
this.AugmentationsSave = JSON.stringify(Augmentations);
var saveString = JSON.stringify(this);
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
window.localStorage.setItem("bitburnerSave", saveString);
}
@ -29,7 +29,7 @@ loadGame = function(saveObj) {
console.log("No save file to load");
return false;
}
var saveString = window.localStorage.getItem("bitburnerSave");
var saveString = decodeURIComponent(escape(atob(window.localStorage.getItem("bitburnerSave"))));
saveObj = JSON.parse(saveString, Reviver);
Player = JSON.parse(saveObj.PlayerSave, Reviver);

@ -17,7 +17,7 @@ document.addEventListener("DOMContentLoaded", scriptEditorSaveCloseInit, false);
//Define key commands in script editor (ctrl o to save + close, etc.)
$(document).keydown(function(e) {
if (Engine.currentPage == Engine.Page.ScriptEditor) {
//Ctrl + x
//Ctrl + b
if (e.keyCode == 66 && e.ctrlKey) {
saveAndCloseScriptEditor();
}
@ -26,6 +26,20 @@ $(document).keydown(function(e) {
function saveAndCloseScriptEditor() {
var filename = document.getElementById("script-editor-filename").value;
if (iTutorialIsRunning && currITutorialStep == iTutorialSteps.TerminalTypeScript) {
if (filename != "foodnstuff") {
dialogBoxCreate("Leave the script name as 'foodnstuff'!");
return;
}
var code = document.getElementById("script-editor-text").value;
code = code.replace(/\s\s+/g, '');
console.log(code);
if (code.indexOf("while(true) {hack('foodnstuff');}") == -1) {
dialogBoxCreate("Please copy and paste the code from the tutorial!");
return;
}
iTutorialNextStep();
}
if (filename == "") {
//If no filename...just close and do nothing
@ -89,13 +103,14 @@ function Script() {
this.numInstructions = 0;
//Stats to display on the Scripts menu, and used to determine offline progress
this.offlineRunningTime = 0; //Seconds
this.offlineRunningTime = 0.01; //Seconds
this.offlineMoneyMade = 0;
this.offlineExpGained = 0;
this.onlineRunningTime = 0; //Seconds
this.onlineRunningTime = 0.01; //Seconds
this.onlineMoneyMade = 0;
this.onlineExpGained = 0;
this.moneyStolenMap = new AllServersToMoneyMap();
};
//Get the script data from the Script Editor and save it to the object
@ -116,14 +131,25 @@ Script.prototype.saveScript = function() {
this.updateRamUsage();
//Clear the stats when the script is updated
this.offlineRunningTime = 0; //Seconds
this.offlineRunningTime = 0.01; //Seconds
this.offlineMoneyMade = 0;
this.onlineRunningTime = 0; //Seconds
this.onlineRunningTime = 0.01; //Seconds
this.onlineMoneyMade = 0;
this.lastUpdate = 0;
this.logs = [];
}
}
Script.prototype.reset = function() {
this.offlineRunningTime = 0.01; //Seconds
this.offlineMoneyMade = 0;
this.offlineExpGained = 0;
this.onlineRunningTime = 0.01; //Seconds
this.onlineMoneyMade = 0;
this.onlineExpGained = 0;
}
//Calculates the number of instructions, which is just determined by number of semicolons
Script.prototype.updateNumInstructions = function() {
var numSemicolons = this.code.split(";").length - 1;
@ -131,11 +157,36 @@ Script.prototype.updateNumInstructions = function() {
}
//Updates how much RAM the script uses when it is running.
//Right now, it is determined solely by the number of instructions
//Ideally, I would want it to be based on type of instructions as well
// (e.g. hack() costs a lot but others dont)
Script.prototype.updateRamUsage = function() {
this.ramUsage = this.numInstructions * 0.5;
var baseRam = 1; //Each script requires 1GB to run regardless
var codeCopy = this.code.repeat(1);
codeCopy = codeCopy.replace(/\s/g,''); //Remove all whitespace
var whileCount = numOccurrences(codeCopy, "while(");
var forCount = numOccurrences(codeCopy, "for(");
var ifCount = numOccurrences(codeCopy, "if(");
var hackCount = numOccurrences(codeCopy, "hack(");
var growCount = numOccurrences(codeCopy, "grow(");
var nukeCount = numOccurrences(codeCopy, "nuke(");
var brutesshCount = numOccurrences(codeCopy, "brutessh(");
var ftpcrackCount = numOccurrences(codeCopy, "ftpcrack(");
var relaysmtpCount = numOccurrences(codeCopy, "relaysmtp(");
var httpwormCount = numOccurrences(codeCopy, "httpworm(");
var sqlinjectCount = numOccurrences(codeCopy, "sqlinject(");
this.ramUsage = baseRam +
((whileCount * CONSTANTS.ScriptWhileRamCost) +
(forCount * CONSTANTS.ScriptForRamCost) +
(ifCount * CONSTANTS.ScriptIfRamCost) +
(hackCount * CONSTANTS.ScriptHackRamCost) +
(growCount * CONSTANTS.ScriptGrowRamCost) +
(nukeCount * CONSTANTS.ScriptNukeRamCost) +
(brutesshCount * CONSTANTS.ScriptBrutesshRamCost) +
(ftpcrackCount * CONSTANTS.ScriptFtpcrackRamCost) +
(relaysmtpCount * CONSTANTS.ScriptRelaysmtpRamCost) +
(httpwormCount * CONSTANTS.ScriptHttpwormRamCost) +
(sqlinjectCount * CONSTANTS.ScriptSqlinjectRamCost));
console.log("ram usage: " + this.ramUsage);
}
Script.prototype.log = function(txt) {
@ -197,41 +248,72 @@ scriptCalculateOfflineProduction = function(script) {
var thisUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate;
var timePassed = (thisUpdate - lastUpdate) / 1000; //Seconds
console.log("Offline for " + timePassed.toString() + " seconds");
console.log("Offline for " + timePassed + " seconds");
//Calculate the "confidence" rating of the script's true production. This is based
//entirely off of time. We will arbitrarily say that if a script has been running for
//4 hours (14400 sec) then we are completely confident in its ability
var confidence = (script.onlineRunningTime) / 14400;
if (confidence >= 1) {confidence = 1;}
console.log("onlineRunningTime: " + script.onlineRunningTime.toString());
console.log("Confidence: " + confidence.toString());
console.log("onlineRunningTime: " + script.onlineRunningTime);
console.log("Confidence: " + confidence);
var totalOfflineProduction = 0;
for (var ip in script.moneyStolenMap) {
if (script.moneyStolenMap.hasOwnProperty(ip)) {
if (script.moneyStolenMap[ip] == 0 || script.moneyStolenMap[ip] == null) {continue;}
var serv = AllServers[ip];
if (serv == null) {continue;}
var production = 0.5 * script.moneyStolenMap[ip] / script.onlineRunningTime * timePassed;
production *= confidence;
if (production > serv.moneyAvailable) {
production = serv.moneyAvailable;
}
totalOfflineProduction += production;
Player.gainMoney(production);
console.log(script.filename + " generated $" + production + " while offline by hacking " + serv.hostname);
serv.moneyAvailable -= production;
if (serv.moneyAvailable < 0) {serv.moneyAvailable = 0;}
}
}
//A script's offline production will always be at most half of its online production.
var production = (1/2) * (script.onlineMoneyMade / script.onlineRunningTime) * timePassed;
production *= confidence;
var expGain = (1/2) * (script.onlineExpGained / script.onlineRunningTime) * timePassed;
expGain *= confidence;
//Account for production in Player and server)
var server = AllServers[script.server];
if (production > server.moneyAvailable) {
production = server.moneyAvailable;
}
Player.gainMoney(production);
Player.gainHackingExp(expGain);
server.moneyAvailable -= production;
if (server.moneyAvailable < 0) {server.moneyAvailable = 0;}
//Update script stats
script.offlineMoneyMade += production;
script.offlineMoneyMade += totalOfflineProduction;
script.offlineRunningTime += timePassed;
script.offlineExpGained += expGain;
//DEBUG
var serverName = AllServers[script.server].hostname;
console.log(script.filename + " from server " + serverName + " generated $" + production.toString() + " while offline");
console.log(script.filename + " from server " + serverName + " generated $" + totalOfflineProduction + " TOTAL while offline");
}
//Creates a function that creates a map/dictionary with the IP of each existing server as
//a key, and 0 as the value. This is used to keep track of how much money a script
//hacks from that server
function AllServersToMoneyMap() {
for (var ip in AllServers) {
if (AllServers.hasOwnProperty(ip)) {
this[ip] = 0;
}
}
}
AllServersToMoneyMap.prototype.printConsole = function() {
console.log("Printing AllServersToMoneyMap");
for (var ip in this) {
if (this.hasOwnProperty(ip)) {
var serv = AllServers[ip];
if (serv == null) {
console.log("Warning null server encountered with ip: " + ip);
continue;
}
console.log(ip + "(" + serv.hostname + "): " + this[ip]);
}
}
}

@ -56,6 +56,14 @@ function Server() {
//Initialize the properties of a server
Server.prototype.init = function(ip, hostname, organizationName, onlineStatus, isConnectedTo, adminRights, purchasedByPlayer, maxRam) {
this.ip = ip;
//Check if hostname is unique
var i = 0;
while (GetServerByHostname(hostname) != null) {
//Server already exists
hostname = hostname + "-" + i;
++i;
}
this.hostname = hostname;
this.organizationName = organizationName;
this.isOnline = onlineStatus;
@ -113,7 +121,6 @@ Reviver.constructors.Server = Server;
//world_daemon: new Server(), //Final server for 2nd tier prestige. Discover that the world is a simulation
/* Initialization. Called only when loading a new game( no save file) */
initForeignServers = function() {
//MegaCorporations
var ECorpServer = new Server();
@ -395,105 +402,105 @@ initForeignServers = function() {
//"Low level" targets
var FoodNStuffServer = new Server();
FoodNStuffServer.init(createRandomIp(), "foodnstuff", "Food N Stuff Supermarket", true, false, false, false, 2);
FoodNStuffServer.init(createRandomIp(), "foodnstuff", "Food N Stuff Supermarket", true, false, false, false, 4);
FoodNStuffServer.setHackingParameters(1, 500000, 10, 5);
FoodNStuffServer.setPortProperties(0);
AddToAllServers(FoodNStuffServer);
var SigmaCosmeticsServer = new Server();
SigmaCosmeticsServer.init(createRandomIp(), "sigma-cosmetics", "Sigma Cosmetics", true, false, false, false, 0);
SigmaCosmeticsServer.setHackingParameters(5, 500000, 10, 10);
SigmaCosmeticsServer.init(createRandomIp(), "sigma-cosmetics", "Sigma Cosmetics", true, false, false, false, 4);
SigmaCosmeticsServer.setHackingParameters(5, 750000, 10, 10);
SigmaCosmeticsServer.setPortProperties(0);
AddToAllServers(SigmaCosmeticsServer);
var JoesGunsServer = new Server();
JoesGunsServer.init(createRandomIp(), "joesguns", "Joe's Guns", true, false, false, false, 2);
JoesGunsServer.setHackingParameters(10, 200000, 20, 25);
JoesGunsServer.init(createRandomIp(), "joesguns", "Joe's Guns", true, false, false, false, 4);
JoesGunsServer.setHackingParameters(10, 1000000, 20, 20);
JoesGunsServer.setPortProperties(0);
AddToAllServers(JoesGunsServer);
var Zer0NightclubServer = new Server();
Zer0NightclubServer.init(createRandomIp(), "zer0", "ZER0 Nightclub", true, false, false, false, 2);
Zer0NightclubServer.setHackingParameters(75, 750000, 25, 40);
Zer0NightclubServer.setHackingParameters(75, 5000000, 25, 40);
Zer0NightclubServer.setPortProperties(1);
AddToAllServers(Zer0NightclubServer);
var NectarNightclubServer = new Server();
NectarNightclubServer.init(createRandomIp(), "nectar-net", "Nectar Nightclub Network", true, false, false, false, 2);
NectarNightclubServer.setHackingParameters(20, 400000, 20, 25);
NectarNightclubServer.init(createRandomIp(), "nectar-net", "Nectar Nightclub Network", true, false, false, false, 4);
NectarNightclubServer.setHackingParameters(20, 1200000, 20, 25);
NectarNightclubServer.setPortProperties(0);
AddToAllServers(NectarNightclubServer);
var NeoNightclubServer = new Server();
NeoNightclubServer.init(createRandomIp(), "neo-net", "Neo Nightclub Network", true, false, false, false, 2);
NeoNightclubServer.setHackingParameters(50, 500000, 25, 25);
NeoNightclubServer.setHackingParameters(50, 2500000, 25, 25);
NeoNightclubServer.setPortProperties(1);
AddToAllServers(NeoNightclubServer);
var SilverHelixServer = new Server();
SilverHelixServer.init(createRandomIp(), "silver-helix", "Silver Helix", true, false, false, false, 2);
SilverHelixServer.setHackingParameters(150, 1000000, 30, 30);
SilverHelixServer.setHackingParameters(150, 50000000, 30, 30);
SilverHelixServer.setPortProperties(2);
AddToAllServers(SilverHelixServer);
var HongFangTeaHouseServer = new Server();
HongFangTeaHouseServer.init(createRandomIp(), "hong-fang-tea", "HongFang Teahouse", true, false, false, false, 0);
HongFangTeaHouseServer.setHackingParameters(30, 250000, 15, 10);
HongFangTeaHouseServer.init(createRandomIp(), "hong-fang-tea", "HongFang Teahouse", true, false, false, false, 4);
HongFangTeaHouseServer.setHackingParameters(30, 1500000, 15, 15);
HongFangTeaHouseServer.setPortProperties(0);
AddToAllServers(HongFangTeaHouseServer);
var HaraKiriSushiBarServer = new Server();
HaraKiriSushiBarServer.setHackingParameters(40, 100000, 15, 40);
HaraKiriSushiBarServer.init(createRandomIp(), "harakiri-sushi", "HaraKiri Sushi Bar Network", true, false, false, false, 0);
HaraKiriSushiBarServer.setHackingParameters(40, 2000000, 15, 40);
HaraKiriSushiBarServer.init(createRandomIp(), "harakiri-sushi", "HaraKiri Sushi Bar Network", true, false, false, false, 4);
HaraKiriSushiBarServer.setPortProperties(1);
AddToAllServers(HaraKiriSushiBarServer);
var PhantasyServer = new Server();
PhantasyServer.init(createRandomIp(), "phantasy", "Phantasy Club", true, false, false, false, 4);
PhantasyServer.setHackingParameters(100, 300000, 20, 35);
PhantasyServer.init(createRandomIp(), "phantasy", "Phantasy Club", true, false, false, false, 0);
PhantasyServer.setHackingParameters(100, 25000000, 20, 35);
PhantasyServer.setPortProperties(2);
AddToAllServers(PhantasyServer);
var MaxHardwareServer = new Server();
MaxHardwareServer.init(createRandomIp(), "max-hardware", "Max Hardware Store", true, false, false, false, 0);
MaxHardwareServer.setHackingParameters(80, 150000, 15, 25);
MaxHardwareServer.setHackingParameters(80, 10000000, 15, 25);
MaxHardwareServer.setPortProperties(1);
AddToAllServers(MaxHardwareServer);
var OmegaSoftwareServer = new Server();
OmegaSoftwareServer.init(createRandomIp(), "omega-net", "Omega Software", true, false, false, false, 8);
OmegaSoftwareServer.setHackingParameters(200, 1000000, 30, 30);
OmegaSoftwareServer.setHackingParameters(200, 80000000, 30, 35);
OmegaSoftwareServer.setPortProperties(2);
AddToAllServers(OmegaSoftwareServer);
//Gyms
var CrushFitnessGymServer = new Server();
CrushFitnessGymServer.init(createRandomIp(), "crush-fitness", "Crush Fitness", true, false, false, false, 0);
CrushFitnessGymServer.setHackingParameters(250, 300000, 40, 25);
CrushFitnessGymServer.setHackingParameters(250, 10000000, 40, 25);
CrushFitnessGymServer.setPortProperties(2);
AddToAllServers(CrushFitnessGymServer);
var IronGymServer = new Server();
IronGymServer.init(createRandomIp(), "iron-gym", "Iron Gym Network", true, false, false, false, 0);
IronGymServer.setHackingParameters(100, 150000, 30, 15);
IronGymServer.setHackingParameters(100, 5000000, 30, 15);
IronGymServer.setPortProperties(1);
AddToAllServers(IronGymServer);
var MilleniumFitnessGymServer = new Server();
MilleniumFitnessGymServer.init(createRandomIp(), "millenium-fitness", "Millenium Fitness Network", true, false, false, false, 0);
MilleniumFitnessGymServer.setHackingParameters(500, 400000, 50, 30);
MilleniumFitnessGymServer.setHackingParameters(500, 2500000, 50, 30);
MilleniumFitnessGymServer.setPortProperties(3);
AddToAllServers(MilleniumFitnessGymServer);
var PowerhouseGymServer = new Server();
PowerhouseGymServer.init(createRandomIp(), "powerhouse-fitness", "Powerhouse Fitness", true, false, false, false, 0);
PowerhouseGymServer.setHackingParameters(1000, 1000000, 60, 50);
PowerhouseGymServer.setHackingParameters(1000, 100000000, 60, 50);
PowerhouseGymServer.setPortProperties(5);
AddToAllServers(PowerhouseGymServer);
var SnapFitnessGymServer = new Server();
SnapFitnessGymServer.init(createRandomIp(), "snap-fitness", "Snap Fitness", true, false, false, false, 0);
SnapFitnessGymServer.setHackingParameters(750, 750000, 50, 45);
SnapFitnessGymServer.setHackingParameters(750, 75000000, 50, 45);
SnapFitnessGymServer.setPortProperties(4);
AddToAllServers(SnapFitnessGymServer);
@ -706,6 +713,15 @@ GetServerByHostname = function(hostname) {
return null;
}
//Get server by IP or hostname. Returns null if invalid
getServer = function(s) {
if (!isValidIPAddress(s)) {
return GetServerByHostname(s);
} else {
return AllServers[s];
}
}
//Debugging tool
PrintAllServers = function() {
for (var ip in AllServers) {

@ -40,7 +40,6 @@ $(document).keydown(function(event) {
if (command.length > 0) {
post("> " + command);
//TODO Do i have to switch the order of these two?
Terminal.executeCommand(command);
$('input[class=terminal-input]').val("");
}
@ -256,7 +255,7 @@ var Terminal = {
var rand = Math.random();
console.log("Hack success chance: " + hackChance + ", rand: " + rand);
var expGainedOnSuccess = Player.calculateExpGain();
var expGainedOnFailure = Math.round(expGainedOnSuccess / 4);
var expGainedOnFailure = (expGainedOnSuccess / 4);
if (rand < hackChance) { //Success!
var moneyGained = Player.calculatePercentMoneyHacked();
moneyGained = Math.floor(Player.getCurrentServer().moneyAvailable * moneyGained);
@ -269,11 +268,11 @@ var Terminal = {
Player.gainHackingExp(expGainedOnSuccess)
post("Hack successful! Gained $" + moneyGained + " and " + expGainedOnSuccess + " hacking EXP");
post("Hack successful! Gained $" + formatNumber(moneyGained, 2) + " and " + formatNumber(expGainedOnSuccess, 4) + " hacking EXP");
} else { //Failure
//Player only gains 25% exp for failure? TODO Can change this later to balance
Player.gainHackingExp(expGainedOnFailure)
post("Failed to hack " + Player.getCurrentServer().hostname + ". Gained " + expGainedOnFailure + " hacking EXP");
post("Failed to hack " + Player.getCurrentServer().hostname + ". Gained " + formatNumber(expGainedOnFailure, 4) + " hacking EXP");
}
}
@ -289,12 +288,16 @@ var Terminal = {
finishAnalyze: function(cancelled = false) {
if (cancelled == false) {
post(Player.getCurrentServer().hostname + ": ");
var rootAccess = "";
if (Player.getCurrentServer().hasAdminRights) {rootAccess = "YES";}
else {rootAccess = "NO";}
post("Root Access: " + rootAccess);
post("Required hacking skill: " + Player.getCurrentServer().requiredHackingSkill);
//TODO Make these actual estimates by adding a random offset to result?
//TODO Change the text to sound better
post("Estimated chance to hack: " + Math.round(Player.calculateHackingChance() * 100) + "%");
post("Estimated time to hack: " + Math.round(Player.calculateHackingTime()) + " seconds");
post("Estimed total money available on server: $" + Player.getCurrentServer().moneyAvailable);
post("Estimated chance to hack: " + formatNumber(addOffset(Player.calculateHackingChance() * 100, 5), 2) + "%");
post("Estimated time to hack: " + formatNumber(addOffset(Player.calculateHackingTime(), 5), 3) + " seconds");
post("Estimated total money available on server: $" + formatNumber(addOffset(Player.getCurrentServer().moneyAvailable, 5), 2));
post("Required number of open ports for NUKE: " + Player.getCurrentServer().numOpenPortsRequired);
if (Player.getCurrentServer().sshPortOpen) {
post("SSH port: Open")
@ -348,10 +351,127 @@ var Terminal = {
var commandArray = command.split(" ");
if (commandArray.length == 0) {
if (commandArray.length == 0) {return;}
/****************** Interactive Tutorial Terminal Commands ******************/
if (iTutorialIsRunning) {
var foodnstuffServ = GetServerByHostname("foodnstuff");
if (foodnstuffServ == null) {throw new Error("Could not get foodnstuff server"); return;}
switch(currITutorialStep) {
case iTutorialSteps.TerminalHelp:
if (commandArray[0] == "help") {
post(CONSTANTS.HelpText);
iTutorialNextStep();
} else {post("Wrong command! Try again!");}
break;
case iTutorialSteps.TerminalLs:
if (commandArray[0] == "ls") {
Terminal.executeListCommand(commandArray);
iTutorialNextStep();
} else {post("Wrong command! Try again!");}
break;
case iTutorialSteps.TerminalScan:
if (commandArray[0] == "scan") {
Terminal.executeScanCommand(commandArray);
iTutorialNextStep();
} else {post("Wrong command! Try again!");}
break;
case iTutorialSteps.TerminalConnect:
if (commandArray.length == 2) {
if ((commandArray[0] == "connect" || commandArray[0] == "telnet") &&
(commandArray[1] == "foodnstuff" || commandArray[1] == foodnstuffServ.ip)) {
Player.getCurrentServer().isConnectedTo = false;
Player.currentServer = foodnstuffServ.ip;
Player.getCurrentServer().isConnectedTo = true;
post("Connected to foodnstuff");
iTutorialNextStep();
} else {post("Wrong command! Try again!"); return;}
} else {post("Wrong command! Try again!");}
break;
case iTutorialSteps.TerminalAnalyze:
if (commandArray[0] == "analyze") {
if (commandArray.length != 1) {
post("Incorrect usage of analyze command. Usage: analyze"); return;
}
//Analyze the current server for information
Terminal.analyzeFlag = true;
post("Analyzing system...");
hackProgressPost("Time left:");
hackProgressBarPost("[");
Player.analyze();
//Disable terminal
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
$('input[class=terminal-input]').prop('disabled', true);
iTutorialNextStep();
} else {
post("Wrong command! Try again!");
}
break;
case iTutorialSteps.TerminalNuke:
if (commandArray.length == 2 &&
commandArray[0] == "run" && commandArray[1] == "NUKE.exe") {
foodnstuffServ.hasAdminRights = true;
post("NUKE successful! Gained root access to foodnstuff");
iTutorialNextStep();
} else {post("Wrong command! Try again!");}
break;
case iTutorialSteps.TerminalManualHack:
if (commandArray.length == 1 && commandArray[0] == "hack") {
Terminal.hackFlag = true;
hackProgressPost("Time left:");
hackProgressBarPost("[");
Player.hack();
//Disable terminal
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
$('input[class=terminal-input]').prop('disabled', true);
iTutorialNextStep();
} else {post("Wrong command! Try again!");}
break;
case iTutorialSteps.TerminalCreateScript:
if (commandArray.length == 2 &&
commandArray[0] == "nano" && commandArray[1] == "foodnstuff.script") {
Engine.loadScriptEditorContent("foodnstuff", "");
iTutorialNextStep();
} else {post("Wrong command! Try again!");}
case iTutorialSteps.TerminalFree:
if (commandArray.length == 1 && commandArray[0] == "free") {
Terminal.executeFreeCommand(commandArray);
iTutorialNextStep();
}
break;
case iTutorialSteps.TerminalRunScript:
if (commandArray.length == 2 &&
commandArray[0] == "run" && commandArray[1] == "foodnstuff.script") {
Terminal.runScript("foodnstuff.script");
iTutorialNextStep();
} else {post("Wrong command! Try again!");}
break;
case iTutorialSteps.ActiveScriptsToTerminal:
if (commandArray.length == 2 &&
commandArray[0] == "tail" && commandArray[1] == "foodnstuff.script") {
var currScripts = Player.getCurrentServer().scripts;
for (var i = 0; i < currScripts.length; ++i) {
if ("foodnstuff.script" == currScripts[i].filename) {
currScripts[i].displayLog();
}
}
iTutorialNextStep();
} else {post("Wrong command! Try again!");}
break;
default:
post("Please follow the tutorial, or click 'Exit Tutorial' if you'd like to skip it");
return;
}
return;
}
/****************** END INTERACTIVE TUTORIAL ******************/
/* Command parser */
switch (commandArray[0]) {
case "analyze":
if (commandArray.length != 1) {
@ -368,6 +488,9 @@ var Terminal = {
document.getElementById("terminal-input-td").innerHTML = '<input type="text" class="terminal-input"/>';
$('input[class=terminal-input]').prop('disabled', true);
break;
case "buy":
executeDarkwebTerminalCommand(commandArray);
break;
case "clear":
case "cls":
if (commandArray.length != 1) {
@ -392,6 +515,9 @@ var Terminal = {
Player.currentServer = Player.getCurrentServer().getServerOnNetwork(i).ip;
Player.getCurrentServer().isConnectedTo = true;
post("Connected to " + ip);
if (Player.getCurrentServer().hostname == "darkweb") {
checkIfConnectedToDarkweb(); //Posts a 'help' message if connecting to dark web
}
return;
}
}
@ -399,12 +525,7 @@ var Terminal = {
post("Host not found");
break;
case "free":
if (commandArray.length != 1) {
post("Incorrect usage of free command. Usage: free"); return;
}
post("Total: " + Player.getCurrentServer().maxRam.toString() + " GB");
post("Used: " + Player.getCurrentServer().ramUsed.toString() + " GB");
post("Available: " + (Player.getCurrentServer().maxRam - Player.getCurrentServer().ramUsed).toString() + " GB");
Terminal.executeFreeCommand(commandArray);
break;
case "hack":
if (commandArray.length != 1) {
@ -475,27 +596,7 @@ var Terminal = {
post("No such script is running. Nothing to kill");
break;
case "ls":
if (commandArray.length != 1) {
post("Incorrect usage of ls command. Usage: ls"); return;
}
//Display all programs and scripts
var allFiles = [];
//Get all of the programs and scripts on the machine into one temporary array
for (var i = 0; i < Player.getCurrentServer().programs.length; i++) {
allFiles.push(Player.getCurrentServer().programs[i]);
}
for (var i = 0; i < Player.getCurrentServer().scripts.length; i++) {
allFiles.push(Player.getCurrentServer().scripts[i].filename);
}
//Sort the files alphabetically then print each
allFiles.sort();
for (var i = 0; i < allFiles.length; i++) {
post(allFiles[i]);
}
Terminal.executeListCommand(commandArray);
break;
case "nano":
if (commandArray.length != 2) {
@ -530,34 +631,7 @@ var Terminal = {
break;
case "netstat":
case "scan":
if (commandArray.length != 1) {
post("Incorrect usage of netstat/scan command. Usage: netstat/scan"); return;
}
//Displays available network connections using TCP
post("Hostname IP Root Access");
for (var i = 0; i < Player.getCurrentServer().serversOnNetwork.length; i++) {
//Add hostname
var entry = Player.getCurrentServer().getServerOnNetwork(i).hostname;
//Calculate padding and add IP
var numSpaces = 21 - entry.length;
var spaces = Array(numSpaces+1).join(" ");
entry += spaces;
entry += Player.getCurrentServer().getServerOnNetwork(i).ip;
//Calculate padding and add root access info
var hasRoot;
if (Player.getCurrentServer().getServerOnNetwork(i).hasAdminRights) {
hasRoot = 'Y';
} else {
hasRoot = 'N';
}
numSpaces = 21 - Player.getCurrentServer().getServerOnNetwork(i).ip.length;
spaces = Array(numSpaces+1).join(" ");
entry += spaces;
entry += hasRoot;
post(entry);
}
Terminal.executeScanCommand(commandArray);
break;
case "ps":
if (commandArray.length != 1) {
@ -616,6 +690,17 @@ var Terminal = {
case "scp":
//TODO
break;
case "sudov":
if (commandArray.length != 1) {
post("Incorrect number of arguments. Usage: sudov"); return;
}
if (Player.getCurrentServer().hasAdminRights) {
post("You have ROOT access to this machine");
} else {
post("You do NOT have root access to this machine");
}
break;
case "tail":
if (commandArray.length != 2) {
post("Incorrect number of arguments. Usage: tail [script]");
@ -648,6 +733,72 @@ var Terminal = {
}
},
executeListCommand: function(commandArray) {
if (commandArray.length != 1) {
post("Incorrect usage of ls command. Usage: ls"); return;
}
//Display all programs and scripts
var allFiles = [];
//Get all of the programs and scripts on the machine into one temporary array
for (var i = 0; i < Player.getCurrentServer().programs.length; i++) {
allFiles.push(Player.getCurrentServer().programs[i]);
}
for (var i = 0; i < Player.getCurrentServer().scripts.length; i++) {
allFiles.push(Player.getCurrentServer().scripts[i].filename);
}
//Sort the files alphabetically then print each
allFiles.sort();
for (var i = 0; i < allFiles.length; i++) {
post(allFiles[i]);
}
},
executeScanCommand: function(commandArray) {
if (commandArray.length != 1) {
post("Incorrect usage of netstat/scan command. Usage: netstat/scan"); return;
}
//Displays available network connections using TCP
post("Hostname IP Root Access");
for (var i = 0; i < Player.getCurrentServer().serversOnNetwork.length; i++) {
//Add hostname
var entry = Player.getCurrentServer().getServerOnNetwork(i);
if (entry == null) {continue;}
entry = entry.hostname;
//Calculate padding and add IP
var numSpaces = 21 - entry.length;
var spaces = Array(numSpaces+1).join(" ");
entry += spaces;
entry += Player.getCurrentServer().getServerOnNetwork(i).ip;
//Calculate padding and add root access info
var hasRoot;
if (Player.getCurrentServer().getServerOnNetwork(i).hasAdminRights) {
hasRoot = 'Y';
} else {
hasRoot = 'N';
}
numSpaces = 21 - Player.getCurrentServer().getServerOnNetwork(i).ip.length;
spaces = Array(numSpaces+1).join(" ");
entry += spaces;
entry += hasRoot;
post(entry);
}
},
executeFreeCommand: function(commandArray) {
if (commandArray.length != 1) {
post("Incorrect usage of free command. Usage: free"); return;
}
post("Total: " + formatNumber(Player.getCurrentServer().maxRam, 2) + " GB");
post("Used: " + formatNumber(Player.getCurrentServer().ramUsed, 2) + " GB");
post("Available: " + formatNumber(Player.getCurrentServer().maxRam - Player.getCurrentServer().ramUsed, 2) + " GB");
},
//First called when the "run [program]" command is called. Checks to see if you
//have the executable and, if you do, calls the executeProgram() function
runProgram: function(programName) {

@ -22,6 +22,7 @@ var Engine = {
tutorialNetworkingButton: null,
tutorialHackingButton: null,
tutorialScriptsButton: null,
tutorialNetscriptButton: null,
tutorialTravelingButton: null,
tutorialJobsButton: null,
tutorialFactionsButton: null,
@ -267,10 +268,11 @@ var Engine = {
'Hacknet Node level upgrade cost multiplier: ' + formatNumber(Player.hacknet_node_level_cost_mult * 100, 2) + '%<br><br>' +
'Company reputation gain multiplier: ' + formatNumber(Player.company_rep_mult * 100, 2) + '%<br>' +
'Faction reputation gain multiplier: ' + formatNumber(Player.faction_rep_mult * 100, 2) + '%<br>' +
'Salary multiplier: ' + formatNumber(Player.work_money_mult * 100, 2) + '%<br><br><br>' +
'Salary multiplier: ' + formatNumber(Player.work_money_mult * 100, 2) + '%<br>' +
'Crime money multiplier: ' + formatNumber(Player.crime_money_mult * 100, 2) + '%<br><br><br>' +
'<b>Misc</b><br><br>' +
'Servers owned: ' + Player.purchasedServers.length + '<br>' +
'Hacknet Nodes owned: ' + Player.hacknetNodes.length + '<br>').replace( / /g, "&nbsp;" );
'Hacknet Nodes owned: ' + Player.hacknetNodes.length + '<br><br> ').replace( / /g, "&nbsp;" );
},
@ -290,7 +292,10 @@ var Engine = {
Engine.ishimaLocationsList.style.display = "none";
Engine.volhavenLocationsList.style.display = "none";
document.getElementById("world-city-name").innerHTML = Player.city;
var cityDesc = document.getElementById("world-city-desc"); //TODO
switch(Player.city) {
case Locations.Aevum:
Engine.aevumLocationsList.style.display = "inline";
break;
@ -438,6 +443,10 @@ var Engine = {
displayAugmentationsContent: function() {
var augmentationsList = document.getElementById("augmentations-list");
while (augmentationsList.firstChild) {
augmentationsList.removeChild(augmentationsList.firstChild);
}
for (var i = 0; i < Player.augmentations.length; ++i) {
var augName = Player.augmentations[i];
var aug = Augmentations[augName];
@ -449,6 +458,9 @@ var Engine = {
item.setAttribute("class", "installed-augmentation");
hElem.innerHTML = augName;
if (augName == AugmentationNames.NeuroFluxGovernor) {
hElem.innerHTML += " - Level " + (aug.level);
}
pElem.innerHTML = aug.info;
item.appendChild(hElem);
@ -463,6 +475,7 @@ var Engine = {
Engine.Clickables.tutorialNetworkingButton.style.display = "block";
Engine.Clickables.tutorialHackingButton.style.display = "block";
Engine.Clickables.tutorialScriptsButton.style.display = "block";
Engine.Clickables.tutorialNetscriptButton.style.display = "block";
Engine.Clickables.tutorialTravelingButton.style.display = "block";
Engine.Clickables.tutorialJobsButton.style.display = "block";
Engine.Clickables.tutorialFactionsButton.style.display = "block";
@ -478,6 +491,7 @@ var Engine = {
Engine.Clickables.tutorialNetworkingButton.style.display = "none";
Engine.Clickables.tutorialHackingButton.style.display = "none";
Engine.Clickables.tutorialScriptsButton.style.display = "none";
Engine.Clickables.tutorialNetscriptButton.style.display = "none";
Engine.Clickables.tutorialTravelingButton.style.display = "none";
Engine.Clickables.tutorialJobsButton.style.display = "none";
Engine.Clickables.tutorialFactionsButton.style.display = "none";
@ -530,6 +544,8 @@ var Engine = {
Player.takeClass(numCycles);
} else if (Player.workType == CONSTANTS.WorkTypeCrime) {
Player.commitCrime(numCycles);
} else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) {
Player.workPartTime(numCycles);
} else {
Player.work(numCycles);
}
@ -557,6 +573,7 @@ var Engine = {
autoSaveCounter: 300, //Autosave every minute
updateSkillLevelsCounter: 10, //Only update skill levels every 2 seconds. Might improve performance
updateDisplays: 3, //Update displays such as Active Scripts display and character display
createProgramNotifications: 10, //Checks whether any programs can be created and notifies
serverGrowth: 450, //Process server growth every minute and a half
checkFactionInvitations: 1500, //Check whether you qualify for any faction invitations every 5 minutes
passiveFactionGrowth: 600,
@ -590,11 +607,26 @@ var Engine = {
Engine.displayCharacterInfo();
} else if (Engine.currentPage == Engine.Page.HacknetNodes) {
updateHacknetNodesContent();
} else if (Engine.currentPage == Engine.Page.CreateProgram) {
displayCreateProgramContent();
}
Engine.Counters.updateDisplays = 3;
}
if (Engine.Counters.createProgramNotifications <= 0) {
var num = getNumAvailableCreateProgram();
var elem = document.getElementById("create-program-notification");
if (num > 0) {
elem.innerHTML = num;
elem.setAttribute("class", "notification-on");
} else {
elem.innerHTML = "";
elem.setAttribute("class", "notification-off");
}
Engine.Counters.createProgramNotifications = 10;
}
if (Engine.Counters.serverGrowth <= 0) {
var numCycles = Math.floor((450 - Engine.Counters.serverGrowth));
processServerGrowth(numCycles);
@ -652,131 +684,63 @@ var Engine = {
}
},
/* Initialization */
init: function() {
//Main menu buttons and content
Engine.Clickables.terminalMainMenuButton = document.getElementById("terminal-menu-link");
Engine.Clickables.terminalMainMenuButton.addEventListener("click", function() {
Engine.loadTerminalContent();
return false;
});
load: function() {
//Load game from save or create new game
if (loadGame(saveObject)) {
console.log("Loaded game from save");
Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.init(); //Initialize buttons, work, etc.
Engine.start(); //Run main game loop and Scripts loop
CompanyPositions.init();
Engine.Clickables.characterMainMenuButton = document.getElementById("character-menu-link");
Engine.Clickables.characterMainMenuButton.addEventListener("click", function() {
Engine.loadCharacterContent();
return false;
});
//Calculate the number of cycles have elapsed while offline
var thisUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate;
var numCyclesOffline = Math.floor((thisUpdate - lastUpdate) / Engine._idleSpeed);
Engine.Clickables.scriptEditorMainMenuButton = document.getElementById("create-script-menu-link");
Engine.Clickables.scriptEditorMainMenuButton.addEventListener("click", function() {
Engine.loadScriptEditorContent();
return false;
});
/* Process offline progress */
processServerGrowth(numCyclesOffline); //Should be done before offline production for scripts
loadAllRunningScripts(); //This also takes care of offline production for those scripts
if (Player.isWorking) {
if (Player.workType == CONSTANTS.WorkTypeFaction) {
Player.workForFaction(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
Player.createProgramWork(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
Player.takeClass(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCrime) {
Player.commitCrime(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) {
Player.workPartTime(numCyclesOffline);
} else {
Player.work(numCyclesOffline);
}
}
Engine.Clickables.activeScriptsMainMenuButton = document.getElementById("active-scripts-menu-link");
Engine.Clickables.activeScriptsMainMenuButton.addEventListener("click", function() {
Engine.loadActiveScriptsContent();
return false;
});
//Hacknet Nodes offline progress
processAllHacknetNodeEarnings(numCyclesOffline);
Engine.Clickables.hacknetNodesMainMenuButton = document.getElementById("hacknet-nodes-menu-link");
Engine.Clickables.hacknetNodesMainMenuButton.addEventListener("click", function() {
Engine.loadHacknetNodesContent();
return false;
});
Engine.Clickables.worldMainMenuButton = document.getElementById("world-menu-link");
Engine.Clickables.worldMainMenuButton.addEventListener("click", function() {
Engine.loadWorldContent();
return false;
});
Engine.Clickables.createProgramMainMenuButton = document.getElementById("create-program-menu-link");
Engine.Clickables.createProgramMainMenuButton.addEventListener("click", function() {
Engine.loadCreateProgramContent();
return false;
});
Engine.Clickables.factionsMainMenuButton = document.getElementById("factions-menu-link");
Engine.Clickables.factionsMainMenuButton.addEventListener("click", function() {
Engine.loadFactionsContent();
return false;
});
Engine.Clickables.augmentationsMainMenuButton = document.getElementById("augmentations-menu-link");
Engine.Clickables.augmentationsMainMenuButton.addEventListener("click", function() {
Engine.loadAugmentationsContent();
return false;
});
Engine.Clickables.tutorialMainMenuButton = document.getElementById("tutorial-menu-link");
Engine.Clickables.tutorialMainMenuButton.addEventListener("click", function() {
Engine.loadTutorialContent();
return false;
});
//Active scripts list
Engine.ActiveScriptsList = document.getElementById("active-scripts-list");
Engine.Clickables.saveMainMenuButton = document.getElementById("save-game-link");
Engine.Clickables.saveMainMenuButton.addEventListener("click", function() {
saveObject.saveGame();
return false;
});
Engine.Clickables.deleteMainMenuButton = document.getElementById("delete-game-link");
Engine.Clickables.deleteMainMenuButton.addEventListener("click", function() {
saveObject.deleteGame();
return false;
});
//Tutorial buttons
Engine.Clickables.tutorialGettingStartedButton = document.getElementById("tutorial-getting-started-link");
Engine.Clickables.tutorialGettingStartedButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialGettingStartedText);
});
Engine.Clickables.tutorialNetworkingButton = document.getElementById("tutorial-networking-link");
Engine.Clickables.tutorialNetworkingButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialNetworkingText);
});
Engine.Clickables.tutorialHackingButton = document.getElementById("tutorial-hacking-link");
Engine.Clickables.tutorialHackingButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialHackingText);
});
Engine.Clickables.tutorialScriptsButton = document.getElementById("tutorial-scripts-link");
Engine.Clickables.tutorialScriptsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialScriptsText);
});
Engine.Clickables.tutorialTravelingButton = document.getElementById("tutorial-traveling-link");
Engine.Clickables.tutorialTravelingButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialTravelingText);
});
Engine.Clickables.tutorialJobsButton = document.getElementById("tutorial-jobs-link");
Engine.Clickables.tutorialJobsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialJobsText);
});
Engine.Clickables.tutorialFactionsButton = document.getElementById("tutorial-factions-link");
Engine.Clickables.tutorialFactionsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialFactionsText);
});
Engine.Clickables.tutorialAugmentationsButton = document.getElementById("tutorial-augmentations-link");
Engine.Clickables.tutorialAugmentationsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialAugmentationsText);
});
Engine.Clickables.tutorialBackButton = document.getElementById("tutorial-back-button");
Engine.Clickables.tutorialBackButton.addEventListener("click", function() {
Engine.displayTutorialContent();
});
//Passive faction rep gain offline
processPassiveFactionRepGain(numCyclesOffline);
} else {
//No save found, start new game
console.log("Initializing new game");
SpecialServerIps = new SpecialServerIpsMap();
Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.start(); //Run main game loop and Scripts loop
Player.init();
initForeignServers();
initCompanies();
initFactions();
CompanyPositions.init();
initAugmentations();
//Start interactive tutorial
iTutorialStart();
}
},
setDisplayElements: function() {
//Content elements
Engine.Display.terminalContent = document.getElementById("terminal-container");
Engine.currentPage = Engine.Page.Terminal;
@ -840,52 +804,172 @@ var Engine = {
//Script editor
Engine.Display.scriptEditorText = document.getElementById("script-editor-text");
//Load game from save or create new game
if (loadGame(saveObject)) {
console.log("Loaded game from save");
CompanyPositions.init();
//Tutorial buttons
Engine.Clickables.tutorialGettingStartedButton = document.getElementById("tutorial-getting-started-link");
Engine.Clickables.tutorialGettingStartedButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialGettingStartedText);
});
//Calculate the number of cycles have elapsed while offline
var thisUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate;
var numCyclesOffline = Math.floor((thisUpdate - lastUpdate) / Engine._idleSpeed);
Engine.Clickables.tutorialNetworkingButton = document.getElementById("tutorial-networking-link");
Engine.Clickables.tutorialNetworkingButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialNetworkingText);
});
/* Process offline progress */
processServerGrowth(numCyclesOffline); //Should be done before offline production for scripts
loadAllRunningScripts(); //This also takes care of offline production for those scripts
if (Player.isWorking) {
if (Player.workType == CONSTANTS.WorkTypeFaction) {
Player.workForFaction(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
Player.createProgramWork(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
Player.takeClass(numCyclesOffline);
} else {
Player.work(numCyclesOffline);
}
Engine.Clickables.tutorialHackingButton = document.getElementById("tutorial-hacking-link");
Engine.Clickables.tutorialHackingButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialHackingText);
});
Engine.Clickables.tutorialScriptsButton = document.getElementById("tutorial-scripts-link");
Engine.Clickables.tutorialScriptsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialScriptsText);
});
Engine.Clickables.tutorialNetscriptButton = document.getElementById("tutorial-netscript-link");
Engine.Clickables.tutorialNetscriptButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialNetscriptText);
});
Engine.Clickables.tutorialTravelingButton = document.getElementById("tutorial-traveling-link");
Engine.Clickables.tutorialTravelingButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialTravelingText);
});
Engine.Clickables.tutorialJobsButton = document.getElementById("tutorial-jobs-link");
Engine.Clickables.tutorialJobsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialJobsText);
});
Engine.Clickables.tutorialFactionsButton = document.getElementById("tutorial-factions-link");
Engine.Clickables.tutorialFactionsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialFactionsText);
});
Engine.Clickables.tutorialAugmentationsButton = document.getElementById("tutorial-augmentations-link");
Engine.Clickables.tutorialAugmentationsButton.addEventListener("click", function() {
Engine.displayTutorialPage(CONSTANTS.TutorialAugmentationsText);
});
Engine.Clickables.tutorialBackButton = document.getElementById("tutorial-back-button");
Engine.Clickables.tutorialBackButton.addEventListener("click", function() {
Engine.displayTutorialContent();
});
//If DarkWeb already purchased, disable the button
if (SpecialServerIps.hasOwnProperty("Darkweb Server")) {
document.getElementById("location-purchase-tor").setAttribute("class", "a-link-button-inactive");
}
},
//Hacknet Nodes offline progress
processAllHacknetNodeEarnings(numCyclesOffline);
/* Initialization */
init: function() {
//Main menu buttons and content
Engine.Clickables.terminalMainMenuButton = clearEventListeners("terminal-menu-link");
Engine.Clickables.terminalMainMenuButton.addEventListener("click", function() {
Engine.loadTerminalContent();
return false;
});
//Passive faction rep gain offline
processPassiveFactionRepGain(numCyclesOffline);
} else {
//No save found, start new game
console.log("Initializing new game");
SpecialServerIps = new SpecialServerIpsMap();
Player.init();
initForeignServers();
initCompanies();
initFactions();
CompanyPositions.init();
initAugmentations();
}
Engine.Clickables.characterMainMenuButton = clearEventListeners("character-menu-link");
Engine.Clickables.characterMainMenuButton.addEventListener("click", function() {
Engine.loadCharacterContent();
return false;
});
Engine.Clickables.scriptEditorMainMenuButton = clearEventListeners("create-script-menu-link");
Engine.Clickables.scriptEditorMainMenuButton.addEventListener("click", function() {
Engine.loadScriptEditorContent();
return false;
});
Engine.Clickables.activeScriptsMainMenuButton = clearEventListeners("active-scripts-menu-link");
Engine.Clickables.activeScriptsMainMenuButton.addEventListener("click", function() {
Engine.loadActiveScriptsContent();
return false;
});
Engine.Clickables.hacknetNodesMainMenuButton = clearEventListeners("hacknet-nodes-menu-link");
Engine.Clickables.hacknetNodesMainMenuButton.addEventListener("click", function() {
Engine.loadHacknetNodesContent();
return false;
});
Engine.Clickables.worldMainMenuButton = clearEventListeners("world-menu-link");
Engine.Clickables.worldMainMenuButton.addEventListener("click", function() {
Engine.loadWorldContent();
return false;
});
Engine.Clickables.createProgramMainMenuButton = clearEventListeners("create-program-menu-link");
Engine.Clickables.createProgramMainMenuButton.addEventListener("click", function() {
Engine.loadCreateProgramContent();
return false;
});
Engine.Clickables.factionsMainMenuButton = clearEventListeners("factions-menu-link");
Engine.Clickables.factionsMainMenuButton.addEventListener("click", function() {
Engine.loadFactionsContent();
return false;
});
Engine.Clickables.augmentationsMainMenuButton = clearEventListeners("augmentations-menu-link");
Engine.Clickables.augmentationsMainMenuButton.addEventListener("click", function() {
Engine.loadAugmentationsContent();
return false;
});
Engine.Clickables.tutorialMainMenuButton = clearEventListeners("tutorial-menu-link");
Engine.Clickables.tutorialMainMenuButton.addEventListener("click", function() {
Engine.loadTutorialContent();
return false;
});
//Active scripts list
Engine.ActiveScriptsList = document.getElementById("active-scripts-list");
//Save and Delete buttons
Engine.Clickables.saveMainMenuButton = document.getElementById("save-game-link");
Engine.Clickables.saveMainMenuButton.addEventListener("click", function() {
saveObject.saveGame();
return false;
});
Engine.Clickables.deleteMainMenuButton = document.getElementById("delete-game-link");
Engine.Clickables.deleteMainMenuButton.addEventListener("click", function() {
saveObject.deleteGame();
return false;
});
//Create Program buttons
var portHackALink = 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() {
createProgram(Programs.PortHackProgram, CONSTANTS.MillisecondsPerQuarterHour);
});
bruteSshALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.BruteSSHProgram, CONSTANTS.MillisecondsPerQuarterHour);
});
ftpCrackALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.FTPCrackProgram, CONSTANTS.MillisecondsPerHalfHour);
});
relaySmtpALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.RelaySMTPProgram. CONSTANTS.MillisecondsPer2Hours);
});
httpWormALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.HTTPWormProgram, CONSTANTS.MillisecondsPer4Hours);
});
sqlInjectALink.addEventListener("click", function() {
Player.startCreateProgramWork(Programs.SQLInjectProgram, CONSTANTS.MillisecondsPer8Hours);
});
//Message at the top of terminal
postNetburnerText();
//Player was working
//Player was working cancel button
if (Player.isWorking) {
var cancelButton = document.getElementById("work-in-progress-cancel-button");
cancelButton.addEventListener("click", function() {
@ -896,14 +980,19 @@ var Engine = {
Player.finishCreateProgramWork(true, Player.createProgramName);
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
Player.finishClass();
} else if (Player.workType == CONSTANTS.WorkTypeCrime) {
Player.finishCrime(true);
} else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) {
Player.finishWorkPartTime();
} else {
Player.finishWork(true);
}
});
Engine.loadWorkInProgressContent();
}
},
start: function() {
//Run main loop
Engine.idleTimer();
@ -913,7 +1002,7 @@ var Engine = {
};
window.onload = function() {
Engine.init();
Engine.load();
};

@ -13,9 +13,6 @@ function dialogBoxInit() {
document.addEventListener("DOMContentLoaded", dialogBoxInit, false);
dialogBoxClose = function() {
if (Engine.Debug) {
console.log("Dialog Box Close called");
}
var dialogBox = document.getElementById("dialog-box-container");
dialogBox.style.display = "none";
}

@ -36,9 +36,10 @@ factionInvitationBoxCreate = function(faction) {
factionInvitationSetText("You have received a faction invitation from " + faction.name);
//TODO Faction invitation message
var yesButton = document.getElementById("faction-invitation-box-yes");
var newYesButton = yesButton.cloneNode(true);
yesButton.parentNode.replaceChild(newYesButton, yesButton);
var newYesButton = clearEventListeners("faction-invitation-box-yes");
//var yesButton = document.getElementById("faction-invitation-box-yes");
//var newYesButton = yesButton.cloneNode(true);
//yesButton.parentNode.replaceChild(newYesButton, yesButton);
newYesButton.addEventListener("click", function() {
joinFaction(faction);

@ -13,9 +13,19 @@ function sizeOfObject(obj) {
//e.g. addOffset(100, 5) will return anything from 95 to 105.
//The percentage argument must be between 0 and 100;
function addOffset(n, percentage) {
if (percentage < 0 || percentage > 100) {return ;}
if (percentage < 0 || percentage > 100) {return;}
var offset = n * (percentage / 100);
return n * (Math.random() * (2 * offset) - offset);
return n + ((Math.random() * (2 * offset)) - offset);
}
//Given an element by its Id(usually an 'a' element), removes all event listeners
//from that element by cloning and replacing. Then returns the new cloned element
function clearEventListeners(elemId) {
var elem = document.getElementById(elemId);
if (elem == null) {console.log("ERR: Could not find element for: " + elemId); return null;}
var newElem = elem.cloneNode(true);
elem.parentNode.replaceChild(newElem, elem);
return newElem;
}

@ -9,6 +9,7 @@ function Reviver(key, value) {
var ctor;
if (value == null) {
console.log("Reviver WRONGLY called with key: " + key + ", and value: " + value);
return 0;
}
if (typeof value === "object" &&
typeof value.ctor === "string" &&

@ -28,14 +28,13 @@ purchaseAugmentationBoxSetText = function(txt) {
//ram argument is in GB
purchaseAugmentationBoxCreate = function(aug, fac) {
console.log("here");
purchaseAugmentationBoxSetText("Would you like to purchase the " + aug.name + " Augmentation for $" +
(aug.baseCost * fac.augmentationPriceMult) + "?");
document.getElementById("purchase-augmentation-box-aug-name").innerHTML = aug.name;
document.getElementById("purchase-augmentation-box-aug-info").innerHTML = aug.info;
purchaseAugmentationBoxSetText("<br>Would you like to purchase the " + aug.name + " Augmentation for $" +
formatNumber(aug.baseCost * fac.augmentationPriceMult, 2) + "?");
//Clear old event listeners from Confirm button
var confirmButton = document.getElementById("purchase-augmentation-box-confirm");
var newConfirmButton = confirmButton.cloneNode(true);
confirmButton.parentNode.replaceChild(newConfirmButton, confirmButton);
var newConfirmButton = clearEventListeners("purchase-augmentation-box-confirm");
newConfirmButton.addEventListener("click", function() {

@ -34,22 +34,20 @@ purchaseRamForHomeBoxCreate = function() {
var numUpgrades = Math.log2(currentRam);
//Calculate cost
//Base cost of RAM is 50k per 1GB...but lets have this increase by 10% for every time
//Base cost of RAM is 50k per 1GB...but lets have this increase by 21% for every time
//the RAM has been upgraded
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRam;
var mult = Math.pow(1.1, numUpgrades);
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome;
var mult = Math.pow(1.21, numUpgrades);
cost = cost * mult;
purchaseRamForHomeBoxSetText("Would you like to purchase additional RAM for your home computer? <br><br>" +
"This will upgrade your RAM from " + currentRam + "GB to " + newRam + "GB. <br><br>" +
"This will cost $" + cost);
"This will cost $" + formatNumber(cost, 2));
purchaseRamForHomeBoxOpen();
//Clear old event listeners from Confirm button
var confirmButton = document.getElementById("purchase-ram-for-home-box-confirm");
var newConfirmButton = confirmButton.cloneNode(true);
confirmButton.parentNode.replaceChild(newConfirmButton, confirmButton);
var newConfirmButton = clearEventListeners("purchase-ram-for-home-box-confirm");
newConfirmButton.addEventListener("click", function() {
purchaseRamForHomeBoxClose();
purchaseRamForHomeComputer(cost);

@ -31,9 +31,7 @@ purchaseServerBoxCreate = function(ram, cost) {
purchaseServerBoxSetText("Would you like to purchase a new server with " + ram + "GB of RAM for $" + cost + "?" );
//Clear old event listeners from Confirm button
var confirmButton = document.getElementById("purchase-server-box-confirm");
var newConfirmButton = confirmButton.cloneNode(true);
confirmButton.parentNode.replaceChild(newConfirmButton, confirmButton);
var newConfirmButton = clearEventListeners("purchase-server-box-confirm");
newConfirmButton.addEventListener("click", function() {
purchaseServerBoxClose();
purchaseServer(ram, cost);

@ -72,3 +72,21 @@ function formatNumber(num, numFractionDigits) {
maximumFractionDigits: numFractionDigits
});
}
//Counters the number of times a substring occurs in a string
function numOccurrences(string, subString) {
string += "";
subString += "";
if (subString.length <= 0) return (string.length + 1);
var n = 0, pos = 0, step = subString.length;
while (true) {
pos = string.indexOf(subString, pos);
if (pos >= 0) {
++n;
pos += step;
} else break;
}
return n;
}

@ -30,9 +30,10 @@ travelBoxCreate = function(destCityName, cost) {
travelBoxSetText("Would you like to travel to " + destCityName + "? The trip will cost $" + cost + ".");
//Clear old event listeners from Confirm button
var confirmButton = document.getElementById("travel-box-confirm");
var newConfirmButton = confirmButton.cloneNode(true);
confirmButton.parentNode.replaceChild(newConfirmButton, confirmButton);
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);