Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUGFIX: Wrong calculation in team casualties of Bladeburner action #1672

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 27 additions & 18 deletions src/Bladeburner/Actions/TeamCasualties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,31 @@ export interface TeamActionWithCasualties {
* and may result in casualties, reducing the player's hp, killing team members
* and killing sleeves (to shock them, sleeves are immortal) *
*/
export function resolveTeamCasualties(action: TeamActionWithCasualties, team: OperationTeam, success: boolean) {
const severity = success ? CasualtyFactor.LOW_CASUALTIES : CasualtyFactor.HIGH_CASUALTIES;
const radius = action.teamCount * severity;
const worstCase = severity < 1 ? Math.ceil(radius) : Math.floor(radius);
/** Best case is always no deaths */
const deaths = team.getTeamCasualtiesRoll(action.getMinimumCasualties(), worstCase);
const humans = action.teamCount - team.sleeveSize;
const humanDeaths = Math.min(humans, deaths);
/** Supporting Sleeves take damage when they are part of losses,
* e.g. 8 sleeves + 3 team members with 4 losses -> 1 sleeve takes damage */
team.killRandomSupportingSleeves(deaths - humanDeaths);

/** Clamped, bugfix for PR#1659
* "BUGFIX: Wrong team size when all team members die in Bladeburner's action" */
team.teamSize = Math.max(team.teamSize - humanDeaths, team.sleeveSize);
team.teamLost += deaths;

return deaths;
export function resolveTeamCasualties(action: TeamActionWithCasualties, team: OperationTeam, success: boolean): number {
catloversg marked this conversation as resolved.
Show resolved Hide resolved
if (action.teamCount <= 0) {
return 0;
}

// Operation actions and Black Operation actions have different min casualties: Min of Ops = 0. Min of BlackOps = 1.
const minCasualties = action.getMinimumCasualties();
const maxCasualties = success
? Math.ceil(action.teamCount * CasualtyFactor.LOW_CASUALTIES)
: Math.floor(action.teamCount * CasualtyFactor.HIGH_CASUALTIES);
/**
* In the current state, it's safe to assume that minCasualties <= maxCasualties. However, in the future, if we change
* min casualties, LOW_CASUALTIES, or HIGH_CASUALTIES, the call of getTeamCasualtiesRoll may crash.
* getTeamCasualtiesRoll is just getRandomIntInclusive, and that function's parameters need to be in the form of
* (min, max).
*/
const losses =
minCasualties <= maxCasualties ? team.getTeamCasualtiesRoll(minCasualties, maxCasualties) : minCasualties;
team.teamSize -= losses;
if (team.teamSize < team.sleeveSize) {
team.killRandomSupportingSleeves(team.sleeveSize - team.teamSize);
// If this happens, all team members died and some sleeves took damage. In this case, teamSize = sleeveSize.
team.teamSize = team.sleeveSize;
}
team.teamLost += losses;

return losses;
}
11 changes: 10 additions & 1 deletion test/jest/Bladeburner/TeamCasualties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { PlayerObject } from "../../../src/PersonObjects/Player/PlayerObject";
*/
describe("Bladeburner Team", () => {
const MAX_ROLL = (_: number, high: number) => high;
const MIN_ROLL = (low: number, _: number) => low;
const MIN_ROLL = (low: number, __: number) => low;
const BLACK_OP = BlackOperation.createId(BladeburnerBlackOpName.OperationAnnihilus);
const OP = Operation.createId(BladeburnerOperationName.Assassination);

Expand Down Expand Up @@ -96,6 +96,15 @@ describe("Bladeburner Team", () => {
});

describe("Casualties", () => {
it.each([[OP], [BLACK_OP]])(
"no change in team size when not using team. Action: %s",
catloversg marked this conversation as resolved.
Show resolved Hide resolved
(op: ActionIdFor<BlackOperation> | ActionIdFor<Operation>) => {
teamSize(0), supportingSleeves(3), startAction(op), teamUsed(0), actionFails();
expect(inst.teamSize).toBe(3);
expect(inst.teamLost).toBe(0);
},
);

it("do not affect contracts", () => {
teamSize(3);
inst.action = Contract.createId(BladeburnerContractName.Tracking);
Expand Down