diff --git a/netscript.js b/netscript.js
index 529088b7f..2118a5a3c 100644
--- a/netscript.js
+++ b/netscript.js
@@ -101,7 +101,14 @@ let NetscriptFunctions =
"upgradeLevel|upgradeRam|upgradeCore|getLevelUpgradeCost|" +
"getRamUpgradeCost|getCoreUpgradeCost|" +
- // Bladeburner functions
+ // Gang API
+ "gang|" +
+ "getMemberNames|getGangInformation|getMemberInformation|canRecruitMember|" +
+ "recruitMember|getTaskNames|setMemberTask|getEquipmentNames|" +
+ "getEquipmentCost|purchaseEquipment|ascendMember|setTerritoryWarfare|" +
+ "getBonusTime|" +
+
+ // Bladeburner API
"bladeburner|getContractNames|getOperationNames|getBlackOpNames|" +
"getGeneralActionNames|getSkillNames|startAction|stopBladeburnerAction|" +
"getActionTime|getActionEstimatedSuccessChance|getActionCountRemaining|" +
diff --git a/src/BitNode.js b/src/BitNode.js
index 6c8a79801..2d309becf 100644
--- a/src/BitNode.js
+++ b/src/BitNode.js
@@ -28,7 +28,9 @@ function initBitNodes() {
"left behind from the collapse of Western government in the 2050's. As society and civlization broke down, " +
"people quickly succumbed to the innate human impulse of evil and savagery. The organized crime " +
"factions quickly rose to the top of the modern world.
" +
- "In this BitNode:
The maximum amount of money available on a server is significantly decreased
" +
+ "In this BitNode:
" +
+ "Your hacking level is reduced by 25%
" +
+ "The growth rate and maximum amount of money available on servers is significantly decreased
" +
"The amount of money gained from crimes and Infiltration is tripled
" +
"Certain Factions (Slum Snakes, Tetrads, The Syndicate, The Dark Army, Speakers for the Dead, " +
"NiteSec, The Black Hand) give the player the ability to form and manage their own gangs. These gangs " +
@@ -214,6 +216,8 @@ function initBitNodeMultipliers() {
case 1: //Source Genesis (every multiplier is 1)
break;
case 2: //Rise of the Underworld
+ BitNodeMultipliers.HackingLevelMultiplier = 0.75;
+ BitNodeMultipliers.ServerGrowthRate = 0.75;
BitNodeMultipliers.ServerMaxMoney = 0.2;
BitNodeMultipliers.ServerStartingMoney = 0.4;
BitNodeMultipliers.CrimeMoney = 3;
diff --git a/src/Constants.js b/src/Constants.js
index 80f299c88..5defbf59a 100644
--- a/src/Constants.js
+++ b/src/Constants.js
@@ -506,15 +506,18 @@ let CONSTANTS = {
v0.41.0
* WARNING: In NetscriptJS, defining a function called print() is no longer possible
* Gang Mechanic Changes (BitNode-2):
+ *** Added a Gang Netscript API
*** Added new 'ascension' mechanic for Gang Members
*** The first three gang members are now 'free' (can be recruited instantly)
- *** Maximum number of increased Gang Members increased from 20 to 50
+ *** Maximum number of increased Gang Members increased from 20 to 40
*** Changed the formula for calculating respect needed to recruit the next gang member
*** Added a new category of upgrades for Gang Members: Augmentations
*** Non-Augmentation Gang member upgrades are now significantly weaker
*** Reputation for your Gang faction can no longer be gained through Infiltration
*** Re-worked the territory 'warfare' mechanic so that player can choose when to engage in it
- *** Player's faction reputation multiplier no longer affects reputation gang from earning respect
+ *** Gang Members can now be killed during territory 'warfare'
+ *** Changed BitNode-2 Multipliers to make hacking slightly less profitable
+ *** Gang Member Equipment + Upgrades now get cheaper as your gang grows in power and respect
* RAM Cost of accessing the global document object lowered from 100 GB to 25 GB
* RAM Cost to use Singularity Functions outside of BitNode-4 lowered by 75%. They now only cost twice as much as they do in BitNode-4
* b1t_flum3.exe now takes significantly less time to create
diff --git a/src/Gang.js b/src/Gang.js
index 988384838..48f723504 100644
--- a/src/Gang.js
+++ b/src/Gang.js
@@ -1,11 +1,6 @@
/*
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
*/
@@ -39,7 +34,7 @@ import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
// Constants
const GangRespectToReputationRatio = 2; // Respect is divided by this to get rep gain
-const MaximumGangMembers = 50;
+const MaximumGangMembers = 40;
const GangRecruitCostMultiplier = 2;
const CyclesPerTerritoryAndPowerUpdate = 100;
const AscensionMultiplierRatio = 10 / 100; // Portion of upgrade multiplier that is kept after ascending
@@ -176,7 +171,7 @@ export function Gang(facName, hacking=false) {
this.notifyMemberDeath = true;
}
-Gang.prototype.power() = function() {
+Gang.prototype.getPower = function() {
return AllGangs[this.facName].power;
}
@@ -275,9 +270,9 @@ Gang.prototype.processTerritoryAndPowerGains = function(numCycles=1) {
AllGangs[name].power += this.calculatePower();
} else {
// Adjust these parameters as necessary
- const additiveGain = Math.random() * AllGangs[name].territory;
+ const additiveGain = 0.5 * Math.random() * AllGangs[name].territory;
AllGangs[name].power += (additiveGain);
- AllGangs[name].power *= 1.01;
+ AllGangs[name].power *= 1.009;
}
}
}
@@ -448,7 +443,7 @@ Gang.prototype.killMember = function(memberObj) {
}
}
-Gang.prototype.ascendMember = function(memberObj) {
+Gang.prototype.ascendMember = function(memberObj, workerScript) {
try {
/**
* res is an object with the following format:
@@ -459,21 +454,42 @@ Gang.prototype.ascendMember = function(memberObj) {
*/
const res = memberObj.ascend();
this.respect = Math.max(1, this.respect - res.respect);
- dialogBoxCreate([`You ascended ${memberObj.name}!`,
- `Your gang lost ${numeralWrapper.format(res.respect, "0.000a")} respect`,
- `${memberObj.name} gained the following stat multipliers for ascending:`,
- `Hacking: ${res.hack}`,
- `Strength: ${res.str}`,
- `Defense: ${res.def}`,
- `Dexterity: ${res.dex}`,
- `Agility: ${res.agi}`,
- `Charisma: ${res.cha}`].join("
"));
- this.displayGangMemberList();
+ if (workerScript == null) {
+ dialogBoxCreate([`You ascended ${memberObj.name}!`,
+ `Your gang lost ${numeralWrapper.format(res.respect, "0.000a")} respect`,
+ `${memberObj.name} gained the following stat multipliers for ascending:`,
+ `Hacking: ${res.hack}`,
+ `Strength: ${res.str}`,
+ `Defense: ${res.def}`,
+ `Dexterity: ${res.dex}`,
+ `Agility: ${res.agi}`,
+ `Charisma: ${res.cha}`].join("
"));
+ } else {
+ workerScript.log(`Ascended Gang member ${memberObj.name}`);
+ }
+ if (routing.isOn(Page.Gang)) {
+ this.displayGangMemberList();
+ }
} catch(e) {
- exceptionAlert(e);
+ if (workerScript == null) {
+ exceptionAlert(e);
+ } else {
+ throw e; // Re-throw, will be caught in the Netscript Function
+ }
}
}
+// Cost of upgrade gets cheaper as gang increases in respect + power
+Gang.prototype.getDiscount = function() {
+ const power = this.getPower();
+ const respect = this.respect;
+
+ const respectLinearFac = 5e6;
+ const powerLinearFac = 1e6;
+ const discount = Math.pow(respect, 0.01) + respect / respectLinearFac + Math.pow(power, 0.01) + power / powerLinearFac - 1;
+ return Math.max(1, discount);
+}
+
// Returns only valid tasks for this gang. Excludes 'Unassigned'
Gang.prototype.getAllTaskNames = function() {
let tasks = [];
@@ -496,6 +512,15 @@ Gang.prototype.getAllTaskNames = function() {
return tasks;
}
+Gang.prototype.getAllUpgradeNames = function() {
+ return Object.keys(GangMemberUpgrades);
+}
+
+Gang.prototype.getUpgradeCost = function(upgName) {
+ if (GangMemberUpgrades[upgName] == null) { return Infinity; }
+ return GangMemberUpgrades[upgName].getCost(this);
+}
+
Gang.prototype.toJSON = function() {
return Generic_toJSON("Gang", this);
}
@@ -567,8 +592,10 @@ GangMember.prototype.calculatePower = function() {
GangMember.prototype.assignToTask = function(taskName) {
if (GangMemberTasks.hasOwnProperty(taskName)) {
this.task = GangMemberTasks[taskName];
+ return true;
} else {
this.task = GangMemberTasks["Unassigned"];
+ return false;
}
}
@@ -734,11 +761,14 @@ GangMember.prototype.getAscensionResults = function() {
}
GangMember.prototype.buyUpgrade = function(upg, player, gang) {
- if (!(upg instanceof GangMemberUpgrade)) {
- throw new Error(`Invalid 'upg' argument passed into GangMember.buyUpgrade`);
+ if (typeof upg === 'string') {
+ upg = GangMemberUpgrades[upg];
}
- if (player.money.lt(upg.cost)) { return false; }
- player.loseMoney(upg.cost);
+ if (!(upg instanceof GangMemberUpgrade)) {
+ return false;
+ }
+ if (player.money.lt(upg.getCost(gang))) { return false; }
+ player.loseMoney(upg.getCost(gang));
if (upg.type === "g") {
this.augmentations.push(upg.name);
} else {
@@ -749,6 +779,7 @@ GangMember.prototype.buyUpgrade = function(upg, player, gang) {
var initFilterValue = UIElems.gangMemberUpgradeBoxFilter.value.toString();
gang.createGangMemberUpgradeBox(player, initFilterValue);
}
+ return true;
}
GangMember.prototype.toJSON = function() {
@@ -822,6 +853,11 @@ function GangMemberUpgrade(name="", cost=0, type="w", mults={}) {
this.createDescription();
}
+GangMemberUpgrade.prototype.getCost = function(gang) {
+ const discount = gang.getDiscount();
+ return this.cost / discount;
+}
+
GangMemberUpgrade.prototype.createDescription = function() {
const lines = ["Increases:"];
if (this.mults.str != null) {
@@ -887,10 +923,10 @@ Gang.prototype.createGangMemberUpgradeBox = function(player, initialFilter="") {
return;
}
- for (var i = 1; i < UIElems.gangMemberUpgradeBoxElements.length; ++i) {
+ for (var i = 2; i < UIElems.gangMemberUpgradeBoxElements.length; ++i) {
removeElement(UIElems.gangMemberUpgradeBoxElements[i]);
}
- UIElems.gangMemberUpgradeBoxElements = [UIElems.gangMemberUpgradeBoxFilter];
+ UIElems.gangMemberUpgradeBoxElements = [UIElems.gangMemberUpgradeBoxFilter, UIElems.gangMemberUpgradeBoxDiscount];
var filter = UIElems.gangMemberUpgradeBoxFilter.value.toString();
for (var i = 0; i < this.members.length; ++i) {
@@ -911,7 +947,14 @@ Gang.prototype.createGangMemberUpgradeBox = function(player, initialFilter="") {
}
});
- UIElems.gangMemberUpgradeBoxElements = [UIElems.gangMemberUpgradeBoxFilter];
+ UIElems.gangMemberUpgradeBoxDiscount = createElement("p", {
+ innerText: "Discount: -" + numeralWrapper.format(1 - 1 / this.getDiscount(), "0.00%"),
+ marginLeft: "6px",
+ tooltip: "You get a discount on equipment and upgrades based on your gang's " +
+ "respect and power. More respect and power leads to more discounts."
+ });
+
+ UIElems.gangMemberUpgradeBoxElements = [UIElems.gangMemberUpgradeBoxFilter, UIElems.gangMemberUpgradeBoxDiscount];
var filter = UIElems.gangMemberUpgradeBoxFilter.value.toString();
for (var i = 0; i < this.members.length; ++i) {
@@ -984,7 +1027,7 @@ GangMember.prototype.createGangMemberUpgradePanel = function(gangObj, player) {
for (let upgName in GangMemberUpgrades) {
if (GangMemberUpgrades.hasOwnProperty(upgName)) {
let upg = GangMemberUpgrades[upgName];
- if (player.money.lt(upg.cost)) { continue; }
+ if (player.money.lt(upg.getCost(gangObj))) { continue; }
if (this.upgrades.includes(upgName) || this.augmentations.includes(upgName)) { continue; }
switch (upg.type) {
case "w":
@@ -1030,10 +1073,10 @@ GangMember.prototype.createGangMemberUpgradePanel = function(gangObj, player) {
let div = divs[i];
for (let j = 0; j < upgradeArray.length; ++j) {
let upg = upgradeArray[j];
- (function (upg, div, memberObj, i) {
+ (function (upg, div, memberObj, i, gang) {
let createElementParams = {
- innerText:upg.name + " - " + numeralWrapper.format(upg.cost, "$0.000a"),
- class:"a-link-button", margin:"2px", padding:"2px", display:"block",
+ innerText: upg.name + " - " + numeralWrapper.format(upg.getCost(gang), "$0.000a"),
+ class: "a-link-button", margin:"2px", padding:"2px", display:"block",
fontSize:"11px",
clickListener:()=>{
memberObj.buyUpgrade(upg, player, gangObj);
@@ -1048,7 +1091,7 @@ GangMember.prototype.createGangMemberUpgradePanel = function(gangObj, player) {
createElementParams.tooltip = upg.desc;
}
div.appendChild(createElement("a", createElementParams));
- })(upg, div, this, i);
+ })(upg, div, this, i, gangObj);
}
}
@@ -1089,6 +1132,7 @@ const UIElems = {
gangMemberUpgradeBox: null,
gangMemberUpgradeBoxContent: null,
gangMemberUpgradeBoxFilter: null,
+ gangMemberUpgradeBoxDiscount: null,
gangMemberUpgradeBoxElements: null,
// Gang Territory Elements
@@ -1190,7 +1234,7 @@ Gang.prototype.displayGangContent = function(player) {
UIElems.gangManagementSubpage.appendChild(UIElems.gangInfo);
UIElems.gangRecruitMemberButton = createElement("a", {
- id:"gang-management-recruit-member-btn", class:"a-link-button-inactive",
+ id: "gang-management-recruit-member-btn", class:"a-link-button-inactive",
innerHTML:"Recruit Gang Member", display:"inline-block", margin:"10px",
clickListener:()=>{
const popupId = "recruit-gang-member-popup";
@@ -1224,8 +1268,10 @@ Gang.prototype.displayGangContent = function(player) {
// have a gang member with the same name
if (!this.recruitMember(name)) {
dialogBoxCreate("You already have a gang member with this name!");
+ return false;
}
+ removeElementById(popupId);
return false;
},
innerText: "Recruit Gang Member",
@@ -1428,11 +1474,19 @@ Gang.prototype.displayGangMemberList = function() {
Gang.prototype.updateGangContent = function() {
if (!UIElems.gangContentCreated) { return; }
+ if (UIElems.gangMemberUpgradeBoxOpened) {
+ UIElems.gangMemberUpgradeBoxDiscount.childNodes[0].nodeValue =
+ "Discount: -" + numeralWrapper.format(1 - 1 / this.getDiscount(), "0.00%");
+ }
+
if (UIElems.gangTerritorySubpage.style.display === "block") {
// Territory Warfare Clash Chance
UIElems.gangTerritoryWarfareClashChance.innerText =
`Territory Clash Chance: ${numeralWrapper.format(this.territoryClashChance, '0.000%')}`;
+ // Engaged in Territory Warfare checkbox
+ UIElems.gangTerritoryWarfareCheckbox.checked = this.territoryWarfareEngaged;
+
// Update territory information
UIElems.gangTerritoryInfoText.innerHTML = "";
for (var gangname in AllGangs) {
@@ -1590,12 +1644,12 @@ Gang.prototype.createGangMemberDisplayElement = function(memberObj) {
const statsDiv = createElement("div", {
class: "gang-member-info-div",
id: name + "gang-member-stats",
- tooltipsmall: [`Hk: x${numeralWrapper.format(memberObj.hack_mult * memberObj.hack_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.hack_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.hack_asc_mult, "0,0.00")} Asc)`,
- `St: x${numeralWrapper.format(memberObj.str_mult * memberObj.str_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.str_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.str_asc_mult, "0,0.00")} Asc)`,
- `Df: x${numeralWrapper.format(memberObj.def_mult * memberObj.def_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.def_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.def_asc_mult, "0,0.00")} Asc)`,
- `Dx: x${numeralWrapper.format(memberObj.dex_mult * memberObj.dex_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.dex_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.dex_asc_mult, "0,0.00")} Asc)`,
- `Ag: x${numeralWrapper.format(memberObj.agi_mult * memberObj.agi_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.agi_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.agi_asc_mult, "0,0.00")} Asc)`,
- `Ch: x${numeralWrapper.format(memberObj.cha_mult * memberObj.cha_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.cha_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.cha_asc_mult, "0,0.00")} Asc)`].join("
"),
+ tooltipsmall: [`Hk: x${numeralWrapper.format(memberObj.hack_mult * memberObj.hack_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.hack_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.hack_asc_mult, "0,0.00")} Asc)`,
+ `St: x${numeralWrapper.format(memberObj.str_mult * memberObj.str_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.str_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.str_asc_mult, "0,0.00")} Asc)`,
+ `Df: x${numeralWrapper.format(memberObj.def_mult * memberObj.def_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.def_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.def_asc_mult, "0,0.00")} Asc)`,
+ `Dx: x${numeralWrapper.format(memberObj.dex_mult * memberObj.dex_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.dex_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.dex_asc_mult, "0,0.00")} Asc)`,
+ `Ag: x${numeralWrapper.format(memberObj.agi_mult * memberObj.agi_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.agi_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.agi_asc_mult, "0,0.00")} Asc)`,
+ `Ch: x${numeralWrapper.format(memberObj.cha_mult * memberObj.cha_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.cha_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.cha_asc_mult, "0,0.00")} Asc)`].join("
"),
});
UIElems.gangMemberPanels[name]["statsDiv"] = statsDiv;
const statsP = createElement("pre", {
@@ -1742,12 +1796,12 @@ Gang.prototype.updateGangMemberDisplayElement = function(memberObj) {
const statsDiv = panel["statsDiv"];
if (statsDiv) {
statsDiv.firstChild.innerHTML =
- [`Hk: x${numeralWrapper.format(memberObj.hack_mult * memberObj.hack_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.hack_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.hack_asc_mult, "0,0.00")} Asc)`,
- `St: x${numeralWrapper.format(memberObj.str_mult * memberObj.str_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.str_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.str_asc_mult, "0,0.00")} Asc)`,
- `Df: x${numeralWrapper.format(memberObj.def_mult * memberObj.def_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.def_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.def_asc_mult, "0,0.00")} Asc)`,
- `Dx: x${numeralWrapper.format(memberObj.dex_mult * memberObj.dex_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.dex_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.dex_asc_mult, "0,0.00")} Asc)`,
- `Ag: x${numeralWrapper.format(memberObj.agi_mult * memberObj.agi_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.agi_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.agi_asc_mult, "0,0.00")} Asc)`,
- `Ch: x${numeralWrapper.format(memberObj.cha_mult * memberObj.cha_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.cha_mult, "0,0.00")} Up, x${numeralWrapper.format(memberObj.cha_asc_mult, "0,0.00")} Asc)`].join("
");
+ [`Hk: x${numeralWrapper.format(memberObj.hack_mult * memberObj.hack_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.hack_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.hack_asc_mult, "0,0.00")} Asc)`,
+ `St: x${numeralWrapper.format(memberObj.str_mult * memberObj.str_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.str_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.str_asc_mult, "0,0.00")} Asc)`,
+ `Df: x${numeralWrapper.format(memberObj.def_mult * memberObj.def_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.def_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.def_asc_mult, "0,0.00")} Asc)`,
+ `Dx: x${numeralWrapper.format(memberObj.dex_mult * memberObj.dex_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.dex_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.dex_asc_mult, "0,0.00")} Asc)`,
+ `Ag: x${numeralWrapper.format(memberObj.agi_mult * memberObj.agi_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.agi_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.agi_asc_mult, "0,0.00")} Asc)`,
+ `Ch: x${numeralWrapper.format(memberObj.cha_mult * memberObj.cha_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.cha_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.cha_asc_mult, "0,0.00")} Asc)`].join("
");
}
}
diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js
index bcbd74ef6..712c437c0 100644
--- a/src/NetscriptFunctions.js
+++ b/src/NetscriptFunctions.js
@@ -3593,16 +3593,29 @@ function NetscriptFunctions(workerScript) {
agility: member.agi,
agilityEquipMult: member.agi_mult,
agilityAscensionMult: member.agi_asc_mult,
+ augmentation: member.augmentations.slice(),
charisma: member.cha,
+ charismaEquipMult: member.cha_mult,
+ charismaAscensionMult: member.cha_asc_mult,
defense: member.def,
+ defenseEquipMult: member.def_mult,
+ defenseAscensionMult: member.def_asc_mult,
dexterity: member.dex,
+ dexterityEquipMult: member.dex_mult,
+ dexterityAscensionMult: member.dex_asc_mult,
+ equipment: member.upgrades.slice(),
hacking: member.hack,
- strength: member.str
+ hackingEquipMult: member.hack_mult,
+ hackingAscensionMult: member.hack_asc_mult,
+ strength: member.str,
+ strengthEquipMult: member.str_mult,
+ strengthAscensionMult: member.str_asc_mult,
task: member.task.name,
}
}
}
+ workerScript.log(`Invalid argument passed to gang.getMemberInformation(). No gang member could be found with name ${name}`);
return {}; // Member could not be found
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getMemberInformation", e));
@@ -3616,12 +3629,12 @@ function NetscriptFunctions(workerScript) {
nsGang.checkGangApiAccess(workerScript, "canRecruitMember");
try {
-
+ return Player.gang.canRecruitMember();
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("canRecruitMember", e));
}
},
- recruitMember : function() {
+ recruitMember : function(name) {
if (workerScript.checkingRam) {
return updateStaticRam("recruitMember", CONSTANTS.ScriptGangApiBaseRamCost / 2);
}
@@ -3629,7 +3642,7 @@ function NetscriptFunctions(workerScript) {
nsGang.checkGangApiAccess(workerScript, "recruitMember");
try {
-
+ return Player.gang.recruitMember(name);
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("recruitMember", e));
}
@@ -3642,12 +3655,14 @@ function NetscriptFunctions(workerScript) {
nsGang.checkGangApiAccess(workerScript, "getTaskNames");
try {
-
+ const tasks = Player.gang.getAllTaskNames();
+ tasks.unshift("Unassigned");
+ return tasks;
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getTaskNames", e));
}
},
- setMemberTask : function() {
+ setMemberTask : function(memberName, taskName) {
if (workerScript.checkingRam) {
return updateStaticRam("setMemberTask", CONSTANTS.ScriptGangApiBaseRamCost / 2);
}
@@ -3655,7 +3670,14 @@ function NetscriptFunctions(workerScript) {
nsGang.checkGangApiAccess(workerScript, "setMemberTask");
try {
+ for (const member of Player.gang.members) {
+ if (member.name === memberName) {
+ return member.assignToTask(taskName);
+ }
+ }
+ workerScript.log(`Invalid argument passed to gang.setMemberTask(). No gang member could be found with name ${memberName}`);
+ return false;
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("setMemberTask", e));
}
@@ -3668,12 +3690,12 @@ function NetscriptFunctions(workerScript) {
nsGang.checkGangApiAccess(workerScript, "getEquipmentNames");
try {
-
+ return Player.gang.getAllUpgradeNames();
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentNames", e));
}
},
- getEquipmentCost : function() {
+ getEquipmentCost : function(equipName) {
if (workerScript.checkingRam) {
return updateStaticRam("getEquipmentCost", CONSTANTS.ScriptGangApiBaseRamCost / 2);
}
@@ -3681,12 +3703,12 @@ function NetscriptFunctions(workerScript) {
nsGang.checkGangApiAccess(workerScript, "getEquipmentCost");
try {
-
+ return Player.gang.getUpgradeCost(equipName);
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentCost", e));
}
},
- purchaseEquipment : function() {
+ purchaseEquipment : function(memberName, equipName) {
if (workerScript.checkingRam) {
return updateStaticRam("purchaseEquipment", CONSTANTS.ScriptGangApiBaseRamCost / 2);
}
@@ -3694,11 +3716,38 @@ function NetscriptFunctions(workerScript) {
nsGang.checkGangApiAccess(workerScript, "purchaseEquipment");
try {
+ for (const member in Player.gang.members) {
+ if (member.name === memberName) {
+ return member.buyUpgrade(equipName, Player, Player.gang);
+ }
+ }
+ workerScript.log(`Invalid argument passed to gang.purchaseEquipment(). No gang member could be found with name ${memberName}`);
+ return false;
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("purchaseEquipment", e));
}
},
+ ascendMember : function(name) {
+ if (workerScript.checkingRam) {
+ return updateStaticRam("ascendMember", CONSTANTS.ScriptGangApiBaseRamCost / 2);
+ }
+ updateDynamicRam("ascendMember", CONSTANTS.ScriptGangApiBaseRamCost / 2);
+ nsGang.checkGangApiAccess(workerScript, "ascendMember");
+
+ try {
+ for (const member in Player.gang.members) {
+ if (member.name === name) {
+ return Player.gang.ascendMember(member, workerScript);
+ }
+ }
+
+ workerScript.log(`Invalid argument passed to gang.ascendMember(). No gang member could be found with name ${memberName}`);
+ return false;
+ } catch(e) {
+ throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("ascendMember", e));
+ }
+ },
setTerritoryWarfare : function(engage) {
if (workerScript.checkingRam) {
return updateStaticRam("setTerritoryWarfare", CONSTANTS.ScriptGangApiBaseRamCost / 2);
@@ -3707,7 +3756,11 @@ function NetscriptFunctions(workerScript) {
nsGang.checkGangApiAccess(workerScript, "setTerritoryWarfare");
try {
-
+ if (engage) {
+ Player.gang.territoryWarfareEngaged = true;
+ } else {
+ Player.gang.territoryWarfareEngaged = false;
+ }
} catch(e) {
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("setTerritoryWarfare", e));
}
diff --git a/src/NetscriptGang.js b/src/NetscriptGang.js
index 4ab5c005a..638bba084 100644
--- a/src/NetscriptGang.js
+++ b/src/NetscriptGang.js
@@ -2,16 +2,14 @@ import {Player} from "./Player";
import {Gang} from "./Gang";
import {makeRuntimeRejectMsg} from "./NetscriptEvaluator";
-function unknownGangApiExceptionMessage(functionName, err) {
+export function unknownGangApiExceptionMessage(functionName, err) {
return `gang.${functionName}() failed with exception: ` + err;
}
-function checkGangApiAccess(workerScript, functionName) {
+export function checkGangApiAccess(workerScript, functionName) {
const accessDenied = `gang.${functionName}() failed because you do not currently have a Gang`;
const hasAccess = Player.gang instanceof Gang;
if (!hasAccess) {
throw makeRuntimeRejectMsg(workerScript, accessDenied);
}
}
-
-export {unknownBladeburnerActionErrorMessage, unknownBladeburnerExceptionMessage, checkBladeburnerAccess};