Merge pull request #23 from danielyxie/dev

Dev v0.15
This commit is contained in:
danielyxie
2017-05-23 15:37:10 -04:00
committed by GitHub
15 changed files with 201 additions and 175 deletions

View File

@ -1,129 +0,0 @@
Cyberpunk theme for now. Hacking? Play Hacknet through to get ideas
Requirements:
Prestige mechanic for replayability (Ascension)
Good progression system
A prestige system does offer a sense of progression, but its better to have multiple systems that allow for progression. For example clicker heroes had ascending, transcending, gilding, Ancients, etc.
Complexity and variety
Different types of gameplay, idle vs active
Allow for different strategies through upgrades (or the faction system like in Realm Grinder)
Crafting
Maybe reward active gameplay by allowing players to find things that allow them to craft. This isn't doable with idle gameplay
Multiplayer, maybe? Hacking other people
People seem to like comparing themselves to others (leaderboards, high scores, etc.)
People like a sense of exploration/discovery
RPG Elements
Suggestions from other people:
For me it's quite important to be able to do stuff differently, I want choice. Realm Grinder and its Mercenary, Research and Faction system is the perfect
example for it. Different factions have different perks and spells, later on you can make your own faction out of everyone and you can further customize
your playstyle by the research skill tree mid-game. I feel like that it is important that you can do other stuff each time you prestige, not just "click-level up-reset".
That might've sparked some ideas, if not something to consider in future content updates.
What I really hate about CH1 is the fact that your Mercs can die [and can only be revived with premium currency (though you can earn a fair amount of it while playing!)],
I don't like when a incremental game punishes me in any way. This is literally why I stopped Tap Titans even though I had a lot of fun with it! I know that some people
really want some kind of challenge or something, just look at Kittens Game and how many people love it.
Also, watch this video about Unfolding Games. It's not just addiction or a formula-that-works that keeps people here, or choice, or multiplayer - it's discovery. I want
to discover something new, not yet another "10 kills til next stage, every 5 is bosses who eventually give prestige currency" game. I want to wonder what comes next even
as I have my eyes on a visible goal. I want to unlock something and be surprised at the features that are enabled next. There are many, many games that do this successfully - just ask for me examples.
Keep in mind that the draw of Clicker Heroes, and indeed most of these games, is that it's an RPG without all the things people don't care about. Take a different aspect
of the RPG and make it part of your idle game, and you've made something new. So far it's got the "kill things for more gold for more ability to kill things, with diminishing returns"
aspect, but that's not all there is. Adding quests, adding more currency, adding skills, adding talent trees, adding travel time, adding monster variability, etc. all fits
the same underlying theme, as long as you keep them engaging and fun.
Hacking background Terminology (and stuff Hacknet game does)
Compromising the security of another computer is illegal under USC ACT 1030-18
Botnet
HackNet commands:
probe command to analyze open ports and security (or nmap)
SSHCrack [Port number] (usually 22)
PortHack [Port number] (usually 80, after ports are cracked)
FTPBounce [Port number] (usually 21)
SMTPoverflow [Port number] (usually 25)
WebServerWorm [Port number] (usually 80) - for HTTP port
SQL_MemCorrupt [Port number] (usually 1433) - The public-facing SQL ports
Decypher to decrypt something
Firewall
Analyze several times
Solve [FIREWALL_SOLUTION] to attempt to syndicate firewall
scp to download files
Shell command
Create a shell on your computer and you can overload proxys
forkbomb Down a system in a hurry
Trace - Traces you when you try to hack, takes some amount of time
Proxy Servers function as a buffering layer between a target computer and a connecting counterpart that filters,
caches, and monitors incoming traffic to both optimize web performacne for repeated queries, and prevent
some kinds of attacks. the most well-recognized flaw in proxy servers is their upper memory limit - which
when reached will force them to allow unchecked traffic to pass trhough. To exploit this, hackers and testers will
often run Shells on other computers that an attack has access to. Then, with a collection of shells on
servant machines, will connect to a target computer, and use the shells "overload" funcitonality to flood
the target proxy server with junk data, allowing other, potentially harmful traffic through.
Netburner
Features:
Command line interface
Hack - Active hack
A hack takes time
Scripts - Automatically perform hacks and other actions
Allow people to write their own scripts?
So, people could write their own complicate scripts
Servers - Allow you to run more hacks. Allow you to hack idly
Computers - More powerful hacks, more hacks
CPU usage stats that lets you do more stuff, goes up as you upgrade?
Hire people
Join different factions (each with different advantages)
Police
Cybersecurity
Hacker group
Botnet
Create and sell botnet
Use botnet to DDOS
Start with only command line, you can develop a GUI after a little
Eventually you can join a gym and go to the gym to train your stats. This can be done idly
Allow people to take jobs to earn money. Working a job can be done idly
Bitcoin - You can exchange USD for bitcoins. Bitcoin exchange rate reflects real exchange rate
Persistent companies, as in companies that stay there through ascensions and you hacking them will
affect their performance. So if you hack something it might give you 100k, but then hacking it again
right away will give less like 99k. Diminishing returns. Therefore you have to stop hacking it for a
little to to allow it to give full rewards again
Character stats:
Hacking skill
Strength - How much damage you give
Defense - How much damage you take
Agility - How fast you attack and dodge %
Dexterity - Accuracy
Prestige system
Ascend
Reset all stats, computers, scripts, get an augmentation
Reincarnate
Reset all stats and augmentations
Get some kind of big powerup for the next run
Crafting
Let's start small at first and add this in later

View File

@ -162,7 +162,7 @@
}
#hacknet-nodes-purchase-button {
display: block;
display: inline-block;
}
#hacknet-nodes-money-multipliers-div {
@ -234,7 +234,7 @@
color: #FFFFFF;
padding: 4px;
border: 1px solid #333333;
width: 50%;
/*width: 30%;*/
}
.create-program-a-link-button-inactive {
@ -259,6 +259,7 @@
margin-left: 10%;
width: 99%;
color: #66ff33;
overflow-y: auto;
}
#faction-container {
@ -268,6 +269,7 @@
height: 100%;
margin-left: 10%;
width: 90%;
overflow-y: auto;
}
#factions-list li {

View File

@ -92,7 +92,7 @@ tr:focus {
padding: 5px;
margin: 5px;
border: 1px solid #333333;
width: 50%;
/*width: 30%;*/
}
.a-link-button:hover {
@ -112,7 +112,7 @@ tr:focus {
border-left: 1px solid #333333;
pointer-events: none;
cursor: default;
width: 50%;
/*width: 50%;*/
}
@ -156,9 +156,10 @@ tr:focus {
color: white;
text-align: center;
padding: 4px;
left: 101%;
position: absolute;
z-index: 1;
z-index: 3;
}
.tooltip:hover .tooltiptext {

View File

@ -55,6 +55,7 @@
<script src="src/SaveObject.js"></script>
<script src="src/DarkWeb.js"></script>
<script src="src/InteractiveTutorial.js"></script>
<script src="src/Alias.js"></script>
<script src="src/engine.js"></script>
@ -180,6 +181,7 @@
in order to increase its computing power and thereby increase the profit you earn from it.
</p>
<a href="#" id="hacknet-nodes-purchase-button" class="a-link-button"> Purchase Hacknet Node </a>
<br>
<div id="hacknet-nodes-money-multipliers-div">"
<p id="hacknet-nodes-money"> </p>
<span id="hacknet-nodes-multipliers">

44
src/Alias.js Normal file
View File

@ -0,0 +1,44 @@
/* Alias.js */
Aliases = {};
//Print all aliases to terminal
function printAliases() {
for (var name in Aliases) {
if (Aliases.hasOwnProperty(name)) {
post("alias " + name + "=" + Aliases[name]);
}
}
}
//True if successful, false otherwise
function parseAliasDeclaration(dec) {
var re = /([^=]+)="(.+)"/;
var matches = dec.match(re);
if (matches == null || matches.length != 3) {return false;}
addAlias(matches[1], matches[2]);
return true;
}
function addAlias(name, value) {
Aliases[name] = value;
}
function getAlias(name) {
if (Aliases.hasOwnProperty(name)) {
return Aliases[name];
}
return null;
}
//Returns the original string with any aliases substituted in
//Aliases only applied to "whole words", one level deep
function substituteAliases(origCommand) {
var commandArray = origCommand.split(" ");
for (var i = 0; i < commandArray.length; ++i) {
var alias = getAlias(commandArray[i]);
if (alias != null) {
commandArray[i] = alias;
}
}
return commandArray.join(" ");
}

View File

@ -790,7 +790,7 @@ initAugmentations = function() {
HacknetNodeKernelDNI.setInfo("Installs a Direct-Neural Interface jack into the arm that is capable of connecting to a " +
"Hacknet Node. This lets the user access and manipulate the Node's kernel using the mind's " +
"electrochemical signals.<br><br>" +
"This augmentation increases the amount of money produced by Hacknet Nodes by 50%.");
"This augmentation increases the amount of money produced by Hacknet Nodes by 30%.");
HacknetNodeKernelDNI.addToFactions(["Netburners"]);
if (augmentationExists(AugmentationNames.HacknetNodeKernelDNI)) {
HacknetNodeKernelDNI.owned = Augmentations[AugmentationNames.HacknetNodeKernelDNI].owned;
@ -803,7 +803,7 @@ initAugmentations = function() {
HacknetNodeCoreDNI.setInfo("Installs a Direct-Neural Interface jack into the arm that is capable of connecting " +
"to a Hacknet Node. This lets the user access and manipulate the Node's processing logic using " +
"the mind's electrochemical signals.<br><br>" +
"This augmentation increases the amount of money produced by Hacknet Nodes by 75%.");
"This augmentation increases the amount of money produced by Hacknet Nodes by 50%.");
HacknetNodeCoreDNI.addToFactions(["Netburners"]);
if (augmentationExists(AugmentationNames.HacknetNodeCoreDNI)) {
HacknetNodeCoreDNI.owned = Augmentations[AugmentationNames.HacknetNodeCoreDNI].owned;
@ -1531,10 +1531,10 @@ applyAugmentation = function(aug, faction) {
Player.hacknet_node_purchase_cost_mult *= 0.9;
break;
case AugmentationNames.HacknetNodeKernelDNI:
Player.hacknet_node_money_mult *= 1.50;
Player.hacknet_node_money_mult *= 1.30;
break;
case AugmentationNames.HacknetNodeCoreDNI:
Player.hacknet_node_money_mult *= 1.75;
Player.hacknet_node_money_mult *= 1.50;
break;
//Misc augmentations
@ -1705,6 +1705,8 @@ applyAugmentation = function(aug, faction) {
case AugmentationNames.Neuregen:
Player.hacking_exp_mult *= 1.75;
break;
case AugmentationNames.CashRoot:
break;
case AugmentationNames.NutriGen:
Player.strength_exp_mult *= 1.2;
Player.defense_exp_mult *= 1.2;
@ -1751,6 +1753,11 @@ applyAugmentation = function(aug, faction) {
aug.owned = true;
aug.factionInstalledBy = faction.name;
if (aug.name == AugmentationNames.NeuroFluxGovernor &&
Player.augmentations.indexOf(AugmentationNames.NeuroFluxGovernor) != -1) {
//Already have this aug, just upgrade the level
return;
}
Player.augmentations.push(aug.name);
++Player.numAugmentations;
}

View File

@ -1,5 +1,5 @@
CONSTANTS = {
Version: "0.14",
Version: "0.15",
//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
@ -21,8 +21,8 @@ CONSTANTS = {
HacknetNodeMoneyGainPerLevel: 1.25,
HacknetNodePurchaseNextMult: 1.33, //Multiplier when purchasing an additional hacknet node
HacknetNodeUpgradeLevelMult: 1.04, //Multiplier for cost when upgrading level
HacknetNodeUpgradeRamMult: 1.21, //Multiplier for cost when upgrading RAM
HacknetNodeUpgradeCoreMult: 1.41, //Multiplier for cost when buying another core
HacknetNodeUpgradeRamMult: 1.22, //Multiplier for cost when upgrading RAM
HacknetNodeUpgradeCoreMult: 1.42, //Multiplier for cost when buying another core
HacknetNodeMaxLevel: 200,
HacknetNodeMaxRam: 64,
@ -110,12 +110,12 @@ CONSTANTS = {
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,
ClassDataStructuresBaseCost: 2,
ClassNetworksBaseCost: 10,
ClassAlgorithmsBaseCost: 40,
ClassManagementBaseCost: 20,
ClassLeadershipBaseCost: 40,
ClassGymBaseCost: 30,
CrimeShoplift: "shoplift",
CrimeMug: "mug someone",
@ -128,7 +128,8 @@ CONSTANTS = {
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>" +
HelpText: 'alias [name="value"] Create aliases for Terminal commands, or list existing aliases<br>' +
"analyze Get statistics and information about current machine <br>" +
"clear Clear all text on the terminal <br>" +
"cls See 'clear' command <br>" +
"connect [ip/hostname] Connects to the machine given by its IP or hostname <br>" +
@ -146,6 +147,7 @@ CONSTANTS = {
"rm Delete a script/program from the machine. (WARNING: Permanent)<br>" +
"run [script/program] Execute a program or a script<br>" +
"scan Displays all available network connections<br>" +
"scan-analyze Displays hacking-related information for all available network connections<br>" +
"sudov Shows whether or not you have root access on this computer<br>" +
"tail [script] Display script logs (logs contain details about active scripts)<br>" +
"top Display all running scripts and their RAM usage<br>",
@ -272,6 +274,9 @@ CONSTANTS = {
"be used to run scripts located on the same server. Returns true if the script is successfully started, and false otherwise. Requires a significant amount " +
"of RAM to run this command. Does NOT work while offline <br>Example: run('hack-foodnstuff.script'); <br> The example above will try and launch the 'hack-foodnstuff.script' script on " +
"the current server, if it exists. <br><br>" +
"<i>hasRootAccess(hostname/ip)</i><br> Returns a boolean (true or false) indicating whether or not the Player has root access to a server. " +
"The argument passed in must be a string with either the hostname or IP of the target server. Does NOT work while offline.<br> " +
"Example:<br>if (hasRootAccess('foodnstuff') == false) {<br>&nbsp;&nbsp;&nbsp;&nbsp;nuke('foodnstuff');<br>}<br><br>" +
"<i>getHackingLevel() </i><br> Returns the Player's current hacking level. Does NOT work while offline <br><br> " +
"<i>getServerMoneyAvailable(hostname/ip)</i><br> Returns the amount of money available on a server. The argument passed in must be a string with either the " +
"hostname or IP of the target server. Does NOT work while offline <br> Example: getServerMoneyAvailable('foodnstuff');<br><br>" +
@ -279,15 +284,16 @@ CONSTANTS = {
"a new hacknet node then the function will return an empty string. Does NOT work offline<br><br>" +
"<i>upgradeHacknetNode(name)</i><br> Upgrades the level of a Hacknet Node. The argument passed in must be a string with the name of the Hacknet Node to upgrade. " +
"If the Hacknet Node is successfully upgraded the function will return true. It will return false otherwise. Does NOT work offline. Example: <br>" +
"var node = purchaseHacknetNode();<br>" +
"node = purchaseHacknetNode();<br>" +
"if (node != '') {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;var i = 0;<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;i = 0;<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;while(i < 10) {<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (upgradeHacknetNode(node)) {i = i + 1;}<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;}; <br>" +
"};<br><br>" +
"The example code above will attempt to purchase a new Hacknet Node. If the Hacknet Node is purchased, then it will " +
"continuously try to level it up until it is leveled up 10 times. <br><br>" +
"<i>getNumHacknetNodes()</i><br> returns the number of Hacknet Nodes that the Player owns. Does NOT work while offline<br><br>" +
"<u><h1>While loops </h1></u><br>" +
"A while loop is a control flow statement that repeatedly executes code as long as a condition is met. <br><br> " +
"<i>while (<i>[cond]</i>) {<br>&nbsp;&nbsp;&nbsp;&nbsp;<i>[code]</i><br>}</i><br><br>" +

View File

@ -27,37 +27,37 @@ function displayCreateProgramContent() {
//NUKE.exe (in case you delete it lol)
if (Player.getHomeComputer().programs.indexOf(Programs.NukeProgram) == -1) {
nukeALink.style.display = "block";
nukeALink.style.display = "inline-block";
}
//BruteSSH
if (Player.getHomeComputer().programs.indexOf(Programs.BruteSSHProgram) == -1 &&
Player.hacking_skill >= 50) {
bruteSshALink.style.display = "block";
bruteSshALink.style.display = "inline-block";
}
//FTPCrack
if (Player.getHomeComputer().programs.indexOf(Programs.FTPCrackProgram) == -1 &&
Player.hacking_skill >= 100) {
ftpCrackALink.style.display = "block";
ftpCrackALink.style.display = "inline-block";
}
//relaySMTP
if (Player.getHomeComputer().programs.indexOf(Programs.RelaySMTPProgram) == -1 &&
Player.hacking_skill >= 250) {
relaySmtpALink.style.display = "block";
relaySmtpALink.style.display = "inline-block";
}
//HTTPWorm
if (Player.getHomeComputer().programs.indexOf(Programs.HTTPWormProgram) == -1 &&
Player.hacking_skill >= 500) {
httpWormALink.style.display = "block";
httpWormALink.style.display = "inline-block";
}
//SQLInject
if (Player.getHomeComputer().programs.indexOf(Programs.SQLInjectProgram) == -1 &&
Player.hacking_skill >= 750) {
sqlInjectALink.style.display = "block";
sqlInjectALink.style.display = "inline-block";
}
}

View File

@ -6,7 +6,7 @@ function factionInit() {
if (isPositiveNumber(val)) {
var numMoneyDonate = Number(val);
document.getElementById("faction-donate-rep-gain").innerHTML =
"This donation will result in " + formatNumber(numMoneyDonate/1000, 3) + " reputation gain";
"This donation will result in " + formatNumber(numMoneyDonate/1000 * Player.faction_rep_mult, 3) + " reputation gain";
} else {
document.getElementById("faction-donate-rep-gain").innerHTML =
"This donation will result in 0 reputation gain";
@ -585,7 +585,7 @@ displayFactionContent = function(factionName) {
return;
}
Player.loseMoney(numMoneyDonate);
var repGain = numMoneyDonate / 1000;
var repGain = numMoneyDonate / 1000 * Player.faction_rep_mult;
faction.playerReputation += repGain;
dialogBoxCreate("You just donated $" + formatNumber(numMoneyDonate, 2) + " to " +
faction.name + " to gain " + formatNumber(repGain, 3) + " reputation");
@ -790,19 +790,20 @@ displayFactionAugmentations = function(factionName) {
var aug = Augmentations[faction.augmentations[i]];
var item = document.createElement("li");
var span = document.createElement("span");
var aDiv = document.createElement("div");
var aElem = document.createElement("a");
var pElem = document.createElement("p");
aElem.setAttribute("href", "#");
var req = aug.baseRepRequirement * faction.augmentationRepRequirementMult;
if (aug.name != AugmentationNames.NeuroFluxGovernor && aug.owned) {
aElem.setAttribute("class", "a-link-button-inactive tooltip");
aElem.setAttribute("class", "a-link-button-inactive");
pElem.innerHTML = "ALREADY OWNED";
} else if (faction.playerReputation >= req) {
aElem.setAttribute("class", "a-link-button tooltip");
aElem.setAttribute("class", "a-link-button");
pElem.innerHTML = "UNLOCKED - $" + formatNumber(aug.baseCost * faction.augmentationPriceMult, 2);
} else {
aElem.setAttribute("class", "a-link-button-inactive tooltip");
pElem.innerHTML = "LOCKED (Requires " + formatNumber(req, 4) + " faction reputation)";
aElem.setAttribute("class", "a-link-button-inactive");
pElem.innerHTML = "LOCKED (Requires " + formatNumber(req, 4) + " faction reputation) - $" + formatNumber(aug.baseCost * faction.augmentationPriceMult, 2);
pElem.style.color = "red";
}
aElem.style.display = "inline";
@ -813,13 +814,16 @@ displayFactionAugmentations = function(factionName) {
}
span.style.display = "inline-block"
aElem.innerHTML += '<span class="tooltiptext">' + aug.info + " </span>";
//The div will have the tooltip.
aDiv.setAttribute("class", "tooltip");
aDiv.innerHTML = '<span class="tooltiptext">' + aug.info + " </span>";
aDiv.appendChild(aElem);
aElem.addEventListener("click", function() {
purchaseAugmentationBoxCreate(aug, faction);
});
span.appendChild(aElem);
span.appendChild(aDiv);
span.appendChild(pElem);
item.appendChild(span);

View File

@ -49,7 +49,7 @@ HacknetNode.prototype.updateMoneyGainRate = function() {
var gainPerLevel = CONSTANTS.HacknetNodeMoneyGainPerLevel;
this.moneyGainRatePerSecond = (this.level * gainPerLevel) *
Math.pow(1.05, this.ram-1) *
Math.pow(1.04, this.ram-1) *
((this.numCores + 1) / 2) * Player.hacknet_node_money_mult;
if (isNaN(this.moneyGainRatePerSecond)) {
this.moneyGainRatePerSecond = 0;
@ -436,7 +436,7 @@ processSingleHacknetNodeEarnings = function(numCycles, nodeObj) {
getHacknetNode = function(name) {
for (var i = 0; i < Player.hacknetNodes.length; ++i) {
if (Player.hacknetNodes[i].name == name) {
return player.hacknetNodes[i];
return Player.hacknetNodes[i];
}
}
return null;

View File

@ -248,7 +248,7 @@ function evaluate(exp, workerScript) {
}
if (server.requiredHackingSkill > Player.hacking_skill) {
workerScript.scriptRef.log("Cannot hack this server (" + server.hostaname + ") because user does not have root access");
workerScript.scriptRef.log("Cannot hack this server (" + server.hostname + ") because user's hacking skill is not high enough");
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Script crashed because player's hacking skill is not high enough to hack " + server.hostname);
return;
}
@ -375,6 +375,7 @@ function evaluate(exp, workerScript) {
var p = new Promise(function(resolve, reject) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
server.moneyAvailable += 1; //It can be grown even if it has no money
var growthPercentage = processSingleServerGrowth(server, 450);
resolve(growthPercentage);
}, 120 * 1000); //grow() takes flat 2 minutes right now
@ -653,6 +654,27 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
} else if (exp.func.value == "hasRootAccess") {
if (exp.args.length != 1) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|hasRootAccess() call has incorrect number of arguments. Takes 1 argument");
return;
}
var ipPromise = evaluate(exp.args[0], workerScript);
ipPromise.then(function(ip) {
if (env.stopFlag) {reject(workerScript);}
setTimeout(function() {
var server = getServer(ip);
if (server == null) {
reject("|" + workerScript.serverIp + "|" + workerScript.name + "|Invalid IP or hostname passed into hasRootAccess() command");
workerScript.scriptRef.log("Cannot hasRootAccess(). Invalid IP or hostname passed in: " + ip);
return;
}
workerScript.scriptRef.log("hasRootAccess() returned " + server.hasAdminRights);
resolve(server.hasAdminRights);
}, CONSTANTS.CodeInstructionRunTime);
}, function(e) {
reject(e);
});
} else if (exp.func.value == "run") {
if (exp.args.length != 1) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|run() call has incorrect number of arguments. Takes 1 argument");
@ -660,6 +682,7 @@ function evaluate(exp, workerScript) {
}
var scriptNamePromise = evaluate(exp.args[0], workerScript);
scriptNamePromise.then(function(scriptname) {
if (env.stopFlag) {reject(workerScript);}
var serverIp = workerScript.serverIp;
var scriptServer = AllServers[serverIp];
if (scriptServer == null) {
@ -683,6 +706,7 @@ function evaluate(exp, workerScript) {
return;
}
setTimeout(function() {
if (env.stopFlag) {reject(workerScript);}
Player.updateSkillLevels();
workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill);
resolve(Player.hacking_skill);
@ -701,7 +725,7 @@ function evaluate(exp, workerScript) {
workerScript.scriptRef.log("Cannot getServerMoneyAvailable(). Invalid IP or hostname passed in: " + ip);
return;
}
workerScript.scriptRef.log("getServerMoneyAvailable() returned " + server.moneyAvailable);
workerScript.scriptRef.log("getServerMoneyAvailable() returned " + formatNumber(server.moneyAvailable, 2));
resolve(server.moneyAvailable);
}, CONSTANTS.CodeInstructionRunTime);
}, function(e) {
@ -770,6 +794,16 @@ function evaluate(exp, workerScript) {
}, function(e) {
reject(e);
});
} else if (exp.func.value == "getNumHacknetNodes") {
if (exp.args.length != 0) {
reject("|"+workerScript.serverIp+"|"+workerScript.name+"|getNumHacknetNodes() call has incorrect number of arguments. Takes 0 arguments");
return;
}
setTimeout(function() {
if (env.stopFlag) {reject(workerScript);}
workerScript.scriptRef.log("getNumHacknetNodes() returned " + Player.hacknetNodes.length);
resolve(Player.hacknetNodes.length);
}, CONSTANTS.CodeInstructionRunTime);
}
}, CONSTANTS.CodeInstructionRunTime);
});
@ -989,7 +1023,7 @@ function apply_op(op, a, b) {
return x;
}
switch (op) {
case "+": return num(a) + num(b);
case "+": return a + b;
case "-": return num(a) - num(b);
case "*": return num(a) * num(b);
case "/": return num(a) / div(b);
@ -1092,7 +1126,7 @@ function scriptCalculateExpGain(server) {
function scriptCalculatePercentMoneyHacked(server) {
var difficultyMult = (100 - server.hackDifficulty) / 100;
var skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill;
var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 1000;
var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 950;
if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;}
return percentMoneyHacked;

View File

@ -243,7 +243,7 @@ PlayerObject.prototype.calculateHackingTime = function() {
PlayerObject.prototype.calculatePercentMoneyHacked = function() {
var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100;
var skillMult = (this.hacking_skill - (this.getCurrentServer().requiredHackingSkill - 1)) / this.hacking_skill;
var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 1000;
var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 950;
console.log("Percent money hacked calculated to be: " + percentMoneyHacked);
if (percentMoneyHacked < 0) {return 0;}
if (percentMoneyHacked > 1) {return 1;}

View File

@ -10,6 +10,7 @@ function BitburnerSaveObject() {
this.FactionsSave = "";
this.SpecialServerIpsSave = "";
this.AugmentationsSave = "";
this.AliasesSave = "";
}
BitburnerSaveObject.prototype.saveGame = function() {
@ -19,6 +20,7 @@ BitburnerSaveObject.prototype.saveGame = function() {
this.FactionsSave = JSON.stringify(Factions);
this.SpecialServerIpsSave = JSON.stringify(SpecialServerIps);
this.AugmentationsSave = JSON.stringify(Augmentations);
this.AliasesSave = JSON.stringify(Aliases);
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
window.localStorage.setItem("bitburnerSave", saveString);
@ -41,6 +43,17 @@ loadGame = function(saveObj) {
Factions = JSON.parse(saveObj.FactionsSave, Reviver);
SpecialServerIps = JSON.parse(saveObj.SpecialServerIpsSave, Reviver);
Augmentations = JSON.parse(saveObj.AugmentationsSave, Reviver);
if (saveObj.hasOwnProperty("AliasesSave")) {
try {
Aliases = JSON.parse(saveObj.AliasesSave, Reviver);
} catch(e) {
Aliases = {};
}
} else {
Aliases = {};
}
return true;
}

View File

@ -360,7 +360,15 @@ var Terminal = {
}
Terminal.commandHistoryIndex = Terminal.commandHistory.length;
//Process any aliases
command = substituteAliases(command);
console.log("command after alises: " + command);
//Only split the first space
var commandArray = command.split(" ");
if (commandArray.length > 1) {
commandArray = [commandArray.shift(), commandArray.join(" ")];
}
if (commandArray.length == 0) {return;}
@ -484,6 +492,20 @@ var Terminal = {
/* Command parser */
switch (commandArray[0]) {
case "alias":
if (commandArray.length == 1) {
printAliases();
} else if (commandArray.length == 2) {
if (parseAliasDeclaration(commandArray[1])) {
} else {
post('Incorrect usage of alias command. Usage: alias [aliasname="value"]'); return;
}
} else {
post('Incorrect usage of alias command. Usage: alias [aliasname="value"]'); return;
}
break;
case "analyze":
if (commandArray.length != 1) {
post("Incorrect usage of analyze command. Usage: analyze"); return;
@ -653,9 +675,6 @@ var Terminal = {
}
Engine.loadScriptEditorContent(scriptname, "");
break;
case "scan":
Terminal.executeScanCommand(commandArray);
break;
case "ps":
if (commandArray.length != 1) {
post("Incorrect usage of ps command. Usage: ps"); return;
@ -710,6 +729,12 @@ var Terminal = {
}
}
break;
case "scan":
Terminal.executeScanCommand(commandArray);
break;
case "scan-analyze":
Terminal.executeScanAnalyzeCommand(commandArray);
break;
case "scp":
//TODO
break;
@ -813,6 +838,24 @@ var Terminal = {
}
},
executeScanAnalyzeCommand: function(commandArray) {
if (commandArray.length != 1) {
post("Incorrect usage of scan-analyze command. usage: scan-analyze"); return;
}
var currServ = Player.getCurrentServer();
for (var i = 0; i < currServ.serversOnNetwork.length; ++i) {
var serv = currServ.getServerOnNetwork(i);
if (serv == null) {continue;}
post("<strong>" + serv.hostname + "</strong>");
var c = "N";
if (serv.hasAdminRights) {c = "Y";}
post("--Root Access: " + c);
post("--Required hacking skill: " + serv.requiredHackingSkill);
post("--Number open ports required to NUKE: " + serv.numOpenPortsRequired);
post(" ");
}
},
executeFreeCommand: function(commandArray) {
if (commandArray.length != 1) {
post("Incorrect usage of free command. Usage: free"); return;

View File

@ -154,7 +154,6 @@ purchaseAugmentationBoxCreate = function(aug, fac) {
}
} else if (Player.money >= (aug.baseCost * fac.augmentationPriceMult)) {
applyAugmentation(aug, fac);
//TODO Make this text better
dialogBoxCreate("You slowly drift to sleep as " + fac.name + "'s scientists put you under " +
" in order to install the " + aug.name + " Augmentation. <br><br>" +
"You wake up in your home...you feel different...");