Merged conflicts. Fixed several minor bugs. Increased infiltration exp. TIX api functions return transaction value rather than boolean. Hacking Mission changes for v0.34.0

This commit is contained in:
danielyxie 2017-12-02 22:19:49 -06:00
commit 9e5db4b644
20 changed files with 31060 additions and 24577 deletions

100
css/companymanagement.css Normal file

@ -0,0 +1,100 @@
#cmpy-mgmt-container p,
#cmpy-mgmt-container a {
font-size: 14px;
}
/* Header tabs */
.cmpy-mgmt-header-tab {
display: inline-block;
color: white;
background-color:#555;
border:1px solid white;
padding: 4px;
}
.cmpy-mgmt-header-tab:hover {
background-color: #666;
}
.cmpy-mgmt-header-tab.current {
background-color: #777;
}
/* Select industry type when creating a new division */
.cmpy-mgmt-industry-select {
color:white;
background-color:black;
}
/* Switch between Cities */
.cmpy-mgmt-city-tab {
display:inline-block;
color: white;
background-color: #555;
border: 1px solid white;
padding: 4px;
}
.cmpy-mgmt-city-tab:hover {
background-color: #666;
}
.cmpy-mgmt-city-tab.current {
background-color: #777;
}
/* Panels */
#cmpy-mgmt-panel {
height: 90%;
}
.cmpy-mgmt-industry-left-panel,
.cmpy-mgmt-industry-right-panel {
display:inline-block;
width: 45%;
height: 100%;
top: 10px;
overflow-y: auto;
overflow-x: auto;
}
.cmpy-mgmt-industry-overview-panel {
border: 1px solid white;
color: var(--my-font-color);
display:inline-block;
width: 100%;
}
.cmpy-mgmt-employee-panel {
border: 1px solid white;
display:block;
width:100%;
}
.cmpy-mgmt-warehouse-panel {
border: 1px solid white;
display:inline-block;
width:100%;
}
/* Hiring new employees*/
.cmpy-mgmt-find-employee-option {
border:1px solid white;
margin: 6px;
}
.cmpy-mgmt-find-employee-option:hover {
background-color:#3d4044;
}
/* Warehouse */
.cmpy-mgmt-warehouse-material-div {
padding:2px;
border:1px solid white;
}
.cmpy-mgmt-warehouse-product-div {
padding:2px;
border:1px solid white;
}

51689
dist/bundle.js vendored

File diff suppressed because one or more lines are too long

@ -11,6 +11,7 @@
<link rel="stylesheet" type="text/css" href="css/interactivetutorial.css" /> <link rel="stylesheet" type="text/css" href="css/interactivetutorial.css" />
<link rel="stylesheet" type="text/css" href="css/loader.css" /> <link rel="stylesheet" type="text/css" href="css/loader.css" />
<link rel="stylesheet" type="text/css" href="css/missions.css" /> <link rel="stylesheet" type="text/css" href="css/missions.css" />
<link rel="stylesheet" type="text/css" href="css/companymanagement.css" />
<!-- Google Analytics --> <!-- Google Analytics -->
<script> <script>
@ -335,6 +336,9 @@
</li> </li>
<li id="sector12-slums-li"> <li id="sector12-slums-li">
<a id="sector12-slums" class="a-link-button">The Slums</a> <a id="sector12-slums" class="a-link-button">The Slums</a>
</li>
<li id="sector12-cityhall-li">
<a id="sector12-cityhall" class="a-link-button">City Hall</a>
</li> </li>
</ul> </ul>
@ -740,6 +744,9 @@
<a id="location-slums-kidnap" class="a-link-button tooltip"> Kidnap and Ransom </a> <a id="location-slums-kidnap" class="a-link-button tooltip"> Kidnap and Ransom </a>
<a id="location-slums-assassinate" class="a-link-button tooltip"> Assassinate </a> <a id="location-slums-assassinate" class="a-link-button tooltip"> Assassinate </a>
<a id="location-slums-heist" class="a-link-button tooltip"> Heist </a> <a id="location-slums-heist" class="a-link-button tooltip"> Heist </a>
<!-- City Hall -->
<a id="location-cityhall-create-corporation" class='a-link-button'>Create a Corporation</a>
</div> </div>
<div id="infiltration-container" class="generic-menupage-container"> <div id="infiltration-container" class="generic-menupage-container">

@ -41,7 +41,26 @@ function initBitNodes() {
"Level 1: 20%<br>" + "Level 1: 20%<br>" +
"Level 2: 30%<br>" + "Level 2: 30%<br>" +
"Level 3: 35%"); "Level 3: 35%");
BitNodes["BitNode3"] = new BitNode(3, "The Price of Civilization", "COMING SOON"); //Corporate Warfare, Run own company BitNodes["BitNode3"] = new BitNode(3, "Corporatocracy", "The Price of Civilization",
"Our greatest illusion is that a healthy society can revolve around a " +
"single-minded pursuit of wealth.<br><br>" +
"Sometime in the early 21st century economic and political globalization turned " +
"the world into a corporatocracy, and it never looked back. Now, the privileged " +
"elite will happily bankrupt their own countrymen, decimate their own community, " +
"and evict their neighbors from houses in their desperate bid to increase their wealth.<br><br>" +
"In this BitNode you can create and manage your own corporation. Running a successful corporation " +
"has the potential of generating massive profits. All other forms of income are reduced by 75%. Furthermore: <br><br>" +
"The price and reputation cost of all Augmentations is tripled<br>" +
"The starting and maximum amount of money on servers is halved<br>" +
"Server growth rate is reduced by 80%<br>" +
"You will start out with $150b so that you can start your corporation<br>" +
"You now only need 75 reputation with a faction in order to donate to it, rather than 150<br><br>" +
"Destroying this BitNode will give you Source-File 3, or if you already have this Source-File it will " +
"upgrade its level up to a maximum of 3. This Source-File lets you create corporations on other BitNodes (although " +
"some BitNodes will disable this mechanic). This Source-File also increases your charisma and company salary multipliers by:<br>" +
"Level 1: 8%<br>" +
"Level 2: 12%<br>" +
"Level 3: 14%");
BitNodes["BitNode4"] = new BitNode(4, "The Singularity", "The Man and the Machine", "The Singularity has arrived. The human race is gone, replaced " + BitNodes["BitNode4"] = new BitNode(4, "The Singularity", "The Man and the Machine", "The Singularity has arrived. The human race is gone, replaced " +
"by artificially superintelligent beings that are more machine than man. <br><br>" + "by artificially superintelligent beings that are more machine than man. <br><br>" +
"In this BitNode, progressing is significantly harder. Experience gain rates " + "In this BitNode, progressing is significantly harder. Experience gain rates " +
@ -76,7 +95,7 @@ function initBitNodes() {
"Level 2: 6%<br>" + "Level 2: 6%<br>" +
"Level 3: 7%"); "Level 3: 7%");
BitNodes["BitNode6"] = new BitNode(6, "Do Androids Dream?", "COMING SOON"); //Build androids for automation BitNodes["BitNode6"] = new BitNode(6, "Do Androids Dream?", "COMING SOON"); //Build androids for automation
BitNodes["BitNode7"] = new BitNode(7, "Waste Runner", "COMING SOON"); //Postapocalyptic wasteland + blade runner BitNodes["BitNode7"] = new BitNode(7, "Bladeburners", "COMING SOON"); //Blade burner
BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "Money never sleeps", BitNodes["BitNode8"] = new BitNode(8, "Ghost of Wall Street", "Money never sleeps",
"You are trying to make a name for yourself as an up-and-coming hedge fund manager on Wall Street.<br><br>" + "You are trying to make a name for yourself as an up-and-coming hedge fund manager on Wall Street.<br><br>" +
"In this BitNode:<br><br>" + "In this BitNode:<br><br>" +
@ -192,6 +211,18 @@ function initBitNodeMultipliers() {
BitNodeMultipliers.FactionWorkRepGain = 0.5; BitNodeMultipliers.FactionWorkRepGain = 0.5;
BitNodeMultipliers.FactionPassiveRepGain = 0; BitNodeMultipliers.FactionPassiveRepGain = 0;
break; break;
case 3: //Corporatocracy
BitNodeMultipliers.RepToDonateToFaction = 0.5;
BitNodeMultipliers.AugmentationRepCost = 3;
BitNodeMultipliers.AugmentationMoneyCost = 3;
BitNodeMultipliers.ServerMaxMoney = 0.50;
BitNodeMultipliers.ServerStartingMoney = 0.50;
BitNodeMultipliers.ServerGrowthRate = 0.20;
BitNodeMultipliers.ScriptHackMoney = 0.25;
BitNodeMultipliers.CompanyWorkMoney = 0.25;
BitNodeMultipliers.CrimeMoney = 0.25;
BitNodeMultipliers.HacknetNodeMoney = 0.25;
break;
case 4: //The Singularity case 4: //The Singularity
BitNodeMultipliers.ServerMaxMoney = 0.15; BitNodeMultipliers.ServerMaxMoney = 0.15;
BitNodeMultipliers.ServerStartingMoney = 0.75; BitNodeMultipliers.ServerStartingMoney = 0.75;

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
let CONSTANTS = { let CONSTANTS = {
Version: "0.32.1", Version: "0.33.0",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience //Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then //and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -126,7 +126,7 @@ let CONSTANTS = {
//Hacking Missions //Hacking Missions
HackingMissionRepToDiffConversion: 10000, //Faction rep is divided by this to get mission difficulty HackingMissionRepToDiffConversion: 10000, //Faction rep is divided by this to get mission difficulty
HackingMissionRepToRewardConversion: 7, //Faction rep divided byt his to get mission rep reward HackingMissionRepToRewardConversion: 7, //Faction rep divided byt his to get mission rep reward
HackingMissionSpamTimeIncrease: 15000, //How much time limit increase is gained when conquering a Spam Node (ms) HackingMissionSpamTimeIncrease: 25000, //How much time limit increase is gained when conquering a Spam Node (ms)
HackingMissionTransferAttackIncrease: 1.05, //Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node HackingMissionTransferAttackIncrease: 1.05, //Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node
HackingMissionMiscDefenseIncrease: 1.05, //The amount by which every misc node's defense is multiplied when one is conquered HackingMissionMiscDefenseIncrease: 1.05, //The amount by which every misc node's defense is multiplied when one is conquered
HackingMissionDifficultyToHacking: 150, //Difficulty is multiplied by this to determine enemy's "hacking" level (to determine effects of scan/attack, etc) HackingMissionDifficultyToHacking: 150, //Difficulty is multiplied by this to determine enemy's "hacking" level (to determine effects of scan/attack, etc)
@ -767,28 +767,28 @@ let CONSTANTS = {
"must be the number of shares to purchase.<br><br>" + "must be the number of shares to purchase.<br><br>" +
"If the player does not have enough money to purchase specified number of shares, then no shares will be purchased (it will not purchase the most you can afford). " + "If the player does not have enough money to purchase specified number of shares, then no shares will be purchased (it will not purchase the most you can afford). " +
"Remember that every transaction on the stock exchange costs a certain commission fee.<br><br>" + "Remember that every transaction on the stock exchange costs a certain commission fee.<br><br>" +
"The function will return true if it successfully purchases the specified number of shares of stock, and false otherwise.<br><br>" + "If this function successfully purchases the shares, it will return the stock price at which each share was purchased. Otherwise, it will return 0.<br><br>" +
"<i><u>sellStock(sym, shares)</u></i><br>Attempts to sell shares of a stock using a Market Order. The first argument must be a string with the stock's symbol. The second argument " + "<i><u>sellStock(sym, shares)</u></i><br>Attempts to sell shares of a stock using a Market Order. The first argument must be a string with the stock's symbol. The second argument " +
"must be the number of shares to sell.<br><br>" + "must be the number of shares to sell.<br><br>" +
"If the specified number of shares in the function exceeds the amount that the player actually owns, then this function will sell all owned shares. " + "If the specified number of shares in the function exceeds the amount that the player actually owns, then this function will sell all owned shares. " +
"Remember that every transaction on the stock exchange costs a certain commission fee.<br><br>" + "Remember that every transaction on the stock exchange costs a certain commission fee.<br><br>" +
"The net profit made from selling stocks with this function is reflected in the script's statistics. This net profit is calculated as: <br><br>" + "The net profit made from selling stocks with this function is reflected in the script's statistics. This net profit is calculated as: <br><br>" +
"shares * (sell price - average price of purchased shares)<br><br>" + "shares * (sell price - average price of purchased shares)<br><br>" +
"This function will return true if the shares of stock are successfully sold and false otherwise.<br><br>" + "If the sale is successful, this function will return the stock price at which each share was sold. Otherwise, it will return 0.<br><br>" +
"<i><u>shortStock(sym, shares)</u></i><br>" + "<i><u>shortStock(sym, shares)</u></i><br>" +
"Attempts to purchase a short position of a stock using a Market Order. The first argument must be a string with the stock's symbol. The second argument " + "Attempts to purchase a short position of a stock using a Market Order. The first argument must be a string with the stock's symbol. The second argument " +
"must be the number of shares to purchase.<br><br>" + "must be the number of shares to purchase.<br><br>" +
"In order to use this function the player must be in BitNode-8 or must have Level 2 of Source-File 8.<br><br>" + "In order to use this function the player must be in BitNode-8 or must have Level 2 of Source-File 8.<br><br>" +
"If the player does not have enough money to purchase the specified number of shares, then no shares will be purchased. Remember that every " + "If the player does not have enough money to purchase the specified number of shares, then no shares will be purchased. Remember that every " +
"every transaction on the stock exchange costs a certain commission fee.<br><br>" + "every transaction on the stock exchange costs a certain commission fee.<br><br>" +
"Returns true if it successfully shorts the stock with the specified number of shares, and false otherwise.<br><br>" + "If the purchase is successful, this function will return the stock price at which each share was purchased. Otherwise, it will return 0.<br><br>" +
"<i><u>sellShort(sym, shares)</u></i><br>" + "<i><u>sellShort(sym, shares)</u></i><br>" +
"Attempts to sell a short position of a stock using a Market Order. The first argument must be a string with the stock's symbol. The second argument must be the " + "Attempts to sell a short position of a stock using a Market Order. The first argument must be a string with the stock's symbol. The second argument must be the " +
"number of shares to sell.<br><br>" + "number of shares to sell.<br><br>" +
"In order to use this function the player must be in BitNode-8 or must have Level 2 of Source-File 8.<br><br>" + "In order to use this function the player must be in BitNode-8 or must have Level 2 of Source-File 8.<br><br>" +
"If the specified number of shares exceeds the amount that the player actually owns, then this function will sell all owned shares. " + "If the specified number of shares exceeds the amount that the player actually owns, then this function will sell all owned shares. " +
"Remember that every transaction on the stock exchange costs a certain commission fee.<br><br>" + "Remember that every transaction on the stock exchange costs a certain commission fee.<br><br>" +
"This function returns true if it successfully sells any number of shares, and false otherwise.<br><br>" + "If the sale was successful, this function will return the stock price at which each sale was sold. Otherwise, it will return 0.<br><br>" +
"<i><u>placeOrder(sym, shares, price, type, pos)</u></i><br>" + "<i><u>placeOrder(sym, shares, price, type, pos)</u></i><br>" +
"Places an order on the stock market. This function only works for Limit and Stop Orders. Use the buyStock/sellStock/shortStock/sellShort functions " + "Places an order on the stock market. This function only works for Limit and Stop Orders. Use the buyStock/sellStock/shortStock/sellShort functions " +
"to place Market Orders. In order to use this function the player must be in BitNode-8 or must have Level 3 of Source-File 8.<br><br>" + "to place Market Orders. In order to use this function the player must be in BitNode-8 or must have Level 3 of Source-File 8.<br><br>" +
@ -1112,18 +1112,18 @@ let CONSTANTS = {
"World Stock Exchange account and TIX API Access<br>", "World Stock Exchange account and TIX API Access<br>",
LatestUpdate: LatestUpdate:
"v0.32.1<br>" + "v0.34.0<br>" +
"-Updated Netscript's 'interpreter/engine' to use the Bluebird promise library instead of native promises. " + "-Slightly increased experience gain from Infiltration<br>" +
"It should now be faster and more memory-efficient. If this has broken any Netscript features please report it through Github or the subreddit (reddit.com/r/bitburner)<br>" + "-buyStock(), sellStock(), shortStock(), and sellShort() Netscript function now return the stock price at which the transaction occurred, rather than a boolean. " +
"-Rebalanced stock market (adjusted parameters such as the volatility/trends/starting price of certain stocks)<br>" + "If the function fails for some reason, 0 will be returned.<br>" +
"-Added prompt() Netscript function<br>" + "-Hacking Mission Changes:<br>" +
"-Added 'Buy Max' and 'Sell All' functions to Stock Market UI<br>" + "---Shield and Firewall Nodes can now fortify<br>" +
"-Added 'Portfolio' Mode to Stock Market UI so you can only view stocks you have a position/order in<br>" + "---The effects of Fortifying are now ~30% lower<br>" +
"-Added a button to kill a script from its log display box<br><br>" + "---Conquering a Spam Node now increases your time limit by 25 secs instead of 15<br>" +
"v0.32.0<br>" + "---Damage dealt by Attacking was slightly reduced<br>" +
"-Released BitNode-8: Ghost of Wall Street<br>" + "---The effect of Scanning was slightly reduced<br>" +
"-Re-designed Stock Market UI<br>" + ""
"-Minor bugfixes<br>"
} }
export {CONSTANTS}; export {CONSTANTS};

@ -515,7 +515,6 @@ function displayFactionContent(factionName) {
var newPurchaseAugmentationsButton = clearEventListeners("faction-purchase-augmentations"); var newPurchaseAugmentationsButton = clearEventListeners("faction-purchase-augmentations");
newPurchaseAugmentationsButton.addEventListener("click", function() { newPurchaseAugmentationsButton.addEventListener("click", function() {
Engine.hideAllContent(); Engine.hideAllContent();
//Engine.Display.factionAugmentationsContent.style.visibility = "visible";
Engine.Display.factionAugmentationsContent.style.display = "block"; Engine.Display.factionAugmentationsContent.style.display = "block";
var newBackButton = clearEventListeners("faction-augmentations-back-button"); var newBackButton = clearEventListeners("faction-augmentations-back-button");
@ -532,6 +531,7 @@ function displayFactionContent(factionName) {
factionName == "The Syndicate" || factionName == "The Dark Army" || factionName == "Speakers for the Dead" || factionName == "The Syndicate" || factionName == "The Dark Army" || factionName == "Speakers for the Dead" ||
factionName == "NiteSec" || factionName == "The Black Hand")) { factionName == "NiteSec" || factionName == "The Black Hand")) {
//Set everything else to invisible //Set everything else to invisible
hackMissionDiv.style.display = "none";
hackDiv.style.display = "none"; hackDiv.style.display = "none";
fieldWorkDiv.style.display = "none"; fieldWorkDiv.style.display = "none";
securityWorkDiv.style.display = "none"; securityWorkDiv.style.display = "none";

@ -1037,7 +1037,7 @@ function displayGangContent() {
territorySubpage.appendChild(territoryBorder); territorySubpage.appendChild(territoryBorder);
} }
document.getElementById("gang-container").style.visibility = "visible"; document.getElementById("gang-container").style.display = "block";
updateGangContent(); updateGangContent();
} }

@ -91,6 +91,7 @@ HacknetNode.prototype.getLevelUpgradeCost = function(levels=1) {
} }
HacknetNode.prototype.purchaseLevelUpgrade = function(levels=1) { HacknetNode.prototype.purchaseLevelUpgrade = function(levels=1) {
levels = Math.round(levels);
var cost = this.calculateLevelUpgradeCost(levels); var cost = this.calculateLevelUpgradeCost(levels);
if (isNaN(cost) || levels < 0) {return false;} if (isNaN(cost) || levels < 0) {return false;}
if (this.level + levels > CONSTANTS.HacknetNodeMaxLevel) { if (this.level + levels > CONSTANTS.HacknetNodeMaxLevel) {

@ -592,10 +592,10 @@ let intWgt = CONSTANTS.IntelligenceInfiltrationWeight;
//Success: 5%, Failure 10%, -Karma //Success: 5%, Failure 10%, -Karma
function attemptInfiltrationKill(inst) { function attemptInfiltrationKill(inst) {
var chance = getInfiltrationKillChance(inst); var chance = getInfiltrationKillChance(inst);
inst.gainStrengthExp(inst.securityLevel / 90) * Player.strength_exp_mult; inst.gainStrengthExp(inst.securityLevel / 85) * Player.strength_exp_mult;
inst.gainDefenseExp(inst.securityLevel / 90) * Player.defense_exp_mult; inst.gainDefenseExp(inst.securityLevel / 85) * Player.defense_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 90) * Player.dexterity_exp_mult; inst.gainDexterityExp(inst.securityLevel / 85) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 90) * Player.agility_exp_mult; inst.gainAgilityExp(inst.securityLevel / 85) * Player.agility_exp_mult;
if (Math.random() <= chance) { if (Math.random() <= chance) {
inst.securityLevel *= 1.05; inst.securityLevel *= 1.05;
return [true, 1.05]; return [true, 1.05];
@ -618,10 +618,10 @@ function getInfiltrationKillChance(inst) {
//Success: 3%, Failure: 10% //Success: 3%, Failure: 10%
function attemptInfiltrationKnockout(inst) { function attemptInfiltrationKnockout(inst) {
var chance = getInfiltrationKnockoutChance(inst); var chance = getInfiltrationKnockoutChance(inst);
inst.gainStrengthExp(inst.securityLevel / 85) * Player.strength_exp_mult; inst.gainStrengthExp(inst.securityLevel / 80) * Player.strength_exp_mult;
inst.gainDefenseExp(inst.securityLevel / 85) * Player.defense_exp_mult; inst.gainDefenseExp(inst.securityLevel / 80) * Player.defense_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 85) * Player.dexterity_exp_mult; inst.gainDexterityExp(inst.securityLevel / 80) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 85) * Player.agility_exp_mult; inst.gainAgilityExp(inst.securityLevel / 80) * Player.agility_exp_mult;
if (Math.random() <= chance) { if (Math.random() <= chance) {
inst.securityLevel *= 1.03; inst.securityLevel *= 1.03;
return [true, 1.03]; return [true, 1.03];
@ -643,9 +643,9 @@ function getInfiltrationKnockoutChance(inst) {
//Success: 0%, Failure: 10% //Success: 0%, Failure: 10%
function attemptInfiltrationStealthKnockout(inst) { function attemptInfiltrationStealthKnockout(inst) {
var chance = getInfiltrationStealthKnockoutChance(inst); var chance = getInfiltrationStealthKnockoutChance(inst);
inst.gainStrengthExp(inst.securityLevel / 90) * Player.strength_exp_mult; inst.gainStrengthExp(inst.securityLevel / 85) * Player.strength_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 70) * Player.dexterity_exp_mult; inst.gainDexterityExp(inst.securityLevel / 65) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 70) * Player.agility_exp_mult; inst.gainAgilityExp(inst.securityLevel / 65) * Player.agility_exp_mult;
if (Math.random() <= chance) { if (Math.random() <= chance) {
return [true, 1]; return [true, 1];
} else { } else {
@ -667,9 +667,9 @@ function getInfiltrationStealthKnockoutChance(inst) {
//Success: 0%, Failure: 5%, -Karma //Success: 0%, Failure: 5%, -Karma
function attemptInfiltrationAssassinate(inst) { function attemptInfiltrationAssassinate(inst) {
var chance = getInfiltrationAssassinateChance(inst); var chance = getInfiltrationAssassinateChance(inst);
inst.gainStrengthExp(inst.securityLevel / 90) * Player.strength_exp_mult; inst.gainStrengthExp(inst.securityLevel / 85) * Player.strength_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 70) * Player.dexterity_exp_mult; inst.gainDexterityExp(inst.securityLevel / 65) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 70) * Player.agility_exp_mult; inst.gainAgilityExp(inst.securityLevel / 65) * Player.agility_exp_mult;
if (Math.random() <= chance) { if (Math.random() <= chance) {
return [true, 1]; return [true, 1];
} else { } else {
@ -691,10 +691,10 @@ function getInfiltrationAssassinateChance(inst) {
//Success: 5%, Failure: 10% //Success: 5%, Failure: 10%
function attemptInfiltrationDestroySecurity(inst) { function attemptInfiltrationDestroySecurity(inst) {
var chance = getInfiltrationDestroySecurityChance(inst); var chance = getInfiltrationDestroySecurityChance(inst);
inst.gainStrengthExp(inst.securityLevel / 90) * Player.strength_exp_mult; inst.gainStrengthExp(inst.securityLevel / 85) * Player.strength_exp_mult;
inst.gainDefenseExp(inst.securityLevel / 90) * Player.defense_exp_mult; inst.gainDefenseExp(inst.securityLevel / 85) * Player.defense_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 90) * Player.dexterity_exp_mult; inst.gainDexterityExp(inst.securityLevel / 85) * Player.dexterity_exp_mult;
inst.gainAgilityExp(inst.securityLevel / 90) * Player.agility_exp_mult; inst.gainAgilityExp(inst.securityLevel / 85) * Player.agility_exp_mult;
if (Math.random() <= chance) { if (Math.random() <= chance) {
inst.securityLevel *= 1.05; inst.securityLevel *= 1.05;
return [true, 1.05]; return [true, 1.05];
@ -718,8 +718,8 @@ function getInfiltrationDestroySecurityChance(inst) {
//Success: 1%, Failure: 5% //Success: 1%, Failure: 5%
function attemptInfiltrationHack(inst) { function attemptInfiltrationHack(inst) {
var chance = getInfiltrationHackChance(inst); var chance = getInfiltrationHackChance(inst);
inst.gainHackingExp(inst.securityLevel / 50) * Player.hacking_exp_mult; inst.gainHackingExp(inst.securityLevel / 40) * Player.hacking_exp_mult;
inst.gainIntelligenceExp(inst.securityLevel / 700); inst.gainIntelligenceExp(inst.securityLevel / 690);
if (Math.random() <= chance) { if (Math.random() <= chance) {
inst.securityLevel *= 1.03; inst.securityLevel *= 1.03;
return [true, 1.03]; return [true, 1.03];
@ -741,7 +741,7 @@ function getInfiltrationHackChance(inst) {
//Success: 0%, Failure: 8% //Success: 0%, Failure: 8%
function attemptInfiltrationSneak(inst) { function attemptInfiltrationSneak(inst) {
var chance = getInfiltrationSneakChance(inst); var chance = getInfiltrationSneakChance(inst);
inst.gainAgilityExp(inst.securityLevel / 50) * Player.agility_exp_mult; inst.gainAgilityExp(inst.securityLevel / 40) * Player.agility_exp_mult;
if (Math.random() <= chance) { if (Math.random() <= chance) {
return [true, 1]; return [true, 1];
} else { } else {
@ -762,7 +762,7 @@ function getInfiltrationSneakChance(inst) {
//Success: 1%, Failure: 3% //Success: 1%, Failure: 3%
function attemptInfiltrationPickLockedDoor(inst) { function attemptInfiltrationPickLockedDoor(inst) {
var chance = getInfiltrationPickLockedDoorChance(inst); var chance = getInfiltrationPickLockedDoorChance(inst);
inst.gainDexterityExp(inst.securityLevel / 40) * Player.dexterity_exp_mult; inst.gainDexterityExp(inst.securityLevel / 30) * Player.dexterity_exp_mult;
if (Math.random() <= chance) { if (Math.random() <= chance) {
inst.securityLevel *= 1.01; inst.securityLevel *= 1.01;
return [true, 1.01]; return [true, 1.01];
@ -802,8 +802,8 @@ function getInfiltrationBribeChance(inst) {
//Failure: 5% //Failure: 5%
function attemptInfiltrationEscape(inst) { function attemptInfiltrationEscape(inst) {
var chance = getInfiltrationEscapeChance(inst); var chance = getInfiltrationEscapeChance(inst);
inst.gainAgilityExp(inst.securityLevel / 40) * Player.agility_exp_mult; inst.gainAgilityExp(inst.securityLevel / 35) * Player.agility_exp_mult;
inst.gainDexterityExp(inst.securityLevel / 40) * Player.dexterity_exp_mult; inst.gainDexterityExp(inst.securityLevel / 35) * Player.dexterity_exp_mult;
if (Math.random() <= chance) { if (Math.random() <= chance) {
return [true, 1]; return [true, 1];
} else { } else {

@ -1,5 +1,6 @@
import {CompanyPositions, initCompanies, import {CompanyPositions, initCompanies,
Companies, getJobRequirementText} from "./Company.js"; Companies, getJobRequirementText} from "./Company.js";
import {Corporation} from "./CompanyManagement.js";
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {commitShopliftCrime, commitRobStoreCrime, commitMugCrime, import {commitShopliftCrime, commitRobStoreCrime, commitMugCrime,
commitLarcenyCrime, commitDealDrugsCrime, commitBondForgeryCrime, commitLarcenyCrime, commitDealDrugsCrime, commitBondForgeryCrime,
@ -22,7 +23,7 @@ import {purchaseServer,
import {SpecialServerNames, SpecialServerIps} from "./SpecialServerIps.js"; import {SpecialServerNames, SpecialServerIps} from "./SpecialServerIps.js";
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
import {clearEventListeners} from "../utils/HelperFunctions.js"; import {clearEventListeners, createElement} from "../utils/HelperFunctions.js";
import {createRandomIp} from "../utils/IPAddress.js"; import {createRandomIp} from "../utils/IPAddress.js";
import numeral from "../utils/numeral.min.js"; import numeral from "../utils/numeral.min.js";
import {formatNumber} from "../utils/StringHelperFunctions.js"; import {formatNumber} from "../utils/StringHelperFunctions.js";
@ -84,6 +85,7 @@ let Locations = {
Sector12IronGym: "Iron Gym", Sector12IronGym: "Iron Gym",
Sector12PowerhouseGym: "Powerhouse Gym", Sector12PowerhouseGym: "Powerhouse Gym",
Sector12Slums: "Sector-12 Slums", Sector12Slums: "Sector-12 Slums",
Sector12CityHall: "Sector-12 City Hall",
//New Tokyo //New Tokyo
NewTokyoTravelAgency: "New Tokyo Travel Agency", NewTokyoTravelAgency: "New Tokyo Travel Agency",
@ -204,6 +206,8 @@ function displayLocationContent() {
var slumsAssassinate = document.getElementById("location-slums-assassinate"); var slumsAssassinate = document.getElementById("location-slums-assassinate");
var slumsHeist = document.getElementById("location-slums-heist"); var slumsHeist = document.getElementById("location-slums-heist");
var cityHallCreateCorporation = document.getElementById("location-cityhall-create-corporation");
var loc = Player.location; var loc = Player.location;
returnToWorld.addEventListener("click", function() { returnToWorld.addEventListener("click", function() {
@ -309,6 +313,8 @@ function displayLocationContent() {
slumsAssassinate.style.display = "none"; slumsAssassinate.style.display = "none";
slumsHeist.style.display = "none"; slumsHeist.style.display = "none";
cityHallCreateCorporation.style.display = "none";
//Check if the player is employed at this Location. If he is, display the "Work" button, //Check if the player is employed at this Location. If he is, display the "Work" button,
//update the job title, etc. //update the job title, etc.
if (loc != "" && loc === Player.companyName) { if (loc != "" && loc === Player.companyName) {
@ -775,6 +781,15 @@ function displayLocationContent() {
setGymLocationButtons(costMult, expMult); setGymLocationButtons(costMult, expMult);
break; break;
case Locations.Sector12CityHall:
cityHallCreateCorporation.style.display = "block";
if (Player.corporation instanceof Corporation) {
cityHallCreateCorporation.className = "a-link-button-inactive";
} else {
cityHallCreateCorporation.className = "a-link-button";
}
break;
case Locations.NewTokyoTravelAgency: case Locations.NewTokyoTravelAgency:
travelAgencyText.style.display = "block"; travelAgencyText.style.display = "block";
travelToAevum.style.display = "block"; travelToAevum.style.display = "block";
@ -1085,7 +1100,6 @@ function displayLocationContent() {
default: default:
console.log("ERROR: INVALID LOCATION"); console.log("ERROR: INVALID LOCATION");
} }
//Make the "Apply to be Employee and Waiter" texts disappear if you already hold the job //Make the "Apply to be Employee and Waiter" texts disappear if you already hold the job
@ -1380,6 +1394,13 @@ function initLocationButtons() {
return false; return false;
}); });
let sector12CityHall = document.getElementById("sector12-cityhall");
sector12CityHall.addEventListener("click", function() {
Player.location = Locations.Sector12CityHall;
Engine.loadLocationContent();
return false;
});
let newTokyoTravelAgency = document.getElementById("newtokyo-travelagency"); let newTokyoTravelAgency = document.getElementById("newtokyo-travelagency");
newTokyoTravelAgency.addEventListener("click", function() { newTokyoTravelAgency.addEventListener("click", function() {
Player.location = Locations.NewTokyoTravelAgency; Player.location = Locations.NewTokyoTravelAgency;
@ -1614,6 +1635,8 @@ function initLocationButtons() {
var slumsAssassinate = document.getElementById("location-slums-assassinate"); var slumsAssassinate = document.getElementById("location-slums-assassinate");
var slumsHeist = document.getElementById("location-slums-heist"); var slumsHeist = document.getElementById("location-slums-heist");
var cityHallCreateCorporation = document.getElementById("location-cityhall-create-corporation");
var hospitalTreatment = document.getElementById("location-hospital-treatment"); var hospitalTreatment = document.getElementById("location-hospital-treatment");
softwareJob.addEventListener("click", function() { softwareJob.addEventListener("click", function() {
@ -1888,6 +1911,42 @@ function initLocationButtons() {
return false; return false;
}); });
cityHallCreateCorporation.addEventListener("click", function() {
var yesBtn = yesNoTxtInpBoxGetYesButton(),
noBtn = yesNoTxtInpBoxGetNoButton();
yesBtn.innerText = "Create Corporation";
noBtn.innerText = "Cancel";
yesBtn.addEventListener("click", function() {
if (Player.money.lt(150e9)) {
dialogBoxCreate("You don't have enough money to create a corporation! You need $150b");
return yesNoTxtInpBoxClose();
}
Player.loseMoney(150e9);
var companyName = yesNoTxtInpBoxGetInput();
if (companyName == null || companyName == "") {
dialogBoxCreate("Invalid company name!");
return false;
}
Player.corporation = new Corporation({
name:companyName,
});
displayLocationContent();
dialogBoxCreate("Congratulations! You just started your own corporation. You can visit " +
"and manage your company in the City");
return yesNoTxtInpBoxClose();
});
noBtn.addEventListener("click", function() {
return yesNoTxtInpBoxClose();
});
if (Player.corporation instanceof Corporation) {
return;
} else {
yesNoTxtInpBoxCreate("Would you like to start a corporation? This will require $150b " +
"for registration and initial funding.<br><br>If so, please enter " +
"a name for your corporation below:");
}
});
hospitalTreatment.addEventListener("click", function() { hospitalTreatment.addEventListener("click", function() {
if (Player.hp < 0) {Player.hp = 0;} if (Player.hp < 0) {Player.hp = 0;}
var price = (Player.max_hp - Player.hp) * CONSTANTS.HospitalCostPerHp; var price = (Player.max_hp - Player.hp) * CONSTANTS.HospitalCostPerHp;

@ -137,6 +137,11 @@ Node.prototype.select = function(actionButtons) {
actionButtons[5].classList.remove("a-link-button-inactive"); actionButtons[5].classList.remove("a-link-button-inactive");
actionButtons[5].classList.add("a-link-button"); actionButtons[5].classList.add("a-link-button");
break; break;
case NodeTypes.Shield:
case NodeTypes.Firewall:
actionButtons[3].classList.remove("a-link-button-inactive");
actionButtons[3].classList.add("a-link-button");
break;
default: default:
break; break;
} }
@ -229,11 +234,6 @@ HackingMission.prototype.init = function() {
var numDatabases = Math.min(10, getRandomInt(1, Math.round(this.difficulty / 3) + 1)); var numDatabases = Math.min(10, getRandomInt(1, Math.round(this.difficulty / 3) + 1));
var totalNodes = numNodes + numFirewalls + numDatabases; var totalNodes = numNodes + numFirewalls + numDatabases;
var xlimit = 7 - Math.floor(totalNodes / 8); var xlimit = 7 - Math.floor(totalNodes / 8);
console.log("numNodes: " + numNodes);
console.log("numFirewalls: " + numFirewalls);
console.log("numDatabases: " + numDatabases);
console.log("totalNodes: " + totalNodes);
console.log("xlimit: " + xlimit);
var randMult = addOffset(0.8 + (this.difficulty / 5), 10); var randMult = addOffset(0.8 + (this.difficulty / 5), 10);
for (var i = 0; i < numNodes; ++i) { for (var i = 0; i < numNodes; ++i) {
var stats = { var stats = {
@ -403,7 +403,7 @@ HackingMission.prototype.createPageDom = function() {
return; return;
} }
if (this.selectedNode.type !== NodeTypes.Core) {return;} if (this.selectedNode.type !== NodeTypes.Core) {return;}
this.setActionButtonsActive(); this.setActionButtonsActive(this.selectedNode.type);
this.setActionButton(NodeActions.Attack, false); //Set attack button inactive this.setActionButton(NodeActions.Attack, false); //Set attack button inactive
this.selectedNode.action = NodeActions.Attack; this.selectedNode.action = NodeActions.Attack;
}); });
@ -413,7 +413,9 @@ HackingMission.prototype.createPageDom = function() {
console.log("ERR: Pressing Action button without selected node"); console.log("ERR: Pressing Action button without selected node");
return; return;
} }
this.setActionButtonsActive(); var nodeType = this.selectedNode.type;
if (nodeType !== NodeTypes.Core && nodeType !== NodeTypes.Transfer) {return;}
this.setActionButtonsActive(nodeType);
this.setActionButton(NodeActions.Scan, false); //Set scan button inactive this.setActionButton(NodeActions.Scan, false); //Set scan button inactive
this.selectedNode.action = NodeActions.Scan; this.selectedNode.action = NodeActions.Scan;
}); });
@ -423,7 +425,9 @@ HackingMission.prototype.createPageDom = function() {
console.log("ERR: Pressing Action button without selected node"); console.log("ERR: Pressing Action button without selected node");
return; return;
} }
this.setActionButtonsActive(); var nodeType = this.selectedNode.type;
if (nodeType !== NodeTypes.Core && nodeType !== NodeTypes.Transfer) {return;}
this.setActionButtonsActive(nodeType);
this.setActionButton(NodeActions.Weaken, false); //Set Weaken button inactive this.setActionButton(NodeActions.Weaken, false); //Set Weaken button inactive
this.selectedNode.action = NodeActions.Weaken; this.selectedNode.action = NodeActions.Weaken;
}); });
@ -433,7 +437,7 @@ HackingMission.prototype.createPageDom = function() {
console.log("ERR: Pressing Action button without selected node"); console.log("ERR: Pressing Action button without selected node");
return; return;
} }
this.setActionButtonsActive(); this.setActionButtonsActive(this.selectedNode.type);
this.setActionButton(NodeActions.Fortify, false); //Set Fortify button inactive this.setActionButton(NodeActions.Fortify, false); //Set Fortify button inactive
this.selectedNode.action = NodeActions.Fortify; this.selectedNode.action = NodeActions.Fortify;
}); });
@ -443,7 +447,9 @@ HackingMission.prototype.createPageDom = function() {
console.log("ERR: Pressing Action button without selected node"); console.log("ERR: Pressing Action button without selected node");
return; return;
} }
this.setActionButtonsActive(); var nodeType = this.selectedNode.type;
if (nodeType !== NodeTypes.Core && nodeType !== NodeTypes.Transfer) {return;}
this.setActionButtonsActive(this.selectedNode.type);
this.setActionButton(NodeActions.Overflow, false); //Set Overflow button inactive this.setActionButton(NodeActions.Overflow, false); //Set Overflow button inactive
this.selectedNode.action = NodeActions.Overflow; this.selectedNode.action = NodeActions.Overflow;
}); });
@ -478,11 +484,37 @@ HackingMission.prototype.setActionButtonsInactive = function() {
} }
} }
HackingMission.prototype.setActionButtonsActive = function() { HackingMission.prototype.setActionButtonsActive = function(nodeType=null) {
for (var i = 0; i < this.actionButtons.length; ++i) { for (var i = 0; i < this.actionButtons.length; ++i) {
this.actionButtons[i].classList.add("a-link-button"); this.actionButtons[i].classList.add("a-link-button");
this.actionButtons[i].classList.remove("a-link-button-inactive"); this.actionButtons[i].classList.remove("a-link-button-inactive");
} }
//For Transfer, FireWall and Shield Nodes, certain buttons should always be disabled
//0 = Attack, 1 = Scan, 2 = Weaken, 3 = Fortify, 4 = overflow, 5 = Drop conn
if (nodeType) {
switch (nodeType) {
case NodeTypes.Firewall:
case NodeTypes.Shield:
this.actionButtons[0].classList.remove("a-link-button");
this.actionButtons[0].classList.add("a-link-button-inactive");
this.actionButtons[1].classList.remove("a-link-button");
this.actionButtons[1].classList.add("a-link-button-inactive");
this.actionButtons[2].classList.remove("a-link-button");
this.actionButtons[2].classList.add("a-link-button-inactive");
this.actionButtons[4].classList.remove("a-link-button");
this.actionButtons[4].classList.add("a-link-button-inactive");
this.actionButtons[5].classList.remove("a-link-button");
this.actionButtons[5].classList.add("a-link-button-inactive");
break;
case NodeTypes.Transfer:
this.actionButtons[0].classList.remove("a-link-button");
this.actionButtons[0].classList.add("a-link-button-inactive");
break;
default:
break;
}
}
} }
//True for active, false for inactive //True for active, false for inactive
@ -1002,7 +1034,9 @@ HackingMission.prototype.process = function(numCycles=1) {
}); });
this.playerNodes.forEach((node)=>{ this.playerNodes.forEach((node)=>{
if (node.type === NodeTypes.Transfer) { if (node.type === NodeTypes.Transfer ||
node.type === NodeTypes.Shield ||
node.type === NodeTypes.Firewall) {
res |= this.processNode(node, storedCycles); res |= this.processNode(node, storedCycles);
} }
}); });
@ -1014,7 +1048,9 @@ HackingMission.prototype.process = function(numCycles=1) {
}); });
this.enemyNodes.forEach((node)=>{ this.enemyNodes.forEach((node)=>{
if (node.type === NodeTypes.Transfer) { if (node.type === NodeTypes.Transfer ||
node.type === NodeTypes.Shield ||
node.type === NodeTypes.Firewall) {
this.enemyAISelectAction(node); this.enemyAISelectAction(node);
res |= this.processNode(node, storedCycles); res |= this.processNode(node, storedCycles);
} }
@ -1243,6 +1279,7 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) {
case NodeTypes.Shield: case NodeTypes.Shield:
if (conqueredByPlayer) { if (conqueredByPlayer) {
swapNodes(isMiscNode ? this.miscNodes : this.enemyNodes, this.playerNodes, targetNode); swapNodes(isMiscNode ? this.miscNodes : this.enemyNodes, this.playerNodes, targetNode);
this.configurePlayerNodeElement(targetNode.el);
} else { } else {
swapNodes(isMiscNode ? this.miscNodes : this.playerNodes, this.enemyNodes, targetNode); swapNodes(isMiscNode ? this.miscNodes : this.playerNodes, this.enemyNodes, targetNode);
} }
@ -1356,6 +1393,10 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) {
nodeObj.action = NodeActions.Overflow; nodeObj.action = NodeActions.Overflow;
} }
break; break;
case NodeTypes.Firewall:
case NodeTypes.Shield:
nodeObj.action = NodeActions.Fortify;
break;
default: default:
break; break;
} }
@ -1367,11 +1408,11 @@ var hackEffWeightAttack = 80; //Weight for Attack action
//Returns damage per cycle based on stats //Returns damage per cycle based on stats
HackingMission.prototype.calculateAttackDamage = function(atk, def, hacking = 0) { HackingMission.prototype.calculateAttackDamage = function(atk, def, hacking = 0) {
return Math.max(0.75 * (atk + (hacking / hackEffWeightAttack) - def), 1); return Math.max(0.55 * (atk + (hacking / hackEffWeightAttack) - def), 1);
} }
HackingMission.prototype.calculateScanEffect = function(atk, def, hacking=0) { HackingMission.prototype.calculateScanEffect = function(atk, def, hacking=0) {
return Math.max(0.7 * ((atk) + hacking / hackEffWeightTarget - (def * 0.95)), 2); return Math.max(0.6 * ((atk) + hacking / hackEffWeightTarget - (def * 0.95)), 2);
} }
HackingMission.prototype.calculateWeakenEffect = function(atk, def, hacking=0) { HackingMission.prototype.calculateWeakenEffect = function(atk, def, hacking=0) {
@ -1379,11 +1420,11 @@ HackingMission.prototype.calculateWeakenEffect = function(atk, def, hacking=0) {
} }
HackingMission.prototype.calculateFortifyEffect = function(hacking=0) { HackingMission.prototype.calculateFortifyEffect = function(hacking=0) {
return hacking / hackEffWeightSelf; return 0.6 * hacking / hackEffWeightSelf;
} }
HackingMission.prototype.calculateOverflowEffect = function(hacking=0) { HackingMission.prototype.calculateOverflowEffect = function(hacking=0) {
return hacking / hackEffWeightSelf; return 0.95 * hacking / hackEffWeightSelf;
} }
//Updates timer display //Updates timer display

@ -866,17 +866,17 @@ function NetscriptFunctions(workerScript) {
} }
if (shares < 0 || isNaN(shares)) { if (shares < 0 || isNaN(shares)) {
workerScript.scriptRef.log("Error: Invalid 'shares' argument passed to buyStock()"); workerScript.scriptRef.log("Error: Invalid 'shares' argument passed to buyStock()");
return false; return 0;
} }
shares = Math.round(shares); shares = Math.round(shares);
if (shares === 0) {return false;} if (shares === 0) {return 0;}
var totalPrice = stock.price * shares; var totalPrice = stock.price * shares;
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) { if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
workerScript.scriptRef.log("Not enough money to purchase " + formatNumber(shares, 0) + " shares of " + workerScript.scriptRef.log("Not enough money to purchase " + formatNumber(shares, 0) + " shares of " +
symbol + ". Need $" + symbol + ". Need $" +
formatNumber(totalPrice + CONSTANTS.StockMarketCommission, 2).toString()); formatNumber(totalPrice + CONSTANTS.StockMarketCommission, 2).toString());
return false; return 0;
} }
var origTotal = stock.playerShares * stock.playerAvgPx; var origTotal = stock.playerShares * stock.playerAvgPx;
@ -889,7 +889,7 @@ function NetscriptFunctions(workerScript) {
} }
workerScript.scriptRef.log("Bought " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at $" + workerScript.scriptRef.log("Bought " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at $" +
formatNumber(stock.price, 2) + " per share"); formatNumber(stock.price, 2) + " per share");
return true; return stock.price;
}, },
sellStock : function(symbol, shares) { sellStock : function(symbol, shares) {
if (!Player.hasTixApiAccess) { if (!Player.hasTixApiAccess) {
@ -901,11 +901,11 @@ function NetscriptFunctions(workerScript) {
} }
if (shares < 0 || isNaN(shares)) { if (shares < 0 || isNaN(shares)) {
workerScript.scriptRef.log("Error: Invalid 'shares' argument passed to sellStock()"); workerScript.scriptRef.log("Error: Invalid 'shares' argument passed to sellStock()");
return false; return 0;
} }
shares = Math.round(shares); shares = Math.round(shares);
if (shares > stock.playerShares) {shares = stock.playerShares;} if (shares > stock.playerShares) {shares = stock.playerShares;}
if (shares === 0) {return false;} if (shares === 0) {return 0;}
var gains = stock.price * shares - CONSTANTS.StockMarketCommission; var gains = stock.price * shares - CONSTANTS.StockMarketCommission;
Player.gainMoney(gains); Player.gainMoney(gains);
@ -925,7 +925,7 @@ function NetscriptFunctions(workerScript) {
workerScript.scriptRef.log("Sold " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at $" + workerScript.scriptRef.log("Sold " + formatNumber(shares, 0) + " shares of " + stock.symbol + " at $" +
formatNumber(stock.price, 2) + " per share. Gained " + formatNumber(stock.price, 2) + " per share. Gained " +
"$" + formatNumber(gains, 2)); "$" + formatNumber(gains, 2));
return true; return stock.price;
}, },
shortStock(symbol, shares) { shortStock(symbol, shares) {
if (!Player.hasTixApiAccess) { if (!Player.hasTixApiAccess) {
@ -940,7 +940,8 @@ function NetscriptFunctions(workerScript) {
if (stock == null) { if (stock == null) {
throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid stock symbol passed into shortStock()"); throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid stock symbol passed into shortStock()");
} }
return shortStock(stock, shares, workerScript); var res = shortStock(stock, shares, workerScript);
return res ? stock.price : 0;
}, },
sellShort(symbol, shares) { sellShort(symbol, shares) {
if (!Player.hasTixApiAccess) { if (!Player.hasTixApiAccess) {
@ -955,7 +956,8 @@ function NetscriptFunctions(workerScript) {
if (stock == null) { if (stock == null) {
throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid stock symbol passed into sellShort()"); throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid stock symbol passed into sellShort()");
} }
return sellShort(stock, shares, workerScript); var res = sellShort(stock, shares, workerScript);
return res ? stock.price : 0;
}, },
placeOrder(symbol, shares, price, type, pos) { placeOrder(symbol, shares, price, type, pos) {
if (!Player.hasTixApiAccess) { if (!Player.hasTixApiAccess) {

@ -6,6 +6,7 @@ import {Company, Companies, getNextCompanyPosition,
getJobRequirementText, CompanyPosition, getJobRequirementText, CompanyPosition,
CompanyPositions} from "./Company.js"; CompanyPositions} from "./Company.js";
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {Corporation} from "./CompanyManagement.js";
import {Programs} from "./CreateProgram.js"; import {Programs} from "./CreateProgram.js";
import {determineCrimeSuccess} from "./Crimes.js"; import {determineCrimeSuccess} from "./Crimes.js";
import {Engine} from "./engine.js"; import {Engine} from "./engine.js";
@ -175,6 +176,9 @@ function PlayerObject() {
//Gang //Gang
this.gang = 0; this.gang = 0;
//Corporation
this.corporation = 0;
//bitnode //bitnode
this.bitNodeN = 1; this.bitNodeN = 1;
@ -370,6 +374,9 @@ PlayerObject.prototype.prestigeSourceFile = function() {
this.hasWseAccount = false; this.hasWseAccount = false;
this.hasTixApiAccess = false; this.hasTixApiAccess = false;
//BitNode 3: Corporatocracy
if (this.bitNodeN === 3) {this.money = new Decimal(150e9);}
//BitNode 8: Ghost of Wall Street //BitNode 8: Ghost of Wall Street
if (this.bitNodeN === 8) {this.money = new Decimal(100000000);} if (this.bitNodeN === 8) {this.money = new Decimal(100000000);}
if (this.bitNodeN === 8 || hasWallStreetSF) { if (this.bitNodeN === 8 || hasWallStreetSF) {
@ -2304,6 +2311,20 @@ function loadPlayer(saveString) {
Player.money = new Decimal(Player.money); Player.money = new Decimal(Player.money);
Player.total_money = new Decimal(Player.total_money); Player.total_money = new Decimal(Player.total_money);
Player.lifetime_money = new Decimal(Player.lifetime_money); Player.lifetime_money = new Decimal(Player.lifetime_money);
if (Player.corporation instanceof Corporation) {
Player.corporation.funds = new Decimal(Player.corporation.funds);
Player.corporation.revenue = new Decimal(Player.corporation.revenue);
Player.corporation.expenses = new Decimal(Player.corporation.expenses);
for (var i = 0; i < Player.corporation.divisions.length; ++i) {
var ind = Player.corporation.divisions[i];
ind.lastCycleRevenue = new Decimal(ind.lastCycleRevenue);
ind.lastCycleExpenses = new Decimal(ind.lastCycleExpenses);
ind.thisCycleRevenue = new Decimal(ind.thisCycleRevenue);
ind.thisCycleExpenses = new Decimal(ind.thisCycleExpenses);
}
}
} }
PlayerObject.prototype.toJSON = function() { PlayerObject.prototype.toJSON = function() {

@ -116,8 +116,11 @@ function prestigeAugmentation() {
} }
} }
//BitNode 3: Corporatocracy
if (Player.bitNodeN === 3) {Player.money = new Decimal(150e9);}
//BitNode 8: Ghost of Wall Street //BitNode 8: Ghost of Wall Street
if (Player.bitNodeN === 8) {Player.money = new Decimal(100000000);} if (Player.bitNodeN === 8) {Player.money = new Decimal(100e6);}
if (Player.bitNodeN === 8 || hasWallStreetSF) { if (Player.bitNodeN === 8 || hasWallStreetSF) {
Player.hasWseAccount = true; Player.hasWseAccount = true;
Player.hasTixApiAccess = true; Player.hasTixApiAccess = true;
@ -235,7 +238,7 @@ function prestigeSourceFile() {
if (Player.hasWseAccount) { if (Player.hasWseAccount) {
initStockMarket(); initStockMarket();
initSymbolToStockMap(); initSymbolToStockMap();
} }
setStockMarketContentCreated(false); setStockMarketContentCreated(false);
var stockMarketList = document.getElementById("stock-market-list"); var stockMarketList = document.getElementById("stock-market-list");
while(stockMarketList.firstChild) { while(stockMarketList.firstChild) {

@ -209,7 +209,7 @@ function loadBitVerse(destroyedBitNodeNum) {
var elemId = "bitnode-" + i.toString(); var elemId = "bitnode-" + i.toString();
var elem = clearEventListeners(elemId); var elem = clearEventListeners(elemId);
if (elem == null) {return;} if (elem == null) {return;}
if (i === 1 || i === 2 || i === 4 || i === 5 || i === 8 || i === 11) { if (i === 1 || i === 2 || i === 3 || i === 4 || i === 5 || i === 8 || i === 11) {
elem.addEventListener("click", function() { elem.addEventListener("click", function() {
var bitNodeKey = "BitNode" + i; var bitNodeKey = "BitNode" + i;
var bitNode = BitNodes[bitNodeKey]; var bitNode = BitNodes[bitNodeKey];

@ -30,7 +30,11 @@ function initSourceFiles() {
"Level 1: 20%<br>" + "Level 1: 20%<br>" +
"Level 2: 30%<br>" + "Level 2: 30%<br>" +
"Level 3: 35%"); "Level 3: 35%");
SourceFiles["SourceFile3"] = new SourceFile(3); SourceFiles["SourceFile3"] = new SourceFile(3,"This Source-File lets you create corporations on other BitNodes (although " +
"some BitNodes will disable this mechanic). This Source-File also increases your charisma and company salary multipliers by:<br>" +
"Level 1: 8%<br>" +
"Level 2: 12%<br>" +
"Level 3: 14%");
SourceFiles["SourceFile4"] = new SourceFile(4, "This Source-File lets you access and use the Singularity Functions in every BitNode. Every " + SourceFiles["SourceFile4"] = new SourceFile(4, "This Source-File lets you access and use the Singularity Functions in every BitNode. Every " +
"level of this Source-File opens up more of the Singularity Functions you can use."); "level of this Source-File opens up more of the Singularity Functions you can use.");
SourceFiles["SourceFile5"] = new SourceFile(5, "This Source-File grants a special new stat called Intelligence. Intelligence " + SourceFiles["SourceFile5"] = new SourceFile(5, "This Source-File grants a special new stat called Intelligence. Intelligence " +
@ -120,6 +124,15 @@ function applySourceFile(srcFile) {
Player.crime_success_mult *= incMult; Player.crime_success_mult *= incMult;
Player.charisma_mult *= incMult; Player.charisma_mult *= incMult;
break; break;
case 3: //Corporatocracy
var mult = 0;
for (var i = 0; i < srcFile.lvl; ++i) {
mult += (8 / (Math.pow(2, i)));
}
var incMult = 1 + (mult / 100);
Player.charisma_mult *= incMult;
Player.work_money_mult *= incMult;
break;
case 4: //The Singularity case 4: //The Singularity
//No effects, just gives access to Singularity functions //No effects, just gives access to Singularity functions
break; break;

@ -1,6 +1,6 @@
import {dialogBoxCreate} from "../utils/DialogBox.js"; import {dialogBoxCreate} from "../utils/DialogBox.js";
import {gameOptionsBoxOpen, gameOptionsBoxClose}from "../utils/GameOptions.js"; import {gameOptionsBoxOpen, gameOptionsBoxClose}from "../utils/GameOptions.js";
import {clearEventListeners} from "../utils/HelperFunctions.js"; import {clearEventListeners, createElement} from "../utils/HelperFunctions.js";
import numeral from "../utils/numeral.min.js"; import numeral from "../utils/numeral.min.js";
import {formatNumber, import {formatNumber,
convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions.js"; convertTimeMsToTimeElapsedString} from "../utils/StringHelperFunctions.js";
@ -14,6 +14,7 @@ import {Augmentations, installAugmentations,
import {BitNodes, initBitNodes, import {BitNodes, initBitNodes,
initBitNodeMultipliers} from "./BitNode.js"; initBitNodeMultipliers} from "./BitNode.js";
import {CompanyPositions, initCompanies} from "./Company.js"; import {CompanyPositions, initCompanies} from "./Company.js";
import {Corporation} from "./CompanyManagement.js";
import {CONSTANTS} from "./Constants.js"; import {CONSTANTS} from "./Constants.js";
import {Programs, displayCreateProgramContent, import {Programs, displayCreateProgramContent,
getNumAvailableCreateProgram, getNumAvailableCreateProgram,
@ -205,6 +206,7 @@ let Engine = {
StockMarket: "StockMarket", StockMarket: "StockMarket",
Gang: "Gang", Gang: "Gang",
Mission: "Mission", Mission: "Mission",
Corporation: "Corporation",
}, },
currentPage: null, currentPage: null,
@ -400,6 +402,15 @@ let Engine = {
Engine.currentPage = Engine.Page.Mission; Engine.currentPage = Engine.Page.Mission;
}, },
loadCorporationContent: function() {
if (Player.corporation instanceof Corporation) {
Engine.hideAllContent();
document.getElementById("character-overview-wrapper").style.visibility = "hidden";
Player.corporation.createUI();
Engine.currentPage = Engine.Page.Corporation;
}
},
//Helper function that hides all content //Helper function that hides all content
hideAllContent: function() { hideAllContent: function() {
Engine.Display.terminalContent.style.display = "none"; Engine.Display.terminalContent.style.display = "none";
@ -424,6 +435,10 @@ let Engine = {
document.getElementById("gang-container").style.display = "none"; document.getElementById("gang-container").style.display = "none";
} }
if (Player.corporation instanceof Corporation) {
Player.corporation.clearUI();
}
//Location lists //Location lists
Engine.aevumLocationsList.style.display = "none"; Engine.aevumLocationsList.style.display = "none";
Engine.chongqingLocationsList.style.display = "none"; Engine.chongqingLocationsList.style.display = "none";
@ -573,6 +588,13 @@ let Engine = {
break; break;
case Locations.Sector12: case Locations.Sector12:
Engine.sector12LocationsList.style.display = "inline"; Engine.sector12LocationsList.style.display = "inline";
//City hall only in BitNode-3
if (Player.bitNodeN === 3) {
document.getElementById("sector12-cityhall-li").style.display = "block";
} else {
document.getElementById("sector12-cityhall-li").style.display = "none";
}
break; break;
case Locations.NewTokyo: case Locations.NewTokyo:
Engine.newTokyoLocationsList.style.display = "inline"; Engine.newTokyoLocationsList.style.display = "inline";
@ -588,7 +610,20 @@ let Engine = {
break; break;
} }
document.getElementById("generic-locations-list").style.display = "inline"; var genericLocationsList = document.getElementById("generic-locations-list");
genericLocationsList.style.display = "inline";
if (Player.corporation instanceof Corporation && document.getElementById("location-corporation-button") == null) {
var li = createElement("li", {});
li.appendChild(createElement("a", {
innerText:Player.corporation.name, id:"location-corporation-button",
class:"a-link-button",
clickListener:()=>{
Engine.loadCorporationContent();
return false;
}
}));
genericLocationsList.appendChild(li);
}
}, },
displayFactionsInfo: function() { displayFactionsInfo: function() {
@ -852,6 +887,11 @@ let Engine = {
currMission.process(numCycles); currMission.process(numCycles);
} }
//Corporation
if (Player.corporation instanceof Corporation) {
Player.corporation.process(numCycles);
}
//Counters //Counters
Engine.decrementAllCounters(numCycles); Engine.decrementAllCounters(numCycles);
Engine.checkCounters(); Engine.checkCounters();
@ -926,6 +966,8 @@ let Engine = {
if (Engine.Counters.updateDisplaysMed <= 0) { if (Engine.Counters.updateDisplaysMed <= 0) {
if (Engine.currentPage == Engine.Page.ActiveScripts) { if (Engine.currentPage == Engine.Page.ActiveScripts) {
updateActiveScriptsItems(); updateActiveScriptsItems();
} else if (Engine.currentPage === Engine.Page.Corporation) {
Player.corporation.updateUIContent();
} }
Engine.Counters.updateDisplaysMed = 9; Engine.Counters.updateDisplaysMed = 9;
} }

@ -1,4 +1,5 @@
//General helper functions //General helper functions
import {isString} from "./StringHelperFunctions.js";
//Returns the size (number of keys) of an object //Returns the size (number of keys) of an object
function sizeOfObject(obj) { function sizeOfObject(obj) {
@ -46,6 +47,115 @@ function removeElementById(id) {
elem.parentNode.removeChild(elem); elem.parentNode.removeChild(elem);
} }
function removeChildrenFromElement(el) {
if (isString(el)) {
el = document.getElementById(el);
}
if (el == null) {return;}
if (el instanceof Element) {
while(el.firstChild) {
el.removeChild(el.firstChild);
}
}
}
function createElement(type, params) {
var el = document.createElement(type);
if (params.id) {el.id = params.id;}
if (params.class) {el.className = params.class;}
if (params.innerHTML) {el.innerHTML = params.innerHTML;}
if (params.innerText) {el.innerText = params.innerText;}
if (params.value) {el.value = params.value;}
if (params.text) {el.text = params.text;}
if (params.display) {el.style.display = params.display;}
if (params.visibility) {el.style.visibility = params.visibility;}
if (params.margin) {el.style.margin = params.margin;}
if (params.padding) {el.style.padding = params.padding;}
if (params.color) {el.style.color = params.color;}
if (params.border) {el.style.border = params.border;}
if (params.float) {el.style.cssFloat = params.float;}
if (params.backgroundColor) {
el.style.backgroundColor = params.backgroundColor
}
if (params.position) {el.style.position = params.position;}
if (params.type) {el.type = params.type;}
if (params.checked) {el.checked = params.checked;}
if (params.for) {el.htmlFor = params.for;}
if (params.pattern) {el.pattern = params.pattern;}
if (params.maxLength) {el.maxLength = params.maxLength;}
if (params.placeholder) {el.placeholder = params.placeholder;}
if (params.tooltip) {
el.className += " tooltip";
el.appendChild(createElement("span", {
class:"tooltiptext",
innerHTML:params.tooltip
}));
}
if (params.clickListener) {
el.addEventListener("click", params.clickListener);
}
if (params.inputListener) {
el.addEventListener("input", params.inputListener);
}
if (params.changeListener) {
el.addEventListener("change", params.changeListener);
}
return el;
}
function createPopup(id, elems) {
var container = createElement("div", {
class:"popup-box-container",
id:id,
display:"block"
}),
content = createElement("div", {
class:"popup-box-content",
});
for (var i = 0; i < elems.length; ++i) {
content.appendChild(elems[i]);
}
container.appendChild(content);
document.getElementById("entire-game-container").appendChild(container);
}
//Creates both the header and panel element of an accordion and sets the click handler
//Returns the 'li' element that contains the hedaer and panel
function createAccordionElement(params) {
var li = document.createElement("li"),
hdr = document.createElement("button"),
panel = document.createElement("div");
hdr.classList.add("accordion-header");
panel.classList.add("accordion-panel");
if (params.id) {
hdr.id = params.id + "-hdr";
panel.id = params.id + "-panel";
}
if (params.hdrText) {hdr.innerHTML = params.hdrText;}
if (params.panelText) {panel.innerHTML = params.panelText;}
li.appendChild(hdr);
li.appendChild(panel);
//Click handler
hdr.onclick = function() {
this.classList.toggle("active");
var tmpPanel = this.nextElementSibling;
if (tmpPanel.style.display === "block") {
tmpPanel.style.display = "none";
} else {
tmpPanel.style.display = "block";
}
}
return li;
}
function clearSelector(selector) {
for (var i = selector.options.length - 1; i >= 0; --i) {
selector.remove(i);
}
}
function getRandomInt(min, max) { function getRandomInt(min, max) {
if (min > max) {return getRandomInt(max, min);} if (min > max) {return getRandomInt(max, min);}
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
@ -76,4 +186,5 @@ function powerOfTwo(n) {
export {sizeOfObject, addOffset, clearEventListeners, getRandomInt, export {sizeOfObject, addOffset, clearEventListeners, getRandomInt,
compareArrays, printArray, powerOfTwo, clearEventListenersEl, compareArrays, printArray, powerOfTwo, clearEventListenersEl,
removeElementById}; removeElementById, createElement, createAccordionElement,
removeChildrenFromElement, createPopup, clearSelector};

@ -11,7 +11,7 @@ function yesNoBoxClose() {
console.log("ERROR: Container not found for YesNoBox"); console.log("ERROR: Container not found for YesNoBox");
} }
yesNoBoxOpen = false; yesNoBoxOpen = false;
return false; return false; //So that 'return yesNoBoxClose()' is return false in event listeners
} }
function yesNoBoxGetYesButton() { function yesNoBoxGetYesButton() {
@ -48,6 +48,7 @@ function yesNoTxtInpBoxClose() {
console.log("ERROR: Container not found for YesNoTextInputBox"); console.log("ERROR: Container not found for YesNoTextInputBox");
} }
yesNoBoxOpen = false; yesNoBoxOpen = false;
document.getElementById("yes-no-text-input-box-input").value = "";
return false; return false;
} }
@ -78,6 +79,8 @@ function yesNoTxtInpBoxCreate(txt) {
} else { } else {
console.log("ERROR: Container not found for YesNoTextInputBox"); console.log("ERROR: Container not found for YesNoTextInputBox");
} }
document.getElementById("yes-no-text-input-box-input").focus();
} }
export {yesNoBoxCreate, yesNoTxtInpBoxCreate, export {yesNoBoxCreate, yesNoTxtInpBoxCreate,