From e47a0ba05baef5eb8275112789e7f1da595365ef Mon Sep 17 00:00:00 2001 From: jatinkohli Date: Mon, 20 May 2024 04:21:25 -0700 Subject: [PATCH] Partially implement taunt --- src/data/move.ts | 22 +++++++++++++++++++++- src/field/pokemon.ts | 10 +++++++++- src/phases.ts | 29 ++++++++++++++++++++++++++--- src/system/pokemon-data.ts | 3 +++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 06d69949437..781464a08d4 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3037,6 +3037,24 @@ export class TormentAttr extends MoveEffectAttr { } } +export class TauntAttr extends MoveEffectAttr { + constructor() { + super(false); + } + + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]) { + const ret = this.canApply(user, target, move, args); + + if (ret) { + target.summonData.justTaunted = true; + target.summonData.taunted = true; + target.summonData.tauntedTurns = 4; + user.scene.queueMessage(getPokemonMessage(target, ' fell for the taunt!')); + } + return ret; + } +} + export class FrenzyAttr extends MoveEffectAttr { constructor() { super(true, MoveEffectTrigger.HIT); @@ -5188,7 +5206,9 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPDEF, 1, true) .attr(AddBattlerTagAttr, BattlerTagType.CHARGED, true, false), new StatusMove(Moves.TAUNT, Type.DARK, 100, 20, -1, 0, 3) - .unimplemented(), + .attr(TauntAttr) + .condition((user, target, move) => (!target.summonData.taunted)) + .partial(), new StatusMove(Moves.HELPING_HAND, Type.NORMAL, -1, 20, -1, 5, 3) .attr(AddBattlerTagAttr, BattlerTagType.HELPING_HAND) .target(MoveTarget.NEAR_ALLY), diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 673958ba3ea..0bfec149efe 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3323,6 +3323,9 @@ export class PokemonSummonData { public abilitySuppressed: boolean = false; public justTormented: boolean = false; public tormented: boolean = false; + public justTaunted: boolean = false; + public taunted: boolean = false; + public tauntedTurns: integer = 0; public speciesForm: PokemonSpeciesForm; public fusionSpeciesForm: PokemonSpeciesForm; @@ -3401,9 +3404,14 @@ export class PokemonMove { isUsable(pokemon: Pokemon, ignorePp?: boolean): boolean { const isMoveDisabled = this.moveId && pokemon.summonData?.disabledMove === this.moveId; + + // for taunt: check valid move, pokemon is taunted, + const isMoveDisabledTaunt = this.moveId && pokemon.summonData.taunted && this.getMove().category === MoveCategory.STATUS; + // for torment: check valid move, pokemon is tormented, pokemon has moved this summon, and selected move is the same as previous move const isMoveDisabledTorment = this.moveId && pokemon.summonData.tormented && pokemon.getLastXMoves(1)[0] && pokemon.getLastXMoves(1)[0].move === this.moveId; - if (isMoveDisabled || isMoveDisabledTorment) + + if (isMoveDisabled || isMoveDisabledTaunt || isMoveDisabledTorment) return false; return (ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1) && !this.getMove().name.endsWith(' (N)'); } diff --git a/src/phases.ts b/src/phases.ts index ed9cb87e24c..9a8bb715e82 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2,7 +2,7 @@ import BattleScene, { AnySound, bypassLogin, startingWave } from "./battle-scene import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import * as Utils from './utils'; import { Moves } from "./data/enums/moves"; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr, SacrificialAttr } from "./data/move"; +import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr, SacrificialAttr, MoveCategory } from "./data/move"; import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; @@ -1732,7 +1732,7 @@ export class CommandPhase extends FieldPhase { const move = playerPokemon.getMoveset()[cursor]; this.scene.ui.setMode(Mode.MESSAGE); - // Decides between a Disabled, Not Implemented, Tormented, or No PP translation message + // Decides between a Disabled, Not Implemented, Taunted, Tormented, or No PP translation message var errorMessage; var canTranslate = true; if (playerPokemon.summonData.disabledMove === move.moveId) @@ -1742,6 +1742,9 @@ export class CommandPhase extends FieldPhase { else if (playerPokemon.summonData.tormented && playerPokemon.getLastXMoves(1)[0] && playerPokemon.getLastXMoves(1)[0].move === move.moveId) { errorMessage = getPokemonMessage(playerPokemon, ' can\'t use the same move twice in a row due to the torment!'); canTranslate = false; + } else if (playerPokemon.summonData.taunted && move.getMove().category === MoveCategory.STATUS) { + errorMessage = getPokemonMessage(playerPokemon, ' can\'t use ' + move.getName() + ' after the taunt!'); + canTranslate = false; } else errorMessage = 'battle:moveNoPP'; @@ -2108,7 +2111,16 @@ export class TurnEndPhase extends FieldPhase { pokemon.summonData.justTormented = false; pokemon.summonData.tormented = true; } - + + if (pokemon.summonData.justTaunted) { + pokemon.summonData.justTaunted = false; + } + + if (pokemon.summonData.taunted && !--pokemon.summonData.tauntedTurns) { + this.scene.pushPhase(new MessagePhase(this.scene, getPokemonMessage(pokemon, " shook off the taunt!"))); + pokemon.summonData.taunted = false; + } + if (pokemon.summonData.disabledMove && !--pokemon.summonData.disabledTurns) { this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('battle:notDisabled', { pokemonName: `${getPokemonPrefix(pokemon)}${pokemon.name}`, moveName: allMoves[pokemon.summonData.disabledMove].name }))); pokemon.summonData.disabledMove = Moves.NONE; @@ -2259,6 +2271,11 @@ export class MovePhase extends BattlePhase { if (!this.canMove()) { if (this.move.moveId && this.pokemon.summonData.disabledMove === this.move.moveId) this.scene.queueMessage(`${this.move.getName()} is disabled!`); + else if (this.pokemon.summonData.taunted && this.move.getMove().category === MoveCategory.STATUS) { + if (this.pokemon.summonData.justTaunted) + this.pokemon.summonData.tauntedTurns--; + this.scene.queueMessage(getPokemonMessage(this.pokemon, ' can\'t use ' + this.move.getName() + ' after the taunt!')) + } return this.end(); } @@ -2711,6 +2728,12 @@ export class MoveEndPhase extends PokemonPhase { this.scene.arena.setIgnoreAbilities(false); + // if pokemon was taunted this turn and moved after the pokemon who taunted it, + // decrement taunt duration by 1 + if (pokemon.summonData.justTaunted) { + pokemon.summonData.tauntedTurns--; + } + this.end(); } } diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index e557d22e0f1..48282ee5233 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -118,6 +118,9 @@ export default class PokemonData { this.summonData.abilitySuppressed = source.summonData.abilitySuppressed; this.summonData.justTormented = source.summonData.justTormented; this.summonData.tormented = source.summonData.tormented; + this.summonData.justTaunted = source.summonData.justTaunted; + this.summonData.taunted = source.summonData.taunted; + this.summonData.tauntedTurns = source.summonData.tauntedTurns; this.summonData.ability = source.summonData.ability; this.summonData.moveset = source.summonData.moveset?.map(m => PokemonMove.loadMove(m));