[Bug] Fix Make It Rain and Clanging Scales stat drop trigger logic (#3355)
* Fix Make It Rain + Clanging Scales stat drop logic * Use "includes" instead of "<" for firstTarget logic instead
This commit is contained in:
parent
b6da93a092
commit
32d4102594
|
@ -7905,7 +7905,7 @@ export function initMoves() {
|
|||
.makesContact(false)
|
||||
.partial(),
|
||||
new AttackMove(Moves.CLANGING_SCALES, Type.DRAGON, MoveCategory.SPECIAL, 110, 100, 5, -1, 0, 7)
|
||||
.attr(StatChangeAttr, BattleStat.DEF, -1, true)
|
||||
.attr(StatChangeAttr, BattleStat.DEF, -1, true, null, true, false, MoveEffectTrigger.HIT, true)
|
||||
.soundBased()
|
||||
.target(MoveTarget.ALL_NEAR_ENEMIES),
|
||||
new AttackMove(Moves.DRAGON_HAMMER, Type.DRAGON, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 7),
|
||||
|
|
|
@ -2966,6 +2966,8 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||
|
||||
// Move animation only needs one target
|
||||
new MoveAnim(move.id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => {
|
||||
/** Has the move successfully hit a target (for damage) yet? */
|
||||
let hasHit: boolean = false;
|
||||
for (const target of targets) {
|
||||
if (!targetHitChecks[target.getBattlerIndex()]) {
|
||||
this.stopMultiHit(target);
|
||||
|
@ -2981,7 +2983,6 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||
const isProtected = !this.move.getMove().checkFlag(MoveFlags.IGNORE_PROTECT, user, target) && target.findTags(t => t instanceof ProtectedTag).find(t => target.lapseTag(t.tagType));
|
||||
|
||||
const firstHit = (user.turnData.hitsLeft === user.turnData.hitCount);
|
||||
const firstTarget = (moveHistoryEntry.result === MoveResult.PENDING);
|
||||
|
||||
if (firstHit) {
|
||||
user.pushMoveHistory(moveHistoryEntry);
|
||||
|
@ -2991,6 +2992,18 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||
|
||||
const hitResult = !isProtected ? target.apply(user, move) : HitResult.NO_EFFECT;
|
||||
|
||||
const dealsDamage = [
|
||||
HitResult.EFFECTIVE,
|
||||
HitResult.SUPER_EFFECTIVE,
|
||||
HitResult.NOT_VERY_EFFECTIVE,
|
||||
HitResult.ONE_HIT_KO
|
||||
].includes(hitResult);
|
||||
|
||||
const firstTarget = dealsDamage && !hasHit;
|
||||
if (firstTarget) {
|
||||
hasHit = true;
|
||||
}
|
||||
|
||||
const lastHit = (user.turnData.hitsLeft === 1 || !this.getTarget()?.isActive());
|
||||
|
||||
if (lastHit) {
|
||||
|
@ -3008,7 +3021,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
|||
if (hitResult !== HitResult.NO_EFFECT) {
|
||||
applyFilteredMoveAttrs((attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_APPLY
|
||||
&& !(attr as MoveEffectAttr).selfTarget && (!attr.firstHitOnly || firstHit) && (!attr.lastHitOnly || lastHit), user, target, this.move.getMove()).then(() => {
|
||||
if (hitResult < HitResult.NO_EFFECT && !target.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr)) {
|
||||
if (dealsDamage && !target.hasAbilityWithAttr(IgnoreMoveEffectsAbAttr)) {
|
||||
const flinched = new Utils.BooleanHolder(false);
|
||||
user.scene.applyModifiers(FlinchChanceModifier, user.isPlayer(), user, flinched);
|
||||
if (flinched.value) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { BattleStat } from "#app/data/battle-stat.js";
|
||||
import {
|
||||
CommandPhase,
|
||||
MoveEffectPhase,
|
||||
MoveEndPhase,
|
||||
StatChangePhase,
|
||||
} from "#app/phases";
|
||||
|
@ -10,7 +10,7 @@ import { Abilities } from "#enums/abilities";
|
|||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { SPLASH_ONLY } from "../utils/testUtils";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
@ -44,16 +44,8 @@ describe("Moves - Make It Rain", () => {
|
|||
await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerField();
|
||||
expect(playerPokemon.length).toBe(2);
|
||||
playerPokemon.forEach(p => expect(p).toBeDefined());
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyField();
|
||||
expect(enemyPokemon.length).toBe(2);
|
||||
enemyPokemon.forEach(p => expect(p).toBeDefined());
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.MAKE_IT_RAIN));
|
||||
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
|
@ -68,10 +60,7 @@ describe("Moves - Make It Rain", () => {
|
|||
await game.startBattle([Species.CHARIZARD]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon();
|
||||
expect(playerPokemon).toBeDefined();
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon();
|
||||
expect(enemyPokemon).toBeDefined();
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.MAKE_IT_RAIN));
|
||||
|
||||
|
@ -87,14 +76,9 @@ describe("Moves - Make It Rain", () => {
|
|||
await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerField();
|
||||
playerPokemon.forEach(p => expect(p).toBeDefined());
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyField();
|
||||
enemyPokemon.forEach(p => expect(p).toBeDefined());
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.MAKE_IT_RAIN));
|
||||
|
||||
await game.phaseInterceptor.to(CommandPhase);
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
|
||||
|
||||
await game.phaseInterceptor.to(StatChangePhase);
|
||||
|
@ -102,4 +86,23 @@ describe("Moves - Make It Rain", () => {
|
|||
enemyPokemon.forEach(p => expect(p.isFainted()).toBe(true));
|
||||
expect(playerPokemon[0].summonData.battleStats[BattleStat.SPATK]).toBe(-1);
|
||||
}, TIMEOUT);
|
||||
|
||||
it("should reduce Sp. Atk if it only hits the second target", async () => {
|
||||
await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]);
|
||||
|
||||
const playerPokemon = game.scene.getPlayerField();
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.MAKE_IT_RAIN));
|
||||
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
|
||||
|
||||
await game.phaseInterceptor.to(MoveEffectPhase, false);
|
||||
|
||||
// Make Make It Rain miss the first target
|
||||
const moveEffectPhase = game.scene.getCurrentPhase() as MoveEffectPhase;
|
||||
vi.spyOn(moveEffectPhase, "hitCheck").mockReturnValueOnce(false);
|
||||
|
||||
await game.phaseInterceptor.to(MoveEndPhase);
|
||||
|
||||
expect(playerPokemon[0].summonData.battleStats[BattleStat.SPATK]).toBe(-1);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue