diff --git a/src/battle-phases.ts b/src/battle-phases.ts index e85cd4123..5c72abf82 100644 --- a/src/battle-phases.ts +++ b/src/battle-phases.ts @@ -1,7 +1,7 @@ import BattleScene, { startingLevel, startingWave } from "./battle-scene"; import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult } from "./pokemon"; import * as Utils from './utils'; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveCategory, MoveEffectAttr, MoveFlags, MoveHitEffectAttr, Moves, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr } from "./data/move"; +import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveCategory, MoveEffectAttr, MoveFlags, MoveHitEffectAttr, Moves, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget } from "./data/move"; import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; @@ -1024,7 +1024,7 @@ abstract class MoveEffectPhase extends PokemonPhase { const isProtected = !this.move.getMove().hasFlag(MoveFlags.IGNORE_PROTECT) && target.lapseTag(BattlerTagType.PROTECTED); - new MoveAnim(this.move.getMove().id as Moves, user, target).play(this.scene, () => { + new MoveAnim(this.move.getMove().id as Moves, user).play(this.scene, () => { const result = !isProtected ? target.apply(user, this.move) : MoveResult.NO_EFFECT; ++user.turnData.hitCount; user.pushMoveHistory({ move: this.move.moveId, result: result, virtual: this.move.virtual }); @@ -1059,7 +1059,7 @@ abstract class MoveEffectPhase extends PokemonPhase { } hitCheck(): boolean { - if (this.move.getMove().selfTarget) + if (this.move.getMove().moveTarget === MoveTarget.USER) return true; const hiddenTag = this.getTargetPokemon().getTag(HiddenTag); @@ -1180,8 +1180,7 @@ export class MoveAnimTestPhase extends BattlePhase { initMoveAnim(moveId).then(() => { loadMoveAnimAssets(this.scene, [ moveId ], true) .then(() => { - new MoveAnim(moveId, player ? this.scene.getPlayerPokemon() : this.scene.getEnemyPokemon(), - player ? this.scene.getEnemyPokemon() : this.scene.getPlayerPokemon()).play(this.scene, () => { + new MoveAnim(moveId, player ? this.scene.getPlayerPokemon() : this.scene.getEnemyPokemon()).play(this.scene, () => { if (player) this.playMoveAnim(moveQueue, false); else diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index 71c2a66d3..6275fec7c 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -1,6 +1,6 @@ //import { battleAnimRawData } from "./battle-anim-raw-data"; import BattleScene from "../battle-scene"; -import { ChargeAttr, Moves, allMoves } from "./move"; +import { ChargeAttr, Moves, allMoves, getMoveTarget } from "./move"; import Pokemon from "../pokemon"; import * as Utils from "../utils"; //import fs from 'vite-plugin-fs/browser'; @@ -658,6 +658,8 @@ export abstract class BattleAnim { for (let frame of spriteFrames) { if (frame.target !== AnimFrameTarget.GRAPHIC) { const isUser = frame.target === AnimFrameTarget.USER; + if (isUser && target === user) + continue; const sprites = spriteCache[isUser ? AnimFrameTarget.USER : AnimFrameTarget.TARGET]; if ((isUser ? u : t) === sprites.length) { const spriteSource = isUser ? userSprite : targetSprite; @@ -829,8 +831,8 @@ export class CommonBattleAnim extends BattleAnim { export class MoveAnim extends BattleAnim { public move: Moves; - constructor(move: Moves, user: Pokemon, target: Pokemon) { - super(user, target); + constructor(move: Moves, user: Pokemon) { + super(user, getMoveTarget(user, move)); this.move = move; } @@ -849,8 +851,8 @@ export class MoveAnim extends BattleAnim { export class MoveChargeAnim extends MoveAnim { private chargeAnim: ChargeAnim; - constructor(chargeAnim: ChargeAnim, move: Moves, user: Pokemon, target: Pokemon) { - super(move, user, target); + constructor(chargeAnim: ChargeAnim, move: Moves, user: Pokemon) { + super(move, user); this.chargeAnim = chargeAnim; } diff --git a/src/data/move.ts b/src/data/move.ts index f5ba7b214..9af2b63e9 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1,7 +1,7 @@ import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./battle-anims"; -import { DamagePhase, EnemyMovePhase, MessagePhase, ObtainStatusEffectPhase, PlayerMovePhase, PokemonHealPhase, StatChangePhase } from "../battle-phases"; +import { DamagePhase, EnemyMovePhase, ObtainStatusEffectPhase, PlayerMovePhase, PokemonHealPhase, StatChangePhase } from "../battle-phases"; import { BattleStat } from "./battle-stat"; -import { BattlerTagType, IgnoreAccuracyTag } from "./battler-tag"; +import { BattlerTagType } from "./battler-tag"; import { getPokemonMessage } from "../messages"; import Pokemon, { EnemyPokemon, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../pokemon"; import { StatusEffect, getStatusEffectDescriptor } from "./status-effect"; @@ -18,6 +18,28 @@ export enum MoveCategory { STATUS } +export enum MoveTarget { + USER, + OTHER, + ALL_OTHERS, + NEAR_OTHER, + ALL_NEAR_OTHERS, + ENEMY, + NEAR_ENEMY, + ALL_NEAR_ENEMIES, + RANDOM_NEAR_ENEMY, + ALL_ENEMIES, + ATTACKER, + ALLY, + NEAR_ALLY, + USER_OR_NEAR_ALLY, + USER_AND_ALLIES, + ALL, + USER_SIDE, + ENEMY_SIDE, + BOTH_SIDES +} + export enum MoveFlags { MAKES_CONTACT = 1, IGNORE_PROTECT = 2, @@ -31,7 +53,7 @@ export default class Move { public name: string; public type: Type; public category: MoveCategory; - public selfTarget: boolean; + public moveTarget: MoveTarget; public power: integer; public accuracy: integer; public pp: integer; @@ -44,12 +66,12 @@ export default class Move { private conditions: MoveCondition[]; private flags: integer; - constructor(id: Moves, name: string, type: Type, category: MoveCategory, selfTarget: boolean, power: integer, accuracy: integer, pp: integer, tm: integer, effect: string, chance: integer, priority: integer, generation: integer) { + constructor(id: Moves, name: string, type: Type, category: MoveCategory, defaultMoveTarget: MoveTarget, power: integer, accuracy: integer, pp: integer, tm: integer, effect: string, chance: integer, priority: integer, generation: integer) { this.id = id; this.name = name.toUpperCase(); this.type = type; this.category = category; - this.selfTarget = selfTarget; + this.moveTarget = defaultMoveTarget; this.power = power; this.accuracy = accuracy; this.pp = pp; @@ -63,7 +85,7 @@ export default class Move { this.conditions = []; this.flags = 0; - if (selfTarget) + if (defaultMoveTarget === MoveTarget.USER) this.setFlag(MoveFlags.IGNORE_PROTECT, true); if (category === MoveCategory.PHYSICAL) this.setFlag(MoveFlags.MAKES_CONTACT, true); @@ -92,6 +114,11 @@ export default class Move { return this; } + target(moveTarget: MoveTarget): Move { + this.moveTarget = moveTarget; + return this; + } + hasFlag(flag: MoveFlags): boolean { return !!(this.flags & flag); } @@ -136,19 +163,19 @@ export default class Move { export class AttackMove extends Move { constructor(id: Moves, name: string, type: Type, category: MoveCategory, power: integer, accuracy: integer, pp: integer, tm: integer, effect: string, chance: integer, priority: integer, generation: integer) { - super(id, name, type, category, false, power, accuracy, pp, tm, effect, chance, priority, generation); + super(id, name, type, category, MoveTarget.NEAR_OTHER, power, accuracy, pp, tm, effect, chance, priority, generation); } } export class StatusMove extends Move { constructor(id: Moves, name: string, type: Type, accuracy: integer, pp: integer, tm: integer, effect: string, chance: integer, priority: integer, generation: integer) { - super(id, name, type, MoveCategory.STATUS, false, -1, accuracy, pp, tm, effect, chance, priority, generation); + super(id, name, type, MoveCategory.STATUS, MoveTarget.NEAR_OTHER, -1, accuracy, pp, tm, effect, chance, priority, generation); } } export class SelfStatusMove extends Move { constructor(id: Moves, name: string, type: Type, accuracy: integer, pp: integer, tm: integer, effect: string, chance: integer, priority: integer, generation: integer) { - super(id, name, type, MoveCategory.STATUS, true, -1, accuracy, pp, tm, effect, chance, priority, generation); + super(id, name, type, MoveCategory.STATUS, MoveTarget.USER, -1, accuracy, pp, tm, effect, chance, priority, generation); } } @@ -1106,7 +1133,7 @@ export class ChargeAttr extends OverrideMoveEffectAttr { const lastMove = user.getLastXMoves(1) as TurnMove[]; if (!lastMove.length || lastMove[0].move !== move.id || lastMove[0].result !== MoveResult.OTHER) { (args[0] as Utils.BooleanHolder).value = true; - new MoveChargeAnim(this.chargeAnim, move.id, user, target).play(user.scene, () => { + new MoveChargeAnim(this.chargeAnim, move.id, user).play(user.scene, () => { user.scene.queueMessage(getPokemonMessage(user, ` ${this.chargeText.replace('{TARGET}', target.name)}`)); if (this.tagType) user.addTag(this.tagType, 1, move.id, user.id); @@ -1838,6 +1865,22 @@ export function applyFilteredMoveAttrs(attrFilter: MoveAttrFilter, user: Pokemon return applyMoveAttrsInternal(attrFilter, user, target, move, args); } +export function getMoveTarget(user: Pokemon, move: Moves): Pokemon { + const moveTarget = allMoves[move].moveTarget; + + const other = user.isPlayer() ? user.scene.getEnemyPokemon() : user.scene.getPlayerPokemon(); + + switch (moveTarget) { + case MoveTarget.USER: + case MoveTarget.USER_OR_NEAR_ALLY: + case MoveTarget.USER_AND_ALLIES: + case MoveTarget.USER_SIDE: + return user; + default: + return other; + } +} + export const allMoves = [ new StatusMove(Moves.NONE, "-", Type.NORMAL, MoveCategory.STATUS, -1, -1, "", -1, 0, 1), ]; @@ -1865,18 +1908,21 @@ export function initMoves() { new AttackMove(Moves.GUILLOTINE, "Guillotine", Type.NORMAL, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 1) .attr(OneHitKOAttr), new AttackMove(Moves.RAZOR_WIND, "Razor Wind", Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, "Charges on first turn, attacks on second. High critical hit ratio.", -1, 0, 1) - .attr(ChargeAttr, ChargeAnim.RAZOR_WIND_CHARGING, 'whipped\nup a whirlwind!') + .attr(ChargeAttr, ChargeAnim.RAZOR_WIND_CHARGING, 'whipped$$$up a whirlwind!') .attr(HighCritAttr) - .ignoresVirtual(), + .ignoresVirtual() + .target(MoveTarget.ALL_NEAR_ENEMIES), new SelfStatusMove(Moves.SWORDS_DANCE, "Swords Dance", Type.NORMAL, -1, 20, 88, "Sharply raises user's Attack.", -1, 0, 1) .attr(StatChangeAttr, BattleStat.ATK, 2, true), new AttackMove(Moves.CUT, "Cut", Type.NORMAL, MoveCategory.PHYSICAL, 50, 95, 30, -1, "", -1, 0, 1), new AttackMove(Moves.GUST, "Gust", Type.FLYING, MoveCategory.SPECIAL, 40, 100, 35, -1, "Hits Pokémon using FLY/BOUNCE/SKY DROP with double power.", -1, 0, 1) - .attr(HitsTagAttr, BattlerTagType.FLYING, true), - new AttackMove(Moves.WING_ATTACK, "Wing Attack", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, -1, "", -1, 0, 1), + .attr(HitsTagAttr, BattlerTagType.FLYING, true) + .target(MoveTarget.OTHER), + new AttackMove(Moves.WING_ATTACK, "Wing Attack", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 35, -1, "", -1, 0, 1) + .target(MoveTarget.OTHER), new StatusMove(Moves.WHIRLWIND, "Whirlwind (N)", Type.NORMAL, -1, 20, -1, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, -6, 1), // TODO new AttackMove(Moves.FLY, "Fly", Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, 97, "Flies up on first turn, attacks on second turn.", -1, 0, 1) - .attr(ChargeAttr, ChargeAnim.FLY_CHARGING, 'flew\nup high!', BattlerTagType.FLYING) + .attr(ChargeAttr, ChargeAnim.FLY_CHARGING, 'flew$$$up high!', BattlerTagType.FLYING) .ignoresVirtual(), new AttackMove(Moves.BIND, "Bind", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 0, 1) .attr(TrapAttr, BattlerTagType.BIND), @@ -1912,9 +1958,11 @@ export function initMoves() { .attr(MissEffectAttr, frenzyMissFunc) .attr(ConfuseAttr, true), // TODO: Update to still confuse if last hit misses new AttackMove(Moves.DOUBLE_EDGE, "Double-Edge", Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, "User receives recoil damage.", -1, 0, 1) - .attr(RecoilAttr), + .attr(RecoilAttr) + .target(MoveTarget.RANDOM_NEAR_ENEMY), new StatusMove(Moves.TAIL_WHIP, "Tail Whip", Type.NORMAL, 100, 30, -1, "Lowers opponent's Defense.", -1, 0, 1) - .attr(StatChangeAttr, BattleStat.DEF, -1), + .attr(StatChangeAttr, BattleStat.DEF, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.POISON_STING, "Poison Sting", Type.POISON, MoveCategory.PHYSICAL, 15, 100, 35, -1, "May poison the opponent.", 30, 0, 1) .attr(StatusEffectAttr, StatusEffect.POISON) .makesContact(false), @@ -1926,11 +1974,13 @@ export function initMoves() { .attr(MultiHitAttr) .makesContact(false), new StatusMove(Moves.LEER, "Leer", Type.NORMAL, 100, 30, -1, "Lowers opponent's Defense.", 100, 0, 1) - .attr(StatChangeAttr, BattleStat.DEF, -1), + .attr(StatChangeAttr, BattleStat.DEF, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.BITE, "Bite", Type.DARK, MoveCategory.PHYSICAL, 60, 100, 25, -1, "May cause flinching.", 30, 0, 1) .attr(FlinchAttr), new StatusMove(Moves.GROWL, "Growl", Type.NORMAL, 100, 40, -1, "Lowers opponent's Attack.", -1, 0, 1) - .attr(StatChangeAttr, BattleStat.ATK, -1), + .attr(StatChangeAttr, BattleStat.ATK, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new StatusMove(Moves.ROAR, "Roar (N)", Type.NORMAL, -1, 20, -1, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, -6, 1), new StatusMove(Moves.SING, "Sing", Type.NORMAL, 55, 15, -1, "Puts opponent to sleep.", -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.SLEEP), @@ -1941,35 +1991,42 @@ export function initMoves() { new StatusMove(Moves.DISABLE, "Disable", Type.NORMAL, 100, 20, -1, "Opponent can't use its last attack for a few turns.", -1, 0, 1) .attr(DisableMoveAttr), new AttackMove(Moves.ACID, "Acid", Type.POISON, MoveCategory.SPECIAL, 40, 100, 30, -1, "May lower opponent's Special Defense.", 10, 0, 1) - .attr(StatChangeAttr, BattleStat.SPDEF, -1), + .attr(StatChangeAttr, BattleStat.SPDEF, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.EMBER, "Ember", Type.FIRE, MoveCategory.SPECIAL, 40, 100, 25, -1, "May burn opponent.", 10, 0, 1) .attr(StatusEffectAttr, StatusEffect.BURN), new AttackMove(Moves.FLAMETHROWER, "Flamethrower", Type.FIRE, MoveCategory.SPECIAL, 90, 100, 15, 125, "May burn opponent.", 10, 0, 1) .attr(StatusEffectAttr, StatusEffect.BURN), - new SelfStatusMove(Moves.MIST, "Mist (N)", Type.ICE, -1, 30, -1, "User's stats cannot be changed for a period of time.", -1, 0, 1), + new SelfStatusMove(Moves.MIST, "Mist (N)", Type.ICE, -1, 30, -1, "User's stats cannot be changed for a period of time.", -1, 0, 1) + .target(MoveTarget.USER_SIDE), new AttackMove(Moves.WATER_GUN, "Water Gun", Type.WATER, MoveCategory.SPECIAL, 40, 100, 25, -1, "", -1, 0, 1), new AttackMove(Moves.HYDRO_PUMP, "Hydro Pump", Type.WATER, MoveCategory.SPECIAL, 110, 80, 5, 142, "", -1, 0, 1), new AttackMove(Moves.SURF, "Surf", Type.WATER, MoveCategory.SPECIAL, 90, 100, 15, 123, "Hits all adjacent Pokémon.", -1, 0, 1), // TODO new AttackMove(Moves.ICE_BEAM, "Ice Beam", Type.ICE, MoveCategory.SPECIAL, 90, 100, 10, 135, "May freeze opponent.", 10, 0, 1) - .attr(StatusEffectAttr, StatusEffect.FREEZE), + .attr(StatusEffectAttr, StatusEffect.FREEZE) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.BLIZZARD, "Blizzard", Type.ICE, MoveCategory.SPECIAL, 110, 70, 5, 143, "May freeze opponent.", 10, 0, 1) .attr(BlizzardAccuracyAttr) .attr(StatusEffectAttr, StatusEffect.FREEZE), // TODO: 30% chance to hit protect/detect in hail new AttackMove(Moves.PSYBEAM, "Psybeam", Type.PSYCHIC, MoveCategory.SPECIAL, 65, 100, 20, 16, "May confuse opponent.", 10, 0, 1) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.BUBBLE_BEAM, "Bubble Beam", Type.WATER, MoveCategory.SPECIAL, 65, 100, 20, -1, "May lower opponent's Speed.", 10, 0, 1) .attr(StatChangeAttr, BattleStat.SPD, -1), new AttackMove(Moves.AURORA_BEAM, "Aurora Beam", Type.ICE, MoveCategory.SPECIAL, 65, 100, 20, -1, "May lower opponent's Attack.", 10, 0, 1) .attr(StatChangeAttr, BattleStat.ATK, -1), new AttackMove(Moves.HYPER_BEAM, "Hyper Beam", Type.NORMAL, MoveCategory.SPECIAL, 150, 90, 5, 163, "User must recharge next turn.", -1, 0, 1) .attr(AddBattlerTagAttr, BattlerTagType.RECHARGING, true), - new AttackMove(Moves.PECK, "Peck", Type.FLYING, MoveCategory.PHYSICAL, 35, 100, 35, -1, "", -1, 0, 1), - new AttackMove(Moves.DRILL_PECK, "Drill Peck", Type.FLYING, MoveCategory.PHYSICAL, 80, 100, 20, -1, "", -1, 0, 1), + new AttackMove(Moves.PECK, "Peck", Type.FLYING, MoveCategory.PHYSICAL, 35, 100, 35, -1, "", -1, 0, 1) + .target(MoveTarget.OTHER), + new AttackMove(Moves.DRILL_PECK, "Drill Peck", Type.FLYING, MoveCategory.PHYSICAL, 80, 100, 20, -1, "", -1, 0, 1) + .target(MoveTarget.OTHER), new AttackMove(Moves.SUBMISSION, "Submission", Type.FIGHTING, MoveCategory.PHYSICAL, 80, 80, 20, -1, "User receives recoil damage.", -1, 0, 1) .attr(RecoilAttr), new AttackMove(Moves.LOW_KICK, "Low Kick", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, 12, "The heavier the opponent, the stronger the attack.", -1, 0, 1) .attr(WeightPowerAttr), - new AttackMove(Moves.COUNTER, "Counter (N)", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, -1, "When hit by a Physical Attack, user strikes back with 2x power.", -1, -5, 1), + new AttackMove(Moves.COUNTER, "Counter (N)", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, -1, "When hit by a Physical Attack, user strikes back with 2x power.", -1, -5, 1) + .target(MoveTarget.ATTACKER), new AttackMove(Moves.SEISMIC_TOSS, "Seismic Toss", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 20, -1, "Inflicts damage equal to user's level (maximum 150).", -1, 0, 1) .attr(LevelPowerAttr), new AttackMove(Moves.STRENGTH, "Strength", Type.NORMAL, MoveCategory.PHYSICAL, 80, 100, 15, -1, "", -1, 0, 1), @@ -1984,7 +2041,8 @@ export function initMoves() { .attr(GrowthStatChangeAttr), new AttackMove(Moves.RAZOR_LEAF, "Razor Leaf", Type.GRASS, MoveCategory.PHYSICAL, 55, 95, 25, -1, "High critical hit ratio.", -1, 0, 1) .attr(HighCritAttr) - .makesContact(false), + .makesContact(false) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.SOLAR_BEAM, "Solar Beam", Type.GRASS, MoveCategory.SPECIAL, 120, 100, 10, 168, "Charges on first turn, attacks on second.", -1, 0, 1) .attr(SolarBeamChargeAttr) .attr(SolarBeamPowerAttr) @@ -1999,9 +2057,11 @@ export function initMoves() { .attr(FrenzyAttr) .attr(MissEffectAttr, frenzyMissFunc) .attr(ConfuseAttr, true) // TODO: Update to still confuse if last hit misses - .makesContact(), + .makesContact() + .target(MoveTarget.RANDOM_NEAR_ENEMY), new StatusMove(Moves.STRING_SHOT, "String Shot", Type.BUG, 95, 40, -1, "Sharply lowers opponent's Speed.", -1, 0, 1) - .attr(StatChangeAttr, BattleStat.SPD, -2), + .attr(StatChangeAttr, BattleStat.SPD, -2) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.DRAGON_RAGE, "Dragon Rage", Type.DRAGON, MoveCategory.SPECIAL, -1, 100, 10, -1, "Always inflicts 40 HP.", -1, 0, 1) .attr(FixedDamageAttr, 40), new AttackMove(Moves.FIRE_SPIN, "Fire Spin", Type.FIRE, MoveCategory.SPECIAL, 35, 85, 15, 24, "Traps opponent, damaging them for 4-5 turns.", 100, 0, 1) @@ -2019,7 +2079,8 @@ export function initMoves() { .makesContact(false), new AttackMove(Moves.EARTHQUAKE, "Earthquake", Type.GROUND, MoveCategory.PHYSICAL, 100, 100, 10, 149, "Power is doubled if opponent is underground from using DIG.", -1, 0, 1) .attr(HitsTagAttr, BattlerTagType.UNDERGROUND, true) - .makesContact(false), + .makesContact(false) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.FISSURE, "Fissure", Type.GROUND, MoveCategory.PHYSICAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 1) .attr(OneHitKOAttr) .makesContact(false), @@ -2066,13 +2127,17 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.DEF, 1, true), new SelfStatusMove(Moves.BARRIER, "Barrier", Type.PSYCHIC, -1, 20, -1, "Sharply raises user's Defense.", -1, 0, 1) .attr(StatChangeAttr, BattleStat.DEF, 2, true), - new SelfStatusMove(Moves.LIGHT_SCREEN, "Light Screen (N)", Type.PSYCHIC, -1, 30, 75, "Halves damage from Special attacks for 5 turns.", -1, 0, 1), - new SelfStatusMove(Moves.HAZE, "Haze (N)", Type.ICE, -1, 30, -1, "Resets all stat changes.", -1, 0, 1), - new SelfStatusMove(Moves.REFLECT, "Reflect (N)", Type.PSYCHIC, -1, 20, 74, "Halves damage from Physical attacks for 5 turns.", -1, 0, 1), + new SelfStatusMove(Moves.LIGHT_SCREEN, "Light Screen (N)", Type.PSYCHIC, -1, 30, 75, "Halves damage from Special attacks for 5 turns.", -1, 0, 1) + .target(MoveTarget.USER_SIDE), + new SelfStatusMove(Moves.HAZE, "Haze (N)", Type.ICE, -1, 30, -1, "Resets all stat changes.", -1, 0, 1) + .target(MoveTarget.BOTH_SIDES), + new SelfStatusMove(Moves.REFLECT, "Reflect (N)", Type.PSYCHIC, -1, 20, 74, "Halves damage from Physical attacks for 5 turns.", -1, 0, 1) + .target(MoveTarget.USER_SIDE), new SelfStatusMove(Moves.FOCUS_ENERGY, "Focus Energy", Type.NORMAL, -1, 30, -1, "Increases critical hit ratio.", -1, 0, 1) .attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, true, undefined, true), new AttackMove(Moves.BIDE, "Bide (N)", Type.NORMAL, MoveCategory.PHYSICAL, -1, -1, 10, -1, "User takes damage for two turns then strikes back double.", -1, 0, 1) - .ignoresVirtual(), + .ignoresVirtual() + .target(MoveTarget.ATTACKER), new SelfStatusMove(Moves.METRONOME, "Metronome", Type.NORMAL, -1, 10, 80, "User performs almost any move in the game at random.", -1, 0, 1) .attr(RandomMoveAttr) .ignoresVirtual(), @@ -2080,7 +2145,8 @@ export function initMoves() { .ignoresVirtual(), new AttackMove(Moves.SELF_DESTRUCT, "Self-Destruct", Type.NORMAL, MoveCategory.PHYSICAL, 200, 100, 5, -1, "User faints.", -1, 0, 1) .attr(SacrificialAttr) - .makesContact(false), + .makesContact(false) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.EGG_BOMB, "Egg Bomb", Type.NORMAL, MoveCategory.PHYSICAL, 100, 75, 10, -1, "", -1, 0, 1) .makesContact(false), new AttackMove(Moves.LICK, "Lick", Type.GHOST, MoveCategory.PHYSICAL, 30, 100, 30, -1, "May paralyze opponent.", 30, 0, 1) @@ -2098,9 +2164,10 @@ export function initMoves() { .attr(FlinchAttr), new AttackMove(Moves.CLAMP, "Clamp", Type.WATER, MoveCategory.PHYSICAL, 35, 85, 15, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 0, 1) .attr(TrapAttr, BattlerTagType.CLAMP), - new AttackMove(Moves.SWIFT, "Swift", Type.NORMAL, MoveCategory.SPECIAL, 60, -1, 20, 32, "Ignores Accuracy and Evasiveness.", -1, 0, 1), + new AttackMove(Moves.SWIFT, "Swift", Type.NORMAL, MoveCategory.SPECIAL, 60, -1, 20, 32, "Ignores Accuracy and Evasiveness.", -1, 0, 1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.SKULL_BASH, "Skull Bash", Type.NORMAL, MoveCategory.PHYSICAL, 130, 100, 10, -1, "Raises Defense on first turn, attacks on second.", 100, 0, 1) - .attr(ChargeAttr, ChargeAnim.SKULL_BASH_CHARGING, 'lowered\nits head!', null, true) + .attr(ChargeAttr, ChargeAnim.SKULL_BASH_CHARGING, 'lowered$$$its head!', null, true) .attr(StatChangeAttr, BattleStat.DEF, 1, true) .ignoresVirtual(), new AttackMove(Moves.SPIKE_CANNON, "Spike Cannon", Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 15, -1, "Hits 2-5 times in one turn.", -1, 0, 1) @@ -2122,7 +2189,8 @@ export function initMoves() { .attr(HitHealAttr) .condition((user: Pokemon, target: Pokemon, move: Move) => target.status?.effect === StatusEffect.SLEEP), new StatusMove(Moves.POISON_GAS, "Poison Gas", Type.POISON, 90, 40, -1, "Poisons opponent.", -1, 0, 1) - .attr(StatusEffectAttr, StatusEffect.POISON), + .attr(StatusEffectAttr, StatusEffect.POISON) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.BARRAGE, "Barrage", Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, "Hits 2-5 times in one turn.", -1, 0, 1) .attr(MultiHitAttr) .makesContact(false), @@ -2135,10 +2203,12 @@ export function initMoves() { .attr(HighCritAttr) .attr(FlinchAttr) .makesContact(false) - .ignoresVirtual(), + .ignoresVirtual() + .target(MoveTarget.OTHER), new SelfStatusMove(Moves.TRANSFORM, "Transform (N)", Type.NORMAL, -1, 10, -1, "User takes on the form and attacks of the opponent.", -1, 0, 1), new AttackMove(Moves.BUBBLE, "Bubble", Type.WATER, MoveCategory.SPECIAL, 40, 100, 30, -1, "May lower opponent's Speed.", 10, 0, 1) - .attr(StatChangeAttr, BattleStat.SPD, -1), + .attr(StatChangeAttr, BattleStat.SPD, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.DIZZY_PUNCH, "Dizzy Punch", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 10, -1, "May confuse opponent.", 20, 0, 1) .attr(ConfuseAttr), new StatusMove(Moves.SPORE, "Spore", Type.GRASS, 100, 15, -1, "Puts opponent to sleep.", -1, 0, 1) @@ -2154,7 +2224,8 @@ export function initMoves() { .attr(HighCritAttr), new AttackMove(Moves.EXPLOSION, "Explosion", Type.NORMAL, MoveCategory.PHYSICAL, 250, 100, 5, -1, "User faints.", -1, 0, 1) .attr(SacrificialAttr) - .makesContact(false), + .makesContact(false) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.FURY_SWIPES, "Fury Swipes", Type.NORMAL, MoveCategory.PHYSICAL, 18, 80, 15, -1, "Hits 2-5 times in one turn.", -1, 0, 1) .attr(MultiHitAttr), new AttackMove(Moves.BONEMERANG, "Bonemerang", Type.GROUND, MoveCategory.PHYSICAL, 50, 90, 10, -1, "Hits twice in one turn.", -1, 0, 1) @@ -2166,7 +2237,8 @@ export function initMoves() { .condition((user: Pokemon, target: Pokemon, move: Move) => user.status?.effect !== StatusEffect.SLEEP), new AttackMove(Moves.ROCK_SLIDE, "Rock Slide", Type.ROCK, MoveCategory.PHYSICAL, 75, 90, 10, 86, "May cause flinching.", 30, 0, 1) .attr(FlinchAttr) - .makesContact(false), + .makesContact(false) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.HYPER_FANG, "Hyper Fang", Type.NORMAL, MoveCategory.PHYSICAL, 80, 90, 15, -1, "May cause flinching.", 10, 0, 1) .attr(FlinchAttr), new SelfStatusMove(Moves.SHARPEN, "Sharpen", Type.NORMAL, -1, 30, -1, "Raises user's Attack.", -1, 0, 1) @@ -2185,7 +2257,8 @@ export function initMoves() { new AttackMove(Moves.STRUGGLE, "Struggle", Type.NORMAL, MoveCategory.PHYSICAL, 50, -1, -1, -1, "Only usable when all PP are gone. Hurts the user.", -1, 0, 1) .attr(RecoilAttr, true) .attr(TypelessAttr) - .ignoresVirtual(), + .ignoresVirtual() + .target(MoveTarget.RANDOM_NEAR_ENEMY), new SelfStatusMove(Moves.SKETCH, "Sketch", Type.NORMAL, -1, 1, -1, "Permanently copies the opponent's last move.", -1, 0, 2) .attr(SketchAttr) .ignoresVirtual(), @@ -2210,19 +2283,23 @@ export function initMoves() { .attr(BypassSleepAttr) .attr(FlinchAttr) .condition((user: Pokemon, target: Pokemon, move: Move) => user.status?.effect === StatusEffect.SLEEP), - new StatusMove(Moves.CURSE, "Curse (N)", Type.GHOST, -1, 10, -1, "Ghosts lose 50% of max HP and curse the opponent; Non-Ghosts raise Attack, Defense and lower Speed.", -1, 0, 2), + new StatusMove(Moves.CURSE, "Curse (N)", Type.GHOST, -1, 10, -1, "Ghosts lose 50% of max HP and curse the opponent; Non-Ghosts raise Attack, Defense and lower Speed.", -1, 0, 2) + .target(MoveTarget.USER), new AttackMove(Moves.FLAIL, "Flail", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 15, -1, "The lower the user's HP, the higher the power.", -1, 0, 2) .attr(LowHpPowerAttr), new SelfStatusMove(Moves.CONVERSION_2, "Conversion 2 (N)", Type.NORMAL, -1, 30, -1, "User changes type to become resistant to opponent's last move.", -1, 0, 2), new AttackMove(Moves.AEROBLAST, "Aeroblast", Type.FLYING, MoveCategory.SPECIAL, 100, 95, 5, -1, "High critical hit ratio.", -1, 0, 2) - .attr(HighCritAttr), + .attr(HighCritAttr) + .target(MoveTarget.OTHER), new StatusMove(Moves.COTTON_SPORE, "Cotton Spore", Type.GRASS, 100, 40, -1, "Sharply lowers opponent's Speed.", -1, 0, 2) - .attr(StatChangeAttr, BattleStat.SPD, -2), + .attr(StatChangeAttr, BattleStat.SPD, -2) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.REVERSAL, "Reversal", Type.FIGHTING, MoveCategory.PHYSICAL, -1, 100, 15, 134, "The lower the user's HP, the higher the power.", -1, 0, 2) .attr(LowHpPowerAttr), new StatusMove(Moves.SPITE, "Spite (N)", Type.GHOST, 100, 10, -1, "The opponent's last move loses 2-5 PP.", -1, 0, 2), new AttackMove(Moves.POWDER_SNOW, "Powder Snow", Type.ICE, MoveCategory.SPECIAL, 40, 100, 25, -1, "May freeze opponent.", 10, 0, 2) - .attr(StatusEffectAttr, StatusEffect.FREEZE), + .attr(StatusEffectAttr, StatusEffect.FREEZE) + .target(MoveTarget.ALL_NEAR_ENEMIES), new SelfStatusMove(Moves.PROTECT, "Protect", Type.NORMAL, -1, 10, 7, "Protects the user, but may fail if used consecutively.", -1, 4, 2) .attr(ProtectAttr), new AttackMove(Moves.MACH_PUNCH, "Mach Punch", Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 30, -1, "User attacks first.", -1, 1, 2), @@ -2239,16 +2316,19 @@ export function initMoves() { new AttackMove(Moves.OCTAZOOKA, "Octazooka", Type.WATER, MoveCategory.SPECIAL, 65, 85, 10, -1, "May lower opponent's Accuracy.", 50, 0, 2) .attr(StatChangeAttr, BattleStat.ACC, -1), new StatusMove(Moves.SPIKES, "Spikes", Type.GROUND, -1, 20, 90, "Hurts opponents when they switch into battle.", -1, 0, 2) - .attr(AddArenaTrapTagAttr, ArenaTagType.SPIKES), + .attr(AddArenaTrapTagAttr, ArenaTagType.SPIKES) + .target(MoveTarget.ENEMY_SIDE), new AttackMove(Moves.ZAP_CANNON, "Zap Cannon", Type.ELECTRIC, MoveCategory.SPECIAL, 120, 50, 5, -1, "Paralyzes opponent.", 100, 0, 2) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new StatusMove(Moves.FORESIGHT, "Foresight (N)", Type.NORMAL, -1, 40, -1, "Resets opponent's Evasiveness, and allows Normal- and Fighting-type attacks to hit Ghosts.", -1, 0, 2), // TODO new StatusMove(Moves.DESTINY_BOND, "Destiny Bond (N)", Type.GHOST, -1, 5, -1, "If the user faints, the opponent also faints.", -1, 0, 2) .ignoresProtect(), new StatusMove(Moves.PERISH_SONG, "Perish Song (N)", Type.NORMAL, -1, 5, -1, "Any Pokémon in play when this attack is used faints in 3 turns.", -1, 0, 2) - .ignoresProtect(), + .ignoresProtect() + .target(MoveTarget.ALL), new AttackMove(Moves.ICY_WIND, "Icy Wind", Type.ICE, MoveCategory.SPECIAL, 55, 95, 15, 34, "Lowers opponent's Speed.", 100, 0, 2) - .attr(StatChangeAttr, BattleStat.SPD, -1), + .attr(StatChangeAttr, BattleStat.SPD, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new SelfStatusMove(Moves.DETECT, "Detect", Type.FIGHTING, -1, 5, -1, "Protects the user, but may fail if used consecutively.", -1, 4, 2) .attr(ProtectAttr), new AttackMove(Moves.BONE_RUSH, "Bone Rush", Type.GROUND, MoveCategory.PHYSICAL, 25, 90, 10, -1, "Hits 2-5 times in one turn.", -1, 0, 2) @@ -2261,7 +2341,8 @@ export function initMoves() { .attr(MissEffectAttr, frenzyMissFunc) .attr(ConfuseAttr, true), // TODO: Update to still confuse if last hit misses new StatusMove(Moves.SANDSTORM, "Sandstorm", Type.ROCK, -1, 10, 51, "Creates a sandstorm for 5 turns.", -1, 0, 2) - .attr(WeatherChangeAttr, WeatherType.SANDSTORM), + .attr(WeatherChangeAttr, WeatherType.SANDSTORM) + .target(MoveTarget.RANDOM_NEAR_ENEMY), new AttackMove(Moves.GIGA_DRAIN, "Giga Drain", Type.GRASS, MoveCategory.SPECIAL, 75, 100, 10, 111, "User recovers half the HP inflicted on opponent.", -1, 4, 2) .attr(HitHealAttr), new SelfStatusMove(Moves.ENDURE, "Endure (N)", Type.NORMAL, -1, 10, 47, "Always left with at least 1 HP, but may fail if used consecutively.", -1, 0, 2), @@ -2288,18 +2369,21 @@ export function initMoves() { .attr(BypassSleepAttr) .attr(RandomMovesetMoveAttr) .condition((user: Pokemon, target: Pokemon, move: Move) => user.status?.effect === StatusEffect.SLEEP), - new SelfStatusMove(Moves.HEAL_BELL, "Heal Bell (N)", Type.NORMAL, -1, 5, -1, "Heals the user's party's status conditions.", -1, 0, 2), + new SelfStatusMove(Moves.HEAL_BELL, "Heal Bell (N)", Type.NORMAL, -1, 5, -1, "Heals the user's party's status conditions.", -1, 0, 2) + .target(MoveTarget.USER_AND_ALLIES), new AttackMove(Moves.RETURN, "Return (N)", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 20, -1, "Power increases with higher Friendship.", -1, 0, 2), new AttackMove(Moves.PRESENT, "Present (N)", Type.NORMAL, MoveCategory.PHYSICAL, -1, 90, 15, -1, "Either deals damage or heals.", -1, 0, 2) .makesContact(false), new AttackMove(Moves.FRUSTRATION, "Frustration (N)", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 20, -1, "Power decreases with higher Friendship.", -1, 0, 2), - new SelfStatusMove(Moves.SAFEGUARD, "Safeguard (N)", Type.NORMAL, -1, 25, -1, "The user's party is protected from status conditions.", -1, 0, 2), + new SelfStatusMove(Moves.SAFEGUARD, "Safeguard (N)", Type.NORMAL, -1, 25, -1, "The user's party is protected from status conditions.", -1, 0, 2) + .target(MoveTarget.USER_SIDE), new StatusMove(Moves.PAIN_SPLIT, "Pain Split (N)", Type.NORMAL, -1, 20, -1, "The user's and opponent's HP becomes the average of both.", -1, 0, 2), new AttackMove(Moves.SACRED_FIRE, "Sacred Fire", Type.FIRE, MoveCategory.PHYSICAL, 100, 95, 5, -1, "May burn opponent.", 50, 0, 2) .attr(StatusEffectAttr, StatusEffect.BURN) .makesContact(false), new AttackMove(Moves.MAGNITUDE, "Magnitude (N)", Type.GROUND, MoveCategory.PHYSICAL, -1, 100, 30, -1, "Hits with random power.", -1, 0, 2) - .makesContact(false), + .makesContact(false) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.DYNAMIC_PUNCH, "Dynamic Punch", Type.FIGHTING, MoveCategory.PHYSICAL, 100, 50, 5, -1, "Confuses opponent.", 100, 0, 2) .attr(ConfuseAttr), new AttackMove(Moves.MEGAHORN, "Megahorn", Type.BUG, MoveCategory.PHYSICAL, 120, 85, 10, -1, "", -1, 0, 2), @@ -2312,7 +2396,8 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPD, 1, true) .attr(LapseBattlerTagAttr, [ BattlerTagType.BIND, BattlerTagType.WRAP, BattlerTagType.FIRE_SPIN, BattlerTagType.WHIRLPOOL, BattlerTagType.CLAMP, BattlerTagType.SAND_TOMB, BattlerTagType.MAGMA_STORM ], true), new StatusMove(Moves.SWEET_SCENT, "Sweet Scent", Type.NORMAL, 100, 20, -1, "Lowers opponent's Evasiveness.", -1, 0, 2) - .attr(StatChangeAttr, BattleStat.EVA, -1), + .attr(StatChangeAttr, BattleStat.EVA, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.IRON_TAIL, "Iron Tail", Type.STEEL, MoveCategory.PHYSICAL, 100, 75, 15, -1, "May lower opponent's Defense.", 30, 0, 2) .attr(StatChangeAttr, BattleStat.DEF, -1), new AttackMove(Moves.METAL_CLAW, "Metal Claw", Type.STEEL, MoveCategory.PHYSICAL, 50, 95, 35, 31, "May raise user's Attack.", 10, 0, 2) @@ -2331,12 +2416,15 @@ export function initMoves() { .attr(HitsTagAttr, BattlerTagType.FLYING, true) .attr(FlinchAttr), // TODO new SelfStatusMove(Moves.RAIN_DANCE, "Rain Dance", Type.WATER, -1, 5, 50, "Makes it rain for 5 turns.", -1, 0, 2) - .attr(WeatherChangeAttr, WeatherType.RAIN), + .attr(WeatherChangeAttr, WeatherType.RAIN) + .target(MoveTarget.ALL_NEAR_ENEMIES), new SelfStatusMove(Moves.SUNNY_DAY, "Sunny Day", Type.FIRE, -1, 5, 49, "Makes it sunny for 5 turns.", -1, 0, 2) - .attr(WeatherChangeAttr, WeatherType.SUNNY), + .attr(WeatherChangeAttr, WeatherType.SUNNY) + .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.CRUNCH, "Crunch", Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, 108, "May lower opponent's Defense.", 20, 0, 2) .attr(StatChangeAttr, BattleStat.DEF, -1), - new AttackMove(Moves.MIRROR_COAT, "Mirror Coat (N)", Type.PSYCHIC, MoveCategory.SPECIAL, -1, 100, 20, -1, "When hit by a Special Attack, user strikes back with 2x power.", -1, -5, 2), + new AttackMove(Moves.MIRROR_COAT, "Mirror Coat (N)", Type.PSYCHIC, MoveCategory.SPECIAL, -1, 100, 20, -1, "When hit by a Special Attack, user strikes back with 2x power.", -1, -5, 2) + .target(MoveTarget.ATTACKER), new SelfStatusMove(Moves.PSYCH_UP, "Psych Up (N)", Type.NORMAL, -1, 10, -1, "Copies the opponent's stat changes.", -1, 0, 2), new AttackMove(Moves.EXTREME_SPEED, "Extreme Speed", Type.NORMAL, MoveCategory.PHYSICAL, 80, 100, 5, -1, "User attacks first.", -1, 2, 2), new AttackMove(Moves.ANCIENT_POWER, "Ancient Power", Type.ROCK, MoveCategory.SPECIAL, 60, 100, 5, -1, "May raise all user's stats at once.", 10, 0, 2) @@ -2354,14 +2442,17 @@ export function initMoves() { .attr(FlinchAttr) .condition((user: Pokemon, target: Pokemon, move: Move) => user.scene.currentBattle.turn === 1), new AttackMove(Moves.UPROAR, "Uproar (N)", Type.NORMAL, MoveCategory.SPECIAL, 90, 100, 10, -1, "User attacks for 3 turns and prevents sleep.", -1, 0, 3) - .ignoresVirtual(), + .ignoresVirtual() + .target(MoveTarget.RANDOM_NEAR_ENEMY), new SelfStatusMove(Moves.STOCKPILE, "Stockpile (N)", Type.NORMAL, -1, 20, -1, "Stores energy for use with Spit Up and Swallow.", -1, 0, 3), new AttackMove(Moves.SPIT_UP, "Spit Up (N)", Type.NORMAL, MoveCategory.SPECIAL, -1, 100, 10, -1, "Power depends on how many times the user performed Stockpile.", -1, 0, 3), new SelfStatusMove(Moves.SWALLOW, "Swallow (N)", Type.NORMAL, -1, 10, -1, "The more times the user has performed Stockpile, the more HP is recovered.", -1, 0, 3), new AttackMove(Moves.HEAT_WAVE, "Heat Wave", Type.FIRE, MoveCategory.SPECIAL, 95, 90, 10, 118, "May burn opponent.", 10, 0, 3) - .attr(StatusEffectAttr, StatusEffect.BURN), + .attr(StatusEffectAttr, StatusEffect.BURN) + .target(MoveTarget.ALL_NEAR_ENEMIES), new SelfStatusMove(Moves.HAIL, "Hail", Type.ICE, -1, 10, -1, "Non-Ice types are damaged for 5 turns.", -1, 0, 3) - .attr(WeatherChangeAttr, WeatherType.HAIL), + .attr(WeatherChangeAttr, WeatherType.HAIL) + .target(MoveTarget.BOTH_SIDES), new StatusMove(Moves.TORMENT, "Torment (N)", Type.DARK, 100, 15, -1, "Opponent cannot use the same move in a row.", -1, 0, 3), new StatusMove(Moves.FLATTER, "Flatter", Type.DARK, 100, 15, -1, "Confuses opponent, but raises its Special Attack.", -1, 0, 3) .attr(StatChangeAttr, BattleStat.SPATK, 1) @@ -2383,7 +2474,8 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.SPDEF, 1, true), // TODO new StatusMove(Moves.TAUNT, "Taunt (N)", Type.DARK, 100, 20, 87, "Opponent can only use moves that attack.", -1, 0, 3), new SelfStatusMove(Moves.HELPING_HAND, "Helping Hand (N)", Type.NORMAL, -1, 20, 130, "In Double Battles, boosts the power of the partner's move.", -1, 5, 3), // TODO - new StatusMove(Moves.TRICK, "Trick (N)", Type.PSYCHIC, 100, 10, 109, "Swaps held items with the opponent.", -1, 0, 3), + new StatusMove(Moves.TRICK, "Trick (N)", Type.PSYCHIC, 100, 10, 109, "Swaps held items with the opponent.", -1, 0, 3) + .target(MoveTarget.NEAR_ALLY), new SelfStatusMove(Moves.ROLE_PLAY, "Role Play (N)", Type.PSYCHIC, -1, 10, -1, "User copies the opponent's Ability.", -1, 0, 3), new SelfStatusMove(Moves.WISH, "Wish (N)", Type.NORMAL, -1, 10, -1, "The user recovers HP in the following turn.", -1, 0, 3), new SelfStatusMove(Moves.ASSIST, "Assist", Type.NORMAL, -1, 20, -1, "User performs a move known by its allies at random.", -1, 0, 3) @@ -2403,9 +2495,11 @@ export function initMoves() { new AttackMove(Moves.KNOCK_OFF, "Knock Off (N)", Type.DARK, MoveCategory.PHYSICAL, 65, 100, 20, -1, "Removes opponent's held item for the rest of the battle.", -1, 0, 3), new AttackMove(Moves.ENDEAVOR, "Endeavor (N)", Type.NORMAL, MoveCategory.PHYSICAL, -1, 100, 5, -1, "Reduces opponent's HP to same as user's.", -1, 0, 3), new AttackMove(Moves.ERUPTION, "Eruption", Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, "Stronger when the user's HP is higher.", -1, 0, 3) - .attr(HpPowerAttr), + .attr(HpPowerAttr) + .target(MoveTarget.ALL_NEAR_ENEMIES), new StatusMove(Moves.SKILL_SWAP, "Skill Swap (N)", Type.PSYCHIC, -1, 10, 98, "The user swaps Abilities with the opponent.", -1, 0, 3), - new StatusMove(Moves.IMPRISON, "Imprison (N)", Type.PSYCHIC, -1, 10, 92, "Opponent is unable to use moves that the user also knows.", -1, 0, 3), + new StatusMove(Moves.IMPRISON, "Imprison (N)", Type.PSYCHIC, -1, 10, 92, "Opponent is unable to use moves that the user also knows.", -1, 0, 3) + .target(MoveTarget.USER), new SelfStatusMove(Moves.REFRESH, "Refresh", Type.NORMAL, -1, 20, -1, "Cures paralysis, poison, and burns.", -1, 0, 3) .attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN) .condition((user: Pokemon, target: Pokemon, move: Move) => user.status && (user.status.effect === StatusEffect.PARALYSIS || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.BURN)), @@ -2414,7 +2508,7 @@ export function initMoves() { new AttackMove(Moves.SECRET_POWER, "Secret Power (N)", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, "Effects of the attack vary with the location.", 30, 0, 3) .makesContact(false), new AttackMove(Moves.DIVE, "Dive", Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, "Dives underwater on first turn, attacks on second turn.", -1, 0, 3) - .attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, 'hid\nunderwater!') + .attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, 'hid$$$underwater!') .ignoresVirtual(), new AttackMove(Moves.ARM_THRUST, "Arm Thrust", Type.FIGHTING, MoveCategory.PHYSICAL, 15, 100, 20, -1, "Hits 2-5 times in one turn.", -1, 0, 3) .attr(MultiHitAttr), @@ -2430,19 +2524,22 @@ export function initMoves() { .attr(StatChangeAttr, BattleStat.ATK, -2), new StatusMove(Moves.TEETER_DANCE, "Teeter Dance", Type.NORMAL, 100, 20, -1, "Confuses all Pokémon.", -1, 0, 3) .attr(ConfuseAttr, true) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.BLAZE_KICK, "Blaze Kick", Type.FIRE, MoveCategory.PHYSICAL, 85, 90, 10, -1, "High critical hit ratio. May burn opponent.", 10, 0, 3) .attr(HighCritAttr) .attr(StatusEffectAttr, StatusEffect.BURN), new SelfStatusMove(Moves.MUD_SPORT, "Mud Sport", Type.GROUND, -1, 15, -1, "Weakens the power of Electric-type moves.", -1, 0, 3) - .attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5), + .attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5) + .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.ICE_BALL, "Ice Ball", Type.ICE, MoveCategory.PHYSICAL, 30, 90, 20, -1, "Doubles in power each turn for 5 turns.", -1, 0, 3) .attr(ConsecutiveUseDoublePowerAttr, 5, true, true), new AttackMove(Moves.NEEDLE_ARM, "Needle Arm", Type.GRASS, MoveCategory.PHYSICAL, 60, 100, 15, -1, "May cause flinching.", 30, 0, 3) .attr(FlinchAttr), new SelfStatusMove(Moves.SLACK_OFF, "Slack Off", Type.NORMAL, -1, 5, -1, "User recovers half its max HP.", -1, 0, 3) .attr(HealAttr), - new AttackMove(Moves.HYPER_VOICE, "Hyper Voice", Type.NORMAL, MoveCategory.SPECIAL, 90, 100, 10, 117, "", -1, 0, 3), + new AttackMove(Moves.HYPER_VOICE, "Hyper Voice", Type.NORMAL, MoveCategory.SPECIAL, 90, 100, 10, 117, "", -1, 0, 3) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.POISON_FANG, "Poison Fang", Type.POISON, MoveCategory.PHYSICAL, 50, 100, 15, -1, "May badly poison opponent.", 50, 0, 3) .attr(StatusEffectAttr, StatusEffect.TOXIC), new AttackMove(Moves.CRUSH_CLAW, "Crush Claw", Type.NORMAL, MoveCategory.PHYSICAL, 75, 95, 10, -1, "May lower opponent's Defense.", 50, 0, 3) @@ -2456,11 +2553,13 @@ export function initMoves() { new AttackMove(Moves.ASTONISH, "Astonish", Type.GHOST, MoveCategory.PHYSICAL, 30, 100, 15, -1, "May cause flinching.", 30, 0, 3) .attr(FlinchAttr), new AttackMove(Moves.WEATHER_BALL, "Weather Ball (N)", Type.NORMAL, MoveCategory.SPECIAL, 50, 100, 10, -1, "Move's power and type changes with the weather.", -1, 0, 3), - new SelfStatusMove(Moves.AROMATHERAPY, "Aromatherapy (N)", Type.GRASS, -1, 5, -1, "Cures all status problems in your party.", -1, 0, 3), + new SelfStatusMove(Moves.AROMATHERAPY, "Aromatherapy (N)", Type.GRASS, -1, 5, -1, "Cures all status problems in your party.", -1, 0, 3) + .target(MoveTarget.USER_AND_ALLIES), new StatusMove(Moves.FAKE_TEARS, "Fake Tears", Type.DARK, 100, 20, 3, "Sharply lowers opponent's Special Defense.", -1, 0, 3) .attr(StatChangeAttr, BattleStat.SPDEF, -2), new AttackMove(Moves.AIR_CUTTER, "Air Cutter", Type.FLYING, MoveCategory.SPECIAL, 60, 95, 25, 40, "High critical hit ratio.", -1, 0, 3) - .attr(HighCritAttr), + .attr(HighCritAttr) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.OVERHEAT, "Overheat", Type.FIRE, MoveCategory.SPECIAL, 130, 90, 5, 157, "Sharply lowers user's Special Attack.", 100, 0, 3) .attr(StatChangeAttr, BattleStat.SPATK, -2, true), new StatusMove(Moves.ODOR_SLEUTH, "Odor Sleuth (N)", Type.NORMAL, -1, 40, -1, "Resets opponent's Evasiveness, and allows Normal- and Fighting-type attacks to hit Ghosts.", -1, 0, 3), @@ -2479,7 +2578,8 @@ export function initMoves() { new SelfStatusMove(Moves.COSMIC_POWER, "Cosmic Power", Type.PSYCHIC, -1, 20, -1, "Raises user's Defense and Special Defense.", -1, 0, 3) .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], 1, true), new AttackMove(Moves.WATER_SPOUT, "Water Spout", Type.WATER, MoveCategory.SPECIAL, 150, 100, 5, -1, "The higher the user's HP, the higher the damage caused.", -1, 0, 3) - .attr(HpPowerAttr), + .attr(HpPowerAttr) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.SIGNAL_BEAM, "Signal Beam", Type.BUG, MoveCategory.SPECIAL, 75, 100, 15, -1, "May confuse opponent.", 10, 0, 3) .attr(ConfuseAttr), new AttackMove(Moves.SHADOW_PUNCH, "Shadow Punch", Type.GHOST, MoveCategory.PHYSICAL, 60, -1, 20, -1, "Ignores Accuracy and Evasiveness.", -1, 0, 3), @@ -2493,11 +2593,13 @@ export function initMoves() { new AttackMove(Moves.SHEER_COLD, "Sheer Cold", Type.ICE, MoveCategory.SPECIAL, -1, 30, 5, -1, "One-Hit-KO, if it hits.", -1, 0, 3) .attr(OneHitKOAttr), new AttackMove(Moves.MUDDY_WATER, "Muddy Water", Type.WATER, MoveCategory.SPECIAL, 90, 85, 10, -1, "May lower opponent's Accuracy.", 30, 0, 3) - .attr(StatChangeAttr, BattleStat.ACC, -1), + .attr(StatChangeAttr, BattleStat.ACC, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.BULLET_SEED, "Bullet Seed", Type.GRASS, MoveCategory.PHYSICAL, 25, 100, 30, 56, "Hits 2-5 times in one turn.", -1, 0, 3) .attr(MultiHitAttr) .makesContact(false), - new AttackMove(Moves.AERIAL_ACE, "Aerial Ace", Type.FLYING, MoveCategory.PHYSICAL, 60, -1, 20, 27, "Ignores Accuracy and Evasiveness.", -1, 0, 3), + new AttackMove(Moves.AERIAL_ACE, "Aerial Ace", Type.FLYING, MoveCategory.PHYSICAL, 60, -1, 20, 27, "Ignores Accuracy and Evasiveness.", -1, 0, 3) + .target(MoveTarget.OTHER), new AttackMove(Moves.ICICLE_SPEAR, "Icicle Spear", Type.ICE, MoveCategory.PHYSICAL, 25, 100, 30, -1, "Hits 2-5 times in one turn.", -1, 0, 3) .attr(MultiHitAttr) .makesContact(false), @@ -2507,7 +2609,8 @@ export function initMoves() { .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, 1, true), new SelfStatusMove(Moves.HOWL, "Howl", Type.NORMAL, -1, 40, -1, "Raises Attack of allies.", -1, 0, 3) .attr(StatChangeAttr, BattleStat.ATK, 1, true), // TODO - new AttackMove(Moves.DRAGON_CLAW, "Dragon Claw", Type.DRAGON, MoveCategory.PHYSICAL, 80, 100, 15, 78, "", -1, 0, 3), + new AttackMove(Moves.DRAGON_CLAW, "Dragon Claw", Type.DRAGON, MoveCategory.PHYSICAL, 80, 100, 15, 78, "", -1, 0, 3) + .target(MoveTarget.USER_AND_ALLIES), new AttackMove(Moves.FRENZY_PLANT, "Frenzy Plant", Type.GRASS, MoveCategory.SPECIAL, 150, 90, 5, 155, "User must recharge next turn.", -1, 0, 3) .attr(AddBattlerTagAttr, BattlerTagType.RECHARGING, true), new SelfStatusMove(Moves.BULK_UP, "Bulk Up", Type.FIGHTING, -1, 20, 64, "Raises user's Attack and Defense.", -1, 0, 3) @@ -2515,7 +2618,8 @@ export function initMoves() { new AttackMove(Moves.BOUNCE, "Bounce", Type.FLYING, MoveCategory.PHYSICAL, 85, 85, 5, -1, "Springs up on first turn, attacks on second. May paralyze opponent.", 30, 0, 3) .attr(ChargeAttr, ChargeAnim.BOUNCE_CHARGING, 'sprang up!', BattlerTagType.FLYING) .attr(StatusEffectAttr, StatusEffect.PARALYSIS) - .ignoresVirtual(), + .ignoresVirtual() + .target(MoveTarget.OTHER), new AttackMove(Moves.MUD_SHOT, "Mud Shot", Type.GROUND, MoveCategory.SPECIAL, 55, 95, 15, 35, "Lowers opponent's Speed.", 100, 0, 3) .attr(StatChangeAttr, BattleStat.SPD, -1), new AttackMove(Moves.POISON_TAIL, "Poison Tail", Type.POISON, MoveCategory.PHYSICAL, 50, 100, 25, 26, "High critical hit ratio. May poison opponent.", 10, 0, 3) @@ -2527,7 +2631,8 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new AttackMove(Moves.MAGICAL_LEAF, "Magical Leaf", Type.GRASS, MoveCategory.SPECIAL, 60, -1, 20, 33, "Ignores Accuracy and Evasiveness.", -1, 0, 3), new SelfStatusMove(Moves.WATER_SPORT, "Water Sport", Type.WATER, -1, 15, -1, "Weakens the power of Fire-type moves.", -1, 0, 3) - .attr(AddArenaTagAttr, ArenaTagType.WATER_SPORT, 5), + .attr(AddArenaTagAttr, ArenaTagType.WATER_SPORT, 5) + .target(MoveTarget.BOTH_SIDES), new SelfStatusMove(Moves.CALM_MIND, "Calm Mind", Type.PSYCHIC, -1, 20, 129, "Raises user's Special Attack and Special Defense.", -1, 0, 3) .attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF ], 1, true), new AttackMove(Moves.LEAF_BLADE, "Leaf Blade", Type.GRASS, MoveCategory.PHYSICAL, 90, 100, 15, -1, "High critical hit ratio.", -1, 0, 3) @@ -2539,15 +2644,17 @@ export function initMoves() { .makesContact(false), new AttackMove(Moves.SHOCK_WAVE, "Shock Wave", Type.ELECTRIC, MoveCategory.SPECIAL, 60, -1, 20, -1, "Ignores Accuracy and Evasiveness.", -1, 0, 3), new AttackMove(Moves.WATER_PULSE, "Water Pulse", Type.WATER, MoveCategory.SPECIAL, 60, 100, 20, 11, "May confuse opponent.", 20, 0, 3) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .target(MoveTarget.OTHER), new AttackMove(Moves.DOOM_DESIRE, "Doom Desire", Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, "Damage occurs 2 turns later.", -1, 0, 3) - .attr(ChargeAttr, ChargeAnim.DOOM_DESIRE_CHARGING, 'chose\nDOOM DESIRE as its destiny!'), // Fix this move to work properly + .attr(ChargeAttr, ChargeAnim.DOOM_DESIRE_CHARGING, 'chose$$$DOOM DESIRE as its destiny!'), // Fix this move to work properly new AttackMove(Moves.PSYCHO_BOOST, "Psycho Boost", Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, -1, "Sharply lowers user's Special Attack.", 100, 0, 3) .attr(StatChangeAttr, BattleStat.SPATK, -2, true), new SelfStatusMove(Moves.ROOST, "Roost", Type.FLYING, -1, 5, -1, "User recovers half of its max HP and loses the Flying type temporarily.", -1, 0, 4) .attr(HitHealAttr) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, true, 1), - new SelfStatusMove(Moves.GRAVITY, "Gravity (N)", Type.PSYCHIC, -1, 5, -1, "Prevents moves like FLY and BOUNCE and the Ability LEVITATE for 5 turns.", -1, 0, 4), + new SelfStatusMove(Moves.GRAVITY, "Gravity (N)", Type.PSYCHIC, -1, 5, -1, "Prevents moves like FLY and BOUNCE and the Ability LEVITATE for 5 turns.", -1, 0, 4) + .target(MoveTarget.BOTH_SIDES), new StatusMove(Moves.MIRACLE_EYE, "Miracle Eye (N)", Type.PSYCHIC, -1, 40, -1, "Resets opponent's Evasiveness, removes Dark's Psychic immunity.", -1, 0, 4), new AttackMove(Moves.WAKE_UP_SLAP, "Wake-Up Slap (N)", Type.FIGHTING, MoveCategory.PHYSICAL, 70, 100, 10, -1, "Power doubles if opponent is asleep, but wakes it up.", -1, 0, 4), new AttackMove(Moves.HAMMER_ARM, "Hammer Arm", Type.FIGHTING, MoveCategory.PHYSICAL, 100, 90, 10, -1, "Lowers user's Speed.", 100, 0, 4) @@ -2563,12 +2670,16 @@ export function initMoves() { .condition((user: Pokemon, target: Pokemon, move: Move) => !!target.getTag(BattlerTagType.PROTECTED)) .makesContact(false) .ignoresProtect(), - new AttackMove(Moves.PLUCK, "Pluck (N)", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 20, -1, "If the opponent is holding a berry, its effect is stolen by user.", -1, 0, 4), - new SelfStatusMove(Moves.TAILWIND, "Tailwind (N)", Type.FLYING, -1, 15, 113, "Doubles Speed for 4 turns.", -1, 0, 4), + new AttackMove(Moves.PLUCK, "Pluck (N)", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 20, -1, "If the opponent is holding a berry, its effect is stolen by user.", -1, 0, 4) + .target(MoveTarget.OTHER), + new SelfStatusMove(Moves.TAILWIND, "Tailwind (N)", Type.FLYING, -1, 15, 113, "Doubles Speed for 4 turns.", -1, 0, 4) + .target(MoveTarget.USER_SIDE), new SelfStatusMove(Moves.ACUPRESSURE, "Acupressure", Type.NORMAL, -1, 30, -1, "Sharply raises a random stat.", -1, 0, 4) - .attr(StatChangeAttr, BattleStat.RAND, 2, true), + .attr(StatChangeAttr, BattleStat.RAND, 2, true) + .target(MoveTarget.USER_OR_NEAR_ALLY), new AttackMove(Moves.METAL_BURST, "Metal Burst (N)", Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 10, -1, "Deals damage equal to 1.5x opponent's attack.", -1, 0, 4) - .makesContact(false), + .makesContact(false) + .target(MoveTarget.ATTACKER), new AttackMove(Moves.U_TURN, "U-turn (N)", Type.BUG, MoveCategory.PHYSICAL, 70, 100, 20, 60, "User switches out immediately after attacking.", -1, 0, 4), new AttackMove(Moves.CLOSE_COMBAT, "Close Combat", Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, 167, "Lowers user's Defense and Special Defense.", 100, 0, 4) .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], -1, true), @@ -2580,15 +2691,18 @@ export function initMoves() { new StatusMove(Moves.PSYCHO_SHIFT, "Psycho Shift (N)", Type.PSYCHIC, 100, 10, -1, "Transfers user's status condition to the opponent.", -1, 0, 4), new AttackMove(Moves.TRUMP_CARD, "Trump Card (N)", Type.NORMAL, MoveCategory.SPECIAL, -1, -1, 5, -1, "The lower the PP, the higher the power.", -1, 0, 4) .makesContact(), - new StatusMove(Moves.HEAL_BLOCK, "Heal Block (N)", Type.PSYCHIC, 100, 15, -1, "Prevents the opponent from restoring HP for 5 turns.", -1, 0, 4), + new StatusMove(Moves.HEAL_BLOCK, "Heal Block (N)", Type.PSYCHIC, 100, 15, -1, "Prevents the opponent from restoring HP for 5 turns.", -1, 0, 4) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.WRING_OUT, "Wring Out (N)", Type.NORMAL, MoveCategory.SPECIAL, -1, 100, 5, -1, "The higher the opponent's HP, the higher the damage.", -1, 0, 4) .makesContact(), new SelfStatusMove(Moves.POWER_TRICK, "Power Trick (N)", Type.PSYCHIC, -1, 10, -1, "User's own Attack and Defense switch.", -1, 0, 4), new StatusMove(Moves.GASTRO_ACID, "Gastro Acid (N)", Type.POISON, 100, 10, -1, "Cancels out the effect of the opponent's Ability.", -1, 0, 4), new StatusMove(Moves.LUCKY_CHANT, "Lucky Chant (N)", Type.NORMAL, -1, 30, -1, "Opponent cannot land critical hits for 5 turns.", -1, 0, 4) - .attr(AddBattlerTagAttr, BattlerTagType.NO_CRIT, false, 5), + .attr(AddBattlerTagAttr, BattlerTagType.NO_CRIT, false, 5) + .target(MoveTarget.USER_SIDE), new StatusMove(Moves.ME_FIRST, "Me First (N)", Type.NORMAL, -1, 20, -1, "User copies the opponent's attack with 1.5× power.", -1, 0, 4) - .ignoresVirtual(), + .ignoresVirtual() + .target(MoveTarget.NEAR_ENEMY), new SelfStatusMove(Moves.COPYCAT, "Copycat", Type.NORMAL, -1, 20, -1, "Copies opponent's last move.", -1, 0, 4) .attr(CopyMoveAttr) .ignoresVirtual(), @@ -2599,7 +2713,8 @@ export function initMoves() { new StatusMove(Moves.WORRY_SEED, "Worry Seed (N)", Type.GRASS, 100, 10, -1, "Changes the opponent's Ability to Insomnia.", -1, 0, 4), new AttackMove(Moves.SUCKER_PUNCH, "Sucker Punch (N)", Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, "User attacks first, but only works if opponent is readying an attack.", -1, 0, 4), new StatusMove(Moves.TOXIC_SPIKES, "Toxic Spikes", Type.POISON, -1, 20, 91, "Poisons opponents when they switch into battle.", -1, 0, 4) - .attr(AddArenaTrapTagAttr, ArenaTagType.TOXIC_SPIKES), + .attr(AddArenaTrapTagAttr, ArenaTagType.TOXIC_SPIKES) + .target(MoveTarget.ENEMY_SIDE), new StatusMove(Moves.HEART_SWAP, "Heart Swap (N)", Type.PSYCHIC, -1, 10, -1, "Stat changes are swapped with the opponent.", -1, 0, 4), new SelfStatusMove(Moves.AQUA_RING, "Aqua Ring", Type.WATER, -1, 20, -1, "Restores a little HP each turn.", -1, 0, 4) .attr(AddBattlerTagAttr, BattlerTagType.AQUA_RING, true, undefined, true), @@ -2609,24 +2724,28 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.BURN), new AttackMove(Moves.FORCE_PALM, "Force Palm", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "May paralyze opponent.", 30, 0, 4) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), - new AttackMove(Moves.AURA_SPHERE, "Aura Sphere", Type.FIGHTING, MoveCategory.SPECIAL, 80, -1, 20, 112, "Ignores Accuracy and Evasiveness.", -1, 0, 4), + new AttackMove(Moves.AURA_SPHERE, "Aura Sphere", Type.FIGHTING, MoveCategory.SPECIAL, 80, -1, 20, 112, "Ignores Accuracy and Evasiveness.", -1, 0, 4) + .target(MoveTarget.OTHER), new SelfStatusMove(Moves.ROCK_POLISH, "Rock Polish", Type.ROCK, -1, 20, -1, "Sharply raises user's Speed.", -1, 0, 4) .attr(StatChangeAttr, BattleStat.SPD, 2, true), new AttackMove(Moves.POISON_JAB, "Poison Jab", Type.POISON, MoveCategory.PHYSICAL, 80, 100, 20, 83, "May poison the opponent.", 30, 0, 4) .attr(StatusEffectAttr, StatusEffect.POISON), new AttackMove(Moves.DARK_PULSE, "Dark Pulse", Type.DARK, MoveCategory.SPECIAL, 80, 100, 15, 94, "May cause flinching.", 20, 0, 4) - .attr(FlinchAttr), + .attr(FlinchAttr) + .target(MoveTarget.OTHER), new AttackMove(Moves.NIGHT_SLASH, "Night Slash", Type.DARK, MoveCategory.PHYSICAL, 70, 100, 15, -1, "High critical hit ratio.", -1, 0, 4) .attr(HighCritAttr), new AttackMove(Moves.AQUA_TAIL, "Aqua Tail", Type.WATER, MoveCategory.PHYSICAL, 90, 90, 10, -1, "", -1, 0, 4), new AttackMove(Moves.SEED_BOMB, "Seed Bomb", Type.GRASS, MoveCategory.PHYSICAL, 80, 100, 15, 71, "", -1, 0, 4) .makesContact(false), new AttackMove(Moves.AIR_SLASH, "Air Slash", Type.FLYING, MoveCategory.SPECIAL, 75, 95, 15, 65, "May cause flinching.", 30, 0, 4) - .attr(FlinchAttr), + .attr(FlinchAttr) + .target(MoveTarget.OTHER), new AttackMove(Moves.X_SCISSOR, "X-Scissor", Type.BUG, MoveCategory.PHYSICAL, 80, 100, 15, 105, "", -1, 0, 4), new AttackMove(Moves.BUG_BUZZ, "Bug Buzz", Type.BUG, MoveCategory.SPECIAL, 90, 100, 10, 162, "May lower opponent's Special Defense.", 10, 0, 4) .attr(StatChangeAttr, BattleStat.SPDEF, -1), - new AttackMove(Moves.DRAGON_PULSE, "Dragon Pulse", Type.DRAGON, MoveCategory.SPECIAL, 85, 100, 10, 115, "", -1, 0, 4), + new AttackMove(Moves.DRAGON_PULSE, "Dragon Pulse", Type.DRAGON, MoveCategory.SPECIAL, 85, 100, 10, 115, "", -1, 0, 4) + .target(MoveTarget.OTHER), new AttackMove(Moves.DRAGON_RUSH, "Dragon Rush", Type.DRAGON, MoveCategory.PHYSICAL, 100, 75, 10, -1, "May cause flinching.", 20, 0, 4) .attr(FlinchAttr), new AttackMove(Moves.POWER_GEM, "Power Gem", Type.ROCK, MoveCategory.SPECIAL, 80, 100, 20, 101, "", -1, 0, 4), @@ -2638,7 +2757,8 @@ export function initMoves() { new AttackMove(Moves.ENERGY_BALL, "Energy Ball", Type.GRASS, MoveCategory.SPECIAL, 90, 100, 10, 119, "May lower opponent's Special Defense.", 10, 0, 4) .attr(StatChangeAttr, BattleStat.SPDEF, -1), new AttackMove(Moves.BRAVE_BIRD, "Brave Bird", Type.FLYING, MoveCategory.PHYSICAL, 120, 100, 15, 164, "User receives recoil damage.", -1, 0, 4) - .attr(RecoilAttr), + .attr(RecoilAttr) + .target(MoveTarget.OTHER), new AttackMove(Moves.EARTH_POWER, "Earth Power", Type.GROUND, MoveCategory.SPECIAL, 90, 100, 10, 133, "May lower opponent's Special Defense.", 10, 0, 4) .attr(StatChangeAttr, BattleStat.SPDEF, -1), new StatusMove(Moves.SWITCHEROO, "Switcheroo (N)", Type.DARK, 100, 10, -1, "Swaps held items with the opponent.", -1, 0, 4), @@ -2681,13 +2801,16 @@ export function initMoves() { .attr(ClearWeatherAttr, WeatherType.FOG), new StatusMove(Moves.TRICK_ROOM, "Trick Room", Type.PSYCHIC, -1, 5, 161, "Slower Pokémon move first in the turn for 5 turns.", -1, 0, 4) .attr(AddArenaTagAttr, ArenaTagType.TRICK_ROOM, 5) - .ignoresProtect(), + .ignoresProtect() + .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.DRACO_METEOR, "Draco Meteor", Type.DRAGON, MoveCategory.SPECIAL, 130, 90, 5, 169, "Sharply lowers user's Special Attack.", 100, -7, 4) .attr(StatChangeAttr, BattleStat.SPATK, -2, true), new AttackMove(Moves.DISCHARGE, "Discharge", Type.ELECTRIC, MoveCategory.SPECIAL, 80, 100, 15, -1, "May paralyze opponent.", 30, 0, 4) - .attr(StatusEffectAttr, StatusEffect.PARALYSIS), + .attr(StatusEffectAttr, StatusEffect.PARALYSIS) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.LAVA_PLUME, "Lava Plume", Type.FIRE, MoveCategory.SPECIAL, 80, 100, 15, -1, "May burn opponent.", 30, 0, 4) - .attr(StatusEffectAttr, StatusEffect.BURN), + .attr(StatusEffectAttr, StatusEffect.BURN) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.LEAF_STORM, "Leaf Storm", Type.GRASS, MoveCategory.SPECIAL, 130, 90, 5, 159, "Sharply lowers user's Special Attack.", 100, 0, 4) .attr(StatChangeAttr, BattleStat.SPATK, -2, true), new AttackMove(Moves.POWER_WHIP, "Power Whip", Type.GRASS, MoveCategory.PHYSICAL, 120, 85, 10, -1, "", -1, 0, 4), @@ -2709,12 +2832,14 @@ export function initMoves() { .makesContact(false), new StatusMove(Moves.CAPTIVATE, "Captivate (N)", Type.NORMAL, 100, 20, -1, "Sharply lowers opponent's Special Attack if opposite gender.", -1, 0, 4), // TODO new StatusMove(Moves.STEALTH_ROCK, "Stealth Rock", Type.ROCK, -1, 20, 116, "Damages opponent switching into battle.", -1, 0, 4) - .attr(AddArenaTrapTagAttr, ArenaTagType.STEALTH_ROCK), + .attr(AddArenaTrapTagAttr, ArenaTagType.STEALTH_ROCK) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.GRASS_KNOT, "Grass Knot", Type.GRASS, MoveCategory.SPECIAL, -1, 100, 20, 81, "The heavier the opponent, the stronger the attack.", -1, 0, 4) .attr(WeightPowerAttr) .makesContact(), new AttackMove(Moves.CHATTER, "Chatter", Type.FLYING, MoveCategory.SPECIAL, 65, 100, 20, -1, "Confuses opponent.", 100, 0, 4) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .target(MoveTarget.OTHER), new AttackMove(Moves.JUDGMENT, "Judgment (N)", Type.NORMAL, MoveCategory.SPECIAL, 100, 100, 10, -1, "Type depends on the Arceus Plate being held.", -1, 0, 4), new AttackMove(Moves.BUG_BITE, "Bug Bite (N)", Type.BUG, MoveCategory.PHYSICAL, 60, 100, 20, -1, "Receives the effect from the opponent's held berry.", -1, 0, 4), new AttackMove(Moves.CHARGE_BEAM, "Charge Beam", Type.ELECTRIC, MoveCategory.SPECIAL, 50, 90, 10, 23, "May raise user's Special Attack.", 70, 0, 4) @@ -2743,22 +2868,25 @@ export function initMoves() { new AttackMove(Moves.MAGMA_STORM, "Magma Storm", Type.FIRE, MoveCategory.SPECIAL, 100, 75, 5, -1, "Traps opponent, damaging them for 4-5 turns.", 100, 0, 4) .attr(TrapAttr, BattlerTagType.MAGMA_STORM), new StatusMove(Moves.DARK_VOID, "Dark Void", Type.DARK, 50, 10, -1, "Puts all adjacent opponents to sleep.", -1, 0, 4) - .attr(StatusEffectAttr, StatusEffect.SLEEP), + .attr(StatusEffectAttr, StatusEffect.SLEEP) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.SEED_FLARE, "Seed Flare", Type.GRASS, MoveCategory.SPECIAL, 120, 85, 5, -1, "May lower opponent's Special Defense.", 40, 0, 4) .attr(StatChangeAttr, BattleStat.SPDEF, -1), new AttackMove(Moves.OMINOUS_WIND, "Ominous Wind", Type.GHOST, MoveCategory.SPECIAL, 60, 100, 5, -1, "May raise all user's stats at once.", 10, 0, 4) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.DEF, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true), new AttackMove(Moves.SHADOW_FORCE, "Shadow Force", Type.GHOST, MoveCategory.PHYSICAL, 120, 100, 5, -1, "Disappears on first turn, attacks on second. Can strike through PROTECT/DETECT.", -1, 0, 4) - .attr(ChargeAttr, ChargeAnim.SHADOW_FORCE_CHARGING, 'vanished\ninstantly!', BattlerTagType.HIDDEN) + .attr(ChargeAttr, ChargeAnim.SHADOW_FORCE_CHARGING, 'vanished$$$instantly!', BattlerTagType.HIDDEN) .ignoresProtect() .ignoresVirtual(), new SelfStatusMove(Moves.HONE_CLAWS, "Hone Claws", Type.DARK, -1, 15, -1, "Raises user's Attack and Accuracy.", -1, 0, 5) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.ACC ], 1, true), - new SelfStatusMove(Moves.WIDE_GUARD, "Wide Guard (N)", Type.ROCK, -1, 10, -1, "Protects the user's team from multi-target attacks.", -1, 3, 5), + new SelfStatusMove(Moves.WIDE_GUARD, "Wide Guard (N)", Type.ROCK, -1, 10, -1, "Protects the user's team from multi-target attacks.", -1, 3, 5) + .target(MoveTarget.USER_SIDE), new StatusMove(Moves.GUARD_SPLIT, "Guard Split (N)", Type.PSYCHIC, -1, 10, -1, "Averages Defense and Special Defense with the target.", -1, 0, 5), new StatusMove(Moves.POWER_SPLIT, "Power Split (N)", Type.PSYCHIC, -1, 10, -1, "Averages Attack and Special Attack with the target.", -1, 0, 5), new StatusMove(Moves.WONDER_ROOM, "Wonder Room (N)", Type.PSYCHIC, -1, 10, -1, "Swaps every Pokémon's Defense and Special Defense for 5 turns.", -1, -7, 5) - .ignoresProtect(), + .ignoresProtect() + .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.PSYSHOCK, "Psyshock (N)", Type.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, 54, "Inflicts damage based on the target's Defense, not Special Defense.", -1, 0, 5), new AttackMove(Moves.VENOSHOCK, "Venoshock (N)", Type.POISON, MoveCategory.SPECIAL, 65, 100, 10, 45, "Inflicts double damage if the target is poisoned.", -1, 0, 5), new SelfStatusMove(Moves.AUTOTOMIZE, "Autotomize", Type.STEEL, -1, 15, -1, "Reduces weight and sharply raises Speed.", -1, 0, 5) @@ -2766,7 +2894,8 @@ export function initMoves() { new SelfStatusMove(Moves.RAGE_POWDER, "Rage Powder (N)", Type.BUG, -1, 20, -1, "Forces attacks to hit user, not team-mates.", -1, 3, 5), new StatusMove(Moves.TELEKINESIS, "Telekinesis (N)", Type.PSYCHIC, -1, 15, -1, "Ignores opponent's Evasiveness for three turns, add Ground immunity.", -1, 0, 5), new StatusMove(Moves.MAGIC_ROOM, "Magic Room (N)", Type.PSYCHIC, -1, 10, -1, "Suppresses the effects of held items for five turns.", -1, -7, 5) - .ignoresProtect(), + .ignoresProtect() + .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.SMACK_DOWN, "Smack Down (N)", Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, -1, "Makes Flying-type Pokémon vulnerable to Ground moves.", 100, 0, 5) // TODO, logic with fly .makesContact(false), new AttackMove(Moves.STORM_THROW, "Storm Throw (N)", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "Always results in a critical hit.", 100, 0, 5), // TODO @@ -2776,7 +2905,8 @@ export function initMoves() { new SelfStatusMove(Moves.QUIVER_DANCE, "Quiver Dance", Type.BUG, -1, 20, -1, "Raises user's Special Attack, Special Defense and Speed.", -1, 0, 5) .attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 1, true), new AttackMove(Moves.HEAVY_SLAM, "Heavy Slam (N)", Type.STEEL, MoveCategory.PHYSICAL, -1, 100, 10, 121, "The heavier the user, the stronger the attack.", -1, 0, 5), - new AttackMove(Moves.SYNCHRONOISE, "Synchronoise (N)", Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, "Hits any Pokémon that shares a type with the user.", -1, 0, 5), + new AttackMove(Moves.SYNCHRONOISE, "Synchronoise (N)", Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, "Hits any Pokémon that shares a type with the user.", -1, 0, 5) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.ELECTRO_BALL, "Electro Ball (N)", Type.ELECTRIC, MoveCategory.SPECIAL, -1, 100, 10, 72, "The faster the user, the stronger the attack.", -1, 0, 5), new StatusMove(Moves.SOAK, "Soak (N)", Type.WATER, 100, 20, -1, "Changes the target's type to water.", -1, 0, 5), new AttackMove(Moves.FLAME_CHARGE, "Flame Charge", Type.FIRE, MoveCategory.PHYSICAL, 50, 100, 20, 38, "Raises user's Speed.", 100, 0, 5) @@ -2798,28 +2928,33 @@ export function initMoves() { new AttackMove(Moves.CHIP_AWAY, "Chip Away (N)", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, "Ignores opponent's stat changes.", -1, 0, 5), new AttackMove(Moves.CLEAR_SMOG, "Clear Smog (N)", Type.POISON, MoveCategory.SPECIAL, 50, -1, 15, -1, "Removes all of the target's stat changes.", -1, 0, 5), new AttackMove(Moves.STORED_POWER, "Stored Power (N)", Type.PSYCHIC, MoveCategory.SPECIAL, 20, 100, 10, 41, "Power increases when user's stats have been raised.", -1, 0, 5), - new SelfStatusMove(Moves.QUICK_GUARD, "Quick Guard (N)", Type.FIGHTING, -1, 15, -1, "Protects the user's team from high-priority moves.", -1, 3, 5), + new SelfStatusMove(Moves.QUICK_GUARD, "Quick Guard (N)", Type.FIGHTING, -1, 15, -1, "Protects the user's team from high-priority moves.", -1, 3, 5) + .target(MoveTarget.USER_SIDE), new StatusMove(Moves.ALLY_SWITCH, "Ally Switch (N)", Type.PSYCHIC, -1, 15, -1, "User switches with opposite teammate.", -1, 0, 5) .ignoresProtect(), // TODO new AttackMove(Moves.SCALD, "Scald", Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, "May burn opponent.", 30, 1, 5) - .attr(StatusEffectAttr, StatusEffect.BURN), + .attr(StatusEffectAttr, StatusEffect.BURN) + .target(MoveTarget.USER), new SelfStatusMove(Moves.SHELL_SMASH, "Shell Smash", Type.NORMAL, -1, 15, -1, "Sharply raises user's Attack, Special Attack and Speed but lowers Defense and Special Defense.", -1, 0, 5) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 2, true) .attr(StatChangeAttr, [ BattleStat.DEF, BattleStat.SPDEF ], -1, true), new StatusMove(Moves.HEAL_PULSE, "Heal Pulse", Type.PSYCHIC, -1, 10, -1, "Restores half the target's max HP.", -1, 0, 5) - .attr(HealAttr, 0.5, false, false), + .attr(HealAttr, 0.5, false, false) + .target(MoveTarget.OTHER), new AttackMove(Moves.HEX, "Hex", Type.GHOST, MoveCategory.SPECIAL, 65, 100, 10, 29, "Inflicts more damage if the target has a status condition.", -1, 0, 5) .attr(MovePowerMultiplierAttr, (user: Pokemon, target: Pokemon, move: Move) => target.status ? 2 : 1), new AttackMove(Moves.SKY_DROP, "Sky Drop", Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 10, -1, "Takes opponent into the air on first turn, drops them on second turn.", -1, 0, 5) - .attr(ChargeAttr, ChargeAnim.SKY_DROP_CHARGING, 'took {TARGET}\ninto the sky!', BattlerTagType.FLYING) // TODO: Add 2nd turn message + .attr(ChargeAttr, ChargeAnim.SKY_DROP_CHARGING, 'took {TARGET}$$$into the sky!', BattlerTagType.FLYING) // TODO: Add 2nd turn message .ignoresVirtual(), new SelfStatusMove(Moves.SHIFT_GEAR, "Shift Gear", Type.STEEL, -1, 10, -1, "Raises user's Attack and sharply raises Speed.", -1, 0, 5) .attr(StatChangeAttr, BattleStat.ATK, 1, true) .attr(StatChangeAttr, BattleStat.SPD, 2, true), new AttackMove(Moves.CIRCLE_THROW, "Circle Throw (N)", Type.FIGHTING, MoveCategory.PHYSICAL, 60, 90, 10, -1, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, -6, 5), - new AttackMove(Moves.INCINERATE, "Incinerate (N)", Type.FIRE, MoveCategory.SPECIAL, 60, 100, 15, -1, "Destroys the target's held berry.", -1, 0, 5), + new AttackMove(Moves.INCINERATE, "Incinerate (N)", Type.FIRE, MoveCategory.SPECIAL, 60, 100, 15, -1, "Destroys the target's held berry.", -1, 0, 5) + .target(MoveTarget.ALL_NEAR_ENEMIES), new StatusMove(Moves.QUASH, "Quash", Type.DARK, 100, 15, -1, "Makes the target act last this turn.", -1, 0, 5), - new AttackMove(Moves.ACROBATICS, "Acrobatics (N)", Type.FLYING, MoveCategory.PHYSICAL, 55, 100, 15, 14, "Stronger when the user does not have a held item.", -1, 0, 5), + new AttackMove(Moves.ACROBATICS, "Acrobatics (N)", Type.FLYING, MoveCategory.PHYSICAL, 55, 100, 15, 14, "Stronger when the user does not have a held item.", -1, 0, 5) + .target(MoveTarget.OTHER), new StatusMove(Moves.REFLECT_TYPE, "Reflect Type", Type.NORMAL, -1, 15, -1, "User becomes the target's type.", -1, 0, 5) .attr(CopyTypeAttr), new AttackMove(Moves.RETALIATE, "Retaliate (N)", Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 5, -1, "Inflicts double damage if a teammate fainted on the last turn.", -1, 0, 5), @@ -2835,16 +2970,19 @@ export function initMoves() { new AttackMove(Moves.GRASS_PLEDGE, "Grass Pledge (N)", Type.GRASS, MoveCategory.SPECIAL, 80, 100, 10, 146, "Added effects appear if preceded by Water Pledge or succeeded by Fire Pledge.", -1, 0, 5), new AttackMove(Moves.VOLT_SWITCH, "Volt Switch (N)", Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 20, 48, "User must switch out after attacking.", -1, 0, 5), new AttackMove(Moves.STRUGGLE_BUG, "Struggle Bug", Type.BUG, MoveCategory.SPECIAL, 50, 100, 20, 15, "Lowers opponent's Special Attack.", 100, 0, 5) - .attr(StatChangeAttr, BattleStat.SPATK, -1), + .attr(StatChangeAttr, BattleStat.SPATK, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.BULLDOZE, "Bulldoze", Type.GROUND, MoveCategory.PHYSICAL, 60, 100, 20, 28, "Lowers opponent's Speed.", 100, 0, 5) .attr(StatChangeAttr, BattleStat.SPD, -1) - .makesContact(false), + .makesContact(false) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.FROST_BREATH, "Frost Breath (N)", Type.ICE, MoveCategory.SPECIAL, 60, 90, 10, -1, "Always results in a critical hit.", 100, 0, 5), // TODO new AttackMove(Moves.DRAGON_TAIL, "Dragon Tail (N)", Type.DRAGON, MoveCategory.PHYSICAL, 60, 90, 10, 44, "In battles, the opponent switches. In the wild, the Pokémon runs.", -1, -6, 5), new SelfStatusMove(Moves.WORK_UP, "Work Up", Type.NORMAL, -1, 30, -1, "Raises user's Attack and Special Attack.", -1, 0, 5) .attr(StatChangeAttr, [ BattleStat.ATK, BattleStat.SPATK ], 1, true), new AttackMove(Moves.ELECTROWEB, "Electroweb", Type.ELECTRIC, MoveCategory.SPECIAL, 55, 95, 15, -1, "Lowers opponent's Speed.", 100, 0, 5) - .attr(StatChangeAttr, BattleStat.SPD, -1), + .attr(StatChangeAttr, BattleStat.SPD, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.WILD_CHARGE, "Wild Charge", Type.ELECTRIC, MoveCategory.PHYSICAL, 90, 100, 15, 147, "User receives recoil damage.", -1, 0, 5) .attr(RecoilAttr), new AttackMove(Moves.DRILL_RUN, "Drill Run", Type.GROUND, MoveCategory.PHYSICAL, 80, 95, 10, 106, "High critical hit ratio.", -1, 0, 5) @@ -2872,19 +3010,23 @@ export function initMoves() { .attr(MultiHitAttr), new AttackMove(Moves.HURRICANE, "Hurricane", Type.FLYING, MoveCategory.SPECIAL, 110, 70, 10, 160, "May confuse opponent.", 30, 0, 5) .attr(ThunderAccuracyAttr) - .attr(ConfuseAttr), + .attr(ConfuseAttr) + .target(MoveTarget.OTHER), new AttackMove(Moves.HEAD_CHARGE, "Head Charge", Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 15, -1, "User receives recoil damage.", -1, 0, 5) .attr(RecoilAttr), new AttackMove(Moves.GEAR_GRIND, "Gear Grind", Type.STEEL, MoveCategory.PHYSICAL, 50, 85, 15, -1, "Hits twice in one turn.", -1, 0, 5) .attr(MultiHitAttr, MultiHitType._2), new AttackMove(Moves.SEARING_SHOT, "Searing Shot", Type.FIRE, MoveCategory.SPECIAL, 100, 100, 5, -1, "May burn opponent.", 30, 0, 5) - .attr(StatusEffectAttr, StatusEffect.BURN), + .attr(StatusEffectAttr, StatusEffect.BURN) + .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.TECHNO_BLAST, "Techno Blast (N)", Type.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, -1, "Type depends on the Drive being held.", -1, 0, 5), new AttackMove(Moves.RELIC_SONG, "Relic Song", Type.NORMAL, MoveCategory.SPECIAL, 75, 100, 10, -1, "May put the target to sleep.", 10, 0, 5) - .attr(StatusEffectAttr, StatusEffect.SLEEP), + .attr(StatusEffectAttr, StatusEffect.SLEEP) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.SECRET_SWORD, "Secret Sword (N)", Type.FIGHTING, MoveCategory.SPECIAL, 85, 100, 10, -1, "Inflicts damage based on the target's Defense, not Special Defense.", -1, 0, 5), new AttackMove(Moves.GLACIATE, "Glaciate", Type.ICE, MoveCategory.SPECIAL, 65, 95, 10, -1, "Lowers opponent's Speed.", 100, 0, 5) - .attr(StatChangeAttr, BattleStat.SPD, -1), + .attr(StatChangeAttr, BattleStat.SPD, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.BOLT_STRIKE, "Bolt Strike", Type.ELECTRIC, MoveCategory.PHYSICAL, 130, 85, 5, -1, "May paralyze opponent.", 20, 0, 5) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new AttackMove(Moves.BLUE_FLARE, "Blue Flare", Type.FIRE, MoveCategory.SPECIAL, 130, 85, 5, -1, "May burn opponent.", 20, 0, 5) @@ -2895,11 +3037,12 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.PARALYSIS) .makesContact(false), new AttackMove(Moves.ICE_BURN, "Ice Burn", Type.ICE, MoveCategory.SPECIAL, 140, 90, 5, -1, "Charges on first turn, attacks on second. May burn opponent.", 30, 0, 5) - .attr(ChargeAttr, ChargeAnim.ICE_BURN_CHARGING, 'became cloaked\nin freezing air!') + .attr(ChargeAttr, ChargeAnim.ICE_BURN_CHARGING, 'became cloaked$$$in freezing air!') .attr(StatusEffectAttr, StatusEffect.BURN) .ignoresVirtual(), new AttackMove(Moves.SNARL, "Snarl", Type.DARK, MoveCategory.SPECIAL, 55, 95, 15, 30, "Lowers opponent's Special Attack.", 100, 0, 5) - .attr(StatChangeAttr, BattleStat.SPATK, -1), + .attr(StatChangeAttr, BattleStat.SPATK, -1) + .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.ICICLE_CRASH, "Icicle Crash", Type.ICE, MoveCategory.PHYSICAL, 85, 90, 10, -1, "May cause flinching.", 30, 0, 5) .attr(FlinchAttr) .makesContact(false), @@ -2908,18 +3051,19 @@ export function initMoves() { new AttackMove(Moves.FUSION_FLARE, "Fusion Flare (N)", Type.FIRE, MoveCategory.SPECIAL, 100, 100, 5, -1, "Power increases if Fusion Bolt is used in the same turn.", -1, 0, 5), new AttackMove(Moves.FUSION_BOLT, "Fusion Bolt (N)", Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 100, 5, -1, "Power increases if Fusion Flare is used in the same turn.", -1, 0, 5) .makesContact(false), - new AttackMove(Moves.MOONBLAST, 'Moonblast', Type.FAIRY, MoveCategory.SPECIAL, 95, 100, 15, -1, "May lower opponent's Special Attack.", 30, 0, 6) + new AttackMove(Moves.MOONBLAST, "Moonblast", Type.FAIRY, MoveCategory.SPECIAL, 95, 100, 15, -1, "May lower opponent's Special Attack.", 30, 0, 6) .attr(StatChangeAttr, BattleStat.SPATK, -1), new AttackMove(Moves.PHANTOM_FORCE, "Phantom Force", Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, "Disappears on first turn, attacks on second. Can strike through PROTECT/DETECT.", -1, 0, 6) - .attr(ChargeAttr, ChargeAnim.PHANTOM_FORCE_CHARGING, 'vanished\ninstantly!', BattlerTagType.HIDDEN) + .attr(ChargeAttr, ChargeAnim.PHANTOM_FORCE_CHARGING, 'vanished$$$instantly!', BattlerTagType.HIDDEN) .ignoresProtect() .ignoresVirtual(), new SelfStatusMove(Moves.GEOMANCY, "Geomancy", Type.FAIRY, -1, 10, -1, "Charges on the first turn, sharply raises user's Special Attack, Special Defense and Speed on the second.", -1, 0, 6) - .attr(ChargeAttr, ChargeAnim.GEOMANCY_CHARGING, "is charging\nits power!") + .attr(ChargeAttr, ChargeAnim.GEOMANCY_CHARGING, "is charging$$$its power!") .attr(StatChangeAttr, [ BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD ], 2, true) .ignoresVirtual(), new AttackMove(Moves.OBLIVION_WING, "Oblivion Wing", Type.FLYING, MoveCategory.SPECIAL, 80, 100, 10, -1, "User recovers 3/4 the HP inflicted on the opponent.", -1, 0, 6) - .attr(HitHealAttr, 0.75), + .attr(HitHealAttr, 0.75) + .target(MoveTarget.OTHER), new AttackMove(Moves.DYNAMAX_CANNON, "Dynamax Cannon", Type.DRAGON, MoveCategory.SPECIAL, 100, 100, 5, -1, "Power is doubled if the target is over level 200.", -1, 0, 8) .attr(MovePowerMultiplierAttr, (user: Pokemon, target: Pokemon, move: Move) => target.level > 200 ? 2 : 1) .ignoresVirtual()