From 721ec6e8a91b19205998daeb848d5a86cb8ce1af Mon Sep 17 00:00:00 2001 From: N1ghtz567 Date: Mon, 18 Dec 2023 21:53:28 -0400 Subject: [PATCH] Implement Perish Song --- src/data/battler-tag.ts | 24 +++++++++++++++++++++++- src/data/move.ts | 30 +++++++++++++++++++++++++++--- src/pokemon.ts | 4 ++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/data/battler-tag.ts b/src/data/battler-tag.ts index 76e475757..19cff75f1 100644 --- a/src/data/battler-tag.ts +++ b/src/data/battler-tag.ts @@ -1,7 +1,7 @@ import { CommonAnim, CommonBattleAnim } from "./battle-anims"; import { CommonAnimPhase, DamagePhase, MovePhase, ObtainStatusEffectPhase, PokemonHealPhase, ShowAbilityPhase } from "../battle-phases"; import { getPokemonMessage } from "../messages"; -import Pokemon, { MoveResult } from "../pokemon"; +import Pokemon, { MoveResult, HitResult } from "../pokemon"; import { Stat } from "./pokemon-stat"; import { StatusEffect } from "./status-effect"; import * as Utils from "../utils"; @@ -31,6 +31,7 @@ export enum BattlerTagType { SAND_TOMB, MAGMA_STORM, PROTECTED, + PERISH_SONG, TRUANT, FLYING, UNDERGROUND, @@ -596,6 +597,25 @@ export class ProtectedTag extends BattlerTag { } } +export class PerishSongTag extends BattlerTag { + constructor(turnCount: integer) { + super(BattlerTagType.PERISH_SONG, BattlerTagLapseType.TURN_END, turnCount, Moves.PERISH_SONG); + } + + lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { + const ret = super.lapse(pokemon, lapseType); + + if (ret) + pokemon.scene.queueMessage(getPokemonMessage(pokemon, `\'s perish count fell to ${this.turnCount}.`)); + else { + pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.getBattlerIndex(), HitResult.ONE_HIT_KO)); + pokemon.damage(pokemon.hp); + } + + return ret; + } +} + export class TruantTag extends BattlerTag { constructor() { super(BattlerTagType.TRUANT, BattlerTagLapseType.MOVE, 1, undefined); @@ -721,6 +741,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc return new MagmaStormTag(turnCount, sourceId); case BattlerTagType.PROTECTED: return new ProtectedTag(sourceMove); + case BattlerTagType.PERISH_SONG: + return new PerishSongTag(turnCount); case BattlerTagType.TRUANT: return new TruantTag(); case BattlerTagType.FLYING: diff --git a/src/data/move.ts b/src/data/move.ts index cfe7d3ab5..38d7d810b 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1785,7 +1785,7 @@ export class ClearWeatherAttr extends MoveEffectAttr { export class OneHitKOAttr extends MoveAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - if (target.species.speciesId === Species.ETERNATUS && target.formIndex === 1) + if (target.isBossImmune()) return false; (args[0] as Utils.BooleanHolder).value = true; @@ -2382,6 +2382,8 @@ export class AddBattlerTagAttr extends MoveEffectAttr { return -5; case BattlerTagType.FRENZY: return -2; + case BattlerTagType.ENCORE: + return -2; case BattlerTagType.INGRAIN: return 3; case BattlerTagType.AQUA_RING: @@ -2398,7 +2400,9 @@ export class AddBattlerTagAttr extends MoveEffectAttr { case BattlerTagType.MAGMA_STORM: return -3; case BattlerTagType.PROTECTED: - return 10; + return 5; + case BattlerTagType.PERISH_SONG: + return -8; case BattlerTagType.FLYING: return 5; case BattlerTagType.CRIT_BOOST: @@ -2483,6 +2487,25 @@ export class IgnoreAccuracyAttr extends AddBattlerTagAttr { } } +export class FaintCountdownAttr extends AddBattlerTagAttr { + constructor() { + super(BattlerTagType.PERISH_SONG, false, 4, true); + } + + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + if (!super.apply(user, target, move, args)) + return false; + + user.scene.queueMessage(getPokemonMessage(target, `\nwill faint in ${this.turnCount - 1} turns.`)); + + return true; + } + + getCondition(): MoveCondition { + return (user, target, move) => super.getCondition()(user, target, move) && !target.isBossImmune(); + } +} + export class HitsTagAttr extends MoveAttr { public tagType: BattlerTagType; public doubleDamage: boolean; @@ -3412,7 +3435,8 @@ export function initMoves() { new StatusMove(Moves.FORESIGHT, "Foresight (N)", Type.NORMAL, -1, 40, -1, "Enables a Ghost-type target to be hit by Normal- and Fighting-type attacks. This also enables an evasive target to be hit.", -1, 0, 2), new SelfStatusMove(Moves.DESTINY_BOND, "Destiny Bond (N)", Type.GHOST, -1, 5, -1, "After using this move, if the user faints, the Pokémon that landed the knockout hit also faints. Its chance of failing rises if it is used in succession.", -1, 0, 2) .ignoresProtect(), - new StatusMove(Moves.PERISH_SONG, "Perish Song (N)", Type.NORMAL, -1, 5, -1, "Any Pokémon that hears this song faints in three turns, unless it switches out of battle.", -1, 0, 2) + new StatusMove(Moves.PERISH_SONG, "Perish Song", Type.NORMAL, -1, 5, -1, "Any Pokémon that hears this song faints in three turns, unless it switches out of battle.", -1, 0, 2) + .attr(FaintCountdownAttr) .ignoresProtect() .soundBased() .target(MoveTarget.ALL), diff --git a/src/pokemon.ts b/src/pokemon.ts index f533d021a..6ea4005dc 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -1035,6 +1035,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.hp = Math.min(this.hp + amount, this.getMaxHp()); } + isBossImmune(): boolean { + return this.species.speciesId === Species.ETERNATUS && this.formIndex === 1; + } + addTag(tagType: BattlerTagType, turnCount?: integer, sourceMove?: Moves, sourceId?: integer): boolean { const existingTag = this.getTag(tagType); if (existingTag) {