/* Gang.js */ //Switch between territory and management screen with 1 and 2 $(document).keydown(function(event) { if (Engine.currentPage == Engine.Page.Gang && !yesNoBoxOpen) { if (event.keyCode === 49) { if(document.getElementById("gang-territory-subpage").style.display === "block") { document.getElementById("gang-management-subpage-button").click(); } } else if (event.keyCode === 50) { if (document.getElementById("gang-management-subpage").style.display === "block") { document.getElementById("gang-territory-subpage-button").click(); } } } }); //Delete upgrade box when clicking outside $(document).mousedown(function(event) { if (gangMemberUpgradeBoxOpened) { if ( $(event.target).closest("#gang-purchase-upgrade-container").get(0) == null ) { //Delete the box var container = document.getElementById("gang-purchase-upgrade-container"); while(container.firstChild) { container.removeChild(container.firstChild); } container.parentNode.removeChild(container); gangMemberUpgradeBoxOpened = false; } } }); GangNames = ["Slum Snakes", "Tetrads", "The Syndicate", "The Dark Army", "Speakers for the Dead", "NiteSec", "The Black Hand"]; GangLocations = [Locations.Aevum, Locations.Chongqing, Locations.Sector12, Locations.NewTokyo, Locations.Ishima, Locations.Volhaven]; AllGangs = { "Slum Snakes" : { power: 1, territory: 1/7, }, "Tetrads" : { power: 1, territory: 1/7, }, "The Syndicate" : { power: 1, territory: 1/7, }, "The Dark Army" : { power: 1, territory: 1/7, }, "Speakers for the Dead" : { power: 1, territory: 1/7, }, "NiteSec" : { power: 1, territory: 1/7, }, "The Black Hand" : { power: 1, territory: 1/7, }, } //Power is an estimate of a gang's ability to gain/defend territory gangStoredPowerCycles = 0; function processAllGangPowerGains(numCycles=1) { if (!Player.inGang()) {return;} gangStoredPowerCycles += numCycles; if (gangStoredPowerCycles < 150) {return;} var playerGangName = Player.gang.facName; for (var name in AllGangs) { if (AllGangs.hasOwnProperty(name)) { if (name == playerGangName) { AllGangs[name].power += Player.gang.calculatePower(); } else { var gain = Math.random() * 0.01; //TODO Adjust as necessary AllGangs[name].power += (gain); } } } gangStoredPowerCycles -= 150; } gangStoredTerritoryCycles = 0; function processAllGangTerritory(numCycles=1) { if (!Player.inGang()) {return;} gangStoredTerritoryCycles += numCycles; if (gangStoredTerritoryCycles < CONSTANTS.GangTerritoryUpdateTimer) {return;} for (var i = 0; i < GangNames.length; ++i) { var other = getRandomInt(0, GangNames.length-1); while(other == i) { other = getRandomInt(0, GangNames.length-1); } var thisPwr = AllGangs[GangNames[i]].power; var otherPwr = AllGangs[GangNames[other]].power; var thisChance = thisPwr / (thisPwr + otherPwr); if (Math.random() < thisChance) { if (AllGangs[GangNames[other]].territory <= 0) { return; } AllGangs[GangNames[i]].territory += 0.0001; AllGangs[GangNames[other]].territory -= 0.0001; } else { if (AllGangs[GangNames[i]].territory <= 0) { return; } AllGangs[GangNames[i]].territory -= 0.0001; AllGangs[GangNames[other]].territory += 0.0001; } } gangStoredTerritoryCycles -= CONSTANTS.GangTerritoryUpdateTimer; } //Returns true if Player is in a gang and false otherwise PlayerObject.prototype.inGang = function() { if (this.gang == null || this.gang == undefined) {return false;} return (this.gang instanceof Gang); } /* faction - Name of corresponding faction hacking - Boolean indicating whether its a hacking gang or not */ function Gang(facName, hacking=false) { this.facName = facName; this.members = []; //Array of GangMembers this.wanted = 1; this.respect = 1; this.power = 0; this.isHackingGang = hacking; this.respectGainRate = 0; this.wantedGainRate = 0; this.moneyGainRate = 0; //When processing gains, this stores the number of cycles until some //limit is reached, and then calculates and applies the gains only at that limit this.storedCycles = 0; } Gang.prototype.process = function(numCycles=1) { this.processGains(numCycles); this.processExperienceGains(numCycles); processAllGangPowerGains(numCycles); processAllGangTerritory(numCycles); } Gang.prototype.processGains = function(numCycles=1) { this.storedCycles += numCycles; if (isNaN(this.storedCycles)) { console.log("ERROR: Gang's storedCylces is NaN"); this.storedCycles = 0; } if (this.storedCycles < 25) {return;} //Only process every 5 seconds at least //Get gains per cycle var moneyGains = 0, respectGains = 0, wantedLevelGains = 0; for (var i = 0; i < this.members.length; ++i) { respectGains += (this.members[i].calculateRespectGain()); wantedLevelGains += (this.members[i].calculateWantedLevelGain()); moneyGains += (this.members[i].calculateMoneyGain()); } this.respectGainRate = respectGains; this.wantedGainRate = wantedLevelGains; this.moneyGainRate = moneyGains; if (!isNaN(respectGains)) { var gain = respectGains * this.storedCycles; this.respect += (gain); //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"); } else { var favorMult = 1 + (fac.favor / 100); fac.playerReputation += ((Player.faction_rep_mult * gain * favorMult) / CONSTANTS.GangRespectToReputationRatio); } } else { console.log("ERROR: respectGains is NaN"); } if (!isNaN(wantedLevelGains)) { this.wanted += (wantedLevelGains * this.storedCycles); if (this.wanted < 1) {this.wanted = 1;} } else { console.log("ERROR: wantedLevelGains is NaN"); } if (!isNaN(moneyGains)) { Player.gainMoney(moneyGains * this.storedCycles); } else { console.log("ERROR: respectGains is NaN"); } this.storedCycles = 0; } Gang.prototype.processExperienceGains = function(numCycles=1) { for (var i = 0; i < this.members.length; ++i) { this.members[i].gainExperience(numCycles); this.members[i].updateSkillLevels(); } } //Calculates power GAIN, which is added onto the Gang's existing power Gang.prototype.calculatePower = function() { var memberTotal = 0; for (var i = 0; i < this.members.length; ++i) { if (this.members[i].task instanceof GangMemberTask && this.members[i].task.name == "Territory Warfare") { memberTotal += this.members[i].calculatePower(); } } return (0.0005 * memberTotal); } Gang.prototype.toJSON = function() { return Generic_toJSON("Gang", this); } Gang.fromJSON = function(value) { return Generic_fromJSON(Gang, value.data); } Reviver.constructors.Gang = Gang; /*** Gang Member object ***/ function GangMember(name) { this.name = name; this.task = null; //GangMemberTask object this.city = Player.city; //Name of upgrade only this.weaponUpgrade = null; this.armorUpgrade = null; this.vehicleUpgrade = null; this.hackingUpgrade = null; this.hack = 1; this.str = 1; this.def = 1; this.dex = 1; this.agi = 1; this.cha = 1; this.hack_exp = 0; this.str_exp = 0; this.def_exp = 0; this.dex_exp = 0; this.agi_exp = 0; this.cha_exp = 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; } //Same formula for Player GangMember.prototype.calculateSkill = function(exp) { return Math.max(Math.floor(32 * Math.log(exp + 534.5) - 200), 1); } GangMember.prototype.updateSkillLevels = function() { this.hack = Math.floor(this.calculateSkill(this.hack_exp) * this.hack_mult); this.str = Math.floor(this.calculateSkill(this.str_exp) * this.str_mult); this.def = Math.floor(this.calculateSkill(this.def_exp) * this.def_mult); this.dex = Math.floor(this.calculateSkill(this.dex_exp) * this.dex_mult); this.agi = Math.floor(this.calculateSkill(this.agi_exp) * this.agi_mult); this.cha = Math.floor(this.calculateSkill(this.cha_exp) * this.cha_mult); } GangMember.prototype.calculatePower = function() { return (this.hack + this.str + this.def + this.dex + this.agi + this.cha) / 100; } GangMember.prototype.assignToTask = function(taskName) { if (GangMemberTasks.hasOwnProperty(taskName)) { this.task = GangMemberTasks[taskName]; } else { console.log("ERROR: Invalid task " + taskName); this.task = null; } } //Gains are per cycle GangMember.prototype.calculateRespectGain = function() { var task = this.task; if (task === null || !(task instanceof GangMemberTask) || task.baseRespect === 0) {return 0;} var statWeight = (task.hackWeight/100) * this.hack + (task.strWeight/100) * this.str + (task.defWeight/100) * this.def + (task.dexWeight/100) * this.dex + (task.agiWeight/100) * this.agi + (task.chaWeight/100) * this.cha; statWeight -= (3.5 * task.difficulty); 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); return 12 * task.baseRespect * statWeight * territoryMult * respectMult; } GangMember.prototype.calculateWantedLevelGain = function() { var task = this.task; if (task === null || !(task instanceof GangMemberTask) || task.baseWanted === 0) {return 0;} var statWeight = (task.hackWeight/100) * this.hack + (task.strWeight/100) * this.str + (task.defWeight/100) * this.def + (task.dexWeight/100) * this.dex + (task.agiWeight/100) * this.agi + (task.chaWeight/100) * this.cha; statWeight -= (3.5 * task.difficulty); if (statWeight <= 0) {return 0;} var territoryMult = AllGangs[Player.gang.facName].territory; if (territoryMult <= 0) {return 0;} if (task.baseWanted < 0) { return task.baseWanted * statWeight * territoryMult; } else { return 6 * task.baseWanted / (3 * statWeight * territoryMult); } } GangMember.prototype.calculateMoneyGain = function() { var task = this.task; if (task === null || !(task instanceof GangMemberTask) || task.baseMoney === 0) {return 0;} var statWeight = (task.hackWeight/100) * this.hack + (task.strWeight/100) * this.str + (task.defWeight/100) * this.def + (task.dexWeight/100) * this.dex + (task.agiWeight/100) * this.agi + (task.chaWeight/100) * this.cha; statWeight -= (3.5 * task.difficulty); 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); return 5 * task.baseMoney * statWeight * territoryMult * respectMult; } GangMember.prototype.gainExperience = function(numCycles=1) { var task = this.task; if (task === null || !(task instanceof GangMemberTask)) {return;} this.hack_exp += (task.hackWeight / 1500) * task.difficulty * numCycles; this.str_exp += (task.strWeight / 1500) * task.difficulty * numCycles; this.def_exp += (task.defWeight / 1500) * task.difficulty * numCycles; this.dex_exp += (task.dexWeight / 1500) * task.difficulty * numCycles; this.agi_exp += (task.agiWeight / 1500) * task.difficulty * numCycles; this.cha_exp += (task.chaWeight / 1500) * task.difficulty * numCycles; } GangMember.prototype.toJSON = function() { return Generic_toJSON("GangMember", this); } GangMember.fromJSON = function(value) { return Generic_fromJSON(GangMember, value.data); } Reviver.constructors.GangMember = GangMember; //Defines tasks that Gang Members can work on function GangMemberTask(name="", desc="", params={baseRespect: 0, baseWanted: 0, baseMoney: 0, hackWeight: 0, strWeight: 0, defWeight: 0, dexWeight: 0, agiWeight: 0, chaWeight: 0, difficulty: 0}) { this.name = name; this.desc = desc; this.baseRespect = params.baseRespect ? params.baseRespect : 0; this.baseWanted = params.baseWanted ? params.baseWanted : 0; this.baseMoney = params.baseMoney ? params.baseMoney : 0; //Weights must add up to 100 this.hackWeight = params.hackWeight ? params.hackWeight : 0; this.strWeight = params.strWeight ? params.strWeight : 0; this.defWeight = params.defWeight ? params.defWeight : 0; this.dexWeight = params.dexWeight ? params.dexWeight : 0; this.agiWeight = params.agiWeight ? params.agiWeight : 0; this.chaWeight = params.chaWeight ? params.chaWeight : 0; //1 - 100 this.difficulty = params.difficulty ? params.difficulty : 1; } GangMemberTask.prototype.toJSON = function() { return Generic_toJSON("GangMemberTask", this); } GangMemberTask.fromJSON = function(value) { return Generic_fromJSON(GangMemberTask, value.data); } Reviver.constructors.GangMemberTask = GangMemberTask; //TODO Human trafficking and an equivalent hacking crime GangMemberTasks = { "Ransomware" : new GangMemberTask( "Ransomware", "Assign this gang member to create and distribute ransomware

" + "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

" + "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

" + "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

" + "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

" + "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

" + "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

" + "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

" + "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

" + "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

" + "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.

" + "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

" + "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

" + "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

" + "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

" + "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

" + "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

" + "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}), } function GangMemberUpgrade(name="", desc="", cost=0, type="-") { this.name = name; this.desc = desc; this.cost = cost; this.type = type; //w, a, v, r } //Passes in a GangMember object GangMemberUpgrade.prototype.apply = function(member, unapply=false) { switch(this.name) { case "Baseball Bat": unapply ? member.str_mult /= 1.1 : member.str_mult *= 1.1; unapply ? member.def_mult /= 1.1 : member.def_mult *= 1.1; break; case "Katana": unapply ? member.str_mult /= 1.15 : member.str_mult *= 1.15; unapply ? member.def_mult /= 1.15 : member.def_mult *= 1.15; unapply ? member.dex_mult /= 1.15 : member.dex_mult *= 1.15; break; case "Glock 18C": unapply ? member.str_mult /= 1.2 : member.str_mult *= 1.2; unapply ? member.def_mult /= 1.2 : member.def_mult *= 1.2; unapply ? member.dex_mult /= 1.2 : member.dex_mult *= 1.2; unapply ? member.agi_mult /= 1.2 : member.agi_mult *= 1.2; break; case "P90": unapply ? member.str_mult /= 1.4 : member.str_mult *= 1.4; unapply ? member.def_mult /= 1.4 : member.def_mult *= 1.4; unapply ? member.agi_mult /= 1.2 : member.agi_mult *= 1.2; break; case "Steyr AUG": unapply ? member.str_mult /= 1.6 : member.str_mult *= 1.6; unapply ? member.def_mult /= 1.6 : member.def_mult *= 1.6; break; case "AK-47": unapply ? member.str_mult /= 1.8 : member.str_mult *= 1.8; unapply ? member.def_mult /= 1.8 : member.def_mult *= 1.8; break; case "M15A10 Assault Rifle": unapply ? member.str_mult /= 1.9 : member.str_mult *= 1.9; unapply ? member.def_mult /= 1.9 : member.def_mult *= 1.9; break; case "AWM Sniper Rifle": unapply ? member.str_mult /= 1.8 : member.str_mult *= 1.8; unapply ? member.dex_mult /= 1.8 : member.dex_mult *= 1.8; unapply ? member.agi_mult /= 1.8 : member.agi_mult *= 1.8; break; case "Bulletproof Vest": unapply ? member.def_mult /= 1.15 : member.def_mult *= 1.15; break; case "Full Body Armor": unapply ? member.def_mult /= 1.3 : member.def_mult *= 1.3; break; case "Liquid Body Armor": unapply ? member.def_mult /= 1.5 : member.def_mult *= 1.5; unapply ? member.agi_mult /= 1.5 : member.agi_mult *= 1.5; break; case "Graphene Plating Armor": unapply ? member.def_mult /= 2 : member.def_mult *= 2; break; case "Ford Flex V20": unapply ? member.agi_mult /= 1.2 : member.agi_mult *= 1.2; unapply ? member.cha_mult /= 1.2 : member.cha_mult *= 1.2; break; case "ATX1070 Superbike": unapply ? member.agi_mult /= 1.4 : member.agi_mult *= 1.4; unapply ? member.cha_mult /= 1.4 : member.cha_mult *= 1.4; break; case "Mercedes-Benz S9001": unapply ? member.agi_mult /= 1.6 : member.agi_mult *= 1.6; unapply ? member.cha_mult /= 1.6 : member.cha_mult *= 1.6; break; case "White Ferrari": unapply ? member.agi_mult /= 1.8 : member.agi_mult *= 1.8; unapply ? member.cha_mult /= 1.8 : member.cha_mult *= 1.8; break; case "NUKE Rootkit": unapply ? member.hack_mult /= 1.2 : member.hack_mult *= 1.2; break; case "Soulstealer Rootkit": unapply ? member.hack_mult /= 1.3 : member.hack_mult *= 1.3; break; case "Demon Rootkit": unapply ? member.hack_mult /= 1.5 : member.hack_mult *= 1.5; break; default: console.log("ERROR: Could not find this upgrade: " + this.name); break; } } //Purchases for given member GangMemberUpgrade.prototype.purchase = function(memberObj) { if (Player.money.lt(this.cost)) { dialogBoxCreate("You do not have enough money to purchase this upgrade"); return; } Player.loseMoney(this.cost); switch (this.type) { case "w": if (memberObj.weaponUpgrade instanceof GangMemberUpgrade) { memberObj.weaponUpgrade.apply(memberObj, true); //Unapply old upgrade } this.apply(memberObj, false); memberObj.weaponUpgrade = this; break; case "a": if (memberObj.armorUpgrade instanceof GangMemberUpgrade) { memberObj.armorUpgrade.apply(memberObj, true); //Unapply old upgrade } this.apply(memberObj, false); memberObj.armorUpgrade = this; break; case "v": if (memberObj.vehicleUpgrade instanceof GangMemberUpgrade) { memberObj.vehicleUpgrade.apply(memberObj, true); //Unapply old upgrade } this.apply(memberObj, false); memberObj.vehicleUpgrade = this; break; case "r": if (memberObj.hackingUpgrade instanceof GangMemberUpgrade) { memberObj.hackingUpgrade.apply(memberObj, true); //Unapply old upgrade } this.apply(memberObj, false); memberObj.hackingUpgrade = this; break; default: console.log("ERROR: GangMemberUpgrade has invalid type: " + this.type); break; } createGangMemberUpgradeBox(memberObj); } GangMemberUpgrade.prototype.toJSON = function() { return Generic_toJSON("GangMemberUpgrade", this); } GangMemberUpgrade.fromJSON = function(value) { return Generic_fromJSON(GangMemberUpgrade, value.data); } Reviver.constructors.GangMemberUpgrade = GangMemberUpgrade; GangMemberUpgrades = { "Baseball Bat" : new GangMemberUpgrade("Baseball Bat", "Increases strength and defense by 10%", 1000000, "w"), "Katana" : new GangMemberUpgrade("Katana", "Increases strength, defense, and dexterity by 15%", 12000000, "w"), "Glock 18C" : new GangMemberUpgrade("Glock 18C", "Increases strength, defense, dexterity, and agility by 20%", 25000000, "w"), "P90" : new GangMemberUpgrade("P90C", "Increases strength and defense by 40%. Increases agility by 20%", 50000000, "w"), "Steyr AUG" : new GangMemberUpgrade("Steyr AUG", "Increases strength and defense by 60%", 60000000, "w"), "AK-47" : new GangMemberUpgrade("AK-47", "Increases strength and defense by 80%", 100000000, "w"), "M15A10 Assault Rifle" : new GangMemberUpgrade("M15A10 Assault Rifle", "Increases strength and defense by 90%", 150000000, "w"), "AWM Sniper Rifle" : new GangMemberUpgrade("AWM Sniper Rifle", "Increases strength, dexterity, and agility by 80%", 225000000, "w"), "Bulletproof Vest" : new GangMemberUpgrade("Bulletproof Vest", "Increases defense by 15%", 2000000, "a"), "Full Body Armor" : new GangMemberUpgrade("Full Body Armor", "Increases defense by 30%", 5000000, "a"), "Liquid Body Armor" : new GangMemberUpgrade("Liquid Body Armor", "Increases defense and agility by 50%", 25000000, "a"), "Graphene Plating Armor" : new GangMemberUpgrade("Graphene Plating Armor", "Increases defense by 100%", 40000000, "a"), "Ford Flex V20" : new GangMemberUpgrade("Ford Flex V20", "Increases agility and charisma by 20%", 3000000, "v"), "ATX1070 Superbike" : new GangMemberUpgrade("ATX1070 Superbike", "Increases agility and charisma by 40%", 9000000, "v"), "Mercedes-Benz S9001" : new GangMemberUpgrade("Mercedes-Benz S9001", "Increases agility and charisma by 60%", 18000000, "v"), "White Ferrari" : new GangMemberUpgrade("White Ferrari", "Increases agility and charisma by 80%", 30000000, "v"), "NUKE Rootkit" : new GangMemberUpgrade("NUKE Rootkit", "Increases hacking by 20%", 5000000, "r"), "Soulstealer Rootkit" : new GangMemberUpgrade("Soulstealer Rootkit", "Increases hacking by 30%", 15000000, "r"), "Demon Rootkit" : new GangMemberUpgrade("Demon Rootkit", "Increases hacking by 50%", 50000000, "r"), } //Create a pop-up box that lets player purchase upgrades var gangMemberUpgradeBoxOpened = false; function createGangMemberUpgradeBox(memberObj) { console.log("Creating gang member upgrade box for " + memberObj.name); var container = document.getElementById("gang-purchase-upgrade-container"); if (container) { while (container.firstChild) { container.removeChild(container.firstChild); } } else { var container = document.createElement("div"); container.setAttribute("id", "gang-purchase-upgrade-container"); document.getElementById("entire-game-container").appendChild(container); container.setAttribute("class", "dialog-box-container"); container.style.display = "block"; } var content = document.createElement("div"); content.setAttribute("class", "dialog-box-content"); content.setAttribute("id", "gang-purchase-upgrade-content"); container.appendChild(content); var intro = document.createElement("p"); content.appendChild(intro); intro.innerHTML = memberObj.name + "

" + "A gang member can be upgraded with a weapon, armor, a vehicle, and a hacking rootkit. " + "For each of these pieces of equipment, a gang member can only have one at a time (i.e " + "a member cannot have two weapons or two vehicles). Purchasing an upgrade will automatically " + "replace the member's existing upgrade, if he/she is equipped with one. The existing upgrade " + "will be lost and will have to be re-purchased if you want to switch back.

"; //Weapons var weaponTxt = document.createElement("p"); weaponTxt.style.display = "block"; content.appendChild(weaponTxt); if (memberObj.weaponUpgrade instanceof GangMemberUpgrade) { weaponTxt.innerHTML = "Weapons (Current Equip: " + memberObj.weaponUpgrade.name + ")"; } else { weaponTxt.innerHTML = "Weapons (Current Equip: NONE)"; } var weaponNames = ["Baseball Bat", "Katana", "Glock 18C", "P90", "Steyr AUG", "AK-47", "M15A10 Assault Rifle", "AWM Sniper Rifle"]; createGangMemberUpgradeButtons(memberObj, weaponNames, memberObj.weaponUpgrade, content); content.appendChild(document.createElement("br")); var armorTxt = document.createElement("p"); armorTxt.style.display = "block"; content.appendChild(armorTxt); if (memberObj.armorUpgrade instanceof GangMemberUpgrade) { armorTxt.innerHTML = "Armor (Current Equip: " + memberObj.armorUpgrade.name + ")"; } else { armorTxt.innerHTML = "Armor (Current Equip: NONE)"; } var armorNames = ["Bulletproof Vest", "Full Body Armor", "Liquid Body Armor", "Graphene Plating Armor"]; createGangMemberUpgradeButtons(memberObj, armorNames, memberObj.armorUpgrade, content); var vehicleTxt = document.createElement("p"); vehicleTxt.style.display = "block"; content.appendChild(vehicleTxt); if (memberObj.vehicleUpgrade instanceof GangMemberUpgrade) { vehicleTxt.innerHTML = "Vehicles (Current Equip: " + memberObj.vehicleUpgrade.name + ")"; } else { vehicleTxt.innerHTML = "Vehicles (Current Equip: NONE)"; } var vehicleNames = ["Ford Flex V20", "ATX1070 Superbike", "Mercedes-Benz S9001", "White Ferrari"]; createGangMemberUpgradeButtons(memberObj, vehicleNames, memberObj.vehicleUpgrade, content); var rootkitTxt = document.createElement("p"); rootkitTxt.style.display = "block"; content.appendChild(rootkitTxt); if (memberObj.hackingUpgrade instanceof GangMemberUpgrade) { rootkitTxt.innerHTML = "Rootkits (Current Equip: " + memberObj.hackingUpgrade.name + ")"; } else { rootkitTxt.innerHTML = "Rootkits (Current Equip: NONE)"; } var rootkitNames = ["NUKE Rootkit", "Soulstealer Rootkit", "Demon Rootkit"]; createGangMemberUpgradeButtons(memberObj, rootkitNames, memberObj.hackingUpgrade, content); gangMemberUpgradeBoxOpened = true; } function createGangMemberUpgradeButtons(memberObj, upgNames, memberUpgrade, content) { for (var i = 0; i < upgNames.length; ++i) { (function() { var upgrade = GangMemberUpgrades[upgNames[i]]; if (upgrade == null) { console.log("ERROR: Could not find GangMemberUpgrade object for" + upgNames[i]); return; //Return inside closure } //Skip the currently owned upgrade if (memberUpgrade instanceof GangMemberUpgrade && memberUpgrade.name == upgrade.name) {return;} //Create button var btn = document.createElement("a"); btn.innerHTML = upgrade.name + " - $" + numeral(upgrade.cost).format('(0.00a)'); if (Player.money.gte(upgrade.cost)) { btn.setAttribute("class", "popup-box-button tooltip") } else { btn.setAttribute("class", "popup-box-button-inactive tooltip"); } btn.style.cssFloat = "none"; btn.style.display = "block"; btn.style.margin = "8px"; btn.style.width = "40%"; //Tooltip for upgrade var tooltip = document.createElement("span"); tooltip.setAttribute("class", "tooltiptext"); tooltip.innerHTML = upgrade.desc; btn.appendChild(tooltip); content.appendChild(btn); btn.addEventListener("click", function() { upgrade.purchase(memberObj); }); }()); // Immediate invocation } } var gangContentCreated = false; function displayGangContent() { if (!gangContentCreated) { gangContentCreated = true; //Create gang container var container = document.createElement("div"); document.getElementById("entire-game-container").appendChild(container); container.setAttribute("id", "gang-container"); container.setAttribute("class", "generic-menupage-container"); //Get variables var facName = Player.gang.facName; var members = Player.gang.members; var wanted = Player.gang.wanted; var respect = Player.gang.respect; //Buttons to switch between panels var managementButton = document.createElement("a"); managementButton.setAttribute("id", "gang-management-subpage-button"); managementButton.innerHTML = "Gang Management (1)"; managementButton.setAttribute("class", "a-link-button-inactive"); managementButton.style.display = "inline-block"; var territoryButton = document.createElement("a"); territoryButton.setAttribute("id", "gang-territory-subpage-button"); territoryButton.innerHTML = "Gang Territory (2)"; territoryButton.setAttribute("class", "a-link-button"); territoryButton.style.display = "inline-block"; managementButton.addEventListener("click", function() { document.getElementById("gang-management-subpage").style.display = "block"; document.getElementById("gang-territory-subpage").style.display = "none"; managementButton.classList.toggle("a-link-button-inactive"); managementButton.classList.toggle("a-link-button"); territoryButton.classList.toggle("a-link-button-inactive"); territoryButton.classList.toggle("a-link-button"); updateGangContent(); return false; }); territoryButton.addEventListener("click", function() { document.getElementById("gang-management-subpage").style.display = "none"; document.getElementById("gang-territory-subpage").style.display = "block"; managementButton.classList.toggle("a-link-button-inactive"); managementButton.classList.toggle("a-link-button"); territoryButton.classList.toggle("a-link-button-inactive"); territoryButton.classList.toggle("a-link-button"); updateGangContent(); return false; }); container.appendChild(managementButton); container.appendChild(territoryButton); //Subpage for managing gang members var managementSubpage = document.createElement("div"); container.appendChild(managementSubpage); managementSubpage.style.display = "block"; managementSubpage.setAttribute("id", "gang-management-subpage"); var infoText = document.createElement("p"); managementSubpage.appendChild(infoText); infoText.setAttribute("id", "gang-info"); infoText.style.width = "70%"; var recruitGangMemberBtn = document.createElement("a"); managementSubpage.appendChild(recruitGangMemberBtn); recruitGangMemberBtn.setAttribute("id", "gang-management-recruit-member-btn"); recruitGangMemberBtn.setAttribute("class", "a-link-button-inactive"); recruitGangMemberBtn.innerHTML = "Recruit Gang Member"; recruitGangMemberBtn.style.display = "inline-block"; recruitGangMemberBtn.style.margin = "10px"; recruitGangMemberBtn.addEventListener("click", () => { var yesBtn = yesNoTxtInpBoxGetYesButton(), noBtn = yesNoTxtInpBoxGetNoButton(); yesBtn.innerHTML = "Recruit Gang Member"; noBtn.innerHTML = "Cancel"; yesBtn.addEventListener("click", ()=>{ var name = yesNoTxtInpBoxGetInput(); if (name == "") { dialogBoxCreate("You must enter a name for your Gang member!"); } else { for (var i = 0; i < Player.gang.members.length; ++i) { if (name == Player.gang.members[i].name) { dialogBoxCreate("You already have a gang member with this name!"); return false; } } var member = new GangMember(name); Player.gang.members.push(member); createGangMemberDisplayElement(member); updateGangContent(); } yesNoTxtInpBoxClose(); }); noBtn.addEventListener("click", ()=>{ yesNoTxtInpBoxClose(); }); yesNoTxtInpBoxCreate("Please enter a name for your new Gang member:"); return false; }); //Text for how much reputation is required for recruiting next memberList var recruitRequirementText = document.createElement("p"); managementSubpage.appendChild(recruitRequirementText); recruitRequirementText.setAttribute("id", "gang-recruit-requirement-text"); recruitRequirementText.style.color = "red"; var memberList = document.createElement("ul"); managementSubpage.appendChild(memberList); memberList.setAttribute("id", "gang-member-list"); for (var i = 0; i < members.length; ++i) { createGangMemberDisplayElement(members[i]); } setGangMemberClickHandlers(); //Set buttons to toggle the gang member info panels //Subpage for seeing gang territory information var territorySubpage = document.createElement("div"); container.appendChild(territorySubpage); territorySubpage.setAttribute("id", "gang-territory-subpage"); territorySubpage.style.display = "none"; //Info text for territory page var territoryInfoText = document.createElement("p"); territorySubpage.appendChild(territoryInfoText); territoryInfoText.innerHTML = "This page shows how much territory your Gang controls. This statistic is listed as a percentage, " + "which represents how much of the total territory you control.

" + "Territory gain and loss is processed automatically and is updated every ~30 seconds. Your chances " + "to gain and lose territory depend on your Gang's power, which is listed in the display below. " + "Your gang's power is determined by the stats of all Gang members you have assigned to the " + "'Territory Warfare' task. Gang members that are not assigned to this task do not contribute to " + "your Gang's power.

" + "The amount of territory you have affects all aspects of your Gang members' production, including " + "money, respect, and wanted level. It is very beneficial to have high territory control.

" territoryInfoText.style.width = "70%"; var territoryBorder = document.createElement("fieldset"); territoryBorder.style.width = "50%"; territoryBorder.style.display = "inline-block"; var territoryP = document.createElement("p"); territoryP.setAttribute("id", "gang-territory-info"); territoryBorder.appendChild(territoryP); territorySubpage.appendChild(territoryBorder); } document.getElementById("gang-container").style.visibility = "visible"; updateGangContent(); } function updateGangContent() { if (!gangContentCreated || !Player.inGang()) {return;} if(document.getElementById("gang-territory-subpage").style.display === "block") { //Update territory information var elem = document.getElementById("gang-territory-info"); elem.innerHTML = ""; for (var gangname in AllGangs) { if (AllGangs.hasOwnProperty(gangname)) { var gangInfo = AllGangs[gangname]; if (gangname == Player.gang.facName) { elem.innerHTML += ("" + gangname + "
(Power: " + formatNumber(gangInfo.power, 6) + "): " + formatNumber(100*gangInfo.territory, 2) + "%

"); } else { elem.innerHTML += (gangname + "
(Power: " + formatNumber(gangInfo.power, 6) + "): " + formatNumber(100*gangInfo.territory, 2) + "%

"); } } } } else { //Update information for overall gang var gangInfo = document.getElementById("gang-info"); if (gangInfo) { var faction = Factions[Player.gang.facName]; var rep; if (!(faction instanceof Faction)) { rep = "ERROR"; } else { rep = faction.playerReputation; } gangInfo.innerHTML = "

This page is used to manage your gang members and get an overview of your gang's stats.

" + "If a gang member is not earning much money or respect, the task that you have assigned to that member " + "might be too difficult. Consider training that member's stats or choosing an easier task. The tasks closer to the " + "top of the dropdown list are generally easier. Alternatively, the gang member's low production might be due to the " + "fact that your wanted level is too high. Consider assigning a few members to the 'Vigilante Justice' or 'Ethical Hacking' " + "tasks to lower your wanted level.

" + "Installing Augmentations does NOT reset your progress with your Gang. Furthermore, after installing Augmentations, you will " + "automatically be a member of whatever Faction you created your gain with.

" + "

Respect: Represents the amount of respect " + "your gang has from other gangs and criminal organizations. Your respect affects the amount of money " + "your gang members will earn, and also determines how much reputation you are earning with your gang's " + "correpsonding Faction.

" + formatNumber(Player.gang.respect, 6) + " (" + formatNumber(5*Player.gang.respectGainRate, 6) + " / sec)


" + "

Wanted Level: Represents how much the gang is wanted by law " + "enforcement. The higher your gang's wanted level, the harder it will be for your gang members to make " + "money and earn respect. Note that the minimum respect value is 1." + "

" + formatNumber(Player.gang.wanted, 6) + " (" + formatNumber(5*Player.gang.wantedGainRate, 6) + " / sec)

" + "Money gain rate: $" + formatNumber(5*Player.gang.moneyGainRate, 2) + " / sec

" + "Faction reputation: " + formatNumber(rep, 3) + "

"; } else { console.log("ERROR: gang-info DOM element DNE"); } //Toggle the 'Recruit member button' if valid var numMembers = Player.gang.members.length; var repCost = 0; if (numMembers > 0) { var repCost = Math.pow(CONSTANTS.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 = document.getElementById("gang-management-recruit-member-btn"); if (numMembers >= CONSTANTS.MaximumGangMembers) { btn.className = "a-link-button-inactive"; document.getElementById("gang-recruit-requirement-text").style.display = "block"; document.getElementById("gang-recruit-requirement-text").innerHTML = "You have reached the maximum amount of gang members"; } else if (faction.playerReputation >= repCost) { btn.className = "a-link-button"; document.getElementById("gang-recruit-requirement-text").style.display = "none"; } else { btn.className = "a-link-button-inactive"; document.getElementById("gang-recruit-requirement-text").style.display = "block"; document.getElementById("gang-recruit-requirement-text").innerHTML = formatNumber(repCost, 2) + " Faction reputation needed to recruit next member"; } //Update information for each gang member for (var i = 0; i < Player.gang.members.length; ++i) { updateGangMemberDisplayElement(Player.gang.members[i]); } } } function setGangMemberClickHandlers() { //Server panel click handlers var gangMemberHdrs = document.getElementsByClassName("gang-member-header"); if (gangMemberHdrs == null) { console.log("ERROR: Could not find Active Scripts server panels"); return; } for (i = 0; i < gangMemberHdrs.length; ++i) { gangMemberHdrs[i].onclick = function() { this.classList.toggle("active"); var panel = this.nextElementSibling; if (panel.style.display === "block") { panel.style.display = "none"; } else { panel.style.display = "block"; } } } } //Takes in a GangMember object function createGangMemberDisplayElement(memberObj) { if (!gangContentCreated || !Player.inGang()) {return;} var name = memberObj.name; var li = document.createElement("li"); var hdr = document.createElement("button"); hdr.setAttribute("class", "gang-member-header"); hdr.setAttribute("id", name + "-gang-member-hdr"); hdr.innerHTML = name; //Div for entire panel var gangMemberDiv = document.createElement("div"); gangMemberDiv.setAttribute("class", "gang-member-panel"); //Gang member content divided into 3 panels: //Stats Panel var statsDiv = document.createElement("div"); statsDiv.setAttribute("id", name + "gang-member-stats"); statsDiv.setAttribute("class", "gang-member-info-div"); var statsP = document.createElement("p"); statsP.setAttribute("id", name + "gang-member-stats-text"); statsP.style.display = "inline"; var upgradeButton = document.createElement("a"); upgradeButton.setAttribute("id", name + "gang-member-upgrade-btn"); upgradeButton.setAttribute("class", "popup-box-button"); upgradeButton.style.cssFloat = "left"; upgradeButton.innerHTML = "Purchase Upgrades"; upgradeButton.addEventListener("click", function() { createGangMemberUpgradeBox(memberObj); }); statsDiv.appendChild(statsP); statsDiv.appendChild(upgradeButton); //Panel for Selecting task and show respect/wanted gain var taskDiv = document.createElement("div"); taskDiv.setAttribute("id", name + "gang-member-task"); taskDiv.setAttribute("class", "gang-member-info-div"); var taskSelector = document.createElement("select"); taskSelector.style.color = "white"; taskSelector.setAttribute("id", name + "gang-member-task-selector"); var tasks = null; if (Player.gang.isHackingGang) { tasks = ["---", "Ransomware", "Phishing", "Identity Theft", "DDoS Attacks", "Plant Virus", "Fraud & Counterfeiting","Money Laundering", "Cyberterrorism", "Ethical Hacking", "Train Combat", "Train Hacking", "Territory Warfare"]; } else { tasks = ["---", "Mug People", "Deal Drugs", "Run a Con", "Armed Robbery", "Traffick Illegal Arms", "Threaten & Blackmail", "Terrorism", "Vigilante Justice", "Train Combat", "Train Hacking", "Territory Warfare"]; } for (var i = 0; i < tasks.length; ++i) { var option = document.createElement("option"); option.text = tasks[i]; taskSelector.add(option); } taskSelector.addEventListener("change", function() { var task = taskSelector.options[taskSelector.selectedIndex].text; memberObj.assignToTask(task); setGangMemberTaskDescription(memberObj, task); updateGangContent(); }); //Set initial task in selector element if (memberObj.task instanceof GangMemberTask) { var taskName = memberObj.task.name; var taskIndex = 0; for (i = 0; i < tasks.length; ++i) { if (taskName == tasks[i]) { taskIndex = i; break; } } taskSelector.selectedIndex = taskIndex; } var gainInfo = document.createElement("p"); //Wanted, respect, reputation, and money gain gainInfo.setAttribute("id", name + "gang-member-gain-info"); taskDiv.appendChild(taskSelector); taskDiv.appendChild(gainInfo); //Panel for Description of task var taskDescDiv = document.createElement("div"); taskDescDiv.setAttribute("id", name + "gang-member-task-desc"); taskDescDiv.setAttribute("class", "gang-member-info-div"); var taskDescP = document.createElement("p"); taskDescP.setAttribute("id", name + "gang-member-task-description"); taskDescP.style.display = "inline"; taskDescDiv.appendChild(taskDescP); statsDiv.style.width = "30%"; taskDiv.style.width = "30%"; taskDescDiv.style.width = "30%"; statsDiv.style.display = "inline"; taskDiv.style.display = "inline"; taskDescDiv.style.display = "inline"; gangMemberDiv.appendChild(statsDiv); gangMemberDiv.appendChild(taskDiv); gangMemberDiv.appendChild(taskDescDiv); li.appendChild(hdr); li.appendChild(gangMemberDiv); document.getElementById("gang-member-list").appendChild(li); setGangMemberTaskDescription(memberObj, taskName); //Initialize description setGangMemberClickHandlers(); //Reset click handlers updateGangMemberDisplayElement(memberObj); } function updateGangMemberDisplayElement(memberObj) { if (!gangContentCreated || !Player.inGang()) {return;} var name = memberObj.name; //TODO Add upgrade information var stats = document.getElementById(name + "gang-member-stats-text"); if (stats) { stats.innerHTML = "Hacking: " + formatNumber(memberObj.hack, 0) + " (" + numeral(memberObj.hack_exp).format('(0.00a)') + " exp)
" + "Strength: " + formatNumber(memberObj.str, 0) + " (" + numeral(memberObj.str_exp).format('(0.00a)') + " exp)
" + "Defense: " + formatNumber(memberObj.def, 0) + " (" + numeral(memberObj.def_exp).format('(0.00a)') + " exp)
" + "Dexterity: " + formatNumber(memberObj.dex, 0) + " (" + numeral(memberObj.dex_exp).format('(0.00a)') + " exp)
" + "Agility: " + formatNumber(memberObj.agi, 0) + " (" + numeral(memberObj.agi_exp).format('(0.00a)') + " exp)
" + "Charisma: " + formatNumber(memberObj.cha, 0) + " (" + numeral(memberObj.cha_exp).format('(0.00a)') + " exp)
"; } var gainInfo = document.getElementById(name + "gang-member-gain-info"); if (gainInfo) { gainInfo.innerHTML = "Money: $" + formatNumber(5*memberObj.calculateMoneyGain(), 2) + " / sec
" + "Respect: " + formatNumber(5*memberObj.calculateRespectGain(), 6) + " / sec
" + "Wanted Level: " + formatNumber(5*memberObj.calculateWantedLevelGain(), 6) + " / sec
"; } } function setGangMemberTaskDescription(memberObj, taskName) { var name = memberObj.name; var taskDesc = document.getElementById(name + "gang-member-task-description"); if (taskDesc) { var task = GangMemberTasks[taskName]; if (task == null) {return;} var desc = task.desc; taskDesc.innerHTML = desc; } }