pokerogue/src/data/battler-tag.ts

674 lines
21 KiB
TypeScript
Raw Normal View History

2023-04-18 09:30:47 -07:00
import { CommonAnim, CommonBattleAnim } from "./battle-anims";
2023-05-06 09:13:35 -07:00
import { CommonAnimPhase, DamagePhase, MovePhase, ObtainStatusEffectPhase, PokemonHealPhase, ShowAbilityPhase } from "../battle-phases";
2023-04-20 12:46:05 -07:00
import { getPokemonMessage } from "../messages";
2023-05-06 09:13:35 -07:00
import Pokemon, { MoveResult } from "../pokemon";
2023-04-14 22:32:16 -07:00
import { Stat } from "./pokemon-stat";
2023-04-19 13:52:14 -07:00
import { StatusEffect } from "./status-effect";
2023-04-20 12:46:05 -07:00
import * as Utils from "../utils";
2023-04-28 12:03:42 -07:00
import { Moves, allMoves } from "./move";
2023-04-22 19:14:53 -07:00
import { Type } from "./type";
2023-05-06 09:13:35 -07:00
import { Abilities } from "./ability";
2023-04-14 22:32:16 -07:00
2023-04-21 16:30:04 -07:00
export enum BattlerTagType {
2023-04-13 09:16:36 -07:00
NONE,
2023-04-20 18:32:48 -07:00
RECHARGING,
FLINCHED,
2023-04-14 22:32:16 -07:00
CONFUSED,
INFATUATED,
2023-04-18 09:30:47 -07:00
SEEDED,
2023-04-16 15:40:32 -07:00
NIGHTMARE,
2023-04-14 22:32:16 -07:00
FRENZY,
2023-04-19 13:52:14 -07:00
INGRAIN,
AQUA_RING,
DROWSY,
2023-04-22 19:14:53 -07:00
TRAPPED,
2023-04-22 12:01:48 -07:00
BIND,
WRAP,
FIRE_SPIN,
WHIRLPOOL,
CLAMP,
SAND_TOMB,
MAGMA_STORM,
2023-04-18 09:30:47 -07:00
PROTECTED,
2023-05-06 09:13:35 -07:00
TRUANT,
2023-04-13 09:16:36 -07:00
FLYING,
2023-04-15 21:29:55 -07:00
UNDERGROUND,
2023-04-26 13:07:29 -07:00
HIDDEN,
FIRE_BOOST,
2023-04-24 22:32:48 -07:00
CRIT_BOOST,
2023-04-19 13:52:14 -07:00
NO_CRIT,
2023-04-27 17:12:25 -07:00
IGNORE_ACCURACY,
2023-04-16 15:40:32 -07:00
BYPASS_SLEEP,
2023-04-15 21:29:55 -07:00
IGNORE_FLYING
2023-04-13 09:16:36 -07:00
}
2023-04-21 16:30:04 -07:00
export enum BattlerTagLapseType {
2023-04-13 09:16:36 -07:00
FAINT,
MOVE,
2023-04-16 15:40:32 -07:00
AFTER_MOVE,
2023-04-14 22:32:16 -07:00
MOVE_EFFECT,
TURN_END,
CUSTOM
2023-04-13 09:16:36 -07:00
}
2023-04-21 16:30:04 -07:00
export class BattlerTag {
public tagType: BattlerTagType;
public lapseType: BattlerTagLapseType;
2023-04-13 09:16:36 -07:00
public turnCount: integer;
2023-04-22 19:14:53 -07:00
public sourceMove: Moves;
public sourceId?: integer;
2023-04-13 09:16:36 -07:00
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: integer, sourceMove: Moves, sourceId?: integer) {
2023-04-13 09:16:36 -07:00
this.tagType = tagType;
this.lapseType = lapseType;
this.turnCount = turnCount;
2023-04-22 19:14:53 -07:00
this.sourceMove = sourceMove;
this.sourceId = sourceId;
2023-04-22 19:14:53 -07:00
}
canAdd(pokemon: Pokemon): boolean {
return true;
2023-04-13 09:16:36 -07:00
}
2023-04-14 22:32:16 -07:00
onAdd(pokemon: Pokemon): void { }
onRemove(pokemon: Pokemon): void { }
onOverlap(pokemon: Pokemon): void { }
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
return --this.turnCount > 0;
}
2023-04-22 19:14:53 -07:00
getDescriptor(): string {
return '';
}
isSourceLinked(): boolean {
return false;
}
2023-04-22 19:14:53 -07:00
getMoveName(): string {
return this.sourceMove
? allMoves[this.sourceMove].name
: null;
}
}
2023-04-21 16:30:04 -07:00
export class RechargingTag extends BattlerTag {
constructor(sourceMove: Moves) {
super(BattlerTagType.RECHARGING, BattlerTagLapseType.MOVE, 1, sourceMove);
2023-04-20 18:32:48 -07:00
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
pokemon.getMoveQueue().push({ move: Moves.NONE })
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
2023-04-20 18:32:48 -07:00
super.lapse(pokemon, lapseType);
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' must\nrecharge!'));
2023-04-20 18:32:48 -07:00
return true;
}
}
2023-04-22 19:14:53 -07:00
export class TrappedTag extends BattlerTag {
constructor(tagType: BattlerTagType, lapseType: BattlerTagLapseType, turnCount: integer, sourceMove: Moves, sourceId: integer) {
super(tagType, lapseType, turnCount, sourceMove, sourceId);
2023-04-22 19:14:53 -07:00
}
canAdd(pokemon: Pokemon): boolean {
return !pokemon.isOfType(Type.GHOST) && !pokemon.getTag(BattlerTagType.TRAPPED);
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
pokemon.scene.queueMessage(this.getTrapMessage(pokemon));
}
onRemove(pokemon: Pokemon): void {
super.onRemove(pokemon);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` was freed\nfrom ${this.getMoveName()}!`));
}
getDescriptor(): string {
return 'trapping';
}
isSourceLinked(): boolean {
return true;
}
2023-04-22 19:14:53 -07:00
getTrapMessage(pokemon: Pokemon): string {
return getPokemonMessage(pokemon, ' can no\nlonger escape!');
}
}
2023-04-21 16:30:04 -07:00
export class FlinchedTag extends BattlerTag {
constructor(sourceMove: Moves) {
super(BattlerTagType.FLINCHED, BattlerTagLapseType.MOVE, 0, sourceMove);
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
2023-04-16 15:40:32 -07:00
super.lapse(pokemon, lapseType);
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' flinched!'));
return true;
2023-04-14 22:32:16 -07:00
}
getDescriptor(): string {
return 'flinching';
}
2023-04-14 22:32:16 -07:00
}
2023-04-22 19:14:53 -07:00
export class ConfusedTag extends BattlerTag {
constructor(turnCount: integer, sourceMove: Moves) {
super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove);
2023-04-14 22:32:16 -07:00
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CONFUSION));
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' became\nconfused!'));
2023-04-14 22:32:16 -07:00
}
onRemove(pokemon: Pokemon): void {
super.onRemove(pokemon);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' snapped\nout of confusion!'));
2023-04-14 22:32:16 -07:00
}
onOverlap(pokemon: Pokemon): void {
super.onOverlap(pokemon);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nalready confused!'));
2023-04-14 22:32:16 -07:00
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = lapseType !== BattlerTagLapseType.CUSTOM && super.lapse(pokemon, lapseType);
2023-04-14 22:32:16 -07:00
if (ret) {
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nconfused!'));
2023-04-14 22:32:16 -07:00
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CONFUSION));
if (Utils.randInt(2)) {
const atk = pokemon.getBattleStat(Stat.ATK);
const def = pokemon.getBattleStat(Stat.DEF);
const damage = Math.ceil(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * ((Utils.randInt(15) + 85) / 100));
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage('It hurt itself in its\nconfusion!');
2023-04-16 15:40:32 -07:00
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer()));
2023-04-23 18:31:06 -07:00
pokemon.damage(damage);
2023-04-14 22:32:16 -07:00
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
}
2023-04-13 09:16:36 -07:00
}
2023-04-14 22:32:16 -07:00
return ret;
}
getDescriptor(): string {
return 'confusion';
}
}
export class InfatuatedTag extends BattlerTag {
constructor(sourceMove: integer, sourceId: integer) {
super(BattlerTagType.INFATUATED, BattlerTagLapseType.MOVE, 1, sourceMove, sourceId);
}
canAdd(pokemon: Pokemon): boolean {
return pokemon.isOppositeGender(pokemon.scene.getPokemonById(this.sourceId));
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` fell in love\nwith ${pokemon.scene.getPokemonById(this.sourceId).name}!`));
}
onOverlap(pokemon: Pokemon): void {
super.onOverlap(pokemon);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nalready in love!'));
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
if (ret) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is in love\nwith ${pokemon.scene.getPokemonById(this.sourceId).name}!`));
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.ATTRACT));
if (Utils.randInt(2)) {
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nimmobilized by love!'));
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
}
}
return ret;
}
onRemove(pokemon: Pokemon): void {
super.onRemove(pokemon);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' got over\nits infatuation.'));
}
getDescriptor(): string {
return 'infatuation';
}
2023-04-14 22:32:16 -07:00
}
2023-04-22 19:14:53 -07:00
export class SeedTag extends BattlerTag {
2023-04-28 16:26:41 -07:00
constructor(sourceId: integer) {
super(BattlerTagType.SEEDED, BattlerTagLapseType.AFTER_MOVE, 1, Moves.LEECH_SEED, sourceId);
2023-04-18 09:30:47 -07:00
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' was seeded!'));
2023-04-18 09:30:47 -07:00
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
2023-04-18 09:30:47 -07:00
if (ret) {
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, !pokemon.isPlayer(), CommonAnim.LEECH_SEED));
const damage = Math.max(Math.floor(pokemon.getMaxHp() / 8), 1);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer()));
2023-04-23 18:31:06 -07:00
pokemon.damage(damage);
2023-04-18 09:30:47 -07:00
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, !pokemon.isPlayer(), damage, getPokemonMessage(pokemon, '\'s health is\nsapped by LEECH SEED!'), false, true));
}
return ret;
}
getDescriptor(): string {
return 'seeding';
}
2023-04-18 09:30:47 -07:00
}
2023-04-22 19:14:53 -07:00
export class NightmareTag extends BattlerTag {
2023-04-16 15:40:32 -07:00
constructor() {
super(BattlerTagType.NIGHTMARE, BattlerTagLapseType.AFTER_MOVE, 1, Moves.NIGHTMARE);
2023-04-16 15:40:32 -07:00
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' began\nhaving a NIGHTMARE!'));
2023-04-16 15:40:32 -07:00
}
onOverlap(pokemon: Pokemon): void {
super.onOverlap(pokemon);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nalready locked in a NIGHTMARE!'));
2023-04-16 15:40:32 -07:00
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
2023-04-16 15:40:32 -07:00
if (ret) {
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is locked\nin a NIGHTMARE!'));
2023-04-16 15:40:32 -07:00
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), CommonAnim.CURSE)); // TODO: Update animation type
const damage = Math.ceil(pokemon.getMaxHp() / 4);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer()));
2023-04-23 18:31:06 -07:00
pokemon.damage(damage);
2023-04-16 15:40:32 -07:00
}
return ret;
}
getDescriptor(): string {
return 'nightmares';
}
2023-04-16 15:40:32 -07:00
}
2023-04-22 19:14:53 -07:00
export class IngrainTag extends TrappedTag {
constructor(sourceId: integer) {
super(BattlerTagType.INGRAIN, BattlerTagLapseType.TURN_END, 1, Moves.INGRAIN, sourceId);
2023-04-19 13:52:14 -07:00
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
2023-04-19 13:52:14 -07:00
if (ret)
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), Math.floor(pokemon.getMaxHp() / 16),
getPokemonMessage(pokemon, ` absorbed\nnutrients with its roots!`), true));
return ret;
}
2023-04-22 19:14:53 -07:00
getTrapMessage(pokemon: Pokemon): string {
return getPokemonMessage(pokemon, ' planted its roots!');
}
getDescriptor(): string {
return 'roots';
}
2023-04-19 13:52:14 -07:00
}
2023-04-22 19:14:53 -07:00
export class AquaRingTag extends BattlerTag {
2023-04-19 13:52:14 -07:00
constructor() {
super(BattlerTagType.AQUA_RING, BattlerTagLapseType.TURN_END, 1, Moves.AQUA_RING, undefined);
2023-04-19 13:52:14 -07:00
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' surrounded\nitself with a veil of water!'));
2023-04-19 13:52:14 -07:00
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
2023-04-19 13:52:14 -07:00
if (ret)
2023-04-22 19:14:53 -07:00
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.isPlayer(), Math.floor(pokemon.getMaxHp() / 16), `${this.getMoveName()} restored\n${pokemon.name}\'s HP!`, true));
2023-04-19 13:52:14 -07:00
return ret;
}
}
2023-04-21 16:30:04 -07:00
export class DrowsyTag extends BattlerTag {
2023-04-19 13:52:14 -07:00
constructor() {
super(BattlerTagType.DROWSY, BattlerTagLapseType.TURN_END, 2, Moves.YAWN);
2023-04-19 13:52:14 -07:00
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' grew drowsy!'));
2023-04-19 13:52:14 -07:00
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
2023-04-19 13:52:14 -07:00
if (!super.lapse(pokemon, lapseType)) {
pokemon.scene.unshiftPhase(new ObtainStatusEffectPhase(pokemon.scene, pokemon.isPlayer(), StatusEffect.SLEEP));
return false;
}
return true;
}
getDescriptor(): string {
return 'drowsiness';
}
2023-04-19 13:52:14 -07:00
}
2023-04-22 19:14:53 -07:00
export abstract class DamagingTrapTag extends TrappedTag {
2023-04-22 12:01:48 -07:00
private commonAnim: CommonAnim;
constructor(tagType: BattlerTagType, commonAnim: CommonAnim, turnCount: integer, sourceMove: Moves, sourceId: integer) {
super(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove, sourceId);
2023-04-22 12:01:48 -07:00
this.commonAnim = commonAnim;
}
2023-04-22 19:14:53 -07:00
canAdd(pokemon: Pokemon): boolean {
return !pokemon.isOfType(Type.GHOST) && !pokemon.findTag(t => t instanceof DamagingTrapTag);
2023-04-22 12:01:48 -07:00
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
2023-04-22 19:14:53 -07:00
const ret = super.lapse(pokemon, lapseType);
2023-04-22 12:01:48 -07:00
if (ret) {
2023-04-22 19:14:53 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` is hurt\nby ${this.getMoveName()}!`));
2023-04-22 12:01:48 -07:00
pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.isPlayer(), this.commonAnim));
const damage = Math.ceil(pokemon.getMaxHp() / 16);
pokemon.scene.unshiftPhase(new DamagePhase(pokemon.scene, pokemon.isPlayer()));
2023-05-02 17:53:06 -07:00
pokemon.damage(damage);
2023-04-22 12:01:48 -07:00
}
return ret;
}
}
2023-04-22 19:14:53 -07:00
export class BindTag extends DamagingTrapTag {
constructor(turnCount: integer, sourceId: integer) {
super(BattlerTagType.BIND, CommonAnim.BIND, turnCount, Moves.BIND, sourceId);
2023-04-22 12:01:48 -07:00
}
getTrapMessage(pokemon: Pokemon): string {
return getPokemonMessage(pokemon, ` was squeezed by\n${pokemon.scene.getPokemonById(this.sourceId).name}'s ${this.getMoveName()}!`);
2023-04-22 12:01:48 -07:00
}
}
2023-04-22 19:14:53 -07:00
export class WrapTag extends DamagingTrapTag {
constructor(turnCount: integer, sourceId: integer) {
super(BattlerTagType.WRAP, CommonAnim.WRAP, turnCount, Moves.WRAP, sourceId);
2023-04-22 12:01:48 -07:00
}
getTrapMessage(pokemon: Pokemon): string {
return getPokemonMessage(pokemon, ` was WRAPPED\nby ${pokemon.scene.getPokemonById(this.sourceId).name}!`);
2023-04-22 12:01:48 -07:00
}
}
2023-04-22 19:14:53 -07:00
export abstract class VortexTrapTag extends DamagingTrapTag {
constructor(tagType: BattlerTagType, commonAnim: CommonAnim, turnCount: integer, sourceMove: Moves, sourceId: integer) {
super(tagType, commonAnim, turnCount, sourceMove, sourceId);
2023-04-22 12:01:48 -07:00
}
getTrapMessage(pokemon: Pokemon): string {
return getPokemonMessage(pokemon, ' was trapped\nin the vortex!');
}
}
2023-04-22 19:14:53 -07:00
export class FireSpinTag extends VortexTrapTag {
constructor(turnCount: integer, sourceId: integer) {
super(BattlerTagType.FIRE_SPIN, CommonAnim.FIRE_SPIN, turnCount, Moves.FIRE_SPIN, sourceId);
2023-04-22 12:01:48 -07:00
}
2023-04-22 19:14:53 -07:00
}
2023-04-22 12:01:48 -07:00
2023-04-22 19:14:53 -07:00
export class WhirlpoolTag extends VortexTrapTag {
constructor(turnCount: integer, sourceId: integer) {
super(BattlerTagType.WHIRLPOOL, CommonAnim.WHIRLPOOL, turnCount, Moves.WHIRLPOOL, sourceId);
2023-04-22 12:01:48 -07:00
}
}
2023-04-22 19:14:53 -07:00
export class ClampTag extends DamagingTrapTag {
constructor(turnCount: integer, sourceId: integer) {
super(BattlerTagType.CLAMP, CommonAnim.CLAMP, turnCount, Moves.CLAMP, sourceId);
2023-04-22 12:01:48 -07:00
}
getTrapMessage(pokemon: Pokemon): string {
2023-04-22 19:14:53 -07:00
return getPokemonMessage(pokemon.scene.getPokemonById(this.sourceId), ` CLAMPED\n${pokemon.name}!`);
2023-04-22 12:01:48 -07:00
}
}
2023-04-22 19:14:53 -07:00
export class SandTombTag extends DamagingTrapTag {
constructor(turnCount: integer, sourceId: integer) {
super(BattlerTagType.SAND_TOMB, CommonAnim.SAND_TOMB, turnCount, Moves.SAND_TOMB, sourceId);
2023-04-22 12:01:48 -07:00
}
getTrapMessage(pokemon: Pokemon): string {
2023-04-22 19:14:53 -07:00
return getPokemonMessage(pokemon.scene.getPokemonById(this.sourceId), ` became trapped\nby ${this.getMoveName()}!`);
2023-04-22 12:01:48 -07:00
}
}
2023-04-22 19:14:53 -07:00
export class MagmaStormTag extends DamagingTrapTag {
constructor(turnCount: integer, sourceId: integer) {
super(BattlerTagType.MAGMA_STORM, CommonAnim.MAGMA_STORM, turnCount, Moves.MAGMA_STORM, sourceId);
2023-04-22 12:01:48 -07:00
}
getTrapMessage(pokemon: Pokemon): string {
return getPokemonMessage(pokemon, ` became trapped\nby swirling magma!`);
}
}
2023-04-21 16:30:04 -07:00
export class ProtectedTag extends BattlerTag {
constructor(sourceMove: Moves) {
super(BattlerTagType.PROTECTED, BattlerTagLapseType.CUSTOM, 0, sourceMove);
2023-04-18 09:30:47 -07:00
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, '\nprotected itself!'));
2023-04-18 09:30:47 -07:00
}
2023-04-21 16:30:04 -07:00
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
if (lapseType === BattlerTagLapseType.CUSTOM) {
2023-04-18 09:30:47 -07:00
new CommonBattleAnim(CommonAnim.PROTECT, pokemon).play(pokemon.scene);
2023-04-21 16:30:04 -07:00
pokemon.scene.queueMessage(getPokemonMessage(pokemon, '\nprotected itself!'));
2023-04-18 09:30:47 -07:00
return true;
}
return super.lapse(pokemon, lapseType);
}
}
2023-05-06 09:13:35 -07:00
export class TruantTag extends BattlerTag {
constructor() {
super(BattlerTagType.TRUANT, BattlerTagLapseType.MOVE, 1, undefined);
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
if (pokemon.getAbility().id !== Abilities.TRUANT)
return super.lapse(pokemon, lapseType);
const lastMove = pokemon.getLastXMoves().find(() => true);
if (lastMove && lastMove.move !== Moves.NONE) {
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
pokemon.scene.unshiftPhase(new ShowAbilityPhase(pokemon.scene, pokemon.isPlayer()));
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is\nloafing around!'));
}
return true;
}
}
2023-04-21 16:30:04 -07:00
export class HideSpriteTag extends BattlerTag {
constructor(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves) {
super(tagType, BattlerTagLapseType.MOVE_EFFECT, turnCount, sourceMove);
2023-04-14 22:32:16 -07:00
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
pokemon.setVisible(false);
}
onRemove(pokemon: Pokemon): void {
// Wait 2 frames before setting visible for battle animations that don't immediately show the sprite invisible
pokemon.scene.tweens.addCounter({
duration: 2,
useFrames: true,
onComplete: () => pokemon.setVisible(true)
});
}
}
2023-04-13 09:16:36 -07:00
export class TypeBoostTag extends BattlerTag {
public boostedType: Type;
constructor(tagType: BattlerTagType, sourceMove: Moves, boostedType: Type) {
super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove);
this.boostedType = boostedType;
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
return lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
}
}
2023-04-24 22:32:48 -07:00
export class CritBoostTag extends BattlerTag {
constructor(tagType: BattlerTagType, sourceMove: Moves) {
super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove);
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' is getting\npumped!'));
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
return lapseType !== BattlerTagLapseType.CUSTOM || super.lapse(pokemon, lapseType);
}
onRemove(pokemon: Pokemon): void {
super.onRemove(pokemon);
pokemon.scene.queueMessage(getPokemonMessage(pokemon, ' relaxed.'));
}
}
2023-04-27 17:12:25 -07:00
export class IgnoreAccuracyTag extends BattlerTag {
constructor(sourceMove: Moves) {
super(BattlerTagType.IGNORE_ACCURACY, BattlerTagLapseType.TURN_END, 1, sourceMove);
}
}
export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourceMove: Moves, sourceId: integer): BattlerTag {
2023-04-14 22:32:16 -07:00
switch (tagType) {
2023-04-21 16:30:04 -07:00
case BattlerTagType.RECHARGING:
return new RechargingTag(sourceMove);
2023-04-21 16:30:04 -07:00
case BattlerTagType.FLINCHED:
return new FlinchedTag(sourceMove);
2023-04-21 16:30:04 -07:00
case BattlerTagType.CONFUSED:
return new ConfusedTag(turnCount, sourceMove);
case BattlerTagType.INFATUATED:
return new InfatuatedTag(sourceMove, sourceId);
2023-04-21 16:30:04 -07:00
case BattlerTagType.SEEDED:
2023-04-28 16:26:41 -07:00
return new SeedTag(sourceId);
2023-04-21 16:30:04 -07:00
case BattlerTagType.NIGHTMARE:
2023-04-16 15:40:32 -07:00
return new NightmareTag();
2023-04-22 10:16:45 -07:00
case BattlerTagType.INGRAIN:
2023-04-22 19:14:53 -07:00
return new IngrainTag(sourceId);
2023-04-21 16:30:04 -07:00
case BattlerTagType.AQUA_RING:
2023-04-19 13:52:14 -07:00
return new AquaRingTag();
2023-04-21 16:30:04 -07:00
case BattlerTagType.DROWSY:
2023-04-19 13:52:14 -07:00
return new DrowsyTag();
2023-04-22 19:14:53 -07:00
case BattlerTagType.TRAPPED:
return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
2023-04-22 12:01:48 -07:00
case BattlerTagType.BIND:
2023-04-22 19:14:53 -07:00
return new BindTag(turnCount, sourceId);
2023-04-22 12:01:48 -07:00
case BattlerTagType.WRAP:
2023-04-22 19:14:53 -07:00
return new WrapTag(turnCount, sourceId);
2023-04-22 12:01:48 -07:00
case BattlerTagType.FIRE_SPIN:
2023-04-22 19:14:53 -07:00
return new FireSpinTag(turnCount, sourceId);
2023-04-22 12:01:48 -07:00
case BattlerTagType.WHIRLPOOL:
2023-04-22 19:14:53 -07:00
return new WhirlpoolTag(turnCount, sourceId);
2023-04-22 12:01:48 -07:00
case BattlerTagType.CLAMP:
2023-04-22 19:14:53 -07:00
return new ClampTag(turnCount, sourceId);
2023-04-22 12:01:48 -07:00
case BattlerTagType.SAND_TOMB:
2023-04-22 19:14:53 -07:00
return new SandTombTag(turnCount, sourceId);
2023-04-22 12:01:48 -07:00
case BattlerTagType.MAGMA_STORM:
2023-04-22 19:14:53 -07:00
return new MagmaStormTag(turnCount, sourceId);
2023-04-21 16:30:04 -07:00
case BattlerTagType.PROTECTED:
return new ProtectedTag(sourceMove);
2023-05-06 09:13:35 -07:00
case BattlerTagType.TRUANT:
return new TruantTag();
2023-04-21 16:30:04 -07:00
case BattlerTagType.FLYING:
case BattlerTagType.UNDERGROUND:
2023-04-26 13:07:29 -07:00
case BattlerTagType.HIDDEN:
return new HideSpriteTag(tagType, turnCount, sourceMove);
case BattlerTagType.FIRE_BOOST:
return new TypeBoostTag(tagType, sourceMove, Type.FIRE);
2023-04-24 22:32:48 -07:00
case BattlerTagType.CRIT_BOOST:
return new CritBoostTag(tagType, sourceMove);
2023-04-21 16:30:04 -07:00
case BattlerTagType.NO_CRIT:
return new BattlerTag(tagType, BattlerTagLapseType.AFTER_MOVE, turnCount, sourceMove);
2023-04-27 17:12:25 -07:00
case BattlerTagType.IGNORE_ACCURACY:
2023-04-28 12:03:42 -07:00
return new IgnoreAccuracyTag(sourceMove);
2023-04-21 16:30:04 -07:00
case BattlerTagType.BYPASS_SLEEP:
return new BattlerTag(BattlerTagType.BYPASS_SLEEP, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
2023-04-21 16:30:04 -07:00
case BattlerTagType.IGNORE_FLYING:
return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove);
2023-04-14 22:32:16 -07:00
default:
return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId);
2023-04-13 09:16:36 -07:00
}
}