[Ability][Move] Finish wind rider/power + tailwind implementation (#1566)

* finish wind moves + tailwind implementation

* move code and add documentations

* remove partial tag of wind_power

* add translations, fix move bugs

* fix ability trigger message

* fix ability trigger message

* add es localization

* move out of else statement
This commit is contained in:
Adrian T 2024-05-31 05:42:46 +08:00 committed by GitHub
parent cb6a0b9973
commit 31e3293c51
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 83 additions and 10 deletions

View File

@ -674,7 +674,10 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr {
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: PokemonMove, hitResult: HitResult, args: any[]): boolean {
if (this.condition(pokemon, attacker, move.getMove())) {
pokemon.addTag(this.tagType, undefined, undefined, pokemon.id);
if (!pokemon.getTag(this.tagType)) {
pokemon.addTag(this.tagType, undefined, undefined, pokemon.id);
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: move.getName() }));
}
return true;
}
return false;
@ -3200,6 +3203,50 @@ export class MoneyAbAttr extends PostBattleAbAttr {
}
}
/**
* Applies a stat change after a Pokémon is summoned,
* conditioned on the presence of a specific arena tag.
*
* @extends {PostSummonStatChangeAbAttr}
*/
export class PostSummonStatChangeOnArenaAbAttr extends PostSummonStatChangeAbAttr {
/**
* The type of arena tag that conditions the stat change.
* @private
* @type {ArenaTagType}
*/
private tagType: ArenaTagType;
/**
* Creates an instance of PostSummonStatChangeOnArenaAbAttr.
* Initializes the stat change to increase Attack by 1 stage if the specified arena tag is present.
*
* @param {ArenaTagType} tagType - The type of arena tag to check for.
*/
constructor(tagType: ArenaTagType) {
super([BattleStat.ATK], 1, true, false);
this.tagType = tagType;
}
/**
* Applies the post-summon stat change if the specified arena tag is present on pokemon's side.
* This is used in Wind Rider ability.
*
* @param {Pokemon} pokemon - The Pokémon being summoned.
* @param {boolean} passive - Whether the effect is passive.
* @param {any[]} args - Additional arguments.
* @returns {boolean} - Returns true if the stat change was applied, otherwise false.
*/
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
const side = pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
if (pokemon.scene.arena.getTagOnSide(this.tagType, side)) {
return super.applyPostSummon(pokemon, passive, args);
}
return false;
}
}
function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any[]): TAttr },
pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> {
return new Promise(resolve => {
@ -4270,9 +4317,9 @@ export function initAbilities() {
.attr(TypeImmunityStatChangeAbAttr, Type.FIRE, BattleStat.DEF, 2)
.ignorable(),
new Ability(Abilities.WIND_RIDER, 9)
.attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE), BattleStat.ATK, 1)
.ignorable()
.partial(),
.attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE) && move.getMove().category !== MoveCategory.STATUS, BattleStat.ATK, 1)
.attr(PostSummonStatChangeOnArenaAbAttr, ArenaTagType.TAILWIND)
.ignorable(),
new Ability(Abilities.GUARD_DOG, 9)
.attr(PostIntimidateStatChangeAbAttr, [BattleStat.ATK], 1, true)
.attr(ForceSwitchOutImmunityAbAttr)
@ -4280,8 +4327,7 @@ export function initAbilities() {
new Ability(Abilities.ROCKY_PAYLOAD, 9)
.attr(MoveTypePowerBoostAbAttr, Type.ROCK),
new Ability(Abilities.WIND_POWER, 9)
.attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.hasFlag(MoveFlags.WIND_MOVE), BattlerTagType.CHARGED)
.partial(),
.attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.hasFlag(MoveFlags.WIND_MOVE), BattlerTagType.CHARGED),
new Ability(Abilities.ZERO_TO_HERO, 9)
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)

View File

@ -4,7 +4,7 @@ import * as Utils from "../utils";
import { MoveCategory, allMoves, MoveTarget } from "./move";
import { getPokemonMessage } from "../messages";
import Pokemon, { HitResult, PokemonMove } from "../field/pokemon";
import { MoveEffectPhase, PokemonHealPhase, StatChangePhase} from "../phases";
import { MoveEffectPhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase} from "../phases";
import { StatusEffect } from "./status-effect";
import { BattlerIndex } from "../battle";
import { Moves } from "./enums/moves";
@ -12,6 +12,9 @@ import { ArenaTagType } from "./enums/arena-tag-type";
import { BlockNonDirectDamageAbAttr, ProtectStatAbAttr, applyAbAttrs } from "./ability";
import { BattleStat } from "./battle-stat";
import { CommonAnim, CommonBattleAnim } from "./battle-anims";
import { Abilities } from "./enums/abilities";
import { BattlerTagType } from "./enums/battler-tag-type";
import i18next from "i18next";
export enum ArenaTagSide {
BOTH,
@ -625,6 +628,22 @@ class TailwindTag extends ArenaTag {
onAdd(arena: Arena): void {
arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? "\nyour" : this.side === ArenaTagSide.ENEMY ? "\nthe opposing" : ""} team!`);
const source = arena.scene.getPokemonById(this.sourceId);
const party = source.isPlayer() ? source.scene.getPlayerField() : source.scene.getEnemyField();
for (const pokemon of party) {
// Apply the CHARGED tag to party members with the WIND_POWER ability
if (pokemon.hasAbility(Abilities.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) {
pokemon.addTag(BattlerTagType.CHARGED);
pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: pokemon.name, moveName: this.getMoveName() }));
}
// Raise attack by one stage if party member has WIND_RIDER ability
if (pokemon.hasAbility(Abilities.WIND_RIDER)) {
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.getBattlerIndex()));
pokemon.scene.unshiftPhase(new StatChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [BattleStat.ATK], 1, true));
}
}
}
onRemove(arena: Arena): void {

View File

@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} wurde durch {{abilityName}}\nvor Rückstoß geschützt!",
"badDreams": "{{pokemonName}} ist in einem Alptraum gefangen!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
} as const;

View File

@ -3,5 +3,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}}'s {{abilityName}}\nprotected it from recoil!",
"badDreams": "{{pokemonName}} is tormented!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
"perishBody": "{{pokemonName}}'s {{abilityName}}\n will faint both pokemon in 3 turns!",
} as const;

View File

@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "¡{{abilityName}} de {{pokemonName}}\nlo protegió del daño de retroceso!",
"badDreams": "¡{{pokemonName}} está atormentado!"
"badDreams": "¡{{pokemonName}} está atormentado!",
"windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!",
} as const;

View File

@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{abilityName}}\nde {{pokemonName}} le protège du contrecoup !",
"badDreams": "{{pokemonName}} a le sommeil agité !"
"badDreams": "{{pokemonName}} a le sommeil agité !",
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !"
} as const;

View File

@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{abilityName}} di {{pokemonName}}\nl'ha protetto dal contraccolpo!",
"badDreams": "{{pokemonName}} è tormentato!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
} as const;

View File

@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{abilityName}} de {{pokemonName}}\nprotegeu-o do dano de recuo!",
"badDreams": "{{pokemonName}} está tendo pesadelos!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!"
} as const;

View File

@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力",
"badDreams": "{{pokemonName}} 被折磨着!"
"badDreams": "{{pokemonName}} 被折磨着!",
"windPowerCharged": "受 {{moveName}} 的影响, {{pokemonName}} 提升了能力!"
} as const;

View File

@ -3,4 +3,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{pokemonName}} 的 {{abilityName}}\n抵消了反作用力!",
"badDreams": "{{pokemonName}} 被折磨着!",
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!"
} as const;