diff --git a/src/Gang/Gang.ts b/src/Gang/Gang.ts index c4acf3963..409dd195b 100644 --- a/src/Gang/Gang.ts +++ b/src/Gang/Gang.ts @@ -350,19 +350,7 @@ export class Gang { try { const res = member.ascend(); this.respect = Math.max(1, this.respect - res.respect); - if (workerScript == null) { - dialogBoxCreate([`You ascended ${member.name}!`, - "", - `Your gang lost ${numeralWrapper.formatRespect(res.respect)} respect`, - "", - `${member.name} gained the following stat multipliers for ascending:`, - `Hacking: ${numeralWrapper.formatPercentage(res.hack, 3)}`, - `Strength: ${numeralWrapper.formatPercentage(res.str, 3)}`, - `Defense: ${numeralWrapper.formatPercentage(res.def, 3)}`, - `Dexterity: ${numeralWrapper.formatPercentage(res.dex, 3)}`, - `Agility: ${numeralWrapper.formatPercentage(res.agi, 3)}`, - `Charisma: ${numeralWrapper.formatPercentage(res.cha, 3)}`].join("
")); - } else { + if (workerScript) { workerScript.log('ascend', `Ascended Gang member ${member.name}`); } return res; diff --git a/src/Gang/GangMember.ts b/src/Gang/GangMember.ts index 53157d415..dac6fe5b9 100644 --- a/src/Gang/GangMember.ts +++ b/src/Gang/GangMember.ts @@ -45,12 +45,12 @@ export class GangMember { agi_mult = 1; cha_mult = 1; - hack_asc_mult = 1; - str_asc_mult = 1; - def_asc_mult = 1; - dex_asc_mult = 1; - agi_asc_mult = 1; - cha_asc_mult = 1; + hack_asc_points = 0; + str_asc_points = 0; + def_asc_points = 0; + dex_asc_points = 0; + agi_asc_points = 0; + cha_asc_points = 0; upgrades: string[] = []; // Names of upgrades augmentations: string[] = []; // Names of augmentations only @@ -63,13 +63,17 @@ export class GangMember { return Math.max(Math.floor(mult * (32 * Math.log(exp + 534.5) - 200)), 1); } + calculateAscensionMult(points: number): number { + return Math.max(Math.pow(points/2000, 0.9), 1); + } + updateSkillLevels(): void { - this.hack = this.calculateSkill(this.hack_exp, this.hack_mult * this.hack_asc_mult); - this.str = this.calculateSkill(this.str_exp, this.str_mult * this.str_asc_mult); - this.def = this.calculateSkill(this.def_exp, this.def_mult * this.def_asc_mult); - this.dex = this.calculateSkill(this.dex_exp, this.dex_mult * this.dex_asc_mult); - this.agi = this.calculateSkill(this.agi_exp, this.agi_mult * this.agi_asc_mult); - this.cha = this.calculateSkill(this.cha_exp, this.cha_mult * this.cha_asc_mult); + this.hack = this.calculateSkill(this.hack_exp, this.hack_mult * this.calculateAscensionMult(this.hack_asc_points)); + this.str = this.calculateSkill(this.str_exp, this.str_mult * this.calculateAscensionMult(this.str_asc_points)); + this.def = this.calculateSkill(this.def_exp, this.def_mult * this.calculateAscensionMult(this.def_asc_points)); + this.dex = this.calculateSkill(this.dex_exp, this.dex_mult * this.calculateAscensionMult(this.dex_asc_points)); + this.agi = this.calculateSkill(this.agi_exp, this.agi_mult * this.calculateAscensionMult(this.agi_asc_points)); + this.cha = this.calculateSkill(this.cha_exp, this.cha_mult * this.calculateAscensionMult(this.cha_asc_points)); } calculatePower(): number { @@ -194,25 +198,47 @@ export class GangMember { this.earnedRespect += (this.calculateRespectGain(gang) * numCycles); } - getAscensionResults(): IMults { + getGainedAscensionPoints(): IMults { return { - hack: this.hack_exp, - str: this.str_exp, - def: this.def_exp, - dex: this.dex_exp, - agi: this.agi_exp, - cha: this.cha_exp, + hack: Math.max(this.hack_exp - 1000, 0), + str: Math.max(this.str_exp - 1000, 0), + def: Math.max(this.def_exp - 1000, 0), + dex: Math.max(this.dex_exp - 1000, 0), + agi: Math.max(this.agi_exp - 1000, 0), + cha: Math.max(this.cha_exp - 1000, 0), + } + } + + canAscend(): boolean { + const points = this.getGainedAscensionPoints(); + return points.hack > 0 || + points.str > 0 || + points.def > 0 || + points.dex > 0 || + points.agi > 0 || + points.cha > 0; + } + + getAscensionResults(): IMults { + const points = this.getGainedAscensionPoints(); + return { + hack: this.calculateAscensionMult(this.hack_asc_points+points.hack)/this.calculateAscensionMult(this.hack_asc_points), + str: this.calculateAscensionMult(this.str_asc_points+points.str)/this.calculateAscensionMult(this.str_asc_points), + def: this.calculateAscensionMult(this.def_asc_points+points.def)/this.calculateAscensionMult(this.def_asc_points), + dex: this.calculateAscensionMult(this.dex_asc_points+points.dex)/this.calculateAscensionMult(this.dex_asc_points), + agi: this.calculateAscensionMult(this.agi_asc_points+points.agi)/this.calculateAscensionMult(this.agi_asc_points), + cha: this.calculateAscensionMult(this.cha_asc_points+points.cha)/this.calculateAscensionMult(this.cha_asc_points), } } ascend(): IAscensionResult { const res = this.getAscensionResults(); - this.hack_asc_mult += res.hack; - this.str_asc_mult += res.str; - this.def_asc_mult += res.def; - this.dex_asc_mult += res.dex; - this.agi_asc_mult += res.agi; - this.cha_asc_mult += res.cha; + this.hack_asc_points += this.hack_exp; + this.str_asc_points += this.str_exp; + this.def_asc_points += this.def_exp; + this.dex_asc_points += this.dex_exp; + this.agi_asc_points += this.agi_exp; + this.cha_asc_points += this.cha_exp; // Remove upgrades. Then re-calculate multipliers and stats this.upgrades.length = 0; diff --git a/src/Gang/data/tasks.ts b/src/Gang/data/tasks.ts index c5d83e7c8..dc14a0fd7 100644 --- a/src/Gang/data/tasks.ts +++ b/src/Gang/data/tasks.ts @@ -255,7 +255,7 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [ name: "Train Combat", params: { strWeight: 25, defWeight: 25, dexWeight: 25, agiWeight: 25, - difficulty: 200, + difficulty: 100, }, }, { diff --git a/src/Gang/ui/AscensionPopup.tsx b/src/Gang/ui/AscensionPopup.tsx index d2e1f1d8d..ce3954192 100644 --- a/src/Gang/ui/AscensionPopup.tsx +++ b/src/Gang/ui/AscensionPopup.tsx @@ -2,11 +2,12 @@ * React Component for the content of the popup before the player confirms the * ascension of a gang member. */ -import React from "react"; +import React, { useState, useEffect } from "react"; import { Gang } from "../Gang"; import { GangMember } from "../GangMember"; import { numeralWrapper } from "../../ui/numeralFormat"; import { removePopup } from "../../ui/React/createPopup"; +import { dialogBoxCreate } from "../../../utils/DialogBox"; interface IProps { member: GangMember; @@ -16,9 +17,29 @@ interface IProps { } export function AscensionPopup(props: IProps): React.ReactElement { + const setRerender = useState(false)[1]; + + useEffect(() => { + const id = setInterval(() => setRerender(old => !old), 1000); + return () => clearInterval(id); + }, []); + function confirm(): void { - props.gang.ascendMember(props.member); props.onAscend(); + const res = props.gang.ascendMember(props.member); + dialogBoxCreate(

+ You ascended {props.member.name}!
+
+ Your gang lost {numeralWrapper.formatRespect(res.respect)} respect.
+
+ {props.member.name} gained the following stat multipliers for ascending:
+ Hacking: x{numeralWrapper.format(res.hack, '0.000')}
+ Strength: x{numeralWrapper.format(res.str, '0.000')}
+ Defense: x{numeralWrapper.format(res.def, '0.000')}
+ Dexterity: x{numeralWrapper.format(res.dex, '0.000')}
+ Agility: x{numeralWrapper.format(res.agi, '0.000')}
+ Charisma: x{numeralWrapper.format(res.cha, '0.000')}
+

); removePopup(props.popupId); } @@ -36,12 +57,12 @@ their non-Augmentation upgrades and their stats will reset back to 1.
Furthermore, your gang will lose {numeralWrapper.formatRespect(props.member.earnedRespect)} respect

In return, they will gain the following permanent boost to stat multipliers:
-Hacking: +{numeralWrapper.formatPercentage(ascendBenefits.hack/100)}
-Strength: +{numeralWrapper.formatPercentage(ascendBenefits.str/100)}
-Defense: +{numeralWrapper.formatPercentage(ascendBenefits.def/100)}
-Dexterity: +{numeralWrapper.formatPercentage(ascendBenefits.dex/100)}
-Agility: +{numeralWrapper.formatPercentage(ascendBenefits.agi/100)}
-Charisma: +{numeralWrapper.formatPercentage(ascendBenefits.cha/100)}
+Hacking: x{numeralWrapper.format(ascendBenefits.hack, '0.000')}
+Strength: x{numeralWrapper.format(ascendBenefits.str, '0.000')}
+Defense: x{numeralWrapper.format(ascendBenefits.def, '0.000')}
+Dexterity: x{numeralWrapper.format(ascendBenefits.dex, '0.000')}
+Agility: x{numeralWrapper.format(ascendBenefits.agi, '0.000')}
+Charisma: x{numeralWrapper.format(ascendBenefits.cha, '0.000')}
diff --git a/src/Gang/ui/GangMemberStats.tsx b/src/Gang/ui/GangMemberStats.tsx index d67b52e56..e5b4f96c9 100644 --- a/src/Gang/ui/GangMemberStats.tsx +++ b/src/Gang/ui/GangMemberStats.tsx @@ -34,8 +34,7 @@ export function GangMemberStats(props: IProps): React.ReactElement { exchange for a permanent boost to their stat multipliers.

The additional stat multiplier that the Gang Member gains upon - ascension is based on the amount of multipliers the member has from - non-Augmentation Equipment. + ascension is based on the amount of exp they have.

Upon ascension, the member will lose all of its non-Augmentation Equipment and your gang will lose respect equal to the total respect @@ -43,14 +42,23 @@ export function GangMemberStats(props: IProps): React.ReactElement { ); } + const asc = { + hack: props.member.calculateAscensionMult(props.member.hack_asc_points), + str: props.member.calculateAscensionMult(props.member.str_asc_points), + def: props.member.calculateAscensionMult(props.member.def_asc_points), + dex: props.member.calculateAscensionMult(props.member.dex_asc_points), + agi: props.member.calculateAscensionMult(props.member.agi_asc_points), + cha: props.member.calculateAscensionMult(props.member.cha_asc_points), + }; + return (<> -Hk: x{numeralWrapper.formatMultiplier(props.member.hack_mult * props.member.hack_asc_mult)}(x{numeralWrapper.formatMultiplier(props.member.hack_mult)} Eq, x{numeralWrapper.formatMultiplier(props.member.hack_asc_mult)} Asc)
-St: x{numeralWrapper.formatMultiplier(props.member.str_mult * props.member.str_asc_mult)}(x{numeralWrapper.formatMultiplier(props.member.str_mult)} Eq, x{numeralWrapper.formatMultiplier(props.member.str_asc_mult)} Asc)
-Df: x{numeralWrapper.formatMultiplier(props.member.def_mult * props.member.def_asc_mult)}(x{numeralWrapper.formatMultiplier(props.member.def_mult)} Eq, x{numeralWrapper.formatMultiplier(props.member.def_asc_mult)} Asc)
-Dx: x{numeralWrapper.formatMultiplier(props.member.dex_mult * props.member.dex_asc_mult)}(x{numeralWrapper.formatMultiplier(props.member.dex_mult)} Eq, x{numeralWrapper.formatMultiplier(props.member.dex_asc_mult)} Asc)
-Ag: x{numeralWrapper.formatMultiplier(props.member.agi_mult * props.member.agi_asc_mult)}(x{numeralWrapper.formatMultiplier(props.member.agi_mult)} Eq, x{numeralWrapper.formatMultiplier(props.member.agi_asc_mult)} Asc)
-Ch: x{numeralWrapper.formatMultiplier(props.member.cha_mult * props.member.cha_asc_mult)}(x{numeralWrapper.formatMultiplier(props.member.cha_mult)} Eq, x{numeralWrapper.formatMultiplier(props.member.cha_asc_mult)} Asc) +Hk: x{numeralWrapper.formatMultiplier(props.member.hack_mult * asc.hack)}(x{numeralWrapper.formatMultiplier(props.member.hack_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.hack)} Asc)
+St: x{numeralWrapper.formatMultiplier(props.member.str_mult * asc.str)}(x{numeralWrapper.formatMultiplier(props.member.str_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.str)} Asc)
+Df: x{numeralWrapper.formatMultiplier(props.member.def_mult * asc.def)}(x{numeralWrapper.formatMultiplier(props.member.def_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.def)} Asc)
+Dx: x{numeralWrapper.formatMultiplier(props.member.dex_mult * asc.dex)}(x{numeralWrapper.formatMultiplier(props.member.dex_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.dex)} Asc)
+Ag: x{numeralWrapper.formatMultiplier(props.member.agi_mult * asc.agi)}(x{numeralWrapper.formatMultiplier(props.member.agi_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.agi)} Asc)
+Ch: x{numeralWrapper.formatMultiplier(props.member.cha_mult * asc.cha)}(x{numeralWrapper.formatMultiplier(props.member.cha_mult)} Eq, x{numeralWrapper.formatMultiplier(asc.cha)} Asc)
 Hacking: {formatNumber(props.member.hack, 0)} ({numeralWrapper.formatExp(props.member.hack_exp)} exp)
@@ -61,7 +69,9 @@ Agility: {formatNumber(props.member.agi, 0)} ({numeralWrapper.formatExp(props.me Charisma: {formatNumber(props.member.cha, 0)} ({numeralWrapper.formatExp(props.member.cha_exp)} exp)

+ { props.member.canAscend() && <>
?
+ } ); } diff --git a/src/Gang/ui/GangMemberUpgradePopup.tsx b/src/Gang/ui/GangMemberUpgradePopup.tsx index 9a07aeebc..982892adc 100644 --- a/src/Gang/ui/GangMemberUpgradePopup.tsx +++ b/src/Gang/ui/GangMemberUpgradePopup.tsx @@ -56,15 +56,23 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement { ); } + const asc = { + hack: props.member.calculateAscensionMult(props.member.hack_asc_points), + str: props.member.calculateAscensionMult(props.member.str_asc_points), + def: props.member.calculateAscensionMult(props.member.def_asc_points), + dex: props.member.calculateAscensionMult(props.member.dex_asc_points), + agi: props.member.calculateAscensionMult(props.member.agi_asc_points), + cha: props.member.calculateAscensionMult(props.member.cha_asc_points), + }; return (

{props.member.name}({props.member.task})

-Hack: {props.member.hack} (x{formatNumber(props.member.hack_mult * props.member.hack_asc_mult, 2)})
-Str: {props.member.str} (x{formatNumber(props.member.str_mult * props.member.str_asc_mult, 2)})
-Def: {props.member.def} (x{formatNumber(props.member.def_mult * props.member.def_asc_mult, 2)})
-Dex: {props.member.dex} (x{formatNumber(props.member.dex_mult * props.member.dex_asc_mult, 2)})
-Agi: {props.member.agi} (x{formatNumber(props.member.agi_mult * props.member.agi_asc_mult, 2)})
-Cha: {props.member.cha} (x{formatNumber(props.member.cha_mult * props.member.cha_asc_mult, 2)}) +Hack: {props.member.hack} (x{formatNumber(props.member.hack_mult * asc.hack, 2)})
+Str: {props.member.str} (x{formatNumber(props.member.str_mult * asc.str, 2)})
+Def: {props.member.def} (x{formatNumber(props.member.def_mult * asc.def, 2)})
+Dex: {props.member.dex} (x{formatNumber(props.member.dex_mult * asc.dex, 2)})
+Agi: {props.member.agi} (x{formatNumber(props.member.agi_mult * asc.agi, 2)})
+Cha: {props.member.cha} (x{formatNumber(props.member.cha_mult * asc.cha, 2)})
Purchased Upgrades: {props.member.upgrades.map((upg: string) => purchasedUpgrade(upg))}