bit more code cleanups

This commit is contained in:
Olivier Gagnon 2021-06-17 18:59:45 -04:00
parent febf0835c2
commit 05b1b55e9a
2 changed files with 82 additions and 111 deletions

@ -97,7 +97,7 @@ export class Gang {
this.storedCycles += numCycles; this.storedCycles += numCycles;
// Only process if there are at least 2 seconds, and at most 5 seconds // Only process if there are at least 2 seconds, and at most 5 seconds
if (this.storedCycles < 2 * CyclesPerSecond) { return; } if (this.storedCycles < 2 * CyclesPerSecond) return;
const cycles = Math.min(this.storedCycles, 5 * CyclesPerSecond); const cycles = Math.min(this.storedCycles, 5 * CyclesPerSecond);
try { try {
@ -113,7 +113,9 @@ export class Gang {
processGains(numCycles = 1, player: IPlayer): void { processGains(numCycles = 1, player: IPlayer): void {
// Get gains per cycle // Get gains per cycle
let moneyGains = 0, respectGains = 0, wantedLevelGains = 0; let moneyGains = 0;
let respectGains = 0;
let wantedLevelGains = 0;
let justice = 0; let justice = 0;
for (let i = 0; i < this.members.length; ++i) { for (let i = 0; i < this.members.length; ++i) {
respectGains += (this.members[i].calculateRespectGain(this)); respectGains += (this.members[i].calculateRespectGain(this));
@ -126,54 +128,38 @@ export class Gang {
this.wantedGainRate = wantedLevelGains; this.wantedGainRate = wantedLevelGains;
this.moneyGainRate = moneyGains; this.moneyGainRate = moneyGains;
if (typeof respectGains === "number") { const gain = respectGains * numCycles;
const gain = respectGains * numCycles; this.respect += gain;
this.respect += gain; // Faction reputation gains is respect gain divided by some constant
// Faction reputation gains is respect gain divided by some constant const fac = Factions[this.facName];
const fac = Factions[this.facName]; if (!(fac instanceof Faction)) {
if (!(fac instanceof Faction)) { dialogBoxCreate("ERROR: Could not get Faction associates with your gang. This is a bug, please report to game dev");
dialogBoxCreate("ERROR: Could not get Faction associates with your gang. This is a bug, please report to game dev"); throw new Error('Could not find the faction associated with this gang.');
} else { }
const favorMult = 1 + (fac.favor / 100); const favorMult = 1 + (fac.favor / 100);
fac.playerReputation += ((player.faction_rep_mult * gain * favorMult) / GangConstants.GangRespectToReputationRatio); fac.playerReputation += ((player.faction_rep_mult * gain * favorMult) / GangConstants.GangRespectToReputationRatio);
}
// Keep track of respect gained per member // Keep track of respect gained per member
for (let i = 0; i < this.members.length; ++i) { for (let i = 0; i < this.members.length; ++i) {
this.members[i].recordEarnedRespect(numCycles, this); this.members[i].recordEarnedRespect(numCycles, this);
}
} else {
console.warn("respectGains calculated to be NaN");
} }
if (typeof wantedLevelGains === "number") { if (!(this.wanted === 1 && wantedLevelGains < 0)) {
if (this.wanted === 1 && wantedLevelGains < 0) { const oldWanted = this.wanted;
// At minimum wanted, do nothing let newWanted = oldWanted + (wantedLevelGains * numCycles);
} else { newWanted = newWanted * (1 - justice * 0.001); // safeguard
const oldWanted = this.wanted; // Prevent overflow
let newWanted = oldWanted + (wantedLevelGains * numCycles); if (wantedLevelGains <= 0 && newWanted > oldWanted) newWanted = 1;
newWanted = newWanted * (1 - justice * 0.001); // safeguard
// Prevent overflow
if (wantedLevelGains <= 0 && newWanted > oldWanted) {
newWanted = 1;
}
this.wanted = newWanted; this.wanted = newWanted;
if (this.wanted < 1) {this.wanted = 1;} if (this.wanted < 1) this.wanted = 1;
}
} else {
console.warn("ERROR: wantedLevelGains is NaN");
}
if (typeof moneyGains === "number") {
player.gainMoney(moneyGains * numCycles);
player.recordMoneySource(moneyGains * numCycles, "gang");
} else {
console.warn("ERROR: respectGains is NaN");
} }
player.gainMoney(moneyGains * numCycles);
player.recordMoneySource(moneyGains * numCycles, "gang");
} }
processTerritoryAndPowerGains(numCycles = 1): void { processTerritoryAndPowerGains(numCycles = 1): void {
this.storedTerritoryAndPowerCycles += numCycles; this.storedTerritoryAndPowerCycles += numCycles;
if (this.storedTerritoryAndPowerCycles < GangConstants.CyclesPerTerritoryAndPowerUpdate) { return; } if (this.storedTerritoryAndPowerCycles < GangConstants.CyclesPerTerritoryAndPowerUpdate) return;
this.storedTerritoryAndPowerCycles -= GangConstants.CyclesPerTerritoryAndPowerUpdate; this.storedTerritoryAndPowerCycles -= GangConstants.CyclesPerTerritoryAndPowerUpdate;
// Process power first // Process power first
@ -221,7 +207,7 @@ export class Gang {
// If either of the gangs involved in this clash is the player, determine // If either of the gangs involved in this clash is the player, determine
// whether to skip or process it using the clash chance // whether to skip or process it using the clash chance
if (thisGang === gangName || otherGang === gangName) { if (thisGang === gangName || otherGang === gangName) {
if (!(Math.random() < this.territoryClashChance)) { continue; } if (!(Math.random() < this.territoryClashChance)) continue;
} }
const thisPwr = AllGangs[thisGang].power; const thisPwr = AllGangs[thisGang].power;
@ -234,11 +220,8 @@ export class Gang {
return gains; return gains;
} }
if (Math.random() < thisChance) { if (Math.random() < thisChance) {
if (AllGangs[otherGang].territory <= 0) { if (AllGangs[otherGang].territory <= 0) return;
return;
}
const territoryGain = calculateTerritoryGain(thisGang, otherGang); const territoryGain = calculateTerritoryGain(thisGang, otherGang);
AllGangs[thisGang].territory += territoryGain; AllGangs[thisGang].territory += territoryGain;
AllGangs[otherGang].territory -= territoryGain; AllGangs[otherGang].territory -= territoryGain;
@ -251,9 +234,7 @@ export class Gang {
AllGangs[otherGang].power *= (1 / 1.01); AllGangs[otherGang].power *= (1 / 1.01);
} }
} else { } else {
if (AllGangs[thisGang].territory <= 0) { if (AllGangs[thisGang].territory <= 0) return;
return;
}
const territoryGain = calculateTerritoryGain(otherGang, thisGang); const territoryGain = calculateTerritoryGain(otherGang, thisGang);
AllGangs[thisGang].territory -= territoryGain; AllGangs[thisGang].territory -= territoryGain;
AllGangs[otherGang].territory += territoryGain; AllGangs[otherGang].territory += territoryGain;
@ -279,21 +260,19 @@ export class Gang {
clash(won = false): void { clash(won = false): void {
// Determine if a gang member should die // Determine if a gang member should die
let baseDeathChance = 0.01; let baseDeathChance = 0.01;
if (won) { baseDeathChance /= 2; } if (won) baseDeathChance /= 2;
// If the clash was lost, the player loses a small percentage of power // If the clash was lost, the player loses a small percentage of power
if (!won) { else AllGangs[this.facName].power *= (1 / 1.008);
AllGangs[this.facName].power *= (1 / 1.008);
}
// Deaths can only occur during X% of clashes // Deaths can only occur during X% of clashes
if (Math.random() < 0.65) { return; } if (Math.random() < 0.65) return;
for (let i = this.members.length - 1; i >= 0; --i) { for (let i = this.members.length - 1; i >= 0; --i) {
const member = this.members[i]; const member = this.members[i];
// Only members assigned to Territory Warfare can die // Only members assigned to Territory Warfare can die
if (member.task !== "Territory Warfare") { continue; } if (member.task !== "Territory Warfare") continue;
// Chance to die is decreased based on defense // Chance to die is decreased based on defense
const modifiedDeathChance = baseDeathChance / Math.pow(member.def, 0.6); const modifiedDeathChance = baseDeathChance / Math.pow(member.def, 0.6);
@ -304,14 +283,14 @@ export class Gang {
} }
canRecruitMember(): boolean { canRecruitMember(): boolean {
if (this.members.length >= GangConstants.MaximumGangMembers) { return false; } if (this.members.length >= GangConstants.MaximumGangMembers) return false;
return (this.respect >= this.getRespectNeededToRecruitMember()); return (this.respect >= this.getRespectNeededToRecruitMember());
} }
getRespectNeededToRecruitMember(): number { getRespectNeededToRecruitMember(): number {
// First N gang members are free (can be recruited at 0 respect) // First N gang members are free (can be recruited at 0 respect)
const numFreeMembers = 3; const numFreeMembers = 3;
if (this.members.length < numFreeMembers) { return 0; } if (this.members.length < numFreeMembers) return 0;
const i = this.members.length - (numFreeMembers - 1); const i = this.members.length - (numFreeMembers - 1);
return Math.round(0.9 * Math.pow(i, 3) + Math.pow(i, 2)); return Math.round(0.9 * Math.pow(i, 3) + Math.pow(i, 2));
@ -319,13 +298,11 @@ export class Gang {
recruitMember(name: string): boolean { recruitMember(name: string): boolean {
name = String(name); name = String(name);
if (name === "" || !this.canRecruitMember()) { return false; } if (name === "" || !this.canRecruitMember()) return false;
// Check for already-existing names // Check for already-existing names
const sameNames = this.members.filter((m) => { const sameNames = this.members.filter((m) => m.name === name);
return m.name === name; if (sameNames.length >= 1) return false;
});
if (sameNames.length >= 1) { return false; }
const member = new GangMember(name); const member = new GangMember(name);
this.members.push(member); this.members.push(member);
@ -342,10 +319,9 @@ export class Gang {
calculatePower(): number { calculatePower(): number {
let memberTotal = 0; let memberTotal = 0;
for (let i = 0; i < this.members.length; ++i) { for (let i = 0; i < this.members.length; ++i) {
if (GangMemberTasks.hasOwnProperty(this.members[i].task) && this.members[i].task == "Territory Warfare") { if (!GangMemberTasks.hasOwnProperty(this.members[i].task) ||
const gain = this.members[i].calculatePower(); this.members[i].task !== "Territory Warfare") continue;
memberTotal += gain; memberTotal += this.members[i].calculatePower();
}
} }
return (0.015 * this.getTerritory() * memberTotal); return (0.015 * this.getTerritory() * memberTotal);
} }
@ -368,7 +344,6 @@ export class Gang {
if (this.notifyMemberDeath) { if (this.notifyMemberDeath) {
dialogBoxCreate(`${member.name} was killed in a gang clash! You lost ${lostRespect} respect`); dialogBoxCreate(`${member.name} was killed in a gang clash! You lost ${lostRespect} respect`);
} }
} }
ascendMember(member: GangMember, workerScript?: WorkerScript): IAscensionResult { ascendMember(member: GangMember, workerScript?: WorkerScript): IAscensionResult {
@ -406,33 +381,26 @@ export class Gang {
const respectLinearFac = 5e6; const respectLinearFac = 5e6;
const powerLinearFac = 1e6; const powerLinearFac = 1e6;
const discount = Math.pow(respect, 0.01) + respect / respectLinearFac + Math.pow(power, 0.01) + power / powerLinearFac - 1; const discount = Math.pow(respect, 0.01) +
respect / respectLinearFac +
Math.pow(power, 0.01) +
power / powerLinearFac - 1;
return Math.max(1, discount); return Math.max(1, discount);
} }
// Returns only valid tasks for this gang. Excludes 'Unassigned' // Returns only valid tasks for this gang. Excludes 'Unassigned'
getAllTaskNames(): string[] { getAllTaskNames(): string[] {
let tasks = []; return Object.keys(GangMemberTasks).filter((taskName: string) => {
const allTasks = Object.keys(GangMemberTasks); const task = GangMemberTasks[taskName];
if (this.isHackingGang) { if (task == null) return false;
tasks = allTasks.filter((e) => { if (task.name === "Unassigned") return false;
const task = GangMemberTasks[e]; // yes you need both checks
if (task == null) { return false; } return this.isHackingGang === task.isHacking ||
if (e === "Unassigned") { return false; } !this.isHackingGang === task.isCombat;
return task.isHacking; });
});
} else {
tasks = allTasks.filter((e) => {
const task = GangMemberTasks[e];
if (task == null) { return false; }
if (e === "Unassigned") { return false; }
return task.isCombat;
});
}
return tasks;
} }
getUpgradeCost(upg: GangMemberUpgrade): number { getUpgradeCost(upg: GangMemberUpgrade | null): number {
if (upg == null) { return Infinity; } if (upg == null) { return Infinity; }
return upg.cost/this.getDiscount(); return upg.cost/this.getDiscount();
} }

@ -73,7 +73,12 @@ export class GangMember {
} }
calculatePower(): number { calculatePower(): number {
return (this.hack + this.str + this.def + this.dex + this.agi + this.cha) / 95; return (this.hack +
this.str +
this.def +
this.dex +
this.agi +
this.cha) / 95;
} }
assignToTask(taskName: string): boolean { assignToTask(taskName: string): boolean {
@ -134,13 +139,12 @@ export class GangMember {
if (isNaN(territoryMult) || territoryMult <= 0) return 0; if (isNaN(territoryMult) || territoryMult <= 0) return 0;
if (task.baseWanted < 0) { if (task.baseWanted < 0) {
return 0.4 * task.baseWanted * statWeight * territoryMult; return 0.4 * task.baseWanted * statWeight * territoryMult;
} else {
const calc = 7 * task.baseWanted / (Math.pow(3 * statWeight * territoryMult, 0.8));
// Put an arbitrary cap on this to prevent wanted level from rising too fast if the
// denominator is very small. Might want to rethink formula later
return Math.min(100, calc);
} }
const calc = 7 * task.baseWanted / (Math.pow(3 * statWeight * territoryMult, 0.8));
// Put an arbitrary cap on this to prevent wanted level from rising too fast if the
// denominator is very small. Might want to rethink formula later
return Math.min(100, calc);
} }
calculateMoneyGain(gang: IGang): number { calculateMoneyGain(gang: IGang): number {
@ -202,12 +206,12 @@ export class GangMember {
let cha = 1; let cha = 1;
for (let i = 0; i < this.upgrades.length; ++i) { for (let i = 0; i < this.upgrades.length; ++i) {
const upg = GangMemberUpgrades[this.upgrades[i]]; const upg = GangMemberUpgrades[this.upgrades[i]];
if (upg.mults.hack != null) { hack *= upg.mults.hack; } if (upg.mults.hack != null) hack *= upg.mults.hack;
if (upg.mults.str != null) { str *= upg.mults.str; } if (upg.mults.str != null) str *= upg.mults.str;
if (upg.mults.def != null) { def *= upg.mults.def; } if (upg.mults.def != null) def *= upg.mults.def;
if (upg.mults.dex != null) { dex *= upg.mults.dex; } if (upg.mults.dex != null) dex *= upg.mults.dex;
if (upg.mults.agi != null) { agi *= upg.mults.agi; } if (upg.mults.agi != null) agi *= upg.mults.agi;
if (upg.mults.cha != null) { cha *= upg.mults.cha; } if (upg.mults.cha != null) cha *= upg.mults.cha;
} }
// Subtract 1 because we're only interested in the actual "bonus" part // Subtract 1 because we're only interested in the actual "bonus" part
@ -287,21 +291,20 @@ export class GangMember {
} }
applyUpgrade(upg: GangMemberUpgrade): void { applyUpgrade(upg: GangMemberUpgrade): void {
if (upg.mults.str != null) { this.str_mult *= upg.mults.str; } if (upg.mults.str != null) this.str_mult *= upg.mults.str;
if (upg.mults.def != null) { this.def_mult *= upg.mults.def; } if (upg.mults.def != null) this.def_mult *= upg.mults.def;
if (upg.mults.dex != null) { this.dex_mult *= upg.mults.dex; } if (upg.mults.dex != null) this.dex_mult *= upg.mults.dex;
if (upg.mults.agi != null) { this.agi_mult *= upg.mults.agi; } if (upg.mults.agi != null) this.agi_mult *= upg.mults.agi;
if (upg.mults.cha != null) { this.cha_mult *= upg.mults.cha; } if (upg.mults.cha != null) this.cha_mult *= upg.mults.cha;
if (upg.mults.hack != null) { this.hack_mult *= upg.mults.hack; } if (upg.mults.hack != null) this.hack_mult *= upg.mults.hack;
} }
buyUpgrade(upg: GangMemberUpgrade, player: IPlayer, gang: IGang): boolean { buyUpgrade(upg: GangMemberUpgrade, player: IPlayer, gang: IGang): boolean {
// Prevent purchasing of already-owned upgrades // Prevent purchasing of already-owned upgrades
if (this.augmentations.includes(upg.name) || this.upgrades.includes(upg.name)) { if (this.augmentations.includes(upg.name) ||
return false; this.upgrades.includes(upg.name)) return false;
}
if (player.money.lt(gang.getUpgradeCost(upg))) { return false; } if (player.money.lt(gang.getUpgradeCost(upg))) return false;
player.loseMoney(gang.getUpgradeCost(upg)); player.loseMoney(gang.getUpgradeCost(upg));
if (upg.type === "g") { if (upg.type === "g") {
this.augmentations.push(upg.name); this.augmentations.push(upg.name);