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

[Bug] Honey Gather and Pickup will only activate if the battle was won #4903

Open
wants to merge 3 commits into
base: beta
Choose a base branch
from
Open
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
20 changes: 12 additions & 8 deletions src/data/ability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4112,9 +4112,13 @@ export class PostBattleAbAttr extends AbAttr {
}

export class PostBattleLootAbAttr extends PostBattleAbAttr {
/**
* @param args - `[0]`: boolean for if the battle ended in a victory
* @returns `true` if successful
*/
applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot;
if (!simulated && postBattleLoot.length) {
if (!simulated && postBattleLoot.length && args[0]) {
const randItem = Utils.randSeedItem(postBattleLoot);
//@ts-ignore - TODO see below
if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, true, 1, true, undefined, false)) { // TODO: fix. This is a promise!?
Expand Down Expand Up @@ -4575,28 +4579,28 @@ export class MoneyAbAttr extends PostBattleAbAttr {
/**
* @param pokemon {@linkcode Pokemon} that is the user of this ability.
* @param passive N/A
* @param args N/A
* @returns true
* @param args - `[0]`: boolean for if the battle ended in a victory
* @returns `true` if successful
*/
applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
if (!simulated) {
if (!simulated && args[0]) {
pokemon.scene.currentBattle.moneyScattered += pokemon.scene.getWaveMoneyAmount(0.2);
return true;
}
return true;
return false;
}
}

/**
* Applies a stat change after a Pokémon is summoned,
* conditioned on the presence of a specific arena tag.
*
* @extends {PostSummonStatStageChangeAbAttr}
* @extends PostSummonStatStageChangeAbAttr
*/
export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageChangeAbAttr {
/**
* The type of arena tag that conditions the stat change.
* @private
* @type {ArenaTagType}
*/
private tagType: ArenaTagType;

Expand Down Expand Up @@ -4972,7 +4976,7 @@ class ForceSwitchOutHelper {
pokemon.scene.clearEnemyHeldItemModifiers();

if (switchOutTarget.hp) {
pokemon.scene.pushPhase(new BattleEndPhase(pokemon.scene));
pokemon.scene.pushPhase(new BattleEndPhase(pokemon.scene, false));
pokemon.scene.pushPhase(new NewBattlePhase(pokemon.scene));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/data/move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6035,7 +6035,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
user.scene.clearEnemyHeldItemModifiers();

if (switchOutTarget.hp) {
user.scene.pushPhase(new BattleEndPhase(user.scene));
user.scene.pushPhase(new BattleEndPhase(user.scene, false));
user.scene.pushPhase(new NewBattlePhase(user.scene));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ export function handleMysteryEncounterVictory(scene: BattleScene, addHealPhase:
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
scene.pushPhase(new EggLapsePhase(scene));
} else if (!scene.getEnemyParty().find(p => encounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true))) {
scene.pushPhase(new BattleEndPhase(scene));
scene.pushPhase(new BattleEndPhase(scene, true));
if (encounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
scene.pushPhase(new TrainerVictoryPhase(scene));
}
Expand Down
2 changes: 1 addition & 1 deletion src/phases/attempt-run-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class AttemptRunPhase extends PokemonPhase {
enemyPokemon.trySetStatus(StatusEffect.FAINT);
});

this.scene.pushPhase(new BattleEndPhase(this.scene));
this.scene.pushPhase(new BattleEndPhase(this.scene, false));
this.scene.pushPhase(new NewBattlePhase(this.scene));
} else {
playerPokemon.turnData.failedRunAway = true;
Expand Down
4 changes: 2 additions & 2 deletions src/phases/battle-end-phase.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some stats that should be updated outside of a victory but aren't, namely:

  • battles (L23, counts total number of battles)
  • highestEndlessWave (L27-29)

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export class BattleEndPhase extends BattlePhase {
/** If true, will increment battles won */
isVictory: boolean;

constructor(scene: BattleScene, isVictory: boolean = true) {
constructor(scene: BattleScene, isVictory: boolean) {
super(scene);

this.isVictory = isVictory;
Expand Down Expand Up @@ -42,7 +42,7 @@ export class BattleEndPhase extends BattlePhase {
}

for (const pokemon of this.scene.getPokemonAllowedInBattle()) {
applyPostBattleAbAttrs(PostBattleAbAttr, pokemon);
applyPostBattleAbAttrs(PostBattleAbAttr, pokemon, false, this.isVictory);
}

if (this.scene.currentBattle.moneyScattered) {
Expand Down
2 changes: 1 addition & 1 deletion src/phases/victory-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class VictoryPhase extends PokemonPhase {
}

if (!this.scene.getEnemyParty().find(p => this.scene.currentBattle.battleType === BattleType.WILD ? p.isOnField() : !p?.isFainted(true))) {
this.scene.pushPhase(new BattleEndPhase(this.scene));
this.scene.pushPhase(new BattleEndPhase(this.scene, true));
if (this.scene.currentBattle.battleType === BattleType.TRAINER) {
this.scene.pushPhase(new TrainerVictoryPhase(this.scene));
}
Expand Down
74 changes: 74 additions & 0 deletions src/test/abilities/honey_gather.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { CommandPhase } from "#app/phases/command-phase";
import { Command } from "#app/ui/command-ui-handler";
import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";

describe("Abilities - Honey Gather", () => {
let phaserGame: Phaser.Game;
let game: GameManager;

beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});

afterEach(() => {
game.phaseInterceptor.restoreOg();
});

beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.moveset([ Moves.SPLASH, Moves.ROAR, Moves.THUNDERBOLT ])
.startingLevel(100)
.ability(Abilities.HONEY_GATHER)
.passiveAbility(Abilities.RUN_AWAY)
.battleType("single")
.disableCrits()
.enemySpecies(Species.MAGIKARP)
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(Moves.SPLASH);
});

it("should give money when winning a battle", async () => {
await game.classicMode.startBattle([ Species.MILOTIC ]);
game.scene.money = 1000;

game.move.select(Moves.THUNDERBOLT);
await game.toNextWave();

expect(game.scene.money).toBeGreaterThan(1000);
});

it("should not give money when the enemy pokemon flees", async () => {
await game.classicMode.startBattle([ Species.MILOTIC ]);
game.scene.money = 1000;

game.move.select(Moves.ROAR);
await game.toNextTurn();

expect(game.scene.money).toBe(1000);
expect(game.scene.currentBattle.waveIndex).toBe(2);
});

it("should not give money when the player flees", async () => {
await game.classicMode.startBattle([ Species.MILOTIC ]);
game.scene.money = 1000;

// something weird is going on with the test framework, so this is required to prevent a crash
const enemy = game.scene.getEnemyPokemon()!;
vi.spyOn(enemy, "scene", "get").mockReturnValue(game.scene);

const commandPhase = game.scene.getCurrentPhase() as CommandPhase;
commandPhase.handleCommand(Command.RUN, 0);
await game.toNextTurn();

expect(game.scene.money).toBe(1000);
expect(game.scene.currentBattle.waveIndex).toBe(2);
});
});
Loading