Initial changes for Gang mechanic rework

This commit is contained in:
danielyxie 2018-10-02 16:54:56 -05:00
parent 34cca95397
commit 45c434aa35
6 changed files with 167837 additions and 417 deletions

56428
dist/engine.bundle.js vendored

File diff suppressed because one or more lines are too long

111047
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bitburner</title>
<title>Bitburner - development</title>
<link rel="apple-touch-icon" sizes="180x180" href="dist/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
@ -109,7 +109,7 @@
<div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"/>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1" />
</div>
<div id="javascript-editor"></div>
@ -159,7 +159,7 @@
<fieldset>
<label for="script-editor-option-maxerr" class="tooltip">Max Error Count</label>
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr"/>
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr" />
<em id="script-editor-option-maxerror-value-label" style="font-style: normal;"></em>
</fieldset>
</div> <!-- End script editor options panel -->
@ -170,7 +170,7 @@
<table id="terminal">
<tr id="terminal-input">
<td id="terminal-input-td" tabindex="2">$
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;"/>
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;" />
</td>
</tr>
</table>
@ -187,7 +187,7 @@
provides information about each script's production. The scripts are categorized by the hostname of the servers on which
they are running. </p>
<p id="active-scripts-total-prod">Total online production of
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br/>
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br />
Total online production since last Aug installation: <span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span>
(<span class="money-gold"><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span>)</p>
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;">
@ -201,19 +201,19 @@
The Hacknet is a global, decentralized network of machines. It is used by hackers all around
the world to anonymously share computing power and perform distributed cyberattacks without the
fear of being traced.
<br/><br/>
<br /><br />
Here, you can purchase a Hacknet Node, a specialized machine that can connect and contribute its
resources to the Hacknet network. This allows you to take a small percentage of profits
from hacks performed on the network. Essentially, you are renting out your Node's computing power.
<br/><br/>
<br /><br />
Each Hacknet Node you purchase will passively earn you money. Each Hacknet Node can be upgraded
in order to increase its computing power and thereby increase the profit you earn from it.
</p>
<a id="hacknet-nodes-purchase-button" class="a-link-button"> Purchase Hacknet Node </a>
<br/>
<br />
<div id="hacknet-nodes-money-multipliers-div">
<p id="hacknet-nodes-money">
<span>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br/>
<span>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br />
<span>Total Hacknet Node Production:</span><span id="hacknet-nodes-total-production" class="money-gold"></span>
</p>
<span id="hacknet-nodes-multipliers">
@ -471,7 +471,8 @@
<!-- Tutorial content -->
<div id="tutorial-container" class="generic-menupage-container">
<a id="tutorial-getting-started-link" class="a-link-button" href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
<a id="tutorial-getting-started-link" class="a-link-button"
href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
<a id="tutorial-networking-link" class="a-link-button"> Servers & Networking </a>
<a id="tutorial-hacking-link" class="a-link-button"> Hacking </a>
<a id="tutorial-scripts-link" class="a-link-button"> Scripts </a>
@ -480,7 +481,8 @@
<a id="tutorial-jobs-link" class="a-link-button"> Companies and Infiltration </a>
<a id="tutorial-factions-link" class="a-link-button"> Factions </a>
<a id="tutorial-augmentations-link" class="a-link-button"> Augmentations </a>
<a id="tutorial-shortcuts-link" class="a-link-button" href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
<a id="tutorial-shortcuts-link" class="a-link-button"
href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
<a id="tutorial-back-button" class="a-link-button"> Back </a>
<p id="tutorial-text"> </p>
@ -623,7 +625,7 @@
<p id="location-slums-description">
You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and
other shadowy entities. The city's government and police have neglected this area for years...
<br/><br/><br/>
<br /><br /><br />
In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always
successful. Your chance at successfully committing a crime is determined by your stats.
</p>
@ -670,7 +672,7 @@
<div id="stock-market-container" class="generic-menupage-container">
<p>
Welcome to the World Stock Exchange (WSE)! <br/><br/>
Welcome to the World Stock Exchange (WSE)! <br /><br />
To begin trading, you must first purchase an account. WSE accounts will persist
after you 'reset' by installing Augmentations.
@ -683,7 +685,7 @@
TIX, short for Trade Information eXchange, is the communications protocol supported by the WSE.
Purchasing access to the TIX API lets you write code to create your own algorithmic/automated
trading strategies.
<br/><br/>
<br /><br />
If you purchase access to the TIX API, you will retain that access even after
you 'reset' by installing Augmentations.
</p>
@ -693,7 +695,7 @@
<p>
Four Sigma's (4S) Market Data Feed provides information about stocks
that will help your trading strategies.
<br/><br/>
<br /><br />
If you purchase access to 4S Market Data and/or the 4S TIX API, you will
retain that access even after you 'reset' by installing Augmentations.
</p>
@ -711,7 +713,7 @@
<a id="stock-market-mode" class="a-link-button tooltip"></a>
<a id="stock-market-expand-tickers" class="a-link-button tooltip">Expand tickers</a>
<a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a>
<br/><br/>
<br /><br />
<input id="stock-market-watchlist-filter" type="text" placeholder="Filter Stocks by symbol (comma-separated list)"/>
<a id="stock-market-watchlist-filter-update" class="a-link-button"> Update Watchlist </a>
<ul id="stock-market-list" style="list-style:none;">
@ -741,7 +743,7 @@
<div id="yes-no-text-input-box-container" class="popup-box-container">
<div id="yes-no-text-input-box-content" class="popup-box-content">
<p id="yes-no-text-input-box-text"> </p>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30"/>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30" />
<span id="yes-no-text-input-box-yes" class="popup-box-button"> Yes </span>
<span id="yes-no-text-input-box-no" class="popup-box-button"> No </span>
</div>
@ -753,7 +755,7 @@
<p id="faction-invitation-box-text"> </p>
<p id="faction-invitation-box-message"> </p>
<p id="faction-invitation-box-warning">
Would you like to join? <br/> <br/>
Would you like to join? <br /> <br />
Warning: Joining this faction may prevent you from joining other factions during this run!
</p>
<span id="faction-invitation-box-yes" class="popup-box-button"> Yes </span>
@ -766,8 +768,8 @@
<div id="infiltration-box-content" class="popup-box-content">
<p id="infiltration-box-text"> </p>
<span id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </span> <br/><br/>
<select id="infiltration-faction-select"> </select> <br/>
<span id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </span> <br /><br />
<select id="infiltration-faction-select"> </select> <br />
<span id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </span>
</div>
@ -853,7 +855,7 @@
<div id="game-options-content" class="game-options-box">
<span id="game-options-close-button">&times;</span>
<h1> Game Options </h1>
<br/>
<br />
<div id="game-options-left-panel">
<!-- Netscript execution time -->
<fieldset>
@ -865,7 +867,7 @@
</span>
</label>
<input type="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25"/>
<input type ="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25" />
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -879,7 +881,7 @@
</span>
</label>
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50"/>
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50" />
<em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -893,7 +895,7 @@
</span>
</label>
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50"/>
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50" />
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -905,7 +907,7 @@
</span>
</label>
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60"/>
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60" />
<em id="settingsAutosaveIntervalValLabel" style="font-style: normal;"></em>
</fieldset>
@ -1017,7 +1019,7 @@
<a id="save-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Save Game </a>
<a id="delete-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Delete Game </a>
<a id="export-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Export Game </a>
<input type="file" id="import-game-file-selector" name="file"/>
<input type="file" id="import-game-file-selector" name="file" />
<a id="import-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Import Game </a>
<a id="debug-delete-scripts-link" class="a-link-button tooltip" style="display:block;width:46%;">
(DEBUG) Delete Active Scripts

@ -1,3 +1,18 @@
/*
gang member upgrades - they should be cheaper as the gang gets more respect/power
kopelli09/12/2018
Another gang-related idea (and perhaps I'm not seeing it in the code) - gangs can lose power. Seems odd that the player's power can drop by removing members, but the other gangs are forever gaining power...
Grub09/12/2018
Maybe add a % chance of other gangs clashing?
assign gangs a number of gang members and each clash kills a number of gang members based on each one's power
and they lose a proportionate number of members
Also add police clashes
balance point to keep them from running out of control
*/
import {gangMemberTasksMetadata} from "./data/gangmembertasks";
import {gangMemberUpgradesMetadata} from "./data/gangmemberupgrades";
import {Engine} from "./engine";
import {Faction, Factions,
displayFactionContent} from "./Faction";
@ -11,6 +26,7 @@ import {createElement} from "../utils/uiHelpers/createE
import {createPopup} from "../utils/uiHelpers/createPopup";
import {Page, routing} from "./ui/navigationTracking";
import {formatNumber} from "../utils/StringHelperFunctions";
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
import {getRandomInt} from "../utils/helpers/getRandomInt";
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
import {removeElement} from "../utils/uiHelpers/removeElement";
@ -22,11 +38,11 @@ import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox";
// Constants
const GangRespectToReputationRatio = 2; //Respect is divided by this to get rep gain
const MaximumGangMembers = 47;
const GangRecruitCostMultiplier = 2;
const GangTerritoryUpdateTimer = 150;
const AscensionMultiplierRatio = 10 / 100; //Portion upgrade multiplier is kept after ascending
// Switch between territory and management screen with 1 and 2
$(document).keydown(function(event) {
@ -218,7 +234,7 @@ Gang.prototype.processGains = function(numCycles=1) {
console.log("ERROR: Gang's storedCylces is NaN");
this.storedCycles = 0;
}
if (this.storedCycles < 25) {return;} //Only process every 5 seconds at least
if (this.storedCycles < 25) { return; } //Only process every 5 seconds at least
//Get gains per cycle
var moneyGains = 0, respectGains = 0, wantedLevelGains = 0;
@ -231,10 +247,10 @@ Gang.prototype.processGains = function(numCycles=1) {
this.wantedGainRate = wantedLevelGains;
this.moneyGainRate = moneyGains;
if (!isNaN(respectGains)) {
if (typeof respectGains === "number") {
var gain = respectGains * this.storedCycles;
this.respect += (gain);
//Faction reputation gains is respect gain divided by some constant
// Faction reputation gains is respect gain divided by some constant
var fac = Factions[this.facName];
if (!(fac instanceof Faction)) {
dialogBoxCreate("ERROR: Could not get Faction associates with your gang. This is a bug, please report to game dev");
@ -243,28 +259,58 @@ Gang.prototype.processGains = function(numCycles=1) {
fac.playerReputation += ((Player.faction_rep_mult * gain * favorMult) / GangRespectToReputationRatio);
}
} else {
console.log("ERROR: respectGains is NaN");
// Keep track of respect gained per member
for (let i = 0; i < this.members.length; ++i) {
this.members[i].recordEarnedRespect(this.storedCycles);
}
if (!isNaN(wantedLevelGains)) {
} else {
console.warn("respectGains calculated to be NaN");
}
if (typeof wantedLevelGains === "number") {
if (this.wanted === 1 && wantedLevelGains < 0) {
//Do nothing
} else {
this.wanted += (wantedLevelGains * this.storedCycles);
const oldWanted = this.wanted;
let newWanted = + (wantedLevelGains * this.storedCycles);
// Prevent overflow
if (wantedLevelGains <= 0 && newWanted > oldWanted) {
newWanted = 1;
}
this.wanted = newWanted;
if (this.wanted < 1) {this.wanted = 1;}
}
} else {
console.log("ERROR: wantedLevelGains is NaN");
console.warn("ERROR: wantedLevelGains is NaN");
}
if (!isNaN(moneyGains)) {
if (typeof moneyGains === "number") {
Player.gainMoney(moneyGains * this.storedCycles);
} else {
console.log("ERROR: respectGains is NaN");
console.warn("ERROR: respectGains is NaN");
}
this.storedCycles = 0;
}
Gang.prototype.canRecruitMember = function() {
if (this.members.length >= MaximumGangMembers) { return false; }
return (this.respect >= this.getRespectNeededToRecruitMember());
}
Gang.prototype.getRespectNeededToRecruitMember = function() {
// First 3 members are free
if (this.members.length < 3) { return 0; }
const i = this.members.length;
return Math.round(0.7 * Math.pow(i, 3) + 0.8 * Math.pow(i, 2));
}
// Money and Respect gains multiplied by this number (< 1)
Gang.prototype.getWantedPenalty = function() {
return (this.respect) / (this.respect + this.wanted);
}
Gang.prototype.processExperienceGains = function(numCycles=1) {
for (var i = 0; i < this.members.length; ++i) {
this.members[i].gainExperience(numCycles);
@ -284,24 +330,17 @@ Gang.prototype.calculatePower = function() {
return (0.0005 * memberTotal);
}
Gang.prototype.autoAssignMemberToTask = function(taskName) {
for (var i = 0; i < this.members.length; ++i) {
if (this.members[i].task.name === taskName) {
this.members[i].assignToTask(taskName);
return true;
}
}
return false;
Gang.prototype.killMember = function(memberObj) {
// TODO
}
Gang.prototype.autoUnassignMemberFromTask = function(taskName) {
for (var i = 0; i < this.members.length; ++i) {
if (this.members[i].task.name === taskName) {
this.members[i].unassignFromTask();
return true;
Gang.prototype.ascendMember = function(memberObj) {
try {
//Member.ascend() returns the amount of respect to deduct
this.respect = Math.min(1, this.respect - memberObj.ascend());
} catch(e) {
exceptionAlert(e);
}
}
return false;
}
Gang.prototype.toJSON = function() {
@ -318,7 +357,8 @@ Reviver.constructors.Gang = Gang;
function GangMember(name) {
this.name = name;
this.task = GangMemberTasks["Unassigned"]; //GangMemberTask object
this.city = Player.city;
this.earnedRespect = 0;
this.hack = 1;
this.str = 1;
@ -341,21 +381,29 @@ function GangMember(name) {
this.agi_mult = 1;
this.cha_mult = 1;
this.hack_asc_mult = 1;
this.str_asc_mult = 1;
this.def_asc_mult = 1;
this.dex_asc_mult = 1;
this.agi_asc_mult = 1;
this.cha_asc_mult = 1;
this.upgrades = []; //Names of upgrades
this.augmentations = []; //Names only
}
//Same formula for Player
GangMember.prototype.calculateSkill = function(exp, mult=1) {
return Math.max(Math.floor(mult*(32 * Math.log(exp + 534.5) - 200)), 1);
return Math.max(Math.floor(mult * (32 * Math.log(exp + 534.5) - 200)), 1);
}
GangMember.prototype.updateSkillLevels = function() {
this.hack = this.calculateSkill(this.hack_exp, this.hack_mult);
this.str = this.calculateSkill(this.str_exp, this.str_mult);
this.def = this.calculateSkill(this.def_exp, this.def_mult);
this.dex = this.calculateSkill(this.dex_exp, this.dex_mult);
this.agi = this.calculateSkill(this.agi_exp, this.agi_mult);
this.cha = this.calculateSkill(this.cha_exp, this.cha_mult);
this.hack = this.calculateSkill(this.hack_exp, this.hack_mult * this.hack_asc_mult);
this.str = this.calculateSkill(this.str_exp, this.str_mult * this.str_asc_mult);
this.def = this.calculateSkill(this.def_exp, this.def_mult * this.def_asc_mult);
this.dex = this.calculateSkill(this.dex_exp, this.dex_mult * this.dex_asc_mult);
this.agi = this.calculateSkill(this.agi_exp, this.agi_mult * this.agi_asc_mult);
this.cha = this.calculateSkill(this.cha_exp, this.cha_mult * this.cha_asc_mult);
}
GangMember.prototype.calculatePower = function() {
@ -391,10 +439,10 @@ GangMember.prototype.calculateRespectGain = function() {
(task.agiWeight/100) * this.agi +
(task.chaWeight/100) * this.cha;
statWeight -= (3.5 * task.difficulty);
if (statWeight <= 0) {return 0;}
if (statWeight <= 0) { return 0; }
var territoryMult = AllGangs[Player.gang.facName].territory;
if (territoryMult <= 0) {return 0;}
var respectMult = (Player.gang.respect) / (Player.gang.respect + Player.gang.wanted);
if (territoryMult <= 0) { return 0; }
var respectMult = Player.gang.getWantedPenalty();
return 12 * task.baseRespect * statWeight * territoryMult * respectMult;
}
@ -431,7 +479,7 @@ GangMember.prototype.calculateMoneyGain = function() {
if (statWeight <= 0) {return 0;}
var territoryMult = AllGangs[Player.gang.facName].territory;
if (territoryMult <= 0) {return 0;}
var respectMult = (Player.gang.respect) / (Player.gang.respect + Player.gang.wanted);
var respectMult = Player.gang.getWantedPenalty();
return 5 * task.baseMoney * statWeight * territoryMult * respectMult;
}
@ -446,6 +494,58 @@ GangMember.prototype.gainExperience = function(numCycles=1) {
this.cha_exp += (task.chaWeight / 1500) * task.difficulty * numCycles;
}
GangMember.prototype.recordEarnedRespect = function(numCycles=1) {
this.earnedRespect += (this.calculateRespectGain() * numCycles);
}
GangMember.prototype.ascend = function() {
// Calculate ascension bonus to stat multipliers.
// This is based on the current number of multipliers from Non-Augmentation upgrades
// + Ascension Bonus = N% of current bonus from Augmentations
let hack = 1;
let str = 1;
let def = 1;
let dex = 1;
let agi = 1;
let cha = 1;
for (let i = 0; i < this.upgrades.length; ++i) {
let upg = GangMemberUpgrades[this.upgrades[i]];
if (upg.mults.hack != null) { hack *= upg.mults.hack; }
if (upg.mults.str != null) { str *= upg.mults.str; }
if (upg.mults.def != null) { def *= upg.mults.def; }
if (upg.mults.dex != null) { dex *= upg.mults.dex; }
if (upg.mults.agi != null) { agi *= upg.mults.agi; }
if (upg.mults.cha != null) { cha *= upg.mults.cha; }
}
// Get just the bonus multiplier part, and then record
--hack; --str; --def; --dex; --agi; --cha;
this.hack_asc_mult += (hack * AscensionMultiplierRatio);
this.str_asc_mult += (str * AscensionMultiplierRatio);
this.def_asc_mult += (def * AscensionMultiplierRatio);
this.dex_asc_mult += (dex * AscensionMultiplierRatio);
this.agi_asc_mult += (agi * AscensionMultiplierRatio);
this.cha_asc_mult += (cha * AscensionMultiplierRatio);
// Remove upgrades. Then re-calculate multipliers and stats
this.upgrades.length = 0;
this.hack_mult = 1;
this.str_mult = 1;
this.def_mult = 1;
this.dex_mult = 1;
this.agi_mult = 1;
this.cha_mult = 1;
for (let i = 0; i < this.augmentations.length; ++i) {
let aug = GangMemberUpgrades[this.augmentations[i]];
aug.apply(this);
}
this.updateSkillLevels();
const respectToDeduct = this.earnedRespect;
this.earnedRespect = 0;
return respectToDeduct;
}
GangMember.prototype.toJSON = function() {
return Generic_toJSON("GangMember", this);
}
@ -492,163 +592,46 @@ GangMemberTask.fromJSON = function(value) {
Reviver.constructors.GangMemberTask = GangMemberTask;
//TODO Human trafficking and an equivalent hacking crime
let GangMemberTasks = {
"Unassigned" : new GangMemberTask(
"Unassigned",
"This gang member is currently idle"),
"Ransomware" : new GangMemberTask(
"Ransomware",
"Assign this gang member to create and distribute ransomware<br><br>" +
"Earns money - Slightly increases respect - Slightly increases wanted level",
{baseRespect: 0.00005, baseWanted: 0.00001, baseMoney: 1,
hackWeight: 100, difficulty: 1}),
"Phishing" : new GangMemberTask(
"Phishing",
"Assign this gang member to attempt phishing scams and attacks<br><br>" +
"Earns money - Slightly increases respect - Slightly increases wanted level",
{baseRespect: 0.00008, baseWanted: 0.001, baseMoney: 2.5,
hackWeight: 85, chaWeight: 15, difficulty: 3}),
"Identity Theft" : new GangMemberTask(
"Identity Theft",
"Assign this gang member to attempt identity theft<br><br>" +
"Earns money - Increases respect - Increases wanted level",
{baseRespect: 0.0001, baseWanted: 0.01, baseMoney: 6,
hackWeight: 80, chaWeight: 20, difficulty: 4}),
"DDoS Attacks" : new GangMemberTask(
"DDoS Attacks",
"Assign this gang member to carry out DDoS attacks<br><br>" +
"Increases respect - Increases wanted level",
{baseRespect: 0.0004, baseWanted: 0.05,
hackWeight: 100, difficulty: 7}),
"Plant Virus" : new GangMemberTask(
"Plant Virus",
"Assign this gang member to create and distribute malicious viruses<br><br>" +
"Increases respect - Increases wanted level",
{baseRespect: 0.0006, baseWanted: 0.05,
hackWeight: 100, difficulty: 10}),
"Fraud & Counterfeiting" : new GangMemberTask(
"Fraud & Counterfeiting",
"Assign this gang member to commit financial fraud and digital counterfeiting<br><br>" +
"Earns money - Slightly increases respect - Slightly increases wanted level",
{baseRespect: 0.0005, baseWanted: 0.1, baseMoney: 15,
hackWeight: 80, chaWeight: 20, difficulty: 17}),
"Money Laundering" : new GangMemberTask(
"Money Laundering",
"Assign this gang member to launder money<br><br>" +
"Earns money - Increases respect - Increases wanted level",
{baseRespect: 0.0006, baseWanted:0.2, baseMoney: 40,
hackWeight: 75, chaWeight: 25, difficulty: 20}),
"Cyberterrorism" : new GangMemberTask(
"Cyberterrorism",
"Assign this gang member to commit acts of cyberterrorism<br><br>" +
"Greatly increases respect - Greatly increases wanted level",
{baseRespect: 0.001, baseWanted: 0.5,
hackWeight: 80, chaWeight: 20, difficulty: 33}),
"Ethical Hacking" : new GangMemberTask(
"Ethical Hacking",
"Assign this gang member to be an ethical hacker for corporations<br><br>" +
"Earns money - Lowers wanted level",
{baseWanted: -0.001, baseMoney: 1,
hackWeight: 90, chaWeight: 10, difficulty: 1}),
"Mug People" : new GangMemberTask(
"Mug People",
"Assign this gang member to mug random people on the streets<br><br>" +
"Earns money - Slightly increases respect - Very slightly increases wanted level",
{baseRespect: 0.00005, baseWanted: 0.00001, baseMoney: 1,
strWeight: 25, defWeight: 25, dexWeight: 25, agiWeight: 10, chaWeight: 15, difficulty: 1}),
"Deal Drugs" : new GangMemberTask(
"Deal Drugs",
"Assign this gang member to sell drugs.<br><br>" +
"Earns money - Slightly increases respect - Slightly increases wanted level",
{baseRespect: 0.00008, baseWanted: 0.001, baseMoney: 4,
agiWeight: 20, dexWeight: 20, chaWeight: 60, difficulty: 3}),
"Run a Con" : new GangMemberTask(
"Run a Con",
"Assign this gang member to run cons<br><br>" +
"Earns money - Increases respect - Increases wanted level",
{baseRespect: 0.00015, baseWanted: 0.01, baseMoney: 10,
strWeight: 5, defWeight: 5, agiWeight: 25, dexWeight: 25, chaWeight: 40, difficulty: 10}),
"Armed Robbery" : new GangMemberTask(
"Armed Robbery",
"Assign this gang member to commit armed robbery on stores, banks and armored cars<br><br>" +
"Earns money - Increases respect - Increases wanted level",
{baseRespect: 0.00015, baseWanted: 0.05, baseMoney: 25,
hackWeight: 20, strWeight: 15, defWeight: 15, agiWeight: 10, dexWeight: 20, chaWeight: 20,
difficulty: 17}),
"Traffick Illegal Arms" : new GangMemberTask(
"Traffick Illegal Arms",
"Assign this gang member to traffick illegal arms<br><br>" +
"Earns money - Increases respect - Increases wanted level",
{baseRespect: 0.0003, baseWanted: 0.1, baseMoney: 40,
hackWeight: 15, strWeight: 20, defWeight: 20, dexWeight: 20, chaWeight: 75,
difficulty: 25}),
"Threaten & Blackmail" : new GangMemberTask(
"Threaten & Blackmail",
"Assign this gang member to threaten and black mail high-profile targets<br><br>" +
"Earns money - Slightly increases respect - Slightly increases wanted level",
{baseRespect: 0.0002, baseWanted: 0.05, baseMoney: 15,
hackWeight: 25, strWeight: 25, dexWeight: 25, chaWeight: 25, difficulty: 28}),
"Terrorism" : new GangMemberTask(
"Terrorism",
"Assign this gang member to commit acts of terrorism<br><br>" +
"Greatly increases respect - Greatly increases wanted level",
{baseRespect: 0.001, baseWanted: 1,
hackWeight: 20, strWeight: 20, defWeight: 20,dexWeight: 20, chaWeight: 20,
difficulty: 33}),
"Vigilante Justice" : new GangMemberTask(
"Vigilante Justice",
"Assign this gang member to be a vigilante and protect the city from criminals<br><br>" +
"Decreases wanted level",
{baseWanted: -0.001,
hackWeight: 20, strWeight: 20, defWeight: 20, dexWeight: 20, agiWeight:20,
difficulty: 1}),
"Train Combat" : new GangMemberTask(
"Train Combat",
"Assign this gang member to increase their combat stats (str, def, dex, agi)",
{strWeight: 25, defWeight: 25, dexWeight: 25, agiWeight: 25, difficulty: 5}),
"Train Hacking" : new GangMemberTask(
"Train Hacking",
"Assign this gang member to train their hacking skills",
{hackWeight: 100, difficulty: 8}),
"Territory Warfare" : new GangMemberTask(
"Territory Warfare",
"Assign this gang member to engage in territorial warfare with other gangs. " +
"Members assigned to this task will help increase your gang's territory " +
"and will defend your territory from being taken.",
{hackWeight: 15, strWeight: 20, defWeight: 20, dexWeight: 20, agiWeight: 20,
chaWeight: 5, difficulty: 3}),
const GangMemberTasks = {};
function addGangMemberTask(name, desc, params) {
GangMemberTasks[name] = new GangMemberTask(name, desc, params);
}
gangMemberTasksMetadata.forEach((e) => {
addGangMemberTask(e.name, e.desc, e.params);
});
function GangMemberUpgrade(name="", cost=0, type="w", mults={}) {
this.name = name;
this.cost = cost;
this.type = type; //w, a, v, r, g
this.type = type; //w = weapon, a = armor, v = vehicle, r = rootkit, g = Aug
this.mults = mults;
this.createDescription();
}
GangMemberUpgrade.prototype.createDescription = function() {
var lines = ["Increases:\n"];
const lines = ["Increases:"];
if (this.mults.str != null) {
lines.push(`* Strength by ${Math.round((this.mults.str - 1) * 100)%}`);
lines.push(`* Strength by ${Math.round((this.mults.str - 1) * 100)}%`);
}
if (this.mults.def != null) {
lines.push(`* Defense by ${Math.round((this.mults.def - 1) * 100)%}`);
lines.push(`* Defense by ${Math.round((this.mults.def - 1) * 100)}%`);
}
if (this.mults.dex != null) {
lines.push(`* Dexterity by ${Math.round((this.mults.dex - 1) * 100)%}`);
lines.push(`* Dexterity by ${Math.round((this.mults.dex - 1) * 100)}%`);
}
if (this.mults.agi != null) {
lines.push(`* Agility by ${Math.round((this.mults.agi - 1) * 100)%}`);
lines.push(`* Agility by ${Math.round((this.mults.agi - 1) * 100)}%`);
}
if (this.mults.cha != null) {
lines.push(`* Charisma by ${Math.round((this.mults.cha - 1) * 100)%}`);
lines.push(`* Charisma by ${Math.round((this.mults.cha - 1) * 100)}%`);
}
if (this.mults.hack != null) {
lines.push(`* Hacking by ${Math.round((this.mults.hack - 1) * 100)%}`);
lines.push(`* Hacking by ${Math.round((this.mults.hack - 1) * 100)}%`);
}
this.desc = lines.join("\n");
}
//Passes in a GangMember object
@ -672,32 +655,16 @@ GangMemberUpgrade.fromJSON = function(value) {
Reviver.constructors.GangMemberUpgrade = GangMemberUpgrade;
// Initialize Gang Member Upgrades
const GangMemberUpgrades = {}
function addGangMemberUpgrade(name, cost, type, mults) {
GangMemberUpgrades[name] = new GangMemberUpgrade(name, desc, cost, type, mults);
GangMemberUpgrades[name] = new GangMemberUpgrade(name, cost, type, mults);
}
addGangMemberUpgrade("Baseball Bat", 1e6, "w", {str: 1.05, def: 1.05});
addGangMemberUpgrade("Katana", 12e6, "w", {str: 1.10, def: 1.10, dex: 1.10});
addGangMemberUpgrade("Glock 18C", 25e6, "w", {str: 1.15, def: 1.15, dex: 1.15, agi: 1.15});
addGangMemberUpgrade("P90C", 50e6, "w", {str: 1.20, def: 1.20, agi: 1.10});
addGangMemberUpgrade("Steyr AUG", 60e6, "w", {str: 1.25, def: 1.25});
addGangMemberUpgrade("AK-47", 100e6, "w", {str: 1.50, def: 1.50});
addGangMemberUpgrade("M15A10 Assault Rifle", 150e6, "w", {str: 1.60, def: 1.60});
addGangMemberUpgrade("AWM Sniper Rifle", 225e6, "w", {str: 1.50, dex: 1.50, agi: 1.50});
addGangMemberUpgrade("Bulletproof Vest", 2e6, "a", {def: 1.05});
addGangMemberUpgrade("Full Body Armor", 5e6, "a", {def: 1.10});
addGangMemberUpgrade("Liquid Body Armor", 25e6, "a", {def: 1.25, agi: 1.25});
addGangMemberUpgrade("Graphene Plating Armor", 40e6, "a", {def: 1.50});
addGangMemberUpgrade("Ford Flex V20", 3e6, "v", {agi: 1.10, cha: 1.10});
addGangMemberUpgrade("ATX1070 Superbike", 9e6, "v", {agi: 1.15, cha: 1.15});
addGangMemberUpgrade("Mercedes-Benz S9001", 18e6, "v", {agi: 1.20, cha: 1.20});
addGangMemberUpgrade("White Ferrari", 30e6, "v", {agi: 1.25, cha: 1.25});
addGangMemberUpgrade("NUKE Rootkit", 5e6, "r", {hack: 1.10});
addGangMemberUpgrade("Soulstealer Rootkit", 15e6, "r", {hack: 1.20});
addGangMemberUpgrade("Demon Rootkit", 50e6, "r", {hack: 1.30});
addGangMemberUpgrade("Bionic Arm";
gangMemberUpgradesMetadata.forEach((e) => {
addGangMemberUpgrade(e.name, e.cost, e.upgType, e.mults);
});
//Create a pop-up box that lets player purchase upgrades
let gangMemberUpgradeBoxOpened = false;
@ -796,10 +763,15 @@ function createGangMemberUpgradePanel(memberObj) {
container.appendChild(createElement("br", {}));
//Upgrade buttons. Only show upgrades that can be afforded
var weaponUpgrades = [], armorUpgrades = [], vehicleUpgrades = [], rootkitUpgrades = [];
for (var upgName in GangMemberUpgrades) {
const weaponUpgrades = [];
const armorUpgrades = [];
const vehicleUpgrades = [];
const rootkitUpgrades = [];
const augUpgrades = [];
for (let upgName in GangMemberUpgrades) {
if (GangMemberUpgrades.hasOwnProperty(upgName)) {
var upg = GangMemberUpgrades[upgName];
let upg = GangMemberUpgrades[upgName];
if (Player.money.lt(upg.cost) || memberObj.upgrades.includes(upgName)) {continue;}
switch (upg.type) {
case "w":
@ -814,34 +786,41 @@ function createGangMemberUpgradePanel(memberObj) {
case "r":
rootkitUpgrades.push(upg);
break;
case "g":
augUpgrades.push(upg);
default:
console.log("ERROR: Invalid Gang Member Upgrade Type: " + upg.type);
console.error(`ERROR: Invalid Gang Member Upgrade Type: ${upg.type}`);
}
}
}
var weaponDiv = createElement("div", {width:"20%", display:"inline-block",});
var armorDiv = createElement("div", {width:"20%", display:"inline-block",});
var vehicleDiv = createElement("div", {width:"20%", display:"inline-block",});
var rootkitDiv = createElement("div", {width:"20%", display:"inline-block",});
var upgrades = [weaponUpgrades, armorUpgrades, vehicleUpgrades, rootkitUpgrades];
var divs = [weaponDiv, armorDiv, vehicleDiv, rootkitDiv];
const weaponDiv = createElement("div", {width: "16%", display: "inline-block"});
const armorDiv = createElement("div", {width: "16%", display: "inline-block"});
const vehicleDiv = createElement("div", {width: "16%", display: "inline-block"});
const rootkitDiv = createElement("div", {width: "16%", display: "inline-block"});
const augDiv = createElement("div", {width: "16%", display: "inline-block"});
const upgrades = [weaponUpgrades, armorUpgrades, vehicleUpgrades, rootkitUpgrades, augUpgrades];
const divs = [weaponDiv, armorDiv, vehicleDiv, rootkitDiv, augDiv];
for (var i = 0; i < upgrades.length; ++i) {
var upgradeArray = upgrades[i];
var div = divs[i];
for (var j = 0; j < upgradeArray.length; ++j) {
var upg = upgradeArray[j];
for (let i = 0; i < upgrades.length; ++i) {
let upgradeArray = upgrades[i];
let div = divs[i];
for (let j = 0; j < upgradeArray.length; ++j) {
let upg = upgradeArray[j];
(function (upg, div, memberObj) {
div.appendChild(createElement("a", {
innerText:upg.name + " - " + numeralWrapper.format(upg.cost, "$0.000a"),
class:"a-link-button", margin:"2px", padding:"2px", display:"block",
fontSize:"12px",
fontSize:"11px",
tooltip:upg.desc,
clickListener:()=>{
if (Player.money.lt(upg.cost)) {return false;}
if (Player.money.lt(upg.cost)) { return false; }
Player.loseMoney(upg.cost);
if (upg.type === "g") {
memberObj.augmentations.push(upg.name);
} else {
memberObj.upgrades.push(upg.name);
}
upg.apply(memberObj);
var initFilterValue = gangMemberUpgradeBoxFilter.value.toString();
createGangMemberUpgradeBox(initFilterValue);
@ -877,7 +856,6 @@ let gangDesc = null, gangInfo = null,
let gangMemberUpgradeBox = null, gangMemberUpgradeBoxContent = null,
gangMemberUpgradeBoxFilter = null, gangMemberUpgradeBoxElements = null;
//Gang Territory Elements
let gangTerritoryDescText = null, gangTerritoryInfoText = null;
@ -1169,19 +1147,18 @@ function updateGangContent() {
}));
gangInfo.appendChild(createElement("br", {}));
var wantedPenalty = (Player.gang.respect) / (Player.gang.respect + Player.gang.wanted);
var wantedPenalty = Player.gang.getWantedPenalty();
wantedPenalty = (1 - wantedPenalty) * 100;
gangInfo.appendChild(createElement("p", { //Wanted Level multiplier
display:"inline-block",
innerText:"Wanted Level Penalty: -" + formatNumber(wantedPenalty, 2) + "%",
innerText:`Wanted Level Penalty: - ${formatNumber(wantedPenalty, 2)}%`,
tooltip:"Penalty for respect and money gain rates due to Wanted Level"
}));
gangInfo.appendChild(createElement("br", {}));
gangInfo.appendChild(createElement("p", { //Money gain rate
display:"inline-block",
innerText:"Money gain rate: $" + formatNumber(5*Player.gang.moneyGainRate, 2) +
" / sec",
innerText: `Money gain rate: ${numeralWrapper.format(5 * Player.gang.moneyGainRate, $0.000a)} / sec`);
}));
gangInfo.appendChild(createElement("br", {}));
@ -1197,7 +1174,7 @@ function updateGangContent() {
}
gangInfo.appendChild(createElement("p", { //Territory multiplier
display:"inline-block",
innerText:"Territory: " + formatNumber(displayNumber, 3) + "%",
innerText:`Territory: ${formatNumber(displayNumber, 3)}%`,
tooltip:"The percentage of total territory your Gang controls"
}));
gangInfo.appendChild(createElement("br", {}));
@ -1213,33 +1190,22 @@ function updateGangContent() {
//Toggle the 'Recruit member button' if valid
var numMembers = Player.gang.members.length;
var repCost = 0;
if (numMembers > 0) {
var repCost = Math.pow(GangRecruitCostMultiplier, numMembers);
}
var faction = Factions[Player.gang.facName];
if (faction == null) {
dialogBoxCreate("Could not find your gang's faction. This is probably a bug please report to dev");
return;
}
var btn = gangRecruitMemberButton;
const respectCost = Player.gang.getRespectNeededToRecruitMember();
if (numMembers >= MaximumGangMembers) {
btn.className = "a-link-button-inactive";
gangRecruitRequirementText.style.display = "block";
gangRecruitRequirementText.innerHTML =
"You have reached the maximum amount of gang members";
} else if (faction.playerReputation >= repCost) {
gangRecruitRequirementText.innerHTML = "You have reached the maximum amount of gang members";
} else if (Player.gang.canRecruitMember()) {
btn.className = "a-link-button";
gangRecruitRequirementText.style.display = "none";
} else {
btn.className = "a-link-button-inactive";
gangRecruitRequirementText.style.display = "block";
gangRecruitRequirementText.innerHTML =
formatNumber(repCost, 2) + " Faction reputation needed to recruit next member";
gangRecruitRequirementText.innerHTML = `${formatNumber(repCost, 2)} respect needed to recruit next member`;
}
//Update information for each gang member
for (var i = 0; i < Player.gang.members.length; ++i) {
for (let i = 0; i < Player.gang.members.length; ++i) {
updateGangMemberDisplayElement(Player.gang.members[i]);
}
}

112
src/data/gangmembertasks.ts Normal file

@ -0,0 +1,112 @@
export interface IGangMemberTaskMetadata {
desc: string;
name: string;
params?: any;
}
export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
{
desc: "This gang member is currently idle",
name: "Unassigned",
},
{
desc: "Assign this gang member to create and distribute ransomware<br><br>Earns money - Slightly increases respect - Slightly increases wanted level",
name: "Ransomware",
params: {baseRespect: 0.00005, baseWanted: 0.00001, baseMoney: 1, hackWeight: 100, difficulty: 1},
},
{
desc: "Assign this gang member to attempt phishing scams and attacks<br><br>Earns money - Slightly increases respect - Slightly increases wanted level",
name: "Phishing",
params: {baseRespect: 0.00008, baseWanted: 0.001, baseMoney: 2.5, hackWeight: 85, chaWeight: 15, difficulty: 3},
},
{
desc: "Assign this gang member to attempt identity theft<br><br>Earns money - Increases respect - Increases wanted level",
name: "Identity Theft",
params: {baseRespect: 0.0001, baseWanted: 0.01, baseMoney: 6, hackWeight: 80, chaWeight: 20, difficulty: 4},
},
{
desc: "Assign this gang member to carry out DDoS attacks<br><br>Increases respect - Increases wanted level",
name: "DDoS Attacks",
params: {baseRespect: 0.0004, baseWanted: 0.05, hackWeight: 100, difficulty: 7},
},
{
desc: "Assign this gang member to create and distribute malicious viruses<br><br>Increases respect - Increases wanted level",
name: "Plant Virus",
params: {baseRespect: 0.0006, baseWanted: 0.05, hackWeight: 100, difficulty: 10},
},
{
desc: "Assign this gang member to commit financial fraud and digital counterfeiting<br><br>Earns money - Slightly increases respect - Slightly increases wanted level",
name: "Fraud & Counterfeiting",
params: {baseRespect: 0.0005, baseWanted: 0.1, baseMoney: 15, hackWeight: 80, chaWeight: 20, difficulty: 17},
},
{
desc: "Assign this gang member to launder money<br><br>Earns money - Increases respect - Increases wanted level",
name: "Money Laundering",
params: {baseRespect: 0.0006, baseWanted:0.2, baseMoney: 40, hackWeight: 75, chaWeight: 25, difficulty: 20},
},
{
desc: "Assign this gang member to commit acts of cyberterrorism<br><br>Greatly increases respect - Greatly increases wanted level",
name: "Cyberterrorism",
params: {baseRespect: 0.001, baseWanted: 0.5, hackWeight: 80, chaWeight: 20, difficulty: 33},
},
{
desc: "Assign this gang member to be an ethical hacker for corporations<br><br>Earns money - Lowers wanted level",
name: "Ethical Hacking",
params: {baseWanted: -0.001, baseMoney: 1, hackWeight: 90, chaWeight: 10, difficulty: 1},
},
{
desc: "Assign this gang member to mug random people on the streets<br><br>Earns money - Slightly increases respect - Very slightly increases wanted level",
name: "Mug People",
params: {baseRespect: 0.00005, baseWanted: 0.00001, baseMoney: 1, strWeight: 25, defWeight: 25, dexWeight: 25, agiWeight: 10, chaWeight: 15, difficulty: 1},
},
{
desc: "Assign this gang member to sell drugs.<br><br>Earns money - Slightly increases respect - Slightly increases wanted level",
name: "Deal Drugs",
params: {baseRespect: 0.00008, baseWanted: 0.001, baseMoney: 4, agiWeight: 20, dexWeight: 20, chaWeight: 60, difficulty: 3},
},
{
desc: "Assign this gang member to run cons<br><br>Earns money - Increases respect - Increases wanted level",
name: "Run a Con",
params: {baseRespect: 0.00015, baseWanted: 0.01, baseMoney: 10, strWeight: 5, defWeight: 5, agiWeight: 25, dexWeight: 25, chaWeight: 40, difficulty: 10},
},
{
desc: "Assign this gang member to commit armed robbery on stores, banks and armored cars<br><br>Earns money - Increases respect - Increases wanted level",
name: "Armed Robbery",
params: {baseRespect: 0.00015, baseWanted: 0.05, baseMoney: 25, hackWeight: 20, strWeight: 15, defWeight: 15, agiWeight: 10, dexWeight: 20, chaWeight: 20, difficulty: 17},
},
{
desc: "Assign this gang member to traffick illegal arms<br><br>Earns money - Increases respect - Increases wanted level",
name: "Traffick Illegal Arms",
params: {baseRespect: 0.0003, baseWanted: 0.1, baseMoney: 40, hackWeight: 15, strWeight: 20, defWeight: 20, dexWeight: 20, chaWeight: 75, difficulty: 25},
},
{
desc: "Assign this gang member to threaten and black mail high-profile targets<br><br>Earns money - Slightly increases respect - Slightly increases wanted level",
name: "Threaten & Blackmail",
params: {baseRespect: 0.0002, baseWanted: 0.05, baseMoney: 15, hackWeight: 25, strWeight: 25, dexWeight: 25, chaWeight: 25, difficulty: 28},
},
{
desc: "Assign this gang member to commit acts of terrorism<br><br>Greatly increases respect - Greatly increases wanted level",
name: "Terrorism",
params: {baseRespect: 0.001, baseWanted: 1, hackWeight: 20, strWeight: 20, defWeight: 20,dexWeight: 20, chaWeight: 20, difficulty: 33},
},
{
desc: "Assign this gang member to be a vigilante and protect the city from criminals<br><br>Decreases wanted level",
name: "Vigilante Justice",
params: {baseWanted: -0.001, hackWeight: 20, strWeight: 20, defWeight: 20, dexWeight: 20, agiWeight:20, difficulty: 1},
},
{
desc: "Assign this gang member to increase their combat stats (str, def, dex, agi)",
name: "Train Combat",
params: {strWeight: 25, defWeight: 25, dexWeight: 25, agiWeight: 25, difficulty: 5},
},
{
desc: "Assign this gang member to train their hacking skills",
name: "Train Hacking",
params: {hackWeight: 100, difficulty: 8},
},
{
desc: "Assign this gang member to engage in territorial warfare with other gangs. Members assigned to this task will help increase your gang's territory and will defend your territory from being taken.",
name: "Territory Warfare",
params: {hackWeight: 15, strWeight: 20, defWeight: 20, dexWeight: 20, agiWeight: 20, chaWeight: 5, difficulty: 3},
},
];

@ -0,0 +1,183 @@
export interface IGangMemberUpgradeMetadata {
cost: number;
mults: any;
name: string;
upgType: string;
}
export const gangMemberUpgradesMetadata: IGangMemberUpgradeMetadata[] = [
{
cost: 1e6,
mults: {str: 1.04, def: 1.04},
name: "Baseball Bat",
upgType: "w",
},
{
cost: 12e6,
mults: {str: 1.08, def: 1.08, dex: 1.08},
name: "Katana",
upgType: "w",
},
{
cost: 25e6,
mults: {str: 1.10, def: 1.10, dex: 1.10, agi: 1.10},
name: "Glock 18C",
upgType: "w",
},
{
cost: 50e6,
mults: {str: 1.12, def: 1.12, agi: 1.10},
name: "P90C",
upgType: "w",
},
{
cost: 60e6,
mults: {str: 1.20, def: 1.20},
name: "Steyr AUG",
upgType: "w",
},
{
cost: 100e6,
mults: {str: 1.25, def: 1.25},
name: "AK-47",
upgType: "w",
},
{
cost: 150e6,
mults: {str: 1.30, def: 1.30},
name: "M15A10 Assault Rifle",
upgType: "w",
},
{
cost: 225e6,
mults: {str: 1.30, dex: 1.30, agi: 1.30},
name: "AWM Sniper Rifle",
upgType: "w",
},
{
cost: 2e6,
mults: {def: 1.04},
name: "Bulletproof Vest",
upgType: "a",
},
{
cost: 5e6,
mults: {def: 1.08},
name: "Full Body Armor",
upgType: "a",
},
{
cost: 25e6,
mults: {def: 1.15, agi: 1.15},
name: "Liquid Body Armor",
upgType: "a",
},
{
cost: 40e6,
mults: {def: 1.20},
name: "Graphene Plating Armor",
upgType: "a",
},
{
cost: 3e6,
mults: {agi: 1.04, cha: 1.04},
name: "Ford Flex V20",
upgType: "v",
},
{
cost: 9e6,
mults: {agi: 1.08, cha: 1.08},
name: "ATX1070 Superbike",
upgType: "v",
},
{
cost: 18e6,
mults: {agi: 1.12, cha: 1.12},
name: "Mercedes-Benz S9001",
upgType: "v",
},
{
cost: 30e6,
mults: {agi: 1.16, cha: 1.16},
name: "White Ferrari",
upgType: "v",
},
{
cost: 5e6,
mults: {hack: 1.05},
name: "NUKE Rootkit",
upgType: "r",
},
{
cost: 15e6,
mults: {hack: 1.10},
name: "Soulstealer Rootkit",
upgType: "r",
},
{
cost: 50e6,
mults: {hack: 1.15},
name: "Demon Rootkit",
upgType: "r",
},
{
cost: 10e9,
mults: {str: 1.30, dex: 1.30},
name: "Bionic Arms",
upgType: "g",
},
{
cost: 10e9,
mults: {agi: 1.60},
name: "Bionic Legs",
upgType: "g",
},
{
cost: 15e9,
mults: {str: 1.15, def: 1.15, dex: 1.15, agi: 1.15},
name: "Bionic Spine",
upgType: "g",
},
{
cost: 20e9,
mults: {str: 1.40, def: 1.40},
name: "BrachiBlades",
upgType: "g",
},
{
cost: 12e9,
mults: {str: 1.20, def: 1.20},
name: "Nanofiber Weave",
upgType: "g",
},
{
cost: 25e9,
mults: {str: 1.50, agi: 1.50},
name: "Synthetic Heart",
upgType: "g",
},
{
cost: 15e9,
mults: {str: 1.30, def:1.30},
name: "Synfibril Muscle",
upgType: "g",
},
{
cost: 5e9,
mults: {hack: 1.05},
name: "BitWire",
upgType: "g",
},
{
cost: 10e9,
mults: {hack: 1.15},
name: "Neuralstimulator",
upgType: "g",
},
{
cost: 50e9,
mults: {str: 1.70, def: 1.70},
name: "Graphene Bone Lacings",
upgType: "g",
},
];