Finished Gang API. Rebalanced the way Gang territory works. Added discount feature for purchasing Gang member equipment

This commit is contained in:
danielyxie 2018-10-21 20:04:32 -05:00
parent e73ebe843f
commit 0cdfe590a7
6 changed files with 185 additions and 66 deletions

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

@ -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.<br><br>" +
"In this BitNode:<br><br>The maximum amount of money available on a server is significantly decreased<br>" +
"In this BitNode:<br><br>" +
"Your hacking level is reduced by 25%<br>" +
"The growth rate and maximum amount of money available on servers is significantly decreased<br>" +
"The amount of money gained from crimes and Infiltration is tripled<br>" +
"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;

@ -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

@ -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("<br>"));
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("<br>"));
} 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("<br>"),
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("<br>"),
});
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("<br>");
[`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("<br>");
}
}

@ -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));
}

@ -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};