[Bug] Honey Gather and Pickup will only activate if the battle was won (#4903)
* Honey Gather and Pickup will only activate if the battle was won * Add tests for Honey Gather * Moves `highestEndlessWave` and `battles` stats outside of victory condition
This commit is contained in:
parent
4d341bf1fd
commit
9bc046fd64
|
@ -4112,9 +4112,13 @@ export class PostBattleAbAttr extends AbAttr {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PostBattleLootAbAttr extends PostBattleAbAttr {
|
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 {
|
applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||||
const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot;
|
const postBattleLoot = pokemon.scene.currentBattle.postBattleLoot;
|
||||||
if (!simulated && postBattleLoot.length) {
|
if (!simulated && postBattleLoot.length && args[0]) {
|
||||||
const randItem = Utils.randSeedItem(postBattleLoot);
|
const randItem = Utils.randSeedItem(postBattleLoot);
|
||||||
//@ts-ignore - TODO see below
|
//@ts-ignore - TODO see below
|
||||||
if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, true, 1, true, undefined, false)) { // TODO: fix. This is a promise!?
|
if (pokemon.scene.tryTransferHeldItemModifier(randItem, pokemon, true, 1, true, undefined, false)) { // TODO: fix. This is a promise!?
|
||||||
|
@ -4575,14 +4579,15 @@ export class MoneyAbAttr extends PostBattleAbAttr {
|
||||||
/**
|
/**
|
||||||
* @param pokemon {@linkcode Pokemon} that is the user of this ability.
|
* @param pokemon {@linkcode Pokemon} that is the user of this ability.
|
||||||
* @param passive N/A
|
* @param passive N/A
|
||||||
* @param args N/A
|
* @param args - `[0]`: boolean for if the battle ended in a victory
|
||||||
* @returns true
|
* @returns `true` if successful
|
||||||
*/
|
*/
|
||||||
applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
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);
|
pokemon.scene.currentBattle.moneyScattered += pokemon.scene.getWaveMoneyAmount(0.2);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4590,13 +4595,12 @@ export class MoneyAbAttr extends PostBattleAbAttr {
|
||||||
* Applies a stat change after a Pokémon is summoned,
|
* Applies a stat change after a Pokémon is summoned,
|
||||||
* conditioned on the presence of a specific arena tag.
|
* conditioned on the presence of a specific arena tag.
|
||||||
*
|
*
|
||||||
* @extends {PostSummonStatStageChangeAbAttr}
|
* @extends PostSummonStatStageChangeAbAttr
|
||||||
*/
|
*/
|
||||||
export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageChangeAbAttr {
|
export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageChangeAbAttr {
|
||||||
/**
|
/**
|
||||||
* The type of arena tag that conditions the stat change.
|
* The type of arena tag that conditions the stat change.
|
||||||
* @private
|
* @private
|
||||||
* @type {ArenaTagType}
|
|
||||||
*/
|
*/
|
||||||
private tagType: ArenaTagType;
|
private tagType: ArenaTagType;
|
||||||
|
|
||||||
|
@ -4972,7 +4976,7 @@ class ForceSwitchOutHelper {
|
||||||
pokemon.scene.clearEnemyHeldItemModifiers();
|
pokemon.scene.clearEnemyHeldItemModifiers();
|
||||||
|
|
||||||
if (switchOutTarget.hp) {
|
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));
|
pokemon.scene.pushPhase(new NewBattlePhase(pokemon.scene));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6082,7 +6082,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
||||||
user.scene.clearEnemyHeldItemModifiers();
|
user.scene.clearEnemyHeldItemModifiers();
|
||||||
|
|
||||||
if (switchOutTarget.hp) {
|
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));
|
user.scene.pushPhase(new NewBattlePhase(user.scene));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -731,7 +731,7 @@ export function handleMysteryEncounterVictory(scene: BattleScene, addHealPhase:
|
||||||
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
||||||
scene.pushPhase(new EggLapsePhase(scene));
|
scene.pushPhase(new EggLapsePhase(scene));
|
||||||
} else if (!scene.getEnemyParty().find(p => encounter.encounterMode !== MysteryEncounterMode.TRAINER_BATTLE ? p.isOnField() : !p?.isFainted(true))) {
|
} 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) {
|
if (encounter.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) {
|
||||||
scene.pushPhase(new TrainerVictoryPhase(scene));
|
scene.pushPhase(new TrainerVictoryPhase(scene));
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ export class AttemptRunPhase extends PokemonPhase {
|
||||||
enemyPokemon.trySetStatus(StatusEffect.FAINT);
|
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));
|
this.scene.pushPhase(new NewBattlePhase(this.scene));
|
||||||
} else {
|
} else {
|
||||||
playerPokemon.turnData.failedRunAway = true;
|
playerPokemon.turnData.failedRunAway = true;
|
||||||
|
|
|
@ -8,7 +8,7 @@ export class BattleEndPhase extends BattlePhase {
|
||||||
/** If true, will increment battles won */
|
/** If true, will increment battles won */
|
||||||
isVictory: boolean;
|
isVictory: boolean;
|
||||||
|
|
||||||
constructor(scene: BattleScene, isVictory: boolean = true) {
|
constructor(scene: BattleScene, isVictory: boolean) {
|
||||||
super(scene);
|
super(scene);
|
||||||
|
|
||||||
this.isVictory = isVictory;
|
this.isVictory = isVictory;
|
||||||
|
@ -17,16 +17,17 @@ export class BattleEndPhase extends BattlePhase {
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
this.scene.gameData.gameStats.battles++;
|
||||||
|
if (this.scene.gameMode.isEndless && this.scene.currentBattle.waveIndex + 1 > this.scene.gameData.gameStats.highestEndlessWave) {
|
||||||
|
this.scene.gameData.gameStats.highestEndlessWave = this.scene.currentBattle.waveIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isVictory) {
|
if (this.isVictory) {
|
||||||
this.scene.currentBattle.addBattleScore(this.scene);
|
this.scene.currentBattle.addBattleScore(this.scene);
|
||||||
|
|
||||||
this.scene.gameData.gameStats.battles++;
|
|
||||||
if (this.scene.currentBattle.trainer) {
|
if (this.scene.currentBattle.trainer) {
|
||||||
this.scene.gameData.gameStats.trainersDefeated++;
|
this.scene.gameData.gameStats.trainersDefeated++;
|
||||||
}
|
}
|
||||||
if (this.scene.gameMode.isEndless && this.scene.currentBattle.waveIndex + 1 > this.scene.gameData.gameStats.highestEndlessWave) {
|
|
||||||
this.scene.gameData.gameStats.highestEndlessWave = this.scene.currentBattle.waveIndex + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Endless graceful end
|
// Endless graceful end
|
||||||
|
@ -42,7 +43,7 @@ export class BattleEndPhase extends BattlePhase {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const pokemon of this.scene.getPokemonAllowedInBattle()) {
|
for (const pokemon of this.scene.getPokemonAllowedInBattle()) {
|
||||||
applyPostBattleAbAttrs(PostBattleAbAttr, pokemon);
|
applyPostBattleAbAttrs(PostBattleAbAttr, pokemon, false, this.isVictory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.scene.currentBattle.moneyScattered) {
|
if (this.scene.currentBattle.moneyScattered) {
|
||||||
|
|
|
@ -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))) {
|
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) {
|
if (this.scene.currentBattle.battleType === BattleType.TRAINER) {
|
||||||
this.scene.pushPhase(new TrainerVictoryPhase(this.scene));
|
this.scene.pushPhase(new TrainerVictoryPhase(this.scene));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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…
Reference in New Issue