mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-23 15:59:26 +02:00
Pledges now only bypass redirection from abilities
This commit is contained in:
parent
c1809a16bd
commit
742b8d4258
@ -4648,7 +4648,15 @@ export class TypelessAttr extends MoveAttr { }
|
||||
* Attribute used for moves which ignore redirection effects, and always target their original target, i.e. Snipe Shot
|
||||
* Bypasses Storm Drain, Follow Me, Ally Switch, and the like.
|
||||
*/
|
||||
export class BypassRedirectAttr extends MoveAttr { }
|
||||
export class BypassRedirectAttr extends MoveAttr {
|
||||
/** `true` if this move only bypasses redirection from Abilities */
|
||||
public readonly abilitiesOnly: boolean;
|
||||
|
||||
constructor(abilitiesOnly: boolean = false) {
|
||||
super();
|
||||
this.abilitiesOnly = abilitiesOnly;
|
||||
}
|
||||
}
|
||||
|
||||
export class FrenzyAttr extends MoveEffectAttr {
|
||||
constructor() {
|
||||
@ -8516,7 +8524,7 @@ export function initMoves() {
|
||||
.attr(CombinedPledgeStabBoostAttr)
|
||||
.attr(AddPledgeEffectAttr, ArenaTagType.WATER_FIRE_PLEDGE, Moves.FIRE_PLEDGE, true)
|
||||
.attr(AddPledgeEffectAttr, ArenaTagType.GRASS_WATER_PLEDGE, Moves.GRASS_PLEDGE)
|
||||
.attr(BypassRedirectAttr), // technically incorrect, should only bypass Storm Drain/Lightning Rod
|
||||
.attr(BypassRedirectAttr, true),
|
||||
new AttackMove(Moves.FIRE_PLEDGE, Type.FIRE, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 5)
|
||||
.attr(AwaitCombinedPledgeAttr)
|
||||
.attr(CombinedPledgeTypeAttr)
|
||||
@ -8524,7 +8532,7 @@ export function initMoves() {
|
||||
.attr(CombinedPledgeStabBoostAttr)
|
||||
.attr(AddPledgeEffectAttr, ArenaTagType.FIRE_GRASS_PLEDGE, Moves.GRASS_PLEDGE)
|
||||
.attr(AddPledgeEffectAttr, ArenaTagType.WATER_FIRE_PLEDGE, Moves.WATER_PLEDGE, true)
|
||||
.attr(BypassRedirectAttr), // technically incorrect, should only bypass Storm Drain/Lightning Rod
|
||||
.attr(BypassRedirectAttr, true),
|
||||
new AttackMove(Moves.GRASS_PLEDGE, Type.GRASS, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 5)
|
||||
.attr(AwaitCombinedPledgeAttr)
|
||||
.attr(CombinedPledgeTypeAttr)
|
||||
@ -8532,7 +8540,7 @@ export function initMoves() {
|
||||
.attr(CombinedPledgeStabBoostAttr)
|
||||
.attr(AddPledgeEffectAttr, ArenaTagType.GRASS_WATER_PLEDGE, Moves.WATER_PLEDGE)
|
||||
.attr(AddPledgeEffectAttr, ArenaTagType.FIRE_GRASS_PLEDGE, Moves.FIRE_PLEDGE)
|
||||
.attr(BypassRedirectAttr), // technically incorrect, should only bypass Storm Drain/Lightning Rod
|
||||
.attr(BypassRedirectAttr, true),
|
||||
new AttackMove(Moves.VOLT_SWITCH, Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 20, -1, 0, 5)
|
||||
.attr(ForceSwitchOutAttr, true),
|
||||
new AttackMove(Moves.STRUGGLE_BUG, Type.BUG, MoveCategory.SPECIAL, 50, 100, 20, 100, 0, 5)
|
||||
|
@ -331,22 +331,30 @@ export class MovePhase extends BattlePhase {
|
||||
// check move redirection abilities of every pokemon *except* the user.
|
||||
this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, false, this.move.moveId, redirectTarget));
|
||||
|
||||
/** `true` if an Ability is responsible for redirecting the move to another target; `false` otherwise */
|
||||
let redirectedByAbility = (currentTarget !== redirectTarget.value);
|
||||
|
||||
// check for center-of-attention tags (note that this will override redirect abilities)
|
||||
this.pokemon.getOpponents().forEach(p => {
|
||||
const redirectTag = p.getTag(CenterOfAttentionTag) as CenterOfAttentionTag;
|
||||
const redirectTag = p.getTag(CenterOfAttentionTag);
|
||||
|
||||
// TODO: don't hardcode this interaction.
|
||||
// Handle interaction between the rage powder center-of-attention tag and moves used by grass types/overcoat-havers (which are immune to RP's redirect)
|
||||
if (redirectTag && (!redirectTag.powder || (!this.pokemon.isOfType(Type.GRASS) && !this.pokemon.hasAbility(Abilities.OVERCOAT)))) {
|
||||
redirectTarget.value = p.getBattlerIndex();
|
||||
redirectedByAbility = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (currentTarget !== redirectTarget.value) {
|
||||
if (this.move.getMove().hasAttr(BypassRedirectAttr)) {
|
||||
redirectTarget.value = currentTarget;
|
||||
const bypassRedirectAttrs = this.move.getMove().getAttrs(BypassRedirectAttr);
|
||||
bypassRedirectAttrs.forEach((attr) => {
|
||||
if (!attr.abilitiesOnly || redirectedByAbility) {
|
||||
redirectTarget.value = currentTarget;
|
||||
}
|
||||
});
|
||||
|
||||
} else if (this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr)) {
|
||||
if (this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr)) {
|
||||
redirectTarget.value = currentTarget;
|
||||
this.scene.unshiftPhase(new ShowAbilityPhase(this.scene, this.pokemon.getBattlerIndex(), this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr)));
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { BattlerIndex } from "#app/battle";
|
||||
import { allAbilities } from "#app/data/ability";
|
||||
import { ArenaTagSide } from "#app/data/arena-tag";
|
||||
import { allMoves, FlinchAttr } from "#app/data/move";
|
||||
import { Type } from "#app/data/type";
|
||||
@ -293,4 +294,44 @@ describe("Moves - Pledge Moves", () => {
|
||||
enemyPokemon.forEach((p) => expect(p.hp).toBe(p.getMaxHp()));
|
||||
}
|
||||
);
|
||||
|
||||
it(
|
||||
"Pledge Moves - should ignore redirection from another Pokemon's Storm Drain",
|
||||
async () => {
|
||||
await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyField();
|
||||
vi.spyOn(enemyPokemon[1], "getAbility").mockReturnValue(allAbilities[Abilities.STORM_DRAIN]);
|
||||
|
||||
game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
|
||||
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]);
|
||||
|
||||
await game.phaseInterceptor.to("MoveEndPhase", false);
|
||||
|
||||
expect(enemyPokemon[0].hp).toBeLessThan(enemyPokemon[0].getMaxHp());
|
||||
expect(enemyPokemon[1].getStatStage(Stat.SPATK)).toBe(0);
|
||||
}
|
||||
);
|
||||
|
||||
it(
|
||||
"Pledge Moves - should not ignore redirection from another Pokemon's Follow Me",
|
||||
async () => {
|
||||
game.override.enemyMoveset([ Moves.FOLLOW_ME, Moves.SPLASH ]);
|
||||
await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]);
|
||||
|
||||
game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY);
|
||||
game.move.select(Moves.SPLASH, 1);
|
||||
|
||||
await game.forceEnemyMove(Moves.SPLASH);
|
||||
await game.forceEnemyMove(Moves.FOLLOW_ME);
|
||||
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyField();
|
||||
expect(enemyPokemon[0].hp).toBe(enemyPokemon[0].getMaxHp());
|
||||
expect(enemyPokemon[1].hp).toBeLessThan(enemyPokemon[1].getMaxHp());
|
||||
}
|
||||
);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user