Skip to content

Commit

Permalink
Merge pull request #55 from OGoodness/GrabThrow
Browse files Browse the repository at this point in the history
Grab/Throw Stats. Updated handleActionCompute() -- Correct branch
  • Loading branch information
vinceau authored Apr 14, 2021
2 parents 85fe431 + b8b9a2f commit b351183
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 12 deletions.
Binary file added slp/throwGrab.slp
Binary file not shown.
41 changes: 35 additions & 6 deletions src/stats/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,20 @@ export class ActionsComputer implements StatComputer<ActionCountsType[]> {
spotDodgeCount: 0,
ledgegrabCount: 0,
rollCount: 0,
lCancelSuccessCount: 0,
lCancelFailCount: 0,
lCancelCount: {
success: 0,
fail: 0,
},
grabCount: {
success: 0,
fail: 0,
},
throwCount: {
up: 0,
forward: 0,
back: 0,
down: 0,
},
};
const playerState: PlayerActionState = {
playerCounts: playerCounts,
Expand Down Expand Up @@ -71,6 +83,13 @@ function isSpotDodging(animation: State): boolean {
return animation === State.SPOT_DODGE;
}

function didStartGrabSuccess(currentAnimation: State, previousAnimation: State): boolean {
return previousAnimation === State.GRAB && currentAnimation <= State.GRAB_WAIT && currentAnimation > State.GRAB;
}
function didStartGrabFail(currentAnimation: State, previousAnimation: State): boolean {
return previousAnimation === State.GRAB && (currentAnimation > State.GRAB_WAIT || currentAnimation < State.GRAB);
}

function didStartSpotDodge(currentAnimation: State, previousAnimation: State): boolean {
const isCurrentlyDodging = isSpotDodging(currentAnimation);
const wasPreviouslyDodging = isSpotDodging(previousAnimation);
Expand Down Expand Up @@ -111,8 +130,7 @@ function handleActionCompute(state: PlayerActionState, playerIndex: number, fram
return;
}

// FIXME: ActionsCountsType should be a map of actions -> number, instead of accessing the field via string
(state.playerCounts as any)[field] += 1;
_.update(state.playerCounts, field, (n) => n + 1);
};

// Manage animation state
Expand All @@ -122,6 +140,7 @@ function handleActionCompute(state: PlayerActionState, playerIndex: number, fram
// Grab last 3 frames
const last3Frames = state.animations.slice(-3);
const prevAnimation = last3Frames[last3Frames.length - 2];
const newAnimation = currentAnimation !== prevAnimation;

// Increment counts based on conditions
const didDashDance = _.isEqual(last3Frames, dashDanceAnimations);
Expand All @@ -139,9 +158,19 @@ function handleActionCompute(state: PlayerActionState, playerIndex: number, fram
const didGrabLedge = didStartLedgegrab(currentAnimation, prevAnimation);
incrementCount("ledgegrabCount", didGrabLedge);

const didGrabSucceed = didStartGrabSuccess(currentAnimation, prevAnimation);
incrementCount("grabCount.success", didGrabSucceed);
const didGrabFail = didStartGrabFail(currentAnimation, prevAnimation);
incrementCount("grabCount.fail", didGrabFail);

incrementCount("throwCount.up", currentAnimation === State.THROW_UP && newAnimation);
incrementCount("throwCount.forward", currentAnimation === State.THROW_FORWARD && newAnimation);
incrementCount("throwCount.down", currentAnimation === State.THROW_DOWN && newAnimation);
incrementCount("throwCount.back", currentAnimation === State.THROW_BACK && newAnimation);

if (isAerialAttack(currentAnimation)) {
incrementCount("lCancelSuccessCount", playerFrame.lCancelStatus === 1);
incrementCount("lCancelFailCount", playerFrame.lCancelStatus === 2);
incrementCount("lCancelCount.success", playerFrame.lCancelStatus === 1);
incrementCount("lCancelCount.fail", playerFrame.lCancelStatus === 2);
}

// Handles wavedash detection (and waveland)
Expand Down
22 changes: 20 additions & 2 deletions src/stats/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,20 @@ export interface ActionCountsType {
spotDodgeCount: number;
ledgegrabCount: number;
rollCount: number;
lCancelSuccessCount: number;
lCancelFailCount: number;
lCancelCount: {
success: number;
fail: number;
};
grabCount: {
success: number;
fail: number;
};
throwCount: {
up: number;
forward: number;
back: number;
down: number;
};
}

export interface InputCountsType {
Expand Down Expand Up @@ -136,7 +148,13 @@ export enum State {
FALL_FORWARD = 0x1e,
FALL_BACKWARD = 0x1f,
GRAB = 0xd4,
GRAB_WAIT = 0xd8,
PUMMEL = 0xd9,
CLIFF_CATCH = 0xfc,
THROW_UP = 0xdd,
THROW_FORWARD = 0xdb,
THROW_DOWN = 0xde,
THROW_BACK = 0xdc,
DAMAGE_FALL = 0x26,

// Command Grabs
Expand Down
34 changes: 30 additions & 4 deletions test/stats.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
import { SlippiGame } from "../src";
import { didLoseStock } from "../src/stats/common";

const expectedThrow = {
up: 1,
forward: 1,
back: 2,
down: 1,
};

const expectedGrab = {
success: 6,
fail: 2,
};

describe("when calculating stats", () => {
it("should correctly calculate L cancel counts", () => {
const game = new SlippiGame("slp/lCancel.slp");
const stats = game.getStats();
const p1Success = stats.actionCounts[0].lCancelSuccessCount;
const p1Fail = stats.actionCounts[0].lCancelFailCount;
const p1Success = stats.actionCounts[0].lCancelCount.success;
const p1Fail = stats.actionCounts[0].lCancelCount.fail;
expect(p1Success).toBe(3);
expect(p1Fail).toBe(4);
const p2Success = stats.actionCounts[1].lCancelSuccessCount;
const p2Fail = stats.actionCounts[1].lCancelFailCount;
const p2Success = stats.actionCounts[1].lCancelCount.success;
const p2Fail = stats.actionCounts[1].lCancelCount.fail;
expect(p2Success).toBe(5);
expect(p2Fail).toBe(4);
});

it("should correctly calculate throw counts", () => {
const game = new SlippiGame("slp/throwGrab.slp");
const stats = game.getStats();
const p2Throws = stats.actionCounts[1].throwCount;
expect(p2Throws).toEqual(expectedThrow);
});

it("should correctly calculate grab counts", () => {
const game = new SlippiGame("slp/throwGrab.slp");
const stats = game.getStats();
const p2Grabs = stats.actionCounts[1].grabCount;
expect(p2Grabs).toEqual(expectedGrab);
});

describe("when calculating total damage done", () => {
it("should ignore Blast Zone Magnifying Glass damage", () => {
const game = new SlippiGame("slp/consistencyTest/Puff-MagnifyingGlass-10.slp");
Expand Down

0 comments on commit b351183

Please sign in to comment.