[Misc][AI] Fix KO filter not accounting for move conditions (#4245)
* Only filter KO moves that won't fail * Add Last Resort enemy command test
This commit is contained in:
parent
39a1963941
commit
bdc7c95c1c
|
@ -4410,7 +4410,10 @@ export class EnemyPokemon extends Pokemon {
|
|||
const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT);
|
||||
|
||||
return move.category !== MoveCategory.STATUS
|
||||
&& moveTargets.some(p => p.getAttackDamage(this, move, !p.battleData.abilityRevealed, false, isCritical).damage >= p.hp);
|
||||
&& moveTargets.some(p => {
|
||||
const doesNotFail = move.applyConditions(this, p, move) || [Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id);
|
||||
return doesNotFail && p.getAttackDamage(this, move, !p.battleData.abilityRevealed, false, isCritical).damage >= p.hp;
|
||||
});
|
||||
}, this);
|
||||
|
||||
if (koMoves.length > 0) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { AiType, EnemyPokemon } from "#app/field/pokemon";
|
|||
import { randSeedInt } from "#app/utils";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
const NUM_TRIALS = 300;
|
||||
|
@ -36,22 +36,26 @@ describe("Enemy Commands - Move Selection", () => {
|
|||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
game = new GameManager(phaserGame);
|
||||
game.override.ability(Abilities.BALL_FETCH);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
|
||||
game.override
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.enemyAbility(Abilities.BALL_FETCH);
|
||||
});
|
||||
|
||||
it(
|
||||
"should never use Status moves if an attack can KO",
|
||||
async () => {
|
||||
game.override
|
||||
.enemySpecies(Species.ETERNATUS)
|
||||
.enemyMoveset([Moves.ETERNABEAM, Moves.SLUDGE_BOMB, Moves.DRAGON_DANCE, Moves.COSMIC_POWER])
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.startingLevel(1)
|
||||
.enemyLevel(100);
|
||||
|
||||
|
@ -72,4 +76,31 @@ describe("Enemy Commands - Move Selection", () => {
|
|||
});
|
||||
}, TIMEOUT
|
||||
);
|
||||
|
||||
it(
|
||||
"should not select Last Resort if it would fail, even if the move KOs otherwise",
|
||||
async () => {
|
||||
game.override
|
||||
.enemySpecies(Species.KANGASKHAN)
|
||||
.enemyMoveset([Moves.LAST_RESORT, Moves.GIGA_IMPACT, Moves.SPLASH, Moves.SWORDS_DANCE])
|
||||
.startingLevel(1)
|
||||
.enemyLevel(100);
|
||||
|
||||
await game.classicMode.startBattle([Species.MAGIKARP]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
enemyPokemon.aiType = AiType.SMART_RANDOM;
|
||||
|
||||
const moveChoices: MoveChoiceSet = {};
|
||||
const enemyMoveset = enemyPokemon.getMoveset();
|
||||
enemyMoveset.forEach(mv => moveChoices[mv!.moveId] = 0);
|
||||
getEnemyMoveChoices(enemyPokemon, moveChoices);
|
||||
|
||||
enemyMoveset.forEach(mv => {
|
||||
if (mv?.getMove().category === MoveCategory.STATUS || mv?.moveId === Moves.LAST_RESORT) {
|
||||
expect(moveChoices[mv.moveId]).toBe(0);
|
||||
}
|
||||
});
|
||||
}, TIMEOUT
|
||||
);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue