diff --git a/src/Bladeburner/Bladeburner.tsx b/src/Bladeburner/Bladeburner.tsx index c57e47beb..1b54b0a3d 100644 --- a/src/Bladeburner/Bladeburner.tsx +++ b/src/Bladeburner/Bladeburner.tsx @@ -994,7 +994,7 @@ export class Bladeburner implements IBladeburner { * @param action(Action obj) - Derived action class * @param success(bool) - Whether action was successful */ - getActionStats(action: IAction, success: boolean): ITaskTracker { + getActionStats(action: IAction, person: IPerson, success: boolean): ITaskTracker { const difficulty = action.getDifficulty(); /** @@ -1005,7 +1005,7 @@ export class Bladeburner implements IBladeburner { Math.pow(difficulty, BladeburnerConstants.DiffMultExponentialFactor) + difficulty / BladeburnerConstants.DiffMultLinearFactor; - const time = this.actionTimeToComplete; + const time = action.getActionTime(this, person); const successMult = success ? 1 : 0.5; const unweightedGain = time * BladeburnerConstants.BaseStatGain * successMult * difficultyMult; @@ -1283,7 +1283,7 @@ export class Bladeburner implements IBladeburner { // Process Contract/Operation success/failure if (action.attempt(this, person)) { - retValue = this.getActionStats(action, true); + retValue = this.getActionStats(action, person, true); ++action.successes; --action.count; @@ -1323,7 +1323,7 @@ export class Bladeburner implements IBladeburner { } isOperation ? this.completeOperation(true, player) : this.completeContract(true, actionIdent); } else { - retValue = this.getActionStats(action, false); + retValue = this.getActionStats(action, person, false); ++action.failures; let loss = 0, damage = 0; @@ -1386,7 +1386,7 @@ export class Bladeburner implements IBladeburner { let teamLossMax; if (action.attempt(this, person)) { - retValue = this.getActionStats(action, true); + retValue = this.getActionStats(action, person, true); action.count = 0; this.blackops[action.name] = true; let rankGain = 0; diff --git a/src/Bladeburner/IBladeburner.ts b/src/Bladeburner/IBladeburner.ts index cb78d3abc..f8113ef1c 100644 --- a/src/Bladeburner/IBladeburner.ts +++ b/src/Bladeburner/IBladeburner.ts @@ -116,6 +116,6 @@ export interface IBladeburner { calculateMaxStamina(player: IPlayer): void; create(): void; process(router: IRouter, player: IPlayer): void; - getActionStats(action: IAction, success: boolean): ITaskTracker; + getActionStats(action: IAction, person: IPerson, success: boolean): ITaskTracker; sleeveSupport(joining: boolean): void; } diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts index cf40155a5..ef9031473 100644 --- a/src/PersonObjects/Sleeve/Sleeve.ts +++ b/src/PersonObjects/Sleeve/Sleeve.ts @@ -485,7 +485,7 @@ export class Sleeve extends Person { this.hp.current -= amt; if (this.hp.current <= 0) { - this.shock = Math.min(1, this.shock - 0.5); + this.shock = Math.max(0, this.shock - 0.5); this.hp.current = this.hp.max; return true; } else { diff --git a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts index 208592e45..198357a98 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts @@ -34,16 +34,35 @@ export class SleeveBladeburnerWork extends Work { process(player: IPlayer, sleeve: Sleeve, cycles: number): number { if (!player.bladeburner) throw new Error("sleeve doing blade work without being a member"); this.cyclesWorked += cycles; + const actionIdent = player.bladeburner.getActionIdFromTypeAndName(this.actionType, this.actionName); + if (!actionIdent) throw new Error(`Error getting ${this.actionName} action`); + if (this.actionType === "Contracts") { + const action = player.bladeburner.getActionObject(actionIdent); + if (!action) throw new Error(`Error getting ${this.actionName} action object`); + if (action.count <= 0) { + sleeve.stopWork(player); + return 0; + } + } + while (this.cyclesWorked > this.cyclesNeeded(player, sleeve)) { - const actionIdent = player.bladeburner.getActionIdFromTypeAndName(this.actionType, this.actionName); - if (!actionIdent) throw new Error(`Error getting ${this.actionName} action`); - player.bladeburner.completeAction(player, sleeve, actionIdent, false); + if (this.actionType === "Contracts") { + const action = player.bladeburner.getActionObject(actionIdent); + if (!action) throw new Error(`Error getting ${this.actionName} action object`); + if (action.count <= 0) { + sleeve.stopWork(player); + return 0; + } + } + const retValue = player.bladeburner.completeAction(player, sleeve, actionIdent, false); let exp: WorkStats | undefined; if (this.actionType === "General") { exp = GeneralActions[this.actionName]?.exp; if (!exp) throw new Error(`Somehow there was no exp for action ${this.actionType} ${this.actionName}`); applySleeveGains(player, sleeve, exp, 1); } + player.gainMoney(retValue.money, "sleeves"); + player.gainStats(retValue); this.cyclesWorked -= this.cyclesNeeded(player, sleeve); } return 0; diff --git a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts index 5610af6f9..30aa8c847 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts @@ -64,6 +64,7 @@ export class SleeveCrimeWork extends Work { APICopy(): Record { return { type: this.type, + crimeType: this.crimeType, }; } diff --git a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts index 0cc7b5bae..398374f37 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts @@ -13,6 +13,7 @@ import { getHackingWorkRepGain, } from "../../../PersonObjects/formulas/reputation"; import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats"; +import { BitNodeMultipliers } from "../../../BitNode/BitNodeMultipliers"; interface SleeveFactionWorkParams { factionWorkType: FactionWorkType; @@ -43,7 +44,11 @@ export class SleeveFactionWork extends Work { [FactionWorkType.FIELD]: getFactionFieldWorkRepGain, [FactionWorkType.SECURITY]: getFactionSecurityWorkRepGain, }; - return repFormulas[this.factionWorkType](sleeve, faction.favor) * sleeve.shockBonus(); + return ( + repFormulas[this.factionWorkType](sleeve, faction.favor) * + sleeve.shockBonus() * + BitNodeMultipliers.FactionWorkRepGain + ); } getFaction(): Faction { diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx index 811647f01..542988092 100644 --- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx +++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx @@ -16,6 +16,7 @@ import { isSleeveClassWork } from "../Work/SleeveClassWork"; import { isSleeveFactionWork } from "../Work/SleeveFactionWork"; import { isSleeveCompanyWork } from "../Work/SleeveCompanyWork"; import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork"; +import { BitNodeMultipliers } from "../../../BitNode/BitNodeMultipliers"; interface IProps { sleeve: Sleeve; @@ -101,12 +102,12 @@ export function EarningsElement(props: IProps): React.ReactElement { const gains = props.sleeve.currentWork.getExp(); data = [ [`Money:`, ], - [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * gains.hackExp)}`], - [`Strength Exp:`, `${numeralWrapper.formatExp(5 * gains.strExp)}`], - [`Defense Exp:`, `${numeralWrapper.formatExp(5 * gains.defExp)}`], - [`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * gains.dexExp)}`], - [`Agility Exp:`, `${numeralWrapper.formatExp(5 * gains.agiExp)}`], - [`Charisma Exp:`, `${numeralWrapper.formatExp(5 * gains.chaExp)}`], + [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * gains.hackExp * BitNodeMultipliers.CrimeExpGain)}`], + [`Strength Exp:`, `${numeralWrapper.formatExp(5 * gains.strExp * BitNodeMultipliers.CrimeExpGain)}`], + [`Defense Exp:`, `${numeralWrapper.formatExp(5 * gains.defExp * BitNodeMultipliers.CrimeExpGain)}`], + [`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * gains.dexExp * BitNodeMultipliers.CrimeExpGain)}`], + [`Agility Exp:`, `${numeralWrapper.formatExp(5 * gains.agiExp * BitNodeMultipliers.CrimeExpGain)}`], + [`Charisma Exp:`, `${numeralWrapper.formatExp(5 * gains.chaExp * BitNodeMultipliers.CrimeExpGain)}`], ]; } if (isSleeveClassWork(props.sleeve.currentWork)) { @@ -131,14 +132,14 @@ export function EarningsElement(props: IProps): React.ReactElement { [`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * rates.dexExp)} / sec`], [`Agility Exp:`, `${numeralWrapper.formatExp(5 * rates.agiExp)} / sec`], [`Charisma Exp:`, `${numeralWrapper.formatExp(5 * rates.chaExp)} / sec`], - [`Reputation:`, ], + [`Reputation:`, ], ]; } if (isSleeveCompanyWork(props.sleeve.currentWork)) { const rates = props.sleeve.currentWork.getGainRates(player, props.sleeve); data = [ - [`Money:`, ], + [`Money:`, ], [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * rates.hackExp)} / sec`], [`Strength Exp:`, `${numeralWrapper.formatExp(5 * rates.strExp)} / sec`], [`Defense Exp:`, `${numeralWrapper.formatExp(5 * rates.defExp)} / sec`],