BLADEBURNER: Fix NaN in getSuccessRange (#1394)

This commit is contained in:
catloversg 2024-06-14 13:48:50 +07:00 committed by GitHub
parent a12056a898
commit 417d420793
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 28 additions and 17 deletions

@ -8,6 +8,7 @@ import { BladeburnerConstants } from "../data/Constants";
import { calculateIntelligenceBonus } from "../../PersonObjects/formulas/intelligence"; import { calculateIntelligenceBonus } from "../../PersonObjects/formulas/intelligence";
import { BladeMultName } from "../Enums"; import { BladeMultName } from "../Enums";
import { getRecordKeys } from "../../Types/Record"; import { getRecordKeys } from "../../Types/Record";
import { clampNumber } from "../../utils/helpers/clampNumber";
export interface ActionParams { export interface ActionParams {
desc: string; desc: string;
@ -146,9 +147,16 @@ export abstract class ActionClass {
let high = real + diff; let high = real + diff;
const city = bladeburner.getCurrentCity(); const city = bladeburner.getCurrentCity();
let r = city.pop / city.popEst; let r = city.pop / city.popEst;
if (Number.isNaN(r)) r = 0; if (Number.isNaN(r)) {
if (r < 1) low *= r; r = 0;
else high *= r; }
if (r < 1) {
low *= r;
} else {
// We need to "clamp" r with "clampNumber" (not "clamp"), otherwise (high *= r) may be NaN. This happens when the
// action is Raid, popEst=0, and comms=0.
high *= clampNumber(r);
}
return [clamp(low), clamp(high)]; return [clamp(low), clamp(high)];
} }

@ -34,18 +34,20 @@ export class BlackOperation extends ActionClass {
if (bladeburner.rank < this.reqdRank) return { error: "Insufficient rank" }; if (bladeburner.rank < this.reqdRank) return { error: "Insufficient rank" };
return { available: true }; return { available: true };
} }
// To be implemented by subtypes
getActionTimePenalty(): number { getActionTimePenalty(): number {
return 1.5; return 1.5;
} }
getPopulationSuccessFactor(/*inst: Bladeburner, params: ISuccessChanceParams*/): number { getPopulationSuccessFactor(): number {
return 1; return 1;
} }
getChaosSuccessFactor(/*inst: Bladeburner, params: ISuccessChanceParams*/): number { getChaosSuccessFactor(): number {
return 1; return 1;
} }
getTeamSuccessBonus = operationTeamSuccessBonus; getTeamSuccessBonus = operationTeamSuccessBonus;
getActionTypeSkillSuccessBonus = operationSkillSuccessBonus; getActionTypeSkillSuccessBonus = operationSkillSuccessBonus;
} }

@ -32,6 +32,7 @@ export class Operation extends LevelableActionClass {
// These functions are shared between operations and blackops, so they are defined outside of Operation // These functions are shared between operations and blackops, so they are defined outside of Operation
getTeamSuccessBonus = operationTeamSuccessBonus; getTeamSuccessBonus = operationTeamSuccessBonus;
getActionTypeSkillSuccessBonus = operationSkillSuccessBonus; getActionTypeSkillSuccessBonus = operationSkillSuccessBonus;
getChaosSuccessFactor(inst: Bladeburner /*, params: ISuccessChanceParams*/): number { getChaosSuccessFactor(inst: Bladeburner /*, params: ISuccessChanceParams*/): number {
@ -45,7 +46,9 @@ export class Operation extends LevelableActionClass {
return 1; return 1;
} }
getSuccessChance(inst: Bladeburner, person: Person, params: SuccessChanceParams) { getSuccessChance(inst: Bladeburner, person: Person, params: SuccessChanceParams) {
if (this.name == BladeOperationName.raid && inst.getCurrentCity().comms <= 0) return 0; if (this.name === BladeOperationName.raid && inst.getCurrentCity().comms <= 0) {
return 0;
}
return ActionClass.prototype.getSuccessChance.call(this, inst, person, params); return ActionClass.prototype.getSuccessChance.call(this, inst, person, params);
} }
@ -57,6 +60,7 @@ export class Operation extends LevelableActionClass {
toJSON(): IReviverValue { toJSON(): IReviverValue {
return this.save("Operation", "teamCount"); return this.save("Operation", "teamCount");
} }
loadData(loadedObject: Operation): void { loadData(loadedObject: Operation): void {
this.teamCount = clampInteger(loadedObject.teamCount, 0); this.teamCount = clampInteger(loadedObject.teamCount, 0);
LevelableActionClass.prototype.loadData.call(this, loadedObject); LevelableActionClass.prototype.loadData.call(this, loadedObject);
@ -73,6 +77,7 @@ constructorsForReviver.Operation = Operation;
export const operationSkillSuccessBonus = (inst: Bladeburner) => { export const operationSkillSuccessBonus = (inst: Bladeburner) => {
return inst.getSkillMult(BladeMultName.successChanceOperation); return inst.getSkillMult(BladeMultName.successChanceOperation);
}; };
export function operationTeamSuccessBonus(this: Operation | BlackOperation, inst: Bladeburner) { export function operationTeamSuccessBonus(this: Operation | BlackOperation, inst: Bladeburner) {
if (this.teamCount && this.teamCount > 0) { if (this.teamCount && this.teamCount > 0) {
this.teamCount = Math.min(this.teamCount, inst.teamSize); this.teamCount = Math.min(this.teamCount, inst.teamSize);

@ -125,7 +125,7 @@ export class Bladeburner {
startAction(actionId: ActionIdentifier | null): Attempt<{ message: string }> { startAction(actionId: ActionIdentifier | null): Attempt<{ message: string }> {
if (!actionId) { if (!actionId) {
this.resetAction(); this.resetAction();
return { success: true, message: "Stopped current bladeburner action" }; return { success: true, message: "Stopped current Bladeburner action" };
} }
if (!Player.hasAugmentation(AugmentationName.BladesSimulacrum, true)) Player.finishWork(true); if (!Player.hasAugmentation(AugmentationName.BladesSimulacrum, true)) Player.finishWork(true);
const action = this.getActionObject(actionId); const action = this.getActionObject(actionId);

@ -20,7 +20,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
const getBladeburner = function (ctx: NetscriptContext): Bladeburner { const getBladeburner = function (ctx: NetscriptContext): Bladeburner {
const apiAccess = Player.bitNodeN === 7 || Player.sourceFileLvl(7) > 0; const apiAccess = Player.bitNodeN === 7 || Player.sourceFileLvl(7) > 0;
if (!apiAccess) { if (!apiAccess) {
throw helpers.errorMessage(ctx, "You have not unlocked the bladeburner API.", "API ACCESS"); throw helpers.errorMessage(ctx, "You have not unlocked the Bladeburner API.", "API ACCESS");
} }
const bladeburner = Player.bladeburner; const bladeburner = Player.bladeburner;
if (!bladeburner) if (!bladeburner)
@ -112,14 +112,10 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
}, },
getActionCurrentTime: (ctx) => () => { getActionCurrentTime: (ctx) => () => {
const bladeburner = getBladeburner(ctx); const bladeburner = getBladeburner(ctx);
try { return (
const timecomputed = Math.min(bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, bladeburner.actionTimeToComplete) *
Math.min(bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, bladeburner.actionTimeToComplete) * 1000
1000; );
return timecomputed;
} catch (e: unknown) {
throw helpers.errorMessage(ctx, String(e));
}
}, },
getActionEstimatedSuccessChance: (ctx) => (type, name) => { getActionEstimatedSuccessChance: (ctx) => (type, name) => {
const bladeburner = getBladeburner(ctx); const bladeburner = getBladeburner(ctx);