2023-04-13 23:04:51 -04:00
import { ChargeAnim , MoveChargeAnim , initMoveAnim , loadMoveAnimAssets } from "./battle-anims" ;
2024-05-23 17:03:10 +02:00
import { BattleEndPhase , MovePhase , NewBattlePhase , PartyStatusCurePhase , PokemonHealPhase , StatChangePhase , SwitchSummonPhase } from "../phases" ;
2024-01-15 23:29:22 -05:00
import { BattleStat , getBattleStatName } from "./battle-stat" ;
2024-01-13 12:24:24 -05:00
import { EncoreTag } from "./battler-tags" ;
2023-04-20 15:46:05 -04:00
import { getPokemonMessage } from "../messages" ;
2024-03-21 00:57:28 -04:00
import Pokemon , { AttackMoveResult , EnemyPokemon , HitResult , MoveResult , PlayerPokemon , PokemonMove , TurnMove } from "../field/pokemon" ;
2024-05-25 05:01:23 -06:00
import { StatusEffect , getStatusEffectHealText , isNonVolatileStatusEffect , getNonVolatileStatusEffects } from "./status-effect" ;
2023-04-03 23:38:31 -04:00
import { Type } from "./type" ;
2023-04-20 15:46:05 -04:00
import * as Utils from "../utils" ;
2023-04-17 00:46:50 -04:00
import { WeatherType } from "./weather" ;
2024-01-15 23:29:22 -05:00
import { ArenaTagSide , ArenaTrapTag } from "./arena-tag" ;
2024-06-15 19:14:49 -07:00
import { UnswappableAbilityAbAttr , UncopiableAbilityAbAttr , UnsuppressableAbilityAbAttr , BlockRecoilDamageAttr , BlockOneHitKOAbAttr , IgnoreContactAbAttr , MaxMultiHitAbAttr , applyAbAttrs , BlockNonDirectDamageAbAttr , applyPreSwitchOutAbAttrs , PreSwitchOutAbAttr , applyPostDefendAbAttrs , PostDefendContactApplyStatusEffectAbAttr , MoveAbilityBypassAbAttr , ReverseDrainAbAttr , FieldPreventExplosiveMovesAbAttr , ForceSwitchOutImmunityAbAttr , BlockItemTheftAbAttr , applyPostAttackAbAttrs , ConfusionOnStatusEffectAbAttr , HealFromBerryUseAbAttr , IgnoreProtectOnContactAbAttr } from "./ability" ;
2024-05-23 17:03:10 +02:00
import { allAbilities } from "./ability" ;
2024-05-19 18:47:30 -04:00
import { PokemonHeldItemModifier , BerryModifier , PreserveBerryModifier } from "../modifier/modifier" ;
2023-05-18 11:11:06 -04:00
import { BattlerIndex } from "../battle" ;
2024-03-01 00:27:46 -05:00
import { Stat } from "./pokemon-stat" ;
2024-03-09 21:57:33 -05:00
import { TerrainType } from "./terrain" ;
2024-03-27 22:40:10 -04:00
import { SpeciesFormChangeActiveTrigger } from "./pokemon-forms" ;
2024-04-10 14:31:29 -04:00
import { ModifierPoolType } from "#app/modifier/modifier-type" ;
2024-04-15 02:05:32 +10:00
import { Command } from "../ui/command-ui-handler" ;
2024-05-23 17:03:10 +02:00
import i18next , { Localizable } from "../plugins/i18n" ;
import { getBerryEffectFunc } from "./berry" ;
2024-06-13 18:44:23 -04:00
import { Abilities } from "#enums/abilities" ;
import { ArenaTagType } from "#enums/arena-tag-type" ;
import { BattlerTagType } from "#enums/battler-tag-type" ;
import { Biome } from "#enums/biome" ;
import { Moves } from "#enums/moves" ;
import { Species } from "#enums/species" ;
2023-03-28 14:54:52 -04:00
2023-03-31 22:31:20 -04:00
export enum MoveCategory {
2023-04-10 23:15:06 -04:00
PHYSICAL ,
2023-03-28 14:54:52 -04:00
SPECIAL ,
STATUS
2023-04-13 23:04:51 -04:00
}
2023-03-28 14:54:52 -04:00
2023-05-01 14:41:44 -04:00
export enum MoveTarget {
2024-05-16 07:07:23 -05:00
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_the_user Moves that target the User} */
2023-05-01 14:41:44 -04:00
USER ,
OTHER ,
ALL_OTHERS ,
NEAR_OTHER ,
2024-05-16 07:07:23 -05:00
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_Pok%C3%A9mon Moves that target all adjacent Pokemon} */
2023-05-01 14:41:44 -04:00
ALL_NEAR_OTHERS ,
NEAR_ENEMY ,
2024-06-06 18:11:14 -07:00
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_adjacent_foes Moves that target all adjacent foes} */
2023-05-01 14:41:44 -04:00
ALL_NEAR_ENEMIES ,
RANDOM_NEAR_ENEMY ,
ALL_ENEMIES ,
2024-05-16 07:07:23 -05:00
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Counterattacks Counterattacks} */
2023-05-01 14:41:44 -04:00
ATTACKER ,
2024-05-16 07:07:23 -05:00
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_one_adjacent_ally Moves that target one adjacent ally} */
2023-05-01 14:41:44 -04:00
NEAR_ALLY ,
2023-05-18 11:11:06 -04:00
ALLY ,
2023-05-01 14:41:44 -04:00
USER_OR_NEAR_ALLY ,
USER_AND_ALLIES ,
2024-05-16 07:07:23 -05:00
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Moves_that_target_all_Pok%C3%A9mon Moves that target all Pokemon} */
2023-05-01 14:41:44 -04:00
ALL ,
USER_SIDE ,
2024-05-17 20:20:02 -05:00
/** {@link https://bulbapedia.bulbagarden.net/wiki/Category:Entry_hazard-creating_moves Entry hazard-creating moves} */
2023-05-01 14:41:44 -04:00
ENEMY_SIDE ,
2024-05-09 15:15:56 -04:00
BOTH_SIDES ,
2024-05-19 19:40:56 +02:00
PARTY ,
CURSE
2023-05-01 14:41:44 -04:00
}
2023-04-18 12:30:47 -04:00
export enum MoveFlags {
2024-05-07 23:28:35 -05:00
NONE = 0 ,
MAKES_CONTACT = 1 << 0 ,
IGNORE_PROTECT = 1 << 1 ,
IGNORE_VIRTUAL = 1 << 2 ,
SOUND_BASED = 1 << 3 ,
HIDE_USER = 1 << 4 ,
HIDE_TARGET = 1 << 5 ,
BITING_MOVE = 1 << 6 ,
PULSE_MOVE = 1 << 7 ,
PUNCHING_MOVE = 1 << 8 ,
SLICING_MOVE = 1 << 9 ,
2024-05-24 01:45:04 +02:00
/ * *
2024-05-16 07:07:23 -05:00
* Indicates a move should be affected by { @linkcode Abilities . RECKLESS }
* @see { @linkcode Move . recklessMove ( ) }
2024-05-07 23:28:35 -05:00
* /
RECKLESS_MOVE = 1 << 10 ,
BALLBOMB_MOVE = 1 << 11 ,
POWDER_MOVE = 1 << 12 ,
DANCE_MOVE = 1 << 13 ,
WIND_MOVE = 1 << 14 ,
TRIAGE_MOVE = 1 << 15 ,
IGNORE_ABILITIES = 1 << 16 ,
2024-05-28 19:07:35 -04:00
/ * *
* Enables all hits of a multi - hit move to be accuracy checked individually
* /
CHECK_ALL_HITS = 1 << 17 ,
2023-04-18 12:30:47 -04:00
}
2024-01-07 23:17:24 -05:00
type MoveConditionFunc = ( user : Pokemon , target : Pokemon , move : Move ) = > boolean ;
type UserMoveConditionFunc = ( user : Pokemon , move : Move ) = > boolean ;
2023-04-24 14:30:21 -04:00
2024-04-19 20:55:01 +02:00
export default class Move implements Localizable {
2023-04-03 20:47:41 -04:00
public id : Moves ;
2023-03-28 14:54:52 -04:00
public name : string ;
2023-04-03 20:47:41 -04:00
public type : Type ;
2024-06-07 16:57:57 -04:00
public defaultType : Type ;
2023-04-03 23:38:31 -04:00
public category : MoveCategory ;
2023-05-01 14:41:44 -04:00
public moveTarget : MoveTarget ;
2023-03-28 14:54:52 -04:00
public power : integer ;
public accuracy : integer ;
public pp : integer ;
public effect : string ;
public chance : integer ;
2023-04-15 17:40:18 -04:00
public priority : integer ;
2023-03-28 14:54:52 -04:00
public generation : integer ;
2023-04-03 23:38:31 -04:00
public attrs : MoveAttr [ ] ;
2023-04-24 14:30:21 -04:00
private conditions : MoveCondition [ ] ;
2023-04-27 14:30:03 -04:00
private flags : integer ;
2024-04-19 17:19:24 -04:00
private nameAppend : string ;
2023-03-28 14:54:52 -04:00
2024-04-16 20:29:32 +02:00
constructor ( id : Moves , type : Type , category : MoveCategory , defaultMoveTarget : MoveTarget , power : integer , accuracy : integer , pp : integer , chance : integer , priority : integer , generation : integer ) {
2023-03-28 14:54:52 -04:00
this . id = id ;
2024-04-16 20:29:32 +02:00
2024-05-23 17:03:10 +02:00
this . nameAppend = "" ;
2023-03-28 14:54:52 -04:00
this . type = type ;
2024-06-07 16:57:57 -04:00
this . defaultType = type ;
2023-03-28 14:54:52 -04:00
this . category = category ;
2023-05-01 14:41:44 -04:00
this . moveTarget = defaultMoveTarget ;
2023-03-28 14:54:52 -04:00
this . power = power ;
this . accuracy = accuracy ;
this . pp = pp ;
this . chance = chance ;
2023-04-15 17:40:18 -04:00
this . priority = priority ;
2023-03-28 14:54:52 -04:00
this . generation = generation ;
2023-04-18 12:30:47 -04:00
2023-04-24 14:30:21 -04:00
this . attrs = [ ] ;
this . conditions = [ ] ;
2023-04-27 14:30:03 -04:00
this . flags = 0 ;
2024-05-23 17:03:10 +02:00
if ( defaultMoveTarget === MoveTarget . USER ) {
2023-04-27 14:30:03 -04:00
this . setFlag ( MoveFlags . IGNORE_PROTECT , true ) ;
2024-05-23 17:03:10 +02:00
}
if ( category === MoveCategory . PHYSICAL ) {
2023-04-27 14:30:03 -04:00
this . setFlag ( MoveFlags . MAKES_CONTACT , true ) ;
2024-05-23 17:03:10 +02:00
}
2024-04-22 01:53:24 +02:00
this . localize ( ) ;
2023-03-28 14:54:52 -04:00
}
2023-04-10 23:15:06 -04:00
2024-04-22 01:53:24 +02:00
localize ( ) : void {
2024-05-23 17:03:10 +02:00
const i18nKey = Moves [ this . id ] . split ( "_" ) . filter ( f = > f ) . map ( ( f , i ) = > i ? ` ${ f [ 0 ] } ${ f . slice ( 1 ) . toLowerCase ( ) } ` : f . toLowerCase ( ) ) . join ( "" ) as unknown as string ;
2024-04-19 20:55:01 +02:00
2024-05-29 10:54:33 -05:00
this . name = this . id ? ` ${ i18next . t ( ` move: ${ i18nKey } .name ` ) } ${ this . nameAppend } ` : "" ;
this . effect = this . id ? ` ${ i18next . t ( ` move: ${ i18nKey } .effect ` ) } ${ this . nameAppend } ` : "" ;
2024-04-19 20:55:01 +02:00
}
2024-05-31 20:50:30 -04:00
/ * *
* Get all move attributes that match ` attrType `
* @param attrType any attribute that extends { @linkcode MoveAttr }
* @returns Array of attributes that match ` attrType ` , Empty Array if none match .
* /
getAttrs < T extends MoveAttr > ( attrType : new ( . . . args : any [ ] ) = > T ) : T [ ] {
return this . attrs . filter ( ( a ) : a is T = > a instanceof attrType ) ;
}
/ * *
* Check if a move has an attribute that matches ` attrType `
* @param attrType any attribute that extends { @linkcode MoveAttr }
* @returns true if the move has attribute ` attrType `
* /
hasAttr < T extends MoveAttr > ( attrType : new ( . . . args : any [ ] ) = > T ) : boolean {
return this . attrs . some ( ( attr ) = > attr instanceof attrType ) ;
2023-04-10 23:15:06 -04:00
}
2023-04-18 12:30:47 -04:00
2024-06-06 18:11:14 -07:00
/ * *
* Takes as input a boolean function and returns the first MoveAttr in attrs that matches true
* @param attrPredicate
* @returns the first { @linkcode MoveAttr } element in attrs that makes the input function return true
* /
2024-03-30 18:46:33 -04:00
findAttr ( attrPredicate : ( attr : MoveAttr ) = > boolean ) : MoveAttr {
return this . attrs . find ( attrPredicate ) ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Adds a new MoveAttr to the move ( appends to the attr array )
* if the MoveAttr also comes with a condition , also adds that to the conditions array : { @linkcode MoveCondition }
* @param AttrType { @linkcode MoveAttr } the constructor of a MoveAttr class
* @param args the args needed to instantiate a the given class
* @returns the called object { @linkcode Move }
* /
2023-11-12 00:31:40 -05:00
attr < T extends new ( ...args : any [ ] ) = > MoveAttr > ( AttrType : T , . . . args : ConstructorParameters < T > ) : this {
2023-04-24 14:30:21 -04:00
const attr = new AttrType ( . . . args ) ;
this . attrs . push ( attr ) ;
2024-01-07 23:17:24 -05:00
let attrCondition = attr . getCondition ( ) ;
if ( attrCondition ) {
2024-05-23 17:03:10 +02:00
if ( typeof attrCondition === "function" ) {
2024-01-07 23:17:24 -05:00
attrCondition = new MoveCondition ( attrCondition ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-24 14:30:21 -04:00
this . conditions . push ( attrCondition ) ;
2024-01-07 23:17:24 -05:00
}
2023-04-24 14:30:21 -04:00
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Adds a new MoveAttr to the move ( appends to the attr array )
* if the MoveAttr also comes with a condition , also adds that to the conditions array : { @linkcode MoveCondition }
* Almost identical to { @link attr } , except you are passing in a MoveAttr object , instead of a constructor and it ' s arguments
* @param attrAdd { @linkcode MoveAttr } the attribute to add
* @returns the called object { @linkcode Move }
* /
addAttr ( attrAdd : MoveAttr ) : this {
this . attrs . push ( attrAdd ) ;
let attrCondition = attrAdd . getCondition ( ) ;
2024-01-07 23:17:24 -05:00
if ( attrCondition ) {
2024-05-23 17:03:10 +02:00
if ( typeof attrCondition === "function" ) {
2024-01-07 23:17:24 -05:00
attrCondition = new MoveCondition ( attrCondition ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-24 14:30:21 -04:00
this . conditions . push ( attrCondition ) ;
2024-01-07 23:17:24 -05:00
}
2023-04-24 14:30:21 -04:00
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the move target of this move
* @param moveTarget { @linkcode MoveTarget } the move target to set
* @returns the called object { @linkcode Move }
* /
2023-11-12 00:31:40 -05:00
target ( moveTarget : MoveTarget ) : this {
2023-05-01 14:41:44 -04:00
this . moveTarget = moveTarget ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Getter function that returns if this Move has a MoveFlag
* @param flag { @linkcode MoveFlags } to check
* @returns boolean
* /
2023-04-18 12:30:47 -04:00
hasFlag ( flag : MoveFlags ) : boolean {
2024-06-06 18:11:14 -07:00
// internally it is taking the bitwise AND (MoveFlags are represented as bit-shifts) and returning False if result is 0 and true otherwise
2023-04-18 12:30:47 -04:00
return ! ! ( this . flags & flag ) ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Getter function that returns if the move hits multiple targets
* @returns boolean
* /
2024-03-28 21:18:07 -04:00
isMultiTarget ( ) : boolean {
switch ( this . moveTarget ) {
2024-05-23 17:03:10 +02:00
case MoveTarget . ALL_OTHERS :
case MoveTarget . ALL_NEAR_OTHERS :
case MoveTarget . ALL_NEAR_ENEMIES :
case MoveTarget . ALL_ENEMIES :
case MoveTarget . USER_AND_ALLIES :
case MoveTarget . ALL :
case MoveTarget . USER_SIDE :
case MoveTarget . ENEMY_SIDE :
case MoveTarget . BOTH_SIDES :
return true ;
2024-03-28 21:18:07 -04:00
}
return false ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Getter function that returns if the move targets itself or an ally
* @returns boolean
* /
2024-05-25 04:22:10 -07:00
isAllyTarget ( ) : boolean {
switch ( this . moveTarget ) {
case MoveTarget . USER :
case MoveTarget . NEAR_ALLY :
case MoveTarget . ALLY :
case MoveTarget . USER_OR_NEAR_ALLY :
case MoveTarget . USER_AND_ALLIES :
case MoveTarget . USER_SIDE :
return true ;
}
return false ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Checks if the move is immune to certain types
* currently only look at case of Grass types and powder moves
* @param type { @linkcode Type } enum
* @returns boolean
* /
2024-03-30 17:23:58 -04:00
isTypeImmune ( type : Type ) : boolean {
switch ( type ) {
2024-05-23 17:03:10 +02:00
case Type . GRASS :
if ( this . hasFlag ( MoveFlags . POWDER_MOVE ) ) {
return true ;
}
break ;
2024-03-30 17:23:58 -04:00
}
return false ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Adds a move condition to the move
* @param condition { @linkcode MoveCondition } or { @linkcode MoveConditionFunc } , appends to conditions array a new MoveCondition object
* @returns the called object { @linkcode Move }
* /
2024-01-07 23:17:24 -05:00
condition ( condition : MoveCondition | MoveConditionFunc ) : this {
2024-05-23 17:03:10 +02:00
if ( typeof condition === "function" ) {
2024-01-07 23:17:24 -05:00
condition = new MoveCondition ( condition as MoveConditionFunc ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-24 14:30:21 -04:00
this . conditions . push ( condition ) ;
return this ;
}
2024-05-24 01:45:04 +02:00
2024-06-06 18:11:14 -07:00
/ * *
* Marks the move as "partial" : appends texts to the move name
* @returns the called object { @linkcode Move }
* /
2024-04-16 20:29:32 +02:00
partial ( ) : this {
2024-05-23 17:03:10 +02:00
this . nameAppend += " (P)" ;
2024-04-16 20:29:32 +02:00
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Marks the move as "unimplemented" : appends texts to the move name
* @returns the called object { @linkcode Move }
* /
2024-04-16 20:29:32 +02:00
unimplemented ( ) : this {
2024-05-23 17:03:10 +02:00
this . nameAppend += " (N)" ;
2024-04-16 20:29:32 +02:00
return this ;
}
2023-04-24 14:30:21 -04:00
2024-06-06 18:11:14 -07:00
/ * *
* Sets the flags of the move
* @param flag { @linkcode MoveFlags }
* @param on a boolean , if True , then "ORs" the flag onto existing ones , if False then "XORs" the flag onto existing ones
* /
2023-04-27 14:30:03 -04:00
private setFlag ( flag : MoveFlags , on : boolean ) : void {
2024-06-06 18:11:14 -07:00
// bitwise OR and bitwise XOR respectively
2024-05-23 17:03:10 +02:00
if ( on ) {
2023-04-27 14:30:03 -04:00
this . flags |= flag ;
2024-05-23 17:03:10 +02:00
} else {
2023-04-27 14:30:03 -04:00
this . flags ^= flag ;
2024-05-23 17:03:10 +02:00
}
2023-04-27 14:30:03 -04:00
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . MAKES_CONTACT } flag for the calling Move
* @param makesContact The value ( boolean ) to set the flag to
* @returns The { @linkcode Move } that called this function
* /
2023-11-12 00:31:40 -05:00
makesContact ( makesContact? : boolean ) : this {
2023-04-27 14:30:03 -04:00
this . setFlag ( MoveFlags . MAKES_CONTACT , makesContact ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . IGNORE_PROTECT } flag for the calling Move
* @param ignoresProtect The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . CURSE }
* @returns The { @linkcode Move } that called this function
* /
2023-11-12 00:31:40 -05:00
ignoresProtect ( ignoresProtect? : boolean ) : this {
2023-04-27 14:30:03 -04:00
this . setFlag ( MoveFlags . IGNORE_PROTECT , ignoresProtect ) ;
2023-04-18 12:30:47 -04:00
return this ;
}
2023-04-24 14:30:21 -04:00
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . IGNORE_VIRTUAL } flag for the calling Move
* @param ignoresVirtual The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . NATURE_POWER }
* @returns The { @linkcode Move } that called this function
* /
2023-11-12 00:31:40 -05:00
ignoresVirtual ( ignoresVirtual? : boolean ) : this {
2023-04-27 20:12:25 -04:00
this . setFlag ( MoveFlags . IGNORE_VIRTUAL , ignoresVirtual ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . SOUND_BASED } flag for the calling Move
* @param soundBased The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . UPROAR }
* @returns The { @linkcode Move } that called this function
* /
2023-11-12 00:31:40 -05:00
soundBased ( soundBased? : boolean ) : this {
2023-10-31 14:09:33 -04:00
this . setFlag ( MoveFlags . SOUND_BASED , soundBased ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . HIDE_USER } flag for the calling Move
* @param hidesUser The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . TELEPORT }
* @returns The { @linkcode Move } that called this function
* /
2023-11-12 00:31:40 -05:00
hidesUser ( hidesUser? : boolean ) : this {
2023-10-31 14:09:33 -04:00
this . setFlag ( MoveFlags . HIDE_USER , hidesUser ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . HIDE_TARGET } flag for the calling Move
* @param hidesTarget The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . WHIRLWIND }
* @returns The { @linkcode Move } that called this function
* /
2023-11-12 00:31:40 -05:00
hidesTarget ( hidesTarget? : boolean ) : this {
2023-10-31 14:09:33 -04:00
this . setFlag ( MoveFlags . HIDE_TARGET , hidesTarget ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . BITING_MOVE } flag for the calling Move
* @param bitingMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . BITE }
* @returns The { @linkcode Move } that called this function
* /
2023-12-15 01:41:45 -06:00
bitingMove ( bitingMove? : boolean ) : this {
this . setFlag ( MoveFlags . BITING_MOVE , bitingMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . PULSE_MOVE } flag for the calling Move
* @param pulseMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . WATER_PULSE }
* @returns The { @linkcode Move } that called this function
* /
2023-12-15 01:41:45 -06:00
pulseMove ( pulseMove? : boolean ) : this {
this . setFlag ( MoveFlags . PULSE_MOVE , pulseMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . PUNCHING_MOVE } flag for the calling Move
* @param punchingMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . DRAIN_PUNCH }
* @returns The { @linkcode Move } that called this function
* /
2023-12-15 01:41:45 -06:00
punchingMove ( punchingMove? : boolean ) : this {
this . setFlag ( MoveFlags . PUNCHING_MOVE , punchingMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . SLICING_MOVE } flag for the calling Move
* @param slicingMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . X_SCISSOR }
* @returns The { @linkcode Move } that called this function
* /
2023-12-15 01:41:45 -06:00
slicingMove ( slicingMove? : boolean ) : this {
this . setFlag ( MoveFlags . SLICING_MOVE , slicingMove ) ;
return this ;
}
2024-05-07 23:28:35 -05:00
/ * *
2024-05-16 07:07:23 -05:00
* Sets the { @linkcode MoveFlags . RECKLESS_MOVE } flag for the calling Move
* @see { @linkcode Abilities . RECKLESS }
* @param recklessMove The value to set the flag to
* @returns The { @linkcode Move } that called this function
2024-05-07 23:28:35 -05:00
* /
recklessMove ( recklessMove? : boolean ) : this {
this . setFlag ( MoveFlags . RECKLESS_MOVE , recklessMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . BALLBOMB_MOVE } flag for the calling Move
* @param ballBombMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . ELECTRO_BALL }
* @returns The { @linkcode Move } that called this function
* /
2023-12-15 01:41:45 -06:00
ballBombMove ( ballBombMove? : boolean ) : this {
this . setFlag ( MoveFlags . BALLBOMB_MOVE , ballBombMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . POWDER_MOVE } flag for the calling Move
* @param powderMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . STUN_SPORE }
* @returns The { @linkcode Move } that called this function
* /
2023-12-15 01:41:45 -06:00
powderMove ( powderMove? : boolean ) : this {
this . setFlag ( MoveFlags . POWDER_MOVE , powderMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . DANCE_MOVE } flag for the calling Move
* @param danceMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . PETAL_DANCE }
* @returns The { @linkcode Move } that called this function
* /
2023-12-15 01:41:45 -06:00
danceMove ( danceMove? : boolean ) : this {
this . setFlag ( MoveFlags . DANCE_MOVE , danceMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . WIND_MOVE } flag for the calling Move
* @param windMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . HURRICANE }
* @returns The { @linkcode Move } that called this function
* /
2023-12-15 01:41:45 -06:00
windMove ( windMove? : boolean ) : this {
this . setFlag ( MoveFlags . WIND_MOVE , windMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . TRIAGE_MOVE } flag for the calling Move
* @param triageMove The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . ABSORB }
* @returns The { @linkcode Move } that called this function
* /
2024-04-08 17:10:07 +03:00
triageMove ( triageMove? : boolean ) : this {
this . setFlag ( MoveFlags . TRIAGE_MOVE , triageMove ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . IGNORE_ABILITIES } flag for the calling Move
* @param ignoresAbilities sThe value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . SUNSTEEL_STRIKE }
* @returns The { @linkcode Move } that called this function
* /
2024-04-18 15:44:03 +10:00
ignoresAbilities ( ignoresAbilities? : boolean ) : this {
this . setFlag ( MoveFlags . IGNORE_ABILITIES , ignoresAbilities ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Sets the { @linkcode MoveFlags . CHECK_ALL_HITS } flag for the calling Move
* @param checkAllHits The value ( boolean ) to set the flag to
* example : @see { @linkcode Moves . TRIPLE_AXEL }
* @returns The { @linkcode Move } that called this function
* /
2024-05-28 19:07:35 -04:00
checkAllHits ( checkAllHits? : boolean ) : this {
this . setFlag ( MoveFlags . CHECK_ALL_HITS , checkAllHits ) ;
return this ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Checks if the move flag applies to the pokemon ( s ) using / receiving the move
* @param flag { @linkcode MoveFlags } MoveFlag to check on user and / or target
* @param user { @linkcode Pokemon } the Pokemon using the move
* @param target { @linkcode Pokemon } the Pokemon receiving the move
* @returns boolean
* /
2023-12-10 22:29:13 -05:00
checkFlag ( flag : MoveFlags , user : Pokemon , target : Pokemon ) : boolean {
2024-06-06 18:11:14 -07:00
// special cases below, eg: if the move flag is MAKES_CONTACT, and the user pokemon has an ability that ignores contact (like "Long Reach"), then overrides and move does not make contact
2023-12-10 22:29:13 -05:00
switch ( flag ) {
2024-05-23 17:03:10 +02:00
case MoveFlags . MAKES_CONTACT :
if ( user . hasAbilityWithAttr ( IgnoreContactAbAttr ) ) {
return false ;
}
break ;
case MoveFlags . IGNORE_ABILITIES :
if ( user . hasAbilityWithAttr ( MoveAbilityBypassAbAttr ) ) {
const abilityEffectsIgnored = new Utils . BooleanHolder ( false ) ;
applyAbAttrs ( MoveAbilityBypassAbAttr , user , abilityEffectsIgnored , this ) ;
if ( abilityEffectsIgnored . value ) {
return true ;
2024-04-18 15:44:03 +10:00
}
2024-05-23 17:03:10 +02:00
}
2024-06-15 19:14:49 -07:00
case MoveFlags . IGNORE_PROTECT :
if ( user . hasAbilityWithAttr ( IgnoreProtectOnContactAbAttr ) &&
this . checkFlag ( MoveFlags . MAKES_CONTACT , user , target ) ) {
return true ;
}
2023-12-10 22:29:13 -05:00
}
return ! ! ( this . flags & flag ) ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Applies each { @linkcode MoveCondition } of this move to the params
* @param user { @linkcode Pokemon } to apply conditions to
* @param target { @linkcode Pokemon } to apply conditions to
* @param move { @linkcode Move } to apply conditions to
* @returns boolean : false if any of the apply ( ) ' s return false , else true
* /
2023-04-24 14:30:21 -04:00
applyConditions ( user : Pokemon , target : Pokemon , move : Move ) : boolean {
2024-05-23 17:03:10 +02:00
for ( const condition of this . conditions ) {
if ( ! condition . apply ( user , target , move ) ) {
2023-04-24 14:30:21 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-24 14:30:21 -04:00
}
return true ;
}
2023-05-18 11:11:06 -04:00
2024-06-06 18:11:14 -07:00
/ * *
* Sees if , given the target pokemon , a move fails on it ( by looking at each { @linkcode MoveAttr } of this move
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } receiving the move
* @param move { @linkcode Move } using the move
* @param cancelled { @linkcode Utils . BooleanHolder } to hold boolean value
* @returns string of the failed text , or null
* /
2024-05-05 07:52:27 -07:00
getFailedText ( user : Pokemon , target : Pokemon , move : Move , cancelled : Utils.BooleanHolder ) : string | null {
2024-05-23 17:03:10 +02:00
for ( const attr of this . attrs ) {
const failedText = attr . getFailedText ( user , target , move , cancelled ) ;
if ( failedText !== null ) {
2024-05-05 10:54:22 -07:00
return failedText ;
2024-05-23 17:03:10 +02:00
}
2024-05-05 10:54:22 -07:00
}
return null ;
2024-05-05 07:52:27 -07:00
}
2024-06-06 18:11:14 -07:00
/ * *
* Calculates the userBenefitScore across all the attributes and conditions
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } receiving the move
* @param move { @linkcode Move } using the move
* @returns integer representing the total benefitScore
* /
2023-05-18 11:11:06 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
let score = 0 ;
2024-05-23 17:03:10 +02:00
for ( const attr of this . attrs ) {
2023-05-18 11:11:06 -04:00
score += attr . getUserBenefitScore ( user , target , move ) ;
2024-05-23 17:03:10 +02:00
}
2023-05-18 11:11:06 -04:00
2024-05-23 17:03:10 +02:00
for ( const condition of this . conditions ) {
2024-01-07 23:17:24 -05:00
score += condition . getUserBenefitScore ( user , target , move ) ;
2024-05-23 17:03:10 +02:00
}
2024-01-07 23:17:24 -05:00
2023-05-18 11:11:06 -04:00
return score ;
}
2024-06-06 18:11:14 -07:00
/ * *
* Calculates the targetBenefitScore across all the attributes
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } receiving the move
* @param move { @linkcode Move } using the move
* @returns integer representing the total benefitScore
* /
2023-05-18 11:11:06 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
let score = 0 ;
2024-05-23 17:03:10 +02:00
for ( const attr of this . attrs ) {
2024-06-06 18:11:14 -07:00
// conditionals to check if the move is self targeting (if so then you are applying the move to yourself, not the target)
2024-01-07 23:17:24 -05:00
score += attr . getTargetBenefitScore ( user , ! attr . selfTarget ? target : user , move ) * ( target !== user && attr . selfTarget ? - 1 : 1 ) ;
2024-05-23 17:03:10 +02:00
}
2023-05-18 11:11:06 -04:00
return score ;
}
2023-03-28 14:54:52 -04:00
}
2023-04-13 23:04:51 -04:00
export class AttackMove extends Move {
2024-04-16 20:29:32 +02:00
constructor ( id : Moves , type : Type , category : MoveCategory , power : integer , accuracy : integer , pp : integer , chance : integer , priority : integer , generation : integer ) {
super ( id , type , category , MoveTarget . NEAR_OTHER , power , accuracy , pp , chance , priority , generation ) ;
2024-05-30 16:04:50 -04:00
/ * *
* { @link https : //bulbapedia.bulbagarden.net/wiki/Freeze_(status_condition)}
* > All damaging Fire - type moves can now thaw a frozen target , regardless of whether or not they have a chance to burn ;
* /
if ( this . type === Type . FIRE ) {
this . addAttr ( new HealStatusEffectAttr ( false , StatusEffect . FREEZE ) ) ;
}
2023-04-13 23:04:51 -04:00
}
2023-05-18 11:11:06 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
let ret = super . getTargetBenefitScore ( user , target , move ) ;
let attackScore = 0 ;
2024-05-06 00:27:56 -05:00
const effectiveness = target . getAttackTypeEffectiveness ( this . type , user ) ;
2023-05-18 11:11:06 -04:00
attackScore = Math . pow ( effectiveness - 1 , 2 ) * effectiveness < 1 ? - 2 : 2 ;
if ( attackScore ) {
if ( this . category === MoveCategory . PHYSICAL ) {
2024-03-11 21:45:32 +01:00
const atk = new Utils . IntegerHolder ( user . getBattleStat ( Stat . ATK , target ) ) ;
applyMoveAttrs ( VariableAtkAttr , user , target , move , atk ) ;
if ( atk . value > user . getBattleStat ( Stat . SPATK , target ) ) {
const statRatio = user . getBattleStat ( Stat . SPATK , target ) / atk . value ;
2024-05-23 17:03:10 +02:00
if ( statRatio <= 0.75 ) {
2023-05-18 11:11:06 -04:00
attackScore *= 2 ;
2024-05-23 17:03:10 +02:00
} else if ( statRatio <= 0.875 ) {
2023-05-18 11:11:06 -04:00
attackScore *= 1.5 ;
2024-05-23 17:03:10 +02:00
}
2023-05-18 11:11:06 -04:00
}
} else {
2024-03-11 21:45:32 +01:00
const spAtk = new Utils . IntegerHolder ( user . getBattleStat ( Stat . SPATK , target ) ) ;
applyMoveAttrs ( VariableAtkAttr , user , target , move , spAtk ) ;
if ( spAtk . value > user . getBattleStat ( Stat . ATK , target ) ) {
const statRatio = user . getBattleStat ( Stat . ATK , target ) / spAtk . value ;
2024-05-23 17:03:10 +02:00
if ( statRatio <= 0.75 ) {
2023-05-18 11:11:06 -04:00
attackScore *= 2 ;
2024-05-23 17:03:10 +02:00
} else if ( statRatio <= 0.875 ) {
2023-05-18 11:11:06 -04:00
attackScore *= 1.5 ;
2024-05-23 17:03:10 +02:00
}
2023-05-18 11:11:06 -04:00
}
}
const power = new Utils . NumberHolder ( this . power ) ;
applyMoveAttrs ( VariablePowerAttr , user , target , move , power ) ;
attackScore += Math . floor ( power . value / 5 ) ;
}
ret -= attackScore ;
return ret ;
}
2023-04-13 23:04:51 -04:00
}
export class StatusMove extends Move {
2024-04-16 20:29:32 +02:00
constructor ( id : Moves , type : Type , accuracy : integer , pp : integer , chance : integer , priority : integer , generation : integer ) {
super ( id , type , MoveCategory . STATUS , MoveTarget . NEAR_OTHER , - 1 , accuracy , pp , chance , priority , generation ) ;
2023-04-18 12:30:47 -04:00
}
}
export class SelfStatusMove extends Move {
2024-04-16 20:29:32 +02:00
constructor ( id : Moves , type : Type , accuracy : integer , pp : integer , chance : integer , priority : integer , generation : integer ) {
super ( id , type , MoveCategory . STATUS , MoveTarget . USER , - 1 , accuracy , pp , chance , priority , generation ) ;
2023-04-13 23:04:51 -04:00
}
}
2024-05-24 01:45:04 +02:00
/ * *
* Base class defining all { @linkcode Move } Attributes
2024-05-14 23:19:12 -05:00
* @abstract
2024-05-16 07:07:23 -05:00
* @see { @linkcode apply }
2024-05-14 23:19:12 -05:00
* /
2023-04-03 23:38:31 -04:00
export abstract class MoveAttr {
2024-05-16 07:07:23 -05:00
/** Should this {@linkcode Move} target the user? */
2024-01-07 23:17:24 -05:00
public selfTarget : boolean ;
constructor ( selfTarget : boolean = false ) {
this . selfTarget = selfTarget ;
}
2024-05-14 23:19:12 -05:00
/ * *
* Applies move attributes
2024-05-16 07:07:23 -05:00
* @see { @linkcode applyMoveAttrsInternal }
2024-05-14 23:19:12 -05:00
* @virtual
2024-05-16 07:07:23 -05:00
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } target of the move
* @param move { @linkcode Move } with this attribute
2024-05-14 23:19:12 -05:00
* @param args Set of unique arguments needed by this attribute
2024-05-16 07:07:23 -05:00
* @returns true if application of the ability succeeds
2024-05-14 23:19:12 -05:00
* /
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean | Promise < boolean > {
2023-04-03 23:38:31 -04:00
return true ;
}
2023-04-24 14:30:21 -04:00
2024-05-24 01:45:04 +02:00
/ * *
2024-05-14 23:19:12 -05:00
* @virtual
2024-05-16 07:07:23 -05:00
* @returns the { @linkcode MoveCondition } or { @linkcode MoveConditionFunc } for this { @linkcode Move }
2024-05-14 23:19:12 -05:00
* /
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveCondition | MoveConditionFunc {
2023-04-24 14:30:21 -04:00
return null ;
}
2023-05-18 11:11:06 -04:00
2024-05-14 23:19:12 -05:00
/ * *
* @virtual
2024-05-16 07:07:23 -05:00
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } target of the move
* @param move { @linkcode Move } with this attribute
* @param cancelled { @linkcode Utils . BooleanHolder } which stores if the move should fail
* @returns the string representing failure of this { @linkcode Move }
2024-05-14 23:19:12 -05:00
* /
2024-05-05 07:52:27 -07:00
getFailedText ( user : Pokemon , target : Pokemon , move : Move , cancelled : Utils.BooleanHolder ) : string | null {
return null ;
}
2024-05-24 01:45:04 +02:00
/ * *
2024-05-14 23:19:12 -05:00
* Used by the Enemy AI to rank an attack based on a given user
2024-05-16 07:07:23 -05:00
* @see { @linkcode EnemyPokemon . getNextMove }
2024-05-14 23:19:12 -05:00
* @virtual
* /
2023-05-18 11:11:06 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return 0 ;
}
2024-05-24 01:45:04 +02:00
/ * *
2024-05-14 23:19:12 -05:00
* Used by the Enemy AI to rank an attack based on a given target
2024-05-16 07:07:23 -05:00
* @see { @linkcode EnemyPokemon . getNextMove }
2024-05-14 23:19:12 -05:00
* @virtual
* /
2023-05-18 11:11:06 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return 0 ;
}
2023-04-03 23:38:31 -04:00
}
2023-07-10 10:54:22 -04:00
export enum MoveEffectTrigger {
PRE_APPLY ,
POST_APPLY ,
2024-05-05 16:37:43 -05:00
HIT ,
/** Triggers one time after all target effects have applied */
POST_TARGET ,
2023-07-10 10:54:22 -04:00
}
2024-05-14 23:19:12 -05:00
/ * * B a s e c l a s s d e f i n i n g a l l M o v e E f f e c t A t t r i b u t e s
* @extends MoveAttr
2024-05-16 07:07:23 -05:00
* @see { @linkcode apply }
2024-05-14 23:19:12 -05:00
* /
2023-04-13 12:16:36 -04:00
export class MoveEffectAttr extends MoveAttr {
2024-05-16 07:07:23 -05:00
/ * * D e f i n e s w h e n t h i s e f f e c t s h o u l d t r i g g e r i n t h e m o v e ' s e f f e c t o r d e r
* @see { @linkcode MoveEffectPhase . start }
* /
2023-07-10 10:54:22 -04:00
public trigger : MoveEffectTrigger ;
2024-05-16 07:07:23 -05:00
/** Should this effect only apply on the first hit? */
2024-03-18 17:15:20 -04:00
public firstHitOnly : boolean ;
2023-04-15 01:32:16 -04:00
2024-03-18 17:15:20 -04:00
constructor ( selfTarget? : boolean , trigger? : MoveEffectTrigger , firstHitOnly : boolean = false ) {
2024-01-07 23:17:24 -05:00
super ( selfTarget ) ;
2023-07-10 10:54:22 -04:00
this . trigger = trigger !== undefined ? trigger : MoveEffectTrigger.POST_APPLY ;
2024-03-18 17:15:20 -04:00
this . firstHitOnly = firstHitOnly ;
2023-04-15 01:32:16 -04:00
}
2024-05-14 23:19:12 -05:00
/ * *
2024-05-16 07:07:23 -05:00
* Determines whether the { @linkcode Move } ' s effects are valid to { @linkcode apply }
2024-05-14 23:19:12 -05:00
* @virtual
2024-05-16 07:07:23 -05:00
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } target of the move
* @param move { @linkcode Move } with this attribute
2024-05-14 23:19:12 -05:00
* @param args Set of unique arguments needed by this attribute
2024-05-16 07:07:23 -05:00
* @returns true if basic application of the ability attribute should be possible
2024-05-14 23:19:12 -05:00
* /
2023-04-16 00:29:55 -04:00
canApply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) {
2024-05-16 07:07:23 -05:00
return ! ! ( this . selfTarget ? user . hp && ! user . getTag ( BattlerTagType . FRENZY ) : target . hp )
2024-06-15 19:14:49 -07:00
&& ( this . selfTarget || ! target . getTag ( BattlerTagType . PROTECTED ) ||
move . checkFlag ( MoveFlags . IGNORE_PROTECT , user , target ) ) ;
2023-04-15 01:32:16 -04:00
}
2024-05-16 07:07:23 -05:00
/** Applies move effects so long as they are able based on {@linkcode canApply} */
2023-10-21 20:40:46 -05:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean | Promise < boolean > {
2024-05-24 01:45:04 +02:00
return this . canApply ( user , target , move , args ) ;
2023-04-15 01:32:16 -04:00
}
2023-04-13 12:16:36 -04:00
}
2024-03-18 22:05:21 -04:00
export class PreMoveMessageAttr extends MoveAttr {
private message : string | ( ( user : Pokemon , target : Pokemon , move : Move ) = > string ) ;
constructor ( message : string | ( ( user : Pokemon , target : Pokemon , move : Move ) = > string ) ) {
super ( ) ;
this . message = message ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
const message = typeof this . message === "string"
2024-03-18 22:05:21 -04:00
? this . message as string
: this . message ( user , target , move ) ;
2024-03-30 22:40:00 -05:00
if ( message ) {
user . scene . queueMessage ( message , 500 ) ;
return true ;
}
return false ;
2024-03-18 22:05:21 -04:00
}
}
2024-03-04 20:28:55 -05:00
export class StatusMoveTypeImmunityAttr extends MoveAttr {
public immuneType : Type ;
constructor ( immuneType : Type ) {
super ( false ) ;
2024-03-10 10:16:49 -04:00
this . immuneType = immuneType ;
2024-03-04 20:28:55 -05:00
}
}
2024-04-02 20:51:38 +03:00
export class IgnoreOpponentStatChangesAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . IntegerHolder ) . value = 0 ;
return true ;
}
}
2023-04-10 23:15:06 -04:00
export class HighCritAttr extends MoveAttr {
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-04-18 22:09:37 -04:00
( args [ 0 ] as Utils . IntegerHolder ) . value ++ ;
2023-04-11 19:08:03 -04:00
2023-04-10 23:15:06 -04:00
return true ;
}
2023-05-18 11:11:06 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return 3 ;
}
2023-04-03 23:38:31 -04:00
}
2023-05-05 18:20:55 -04:00
export class CritOnlyAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . BooleanHolder ) . value = true ;
return true ;
}
2023-05-18 11:11:06 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return 5 ;
}
2023-05-05 18:20:55 -04:00
}
2023-04-15 17:40:18 -04:00
export class FixedDamageAttr extends MoveAttr {
private damage : integer ;
constructor ( damage : integer ) {
super ( ) ;
this . damage = damage ;
}
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-07-05 16:25:09 -04:00
( args [ 0 ] as Utils . IntegerHolder ) . value = this . getDamage ( user , target , move ) ;
2023-04-15 17:40:18 -04:00
return true ;
}
2023-04-18 13:36:11 -04:00
2023-07-05 16:25:09 -04:00
getDamage ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2023-04-18 13:36:11 -04:00
return this . damage ;
}
}
export class UserHpDamageAttr extends FixedDamageAttr {
constructor ( ) {
super ( 0 ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . IntegerHolder ) . value = user . hp ;
return true ;
}
}
2023-04-22 10:56:17 -04:00
export class TargetHalfHpDamageAttr extends FixedDamageAttr {
constructor ( ) {
super ( 0 ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-01 18:05:34 -05:00
( args [ 0 ] as Utils . IntegerHolder ) . value = Math . max ( Math . floor ( target . hp / 2 ) , 1 ) ;
2023-04-22 10:56:17 -04:00
return true ;
}
2024-04-09 11:04:09 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
2024-04-09 11:25:15 -04:00
return target . getHpRatio ( ) > 0.5 ? Math . floor ( ( ( target . getHpRatio ( ) - 0.5 ) * - 24 ) + 4 ) : - 20 ;
2024-04-09 11:04:09 -04:00
}
2023-04-22 10:56:17 -04:00
}
2023-10-20 20:30:28 -05:00
export class MatchHpAttr extends FixedDamageAttr {
constructor ( ) {
super ( 0 ) ;
}
2024-05-24 01:45:04 +02:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-10-20 20:30:28 -05:00
( args [ 0 ] as Utils . IntegerHolder ) . value = target . hp - user . hp ;
return true ;
2024-05-24 01:45:04 +02:00
}
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-12-10 17:57:12 -05:00
return ( user , target , move ) = > user . hp <= target . hp ;
2023-10-20 20:30:28 -05:00
}
2024-05-24 01:45:04 +02:00
2023-10-20 20:30:28 -05:00
// TODO
/ * g e t U s e r B e n e f i t S c o r e ( u s e r : P o k e m o n , t a r g e t : P o k e m o n , m o v e : M o v e ) : i n t e g e r {
return 0 ;
} * /
}
2023-05-06 00:42:01 -04:00
type MoveFilter = ( move : Move ) = > boolean ;
export class CounterDamageAttr extends FixedDamageAttr {
private moveFilter : MoveFilter ;
2024-04-08 12:13:34 -04:00
private multiplier : number ;
2023-05-06 00:42:01 -04:00
2024-04-08 12:13:34 -04:00
constructor ( moveFilter : MoveFilter , multiplier : integer ) {
2023-05-06 00:42:01 -04:00
super ( 0 ) ;
this . moveFilter = moveFilter ;
2024-04-08 12:13:34 -04:00
this . multiplier = multiplier ;
2023-05-06 00:42:01 -04:00
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const damage = user . turnData . attacksReceived . filter ( ar = > this . moveFilter ( allMoves [ ar . move ] ) ) . reduce ( ( total : integer , ar : AttackMoveResult ) = > total + ar . damage , 0 ) ;
2024-04-08 12:13:34 -04:00
( args [ 0 ] as Utils . IntegerHolder ) . value = Math . floor ( Math . max ( damage * this . multiplier , 1 ) ) ;
2023-05-06 00:42:01 -04:00
return true ;
}
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-12-10 17:57:12 -05:00
return ( user , target , move ) = > ! ! user . turnData . attacksReceived . filter ( ar = > this . moveFilter ( allMoves [ ar . move ] ) ) . length ;
2023-05-06 00:42:01 -04:00
}
}
2023-07-05 16:25:09 -04:00
export class LevelDamageAttr extends FixedDamageAttr {
constructor ( ) {
super ( 0 ) ;
}
getDamage ( user : Pokemon , target : Pokemon , move : Move ) : number {
return user . level ;
}
}
export class RandomLevelDamageAttr extends FixedDamageAttr {
constructor ( ) {
super ( 0 ) ;
}
getDamage ( user : Pokemon , target : Pokemon , move : Move ) : number {
2024-01-02 21:31:59 -05:00
return Math . max ( Math . floor ( user . level * ( user . randSeedIntRange ( 50 , 150 ) * 0.01 ) ) , 1 ) ;
2023-07-05 16:25:09 -04:00
}
}
2024-03-29 11:58:22 -04:00
export class ModifiedDamageAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const initialDamage = args [ 0 ] as Utils . IntegerHolder ;
initialDamage . value = this . getModifiedDamage ( user , target , move , initialDamage . value ) ;
return true ;
}
getModifiedDamage ( user : Pokemon , target : Pokemon , move : Move , damage : integer ) : integer {
return damage ;
}
}
export class SurviveDamageAttr extends ModifiedDamageAttr {
getModifiedDamage ( user : Pokemon , target : Pokemon , move : Move , damage : number ) : number {
return Math . min ( damage , target . hp - 1 ) ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > target . hp > 1 ;
}
2024-05-24 01:45:04 +02:00
2024-03-29 11:58:22 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return target . hp > 1 ? 0 : - 20 ;
}
}
2023-04-18 13:36:11 -04:00
export class RecoilAttr extends MoveEffectAttr {
2023-04-27 14:30:03 -04:00
private useHp : boolean ;
2023-12-08 16:29:03 -05:00
private damageRatio : number ;
2024-04-20 19:43:48 -04:00
private unblockable : boolean ;
2023-04-27 14:30:03 -04:00
2024-04-20 19:43:48 -04:00
constructor ( useHp : boolean = false , damageRatio : number = 0.25 , unblockable : boolean = false ) {
2023-04-18 13:36:11 -04:00
super ( true ) ;
2023-04-27 14:30:03 -04:00
this . useHp = useHp ;
2024-04-20 19:43:48 -04:00
this . damageRatio = damageRatio ;
this . unblockable = unblockable ;
2023-04-18 13:36:11 -04:00
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-18 13:36:11 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-18 13:36:11 -04:00
2023-04-27 14:30:03 -04:00
const cancelled = new Utils . BooleanHolder ( false ) ;
2024-05-23 17:03:10 +02:00
if ( ! this . unblockable ) {
2024-04-20 19:43:48 -04:00
applyAbAttrs ( BlockRecoilDamageAttr , user , cancelled ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-27 14:30:03 -04:00
2024-05-23 17:03:10 +02:00
if ( cancelled . value ) {
2023-04-27 14:30:03 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-27 14:30:03 -04:00
2024-05-20 00:54:17 +02:00
const recoilDamage = Math . max ( Math . floor ( ( ! this . useHp ? user.turnData.currDamageDealt : user.getMaxHp ( ) ) * this . damageRatio ) ,
user . turnData . currDamageDealt ? 1 : 0 ) ;
2024-05-23 17:03:10 +02:00
if ( ! recoilDamage ) {
2023-11-26 22:22:05 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-11-26 22:22:05 -05:00
2024-04-02 15:14:07 -04:00
applyAbAttrs ( BlockNonDirectDamageAbAttr , user , cancelled ) ;
2024-05-23 17:03:10 +02:00
if ( cancelled . value ) {
2024-04-02 15:14:07 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2024-04-06 01:56:49 -04:00
user . damageAndUpdate ( recoilDamage , HitResult . OTHER , false , true , true ) ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( user , " is hit\nwith recoil!" ) ) ;
user . turnData . damageTaken += recoilDamage ;
2023-04-18 13:36:11 -04:00
return true ;
}
2023-05-18 11:11:06 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return Math . floor ( ( move . power / 5 ) / - 4 ) ;
}
2023-04-18 13:36:11 -04:00
}
2024-05-15 11:10:20 +02:00
/ * *
* Attribute used for moves which self KO the user regardless if the move hits a target
* @extends MoveEffectAttr
2024-05-16 07:07:23 -05:00
* @see { @linkcode apply }
2024-05-15 11:10:20 +02:00
* * /
2023-04-18 13:36:11 -04:00
export class SacrificialAttr extends MoveEffectAttr {
constructor ( ) {
2024-05-15 11:10:20 +02:00
super ( true , MoveEffectTrigger . POST_TARGET ) ;
2023-04-18 13:36:11 -04:00
}
2024-05-15 11:10:20 +02:00
/ * *
* Deals damage to the user equal to their current hp
2024-05-16 07:07:23 -05:00
* @param user { @linkcode Pokemon } that used the move
* @param target { @linkcode Pokemon } target of the move
* @param move { @linkcode Move } with this attribute
2024-05-15 11:10:20 +02:00
* @param args N / A
* @returns true if the function succeeds
* * /
2023-04-18 13:36:11 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-15 11:10:20 +02:00
user . damageAndUpdate ( user . hp , HitResult . OTHER , false , true , true ) ;
user . turnData . damageTaken += user . hp ;
return true ;
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2024-05-23 17:03:10 +02:00
if ( user . isBoss ( ) ) {
2024-05-15 11:10:20 +02:00
return - 20 ;
2024-05-23 17:03:10 +02:00
}
2024-05-15 11:10:20 +02:00
return Math . ceil ( ( ( 1 - user . getHpRatio ( ) ) * 10 - 10 ) * ( target . getAttackTypeEffectiveness ( move . type , user ) - 0.5 ) ) ;
}
}
/ * *
* Attribute used for moves which self KO the user but only if the move hits a target
* @extends MoveEffectAttr
2024-05-16 07:07:23 -05:00
* @see { @linkcode apply }
2024-05-15 11:10:20 +02:00
* * /
export class SacrificialAttrOnHit extends MoveEffectAttr {
constructor ( ) {
super ( true , MoveEffectTrigger . POST_TARGET ) ;
}
/ * *
* Deals damage to the user equal to their current hp if the move lands
2024-05-16 07:07:23 -05:00
* @param user { @linkcode Pokemon } that used the move
* @param target { @linkcode Pokemon } target of the move
* @param move { @linkcode Move } with this attribute
2024-05-15 11:10:20 +02:00
* @param args N / A
* @returns true if the function succeeds
* * /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
// If the move fails to hit a target, then the user does not faint and the function returns false
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-18 13:36:11 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-18 13:36:11 -04:00
2024-03-01 10:15:43 -05:00
user . damageAndUpdate ( user . hp , HitResult . OTHER , false , true , true ) ;
2024-05-15 11:10:20 +02:00
user . turnData . damageTaken += user . hp ;
2023-04-18 13:36:11 -04:00
return true ;
}
2023-05-18 11:11:06 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2024-05-23 17:03:10 +02:00
if ( user . isBoss ( ) ) {
2024-04-05 12:36:09 -04:00
return - 20 ;
2024-05-23 17:03:10 +02:00
}
2024-05-06 00:27:56 -05:00
return Math . ceil ( ( ( 1 - user . getHpRatio ( ) ) * 10 - 10 ) * ( target . getAttackTypeEffectiveness ( move . type , user ) - 0.5 ) ) ;
2023-05-18 11:11:06 -04:00
}
2023-04-15 17:40:18 -04:00
}
2024-05-05 16:37:43 -05:00
/ * *
* Attribute used for moves which cut the user ' s Max HP in half .
2024-05-16 07:07:23 -05:00
* Triggers using { @linkcode MoveEffectTrigger . POST_TARGET } .
* @extends MoveEffectAttr
* @see { @linkcode apply }
2024-05-05 16:37:43 -05:00
* /
2024-04-25 21:42:41 -04:00
export class HalfSacrificialAttr extends MoveEffectAttr {
constructor ( ) {
2024-05-05 16:37:43 -05:00
super ( true , MoveEffectTrigger . POST_TARGET ) ;
2024-04-25 21:42:41 -04:00
}
2024-05-05 16:37:43 -05:00
/ * *
* Cut 's the user' s Max HP in half and displays the appropriate recoil message
2024-05-16 07:07:23 -05:00
* @param user { @linkcode Pokemon } that used the move
2024-05-05 16:37:43 -05:00
* @param target N / A
2024-05-16 07:07:23 -05:00
* @param move { @linkcode Move } with this attribute
2024-05-05 16:37:43 -05:00
* @param args N / A
* @returns true if the function succeeds
* /
2024-04-25 21:42:41 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-25 21:42:41 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-25 21:42:41 -04:00
const cancelled = new Utils . BooleanHolder ( false ) ;
2024-05-05 16:37:43 -05:00
// Check to see if the Pokemon has an ability that blocks non-direct damage
2024-04-25 21:42:41 -04:00
applyAbAttrs ( BlockNonDirectDamageAbAttr , user , cancelled ) ;
2024-05-24 02:19:20 +02:00
if ( ! cancelled . value ) {
2024-04-25 21:42:41 -04:00
user . damageAndUpdate ( Math . ceil ( user . getMaxHp ( ) / 2 ) , HitResult . OTHER , false , true , true ) ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( user , " cut its own HP to power up its move!" ) ) ; // Queue recoil message
2024-05-24 01:45:04 +02:00
}
2024-04-25 21:42:41 -04:00
return true ;
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2024-05-23 17:03:10 +02:00
if ( user . isBoss ( ) ) {
2024-04-25 21:42:41 -04:00
return - 10 ;
2024-05-23 17:03:10 +02:00
}
2024-05-06 00:27:56 -05:00
return Math . ceil ( ( ( 1 - user . getHpRatio ( ) / 2 ) * 10 - 10 ) * ( target . getAttackTypeEffectiveness ( move . type , user ) - 0.5 ) ) ;
2024-04-25 21:42:41 -04:00
}
}
2023-04-17 00:46:50 -04:00
export enum MultiHitType {
2023-04-10 16:17:25 -04:00
_2 ,
_2_TO_5 ,
2023-12-09 20:09:09 -05:00
_3 ,
2024-05-28 19:07:35 -04:00
_10 ,
2024-05-19 07:22:37 -07:00
BEAT_UP ,
2023-04-10 16:17:25 -04:00
}
2024-05-14 23:19:12 -05:00
/ * *
2024-05-16 07:07:23 -05:00
* Heals the user or target by { @linkcode healRatio } depending on the value of { @linkcode selfTarget }
2024-05-14 23:19:12 -05:00
* @extends MoveEffectAttr
2024-05-16 07:07:23 -05:00
* @see { @linkcode apply }
2024-05-14 23:19:12 -05:00
* /
2023-04-17 00:46:50 -04:00
export class HealAttr extends MoveEffectAttr {
2024-05-16 07:07:23 -05:00
/** The percentage of {@linkcode Stat.HP} to heal */
2023-04-17 00:46:50 -04:00
private healRatio : number ;
2024-05-14 23:19:12 -05:00
/** Should an animation be shown? */
2023-04-16 18:40:32 -04:00
private showAnim : boolean ;
2023-04-18 12:30:47 -04:00
constructor ( healRatio? : number , showAnim? : boolean , selfTarget? : boolean ) {
super ( selfTarget === undefined || selfTarget ) ;
2023-04-16 18:40:32 -04:00
2023-04-17 00:46:50 -04:00
this . healRatio = healRatio || 1 ;
2023-04-16 18:40:32 -04:00
this . showAnim = ! ! showAnim ;
}
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-05-31 15:04:03 -04:00
this . addHealPhase ( this . selfTarget ? user : target , this . healRatio ) ;
2023-04-16 00:29:55 -04:00
return true ;
}
2023-04-17 00:46:50 -04:00
2024-05-24 01:45:04 +02:00
/ * *
2024-05-16 07:07:23 -05:00
* Creates a new { @linkcode PokemonHealPhase } .
2024-05-14 23:19:12 -05:00
* This heals the target and shows the appropriate message .
* /
2023-05-31 15:04:03 -04:00
addHealPhase ( target : Pokemon , healRatio : number ) {
target . scene . unshiftPhase ( new PokemonHealPhase ( target . scene , target . getBattlerIndex ( ) ,
2024-05-23 17:03:10 +02:00
Math . max ( Math . floor ( target . getMaxHp ( ) * healRatio ) , 1 ) , getPokemonMessage ( target , " \nhad its HP restored." ) , true , ! this . showAnim ) ) ;
2023-05-18 11:11:06 -04:00
}
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2024-05-23 17:03:10 +02:00
const score = ( ( 1 - ( this . selfTarget ? user : target ) . getHpRatio ( ) ) * 20 ) - this . healRatio * 10 ;
2024-03-27 13:13:37 -04:00
return Math . round ( score / ( 1 - this . healRatio / 2 ) ) ;
2023-04-17 00:46:50 -04:00
}
2023-04-16 00:29:55 -04:00
}
2024-05-09 15:15:56 -04:00
/ * *
* Cures the user ' s party of non - volatile status conditions , ie . Heal Bell , Aromatherapy
2024-05-16 07:07:23 -05:00
* @extends MoveEffectAttr
* @see { @linkcode apply }
2024-05-09 15:15:56 -04:00
* /
export class PartyStatusCureAttr extends MoveEffectAttr {
2024-05-16 07:07:23 -05:00
/** Message to display after using move */
2024-05-09 15:15:56 -04:00
private message : string ;
2024-05-16 07:07:23 -05:00
/** Skips mons with this ability, ie. Soundproof */
2024-05-09 15:15:56 -04:00
private abilityCondition : Abilities ;
constructor ( message : string , abilityCondition : Abilities ) {
super ( ) ;
this . message = message ;
this . abilityCondition = abilityCondition ;
}
2024-06-09 15:08:33 -05:00
//The same as MoveEffectAttr.canApply, except it doesn't check for the target's HP.
canApply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) {
const isTargetValid =
( this . selfTarget && user . hp && ! user . getTag ( BattlerTagType . FRENZY ) ) ||
( ! this . selfTarget && ( ! target . getTag ( BattlerTagType . PROTECTED ) || move . hasFlag ( MoveFlags . IGNORE_PROTECT ) ) ) ;
return ! ! isTargetValid ;
}
2024-05-09 15:15:56 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-06-09 15:08:33 -05:00
if ( ! this . canApply ( user , target , move , args ) ) {
2024-05-09 15:15:56 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-09 15:15:56 -04:00
this . addPartyCurePhase ( user ) ;
}
addPartyCurePhase ( user : Pokemon ) {
user . scene . unshiftPhase ( new PartyStatusCurePhase ( user . scene , user , this . message , this . abilityCondition ) ) ;
}
}
2024-03-11 18:18:49 +01:00
export class SacrificialFullRestoreAttr extends SacrificialAttr {
constructor ( ) {
super ( ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-03-11 18:18:49 +01:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-03-11 18:18:49 +01:00
// We don't know which party member will be chosen, so pick the highest max HP in the party
const maxPartyMemberHp = user . scene . getParty ( ) . map ( p = > p . getMaxHp ( ) ) . reduce ( ( maxHp : integer , hp : integer ) = > Math . max ( hp , maxHp ) , 0 ) ;
user . scene . pushPhase ( new PokemonHealPhase ( user . scene , user . getBattlerIndex ( ) ,
2024-05-23 17:03:10 +02:00
maxPartyMemberHp , getPokemonMessage ( user , "'s Healing Wish\nwas granted!" ) , true , false , false , true ) , true ) ;
2024-03-11 18:18:49 +01:00
return true ;
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return - 20 ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > user . scene . getParty ( ) . filter ( p = > p . isActive ( ) ) . length > user . scene . currentBattle . getBattlerCount ( ) ;
}
}
2024-05-09 21:21:57 -04:00
/ * *
* Attribute used for moves which ignore type - based debuffs from weather , namely Hydro Steam .
* Called during damage calculation after getting said debuff from getAttackTypeMultiplier in the Pokemon class .
2024-05-16 07:07:23 -05:00
* @extends MoveAttr
* @see { @linkcode apply }
2024-05-09 21:21:57 -04:00
* /
export class IgnoreWeatherTypeDebuffAttr extends MoveAttr {
2024-05-16 07:07:23 -05:00
/** The {@linkcode WeatherType} this move ignores */
2024-05-09 21:21:57 -04:00
public weather : WeatherType ;
2024-05-16 07:07:23 -05:00
2024-05-24 02:19:20 +02:00
constructor ( weather : WeatherType ) {
2024-05-09 21:21:57 -04:00
super ( ) ;
this . weather = weather ;
}
/ * *
* Changes the type - based weather modifier if this move ' s power would be reduced by it
2024-05-16 07:07:23 -05:00
* @param user { @linkcode Pokemon } that used the move
2024-05-09 21:21:57 -04:00
* @param target N / A
2024-05-16 07:07:23 -05:00
* @param move { @linkcode Move } with this attribute
* @param args [ 0 ] { @linkcode Utils . NumberHolder } for arenaAttackTypeMultiplier
2024-05-09 21:21:57 -04:00
* @returns true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const weatherModifier = args [ 0 ] as Utils . NumberHolder ;
//If the type-based attack power modifier due to weather (e.g. Water moves in Sun) is below 1, set it to 1
2024-05-23 17:03:10 +02:00
if ( user . scene . arena . weather ? . weatherType === this . weather ) {
2024-05-09 21:21:57 -04:00
weatherModifier . value = Math . max ( weatherModifier . value , 1 ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-09 21:21:57 -04:00
return true ;
}
}
2023-12-08 16:29:03 -05:00
export abstract class WeatherHealAttr extends HealAttr {
2023-04-17 00:46:50 -04:00
constructor ( ) {
super ( 0.5 ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
let healRatio = 0.5 ;
2023-04-27 14:30:03 -04:00
if ( ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) ) {
const weatherType = user . scene . arena . weather ? . weatherType || WeatherType . NONE ;
2023-12-08 16:29:03 -05:00
healRatio = this . getWeatherHealRatio ( weatherType ) ;
2023-04-17 00:46:50 -04:00
}
this . addHealPhase ( user , healRatio ) ;
return true ;
}
2023-12-08 16:29:03 -05:00
abstract getWeatherHealRatio ( weatherType : WeatherType ) : number ;
}
export class PlantHealAttr extends WeatherHealAttr {
getWeatherHealRatio ( weatherType : WeatherType ) : number {
switch ( weatherType ) {
2024-05-23 17:03:10 +02:00
case WeatherType . SUNNY :
case WeatherType . HARSH_SUN :
return 2 / 3 ;
case WeatherType . RAIN :
case WeatherType . SANDSTORM :
case WeatherType . HAIL :
case WeatherType . SNOW :
case WeatherType . HEAVY_RAIN :
return 0.25 ;
default :
return 0.5 ;
2023-12-08 16:29:03 -05:00
}
}
}
export class SandHealAttr extends WeatherHealAttr {
getWeatherHealRatio ( weatherType : WeatherType ) : number {
switch ( weatherType ) {
2024-05-23 17:03:10 +02:00
case WeatherType . SANDSTORM :
return 2 / 3 ;
default :
return 0.5 ;
2023-12-08 16:29:03 -05:00
}
}
2023-04-17 00:46:50 -04:00
}
2024-05-13 11:27:38 +02:00
/ * *
2024-05-24 01:45:04 +02:00
* Heals the target or the user by either { @linkcode normalHealRatio } or { @linkcode boostedHealRatio }
2024-05-16 07:07:23 -05:00
* depending on the evaluation of { @linkcode condition }
2024-05-14 23:19:12 -05:00
* @extends HealAttr
2024-05-16 07:07:23 -05:00
* @see { @linkcode apply }
2024-05-13 11:27:38 +02:00
* /
export class BoostHealAttr extends HealAttr {
2024-05-16 07:07:23 -05:00
/** Healing received when {@linkcode condition} is false */
2024-05-13 11:27:38 +02:00
private normalHealRatio? : number ;
2024-05-16 07:07:23 -05:00
/** Healing received when {@linkcode condition} is true */
2024-05-13 11:27:38 +02:00
private boostedHealRatio? : number ;
2024-05-14 23:19:12 -05:00
/** The lambda expression to check against when boosting the healing value */
2024-05-13 11:27:38 +02:00
private condition? : MoveConditionFunc ;
constructor ( normalHealRatio? : number , boostedHealRatio? : number , showAnim? : boolean , selfTarget? : boolean , condition? : MoveConditionFunc ) {
super ( normalHealRatio , showAnim , selfTarget ) ;
this . normalHealRatio = normalHealRatio ;
this . boostedHealRatio = boostedHealRatio ;
this . condition = condition ;
}
2024-05-14 23:19:12 -05:00
/ * *
2024-05-16 07:07:23 -05:00
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } target of the move
* @param move { @linkcode Move } with this attribute
2024-05-14 23:19:12 -05:00
* @param args N / A
* @returns true if the move was successful
* /
2024-05-13 11:27:38 +02:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const healRatio = this . condition ( user , target , move ) ? this . boostedHealRatio : this.normalHealRatio ;
this . addHealPhase ( target , healRatio ) ;
return true ;
}
}
2024-06-03 22:26:15 +02:00
/ * *
* Heals the target only if it is the ally
* @extends HealAttr
* @see { @linkcode apply }
* /
export class HealOnAllyAttr extends HealAttr {
/ * *
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } target of the move
* @param move { @linkcode Move } with this attribute
* @param args N / A
* @returns true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( user . getAlly ( ) === target ) {
super . apply ( user , target , move , args ) ;
return true ;
}
return false ;
}
}
2024-06-01 15:53:32 -04:00
/ * *
* Heals user as a side effect of a move that hits a target .
* Healing is based on { @linkcode healRatio } * the amount of damage dealt or a stat of the target .
* @extends MoveEffectAttr
* @see { @linkcode apply }
* @see { @linkcode getUserBenefitScore }
* /
2023-07-10 10:54:22 -04:00
export class HitHealAttr extends MoveEffectAttr {
2023-04-26 16:07:29 -04:00
private healRatio : number ;
2024-06-01 15:53:32 -04:00
private message : string ;
private healStat : Stat ;
2023-04-26 16:07:29 -04:00
2024-06-01 15:53:32 -04:00
constructor ( healRatio? : number , healStat? : Stat ) {
2023-07-10 10:54:22 -04:00
super ( true , MoveEffectTrigger . HIT ) ;
2023-04-26 16:07:29 -04:00
this . healRatio = healRatio || 0.5 ;
2024-06-01 15:53:32 -04:00
this . healStat = healStat || null ;
2023-04-26 16:07:29 -04:00
}
2024-06-01 15:53:32 -04:00
/ * *
* Heals the user the determined amount and possibly displays a message about regaining health .
* If the target has the { @linkcode ReverseDrainAbAttr } , all healing is instead converted
* to damage to the user .
* @param user { @linkcode Pokemon } using this move
* @param target { @linkcode Pokemon } target of this move
* @param move { @linkcode Move } being used
* @param args N / A
* @returns true if the function succeeds
* /
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-06-01 15:53:32 -04:00
let healAmount = 0 ;
let message = "" ;
const reverseDrain = target . hasAbilityWithAttr ( ReverseDrainAbAttr , false ) ;
if ( this . healStat ) {
// Strength Sap formula
healAmount = target . getBattleStat ( this . healStat ) ;
message = i18next . t ( "battle:drainMessage" , { pokemonName : target.name } ) ;
} else {
// Default healing formula used by draining moves like Absorb, Draining Kiss, Bitter Blade, etc.
2024-06-08 23:53:03 -04:00
healAmount = Math . max ( Math . floor ( user . turnData . currDamageDealt * this . healRatio ) , 1 ) ;
2024-06-01 15:53:32 -04:00
message = i18next . t ( "battle:regainHealth" , { pokemonName : user.name } ) ;
}
2024-05-23 17:03:10 +02:00
if ( reverseDrain ) {
user . turnData . damageTaken += healAmount ;
2024-06-01 15:53:32 -04:00
healAmount = healAmount * - 1 ;
message = null ;
2024-05-23 17:03:10 +02:00
}
2024-06-01 15:53:32 -04:00
user . scene . unshiftPhase ( new PokemonHealPhase ( user . scene , user . getBattlerIndex ( ) , healAmount , message , false , true ) ) ;
2023-04-16 00:29:55 -04:00
return true ;
}
2023-05-18 11:11:06 -04:00
2024-06-01 15:53:32 -04:00
/ * *
* Used by the Enemy AI to rank an attack based on a given user
* @param user { @linkcode Pokemon } using this move
* @param target { @linkcode Pokemon } target of this move
* @param move { @linkcode Move } being used
* @returns an integer . Higher means enemy is more likely to use that move .
* /
2023-05-18 11:11:06 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2024-06-01 15:53:32 -04:00
if ( this . healStat ) {
const healAmount = target . getBattleStat ( this . healStat ) ;
return Math . floor ( Math . max ( 0 , ( Math . min ( 1 , ( healAmount + user . hp ) / user . getMaxHp ( ) - 0.33 ) ) ) / user . getHpRatio ( ) ) ;
}
return Math . floor ( Math . max ( ( 1 - user . getHpRatio ( ) ) - 0.33 , 0 ) * ( move . power / 4 ) ) ;
2023-05-18 11:11:06 -04:00
}
2023-04-16 00:29:55 -04:00
}
2024-05-20 07:52:51 +09:00
/ * *
* Attribute used for moves that change priority in a turn given a condition ,
* e . g . Grassy Glide
* Called when move order is calculated in { @linkcode TurnStartPhase } .
* @extends MoveAttr
* @see { @linkcode apply }
* /
export class IncrementMovePriorityAttr extends MoveAttr {
/** The condition for a move's priority being incremented */
private moveIncrementFunc : ( pokemon : Pokemon , target :Pokemon , move : Move ) = > boolean ;
/** The amount to increment priority by, if condition passes. */
private increaseAmount : integer ;
constructor ( moveIncrementFunc : ( pokemon : Pokemon , target :Pokemon , move : Move ) = > boolean , increaseAmount = 1 ) {
super ( ) ;
this . moveIncrementFunc = moveIncrementFunc ;
this . increaseAmount = increaseAmount ;
}
/ * *
* Increments move priority by set amount if condition passes
* @param user { @linkcode Pokemon } using this move
* @param target { @linkcode Pokemon } target of this move
* @param move { @linkcode Move } being used
* @param args [ 0 ] { @linkcode Utils . IntegerHolder } for move priority .
* @returns true if function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! this . moveIncrementFunc ( user , target , move ) ) {
2024-05-20 07:52:51 +09:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2024-05-20 07:52:51 +09:00
( args [ 0 ] as Utils . IntegerHolder ) . value += this . increaseAmount ;
return true ;
}
}
2024-04-12 10:47:59 +10:00
2024-06-13 14:23:13 -04:00
/ * *
* Attribute used for attack moves that hit multiple times per use , e . g . Bullet Seed .
*
* Applied at the beginning of { @linkcode MoveEffectPhase } .
*
* @extends MoveAttr
* @see { @linkcode apply }
* /
2023-04-10 16:17:25 -04:00
export class MultiHitAttr extends MoveAttr {
private multiHitType : MultiHitType ;
constructor ( multiHitType? : MultiHitType ) {
2023-04-03 23:38:31 -04:00
super ( ) ;
2023-04-10 16:17:25 -04:00
this . multiHitType = multiHitType !== undefined ? multiHitType : MultiHitType._2_TO_5 ;
2023-04-03 23:38:31 -04:00
}
2024-06-13 14:23:13 -04:00
/ * *
* Set the hit count of an attack based on this attribute instance ' s { @linkcode MultiHitType } .
* If the target has an immunity to this attack ' s types , the hit count will always be 1 .
*
* @param user { @linkcode Pokemon } that used the attack
* @param target { @linkcode Pokemon } targeted by the attack
* @param move { @linkcode Move } being used
* @param args [ 0 ] { @linkcode Utils . IntegerHolder } storing the hit count of the attack
* @returns True
* /
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-04-03 23:38:31 -04:00
let hitTimes : integer ;
2024-06-13 14:23:13 -04:00
if ( target . getAttackMoveEffectiveness ( user , new PokemonMove ( move . id ) ) === 0 ) {
// If there is a type immunity, the attack will stop no matter what
hitTimes = 1 ;
} else {
const hitType = new Utils . IntegerHolder ( this . multiHitType ) ;
applyMoveAttrs ( ChangeMultiHitTypeAttr , user , target , move , hitType ) ;
hitTimes = this . getHitCount ( user , target ) ;
}
( args [ 0 ] as Utils . IntegerHolder ) . value = hitTimes ;
return true ;
}
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
return - 5 ;
}
/ * *
* Calculate the number of hits that an attack should have given this attribute ' s
* { @linkcode MultiHitType } .
*
* @param user { @linkcode Pokemon } using the attack
* @param target { @linkcode Pokemon } targeted by the attack
* @returns The number of hits this attack should deal
* /
getHitCount ( user : Pokemon , target : Pokemon ) : integer {
switch ( this . multiHitType ) {
2024-05-23 17:03:10 +02:00
case MultiHitType . _2_TO_5 :
2024-06-13 14:23:13 -04:00
{
const rand = user . randSeedInt ( 16 ) ;
const hitValue = new Utils . IntegerHolder ( rand ) ;
applyAbAttrs ( MaxMultiHitAbAttr , user , null , hitValue ) ;
if ( hitValue . value >= 10 ) {
return 2 ;
} else if ( hitValue . value >= 4 ) {
return 3 ;
} else if ( hitValue . value >= 2 ) {
return 4 ;
} else {
return 5 ;
2024-05-23 17:03:10 +02:00
}
2024-06-13 14:23:13 -04:00
}
2024-05-23 17:03:10 +02:00
case MultiHitType . _2 :
2024-06-13 14:23:13 -04:00
return 2 ;
2024-05-23 17:03:10 +02:00
break ;
case MultiHitType . _3 :
2024-06-13 14:23:13 -04:00
return 3 ;
2024-05-23 17:03:10 +02:00
break ;
2024-05-28 19:07:35 -04:00
case MultiHitType . _10 :
2024-06-13 14:23:13 -04:00
return 10 ;
2024-05-23 17:03:10 +02:00
break ;
case MultiHitType . BEAT_UP :
2024-05-25 07:31:04 -04:00
const party = user . isPlayer ( ) ? user . scene . getParty ( ) : user . scene . getEnemyParty ( ) ;
2024-05-23 17:03:10 +02:00
// No status means the ally pokemon can contribute to Beat Up
2024-06-13 14:23:13 -04:00
return party . reduce ( ( total , pokemon ) = > {
2024-05-23 17:03:10 +02:00
return total + ( pokemon . id === user . id ? 1 : pokemon?.status && pokemon . status . effect !== StatusEffect . NONE ? 0 : 1 ) ;
} , 0 ) ;
2023-04-10 16:17:25 -04:00
}
2023-05-18 11:11:06 -04:00
}
2023-04-03 23:38:31 -04:00
}
2024-05-04 18:50:12 -07:00
export class ChangeMultiHitTypeAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
//const hitType = args[0] as Utils.NumberHolder;
return false ;
}
}
export class WaterShurikenMultiHitTypeAttr extends ChangeMultiHitTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( user . species . speciesId === Species . GRENINJA && user . hasAbility ( Abilities . BATTLE_BOND ) && user . formIndex === 2 ) {
( args [ 0 ] as Utils . IntegerHolder ) . value = MultiHitType . _3 ;
2024-05-04 18:50:12 -07:00
return true ;
}
return false ;
}
}
2023-07-10 10:54:22 -04:00
export class StatusEffectAttr extends MoveEffectAttr {
2023-04-03 23:38:31 -04:00
public effect : StatusEffect ;
2023-04-16 18:40:32 -04:00
public cureTurn : integer ;
2023-10-27 22:18:54 -04:00
public overrideStatus : boolean ;
2023-04-03 23:38:31 -04:00
2023-10-27 22:18:54 -04:00
constructor ( effect : StatusEffect , selfTarget? : boolean , cureTurn? : integer , overrideStatus? : boolean ) {
2023-07-10 10:54:22 -04:00
super ( selfTarget , MoveEffectTrigger . HIT ) ;
2023-04-16 18:40:32 -04:00
2023-04-03 23:38:31 -04:00
this . effect = effect ;
2023-04-16 18:40:32 -04:00
this . cureTurn = cureTurn ;
2023-10-27 22:18:54 -04:00
this . overrideStatus = ! ! overrideStatus ;
2023-04-03 23:38:31 -04:00
}
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-01-02 21:31:59 -05:00
const statusCheck = move . chance < 0 || move . chance === 100 || user . randSeedInt ( 100 ) < move . chance ;
2023-04-11 19:08:03 -04:00
if ( statusCheck ) {
2023-04-16 18:40:32 -04:00
const pokemon = this . selfTarget ? user : target ;
2023-11-21 14:11:13 -05:00
if ( pokemon . status ) {
2024-05-23 17:03:10 +02:00
if ( this . overrideStatus ) {
2023-11-21 14:11:13 -05:00
pokemon . resetStatus ( ) ;
2024-05-23 17:03:10 +02:00
} else {
2023-11-21 14:11:13 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-11-21 14:11:13 -05:00
}
2024-05-25 05:51:36 -04:00
if ( ( ! pokemon . status || ( pokemon . status . effect === this . effect && move . chance < 0 ) )
&& pokemon . trySetStatus ( this . effect , true , user , this . cureTurn ) ) {
2024-06-07 16:57:57 -04:00
applyPostAttackAbAttrs ( ConfusionOnStatusEffectAbAttr , user , target , move , null , this . effect ) ;
2024-05-25 05:51:36 -04:00
return true ;
2024-05-23 17:03:10 +02:00
}
2023-04-11 19:08:03 -04:00
}
2023-04-15 01:32:16 -04:00
return false ;
2023-04-03 23:38:31 -04:00
}
2023-05-18 11:11:06 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
2024-05-14 14:00:37 -04:00
return ! ( this . selfTarget ? user : target ) . status && ( this . selfTarget ? user : target ) . canSetStatus ( this . effect , true , false , user ) ? Math . floor ( move . chance * - 0.1 ) : 0 ;
2023-05-18 11:11:06 -04:00
}
2023-04-03 23:38:31 -04:00
}
2024-04-30 23:30:10 -04:00
export class MultiStatusEffectAttr extends StatusEffectAttr {
public effects : StatusEffect [ ] ;
constructor ( effects : StatusEffect [ ] , selfTarget? : boolean , cureTurn? : integer , overrideStatus? : boolean ) {
super ( effects [ 0 ] , selfTarget , cureTurn , overrideStatus ) ;
this . effects = effects ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
this . effect = Utils . randSeedItem ( this . effects ) ;
const result = super . apply ( user , target , move , args ) ;
return result ;
}
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
2024-05-14 14:00:37 -04:00
return ! ( this . selfTarget ? user : target ) . status && ( this . selfTarget ? user : target ) . canSetStatus ( this . effect , true , false , user ) ? Math . floor ( move . chance * - 0.1 ) : 0 ;
2024-04-30 23:30:10 -04:00
}
}
2024-04-16 13:00:55 -04:00
export class PsychoShiftEffectAttr extends MoveEffectAttr {
constructor ( ) {
super ( false , MoveEffectTrigger . HIT ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const statusToApply : StatusEffect = user . status ? . effect ;
if ( target . status ) {
return false ;
}
2024-04-26 12:18:01 -04:00
if ( ! target . status || ( target . status . effect === statusToApply && move . chance < 0 ) ) {
2024-05-23 17:03:10 +02:00
const statusAfflictResult = target . trySetStatus ( statusToApply , true , user ) ;
2024-04-16 14:34:57 -04:00
if ( statusAfflictResult ) {
user . scene . queueMessage ( getPokemonMessage ( user , getStatusEffectHealText ( user . status . effect ) ) ) ;
user . resetStatus ( ) ;
user . updateInfo ( ) ;
}
return statusAfflictResult ;
2024-04-26 12:16:56 -04:00
}
2024-05-24 01:45:04 +02:00
2024-04-16 13:00:55 -04:00
return false ;
}
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
2024-05-14 14:00:37 -04:00
return ! ( this . selfTarget ? user : target ) . status && ( this . selfTarget ? user : target ) . canSetStatus ( user . status ? . effect , true , false , user ) ? Math . floor ( move . chance * - 0.1 ) : 0 ;
2024-04-16 13:00:55 -04:00
}
}
2024-06-15 22:26:54 -04:00
/ * *
* The following needs to be implemented for Thief
* "If the user faints due to the target's Ability (Rough Skin or Iron Barbs) or held Rocky Helmet, it cannot remove the target's held item."
* "If Knock Off causes a Pokémon with the Sticky Hold Ability to faint, it can now remove that Pokémon's held item."
* /
2024-03-04 21:51:28 -05:00
export class StealHeldItemChanceAttr extends MoveEffectAttr {
private chance : number ;
constructor ( chance : number ) {
2023-07-10 10:54:22 -04:00
super ( false , MoveEffectTrigger . HIT ) ;
2024-03-04 21:51:28 -05:00
this . chance = chance ;
2023-04-30 19:05:47 -04:00
}
2023-12-22 01:16:56 -05:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise < boolean > ( resolve = > {
2024-03-04 21:51:28 -05:00
const rand = Phaser . Math . RND . realInRange ( 0 , 1 ) ;
2024-05-23 17:03:10 +02:00
if ( rand >= this . chance ) {
2024-03-04 21:51:28 -05:00
return resolve ( false ) ;
2024-05-23 17:03:10 +02:00
}
2023-12-22 01:16:56 -05:00
const heldItems = this . getTargetHeldItems ( target ) . filter ( i = > i . getTransferrable ( false ) ) ;
if ( heldItems . length ) {
2024-04-10 14:31:29 -04:00
const poolType = target . isPlayer ( ) ? ModifierPoolType.PLAYER : target.hasTrainer ( ) ? ModifierPoolType.TRAINER : ModifierPoolType.WILD ;
const highestItemTier = heldItems . map ( m = > m . type . getOrInferTier ( poolType ) ) . reduce ( ( highestTier , tier ) = > Math . max ( tier , highestTier ) , 0 ) ;
const tierHeldItems = heldItems . filter ( m = > m . type . getOrInferTier ( poolType ) === highestItemTier ) ;
2024-03-04 21:51:28 -05:00
const stolenItem = tierHeldItems [ user . randSeedInt ( tierHeldItems . length ) ] ;
2024-05-30 23:58:10 +02:00
user . scene . tryTransferHeldItemModifier ( stolenItem , user , false ) . then ( success = > {
2024-05-23 17:03:10 +02:00
if ( success ) {
2023-12-22 01:16:56 -05:00
user . scene . queueMessage ( getPokemonMessage ( user , ` stole \ n ${ target . name } 's ${ stolenItem . type . name } ! ` ) ) ;
2024-05-23 17:03:10 +02:00
}
2023-12-22 01:16:56 -05:00
resolve ( success ) ;
} ) ;
return ;
}
2023-04-30 19:05:47 -04:00
2023-12-22 01:16:56 -05:00
resolve ( false ) ;
} ) ;
2023-04-30 19:05:47 -04:00
}
2023-05-18 11:11:06 -04:00
getTargetHeldItems ( target : Pokemon ) : PokemonHeldItemModifier [ ] {
return target . scene . findModifiers ( m = > m instanceof PokemonHeldItemModifier
&& ( m as PokemonHeldItemModifier ) . pokemonId === target . id , target . isPlayer ( ) ) as PokemonHeldItemModifier [ ] ;
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
const heldItems = this . getTargetHeldItems ( target ) ;
return heldItems . length ? 5 : 0 ;
}
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
const heldItems = this . getTargetHeldItems ( target ) ;
return heldItems . length ? - 5 : 0 ;
}
2023-04-30 19:05:47 -04:00
}
2024-06-15 22:26:54 -04:00
/ * *
* Removes a random held item ( or berry ) from target .
* Used for Incinerate and Knock Off .
* Not Implemented Cases : ( Same applies for Thief )
* "If the user faints due to the target's Ability (Rough Skin or Iron Barbs) or held Rocky Helmet, it cannot remove the target's held item."
* "If Knock Off causes a Pokémon with the Sticky Hold Ability to faint, it can now remove that Pokémon's held item."
* /
2024-03-11 18:18:49 +01:00
export class RemoveHeldItemAttr extends MoveEffectAttr {
2024-06-15 22:26:54 -04:00
/** Optional restriction for item pool to berries only i.e. Differentiating Incinerate and Knock Off */
private berriesOnly : boolean ;
constructor ( berriesOnly : boolean ) {
2024-03-11 18:18:49 +01:00
super ( false , MoveEffectTrigger . HIT ) ;
2024-06-15 22:26:54 -04:00
this . berriesOnly = berriesOnly ;
2024-03-11 18:18:49 +01:00
}
2024-06-15 22:26:54 -04:00
/ * *
*
* @param user { @linkcode Pokemon } that used the move
* @param target Target { @linkcode Pokemon } that the moves applies to
* @param move { @linkcode Move } that is used
* @param args N / A
* @returns { boolean } True if an item was removed
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( ! this . berriesOnly && target . isPlayer ( ) ) { // "Wild Pokemon cannot knock off Player Pokemon's held items" (See Bulbapedia)
return false ;
}
const cancelled = new Utils . BooleanHolder ( false ) ;
applyAbAttrs ( BlockItemTheftAbAttr , target , cancelled ) ; // Check for abilities that block item theft
if ( cancelled . value === true ) {
return false ;
}
// Considers entire transferrable item pool by default (Knock Off). Otherwise berries only if specified (Incinerate).
let heldItems = this . getTargetHeldItems ( target ) . filter ( i = > i . getTransferrable ( false ) ) ;
if ( this . berriesOnly ) {
heldItems = heldItems . filter ( m = > m instanceof BerryModifier && m . pokemonId === target . id , target . isPlayer ( ) ) ;
}
if ( heldItems . length ) {
const removedItem = heldItems [ user . randSeedInt ( heldItems . length ) ] ;
// Decrease item amount and update icon
! -- removedItem . stackCount ;
target . scene . updateModifiers ( target . isPlayer ( ) ) ;
if ( this . berriesOnly ) {
user . scene . queueMessage ( getPokemonMessage ( user , ` incinerated \ n ${ target . name } 's ${ removedItem . type . name } ! ` ) ) ;
} else {
user . scene . queueMessage ( getPokemonMessage ( user , ` knocked off \ n ${ target . name } 's ${ removedItem . type . name } ! ` ) ) ;
2024-03-11 18:18:49 +01:00
}
2024-06-15 22:26:54 -04:00
}
2024-03-11 18:18:49 +01:00
2024-06-15 22:26:54 -04:00
return true ;
2024-03-11 18:18:49 +01:00
}
getTargetHeldItems ( target : Pokemon ) : PokemonHeldItemModifier [ ] {
return target . scene . findModifiers ( m = > m instanceof PokemonHeldItemModifier
&& ( m as PokemonHeldItemModifier ) . pokemonId === target . id , target . isPlayer ( ) ) as PokemonHeldItemModifier [ ] ;
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
const heldItems = this . getTargetHeldItems ( target ) ;
return heldItems . length ? 5 : 0 ;
}
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
const heldItems = this . getTargetHeldItems ( target ) ;
return heldItems . length ? - 5 : 0 ;
}
}
2024-05-19 18:47:30 -04:00
/ * *
2024-06-13 18:44:23 -04:00
* Attribute that causes targets of the move to eat a berry . If chosenBerry is not overridden , a random berry will be picked from the target ' s inventory .
2024-05-19 18:47:30 -04:00
* /
export class EatBerryAttr extends MoveEffectAttr {
protected chosenBerry : BerryModifier ;
constructor ( ) {
super ( true , MoveEffectTrigger . HIT ) ;
this . chosenBerry = undefined ;
}
2024-05-23 17:03:10 +02:00
/ * *
2024-05-19 18:47:30 -04:00
* Causes the target to eat a berry .
* @param user { @linkcode Pokemon } Pokemon that used the move
* @param target { @linkcode Pokemon } Pokemon that will eat a berry
* @param move { @linkcode Move } The move being used
* @param args Unused
* @returns { boolean } true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-05-19 18:47:30 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-19 18:47:30 -04:00
2024-05-24 02:19:20 +02:00
if ( this . chosenBerry === undefined ) { // if no berry has been provided, pick a random berry from their inventory
2024-05-19 18:47:30 -04:00
const heldBerries = this . getTargetHeldBerries ( target ) ;
2024-05-24 02:19:20 +02:00
if ( heldBerries . length <= 0 ) {
2024-05-19 18:47:30 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-19 18:47:30 -04:00
this . chosenBerry = heldBerries [ user . randSeedInt ( heldBerries . length ) ] ;
}
getBerryEffectFunc ( this . chosenBerry . berryType ) ( target ) ; // target eats the berry
const preserve = new Utils . BooleanHolder ( false ) ;
target . scene . applyModifiers ( PreserveBerryModifier , target . isPlayer ( ) , target , preserve ) ;
2024-05-24 02:19:20 +02:00
if ( ! preserve . value ) { // remove the eaten berry if not preserved
2024-05-23 17:03:10 +02:00
if ( ! -- this . chosenBerry . stackCount ) {
2024-05-19 18:47:30 -04:00
target . scene . removeModifier ( this . chosenBerry , ! target . isPlayer ( ) ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-19 18:47:30 -04:00
target . scene . updateModifiers ( target . isPlayer ( ) ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-28 13:19:03 -04:00
2024-05-19 18:47:30 -04:00
this . chosenBerry = undefined ;
2024-05-24 01:45:04 +02:00
2024-05-28 13:19:03 -04:00
applyAbAttrs ( HealFromBerryUseAbAttr , target , new Utils . BooleanHolder ( false ) ) ;
2024-05-19 18:47:30 -04:00
return true ;
}
getTargetHeldBerries ( target : Pokemon ) : BerryModifier [ ] {
return target . scene . findModifiers ( m = > m instanceof BerryModifier
&& ( m as BerryModifier ) . pokemonId === target . id , target . isPlayer ( ) ) as BerryModifier [ ] ;
}
}
/ * *
* Attribute used for moves that steal a random berry from the target . The user then eats the stolen berry .
* Used for Pluck & Bug Bite .
* /
export class StealEatBerryAttr extends EatBerryAttr {
constructor ( ) {
super ( ) ;
}
2024-05-23 17:03:10 +02:00
/ * *
2024-05-19 18:47:30 -04:00
* User steals a random berry from the target and then eats it .
* @param { Pokemon } user Pokemon that used the move and will eat the stolen berry
* @param { Pokemon } target Pokemon that will have its berry stolen
* @param { Move } move Move being used
* @param { any [ ] } args Unused
* @returns { boolean } true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const cancelled = new Utils . BooleanHolder ( false ) ;
applyAbAttrs ( BlockItemTheftAbAttr , target , cancelled ) ; // check for abilities that block item theft
2024-05-24 02:19:20 +02:00
if ( cancelled . value === true ) {
2024-05-19 18:47:30 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2024-05-19 18:47:30 -04:00
const heldBerries = this . getTargetHeldBerries ( target ) . filter ( i = > i . getTransferrable ( false ) ) ;
if ( heldBerries . length ) { // if the target has berries, pick a random berry and steal it
this . chosenBerry = heldBerries [ user . randSeedInt ( heldBerries . length ) ] ;
2024-05-23 17:03:10 +02:00
if ( this . chosenBerry . stackCount === 1 ) { // remove modifier if its the last berry
2024-05-19 18:47:30 -04:00
target . scene . removeModifier ( this . chosenBerry , ! target . isPlayer ( ) ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-19 18:47:30 -04:00
target . scene . updateModifiers ( target . isPlayer ( ) ) ;
user . scene . queueMessage ( getPokemonMessage ( user , ` stole and ate \ n ${ target . name } 's ${ this . chosenBerry . type . name } ! ` ) ) ;
return super . apply ( user , user , move , args ) ;
}
return false ;
}
}
2024-05-30 16:04:50 -04:00
/ * *
* Move attribute that signals that the move should cure a status effect
* @extends MoveEffectAttr
* @see { @linkcode apply ( ) }
* /
2023-04-19 16:52:14 -04:00
export class HealStatusEffectAttr extends MoveEffectAttr {
2024-05-30 16:04:50 -04:00
/** List of Status Effects to cure */
2023-04-19 16:52:14 -04:00
private effects : StatusEffect [ ] ;
2024-05-30 16:04:50 -04:00
/ * *
* @param selfTarget - Whether this move targets the user
* @param . . . effects - List of status effects to cure
* /
2023-04-19 16:52:14 -04:00
constructor ( selfTarget : boolean , . . . effects : StatusEffect [ ] ) {
super ( selfTarget ) ;
this . effects = effects ;
}
2024-05-30 16:04:50 -04:00
/ * *
* @param user { @linkcode Pokemon } source of the move
* @param target { @linkcode Pokemon } target of the move
* @param move the { @linkcode Move } being used
* @returns true if the status is cured
* /
2023-04-19 16:52:14 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-19 16:52:14 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-19 16:52:14 -04:00
const pokemon = this . selfTarget ? user : target ;
2024-03-30 18:46:33 -04:00
if ( pokemon . status && this . effects . includes ( pokemon . status . effect ) ) {
2024-02-28 15:15:27 -05:00
pokemon . scene . queueMessage ( getPokemonMessage ( pokemon , getStatusEffectHealText ( pokemon . status . effect ) ) ) ;
2023-04-19 16:52:14 -04:00
pokemon . resetStatus ( ) ;
pokemon . updateInfo ( ) ;
2024-05-24 01:45:04 +02:00
2023-04-27 20:12:25 -04:00
return true ;
2023-04-19 16:52:14 -04:00
}
return false ;
}
2023-05-18 11:11:06 -04:00
2024-03-30 18:46:33 -04:00
isOfEffect ( effect : StatusEffect ) : boolean {
return this . effects . includes ( effect ) ;
}
2023-05-18 11:11:06 -04:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return user . status ? 10 : 0 ;
}
2023-04-19 16:52:14 -04:00
}
2023-04-16 18:40:32 -04:00
export class BypassSleepAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( user . status ? . effect === StatusEffect . SLEEP ) {
2023-04-24 14:30:21 -04:00
user . addTag ( BattlerTagType . BYPASS_SLEEP , 1 , move . id , user . id ) ;
2023-04-16 18:40:32 -04:00
return true ;
}
return false ;
}
}
2024-05-13 11:06:15 -07:00
/ * *
* Attribute used for moves that bypass the burn damage reduction of physical moves , currently only facade
* Called during damage calculation
2024-05-16 07:07:23 -05:00
* @extends MoveAttr
* @see { @linkcode apply }
2024-05-13 11:06:15 -07:00
* /
export class BypassBurnDamageReductionAttr extends MoveAttr {
2024-05-16 07:07:23 -05:00
/ * * P r e v e n t s t h e m o v e ' s d a m a g e f r o m b e i n g r e d u c e d b y b u r n
* @param user N / A
* @param target N / A
* @param move { @linkcode Move } with this attribute
* @param args [ 0 ] { @linkcode Utils . BooleanHolder } for burnDamageReductionCancelled
* @returns true if the function succeeds
* /
2024-05-13 11:06:15 -07:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . BooleanHolder ) . value = true ;
2024-05-24 01:45:04 +02:00
return true ;
2024-05-13 11:06:15 -07:00
}
}
2023-04-17 00:46:50 -04:00
export class WeatherChangeAttr extends MoveEffectAttr {
private weatherType : WeatherType ;
2024-05-24 01:45:04 +02:00
2023-04-17 00:46:50 -04:00
constructor ( weatherType : WeatherType ) {
super ( ) ;
this . weatherType = weatherType ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
return user . scene . arena . trySetWeather ( this . weatherType , true ) ;
}
2023-04-24 14:30:21 -04:00
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-12-10 17:57:12 -05:00
return ( user , target , move ) = > ! user . scene . arena . weather || ( user . scene . arena . weather . weatherType !== this . weatherType && ! user . scene . arena . weather . isImmutable ( ) ) ;
2023-04-24 14:30:21 -04:00
}
2023-04-17 00:46:50 -04:00
}
export class ClearWeatherAttr extends MoveEffectAttr {
private weatherType : WeatherType ;
2024-05-24 01:45:04 +02:00
2023-04-17 00:46:50 -04:00
constructor ( weatherType : WeatherType ) {
super ( ) ;
this . weatherType = weatherType ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( user . scene . arena . weather ? . weatherType === this . weatherType ) {
2023-04-17 00:46:50 -04:00
return user . scene . arena . trySetWeather ( WeatherType . NONE , true ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-17 00:46:50 -04:00
return false ;
}
}
2024-03-09 21:57:33 -05:00
export class TerrainChangeAttr extends MoveEffectAttr {
private terrainType : TerrainType ;
2024-05-24 01:45:04 +02:00
2024-03-09 21:57:33 -05:00
constructor ( terrainType : TerrainType ) {
super ( ) ;
this . terrainType = terrainType ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
return user . scene . arena . trySetTerrain ( this . terrainType , true , true ) ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > ! user . scene . arena . terrain || ( user . scene . arena . terrain . terrainType !== this . terrainType ) ;
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
// TODO: Expand on this
return user . scene . arena . terrain ? 0 : 6 ;
}
}
export class ClearTerrainAttr extends MoveEffectAttr {
2024-03-09 22:05:49 -05:00
constructor ( ) {
2024-03-09 21:57:33 -05:00
super ( ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-03-09 22:05:49 -05:00
return user . scene . arena . trySetTerrain ( TerrainType . NONE , true , true ) ;
2024-03-09 21:57:33 -05:00
}
}
2023-11-07 22:23:42 -05:00
export class OneHitKOAttr extends MoveAttr {
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( target . isBossImmune ( ) ) {
2023-10-27 22:25:48 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-11-07 22:23:42 -05:00
( args [ 0 ] as Utils . BooleanHolder ) . value = true ;
2024-05-24 01:45:04 +02:00
2023-04-03 23:38:31 -04:00
return true ;
}
2023-11-30 16:37:16 -05:00
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2024-03-09 23:49:00 +01:00
return ( user , target , move ) = > {
const cancelled = new Utils . BooleanHolder ( false ) ;
applyAbAttrs ( BlockOneHitKOAbAttr , target , cancelled ) ;
2024-04-08 12:52:37 -04:00
return ! cancelled . value && user . level >= target . level ;
2024-05-23 17:03:10 +02:00
} ;
2023-11-30 16:37:16 -05:00
}
2023-04-03 23:38:31 -04:00
}
2023-12-04 00:09:38 -05:00
export class OverrideMoveEffectAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean | Promise < boolean > {
//const overridden = args[0] as Utils.BooleanHolder;
//const virtual = arg[1] as boolean;
return true ;
}
}
2023-04-10 23:15:06 -04:00
2023-04-13 12:16:36 -04:00
export class ChargeAttr extends OverrideMoveEffectAttr {
public chargeAnim : ChargeAnim ;
private chargeText : string ;
2023-04-21 19:30:04 -04:00
private tagType : BattlerTagType ;
2024-02-27 14:21:17 -05:00
private chargeEffect : boolean ;
2024-02-20 13:15:53 -05:00
public sameTurn : boolean ;
public followUpPriority : integer ;
2023-04-13 12:16:36 -04:00
2024-02-20 13:15:53 -05:00
constructor ( chargeAnim : ChargeAnim , chargeText : string , tagType? : BattlerTagType , chargeEffect : boolean = false , sameTurn : boolean = false , followUpPriority? : integer ) {
2023-04-10 23:15:06 -04:00
super ( ) ;
2023-04-13 12:16:36 -04:00
this . chargeAnim = chargeAnim ;
this . chargeText = chargeText ;
this . tagType = tagType ;
2024-02-20 13:15:53 -05:00
this . chargeEffect = chargeEffect ;
this . sameTurn = sameTurn ;
this . followUpPriority = followUpPriority ;
2023-04-10 23:15:06 -04:00
}
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
2023-04-13 12:16:36 -04:00
return new Promise ( resolve = > {
2024-02-27 14:21:17 -05:00
const lastMove = user . getLastXMoves ( ) . find ( ( ) = > true ) ;
2024-04-04 08:51:46 -04:00
if ( ! lastMove || lastMove . move !== move . id || ( lastMove . result !== MoveResult . OTHER && ( this . sameTurn || lastMove . turn !== user . scene . currentBattle . turn ) ) ) {
2023-04-13 12:16:36 -04:00
( args [ 0 ] as Utils . BooleanHolder ) . value = true ;
2023-05-01 14:41:44 -04:00
new MoveChargeAnim ( this . chargeAnim , move . id , user ) . play ( user . scene , ( ) = > {
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( user , ` ${ this . chargeText . replace ( "{TARGET}" , target . name ) } ` ) ) ;
if ( this . tagType ) {
2023-04-24 14:30:21 -04:00
user . addTag ( this . tagType , 1 , move . id , user . id ) ;
2024-05-23 17:03:10 +02:00
}
if ( this . chargeEffect ) {
2023-04-16 00:29:55 -04:00
applyMoveAttrs ( MoveEffectAttr , user , target , move ) ;
2024-05-23 17:03:10 +02:00
}
2023-05-18 11:11:06 -04:00
user . pushMoveHistory ( { move : move.id , targets : [ target . getBattlerIndex ( ) ] , result : MoveResult.OTHER } ) ;
user . getMoveQueue ( ) . push ( { move : move.id , targets : [ target . getBattlerIndex ( ) ] , ignorePP : true } ) ;
2024-05-23 17:03:10 +02:00
if ( this . sameTurn ) {
2024-02-20 13:15:53 -05:00
user . scene . pushMovePhase ( new MovePhase ( user . scene , user , [ target . getBattlerIndex ( ) ] , user . moveset . find ( m = > m . moveId === move . id ) , true ) , this . followUpPriority ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-03 00:18:05 +02:00
user . addTag ( BattlerTagType . CHARGING , 1 , move . id , user . id ) ;
2023-04-13 12:16:36 -04:00
resolve ( true ) ;
} ) ;
2024-05-03 00:18:05 +02:00
} else {
user . lapseTag ( BattlerTagType . CHARGING ) ;
2023-04-15 01:32:16 -04:00
resolve ( false ) ;
2024-05-03 00:18:05 +02:00
}
2023-04-13 12:16:36 -04:00
} ) ;
2023-04-03 23:38:31 -04:00
}
2024-02-27 14:21:17 -05:00
usedChargeEffect ( user : Pokemon , target : Pokemon , move : Move ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! this . chargeEffect ) {
2024-02-27 14:21:17 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-02-27 20:15:47 -05:00
// Account for move history being populated when this function is called
const lastMoves = user . getLastXMoves ( 2 ) ;
return lastMoves . length === 2 && lastMoves [ 1 ] . move === move . id && lastMoves [ 1 ] . result === MoveResult . OTHER ;
2024-02-27 14:21:17 -05:00
}
2023-04-03 23:38:31 -04:00
}
2024-03-09 21:57:33 -05:00
export class SunlightChargeAttr extends ChargeAttr {
constructor ( chargeAnim : ChargeAnim , chargeText : string ) {
super ( chargeAnim , chargeText ) ;
2023-04-17 00:46:50 -04:00
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise ( resolve = > {
const weatherType = user . scene . arena . weather ? . weatherType ;
2024-05-23 17:03:10 +02:00
if ( ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) && ( weatherType === WeatherType . SUNNY || weatherType === WeatherType . HARSH_SUN ) ) {
2023-04-17 00:46:50 -04:00
resolve ( false ) ;
2024-05-23 17:03:10 +02:00
} else {
2023-04-17 00:46:50 -04:00
super . apply ( user , target , move , args ) . then ( result = > resolve ( result ) ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-17 00:46:50 -04:00
} ) ;
}
}
2023-12-14 03:03:00 -06:00
export class ElectroShotChargeAttr extends ChargeAttr {
2024-04-19 14:28:44 +01:00
private statIncreaseApplied : boolean ;
2023-12-14 03:03:00 -06:00
constructor ( ) {
2024-05-23 17:03:10 +02:00
super ( ChargeAnim . ELECTRO_SHOT_CHARGING , "absorbed electricity!" , null , true ) ;
2024-04-19 14:28:44 +01:00
// Add a flag because ChargeAttr skills use themselves twice instead of once over one-to-two turns
this . statIncreaseApplied = false ;
2023-12-14 03:03:00 -06:00
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise ( resolve = > {
const weatherType = user . scene . arena . weather ? . weatherType ;
2024-04-19 14:28:44 +01:00
if ( ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) && ( weatherType === WeatherType . RAIN || weatherType === WeatherType . HEAVY_RAIN ) ) {
// Apply the SPATK increase every call when used in the rain
const statChangeAttr = new StatChangeAttr ( BattleStat . SPATK , 1 , true ) ;
statChangeAttr . apply ( user , target , move , args ) ;
// After the SPATK is raised, execute the move resolution e.g. deal damage
2023-12-14 03:03:00 -06:00
resolve ( false ) ;
2024-04-19 14:28:44 +01:00
} else {
if ( ! this . statIncreaseApplied ) {
// Apply the SPATK increase only if it hasn't been applied before e.g. on the first turn charge up animation
const statChangeAttr = new StatChangeAttr ( BattleStat . SPATK , 1 , true ) ;
statChangeAttr . apply ( user , target , move , args ) ;
// Set the flag to true so that on the following turn it doesn't raise SPATK a second time
this . statIncreaseApplied = true ;
}
super . apply ( user , target , move , args ) . then ( result = > {
if ( ! result ) {
// On the second turn, reset the statIncreaseApplied flag without applying the SPATK increase
this . statIncreaseApplied = false ;
}
resolve ( result ) ;
} ) ;
}
2023-12-14 03:03:00 -06:00
} ) ;
}
}
2023-12-04 00:09:38 -05:00
export class DelayedAttackAttr extends OverrideMoveEffectAttr {
public tagType : ArenaTagType ;
public chargeAnim : ChargeAnim ;
private chargeText : string ;
constructor ( tagType : ArenaTagType , chargeAnim : ChargeAnim , chargeText : string ) {
super ( ) ;
this . tagType = tagType ;
this . chargeAnim = chargeAnim ;
this . chargeText = chargeText ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise ( resolve = > {
if ( args . length < 2 || ! args [ 1 ] ) {
new MoveChargeAnim ( this . chargeAnim , move . id , user ) . play ( user . scene , ( ) = > {
( args [ 0 ] as Utils . BooleanHolder ) . value = true ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( user , ` ${ this . chargeText . replace ( "{TARGET}" , target . name ) } ` ) ) ;
2023-12-04 00:09:38 -05:00
user . pushMoveHistory ( { move : move.id , targets : [ target . getBattlerIndex ( ) ] , result : MoveResult.OTHER } ) ;
2024-06-07 10:27:11 -04:00
user . scene . arena . addTag ( this . tagType , 3 , move . id , user . id , ArenaTagSide . BOTH , false , target . getBattlerIndex ( ) ) ;
2023-12-04 00:09:38 -05:00
resolve ( true ) ;
} ) ;
2024-05-23 17:03:10 +02:00
} else {
2023-12-04 00:09:38 -05:00
user . scene . ui . showText ( getPokemonMessage ( user . scene . getPokemonById ( target . id ) , ` took \ nthe ${ move . name } attack! ` ) , null , ( ) = > resolve ( true ) ) ;
2024-05-23 17:03:10 +02:00
}
2023-12-04 00:09:38 -05:00
} ) ;
}
}
2023-07-10 10:54:22 -04:00
export class StatChangeAttr extends MoveEffectAttr {
2023-04-10 23:15:06 -04:00
public stats : BattleStat [ ] ;
2023-04-03 23:38:31 -04:00
public levels : integer ;
2024-01-07 23:17:24 -05:00
private condition : MoveConditionFunc ;
2024-01-15 23:29:22 -05:00
private showMessage : boolean ;
2023-04-03 23:38:31 -04:00
2024-05-05 08:50:46 -07:00
constructor ( stats : BattleStat | BattleStat [ ] , levels : integer , selfTarget? : boolean , condition? : MoveConditionFunc , showMessage : boolean = true , firstHitOnly : boolean = false , moveEffectTrigger : MoveEffectTrigger = MoveEffectTrigger . HIT ) {
super ( selfTarget , moveEffectTrigger , firstHitOnly ) ;
2024-05-23 17:03:10 +02:00
this . stats = typeof ( stats ) === "number"
2023-04-10 23:15:06 -04:00
? [ stats as BattleStat ]
: stats as BattleStat [ ] ;
this . levels = levels ;
2023-12-10 17:57:12 -05:00
this . condition = condition || null ;
2024-01-15 23:29:22 -05:00
this . showMessage = showMessage ;
2023-04-03 23:38:31 -04:00
}
2024-01-15 23:29:22 -05:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean | Promise < boolean > {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) || ( this . condition && ! this . condition ( user , target , move ) ) ) {
2023-04-15 01:32:16 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-15 01:32:16 -04:00
2024-01-02 21:31:59 -05:00
if ( move . chance < 0 || move . chance === 100 || user . randSeedInt ( 100 ) < move . chance ) {
2023-04-17 00:46:50 -04:00
const levels = this . getLevels ( user ) ;
2024-01-15 23:29:22 -05:00
user . scene . unshiftPhase ( new StatChangePhase ( user . scene , ( this . selfTarget ? user : target ) . getBattlerIndex ( ) , this . selfTarget , this . stats , levels , this . showMessage ) ) ;
2023-04-17 00:46:50 -04:00
return true ;
}
return false ;
}
getLevels ( _user : Pokemon ) : integer {
return this . levels ;
}
2023-05-18 11:11:06 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2024-04-10 12:49:23 -04:00
let ret = 0 ;
2024-05-23 17:03:10 +02:00
const moveLevels = this . getLevels ( user ) ;
for ( const stat of this . stats ) {
2024-04-10 12:49:23 -04:00
let levels = moveLevels ;
2024-05-23 17:03:10 +02:00
if ( levels > 0 ) {
2024-04-10 12:49:23 -04:00
levels = Math . min ( target . summonData . battleStats [ stat ] + levels , 6 ) - target . summonData . battleStats [ stat ] ;
2024-05-23 17:03:10 +02:00
} else {
2024-04-10 12:49:23 -04:00
levels = Math . max ( target . summonData . battleStats [ stat ] + levels , - 6 ) - target . summonData . battleStats [ stat ] ;
2024-05-23 17:03:10 +02:00
}
2024-04-10 12:49:23 -04:00
let noEffect = false ;
switch ( stat ) {
2024-05-23 17:03:10 +02:00
case BattleStat . ATK :
if ( this . selfTarget ) {
noEffect = ! user . getMoveset ( ) . find ( m = > m instanceof AttackMove && m . category === MoveCategory . PHYSICAL ) ;
}
break ;
case BattleStat . DEF :
if ( ! this . selfTarget ) {
noEffect = ! user . getMoveset ( ) . find ( m = > m instanceof AttackMove && m . category === MoveCategory . PHYSICAL ) ;
}
break ;
case BattleStat . SPATK :
if ( this . selfTarget ) {
noEffect = ! user . getMoveset ( ) . find ( m = > m instanceof AttackMove && m . category === MoveCategory . SPECIAL ) ;
}
break ;
case BattleStat . SPDEF :
if ( ! this . selfTarget ) {
noEffect = ! user . getMoveset ( ) . find ( m = > m instanceof AttackMove && m . category === MoveCategory . SPECIAL ) ;
}
break ;
2024-04-10 12:49:23 -04:00
}
2024-05-23 17:03:10 +02:00
if ( noEffect ) {
2024-04-10 12:49:23 -04:00
continue ;
2024-05-23 17:03:10 +02:00
}
2024-04-10 12:49:23 -04:00
ret += ( levels * 4 ) + ( levels > 0 ? - 2 : 2 ) ;
}
return ret ;
2023-05-18 11:11:06 -04:00
}
2023-04-17 00:46:50 -04:00
}
2024-05-08 05:44:55 +01:00
export class PostVictoryStatChangeAttr extends MoveAttr {
private stats : BattleStat [ ] ;
private levels : integer ;
private condition : MoveConditionFunc ;
private showMessage : boolean ;
constructor ( stats : BattleStat | BattleStat [ ] , levels : integer , selfTarget? : boolean , condition? : MoveConditionFunc , showMessage : boolean = true , firstHitOnly : boolean = false ) {
super ( ) ;
2024-05-23 17:03:10 +02:00
this . stats = typeof ( stats ) === "number"
2024-05-08 05:44:55 +01:00
? [ stats as BattleStat ]
: stats as BattleStat [ ] ;
this . levels = levels ;
this . condition = condition || null ;
this . showMessage = showMessage ;
}
applyPostVictory ( user : Pokemon , target : Pokemon , move : Move ) : void {
2024-05-24 02:19:20 +02:00
if ( this . condition && ! this . condition ( user , target , move ) ) {
2024-05-29 10:54:33 -05:00
return ;
2024-05-23 17:03:10 +02:00
}
2024-05-08 05:44:55 +01:00
const statChangeAttr = new StatChangeAttr ( this . stats , this . levels , this . showMessage ) ;
2024-05-29 10:54:33 -05:00
statChangeAttr . apply ( user , target , move , undefined ) ;
2024-05-08 05:44:55 +01:00
}
}
2024-05-03 22:30:23 -04:00
export class AcupressureStatChangeAttr extends MoveEffectAttr {
constructor ( ) {
super ( ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean | Promise < boolean > {
let randStats = [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD , BattleStat . ACC , BattleStat . EVA ] ;
randStats = randStats . filter ( s = > target . summonData . battleStats [ s ] < 6 ) ;
if ( randStats . length > 0 ) {
2024-05-23 17:03:10 +02:00
const boostStat = [ randStats [ Utils . randInt ( randStats . length ) ] ] ;
2024-05-03 22:30:23 -04:00
user . scene . unshiftPhase ( new StatChangePhase ( user . scene , target . getBattlerIndex ( ) , this . selfTarget , boostStat , 2 ) ) ;
return true ;
}
return false ;
2024-05-08 05:44:55 +01:00
}
2024-05-03 22:30:23 -04:00
}
2023-04-17 00:46:50 -04:00
export class GrowthStatChangeAttr extends StatChangeAttr {
constructor ( ) {
super ( [ BattleStat . ATK , BattleStat . SPATK ] , 1 , true ) ;
}
getLevels ( user : Pokemon ) : number {
2023-04-27 14:30:03 -04:00
if ( ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) ) {
const weatherType = user . scene . arena . weather ? . weatherType ;
2024-05-23 17:03:10 +02:00
if ( weatherType === WeatherType . SUNNY || weatherType === WeatherType . HARSH_SUN ) {
2023-04-27 14:30:03 -04:00
return this . levels + 1 ;
2024-05-23 17:03:10 +02:00
}
2023-04-27 14:30:03 -04:00
}
2023-04-17 00:46:50 -04:00
return this . levels ;
}
}
2024-01-15 23:29:22 -05:00
export class HalfHpStatMaxAttr extends StatChangeAttr {
constructor ( stat : BattleStat ) {
super ( stat , 12 , true , null , false ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise < boolean > ( resolve = > {
2024-04-10 12:49:23 -04:00
const damage = user . damageAndUpdate ( Math . floor ( user . getMaxHp ( ) / 2 ) , HitResult . OTHER , false , true ) ;
2024-05-23 17:03:10 +02:00
if ( damage ) {
2024-03-01 09:35:36 -05:00
user . scene . damageNumberHandler . add ( user , damage ) ;
2024-05-23 17:03:10 +02:00
}
2024-01-15 23:29:22 -05:00
user . updateInfo ( ) . then ( ( ) = > {
const ret = super . apply ( user , target , move , args ) ;
2024-04-18 12:16:49 -05:00
user . scene . queueMessage ( getPokemonMessage ( user , ` cut its own HP \ nand maximized its ${ getBattleStatName ( this . stats [ 0 ] ) } ! ` ) ) ;
2024-01-15 23:29:22 -05:00
resolve ( ret ) ;
} ) ;
} ) ;
}
getCondition ( ) : MoveConditionFunc {
2024-02-29 15:47:29 -05:00
return ( user , target , move ) = > user . getHpRatio ( ) > 0.5 && user . summonData . battleStats [ this . stats [ 0 ] ] < 6 ;
2024-01-15 23:29:22 -05:00
}
2024-04-10 12:49:23 -04:00
// TODO: Add benefit score that considers HP cut
2024-01-15 23:29:22 -05:00
}
2024-02-08 16:50:17 -06:00
export class CutHpStatBoostAttr extends StatChangeAttr {
2024-04-10 17:31:39 -04:00
private cutRatio : integer ;
constructor ( stat : BattleStat | BattleStat [ ] , levels : integer , cutRatio : integer ) {
super ( stat , levels , true , null , true ) ;
this . cutRatio = cutRatio ;
2024-02-08 16:50:17 -06:00
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise < boolean > ( resolve = > {
2024-04-10 17:31:39 -04:00
const damage = user . damageAndUpdate ( Math . floor ( user . getMaxHp ( ) / this . cutRatio ) , HitResult . OTHER , false , true ) ;
2024-05-23 17:03:10 +02:00
if ( damage ) {
2024-03-01 09:35:36 -05:00
user . scene . damageNumberHandler . add ( user , damage ) ;
2024-05-23 17:03:10 +02:00
}
2024-02-08 16:50:17 -06:00
user . updateInfo ( ) . then ( ( ) = > {
const ret = super . apply ( user , target , move , args ) ;
resolve ( ret ) ;
} ) ;
} ) ;
}
getCondition ( ) : MoveConditionFunc {
2024-04-10 17:31:39 -04:00
return ( user , target , move ) = > user . getHpRatio ( ) > 1 / this . cutRatio ;
2024-02-08 16:50:17 -06:00
}
}
2024-04-18 16:47:12 +10:00
export class CopyStatsAttr extends MoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-18 16:47:12 +10:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-18 16:47:12 +10:00
2024-05-23 17:03:10 +02:00
for ( let s = 0 ; s < target . summonData . battleStats . length ; s ++ ) {
2024-04-18 16:47:12 +10:00
user . summonData . battleStats [ s ] = target . summonData . battleStats [ s ] ;
2024-05-23 17:03:10 +02:00
}
if ( target . getTag ( BattlerTagType . CRIT_BOOST ) ) {
2024-04-18 16:47:12 +10:00
user . addTag ( BattlerTagType . CRIT_BOOST , 0 , move . id ) ;
2024-05-23 17:03:10 +02:00
} else {
2024-04-18 16:47:12 +10:00
user . removeTag ( BattlerTagType . CRIT_BOOST ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-03 12:06:43 -07:00
target . updateInfo ( ) ;
2024-04-30 23:23:32 -04:00
user . updateInfo ( ) ;
2024-05-23 17:03:10 +02:00
target . scene . queueMessage ( getPokemonMessage ( user , " copied\n" ) + getPokemonMessage ( target , "'s stat changes!" ) ) ;
2024-04-18 16:47:12 +10:00
return true ;
}
}
2024-03-11 18:44:40 -04:00
export class InvertStatsAttr extends MoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-03-11 18:44:40 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-03-11 18:44:40 -04:00
2024-05-23 17:03:10 +02:00
for ( let s = 0 ; s < target . summonData . battleStats . length ; s ++ ) {
2024-03-11 18:44:40 -04:00
target . summonData . battleStats [ s ] *= - 1 ;
2024-05-23 17:03:10 +02:00
}
2024-05-03 12:06:43 -07:00
target . updateInfo ( ) ;
2024-04-30 23:23:32 -04:00
user . updateInfo ( ) ;
2024-05-23 17:03:10 +02:00
target . scene . queueMessage ( getPokemonMessage ( target , "'s stat changes\nwere all reversed!" ) ) ;
2024-03-11 18:44:40 -04:00
return true ;
}
}
2024-04-18 16:28:22 +10:00
export class ResetStatsAttr extends MoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-18 16:28:22 +10:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-18 16:28:22 +10:00
2024-05-23 17:03:10 +02:00
for ( let s = 0 ; s < target . summonData . battleStats . length ; s ++ ) {
2024-04-18 16:28:22 +10:00
target . summonData . battleStats [ s ] = 0 ;
2024-05-23 17:03:10 +02:00
}
2024-05-03 12:06:43 -07:00
target . updateInfo ( ) ;
2024-04-30 23:23:32 -04:00
user . updateInfo ( ) ;
2024-05-23 17:03:10 +02:00
target . scene . queueMessage ( getPokemonMessage ( target , "'s stat changes\nwere eliminated!" ) ) ;
2024-04-18 16:28:22 +10:00
return true ;
}
}
2024-05-11 15:42:57 +01:00
/ * *
* Attribute used for moves which swap the user and the target ' s stat changes .
* /
2024-05-23 17:03:10 +02:00
export class SwapStatsAttr extends MoveEffectAttr {
/ * *
2024-05-11 15:42:57 +01:00
* Swaps the user and the target ' s stat changes .
* @param user Pokemon that used the move
* @param target The target of the move
* @param move Move with this attribute
* @param args N / A
* @returns true if the function succeeds
* /
2024-05-23 17:03:10 +02:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( ! super . apply ( user , target , move , args ) ) {
return false ;
} //Exits if the move can't apply
let priorBoost : integer ; //For storing a stat boost
for ( let s = 0 ; s < target . summonData . battleStats . length ; s ++ ) {
priorBoost = user . summonData . battleStats [ s ] ; //Store user stat boost
user . summonData . battleStats [ s ] = target . summonData . battleStats [ s ] ; //Applies target boost to self
target . summonData . battleStats [ s ] = priorBoost ; //Applies stored boost to target
2024-05-11 15:42:57 +01:00
}
2024-05-23 17:03:10 +02:00
target . updateInfo ( ) ;
user . updateInfo ( ) ;
target . scene . queueMessage ( getPokemonMessage ( user , " switched stat changes with the target!" ) ) ;
return true ;
}
2024-05-11 15:42:57 +01:00
}
2023-10-21 20:40:46 -05:00
export class HpSplitAttr extends MoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise ( resolve = > {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-10-21 20:40:46 -05:00
return resolve ( false ) ;
2024-05-23 17:03:10 +02:00
}
2023-10-21 20:40:46 -05:00
const infoUpdates = [ ] ;
2024-05-24 01:45:04 +02:00
2023-10-21 20:40:46 -05:00
const hpValue = Math . floor ( ( target . hp + user . hp ) / 2 ) ;
2024-03-01 09:35:36 -05:00
if ( user . hp < hpValue ) {
const healing = user . heal ( hpValue - user . hp ) ;
2024-05-23 17:03:10 +02:00
if ( healing ) {
2024-03-01 09:35:36 -05:00
user . scene . damageNumberHandler . add ( user , healing , HitResult . HEAL ) ;
2024-05-23 17:03:10 +02:00
}
2024-03-01 09:35:36 -05:00
} else if ( user . hp > hpValue ) {
const damage = user . damage ( user . hp - hpValue , true ) ;
2024-05-23 17:03:10 +02:00
if ( damage ) {
2024-03-01 09:35:36 -05:00
user . scene . damageNumberHandler . add ( user , damage ) ;
2024-05-23 17:03:10 +02:00
}
2024-03-01 09:35:36 -05:00
}
2023-10-21 20:40:46 -05:00
infoUpdates . push ( user . updateInfo ( ) ) ;
2024-03-01 09:35:36 -05:00
if ( target . hp < hpValue ) {
const healing = target . heal ( hpValue - target . hp ) ;
2024-05-23 17:03:10 +02:00
if ( healing ) {
2024-03-01 09:35:36 -05:00
user . scene . damageNumberHandler . add ( user , healing , HitResult . HEAL ) ;
2024-05-23 17:03:10 +02:00
}
2024-03-01 09:35:36 -05:00
} else if ( target . hp > hpValue ) {
const damage = target . damage ( target . hp - hpValue , true ) ;
2024-05-23 17:03:10 +02:00
if ( damage ) {
2024-03-01 09:35:36 -05:00
target . scene . damageNumberHandler . add ( target , damage ) ;
2024-05-23 17:03:10 +02:00
}
2024-03-01 09:35:36 -05:00
}
2023-10-21 20:40:46 -05:00
infoUpdates . push ( target . updateInfo ( ) ) ;
return Promise . all ( infoUpdates ) . then ( ( ) = > resolve ( true ) ) ;
} ) ;
}
}
2023-04-17 00:46:50 -04:00
export class VariablePowerAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
//const power = args[0] as Utils.NumberHolder;
return false ;
}
}
2024-05-19 20:17:58 +02:00
export class LessPPMorePowerAttr extends VariablePowerAttr {
/ * *
* Power up moves when less PP user has
* @param user { @linkcode Pokemon } using this move
* @param target { @linkcode Pokemon } target of this move
* @param move { @linkcode Move } being used
* @param args [ 0 ] { @linkcode Utils . NumberHolder } of power
* @returns true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const ppMax = move . pp ;
2024-05-23 17:03:10 +02:00
const ppUsed = user . moveset . find ( ( m ) = > m . moveId === move . id ) . ppUsed ;
2024-05-24 01:45:04 +02:00
2024-05-19 20:17:58 +02:00
let ppRemains = ppMax - ppUsed ;
/** Reduce to 0 to avoid negative numbers if user has 1PP before attack and target has Ability.PRESSURE */
2024-05-24 02:19:20 +02:00
if ( ppRemains < 0 ) {
2024-05-23 17:03:10 +02:00
ppRemains = 0 ;
}
2024-05-24 01:45:04 +02:00
2024-05-19 20:17:58 +02:00
const power = args [ 0 ] as Utils . NumberHolder ;
switch ( ppRemains ) {
2024-05-23 17:03:10 +02:00
case 0 :
power . value = 200 ;
break ;
case 1 :
power . value = 80 ;
break ;
case 2 :
power . value = 60 ;
break ;
case 3 :
power . value = 50 ;
break ;
default :
power . value = 40 ;
break ;
2024-05-19 20:17:58 +02:00
}
return true ;
}
}
2023-04-19 16:52:14 -04:00
export class MovePowerMultiplierAttr extends VariablePowerAttr {
private powerMultiplierFunc : ( user : Pokemon , target : Pokemon , move : Move ) = > number ;
constructor ( powerMultiplier : ( user : Pokemon , target : Pokemon , move : Move ) = > number ) {
super ( ) ;
this . powerMultiplierFunc = powerMultiplier ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
power . value *= this . powerMultiplierFunc ( user , target , move ) ;
return true ;
}
}
2024-05-19 07:22:37 -07:00
/ * *
* Helper function to calculate the the base power of an ally ' s hit when using Beat Up .
* @param user The Pokemon that used Beat Up .
* @param allyIndex The party position of the ally contributing to Beat Up .
* @returns The base power of the Beat Up hit .
* /
const beatUpFunc = ( user : Pokemon , allyIndex : number ) : number = > {
2024-05-25 07:31:04 -04:00
const party = user . isPlayer ( ) ? user . scene . getParty ( ) : user . scene . getEnemyParty ( ) ;
2024-05-19 07:22:37 -07:00
for ( let i = allyIndex ; i < party . length ; i ++ ) {
const pokemon = party [ i ] ;
// The user contributes to Beat Up regardless of status condition.
// Allies can contribute only if they do not have a non-volatile status condition.
if ( pokemon . id !== user . id && pokemon ? . status && pokemon . status . effect !== StatusEffect . NONE ) {
continue ;
}
return ( pokemon . species . getBaseStat ( Stat . ATK ) / 10 ) + 5 ;
}
2024-05-23 17:03:10 +02:00
} ;
2024-05-19 07:22:37 -07:00
export class BeatUpAttr extends VariablePowerAttr {
/ * *
* Gets the next party member to contribute to a Beat Up hit , and calculates the base power for it .
* @param user Pokemon that used the move
* @param _target N / A
* @param _move Move with this attribute
* @param args N / A
* @returns true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
const allyIndex = user . turnData . hitCount - user . turnData . hitsLeft ;
power . value = beatUpFunc ( user , allyIndex ) ;
return true ;
}
}
2024-03-30 22:40:00 -05:00
const doublePowerChanceMessageFunc = ( user : Pokemon , target : Pokemon , move : Move ) = > {
let message : string = null ;
user . scene . executeWithSeedOffset ( ( ) = > {
2024-05-23 17:03:10 +02:00
const rand = Utils . randSeedInt ( 100 ) ;
if ( rand < move . chance ) {
message = getPokemonMessage ( user , " is going all out for this attack!" ) ;
}
2024-03-30 22:40:00 -05:00
} , user . scene . currentBattle . turn << 6 , user . scene . waveSeed ) ;
return message ;
} ;
export class DoublePowerChanceAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
let rand : integer ;
user . scene . executeWithSeedOffset ( ( ) = > rand = Utils . randSeedInt ( 100 ) , user . scene . currentBattle . turn << 6 , user . scene . waveSeed ) ;
if ( rand < move . chance ) {
const power = args [ 0 ] as Utils . NumberHolder ;
power . value *= 2 ;
return true ;
}
return false ;
}
}
2023-04-22 10:56:17 -04:00
export abstract class ConsecutiveUsePowerMultiplierAttr extends MovePowerMultiplierAttr {
2023-05-08 10:03:57 -04:00
constructor ( limit : integer , resetOnFail : boolean , resetOnLimit? : boolean , . . . comboMoves : Moves [ ] ) {
2023-04-22 10:56:17 -04:00
super ( ( user : Pokemon , target : Pokemon , move : Move ) : number = > {
2024-03-30 22:06:16 -04:00
const moveHistory = user . getMoveHistory ( ) . reverse ( ) . slice ( 1 ) ;
2023-04-22 10:56:17 -04:00
let count = 0 ;
let turnMove : TurnMove ;
2024-03-30 22:06:16 -04:00
while ( ( ( turnMove = moveHistory . shift ( ) ) ? . move === move . id || ( comboMoves . length && comboMoves . includes ( turnMove ? . move ) ) ) && ( ! resetOnFail || turnMove . result === MoveResult . SUCCESS ) ) {
2024-05-23 17:03:10 +02:00
if ( count < ( limit - 1 ) ) {
2023-04-22 10:56:17 -04:00
count ++ ;
2024-05-23 17:03:10 +02:00
} else if ( resetOnLimit ) {
2023-04-22 10:56:17 -04:00
count = 0 ;
2024-05-23 17:03:10 +02:00
} else {
2023-04-22 10:56:17 -04:00
break ;
2024-05-23 17:03:10 +02:00
}
2023-04-22 10:56:17 -04:00
}
2024-03-30 22:06:16 -04:00
return this . getMultiplier ( count ) ;
2023-04-22 10:56:17 -04:00
} ) ;
}
abstract getMultiplier ( count : integer ) : number ;
}
export class ConsecutiveUseDoublePowerAttr extends ConsecutiveUsePowerMultiplierAttr {
getMultiplier ( count : number ) : number {
return Math . pow ( 2 , count ) ;
}
}
export class ConsecutiveUseMultiBasePowerAttr extends ConsecutiveUsePowerMultiplierAttr {
getMultiplier ( count : number ) : number {
return ( count + 1 ) ;
}
}
2023-04-21 01:17:43 -04:00
export class WeightPowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
2023-12-10 22:29:13 -05:00
const targetWeight = target . getWeight ( ) ;
2023-04-21 01:17:43 -04:00
const weightThresholds = [ 10 , 25 , 50 , 100 , 200 ] ;
let w = 0 ;
while ( targetWeight >= weightThresholds [ w ] ) {
2024-05-23 17:03:10 +02:00
if ( ++ w === weightThresholds . length ) {
2023-04-21 01:17:43 -04:00
break ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 01:17:43 -04:00
}
power . value = ( w + 1 ) * 20 ;
return true ;
}
}
2024-05-17 07:42:43 +02:00
/ * *
* Attribute used for Electro Ball move .
* @extends VariablePowerAttr
* @see { @linkcode apply }
* * /
export class ElectroBallPowerAttr extends VariablePowerAttr {
/ * *
* Move that deals more damage the faster { @linkcode BattleStat . SPD }
* the user is compared to the target .
* @param user Pokemon that used the move
* @param target The target of the move
* @param move Move with this attribute
* @param args N / A
* @returns true if the function succeeds
* /
2024-03-09 22:58:05 +01:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
2024-05-17 07:42:43 +02:00
const statRatio = target . getBattleStat ( Stat . SPD ) / user . getBattleStat ( Stat . SPD ) ;
2024-03-09 22:58:05 +01:00
const statThresholds = [ 0.25 , 1 / 3 , 0.5 , 1 , - 1 ] ;
2024-05-17 07:42:43 +02:00
const statThresholdPowers = [ 150 , 120 , 80 , 60 , 40 ] ;
2024-03-09 22:58:05 +01:00
let w = 0 ;
while ( w < statThresholds . length - 1 && statRatio > statThresholds [ w ] ) {
2024-05-23 17:03:10 +02:00
if ( ++ w === statThresholds . length ) {
2024-03-09 22:58:05 +01:00
break ;
2024-05-23 17:03:10 +02:00
}
2024-03-09 22:58:05 +01:00
}
power . value = statThresholdPowers [ w ] ;
2024-05-17 07:42:43 +02:00
return true ;
}
}
/ * *
* Attribute used for Gyro Ball move .
* @extends VariablePowerAttr
* @see { @linkcode apply }
* * /
export class GyroBallPowerAttr extends VariablePowerAttr {
/ * *
* Move that deals more damage the slower { @linkcode BattleStat . SPD }
* the user is compared to the target .
* @param user Pokemon that used the move
* @param target The target of the move
* @param move Move with this attribute
* @param args N / A
* @returns true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
const userSpeed = user . getBattleStat ( Stat . SPD ) ;
if ( userSpeed < 1 ) {
// Gen 6+ always have 1 base power
power . value = 1 ;
return true ;
}
2024-03-09 22:58:05 +01:00
2024-05-17 07:42:43 +02:00
power . value = Math . floor ( Math . min ( 150 , 25 * target . getBattleStat ( Stat . SPD ) / userSpeed + 1 ) ) ;
2024-03-09 22:58:05 +01:00
return true ;
}
}
2023-04-22 10:56:17 -04:00
export class LowHpPowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
const hpRatio = user . getHpRatio ( ) ;
switch ( true ) {
2024-05-23 17:03:10 +02:00
case ( hpRatio < 0.0417 ) :
power . value = 200 ;
break ;
case ( hpRatio < 0.1042 ) :
power . value = 150 ;
break ;
case ( hpRatio < 0.2083 ) :
power . value = 100 ;
break ;
case ( hpRatio < 0.3542 ) :
power . value = 80 ;
break ;
case ( hpRatio < 0.6875 ) :
power . value = 40 ;
break ;
default :
power . value = 20 ;
break ;
2023-04-22 10:56:17 -04:00
}
return true ;
}
}
2024-04-04 18:29:28 +03:00
export class CompareWeightPowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
const userWeight = user . getWeight ( ) ;
const targetWeight = target . getWeight ( ) ;
2024-05-23 17:03:10 +02:00
if ( ! userWeight || userWeight === 0 ) {
2024-04-04 18:29:28 +03:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2024-04-04 18:29:28 +03:00
const relativeWeight = ( targetWeight / userWeight ) * 100 ;
switch ( true ) {
2024-05-23 17:03:10 +02:00
case ( relativeWeight < 20.01 ) :
power . value = 120 ;
break ;
case ( relativeWeight < 25.01 ) :
power . value = 100 ;
break ;
case ( relativeWeight < 33.35 ) :
power . value = 80 ;
break ;
case ( relativeWeight < 50.01 ) :
power . value = 60 ;
break ;
default :
power . value = 40 ;
break ;
2024-04-04 18:29:28 +03:00
}
return true ;
}
}
2023-04-21 19:30:04 -04:00
export class HpPowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . NumberHolder ) . value = Math . max ( Math . floor ( 150 * user . getHpRatio ( ) ) , 1 ) ;
return true ;
}
}
2023-05-08 18:48:35 -04:00
export class OpponentHighHpPowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . NumberHolder ) . value = Math . max ( Math . floor ( 120 * target . getHpRatio ( ) ) , 1 ) ;
return true ;
}
}
2024-03-18 22:05:21 -04:00
export class FirstAttackDoublePowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
console . log ( target . getLastXMoves ( 1 ) , target . scene . currentBattle . turn ) ;
if ( ! target . getLastXMoves ( 1 ) . find ( m = > m . turn === target . scene . currentBattle . turn ) ) {
( args [ 0 ] as Utils . NumberHolder ) . value *= 2 ;
return true ;
}
return false ;
}
}
2024-04-19 09:33:35 -04:00
2023-04-24 14:30:21 -04:00
export class TurnDamagedDoublePowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-03-18 22:05:21 -04:00
if ( user . turnData . attacksReceived . find ( r = > r . damage && r . sourceId === target . id ) ) {
( args [ 0 ] as Utils . NumberHolder ) . value *= 2 ;
2023-04-24 14:30:21 -04:00
return true ;
}
return false ;
}
}
2024-03-18 22:05:21 -04:00
const magnitudeMessageFunc = ( user : Pokemon , target : Pokemon , move : Move ) = > {
let message : string ;
user . scene . executeWithSeedOffset ( ( ) = > {
const magnitudeThresholds = [ 5 , 15 , 35 , 65 , 75 , 95 ] ;
const rand = Utils . randSeedInt ( 100 ) ;
let m = 0 ;
for ( ; m < magnitudeThresholds . length ; m ++ ) {
2024-05-23 17:03:10 +02:00
if ( rand < magnitudeThresholds [ m ] ) {
2024-03-18 22:05:21 -04:00
break ;
2024-05-23 17:03:10 +02:00
}
2024-03-18 22:05:21 -04:00
}
message = ` Magnitude ${ m + 4 } ! ` ;
2024-03-30 22:40:00 -05:00
} , user . scene . currentBattle . turn << 6 , user . scene . waveSeed ) ;
2024-03-18 22:05:21 -04:00
return message ;
} ;
export class MagnitudePowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
const magnitudeThresholds = [ 5 , 15 , 35 , 65 , 75 , 95 ] ;
const magnitudePowers = [ 10 , 30 , 50 , 70 , 90 , 100 , 110 , 150 ] ;
let rand : integer ;
2024-05-24 01:45:04 +02:00
2024-03-30 22:40:00 -05:00
user . scene . executeWithSeedOffset ( ( ) = > rand = Utils . randSeedInt ( 100 ) , user . scene . currentBattle . turn << 6 , user . scene . waveSeed ) ;
2024-03-18 22:05:21 -04:00
let m = 0 ;
for ( ; m < magnitudeThresholds . length ; m ++ ) {
2024-05-23 17:03:10 +02:00
if ( rand < magnitudeThresholds [ m ] ) {
2024-03-18 22:05:21 -04:00
break ;
2024-05-23 17:03:10 +02:00
}
2024-03-18 22:05:21 -04:00
}
power . value = magnitudePowers [ m ] ;
return true ;
}
}
2024-03-09 21:57:33 -05:00
export class AntiSunlightPowerDecreaseAttr extends VariablePowerAttr {
2023-04-17 00:46:50 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-04-27 14:30:03 -04:00
if ( ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) ) {
const power = args [ 0 ] as Utils . NumberHolder ;
const weatherType = user . scene . arena . weather ? . weatherType || WeatherType . NONE ;
switch ( weatherType ) {
2024-05-23 17:03:10 +02:00
case WeatherType . RAIN :
case WeatherType . SANDSTORM :
case WeatherType . HAIL :
case WeatherType . SNOW :
case WeatherType . HEAVY_RAIN :
power . value *= 0.5 ;
return true ;
2023-04-27 14:30:03 -04:00
}
2023-04-17 00:46:50 -04:00
}
return false ;
}
}
2023-12-21 23:00:45 -05:00
export class FriendshipPowerAttr extends VariablePowerAttr {
2023-10-26 22:03:24 -07:00
private invert : boolean ;
constructor ( invert? : boolean ) {
super ( ) ;
this . invert = ! ! invert ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const power = args [ 0 ] as Utils . NumberHolder ;
2024-06-16 18:40:47 -04:00
const friendshipPower = Math . floor ( Math . min ( user instanceof PlayerPokemon ? user.friendship : user.species.baseFriendship , 255 ) / 2.5 ) ;
power . value = Math . max ( ! this . invert ? friendshipPower : 102 - friendshipPower , 1 ) ;
2023-10-26 22:03:24 -07:00
return true ;
}
}
2023-11-28 21:35:52 -05:00
export class HitCountPowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . NumberHolder ) . value += Math . min ( user . battleData . hitCount , 6 ) * 50 ;
return true ;
}
}
2024-05-30 17:01:42 -04:00
/ * *
* Turning a once was ( StatChangeCountPowerAttr ) statement and making it available to call for any attribute .
* @param { Pokemon } pokemon The pokemon that is being used to calculate the count of positive stats
* @returns { number } Returns the amount of positive stats
* /
const countPositiveStats = ( pokemon : Pokemon ) : number = > {
return pokemon . summonData . battleStats . reduce ( ( total , stat ) = > ( stat && stat > 0 ) ? total + stat : total , 0 ) ;
} ;
/ * *
* Attribute that increases power based on the amount of positive stat increases .
* /
2024-04-05 01:33:42 +02:00
export class StatChangeCountPowerAttr extends VariablePowerAttr {
2024-05-30 17:01:42 -04:00
/ * *
* @param { Pokemon } user The pokemon that is being used to calculate the amount of positive stats
* @param { Pokemon } target N / A
* @param { Move } move N / A
* @param { any [ ] } args The argument for VariablePowerAttr , accumulates and sets the amount of power multiplied by stats
* @returns { boolean } Returns true if attribute is applied
* /
2024-04-05 01:33:42 +02:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-30 17:01:42 -04:00
const positiveStats : number = countPositiveStats ( user ) ;
2024-04-05 01:33:42 +02:00
( args [ 0 ] as Utils . NumberHolder ) . value += positiveStats * 20 ;
2024-05-30 17:01:42 -04:00
return true ;
}
}
/ * *
* Punishment normally has a base power of 60 ,
* but gains 20 power for every increased stat stage the target has ,
* up to a maximum of 200 base power in total .
* /
export class PunishmentPowerAttr extends VariablePowerAttr {
private PUNISHMENT_MIN_BASE_POWER = 60 ;
private PUNISHMENT_MAX_BASE_POWER = 200 ;
2024-04-05 01:33:42 +02:00
2024-05-30 17:01:42 -04:00
/ * *
* @param { Pokemon } user N / A
* @param { Pokemon } target The pokemon that the move is being used against , as well as calculating the stats for the min / max base power
* @param { Move } move N / A
* @param { any [ ] } args The value that is being changed due to VariablePowerAttr
* @returns Returns true if attribute is applied
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const positiveStats : number = countPositiveStats ( target ) ;
( args [ 0 ] as Utils . NumberHolder ) . value = Math . min (
this . PUNISHMENT_MAX_BASE_POWER ,
this . PUNISHMENT_MIN_BASE_POWER + positiveStats * 20
) ;
2024-04-05 01:33:42 +02:00
return true ;
}
}
2024-04-16 00:41:15 -04:00
export class PresentPowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const powerSeed = Utils . randSeedInt ( 100 ) ;
if ( powerSeed <= 40 ) {
( args [ 0 ] as Utils . NumberHolder ) . value = 40 ;
2024-05-23 17:03:10 +02:00
} else if ( 40 < powerSeed && powerSeed <= 70 ) {
2024-04-16 00:41:15 -04:00
( args [ 0 ] as Utils . NumberHolder ) . value = 80 ;
2024-05-23 17:03:10 +02:00
} else if ( 70 < powerSeed && powerSeed <= 80 ) {
2024-04-16 00:41:15 -04:00
( args [ 0 ] as Utils . NumberHolder ) . value = 120 ;
2024-05-23 17:03:10 +02:00
} else if ( 80 < powerSeed && powerSeed <= 100 ) {
2024-04-16 00:41:15 -04:00
target . scene . unshiftPhase ( new PokemonHealPhase ( target . scene , target . getBattlerIndex ( ) ,
2024-05-23 17:03:10 +02:00
Math . max ( Math . floor ( target . getMaxHp ( ) / 4 ) , 1 ) , getPokemonMessage ( target , " regained\nhealth!" ) , true ) ) ;
2024-04-16 00:41:15 -04:00
}
return true ;
}
}
2024-05-04 18:50:12 -07:00
export class WaterShurikenPowerAttr extends VariablePowerAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( user . species . speciesId === Species . GRENINJA && user . hasAbility ( Abilities . BATTLE_BOND ) && user . formIndex === 2 ) {
( args [ 0 ] as Utils . IntegerHolder ) . value = 20 ;
2024-05-04 18:50:12 -07:00
return true ;
}
return false ;
}
}
2024-05-28 19:07:35 -04:00
/ * *
* Attribute used for multi - hit moves that increase power in increments of the
* move ' s base power for each hit , namely Triple Kick and Triple Axel .
* @extends VariablePowerAttr
* @see { @linkcode apply }
* /
export class MultiHitPowerIncrementAttr extends VariablePowerAttr {
/** The max number of base power increments allowed for this move */
private maxHits : integer ;
constructor ( maxHits : integer ) {
super ( ) ;
this . maxHits = maxHits ;
}
/ * *
* Increases power of move in increments of the base power for the amount of times
* the move hit . In the case that the move is extended , it will circle back to the
* original base power of the move after incrementing past the maximum amount of
* hits .
* @param user { @linkcode Pokemon } that used the move
* @param target { @linkcode Pokemon } that the move was used on
* @param move { @linkcode Move } with this attribute
* @param args [ 0 ] { @linkcode Utils . NumberHolder } for final calculated power of move
* @returns true if attribute application succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const hitsTotal = user . turnData . hitCount - Math . max ( user . turnData . hitsLeft , 0 ) ;
const power = args [ 0 ] as Utils . NumberHolder ;
power . value = move . power * ( 1 + hitsTotal % this . maxHits ) ;
return true ;
}
}
2024-03-11 21:45:32 +01:00
export class VariableAtkAttr extends MoveAttr {
constructor ( ) {
super ( ) ;
}
2024-03-11 18:18:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-03-11 21:45:32 +01:00
//const atk = args[0] as Utils.IntegerHolder;
return false ;
}
}
2024-04-02 16:16:35 +03:00
export class TargetAtkUserAtkAttr extends VariableAtkAttr {
2024-05-24 02:19:20 +02:00
constructor ( ) {
2024-04-02 16:16:35 +03:00
super ( ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . IntegerHolder ) . value = target . getBattleStat ( Stat . ATK , target ) ;
return true ;
}
}
2024-03-11 21:45:32 +01:00
export class DefAtkAttr extends VariableAtkAttr {
constructor ( ) {
super ( ) ;
}
2024-03-11 18:18:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-03-11 21:45:32 +01:00
( args [ 0 ] as Utils . IntegerHolder ) . value = user . getBattleStat ( Stat . DEF , target ) ;
return true ;
}
}
2024-03-11 18:18:55 -04:00
export class VariableDefAttr extends MoveAttr {
constructor ( ) {
super ( ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
//const def = args[0] as Utils.IntegerHolder;
return false ;
}
}
export class DefDefAttr extends VariableDefAttr {
constructor ( ) {
super ( ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
( args [ 0 ] as Utils . IntegerHolder ) . value = target . getBattleStat ( Stat . DEF , user ) ;
return true ;
}
}
2023-04-17 00:46:50 -04:00
export class VariableAccuracyAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
//const accuracy = args[0] as Utils.NumberHolder;
return false ;
}
}
export class ThunderAccuracyAttr extends VariableAccuracyAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-04-27 14:30:03 -04:00
if ( ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) ) {
const accuracy = args [ 0 ] as Utils . NumberHolder ;
const weatherType = user . scene . arena . weather ? . weatherType || WeatherType . NONE ;
switch ( weatherType ) {
2024-05-23 17:03:10 +02:00
case WeatherType . SUNNY :
case WeatherType . SANDSTORM :
case WeatherType . HARSH_SUN :
accuracy . value = 50 ;
return true ;
case WeatherType . RAIN :
case WeatherType . HEAVY_RAIN :
accuracy . value = - 1 ;
return true ;
2023-04-27 14:30:03 -04:00
}
2023-04-17 00:46:50 -04:00
}
return false ;
}
}
2024-05-15 06:36:34 -06:00
/ * *
* Attribute used for moves which never miss
2024-05-16 07:07:23 -05:00
* against Pokemon with the { @linkcode BattlerTagType . MINIMIZED }
* @extends VariableAccuracyAttr
* @see { @linkcode apply }
2024-05-15 06:36:34 -06:00
* /
2024-05-24 01:45:04 +02:00
export class MinimizeAccuracyAttr extends VariableAccuracyAttr {
2024-05-16 07:07:23 -05:00
/ * *
* @see { @linkcode apply }
* @param user N / A
* @param target { @linkcode Pokemon } target of the move
* @param move N / A
* @param args [ 0 ] Accuracy of the move to be modified
2024-05-24 01:45:04 +02:00
* @returns true if the function succeeds
2024-05-16 07:07:23 -05:00
* /
2024-05-15 06:36:34 -06:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-24 02:19:20 +02:00
if ( target . getTag ( BattlerTagType . MINIMIZED ) ) {
2024-05-23 17:03:10 +02:00
const accuracy = args [ 0 ] as Utils . NumberHolder ;
2024-05-15 06:36:34 -06:00
accuracy . value = - 1 ;
return true ;
}
return false ;
}
}
2024-04-09 18:44:13 +03:00
export class ToxicAccuracyAttr extends VariableAccuracyAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( user . isOfType ( Type . POISON ) ) {
const accuracy = args [ 0 ] as Utils . NumberHolder ;
accuracy . value = - 1 ;
return true ;
}
2024-04-09 18:44:13 +03:00
return false ;
}
}
2023-04-17 00:46:50 -04:00
export class BlizzardAccuracyAttr extends VariableAccuracyAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-04-27 14:30:03 -04:00
if ( ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) ) {
const accuracy = args [ 0 ] as Utils . NumberHolder ;
const weatherType = user . scene . arena . weather ? . weatherType || WeatherType . NONE ;
2024-04-15 22:35:35 +02:00
if ( weatherType === WeatherType . HAIL || weatherType === WeatherType . SNOW ) {
2023-04-27 14:30:03 -04:00
accuracy . value = - 1 ;
return true ;
}
2023-04-15 01:32:16 -04:00
}
return false ;
2023-04-03 23:38:31 -04:00
}
}
2024-04-11 07:49:35 +10:00
export class VariableMoveCategoryAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
return false ;
}
}
export class PhotonGeyserCategoryAttr extends VariableMoveCategoryAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const category = ( args [ 0 ] as Utils . IntegerHolder ) ;
if ( user . getBattleStat ( Stat . ATK , target , move ) > user . getBattleStat ( Stat . SPATK , target , move ) ) {
category . value = MoveCategory . PHYSICAL ;
return true ;
}
return false ;
}
}
export class TeraBlastCategoryAttr extends VariableMoveCategoryAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const category = ( args [ 0 ] as Utils . IntegerHolder ) ;
if ( user . isTerastallized ( ) && user . getBattleStat ( Stat . ATK , target , move ) > user . getBattleStat ( Stat . SPATK , target , move ) ) {
category . value = MoveCategory . PHYSICAL ;
return true ;
}
return false ;
}
}
2024-06-03 22:26:15 +02:00
/ * *
* Change the move category to status when used on the ally
* @extends VariableMoveCategoryAttr
* @see { @linkcode apply }
* /
export class StatusCategoryOnAllyAttr extends VariableMoveCategoryAttr {
/ * *
* @param user { @linkcode Pokemon } using the move
* @param target { @linkcode Pokemon } target of the move
* @param move { @linkcode Move } with this attribute
* @param args [ 0 ] { @linkcode Utils . IntegerHolder } The category of the move
* @returns true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const category = ( args [ 0 ] as Utils . IntegerHolder ) ;
if ( user . getAlly ( ) === target ) {
category . value = MoveCategory . STATUS ;
return true ;
}
return false ;
}
}
2024-04-11 07:49:35 +10:00
export class ShellSideArmCategoryAttr extends VariableMoveCategoryAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const category = ( args [ 0 ] as Utils . IntegerHolder ) ;
const atkRatio = user . getBattleStat ( Stat . ATK , target , move ) / target . getBattleStat ( Stat . DEF , user , move ) ;
2024-04-11 10:45:33 +10:00
const specialRatio = user . getBattleStat ( Stat . SPATK , target , move ) / target . getBattleStat ( Stat . SPDEF , user , move ) ;
2024-04-11 07:49:35 +10:00
// Shell Side Arm is much more complicated than it looks, this is a partial implementation to try to achieve something similar to the games
2024-04-11 10:45:33 +10:00
if ( atkRatio > specialRatio ) {
2024-04-11 07:49:35 +10:00
category . value = MoveCategory . PHYSICAL ;
return true ;
2024-04-11 10:45:33 +10:00
} else if ( atkRatio === specialRatio && user . randSeedInt ( 2 ) === 0 ) {
2024-04-11 07:49:35 +10:00
category . value = MoveCategory . PHYSICAL ;
return true ;
}
return false ;
}
}
2024-04-09 21:02:41 +03:00
export class VariableMoveTypeAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
return false ;
}
}
2024-06-10 08:58:34 -05:00
export class FormChangeItemTypeAttr extends VariableMoveTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( [ user . species . speciesId , user . fusionSpecies ? . speciesId ] . includes ( Species . ARCEUS ) || [ user . species . speciesId , user . fusionSpecies ? . speciesId ] . includes ( Species . SILVALLY ) ) {
const form = user . species . speciesId === Species . ARCEUS || user . species . speciesId === Species . SILVALLY ? user.formIndex : user.fusionSpecies.formIndex ;
move . type = Type [ Type [ form ] ] ;
return true ;
}
return false ;
}
}
2024-05-04 19:45:07 -05:00
export class TechnoBlastTypeAttr extends VariableMoveTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( [ user . species . speciesId , user . fusionSpecies ? . speciesId ] . includes ( Species . GENESECT ) ) {
const form = user . species . speciesId === Species . GENESECT ? user.formIndex : user.fusionSpecies.formIndex ;
switch ( form ) {
2024-05-23 17:03:10 +02:00
case 1 : // Shock Drive
2024-06-07 16:57:57 -04:00
move . type = Type . ELECTRIC ;
2024-05-23 17:03:10 +02:00
break ;
case 2 : // Burn Drive
2024-06-07 16:57:57 -04:00
move . type = Type . FIRE ;
2024-05-23 17:03:10 +02:00
break ;
case 3 : // Chill Drive
2024-06-07 16:57:57 -04:00
move . type = Type . ICE ;
2024-05-23 17:03:10 +02:00
break ;
case 4 : // Douse Drive
2024-06-07 16:57:57 -04:00
move . type = Type . WATER ;
2024-05-23 17:03:10 +02:00
break ;
default :
2024-06-07 16:57:57 -04:00
move . type = Type . NORMAL ;
2024-05-23 17:03:10 +02:00
break ;
2024-05-04 19:45:07 -05:00
}
return true ;
}
return false ;
}
}
2024-04-09 21:02:41 +03:00
export class AuraWheelTypeAttr extends VariableMoveTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( [ user . species . speciesId , user . fusionSpecies ? . speciesId ] . includes ( Species . MORPEKO ) ) {
const form = user . species . speciesId === Species . MORPEKO ? user.formIndex : user.fusionSpecies.formIndex ;
switch ( form ) {
2024-05-23 17:03:10 +02:00
case 1 : // Hangry Mode
2024-06-07 16:57:57 -04:00
move . type = Type . DARK ;
2024-05-23 17:03:10 +02:00
break ;
default : // Full Belly Mode
2024-06-07 16:57:57 -04:00
move . type = Type . ELECTRIC ;
2024-05-23 17:03:10 +02:00
break ;
2024-04-09 21:02:41 +03:00
}
return true ;
}
return false ;
}
}
export class RagingBullTypeAttr extends VariableMoveTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( [ user . species . speciesId , user . fusionSpecies ? . speciesId ] . includes ( Species . PALDEA_TAUROS ) ) {
const form = user . species . speciesId === Species . PALDEA_TAUROS ? user.formIndex : user.fusionSpecies.formIndex ;
switch ( form ) {
2024-05-23 17:03:10 +02:00
case 1 : // Blaze breed
2024-06-07 16:57:57 -04:00
move . type = Type . FIRE ;
2024-05-23 17:03:10 +02:00
break ;
case 2 : // Aqua breed
2024-06-07 16:57:57 -04:00
move . type = Type . WATER ;
2024-05-23 17:03:10 +02:00
break ;
default :
2024-06-07 16:57:57 -04:00
move . type = Type . FIGHTING ;
2024-05-23 17:03:10 +02:00
break ;
2024-04-09 21:02:41 +03:00
}
return true ;
}
return false ;
}
}
2024-04-14 21:41:12 -05:00
export class IvyCudgelTypeAttr extends VariableMoveTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( [ user . species . speciesId , user . fusionSpecies ? . speciesId ] . includes ( Species . OGERPON ) ) {
const form = user . species . speciesId === Species . OGERPON ? user.formIndex : user.fusionSpecies.formIndex ;
switch ( form ) {
2024-05-23 17:03:10 +02:00
case 1 : // Wellspring Mask
2024-06-07 16:57:57 -04:00
move . type = Type . WATER ;
2024-05-23 17:03:10 +02:00
break ;
case 2 : // Hearthflame Mask
2024-06-07 16:57:57 -04:00
move . type = Type . FIRE ;
2024-05-23 17:03:10 +02:00
break ;
case 3 : // Cornerstone Mask
2024-06-07 16:57:57 -04:00
move . type = Type . ROCK ;
2024-05-23 17:03:10 +02:00
break ;
case 4 : // Teal Mask Tera
2024-06-07 16:57:57 -04:00
move . type = Type . GRASS ;
2024-05-23 17:03:10 +02:00
break ;
case 5 : // Wellspring Mask Tera
2024-06-07 16:57:57 -04:00
move . type = Type . WATER ;
2024-05-23 17:03:10 +02:00
break ;
case 6 : // Hearthflame Mask Tera
2024-06-07 16:57:57 -04:00
move . type = Type . FIRE ;
2024-05-23 17:03:10 +02:00
break ;
case 7 : // Cornerstone Mask Tera
2024-06-07 16:57:57 -04:00
move . type = Type . ROCK ;
2024-05-23 17:03:10 +02:00
break ;
default :
2024-06-07 16:57:57 -04:00
move . type = Type . GRASS ;
2024-05-23 17:03:10 +02:00
break ;
2024-04-14 21:41:12 -05:00
}
return true ;
}
return false ;
}
}
2024-04-10 14:07:47 +10:00
export class WeatherBallTypeAttr extends VariableMoveTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) ) {
switch ( user . scene . arena . weather ? . weatherType ) {
2024-05-23 17:03:10 +02:00
case WeatherType . SUNNY :
case WeatherType . HARSH_SUN :
2024-06-07 16:57:57 -04:00
move . type = Type . FIRE ;
2024-05-23 17:03:10 +02:00
break ;
case WeatherType . RAIN :
case WeatherType . HEAVY_RAIN :
2024-06-07 16:57:57 -04:00
move . type = Type . WATER ;
2024-05-23 17:03:10 +02:00
break ;
case WeatherType . SANDSTORM :
2024-06-07 16:57:57 -04:00
move . type = Type . ROCK ;
2024-05-23 17:03:10 +02:00
break ;
case WeatherType . HAIL :
case WeatherType . SNOW :
2024-06-07 16:57:57 -04:00
move . type = Type . ICE ;
2024-05-23 17:03:10 +02:00
break ;
default :
return false ;
2024-04-10 14:07:47 +10:00
}
return true ;
}
return false ;
}
}
2024-05-19 09:31:13 -04:00
/ * *
* Changes the move ' s type to match the current terrain .
* Has no effect if the user is not grounded .
* @extends VariableMoveTypeAttr
* @see { @linkcode apply }
* /
export class TerrainPulseTypeAttr extends VariableMoveTypeAttr {
/ * *
* @param user { @linkcode Pokemon } using this move
* @param target N / A
* @param move N / A
* @param args [ 0 ] { @linkcode Utils . IntegerHolder } The move ' s type to be modified
* @returns true if the function succeeds
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-24 02:19:20 +02:00
if ( ! user . isGrounded ) {
2024-05-19 09:31:13 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-19 09:31:13 -04:00
const currentTerrain = user . scene . arena . getTerrainType ( ) ;
switch ( currentTerrain ) {
2024-05-23 17:03:10 +02:00
case TerrainType . MISTY :
2024-06-07 16:57:57 -04:00
move . type = Type . FAIRY ;
2024-05-23 17:03:10 +02:00
break ;
case TerrainType . ELECTRIC :
2024-06-07 16:57:57 -04:00
move . type = Type . ELECTRIC ;
2024-05-23 17:03:10 +02:00
break ;
case TerrainType . GRASSY :
2024-06-07 16:57:57 -04:00
move . type = Type . GRASS ;
2024-05-23 17:03:10 +02:00
break ;
case TerrainType . PSYCHIC :
2024-06-07 16:57:57 -04:00
move . type = Type . PSYCHIC ;
2024-05-23 17:03:10 +02:00
break ;
default :
return false ;
2024-05-19 09:31:13 -04:00
}
return true ;
}
}
2024-04-12 15:43:09 +10:00
export class HiddenPowerTypeAttr extends VariableMoveTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const iv_val = Math . floor ( ( ( user . ivs [ Stat . HP ] & 1 )
+ ( user . ivs [ Stat . ATK ] & 1 ) * 2
+ ( user . ivs [ Stat . DEF ] & 1 ) * 4
+ ( user . ivs [ Stat . SPD ] & 1 ) * 8
+ ( user . ivs [ Stat . SPATK ] & 1 ) * 16
+ ( user . ivs [ Stat . SPDEF ] & 1 ) * 32 ) * 15 / 63 ) ;
2024-05-24 01:45:04 +02:00
2024-06-07 16:57:57 -04:00
move . type = [
2024-04-12 15:43:09 +10:00
Type . FIGHTING , Type . FLYING , Type . POISON , Type . GROUND ,
Type . ROCK , Type . BUG , Type . GHOST , Type . STEEL ,
Type . FIRE , Type . WATER , Type . GRASS , Type . ELECTRIC ,
Type . PSYCHIC , Type . ICE , Type . DRAGON , Type . DARK ] [ iv_val ] ;
return true ;
}
}
2024-05-06 11:24:37 -04:00
export class MatchUserTypeAttr extends VariableMoveTypeAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const userTypes = user . getTypes ( true ) ;
2024-05-24 02:19:20 +02:00
if ( userTypes . includes ( Type . STELLAR ) ) { // will not change to stellar type
2024-05-06 11:24:37 -04:00
const nonTeraTypes = user . getTypes ( ) ;
2024-06-07 16:57:57 -04:00
move . type = nonTeraTypes [ 0 ] ;
2024-05-24 01:45:04 +02:00
return true ;
2024-05-23 17:03:10 +02:00
} else if ( userTypes . length > 0 ) {
2024-06-07 16:57:57 -04:00
move . type = userTypes [ 0 ] ;
2024-05-06 11:24:37 -04:00
return true ;
2024-05-23 17:03:10 +02:00
} else {
2024-05-06 11:24:37 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-06 11:24:37 -04:00
}
}
2024-04-01 20:26:35 +03:00
export class VariableMoveTypeMultiplierAttr extends MoveAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
return false ;
}
}
2024-04-03 16:33:11 +03:00
export class NeutralDamageAgainstFlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( ! target . getTag ( BattlerTagType . IGNORE_FLYING ) ) {
const multiplier = args [ 0 ] as Utils . NumberHolder ;
//When a flying type is hit, the first hit is always 1x multiplier. Levitating pokemon are instantly affected by typing
2024-05-23 17:03:10 +02:00
if ( target . isOfType ( Type . FLYING ) ) {
2024-04-03 16:33:11 +03:00
multiplier . value = 1 ;
2024-05-23 17:03:10 +02:00
}
2024-04-03 16:33:11 +03:00
target . addTag ( BattlerTagType . IGNORE_FLYING , 20 , move . id , user . id ) ; //TODO: Grounded effect should not have turn limit
return true ;
}
return false ;
}
}
2024-04-02 16:16:35 +03:00
export class WaterSuperEffectTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-04-01 20:26:35 +03:00
const multiplier = args [ 0 ] as Utils . NumberHolder ;
2024-04-09 18:44:13 +03:00
if ( target . isOfType ( Type . WATER ) ) {
2024-04-02 16:16:35 +03:00
multiplier . value *= 4 ; // Increased twice because initial reduction against water
2024-04-09 18:44:13 +03:00
return true ;
}
2024-04-01 20:26:35 +03:00
return false ;
}
}
2024-05-14 14:01:37 -04:00
export class IceNoEffectTypeAttr extends VariableMoveTypeMultiplierAttr {
/ * *
* Checks to see if the Target is Ice - Type or not . If so , the move will have no effect .
* @param { Pokemon } user N / A
* @param { Pokemon } target Pokemon that is being checked whether Ice - Type or not .
* @param { Move } move N / A
* @param { any [ ] } args Sets to false if the target is Ice - Type , so it should do no damage / no effect .
* @returns { boolean } Returns true if move is successful , false if Ice - Type .
* /
2024-05-23 17:03:10 +02:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-14 14:01:37 -04:00
if ( target . isOfType ( Type . ICE ) ) {
( args [ 0 ] as Utils . BooleanHolder ) . value = false ;
return false ;
}
return true ;
}
}
2024-04-23 17:42:45 -04:00
export class FlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const multiplier = args [ 0 ] as Utils . NumberHolder ;
2024-05-06 00:27:56 -05:00
multiplier . value *= target . getAttackTypeEffectiveness ( Type . FLYING , user ) ;
2024-04-23 17:42:45 -04:00
return true ;
}
}
2024-04-22 01:05:48 -04:00
export class OneHitKOAccuracyAttr extends VariableAccuracyAttr {
2023-11-30 16:37:16 -05:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const accuracy = args [ 0 ] as Utils . NumberHolder ;
2024-05-23 17:03:10 +02:00
if ( user . level < target . level ) {
2024-04-22 20:59:47 +10:00
accuracy . value = 0 ;
2024-05-23 17:03:10 +02:00
} else {
2024-04-22 20:59:47 +10:00
accuracy . value = Math . min ( Math . max ( 30 + 100 * ( 1 - target . level / user . level ) , 0 ) , 100 ) ;
2024-05-23 17:03:10 +02:00
}
2024-04-08 12:52:37 -04:00
return true ;
2023-11-30 16:37:16 -05:00
}
}
2024-05-14 14:01:37 -04:00
export class SheerColdAccuracyAttr extends OneHitKOAccuracyAttr {
/ * *
2024-05-24 01:45:04 +02:00
* Changes the normal One Hit KO Accuracy Attr to implement the Gen VII changes ,
2024-05-14 14:01:37 -04:00
* where if the user is Ice - Type , it has more accuracy .
* @param { Pokemon } user Pokemon that is using the move ; checks the Pokemon ' s level .
* @param { Pokemon } target Pokemon that is receiving the move ; checks the Pokemon ' s level .
2024-05-24 01:45:04 +02:00
* @param { Move } move N / A
2024-05-14 14:01:37 -04:00
* @param { any [ ] } args Uses the accuracy argument , allowing to change it from either 0 if it doesn ' t pass
* the first if / e l s e , o r 3 0 / 2 0 d e p e n d i n g o n t h e t y p e o f t h e u s e r P o k e m o n .
* @returns Returns true if move is successful , false if misses .
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const accuracy = args [ 0 ] as Utils . NumberHolder ;
2024-05-23 17:03:10 +02:00
if ( user . level < target . level ) {
accuracy . value = 0 ;
2024-05-24 01:45:04 +02:00
} else {
2024-05-23 17:03:10 +02:00
const baseAccuracy = user . isOfType ( Type . ICE ) ? 30 : 20 ;
accuracy . value = Math . min ( Math . max ( baseAccuracy + 100 * ( 1 - target . level / user . level ) , 0 ) , 100 ) ;
}
2024-05-14 14:01:37 -04:00
return true ;
}
}
2023-04-10 23:15:06 -04:00
export class MissEffectAttr extends MoveAttr {
2024-01-07 23:17:24 -05:00
private missEffectFunc : UserMoveConditionFunc ;
2023-04-10 16:17:25 -04:00
2024-01-07 23:17:24 -05:00
constructor ( missEffectFunc : UserMoveConditionFunc ) {
2023-04-10 16:17:25 -04:00
super ( ) ;
this . missEffectFunc = missEffectFunc ;
}
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-05-18 11:11:06 -04:00
this . missEffectFunc ( user , move ) ;
2023-04-10 16:17:25 -04:00
return true ;
}
}
2024-04-12 18:49:48 -07:00
export class NoEffectAttr extends MoveAttr {
private noEffectFunc : UserMoveConditionFunc ;
constructor ( noEffectFunc : UserMoveConditionFunc ) {
super ( ) ;
this . noEffectFunc = noEffectFunc ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
this . noEffectFunc ( user , move ) ;
return true ;
}
}
const crashDamageFunc = ( user : Pokemon , move : Move ) = > {
2024-04-02 15:14:07 -04:00
const cancelled = new Utils . BooleanHolder ( false ) ;
applyAbAttrs ( BlockNonDirectDamageAbAttr , user , cancelled ) ;
2024-05-23 17:03:10 +02:00
if ( cancelled . value ) {
2024-04-02 15:14:07 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2024-04-12 18:49:48 -07:00
user . damageAndUpdate ( Math . floor ( user . getMaxHp ( ) / 2 ) , HitResult . OTHER , false , true ) ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( user , " kept going\nand crashed!" ) ) ;
2024-04-25 20:51:04 -04:00
user . turnData . damageTaken += Math . floor ( user . getMaxHp ( ) / 2 ) ;
2024-05-24 01:45:04 +02:00
2024-03-01 09:35:36 -05:00
return true ;
} ;
2023-04-27 14:30:03 -04:00
export class TypelessAttr extends MoveAttr { }
2024-05-10 11:40:21 -04:00
/ * *
* Attribute used for moves which ignore redirection effects , and always target their original target , i . e . Snipe Shot
* Bypasses Storm Drain , Follow Me , Ally Switch , and the like .
2024-05-24 01:45:04 +02:00
* /
2024-05-10 11:40:21 -04:00
export class BypassRedirectAttr extends MoveAttr { }
2023-04-27 14:30:03 -04:00
2023-04-19 18:19:55 -04:00
export class DisableMoveAttr extends MoveEffectAttr {
constructor ( ) {
super ( false ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-19 18:19:55 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-19 18:19:55 -04:00
const moveQueue = target . getLastXMoves ( ) ;
let turnMove : TurnMove ;
while ( moveQueue . length ) {
turnMove = moveQueue . shift ( ) ;
2024-05-23 17:03:10 +02:00
if ( turnMove . virtual ) {
2023-04-19 18:19:55 -04:00
continue ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2023-05-06 00:42:01 -04:00
const moveIndex = target . getMoveset ( ) . findIndex ( m = > m . moveId === turnMove . move ) ;
2024-05-23 17:03:10 +02:00
if ( moveIndex === - 1 ) {
2023-04-19 18:19:55 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2023-05-06 00:42:01 -04:00
const disabledMove = target . getMoveset ( ) [ moveIndex ] ;
2023-10-25 09:41:37 -04:00
target . summonData . disabledMove = disabledMove . moveId ;
target . summonData . disabledTurns = 4 ;
2023-04-19 18:19:55 -04:00
2023-04-21 19:30:04 -04:00
user . scene . queueMessage ( getPokemonMessage ( target , ` 's ${ disabledMove . getName ( ) } \ nwas disabled! ` ) ) ;
2024-05-24 01:45:04 +02:00
2023-04-19 18:19:55 -04:00
return true ;
}
2024-05-24 01:45:04 +02:00
2023-04-19 18:19:55 -04:00
return false ;
}
2024-05-24 01:45:04 +02:00
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-12-10 17:57:12 -05:00
return ( user , target , move ) = > {
2024-05-23 17:03:10 +02:00
if ( target . summonData . disabledMove || target . isMax ( ) ) {
2023-10-25 09:41:37 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-10-25 09:41:37 -04:00
2023-04-19 18:19:55 -04:00
const moveQueue = target . getLastXMoves ( ) ;
let turnMove : TurnMove ;
while ( moveQueue . length ) {
turnMove = moveQueue . shift ( ) ;
2024-05-23 17:03:10 +02:00
if ( turnMove . virtual ) {
2023-04-19 18:19:55 -04:00
continue ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2023-05-06 00:42:01 -04:00
const move = target . getMoveset ( ) . find ( m = > m . moveId === turnMove . move ) ;
2024-05-23 17:03:10 +02:00
if ( ! move ) {
2023-04-19 18:19:55 -04:00
continue ;
2024-05-23 17:03:10 +02:00
}
2023-04-19 18:19:55 -04:00
2023-10-25 09:41:37 -04:00
return true ;
2023-04-19 18:19:55 -04:00
}
2023-04-24 14:30:21 -04:00
} ;
2023-04-19 18:19:55 -04:00
}
2023-07-28 10:23:37 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return - 5 ;
}
2023-04-19 18:19:55 -04:00
}
2023-07-10 10:54:22 -04:00
export class FrenzyAttr extends MoveEffectAttr {
2023-04-15 01:32:16 -04:00
constructor ( ) {
2023-07-10 10:54:22 -04:00
super ( true , MoveEffectTrigger . HIT ) ;
2023-04-15 01:32:16 -04:00
}
2023-04-16 00:29:55 -04:00
canApply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) {
2023-05-18 11:11:06 -04:00
return ! ( this . selfTarget ? user : target ) . isFainted ( ) ;
2023-04-15 01:32:16 -04:00
}
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-15 01:32:16 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-15 01:32:16 -04:00
2023-04-20 21:32:48 -04:00
if ( ! user . getMoveQueue ( ) . length ) {
2023-04-21 19:30:04 -04:00
if ( ! user . getTag ( BattlerTagType . FRENZY ) ) {
2024-04-28 23:52:41 -04:00
const turnCount = user . randSeedIntRange ( 1 , 2 ) ;
2023-05-18 11:11:06 -04:00
new Array ( turnCount ) . fill ( null ) . map ( ( ) = > user . getMoveQueue ( ) . push ( { move : move.id , targets : [ target . getBattlerIndex ( ) ] , ignorePP : true } ) ) ;
2023-04-24 14:30:21 -04:00
user . addTag ( BattlerTagType . FRENZY , 1 , move . id , user . id ) ;
2023-04-15 01:32:16 -04:00
} else {
2023-04-21 19:30:04 -04:00
applyMoveAttrs ( AddBattlerTagAttr , user , target , move , args ) ;
user . lapseTag ( BattlerTagType . FRENZY ) ;
2023-04-15 01:32:16 -04:00
}
return true ;
}
return false ;
}
}
2024-01-07 23:17:24 -05:00
export const frenzyMissFunc : UserMoveConditionFunc = ( user : Pokemon , move : Move ) = > {
2024-05-23 17:03:10 +02:00
while ( user . getMoveQueue ( ) . length && user . getMoveQueue ( ) [ 0 ] . move === move . id ) {
2023-04-20 21:32:48 -04:00
user . getMoveQueue ( ) . shift ( ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-24 14:30:21 -04:00
user . lapseTag ( BattlerTagType . FRENZY ) ;
return true ;
2023-04-15 01:32:16 -04:00
} ;
2023-04-21 19:30:04 -04:00
export class AddBattlerTagAttr extends MoveEffectAttr {
public tagType : BattlerTagType ;
2024-01-02 21:31:59 -05:00
public turnCountMin : integer ;
public turnCountMax : integer ;
2023-04-24 14:30:21 -04:00
private failOnOverlap : boolean ;
2023-04-15 01:32:16 -04:00
2024-01-02 21:31:59 -05:00
constructor ( tagType : BattlerTagType , selfTarget : boolean = false , failOnOverlap : boolean = false , turnCountMin : integer = 0 , turnCountMax? : integer ) {
2023-04-15 01:32:16 -04:00
super ( selfTarget ) ;
this . tagType = tagType ;
2024-01-02 21:31:59 -05:00
this . turnCountMin = turnCountMin ;
this . turnCountMax = turnCountMax !== undefined ? turnCountMax : turnCountMin ;
2023-04-24 14:30:21 -04:00
this . failOnOverlap = ! ! failOnOverlap ;
2023-04-15 01:32:16 -04:00
}
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-15 01:32:16 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-15 01:32:16 -04:00
2023-04-25 01:32:48 -04:00
const chance = this . getTagChance ( user , target , move ) ;
2024-05-23 17:03:10 +02:00
if ( chance < 0 || chance === 100 || user . randSeedInt ( 100 ) < chance ) {
2024-03-28 09:21:39 -04:00
return ( this . selfTarget ? user : target ) . addTag ( this . tagType , user . randSeedInt ( this . turnCountMax - this . turnCountMin , this . turnCountMin ) , move . id , user . id ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-15 01:32:16 -04:00
return false ;
}
2023-04-24 14:30:21 -04:00
2023-04-25 01:32:48 -04:00
getTagChance ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return move . chance ;
}
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-04-24 14:30:21 -04:00
return this . failOnOverlap
2023-12-10 17:57:12 -05:00
? ( user , target , move ) = > ! ( this . selfTarget ? user : target ) . getTag ( this . tagType )
2023-04-24 14:30:21 -04:00
: null ;
}
2023-05-18 11:11:06 -04:00
2024-02-20 12:27:38 -05:00
getTagTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2023-05-18 11:11:06 -04:00
switch ( this . tagType ) {
2024-05-23 17:03:10 +02:00
case BattlerTagType . RECHARGING :
case BattlerTagType . PERISH_SONG :
return - 16 ;
case BattlerTagType . FLINCHED :
case BattlerTagType . CONFUSED :
case BattlerTagType . INFATUATED :
case BattlerTagType . NIGHTMARE :
case BattlerTagType . DROWSY :
case BattlerTagType . NO_CRIT :
return - 5 ;
case BattlerTagType . SEEDED :
case BattlerTagType . SALT_CURED :
case BattlerTagType . CURSED :
case BattlerTagType . FRENZY :
case BattlerTagType . TRAPPED :
case BattlerTagType . BIND :
case BattlerTagType . WRAP :
case BattlerTagType . FIRE_SPIN :
case BattlerTagType . WHIRLPOOL :
case BattlerTagType . CLAMP :
case BattlerTagType . SAND_TOMB :
case BattlerTagType . MAGMA_STORM :
case BattlerTagType . SNAP_TRAP :
case BattlerTagType . THUNDER_CAGE :
case BattlerTagType . INFESTATION :
return - 3 ;
case BattlerTagType . ENCORE :
return - 2 ;
case BattlerTagType . INGRAIN :
case BattlerTagType . IGNORE_ACCURACY :
case BattlerTagType . AQUA_RING :
return 3 ;
case BattlerTagType . PROTECTED :
case BattlerTagType . FLYING :
case BattlerTagType . CRIT_BOOST :
case BattlerTagType . ALWAYS_CRIT :
return 5 ;
2023-05-18 11:11:06 -04:00
}
}
2024-02-20 12:27:38 -05:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
let chance = this . getTagChance ( user , target , move ) ;
2024-05-23 17:03:10 +02:00
if ( chance < 0 ) {
2024-02-20 12:27:38 -05:00
chance = 100 ;
2024-05-23 17:03:10 +02:00
}
2024-02-20 12:27:38 -05:00
return Math . floor ( this . getTagTargetBenefitScore ( user , target , move ) * ( chance / 100 ) ) ;
}
2023-04-15 01:32:16 -04:00
}
2024-04-21 18:23:45 -04:00
export class CurseAttr extends MoveEffectAttr {
2024-05-24 01:45:04 +02:00
2024-04-21 18:23:45 -04:00
apply ( user : Pokemon , target : Pokemon , move :Move , args : any [ ] ) : boolean {
if ( user . getTypes ( true ) . includes ( Type . GHOST ) ) {
if ( target . getTag ( BattlerTagType . CURSED ) ) {
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( "But it failed!" ) ;
2024-04-21 18:23:45 -04:00
return false ;
}
2024-05-23 17:03:10 +02:00
const curseRecoilDamage = Math . max ( 1 , Math . floor ( user . getMaxHp ( ) / 2 ) ) ;
2024-04-21 18:23:45 -04:00
user . damageAndUpdate ( curseRecoilDamage , HitResult . OTHER , false , true , true ) ;
2024-05-01 12:21:22 -05:00
user . scene . queueMessage ( getPokemonMessage ( user , ` cut its own HP \ nand laid a curse on the ${ target . name } ! ` ) ) ;
2024-04-21 18:23:45 -04:00
target . addTag ( BattlerTagType . CURSED , 0 , move . id , user . id ) ;
return true ;
} else {
2024-05-05 17:45:20 -04:00
user . scene . unshiftPhase ( new StatChangePhase ( user . scene , user . getBattlerIndex ( ) , true , [ BattleStat . ATK , BattleStat . DEF ] , 1 ) ) ;
user . scene . unshiftPhase ( new StatChangePhase ( user . scene , user . getBattlerIndex ( ) , true , [ BattleStat . SPD ] , - 1 ) ) ;
2024-04-21 18:23:45 -04:00
return true ;
}
}
}
2023-04-22 15:01:48 -04:00
export class LapseBattlerTagAttr extends MoveEffectAttr {
public tagTypes : BattlerTagType [ ] ;
2024-02-20 12:27:38 -05:00
constructor ( tagTypes : BattlerTagType [ ] , selfTarget : boolean = false ) {
2023-04-22 15:01:48 -04:00
super ( selfTarget ) ;
this . tagTypes = tagTypes ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-22 15:01:48 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-22 15:01:48 -04:00
2024-05-23 17:03:10 +02:00
for ( const tagType of this . tagTypes ) {
2023-04-22 15:01:48 -04:00
( this . selfTarget ? user : target ) . lapseTag ( tagType ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2023-04-22 15:01:48 -04:00
return true ;
}
}
2024-02-20 12:27:38 -05:00
export class RemoveBattlerTagAttr extends MoveEffectAttr {
public tagTypes : BattlerTagType [ ] ;
constructor ( tagTypes : BattlerTagType [ ] , selfTarget : boolean = false ) {
super ( selfTarget ) ;
this . tagTypes = tagTypes ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-02-20 12:27:38 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-02-20 12:27:38 -05:00
2024-05-23 17:03:10 +02:00
for ( const tagType of this . tagTypes ) {
2024-02-20 12:27:38 -05:00
( this . selfTarget ? user : target ) . removeTag ( tagType ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2024-02-20 12:27:38 -05:00
return true ;
}
}
2023-04-21 19:30:04 -04:00
export class FlinchAttr extends AddBattlerTagAttr {
2023-04-15 17:40:18 -04:00
constructor ( ) {
2023-04-21 19:30:04 -04:00
super ( BattlerTagType . FLINCHED , false ) ;
2023-04-15 17:40:18 -04:00
}
}
2023-04-21 19:30:04 -04:00
export class ConfuseAttr extends AddBattlerTagAttr {
2023-04-15 01:32:16 -04:00
constructor ( selfTarget? : boolean ) {
2024-01-02 21:31:59 -05:00
super ( BattlerTagType . CONFUSED , selfTarget , false , 2 , 5 ) ;
2023-04-19 16:52:14 -04:00
}
}
2024-01-07 23:17:24 -05:00
export class RechargeAttr extends AddBattlerTagAttr {
constructor ( ) {
super ( BattlerTagType . RECHARGING , true ) ;
}
}
2023-04-22 15:01:48 -04:00
export class TrapAttr extends AddBattlerTagAttr {
constructor ( tagType : BattlerTagType ) {
2024-02-08 16:50:17 -06:00
super ( tagType , false , false , 4 , 5 ) ;
2023-04-22 15:01:48 -04:00
}
}
2023-04-24 14:30:21 -04:00
export class ProtectAttr extends AddBattlerTagAttr {
2024-01-15 23:29:22 -05:00
constructor ( tagType : BattlerTagType = BattlerTagType . PROTECTED ) {
super ( tagType , true ) ;
2023-04-24 14:30:21 -04:00
}
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-12-10 17:57:12 -05:00
return ( ( user , target , move ) : boolean = > {
2023-04-24 14:30:21 -04:00
let timesUsed = 0 ;
2024-01-02 21:31:59 -05:00
const moveHistory = user . getLastXMoves ( ) ;
2023-04-24 14:30:21 -04:00
let turnMove : TurnMove ;
2024-04-10 21:14:03 +03:00
while ( moveHistory . length ) {
turnMove = moveHistory . shift ( ) ;
2024-05-31 20:50:30 -04:00
if ( ! allMoves [ turnMove . move ] . hasAttr ( ProtectAttr ) || turnMove . result !== MoveResult . SUCCESS ) {
2024-04-10 21:14:03 +03:00
break ;
2024-05-23 17:03:10 +02:00
}
2023-04-24 14:30:21 -04:00
timesUsed ++ ;
2024-04-10 21:14:03 +03:00
}
2024-05-23 17:03:10 +02:00
if ( timesUsed ) {
2024-04-10 21:14:03 +03:00
return ! user . randSeedInt ( Math . pow ( 3 , timesUsed ) ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-24 14:30:21 -04:00
return true ;
} ) ;
2023-04-15 01:32:16 -04:00
}
}
2024-01-15 23:29:22 -05:00
export class EndureAttr extends ProtectAttr {
constructor ( ) {
super ( BattlerTagType . ENDURING ) ;
}
}
2023-04-27 20:12:25 -04:00
export class IgnoreAccuracyAttr extends AddBattlerTagAttr {
constructor ( ) {
2024-03-01 16:21:28 -05:00
super ( BattlerTagType . IGNORE_ACCURACY , true , false , 2 ) ;
2023-04-27 20:12:25 -04:00
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-27 20:12:25 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-27 20:12:25 -04:00
user . scene . queueMessage ( getPokemonMessage ( user , ` took aim \ nat ${ target . name } ! ` ) ) ;
return true ;
}
}
2024-04-12 21:05:32 +01:00
export class AlwaysCritsAttr extends AddBattlerTagAttr {
constructor ( ) {
super ( BattlerTagType . ALWAYS_CRIT , true , false , 2 ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-12 21:05:32 +01:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-12 21:05:32 +01:00
user . scene . queueMessage ( getPokemonMessage ( user , ` took aim \ nat ${ target . name } ! ` ) ) ;
return true ;
}
}
2023-12-18 21:53:28 -04:00
export class FaintCountdownAttr extends AddBattlerTagAttr {
constructor ( ) {
2024-01-02 21:31:59 -05:00
super ( BattlerTagType . PERISH_SONG , false , true , 4 ) ;
2023-12-18 21:53:28 -04:00
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-12-18 21:53:28 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-12-18 21:53:28 -04:00
2024-01-02 21:31:59 -05:00
user . scene . queueMessage ( getPokemonMessage ( target , ` \ nwill faint in ${ this . turnCountMin - 1 } turns. ` ) ) ;
2023-12-18 21:53:28 -04:00
return true ;
}
}
2024-05-24 01:45:04 +02:00
/ * *
* Attribute used when a move hits a { @linkcode BattlerTagType } for double damage
2024-05-16 07:07:23 -05:00
* @extends MoveAttr
* /
2023-04-13 12:16:36 -04:00
export class HitsTagAttr extends MoveAttr {
2024-05-16 07:07:23 -05:00
/** The {@linkcode BattlerTagType} this move hits */
2023-04-21 19:30:04 -04:00
public tagType : BattlerTagType ;
2024-05-16 07:07:23 -05:00
/** Should this move deal double damage against {@linkcode HitsTagAttr.tagType}? */
2023-04-13 12:16:36 -04:00
public doubleDamage : boolean ;
2023-04-21 19:30:04 -04:00
constructor ( tagType : BattlerTagType , doubleDamage? : boolean ) {
2023-04-13 12:16:36 -04:00
super ( ) ;
this . tagType = tagType ;
this . doubleDamage = ! ! doubleDamage ;
2023-04-03 23:38:31 -04:00
}
2023-05-18 11:11:06 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return target . getTag ( this . tagType ) ? this . doubleDamage ? 10 : 5 : 0 ;
}
2023-04-03 23:38:31 -04:00
}
2023-04-21 19:30:04 -04:00
export class AddArenaTagAttr extends MoveEffectAttr {
public tagType : ArenaTagType ;
public turnCount : integer ;
2024-01-15 23:29:22 -05:00
private failOnOverlap : boolean ;
2024-05-05 00:27:46 -05:00
public selfSideTarget : boolean ;
2023-04-21 19:30:04 -04:00
2024-04-05 14:28:50 -05:00
constructor ( tagType : ArenaTagType , turnCount? : integer , failOnOverlap : boolean = false , selfSideTarget : boolean = false ) {
2024-04-02 12:00:41 -04:00
super ( true , MoveEffectTrigger . POST_APPLY , true ) ;
2023-04-21 19:30:04 -04:00
this . tagType = tagType ;
this . turnCount = turnCount ;
2024-01-15 23:29:22 -05:00
this . failOnOverlap = failOnOverlap ;
2024-04-05 14:28:50 -05:00
this . selfSideTarget = selfSideTarget ;
2023-04-21 19:30:04 -04:00
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-21 19:30:04 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
2024-01-02 21:31:59 -05:00
if ( move . chance < 0 || move . chance === 100 || user . randSeedInt ( 100 ) < move . chance ) {
2024-04-05 14:28:50 -05:00
user . scene . arena . addTag ( this . tagType , this . turnCount , move . id , user . id , ( this . selfSideTarget ? user : target ) . isPlayer ( ) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY ) ;
2023-04-21 19:30:04 -04:00
return true ;
2023-04-13 12:16:36 -04:00
}
2023-04-21 19:30:04 -04:00
return false ;
}
2024-01-15 23:29:22 -05:00
getCondition ( ) : MoveConditionFunc {
return this . failOnOverlap
? ( user , target , move ) = > ! user . scene . arena . getTagOnSide ( this . tagType , target . isPlayer ( ) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY )
: null ;
}
2023-04-21 19:30:04 -04:00
}
2024-05-25 04:22:10 -07:00
/ * *
* Generic class for removing arena tags
* @param tagTypes : The types of tags that can be removed
* @param selfSideTarget : Is the user removing tags from its own side ?
* /
export class RemoveArenaTagsAttr extends MoveEffectAttr {
public tagTypes : ArenaTagType [ ] ;
public selfSideTarget : boolean ;
constructor ( tagTypes : ArenaTagType [ ] , selfSideTarget : boolean ) {
super ( true , MoveEffectTrigger . POST_APPLY ) ;
this . tagTypes = tagTypes ;
this . selfSideTarget = selfSideTarget ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( ! super . apply ( user , target , move , args ) ) {
return false ;
}
const side = ( this . selfSideTarget ? user : target ) . isPlayer ( ) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY ;
for ( const tagType of this . tagTypes ) {
user . scene . arena . removeTagOnSide ( tagType , side ) ;
}
return true ;
}
}
2023-04-24 14:30:21 -04:00
export class AddArenaTrapTagAttr extends AddArenaTagAttr {
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-12-10 17:57:12 -05:00
return ( user , target , move ) = > {
2024-05-05 00:27:46 -05:00
const side = ( this . selfSideTarget ? user : target ) . isPlayer ( ) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY ;
2024-05-23 17:03:10 +02:00
if ( move . category !== MoveCategory . STATUS || ! user . scene . arena . getTagOnSide ( this . tagType , side ) ) {
2023-04-24 14:30:21 -04:00
return true ;
2024-05-23 17:03:10 +02:00
}
2024-05-05 00:27:46 -05:00
const tag = user . scene . arena . getTagOnSide ( this . tagType , side ) as ArenaTrapTag ;
2023-04-24 14:30:21 -04:00
return tag . layers < tag . maxLayers ;
} ;
}
}
2024-05-06 23:00:31 -04:00
export class RemoveArenaTrapAttr extends MoveEffectAttr {
private targetBothSides : boolean ;
constructor ( targetBothSides : boolean = false ) {
super ( true , MoveEffectTrigger . PRE_APPLY ) ;
this . targetBothSides = targetBothSides ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-05-06 23:00:31 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-06 23:00:31 -04:00
2024-05-24 02:19:20 +02:00
if ( this . targetBothSides ) {
2024-05-06 23:00:31 -04:00
user . scene . arena . removeTagOnSide ( ArenaTagType . SPIKES , ArenaTagSide . PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . TOXIC_SPIKES , ArenaTagSide . PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . STEALTH_ROCK , ArenaTagSide . PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . STICKY_WEB , ArenaTagSide . PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . SPIKES , ArenaTagSide . ENEMY ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . TOXIC_SPIKES , ArenaTagSide . ENEMY ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . STEALTH_ROCK , ArenaTagSide . ENEMY ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . STICKY_WEB , ArenaTagSide . ENEMY ) ;
2024-05-23 17:03:10 +02:00
} else {
2024-05-06 23:00:31 -04:00
user . scene . arena . removeTagOnSide ( ArenaTagType . SPIKES , target . isPlayer ( ) ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . TOXIC_SPIKES , target . isPlayer ( ) ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . STEALTH_ROCK , target . isPlayer ( ) ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . STICKY_WEB , target . isPlayer ( ) ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER ) ;
}
return true ;
}
}
2024-04-14 22:26:58 -04:00
export class RemoveScreensAttr extends MoveEffectAttr {
private targetBothSides : boolean ;
constructor ( targetBothSides : boolean = false ) {
super ( true , MoveEffectTrigger . PRE_APPLY ) ;
this . targetBothSides = targetBothSides ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-14 22:26:58 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-14 22:26:58 -04:00
2024-05-24 02:19:20 +02:00
if ( this . targetBothSides ) {
2024-04-14 22:26:58 -04:00
user . scene . arena . removeTagOnSide ( ArenaTagType . REFLECT , ArenaTagSide . PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . LIGHT_SCREEN , ArenaTagSide . PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . AURORA_VEIL , ArenaTagSide . PLAYER ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . REFLECT , ArenaTagSide . ENEMY ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . LIGHT_SCREEN , ArenaTagSide . ENEMY ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . AURORA_VEIL , ArenaTagSide . ENEMY ) ;
2024-05-24 02:19:20 +02:00
} else {
2024-04-14 22:26:58 -04:00
user . scene . arena . removeTagOnSide ( ArenaTagType . REFLECT , target . isPlayer ( ) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . LIGHT_SCREEN , target . isPlayer ( ) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY ) ;
user . scene . arena . removeTagOnSide ( ArenaTagType . AURORA_VEIL , target . isPlayer ( ) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY ) ;
}
return true ;
}
}
2024-06-07 10:27:11 -04:00
/ * S w a p s a r e n a e f f e c t s b e t w e e n t h e p l a y e r a n d e n e m y s i d e
* @extends MoveEffectAttr
* @see { @linkcode apply }
* /
export class SwapArenaTagsAttr extends MoveEffectAttr {
public SwapTags : ArenaTagType [ ] ;
constructor ( SwapTags : ArenaTagType [ ] ) {
super ( true , MoveEffectTrigger . POST_APPLY ) ;
this . SwapTags = SwapTags ;
}
apply ( user :Pokemon , target :Pokemon , move :Move , args : any [ ] ) : boolean {
if ( ! super . apply ( user , target , move , args ) ) {
return false ;
}
const tagPlayerTemp = user . scene . arena . findTagsOnSide ( ( t = > this . SwapTags . includes ( t . tagType ) ) , ArenaTagSide . PLAYER ) ;
const tagEnemyTemp = user . scene . arena . findTagsOnSide ( ( t = > this . SwapTags . includes ( t . tagType ) ) , ArenaTagSide . ENEMY ) ;
if ( tagPlayerTemp ) {
for ( const swapTagsType of tagPlayerTemp ) {
user . scene . arena . removeTagOnSide ( swapTagsType . tagType , ArenaTagSide . PLAYER , true ) ;
user . scene . arena . addTag ( swapTagsType . tagType , swapTagsType . turnCount , swapTagsType . sourceMove , swapTagsType . sourceId , ArenaTagSide . ENEMY , true ) ;
}
}
if ( tagEnemyTemp ) {
for ( const swapTagsType of tagEnemyTemp ) {
user . scene . arena . removeTagOnSide ( swapTagsType . tagType , ArenaTagSide . ENEMY , true ) ;
user . scene . arena . addTag ( swapTagsType . tagType , swapTagsType . turnCount , swapTagsType . sourceMove , swapTagsType . sourceId , ArenaTagSide . PLAYER , true ) ;
}
}
user . scene . queueMessage ( ` ${ user . name } swapped the battle effects affecting each side of the field! ` ) ;
return true ;
}
}
2024-05-20 08:02:17 +09:00
/ * *
* Attribute used for Revival Blessing .
* @extends MoveEffectAttr
* @see { @linkcode apply }
* /
export class RevivalBlessingAttr extends MoveEffectAttr {
constructor ( user? : boolean ) {
super ( true ) ;
}
/ * *
2024-05-24 01:45:04 +02:00
*
2024-05-20 08:02:17 +09:00
* @param user { @linkcode Pokemon } using this move
* @param target { @linkcode Pokemon } target of this move
* @param move { @linkcode Move } being used
* @param args N / A
* @returns Promise , true if function succeeds .
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise ( resolve = > {
// If user is player, checks if the user has fainted pokemon
2024-05-24 02:19:20 +02:00
if ( user instanceof PlayerPokemon
2024-05-20 08:02:17 +09:00
&& user . scene . getParty ( ) . findIndex ( p = > p . isFainted ( ) ) > - 1 ) {
2024-05-23 17:03:10 +02:00
( user as PlayerPokemon ) . revivalBlessing ( ) . then ( ( ) = > {
resolve ( true ) ;
} ) ;
2024-05-24 01:45:04 +02:00
// If user is enemy, checks that it is a trainer, and it has fainted non-boss pokemon in party
2024-05-24 02:19:20 +02:00
} else if ( user instanceof EnemyPokemon
2024-05-20 08:02:17 +09:00
&& user . hasTrainer ( )
&& user . scene . getEnemyParty ( ) . findIndex ( p = > p . isFainted ( ) && ! p . isBoss ( ) ) > - 1 ) {
2024-05-23 17:03:10 +02:00
// Selects a random fainted pokemon
const faintedPokemon = user . scene . getEnemyParty ( ) . filter ( p = > p . isFainted ( ) && ! p . isBoss ( ) ) ;
const pokemon = faintedPokemon [ user . randSeedInt ( faintedPokemon . length ) ] ;
const slotIndex = user . scene . getEnemyParty ( ) . findIndex ( p = > pokemon . id === p . id ) ;
pokemon . resetStatus ( ) ;
pokemon . heal ( Math . min ( Math . max ( Math . ceil ( Math . floor ( 0.5 * pokemon . getMaxHp ( ) ) ) , 1 ) , pokemon . getMaxHp ( ) ) ) ;
user . scene . queueMessage ( ` ${ pokemon . name } was revived! ` , 0 , true ) ;
2024-05-24 02:19:20 +02:00
if ( user . scene . currentBattle . double && user . scene . getEnemyParty ( ) . length > 1 ) {
2024-05-23 17:03:10 +02:00
const allyPokemon = user . getAlly ( ) ;
2024-05-24 02:19:20 +02:00
if ( slotIndex <= 1 ) {
2024-05-23 17:03:10 +02:00
user . scene . unshiftPhase ( new SwitchSummonPhase ( user . scene , pokemon . getFieldIndex ( ) , slotIndex , false , false , false ) ) ;
2024-05-24 02:19:20 +02:00
} else if ( allyPokemon . isFainted ( ) ) {
2024-05-23 17:03:10 +02:00
user . scene . unshiftPhase ( new SwitchSummonPhase ( user . scene , allyPokemon . getFieldIndex ( ) , slotIndex , false , false , false ) ) ;
2024-05-20 08:02:17 +09:00
}
2024-05-23 17:03:10 +02:00
}
resolve ( true ) ;
2024-05-20 08:02:17 +09:00
} else {
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( "But it failed!" ) ;
2024-05-20 08:02:17 +09:00
resolve ( false ) ;
}
2024-05-23 17:03:10 +02:00
} ) ;
2024-05-20 08:02:17 +09:00
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2024-05-24 02:19:20 +02:00
if ( user . hasTrainer ( ) && user . scene . getEnemyParty ( ) . findIndex ( p = > p . isFainted ( ) && ! p . isBoss ( ) ) > - 1 ) {
2024-05-20 08:02:17 +09:00
return 20 ;
2024-05-23 17:03:10 +02:00
}
2024-05-20 08:02:17 +09:00
return - 20 ;
}
}
2024-04-14 22:26:58 -04:00
2023-10-31 14:09:33 -04:00
export class ForceSwitchOutAttr extends MoveEffectAttr {
private user : boolean ;
private batonPass : boolean ;
2024-05-24 01:45:04 +02:00
2023-10-31 14:09:33 -04:00
constructor ( user? : boolean , batonPass? : boolean ) {
2024-04-17 09:56:13 +07:00
super ( false , MoveEffectTrigger . POST_APPLY , true ) ;
2023-10-31 14:09:33 -04:00
this . user = ! ! user ;
this . batonPass = ! ! batonPass ;
}
2024-05-24 01:45:04 +02:00
2023-10-31 14:09:33 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise ( resolve = > {
2024-05-24 01:45:04 +02:00
2024-04-12 12:32:06 +01:00
// Check if the move category is not STATUS or if the switch out condition is not met
2024-05-23 17:03:10 +02:00
if ( ! this . getSwitchOutCondition ( ) ( user , target , move ) ) {
2024-04-12 07:44:45 -04:00
//Apply effects before switch out i.e. poison point, flame body, etc
2024-06-07 16:57:57 -04:00
applyPostDefendAbAttrs ( PostDefendContactApplyStatusEffectAbAttr , target , user , move , null ) ;
2024-05-23 17:03:10 +02:00
return resolve ( false ) ;
}
2024-05-05 07:52:27 -07:00
2024-04-12 12:32:06 +01:00
// Move the switch out logic inside the conditional block
// This ensures that the switch out only happens when the conditions are met
const switchOutTarget = this . user ? user : target ;
2024-05-24 01:45:04 +02:00
if ( switchOutTarget instanceof PlayerPokemon ) {
2024-04-12 12:32:06 +01:00
if ( switchOutTarget . hp ) {
applyPreSwitchOutAbAttrs ( PreSwitchOutAbAttr , switchOutTarget ) ;
( switchOutTarget as PlayerPokemon ) . switchOut ( this . batonPass , true ) . then ( ( ) = > resolve ( true ) ) ;
2024-05-23 17:03:10 +02:00
} else {
resolve ( false ) ;
}
2024-04-12 12:32:06 +01:00
return ;
2024-05-23 17:03:10 +02:00
} else if ( user . scene . currentBattle . battleType ) {
2024-04-12 12:32:06 +01:00
// Switch out logic for the battle type
switchOutTarget . resetTurnData ( ) ;
switchOutTarget . resetSummonData ( ) ;
switchOutTarget . hideInfo ( ) ;
switchOutTarget . setVisible ( false ) ;
switchOutTarget . scene . field . remove ( switchOutTarget ) ;
user . scene . triggerPokemonFormChange ( switchOutTarget , SpeciesFormChangeActiveTrigger , true ) ;
2024-05-24 01:45:04 +02:00
2024-05-23 17:03:10 +02:00
if ( switchOutTarget . hp ) {
user . scene . unshiftPhase ( new SwitchSummonPhase ( user . scene , switchOutTarget . getFieldIndex ( ) , user . scene . currentBattle . trainer . getNextSummonIndex ( ( switchOutTarget as EnemyPokemon ) . trainerSlot ) , false , this . batonPass , false ) ) ;
}
2024-05-24 01:45:04 +02:00
} else {
2024-04-12 07:44:45 -04:00
// Switch out logic for everything else
2024-04-12 12:32:06 +01:00
switchOutTarget . setVisible ( false ) ;
2024-05-24 01:45:04 +02:00
2024-04-12 12:32:06 +01:00
if ( switchOutTarget . hp ) {
switchOutTarget . hideInfo ( ) . then ( ( ) = > switchOutTarget . destroy ( ) ) ;
switchOutTarget . scene . field . remove ( switchOutTarget ) ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( switchOutTarget , " fled!" ) , null , true , 500 ) ;
2024-04-12 12:32:06 +01:00
}
2024-05-24 01:45:04 +02:00
2024-04-12 12:32:06 +01:00
if ( ! switchOutTarget . getAlly ( ) ? . isActive ( true ) ) {
user . scene . clearEnemyHeldItemModifiers ( ) ;
2024-05-24 01:45:04 +02:00
2024-04-12 12:32:06 +01:00
if ( switchOutTarget . hp ) {
user . scene . pushPhase ( new BattleEndPhase ( user . scene ) ) ;
user . scene . pushPhase ( new NewBattlePhase ( user . scene ) ) ;
}
}
}
2024-05-24 01:45:04 +02:00
2024-04-12 12:32:06 +01:00
resolve ( true ) ;
} ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-05 07:52:27 -07:00
2024-05-23 17:03:10 +02:00
getCondition ( ) : MoveConditionFunc {
2024-05-05 07:52:27 -07:00
return ( user , target , move ) = > ( move . category !== MoveCategory . STATUS || this . getSwitchOutCondition ( ) ( user , target , move ) ) ;
}
getFailedText ( user : Pokemon , target : Pokemon , move : Move , cancelled : Utils.BooleanHolder ) : string | null {
2024-05-05 10:54:22 -07:00
const blockedByAbility = new Utils . BooleanHolder ( false ) ;
applyAbAttrs ( ForceSwitchOutImmunityAbAttr , target , blockedByAbility ) ;
2024-05-23 17:03:10 +02:00
return blockedByAbility . value ? getPokemonMessage ( target , " can't be switched out!" ) : null ;
2023-12-30 22:01:46 -05:00
}
2024-01-07 23:17:24 -05:00
getSwitchOutCondition ( ) : MoveConditionFunc {
2023-12-10 17:57:12 -05:00
return ( user , target , move ) = > {
2023-11-28 08:43:21 -05:00
const switchOutTarget = ( this . user ? user : target ) ;
const player = switchOutTarget instanceof PlayerPokemon ;
2024-05-24 01:45:04 +02:00
2024-05-23 17:03:10 +02:00
if ( ! this . user && move . category === MoveCategory . STATUS && ( target . hasAbilityWithAttr ( ForceSwitchOutImmunityAbAttr ) || target . isMax ( ) ) ) {
2024-05-05 07:52:27 -07:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-11-28 08:43:21 -05:00
if ( ! player && ! user . scene . currentBattle . battleType ) {
2024-05-23 17:03:10 +02:00
if ( this . batonPass ) {
2023-11-28 08:43:21 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-11-28 08:43:21 -05:00
// Don't allow wild opponents to flee on the boss stage since it can ruin a run early on
2024-05-23 17:03:10 +02:00
if ( ! ( user . scene . currentBattle . waveIndex % 10 ) ) {
2023-11-28 08:43:21 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-11-28 08:43:21 -05:00
}
const party = player ? user . scene . getParty ( ) : user . scene . getEnemyParty ( ) ;
2024-06-09 09:05:18 +10:00
return ( ! player && ! user . scene . currentBattle . battleType ) || party . filter ( p = > p . isAllowedInBattle ( ) && ( player || ( p as EnemyPokemon ) . trainerSlot === ( switchOutTarget as EnemyPokemon ) . trainerSlot ) ) . length > user . scene . currentBattle . getBattlerCount ( ) ;
2023-11-28 08:43:21 -05:00
} ;
2023-10-31 14:09:33 -04:00
}
2024-01-15 00:20:26 -05:00
2024-01-15 23:29:22 -05:00
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
2024-05-23 17:03:10 +02:00
if ( ! user . scene . getEnemyParty ( ) . find ( p = > p . isActive ( ) && ! p . isOnField ( ) ) ) {
2024-04-03 12:14:26 -04:00
return - 20 ;
2024-05-23 17:03:10 +02:00
}
2024-04-03 12:14:26 -04:00
let ret = this . user ? Math . floor ( ( 1 - user . getHpRatio ( ) ) * 20 ) : super . getUserBenefitScore ( user , target , move ) ;
if ( this . user && this . batonPass ) {
const battleStatTotal = user . summonData . battleStats . reduce ( ( bs : integer , total : integer ) = > total += bs , 0 ) ;
2024-05-23 17:03:10 +02:00
ret = ret / 2 + ( Phaser . Tweens . Builders . GetEaseFunction ( "Sine.easeOut" ) ( Math . min ( Math . abs ( battleStatTotal ) , 10 ) / 10 ) * ( battleStatTotal >= 0 ? 10 : - 10 ) ) ;
2024-04-03 12:14:26 -04:00
}
return ret ;
2024-01-15 00:20:26 -05:00
}
2023-10-31 14:09:33 -04:00
}
2024-04-16 15:07:38 -04:00
export class RemoveTypeAttr extends MoveEffectAttr {
private removedType : Type ;
private messageCallback : ( ( user : Pokemon ) = > void ) | undefined ;
constructor ( removedType : Type , messageCallback ? : ( user : Pokemon ) = > void ) {
super ( true , MoveEffectTrigger . POST_APPLY ) ;
this . removedType = removedType ;
this . messageCallback = messageCallback ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-16 15:07:38 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-16 15:07:38 -04:00
2024-05-24 02:19:20 +02:00
if ( user . isTerastallized && user . getTeraType ( ) === this . removedType ) { // active tera types cannot be removed
2024-04-16 15:07:38 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-16 15:07:38 -04:00
2024-05-23 17:03:10 +02:00
const userTypes = user . getTypes ( true ) ;
2024-04-16 15:07:38 -04:00
const modifiedTypes = userTypes . filter ( type = > type !== this . removedType ) ;
user . summonData . types = modifiedTypes ;
2024-04-20 03:32:40 +10:00
user . updateInfo ( ) ;
2024-04-16 15:07:38 -04:00
if ( this . messageCallback ) {
this . messageCallback ( user ) ;
}
return true ;
}
}
2023-04-21 19:30:04 -04:00
export class CopyTypeAttr extends MoveEffectAttr {
constructor ( ) {
super ( true ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-21 19:30:04 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
2024-02-17 00:40:03 -05:00
user . summonData . types = target . getTypes ( true ) ;
2024-04-20 03:32:40 +10:00
user . updateInfo ( ) ;
2023-04-21 19:30:04 -04:00
user . scene . queueMessage ( getPokemonMessage ( user , ` 's type \ nchanged to match ${ target . name } 's! ` ) ) ;
return true ;
}
2024-04-20 03:32:40 +10:00
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > target . getTypes ( ) [ 0 ] !== Type . UNKNOWN ;
}
2023-04-21 19:30:04 -04:00
}
export class CopyBiomeTypeAttr extends MoveEffectAttr {
constructor ( ) {
super ( true ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-21 19:30:04 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
const biomeType = user . scene . arena . getTypeForBiome ( ) ;
user . summonData . types = [ biomeType ] ;
2024-04-20 03:32:40 +10:00
user . updateInfo ( ) ;
2023-04-21 19:30:04 -04:00
2023-10-18 18:01:15 -04:00
user . scene . queueMessage ( getPokemonMessage ( user , ` transformed \ ninto the ${ Utils . toReadableString ( Type [ biomeType ] ) } type! ` ) ) ;
2023-04-21 19:30:04 -04:00
return true ;
}
2023-04-13 12:16:36 -04:00
}
2024-04-20 03:32:40 +10:00
export class ChangeTypeAttr extends MoveEffectAttr {
private type : Type ;
constructor ( type : Type ) {
super ( false , MoveEffectTrigger . HIT ) ;
this . type = type ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
target . summonData . types = [ this . type ] ;
target . updateInfo ( ) ;
user . scene . queueMessage ( getPokemonMessage ( target , ` transformed \ ninto the ${ Utils . toReadableString ( Type [ this . type ] ) } type! ` ) ) ;
return true ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > ! target . isTerastallized ( ) && ! target . hasAbility ( Abilities . MULTITYPE ) && ! target . hasAbility ( Abilities . RKS_SYSTEM ) && ! ( target . getTypes ( ) . length === 1 && target . getTypes ( ) [ 0 ] === this . type ) ;
}
}
export class AddTypeAttr extends MoveEffectAttr {
private type : Type ;
constructor ( type : Type ) {
super ( false , MoveEffectTrigger . HIT ) ;
this . type = type ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const types = target . getTypes ( ) . slice ( 0 , 2 ) . filter ( t = > t !== Type . UNKNOWN ) ; // TODO: Figure out some way to actually check if another version of this effect is already applied
types . push ( this . type ) ;
target . summonData . types = types ;
target . updateInfo ( ) ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( ` ${ Utils . toReadableString ( Type [ this . type ] ) } was added to \ n ` + getPokemonMessage ( target , "!" ) ) ;
2024-04-20 03:32:40 +10:00
return true ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > ! target . isTerastallized ( ) && ! target . getTypes ( ) . includes ( this . type ) ;
}
}
2024-03-11 22:57:07 +01:00
export class FirstMoveTypeAttr extends MoveEffectAttr {
constructor ( ) {
super ( true ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-03-11 22:57:07 +01:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-03-11 22:57:07 +01:00
2024-05-23 17:03:10 +02:00
const firstMoveType = target . getMoveset ( ) [ 0 ] . getMove ( ) . type ;
2024-05-24 01:45:04 +02:00
2024-03-11 22:57:07 +01:00
user . summonData . types = [ firstMoveType ] ;
2024-03-11 18:13:07 -04:00
user . scene . queueMessage ( getPokemonMessage ( user , ` transformed \ ninto to the ${ Utils . toReadableString ( Type [ firstMoveType ] ) } type! ` ) ) ;
2024-03-11 22:57:07 +01:00
return true ;
}
}
2023-04-17 00:46:50 -04:00
export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr {
2023-04-27 20:12:25 -04:00
private enemyMoveset : boolean ;
constructor ( enemyMoveset? : boolean ) {
super ( ) ;
this . enemyMoveset = enemyMoveset ;
}
2023-04-16 18:40:32 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-05-06 00:42:01 -04:00
const moveset = ( ! this . enemyMoveset ? user : target ) . getMoveset ( ) ;
2023-04-27 20:12:25 -04:00
const moves = moveset . filter ( m = > ! m . getMove ( ) . hasFlag ( MoveFlags . IGNORE_VIRTUAL ) ) ;
2023-04-16 18:40:32 -04:00
if ( moves . length ) {
2024-01-02 21:31:59 -05:00
const move = moves [ user . randSeedInt ( moves . length ) ] ;
2023-04-27 20:12:25 -04:00
const moveIndex = moveset . findIndex ( m = > m . moveId === move . moveId ) ;
2023-05-18 11:11:06 -04:00
const moveTargets = getMoveTargets ( user , move . moveId ) ;
2024-05-23 17:03:10 +02:00
if ( ! moveTargets . targets . length ) {
2023-05-18 11:11:06 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-30 09:47:10 -06:00
let selectTargets : BattlerIndex [ ] ;
switch ( true ) {
2024-05-23 17:03:10 +02:00
case ( moveTargets . multiple || moveTargets . targets . length === 1 ) : {
selectTargets = moveTargets . targets ;
break ;
}
case ( moveTargets . targets . indexOf ( target . getBattlerIndex ( ) ) > - 1 ) : {
selectTargets = [ target . getBattlerIndex ( ) ] ;
break ;
}
default : {
moveTargets . targets . splice ( moveTargets . targets . indexOf ( user . getAlly ( ) . getBattlerIndex ( ) ) ) ;
selectTargets = [ moveTargets . targets [ user . randSeedInt ( moveTargets . targets . length ) ] ] ;
break ;
}
2024-05-24 01:45:04 +02:00
}
const targets = selectTargets ;
2024-04-18 22:49:07 +03:00
user . getMoveQueue ( ) . push ( { move : move.moveId , targets : targets , ignorePP : true } ) ;
2023-05-18 11:11:06 -04:00
user . scene . unshiftPhase ( new MovePhase ( user . scene , user , targets , moveset [ moveIndex ] , true ) ) ;
2023-04-16 18:40:32 -04:00
return true ;
}
return false ;
}
}
2023-04-17 00:46:50 -04:00
export class RandomMoveAttr extends OverrideMoveEffectAttr {
2023-04-16 00:29:55 -04:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
2023-04-13 23:04:51 -04:00
return new Promise ( resolve = > {
2024-05-23 17:03:10 +02:00
const moveIds = Utils . getEnumValues ( Moves ) . filter ( m = > ! allMoves [ m ] . hasFlag ( MoveFlags . IGNORE_VIRTUAL ) && ! allMoves [ m ] . name . endsWith ( " (N)" ) ) ;
2024-01-02 21:31:59 -05:00
const moveId = moveIds [ user . randSeedInt ( moveIds . length ) ] ;
2024-05-24 01:45:04 +02:00
2023-05-18 11:11:06 -04:00
const moveTargets = getMoveTargets ( user , moveId ) ;
if ( ! moveTargets . targets . length ) {
resolve ( false ) ;
return ;
}
const targets = moveTargets . multiple || moveTargets . targets . length === 1
? moveTargets . targets
: moveTargets . targets . indexOf ( target . getBattlerIndex ( ) ) > - 1
? [ target . getBattlerIndex ( ) ]
2024-01-02 21:31:59 -05:00
: [ moveTargets . targets [ user . randSeedInt ( moveTargets . targets . length ) ] ] ;
2023-05-18 11:11:06 -04:00
user . getMoveQueue ( ) . push ( { move : moveId , targets : targets , ignorePP : true } ) ;
user . scene . unshiftPhase ( new MovePhase ( user . scene , user , targets , new PokemonMove ( moveId , 0 , 0 , true ) , true ) ) ;
2024-04-23 22:00:23 -04:00
initMoveAnim ( user . scene , moveId ) . then ( ( ) = > {
2023-04-16 00:29:55 -04:00
loadMoveAnimAssets ( user . scene , [ moveId ] , true )
2023-04-13 23:04:51 -04:00
. then ( ( ) = > resolve ( true ) ) ;
} ) ;
} ) ;
}
}
2024-04-14 17:43:03 -04:00
export class NaturePowerAttr extends OverrideMoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise ( resolve = > {
2024-05-23 17:03:10 +02:00
let moveId ;
2024-04-14 17:43:03 -04:00
switch ( user . scene . arena . getTerrainType ( ) ) {
2024-05-23 17:03:10 +02:00
// this allows terrains to 'override' the biome move
case TerrainType . NONE :
switch ( user . scene . arena . biomeType ) {
case Biome . TOWN :
moveId = Moves . ROUND ;
break ;
case Biome . METROPOLIS :
moveId = Moves . TRI_ATTACK ;
2024-04-14 17:43:03 -04:00
break ;
2024-05-23 17:03:10 +02:00
case Biome . SLUM :
moveId = Moves . SLUDGE_BOMB ;
2024-04-14 17:43:03 -04:00
break ;
2024-05-23 17:03:10 +02:00
case Biome . PLAINS :
moveId = Moves . SILVER_WIND ;
2024-04-14 17:43:03 -04:00
break ;
2024-05-23 17:03:10 +02:00
case Biome . GRASS :
moveId = Moves . GRASS_KNOT ;
2024-04-14 17:43:03 -04:00
break ;
2024-05-23 17:03:10 +02:00
case Biome . TALL_GRASS :
moveId = Moves . POLLEN_PUFF ;
2024-04-14 17:43:03 -04:00
break ;
2024-05-23 17:03:10 +02:00
case Biome . MEADOW :
moveId = Moves . GIGA_DRAIN ;
break ;
case Biome . FOREST :
moveId = Moves . BUG_BUZZ ;
break ;
case Biome . JUNGLE :
moveId = Moves . LEAF_STORM ;
break ;
case Biome . SEA :
moveId = Moves . HYDRO_PUMP ;
break ;
case Biome . SWAMP :
moveId = Moves . MUD_BOMB ;
break ;
case Biome . BEACH :
moveId = Moves . SCALD ;
break ;
case Biome . LAKE :
moveId = Moves . BUBBLE_BEAM ;
break ;
case Biome . SEABED :
moveId = Moves . BRINE ;
2024-04-14 17:43:03 -04:00
break ;
2024-05-23 17:03:10 +02:00
case Biome . ISLAND :
moveId = Moves . LEAF_TORNADO ;
break ;
case Biome . MOUNTAIN :
moveId = Moves . AIR_SLASH ;
break ;
case Biome . BADLANDS :
moveId = Moves . EARTH_POWER ;
break ;
case Biome . DESERT :
moveId = Moves . SCORCHING_SANDS ;
break ;
case Biome . WASTELAND :
moveId = Moves . DRAGON_PULSE ;
break ;
case Biome . CONSTRUCTION_SITE :
moveId = Moves . STEEL_BEAM ;
break ;
case Biome . CAVE :
moveId = Moves . POWER_GEM ;
break ;
case Biome . ICE_CAVE :
moveId = Moves . ICE_BEAM ;
break ;
case Biome . SNOWY_FOREST :
moveId = Moves . FROST_BREATH ;
break ;
case Biome . VOLCANO :
moveId = Moves . LAVA_PLUME ;
break ;
case Biome . GRAVEYARD :
moveId = Moves . SHADOW_BALL ;
break ;
case Biome . RUINS :
moveId = Moves . ANCIENT_POWER ;
break ;
case Biome . TEMPLE :
moveId = Moves . EXTRASENSORY ;
break ;
case Biome . DOJO :
moveId = Moves . FOCUS_BLAST ;
break ;
case Biome . FAIRY_CAVE :
moveId = Moves . ALLURING_VOICE ;
break ;
case Biome . ABYSS :
moveId = Moves . OMINOUS_WIND ;
break ;
case Biome . SPACE :
moveId = Moves . DRACO_METEOR ;
break ;
case Biome . FACTORY :
moveId = Moves . FLASH_CANNON ;
break ;
case Biome . LABORATORY :
moveId = Moves . ZAP_CANNON ;
break ;
case Biome . POWER_PLANT :
moveId = Moves . CHARGE_BEAM ;
break ;
case Biome . END :
moveId = Moves . ETERNABEAM ;
break ;
}
break ;
case TerrainType . MISTY :
moveId = Moves . MOONBLAST ;
break ;
case TerrainType . ELECTRIC :
moveId = Moves . THUNDERBOLT ;
break ;
case TerrainType . GRASSY :
moveId = Moves . ENERGY_BALL ;
break ;
case TerrainType . PSYCHIC :
moveId = Moves . PSYCHIC ;
break ;
default :
// Just in case there's no match
moveId = Moves . TRI_ATTACK ;
break ;
2024-04-14 17:43:03 -04:00
}
2024-05-24 01:45:04 +02:00
2024-04-14 18:25:15 -04:00
user . getMoveQueue ( ) . push ( { move : moveId , targets : [ target . getBattlerIndex ( ) ] , ignorePP : true } ) ;
user . scene . unshiftPhase ( new MovePhase ( user . scene , user , [ target . getBattlerIndex ( ) ] , new PokemonMove ( moveId , 0 , 0 , true ) , true ) ) ;
2024-04-23 22:00:23 -04:00
initMoveAnim ( user . scene , moveId ) . then ( ( ) = > {
2024-04-14 17:43:03 -04:00
loadMoveAnimAssets ( user . scene , [ moveId ] , true )
. then ( ( ) = > resolve ( true ) ) ;
} ) ;
} ) ;
}
}
2024-01-07 23:17:24 -05:00
const lastMoveCopiableCondition : MoveConditionFunc = ( user , target , move ) = > {
2023-10-09 20:20:02 -04:00
const copiableMove = user . scene . currentBattle . lastMove ;
2023-04-21 19:30:04 -04:00
2024-05-23 17:03:10 +02:00
if ( ! copiableMove ) {
2023-10-09 20:20:02 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
2024-05-31 20:50:30 -04:00
if ( allMoves [ copiableMove ] . hasAttr ( ChargeAttr ) ) {
2023-10-09 20:20:02 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
2023-10-09 20:20:02 -04:00
// TODO: Add last turn of Bide
2023-04-21 19:30:04 -04:00
2023-10-09 20:20:02 -04:00
return true ;
2023-04-21 19:30:04 -04:00
} ;
export class CopyMoveAttr extends OverrideMoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2023-10-09 20:20:02 -04:00
const lastMove = user . scene . currentBattle . lastMove ;
2023-04-21 19:30:04 -04:00
2023-10-09 20:20:02 -04:00
const moveTargets = getMoveTargets ( user , lastMove ) ;
2024-05-23 17:03:10 +02:00
if ( ! moveTargets . targets . length ) {
2023-05-18 11:11:06 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-05-18 11:11:06 -04:00
const targets = moveTargets . multiple || moveTargets . targets . length === 1
? moveTargets . targets
: moveTargets . targets . indexOf ( target . getBattlerIndex ( ) ) > - 1
? [ target . getBattlerIndex ( ) ]
2024-01-02 21:31:59 -05:00
: [ moveTargets . targets [ user . randSeedInt ( moveTargets . targets . length ) ] ] ;
2023-10-09 20:20:02 -04:00
user . getMoveQueue ( ) . push ( { move : lastMove , targets : targets , ignorePP : true } ) ;
2023-05-18 11:11:06 -04:00
2023-10-09 20:20:02 -04:00
user . scene . unshiftPhase ( new MovePhase ( user . scene , user as PlayerPokemon , targets , new PokemonMove ( lastMove , 0 , 0 , true ) , true ) ) ;
2023-04-21 19:30:04 -04:00
return true ;
}
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-10-09 20:20:02 -04:00
return lastMoveCopiableCondition ;
2023-04-24 14:30:21 -04:00
}
}
2023-04-21 19:30:04 -04:00
2024-03-11 15:40:56 -04:00
export class ReducePpMoveAttr extends MoveEffectAttr {
2024-03-11 18:18:49 +01:00
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-03-11 15:40:56 -04:00
// Null checks can be skipped due to condition function
const lastMove = target . getLastXMoves ( ) . find ( ( ) = > true ) ;
const movesetMove = target . getMoveset ( ) . find ( m = > m . moveId === lastMove . move ) ;
const lastPpUsed = movesetMove . ppUsed ;
movesetMove . ppUsed = Math . min ( movesetMove . ppUsed + 4 , movesetMove . getMovePp ( ) ) ;
user . scene . queueMessage ( ` It reduced the PP of ${ getPokemonMessage ( target , ` 's \ n ${ movesetMove . getName ( ) } by ${ movesetMove . ppUsed - lastPpUsed } ! ` ) } ` ) ;
2024-03-11 18:18:49 +01:00
2024-03-11 15:40:56 -04:00
return true ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > {
const lastMove = target . getLastXMoves ( ) . find ( ( ) = > true ) ;
if ( lastMove ) {
const movesetMove = target . getMoveset ( ) . find ( m = > m . moveId === lastMove . move ) ;
return ! ! movesetMove ? . getPpRatio ( ) ;
}
2024-03-11 18:18:49 +01:00
return false ;
2024-03-11 15:40:56 -04:00
} ;
}
2024-03-11 18:18:49 +01:00
2024-03-11 15:40:56 -04:00
getTargetBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : number {
const lastMove = target . getLastXMoves ( ) . find ( ( ) = > true ) ;
if ( lastMove ) {
const movesetMove = target . getMoveset ( ) . find ( m = > m . moveId === lastMove . move ) ;
if ( movesetMove ) {
const maxPp = movesetMove . getMovePp ( ) ;
const ppLeft = maxPp - movesetMove . ppUsed ;
const value = - ( 8 - Math . ceil ( Math . min ( maxPp , 30 ) / 5 ) ) ;
2024-05-23 17:03:10 +02:00
if ( ppLeft < 4 ) {
2024-03-11 15:40:56 -04:00
return ( value / 4 ) * ppLeft ;
2024-05-23 17:03:10 +02:00
}
2024-03-11 15:40:56 -04:00
return value ;
}
}
2024-03-11 18:18:49 +01:00
2024-03-11 15:40:56 -04:00
return 0 ;
2024-03-11 18:18:49 +01:00
}
}
2023-10-09 20:20:02 -04:00
// TODO: Review this
2024-01-07 23:17:24 -05:00
const targetMoveCopiableCondition : MoveConditionFunc = ( user , target , move ) = > {
2023-10-09 20:20:02 -04:00
const targetMoves = target . getMoveHistory ( ) . filter ( m = > ! m . virtual ) ;
2024-05-23 17:03:10 +02:00
if ( ! targetMoves . length ) {
2023-11-16 00:58:57 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-10-09 20:20:02 -04:00
2023-11-16 00:58:57 -05:00
const copiableMove = targetMoves [ 0 ] ;
2023-10-09 20:20:02 -04:00
2024-05-23 17:03:10 +02:00
if ( ! copiableMove . move ) {
2023-11-16 00:58:57 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-10-09 20:20:02 -04:00
2024-05-31 20:50:30 -04:00
if ( allMoves [ copiableMove . move ] . hasAttr ( ChargeAttr ) && copiableMove . result === MoveResult . OTHER ) {
2023-11-16 00:58:57 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-10-09 20:20:02 -04:00
2024-05-23 17:03:10 +02:00
// TODO: Add last turn of Bide
2023-10-09 20:20:02 -04:00
2024-05-23 17:03:10 +02:00
return true ;
2023-10-09 20:20:02 -04:00
} ;
2023-05-06 00:42:01 -04:00
export class MovesetCopyMoveAttr extends OverrideMoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const targetMoves = target . getMoveHistory ( ) . filter ( m = > ! m . virtual ) ;
2024-05-23 17:03:10 +02:00
if ( ! targetMoves . length ) {
2023-05-06 00:42:01 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-05-06 00:42:01 -04:00
const copiedMove = allMoves [ targetMoves [ 0 ] . move ] ;
const thisMoveIndex = user . getMoveset ( ) . findIndex ( m = > m . moveId === move . id ) ;
2024-05-23 17:03:10 +02:00
if ( thisMoveIndex === - 1 ) {
2023-05-06 00:42:01 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-05-06 00:42:01 -04:00
user . summonData . moveset = user . getMoveset ( ) . slice ( 0 ) ;
user . summonData . moveset [ thisMoveIndex ] = new PokemonMove ( copiedMove . id , 0 , 0 ) ;
user . scene . queueMessage ( getPokemonMessage ( user , ` copied \ n ${ copiedMove . name } ! ` ) ) ;
return true ;
}
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-05-06 00:42:01 -04:00
return targetMoveCopiableCondition ;
}
}
2023-04-21 19:30:04 -04:00
export class SketchAttr extends MoveEffectAttr {
constructor ( ) {
super ( true ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-04-21 19:30:04 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
const targetMoves = target . getMoveHistory ( ) . filter ( m = > ! m . virtual ) ;
2024-05-23 17:03:10 +02:00
if ( ! targetMoves . length ) {
2023-04-21 19:30:04 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
const sketchedMove = allMoves [ targetMoves [ 0 ] . move ] ;
2023-05-06 00:42:01 -04:00
const sketchIndex = user . getMoveset ( ) . findIndex ( m = > m . moveId === move . id ) ;
2023-04-21 19:30:04 -04:00
2024-05-23 17:03:10 +02:00
if ( sketchIndex === - 1 ) {
2023-04-21 19:30:04 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
2023-05-06 00:42:01 -04:00
user . setMove ( sketchIndex , sketchedMove . id ) ;
2023-04-21 19:30:04 -04:00
user . scene . queueMessage ( getPokemonMessage ( user , ` sketched \ n ${ sketchedMove . name } ! ` ) ) ;
return true ;
}
2023-04-24 14:30:21 -04:00
2024-01-07 23:17:24 -05:00
getCondition ( ) : MoveConditionFunc {
2023-12-10 17:57:12 -05:00
return ( user , target , move ) = > {
2024-05-23 17:03:10 +02:00
if ( ! targetMoveCopiableCondition ( user , target , move ) ) {
2023-04-24 14:30:21 -04:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2023-04-24 14:30:21 -04:00
const targetMoves = target . getMoveHistory ( ) . filter ( m = > ! m . virtual ) ;
2024-05-23 17:03:10 +02:00
if ( ! targetMoves . length ) {
2023-11-16 00:58:57 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2023-11-16 00:58:57 -05:00
const sketchableMove = targetMoves [ 0 ] ;
2024-05-24 01:45:04 +02:00
2024-05-23 17:03:10 +02:00
if ( user . getMoveset ( ) . find ( m = > m . moveId === sketchableMove . move ) ) {
2023-11-16 00:58:57 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-24 01:45:04 +02:00
2023-11-16 00:58:57 -05:00
return true ;
2023-04-24 14:30:21 -04:00
} ;
}
2023-04-21 19:30:04 -04:00
}
2024-04-14 13:21:34 +10:00
export class AbilityChangeAttr extends MoveEffectAttr {
public ability : Abilities ;
constructor ( ability : Abilities , selfTarget? : boolean ) {
super ( selfTarget , MoveEffectTrigger . HIT ) ;
this . ability = ability ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-14 13:21:34 +10:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-14 13:21:34 +10:00
( this . selfTarget ? user : target ) . summonData . ability = this . ability ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( "The " + getPokemonMessage ( ( this . selfTarget ? user : target ) , ` acquired \ n ${ allAbilities [ this . ability ] . name } ! ` ) ) ;
2024-04-14 13:21:34 +10:00
return true ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > ! ( this . selfTarget ? user : target ) . getAbility ( ) . hasAttr ( UnsuppressableAbilityAbAttr ) && ( this . selfTarget ? user : target ) . getAbility ( ) . id !== this . ability ;
}
}
export class AbilityCopyAttr extends MoveEffectAttr {
public copyToPartner : boolean ;
constructor ( copyToPartner : boolean = false ) {
super ( false , MoveEffectTrigger . HIT ) ;
this . copyToPartner = copyToPartner ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-14 13:21:34 +10:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-14 13:21:34 +10:00
user . summonData . ability = target . getAbility ( ) . id ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( user , " copied the " ) + getPokemonMessage ( target , ` 's \ n ${ allAbilities [ target . getAbility ( ) . id ] . name } ! ` ) ) ;
2024-05-24 01:45:04 +02:00
2024-04-14 13:21:34 +10:00
if ( this . copyToPartner && user . scene . currentBattle ? . double && user . getAlly ( ) . hp ) {
user . getAlly ( ) . summonData . ability = target . getAbility ( ) . id ;
2024-05-23 17:03:10 +02:00
user . getAlly ( ) . scene . queueMessage ( getPokemonMessage ( user . getAlly ( ) , " copied the " ) + getPokemonMessage ( target , ` 's \ n ${ allAbilities [ target . getAbility ( ) . id ] . name } ! ` ) ) ;
2024-04-14 13:21:34 +10:00
}
return true ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > {
let ret = ! target . getAbility ( ) . hasAttr ( UncopiableAbilityAbAttr ) && ! user . getAbility ( ) . hasAttr ( UnsuppressableAbilityAbAttr ) ;
2024-05-23 17:03:10 +02:00
if ( this . copyToPartner && user . scene . currentBattle ? . double ) {
2024-04-14 13:21:34 +10:00
ret = ret && ( ! user . getAlly ( ) . hp || ! user . getAlly ( ) . getAbility ( ) . hasAttr ( UnsuppressableAbilityAbAttr ) ) ;
2024-05-23 17:03:10 +02:00
} else {
2024-04-14 13:21:34 +10:00
ret = ret && user . getAbility ( ) . id !== target . getAbility ( ) . id ;
2024-05-23 17:03:10 +02:00
}
2024-04-14 13:21:34 +10:00
return ret ;
} ;
}
}
export class AbilityGiveAttr extends MoveEffectAttr {
public copyToPartner : boolean ;
constructor ( ) {
super ( false , MoveEffectTrigger . HIT ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-04-14 13:21:34 +10:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-04-14 13:21:34 +10:00
target . summonData . ability = user . getAbility ( ) . id ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( "The" + getPokemonMessage ( target , ` \ nacquired ${ allAbilities [ user . getAbility ( ) . id ] . name } ! ` ) ) ;
2024-04-14 13:21:34 +10:00
return true ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > ! user . getAbility ( ) . hasAttr ( UncopiableAbilityAbAttr ) && ! target . getAbility ( ) . hasAttr ( UnsuppressableAbilityAbAttr ) && user . getAbility ( ) . id !== target . getAbility ( ) . id ;
}
}
2024-03-04 21:32:11 -05:00
export class SwitchAbilitiesAttr extends MoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-03-04 21:32:11 -05:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-03-04 21:32:11 -05:00
const tempAbilityId = user . getAbility ( ) . id ;
user . summonData . ability = target . getAbility ( ) . id ;
target . summonData . ability = tempAbilityId ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( user , " swapped\nabilities with its target!" ) ) ;
2024-03-04 21:32:11 -05:00
return true ;
}
getCondition ( ) : MoveConditionFunc {
2024-04-13 11:08:32 +10:00
return ( user , target , move ) = > ! user . getAbility ( ) . hasAttr ( UnswappableAbilityAbAttr ) && ! target . getAbility ( ) . hasAttr ( UnswappableAbilityAbAttr ) ;
2024-03-04 21:32:11 -05:00
}
}
2024-05-02 14:22:30 +10:00
export class SuppressAbilitiesAttr extends MoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2024-05-02 14:22:30 +10:00
return false ;
2024-05-23 17:03:10 +02:00
}
2024-05-02 14:22:30 +10:00
target . summonData . abilitySuppressed = true ;
2024-06-10 21:17:28 -04:00
target . scene . queueMessage ( getPokemonMessage ( target , "'s ability\nwas suppressed!" ) ) ;
2024-05-02 14:22:30 +10:00
return true ;
}
getCondition ( ) : MoveConditionFunc {
return ( user , target , move ) = > ! target . getAbility ( ) . hasAttr ( UnsuppressableAbilityAbAttr ) ;
}
}
2024-06-10 21:17:28 -04:00
/ * *
* Applies the effects of { @linkcode SuppressAbilitiesAttr } if the target has already moved this turn .
* @extends MoveEffectAttr
* @see { @linkcode Moves . CORE_ENFORCER } ( the move which uses this effect )
* /
export class SuppressAbilitiesIfActedAttr extends MoveEffectAttr {
/ * *
* If the target has already acted this turn , apply a { @linkcode SuppressAbilitiesAttr } effect unless the
* abillity cannot be suppressed . This is a secondary effect and has no bearing on the success or failure of the move .
*
* @returns True if the move occurred , otherwise false . Note that true will be returned even if the target has not
* yet moved or if the target ' s abiilty is un - suppressable .
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
if ( ! super . apply ( user , target , move , args ) ) {
return false ;
}
if ( target . turnData . acted ) {
const suppressAttr = new SuppressAbilitiesAttr ( ) ;
if ( suppressAttr . getCondition ( ) ( user , target , move ) ) {
suppressAttr . apply ( user , target , move , args ) ;
}
}
return true ;
}
}
2023-10-29 01:28:56 -04:00
export class TransformAttr extends MoveEffectAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < boolean > {
return new Promise ( resolve = > {
2024-05-23 17:03:10 +02:00
if ( ! super . apply ( user , target , move , args ) ) {
2023-10-29 01:28:56 -04:00
return resolve ( false ) ;
2024-05-23 17:03:10 +02:00
}
2023-10-29 01:28:56 -04:00
user . summonData . speciesForm = target . getSpeciesForm ( ) ;
2023-11-24 15:12:26 -05:00
user . summonData . fusionSpeciesForm = target . getFusionSpeciesForm ( ) ;
2024-04-14 12:23:49 -04:00
user . summonData . ability = target . getAbility ( ) . id ;
2023-10-29 01:28:56 -04:00
user . summonData . gender = target . getGender ( ) ;
2023-11-24 15:12:26 -05:00
user . summonData . fusionGender = target . getFusionGender ( ) ;
2023-10-29 01:28:56 -04:00
user . summonData . stats = [ user . stats [ Stat . HP ] ] . concat ( target . stats . slice ( 1 ) ) ;
user . summonData . battleStats = target . summonData . battleStats . slice ( 0 ) ;
user . summonData . moveset = target . getMoveset ( ) . map ( m = > new PokemonMove ( m . moveId , m . ppUsed , m . ppUp ) ) ;
user . summonData . types = target . getTypes ( ) ;
user . scene . queueMessage ( getPokemonMessage ( user , ` transformed \ ninto ${ target . name } ! ` ) ) ;
2023-11-24 15:12:26 -05:00
2024-03-27 23:44:11 -04:00
user . loadAssets ( false ) . then ( ( ) = > {
2023-10-29 01:28:56 -04:00
user . playAnim ( ) ;
resolve ( true ) ;
} ) ;
} ) ;
}
}
2024-01-13 12:24:24 -05:00
export class DiscourageFrequentUseAttr extends MoveAttr {
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
const lastMoves = user . getLastXMoves ( 4 ) ;
console . log ( lastMoves ) ;
for ( let m = 0 ; m < lastMoves . length ; m ++ ) {
2024-05-23 17:03:10 +02:00
if ( lastMoves [ m ] . move === move . id ) {
2024-01-13 12:24:24 -05:00
return ( 4 - ( m + 1 ) ) * - 10 ;
2024-05-23 17:03:10 +02:00
}
2024-01-13 12:24:24 -05:00
}
return 0 ;
}
}
2024-04-03 22:52:39 -04:00
export class MoneyAttr extends MoveEffectAttr {
constructor ( ) {
super ( true , MoveEffectTrigger . HIT ) ;
}
apply ( user : Pokemon , target : Pokemon , move : Move ) : boolean {
user . scene . currentBattle . moneyScattered += user . scene . getWaveMoneyAmount ( 0.2 ) ;
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( "Coins were scattered everywhere!" ) ;
2024-04-03 22:52:39 -04:00
return true ;
}
}
2024-05-24 22:23:23 +02:00
/ * *
* Applies { @linkcode BattlerTagType . DESTINY_BOND } to the user .
*
* @extends MoveEffectAttr
* /
export class DestinyBondAttr extends MoveEffectAttr {
constructor ( ) {
super ( true , MoveEffectTrigger . PRE_APPLY ) ;
}
/ * *
* Applies { @linkcode BattlerTagType . DESTINY_BOND } to the user .
* @param user { @linkcode Pokemon } that is having the tag applied to .
* @param target { @linkcode Pokemon } N / A
* @param move { @linkcode Move } { @linkcode Move . DESTINY_BOND }
* @param { any [ ] } args N / A
* @returns true
* /
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
user . scene . queueMessage ( ` ${ getPokemonMessage ( user , " is trying\nto take its foe down with it!" ) } ` ) ;
user . addTag ( BattlerTagType . DESTINY_BOND , undefined , move . id , user . id ) ;
return true ;
}
}
2024-05-01 18:17:12 -04:00
export class LastResortAttr extends MoveAttr {
getCondition ( ) : MoveConditionFunc {
return ( user : Pokemon , target : Pokemon , move : Move ) = > {
const uniqueUsedMoveIds = new Set < Moves > ( ) ;
const movesetMoveIds = user . getMoveset ( ) . map ( m = > m . moveId ) ;
user . getMoveHistory ( ) . map ( m = > {
2024-05-23 17:03:10 +02:00
if ( m . move !== move . id && movesetMoveIds . find ( mm = > mm === m . move ) ) {
2024-05-01 18:17:12 -04:00
uniqueUsedMoveIds . add ( m . move ) ;
2024-05-23 17:03:10 +02:00
}
2024-05-01 18:17:12 -04:00
} ) ;
return uniqueUsedMoveIds . size >= movesetMoveIds . length - 1 ;
} ;
}
}
2024-06-16 04:24:38 +02:00
/ * *
* The move only works if the target has a transferable held item
* @extends MoveAttr
* @see { @linkcode getCondition }
* /
export class AttackedByItemAttr extends MoveAttr {
/ * *
* @returns the { @linkcode MoveConditionFunc } for this { @linkcode Move }
* /
getCondition ( ) : MoveConditionFunc {
return ( user : Pokemon , target : Pokemon , move : Move ) = > {
const heldItems = target . getHeldItems ( ) . filter ( i = > i . getTransferrable ( true ) ) ;
if ( heldItems . length === 0 ) {
return false ;
}
const itemName = heldItems [ 0 ] ? . type ? . name ? ? "item" ;
const attackedByItemString = ` is about to be attacked by its ${ itemName } ! ` ;
target . scene . queueMessage ( getPokemonMessage ( target , attackedByItemString ) ) ;
return true ;
} ;
}
}
2024-05-04 11:52:24 -04:00
export class VariableTargetAttr extends MoveAttr {
private targetChangeFunc : ( user : Pokemon , target : Pokemon , move : Move ) = > number ;
constructor ( targetChange : ( user : Pokemon , target : Pokemon , move : Move ) = > number ) {
super ( ) ;
this . targetChangeFunc = targetChange ;
}
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const targetVal = args [ 0 ] as Utils . NumberHolder ;
targetVal . value = this . targetChangeFunc ( user , target , move ) ;
return true ;
}
}
2024-01-07 23:17:24 -05:00
const failOnGravityCondition : MoveConditionFunc = ( user , target , move ) = > ! user . scene . arena . getTag ( ArenaTagType . GRAVITY ) ;
2023-05-08 18:48:35 -04:00
2024-01-14 20:47:08 -05:00
const failOnBossCondition : MoveConditionFunc = ( user , target , move ) = > ! target . isBossImmune ( ) ;
2024-04-24 01:57:59 +10:00
const failOnMaxCondition : MoveConditionFunc = ( user , target , move ) = > ! target . isMax ( ) ;
2024-04-26 21:44:25 +10:00
const failIfDampCondition : MoveConditionFunc = ( user , target , move ) = > {
const cancelled = new Utils . BooleanHolder ( false ) ;
user . scene . getField ( true ) . map ( p = > applyAbAttrs ( FieldPreventExplosiveMovesAbAttr , p , cancelled ) ) ;
2024-05-05 16:37:43 -05:00
// Queue a message if an ability prevented usage of the move
2024-05-23 17:03:10 +02:00
if ( cancelled . value ) {
2024-05-05 16:37:43 -05:00
user . scene . queueMessage ( getPokemonMessage ( user , ` cannot use ${ move . name } ! ` ) ) ;
2024-05-23 17:03:10 +02:00
}
2024-04-26 21:44:25 +10:00
return ! cancelled . value ;
2024-05-23 17:03:10 +02:00
} ;
2024-04-26 21:44:25 +10:00
2024-05-27 05:01:03 -06:00
const userSleptOrComatoseCondition : MoveConditionFunc = ( user : Pokemon , target : Pokemon , move : Move ) = > user . status ? . effect === StatusEffect . SLEEP || user . hasAbility ( Abilities . COMATOSE ) ;
const targetSleptOrComatoseCondition : MoveConditionFunc = ( user : Pokemon , target : Pokemon , move : Move ) = > target . status ? . effect === StatusEffect . SLEEP || target . hasAbility ( Abilities . COMATOSE ) ;
2023-04-30 00:51:33 -04:00
export type MoveAttrFilter = ( attr : MoveAttr ) = > boolean ;
function applyMoveAttrsInternal ( attrFilter : MoveAttrFilter , user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : Promise < void > {
2023-04-21 19:30:04 -04:00
return new Promise ( resolve = > {
const attrPromises : Promise < boolean > [ ] = [ ] ;
2023-04-30 00:51:33 -04:00
const moveAttrs = move . attrs . filter ( a = > attrFilter ( a ) ) ;
2024-05-23 17:03:10 +02:00
for ( const attr of moveAttrs ) {
2023-04-21 19:30:04 -04:00
const result = attr . apply ( user , target , move , args ) ;
2024-05-23 17:03:10 +02:00
if ( result instanceof Promise ) {
2023-04-21 19:30:04 -04:00
attrPromises . push ( result ) ;
2024-05-23 17:03:10 +02:00
}
2023-04-21 19:30:04 -04:00
}
Promise . allSettled ( attrPromises ) . then ( ( ) = > resolve ( ) ) ;
} ) ;
}
2023-04-30 00:51:33 -04:00
export function applyMoveAttrs ( attrType : { new ( . . . args : any [ ] ) : MoveAttr } , user : Pokemon , target : Pokemon , move : Move , . . . args : any [ ] ) : Promise < void > {
return applyMoveAttrsInternal ( ( attr : MoveAttr ) = > attr instanceof attrType , user , target , move , args ) ;
}
export function applyFilteredMoveAttrs ( attrFilter : MoveAttrFilter , user : Pokemon , target : Pokemon , move : Move , . . . args : any [ ] ) : Promise < void > {
return applyMoveAttrsInternal ( attrFilter , user , target , move , args ) ;
}
2024-01-07 23:17:24 -05:00
export class MoveCondition {
protected func : MoveConditionFunc ;
constructor ( func : MoveConditionFunc ) {
this . func = func ;
}
apply ( user : Pokemon , target : Pokemon , move : Move ) : boolean {
return this . func ( user , target , move ) ;
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return 0 ;
}
}
export class FirstMoveCondition extends MoveCondition {
constructor ( ) {
2024-03-08 13:14:08 -05:00
super ( ( user , target , move ) = > user . battleSummonData ? . turnCount === 1 ) ;
2024-01-07 23:17:24 -05:00
}
getUserBenefitScore ( user : Pokemon , target : Pokemon , move : Move ) : integer {
return this . apply ( user , target , move ) ? 10 : - 20 ;
}
}
2024-05-01 16:14:19 -04:00
export class hitsSameTypeAttr extends VariableMoveTypeMultiplierAttr {
apply ( user : Pokemon , target : Pokemon , move : Move , args : any [ ] ) : boolean {
const multiplier = args [ 0 ] as Utils . NumberHolder ;
2024-05-24 02:19:20 +02:00
if ( ! user . getTypes ( ) . some ( type = > target . getTypes ( ) . includes ( type ) ) ) {
2024-05-01 16:14:19 -04:00
multiplier . value = 0 ;
return true ;
}
return false ;
}
}
const unknownTypeCondition : MoveConditionFunc = ( user , target , move ) = > ! user . getTypes ( ) . includes ( Type . UNKNOWN ) ;
2023-05-18 11:11:06 -04:00
export type MoveTargetSet = {
targets : BattlerIndex [ ] ;
multiple : boolean ;
2024-05-23 17:03:10 +02:00
} ;
2023-05-01 14:41:44 -04:00
2023-05-18 11:11:06 -04:00
export function getMoveTargets ( user : Pokemon , move : Moves ) : MoveTargetSet {
2024-05-04 11:52:24 -04:00
const variableTarget = new Utils . NumberHolder ( 0 ) ;
user . getOpponents ( ) . forEach ( p = > applyMoveAttrs ( VariableTargetAttr , user , p , allMoves [ move ] , variableTarget ) ) ;
2024-05-31 20:50:30 -04:00
const moveTarget = allMoves [ move ] . hasAttr ( VariableTargetAttr ) ? variableTarget.value : move ? allMoves [ move ] . moveTarget : move === undefined ? MoveTarget . NEAR_ENEMY : [ ] ;
2023-05-18 11:11:06 -04:00
const opponents = user . getOpponents ( ) ;
2024-05-24 01:45:04 +02:00
2023-10-31 14:09:33 -04:00
let set : Pokemon [ ] = [ ] ;
2023-05-18 11:11:06 -04:00
let multiple = false ;
2023-05-01 14:41:44 -04:00
switch ( moveTarget ) {
2024-05-23 17:03:10 +02:00
case MoveTarget . USER :
case MoveTarget . PARTY :
set = [ user ] ;
break ;
case MoveTarget . NEAR_OTHER :
case MoveTarget . OTHER :
case MoveTarget . ALL_NEAR_OTHERS :
case MoveTarget . ALL_OTHERS :
set = ( opponents . concat ( [ user . getAlly ( ) ] ) ) ;
multiple = moveTarget === MoveTarget . ALL_NEAR_OTHERS || moveTarget === MoveTarget . ALL_OTHERS ;
break ;
case MoveTarget . NEAR_ENEMY :
case MoveTarget . ALL_NEAR_ENEMIES :
case MoveTarget . ALL_ENEMIES :
case MoveTarget . ENEMY_SIDE :
set = opponents ;
multiple = moveTarget !== MoveTarget . NEAR_ENEMY ;
break ;
case MoveTarget . RANDOM_NEAR_ENEMY :
set = [ opponents [ user . randSeedInt ( opponents . length ) ] ] ;
break ;
case MoveTarget . ATTACKER :
return { targets : [ - 1 as BattlerIndex ] , multiple : false } ;
case MoveTarget . NEAR_ALLY :
case MoveTarget . ALLY :
set = [ user . getAlly ( ) ] ;
break ;
case MoveTarget . USER_OR_NEAR_ALLY :
case MoveTarget . USER_AND_ALLIES :
case MoveTarget . USER_SIDE :
set = [ user , user . getAlly ( ) ] ;
multiple = moveTarget !== MoveTarget . USER_OR_NEAR_ALLY ;
break ;
case MoveTarget . ALL :
case MoveTarget . BOTH_SIDES :
set = [ user , user . getAlly ( ) ] . concat ( opponents ) ;
multiple = true ;
break ;
case MoveTarget . CURSE :
set = user . getTypes ( true ) . includes ( Type . GHOST ) ? ( opponents . concat ( [ user . getAlly ( ) ] ) ) : [ user ] ;
break ;
2023-05-01 14:41:44 -04:00
}
2023-05-18 11:11:06 -04:00
2023-10-31 14:09:33 -04:00
return { targets : set.filter ( p = > p ? . isActive ( true ) ) . map ( p = > p . getBattlerIndex ( ) ) . filter ( t = > t !== undefined ) , multiple } ;
2023-05-01 14:41:44 -04:00
}
2023-07-04 15:25:11 -04:00
export const allMoves : Move [ ] = [
2024-04-16 15:22:19 -04:00
new SelfStatusMove ( Moves . NONE , Type . NORMAL , MoveCategory . STATUS , - 1 , - 1 , 0 , 1 ) ,
2023-04-27 14:30:03 -04:00
] ;
export function initMoves() {
allMoves . push (
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POUND , Type . NORMAL , MoveCategory . PHYSICAL , 40 , 100 , 35 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . KARATE_CHOP , Type . FIGHTING , MoveCategory . PHYSICAL , 50 , 100 , 25 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DOUBLE_SLAP , Type . NORMAL , MoveCategory . PHYSICAL , 15 , 85 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . COMET_PUNCH , Type . NORMAL , MoveCategory . PHYSICAL , 18 , 85 , 15 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( MultiHitAttr )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MEGA_PUNCH , Type . NORMAL , MoveCategory . PHYSICAL , 80 , 85 , 20 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PAY_DAY , Type . NORMAL , MoveCategory . PHYSICAL , 40 , 100 , 20 , - 1 , 0 , 1 )
2024-04-03 22:52:39 -04:00
. attr ( MoneyAttr )
2023-04-27 14:30:03 -04:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FIRE_PUNCH , Type . FIRE , MoveCategory . PHYSICAL , 75 , 100 , 15 , 10 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICE_PUNCH , Type . ICE , MoveCategory . PHYSICAL , 75 , 100 , 15 , 10 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . FREEZE )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THUNDER_PUNCH , Type . ELECTRIC , MoveCategory . PHYSICAL , 75 , 100 , 15 , 10 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SCRATCH , Type . NORMAL , MoveCategory . PHYSICAL , 40 , 100 , 35 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . VISE_GRIP , Type . NORMAL , MoveCategory . PHYSICAL , 55 , 100 , 30 , - 1 , 0 , 1 ) ,
2024-04-22 01:05:48 -04:00
new AttackMove ( Moves . GUILLOTINE , Type . NORMAL , MoveCategory . PHYSICAL , 200 , 30 , 5 , - 1 , 0 , 1 )
2023-11-30 16:37:16 -05:00
. attr ( OneHitKOAttr )
. attr ( OneHitKOAccuracyAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RAZOR_WIND , Type . NORMAL , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 1 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . RAZOR_WIND_CHARGING , "whipped\nup a whirlwind!" )
2023-04-27 20:12:25 -04:00
. attr ( HighCritAttr )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-05-01 14:41:44 -04:00
. ignoresVirtual ( )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SWORDS_DANCE , Type . NORMAL , - 1 , 20 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , 2 , true )
. danceMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CUT , Type . NORMAL , MoveCategory . PHYSICAL , 50 , 95 , 30 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GUST , Type . FLYING , MoveCategory . SPECIAL , 40 , 100 , 35 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( HitsTagAttr , BattlerTagType . FLYING , true )
. windMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WING_ATTACK , Type . FLYING , MoveCategory . PHYSICAL , 60 , 100 , 35 , - 1 , 0 , 1 ) ,
new StatusMove ( Moves . WHIRLWIND , Type . NORMAL , - 1 , 20 , - 1 , - 6 , 1 )
2023-10-31 14:09:33 -04:00
. attr ( ForceSwitchOutAttr )
2024-04-15 12:49:10 -07:00
. attr ( HitsTagAttr , BattlerTagType . FLYING , false )
2023-12-15 01:41:45 -06:00
. hidesTarget ( )
. windMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLY , Type . FLYING , MoveCategory . PHYSICAL , 90 , 95 , 15 , - 1 , 0 , 1 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . FLY_CHARGING , "flew\nup high!" , BattlerTagType . FLYING )
2023-05-08 18:48:35 -04:00
. condition ( failOnGravityCondition )
2023-04-27 20:12:25 -04:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BIND , Type . NORMAL , MoveCategory . PHYSICAL , 15 , 85 , 20 , 100 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( TrapAttr , BattlerTagType . BIND ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SLAM , Type . NORMAL , MoveCategory . PHYSICAL , 80 , 75 , 20 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . VINE_WHIP , Type . GRASS , MoveCategory . PHYSICAL , 45 , 100 , 25 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . STOMP , Type . NORMAL , MoveCategory . PHYSICAL , 65 , 100 , 20 , 30 , 0 , 1 )
2024-05-15 06:36:34 -06:00
. attr ( MinimizeAccuracyAttr )
. attr ( HitsTagAttr , BattlerTagType . MINIMIZED , true )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DOUBLE_KICK , Type . FIGHTING , MoveCategory . PHYSICAL , 30 , 100 , 30 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr , MultiHitType . _2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MEGA_KICK , Type . NORMAL , MoveCategory . PHYSICAL , 120 , 75 , 5 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . JUMP_KICK , Type . FIGHTING , MoveCategory . PHYSICAL , 100 , 95 , 10 , - 1 , 0 , 1 )
2024-04-12 18:49:48 -07:00
. attr ( MissEffectAttr , crashDamageFunc )
. attr ( NoEffectAttr , crashDamageFunc )
2024-05-07 23:28:35 -05:00
. condition ( failOnGravityCondition )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ROLLING_KICK , Type . FIGHTING , MoveCategory . PHYSICAL , 60 , 85 , 15 , 30 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SAND_ATTACK , Type . GROUND , 100 , 15 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HEADBUTT , Type . NORMAL , MoveCategory . PHYSICAL , 70 , 100 , 15 , 30 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HORN_ATTACK , Type . NORMAL , MoveCategory . PHYSICAL , 65 , 100 , 25 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . FURY_ATTACK , Type . NORMAL , MoveCategory . PHYSICAL , 15 , 85 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr ) ,
2024-04-22 01:05:48 -04:00
new AttackMove ( Moves . HORN_DRILL , Type . NORMAL , MoveCategory . PHYSICAL , 200 , 30 , 5 , - 1 , 0 , 1 )
2023-11-30 16:37:16 -05:00
. attr ( OneHitKOAttr )
. attr ( OneHitKOAccuracyAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TACKLE , Type . NORMAL , MoveCategory . PHYSICAL , 40 , 100 , 35 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . BODY_SLAM , Type . NORMAL , MoveCategory . PHYSICAL , 85 , 100 , 15 , 30 , 0 , 1 )
2024-05-15 06:36:34 -06:00
. attr ( MinimizeAccuracyAttr )
. attr ( HitsTagAttr , BattlerTagType . MINIMIZED , true )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WRAP , Type . NORMAL , MoveCategory . PHYSICAL , 15 , 90 , 20 , 100 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( TrapAttr , BattlerTagType . WRAP ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TAKE_DOWN , Type . NORMAL , MoveCategory . PHYSICAL , 90 , 85 , 20 , - 1 , 0 , 1 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THRASH , Type . NORMAL , MoveCategory . PHYSICAL , 120 , 100 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FrenzyAttr )
. attr ( MissEffectAttr , frenzyMissFunc )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . RANDOM_NEAR_ENEMY ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DOUBLE_EDGE , Type . NORMAL , MoveCategory . PHYSICAL , 120 , 100 , 15 , - 1 , 0 , 1 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr , false , 0.33 )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TAIL_WHIP , Type . NORMAL , 100 , 30 , - 1 , 0 , 1 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POISON_STING , Type . POISON , MoveCategory . PHYSICAL , 15 , 100 , 35 , 30 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TWINEEDLE , Type . BUG , MoveCategory . PHYSICAL , 25 , 100 , 20 , 20 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr , MultiHitType . _2 )
. attr ( StatusEffectAttr , StatusEffect . POISON )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PIN_MISSILE , Type . BUG , MoveCategory . PHYSICAL , 25 , 95 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . LEER , Type . NORMAL , 100 , 30 , 100 , 0 , 1 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BITE , Type . DARK , MoveCategory . PHYSICAL , 60 , 100 , 25 , 30 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( FlinchAttr )
. bitingMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . GROWL , Type . NORMAL , 100 , 40 , - 1 , 0 , 1 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 )
2023-11-30 16:37:16 -05:00
. soundBased ( )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ROAR , Type . NORMAL , - 1 , 20 , - 1 , - 6 , 1 )
2023-10-31 14:09:33 -04:00
. attr ( ForceSwitchOutAttr )
. soundBased ( )
. hidesTarget ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SING , Type . NORMAL , 55 , 15 , - 1 , 0 , 1 )
2023-10-31 14:09:33 -04:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SUPERSONIC , Type . NORMAL , 55 , 20 , - 1 , 0 , 1 )
2023-10-31 14:09:33 -04:00
. attr ( ConfuseAttr )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SONIC_BOOM , Type . NORMAL , MoveCategory . SPECIAL , - 1 , 90 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FixedDamageAttr , 20 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . DISABLE , Type . NORMAL , 100 , 20 , - 1 , 0 , 1 )
2024-04-24 01:57:59 +10:00
. attr ( DisableMoveAttr )
. condition ( failOnMaxCondition ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ACID , Type . POISON , MoveCategory . SPECIAL , 40 , 100 , 30 , 10 , 0 , 1 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EMBER , Type . FIRE , MoveCategory . SPECIAL , 40 , 100 , 25 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLAMETHROWER , Type . FIRE , MoveCategory . SPECIAL , 90 , 100 , 15 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MIST , Type . ICE , - 1 , 30 , - 1 , 0 , 1 )
2024-01-15 23:29:22 -05:00
. attr ( AddArenaTagAttr , ArenaTagType . MIST , 5 , true )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . USER_SIDE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WATER_GUN , Type . WATER , MoveCategory . SPECIAL , 40 , 100 , 25 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . HYDRO_PUMP , Type . WATER , MoveCategory . SPECIAL , 110 , 80 , 5 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . SURF , Type . WATER , MoveCategory . SPECIAL , 90 , 100 , 15 , - 1 , 0 , 1 )
2024-04-15 12:49:10 -07:00
. target ( MoveTarget . ALL_NEAR_OTHERS )
. attr ( HitsTagAttr , BattlerTagType . UNDERWATER , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICE_BEAM , Type . ICE , MoveCategory . SPECIAL , 90 , 100 , 10 , 10 , 0 , 1 )
2023-10-23 17:47:05 -04:00
. attr ( StatusEffectAttr , StatusEffect . FREEZE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLIZZARD , Type . ICE , MoveCategory . SPECIAL , 110 , 70 , 5 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( BlizzardAccuracyAttr )
2024-05-22 10:59:29 -04:00
. attr ( StatusEffectAttr , StatusEffect . FREEZE )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-05-18 11:11:06 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYBEAM , Type . PSYCHIC , MoveCategory . SPECIAL , 65 , 100 , 20 , 10 , 0 , 1 )
2023-07-11 11:32:56 -04:00
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BUBBLE_BEAM , Type . WATER , MoveCategory . SPECIAL , 65 , 100 , 20 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AURORA_BEAM , Type . ICE , MoveCategory . SPECIAL , 65 , 100 , 20 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYPER_BEAM , Type . NORMAL , MoveCategory . SPECIAL , 150 , 90 , 5 , - 1 , 0 , 1 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PECK , Type . FLYING , MoveCategory . PHYSICAL , 35 , 100 , 35 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . DRILL_PECK , Type . FLYING , MoveCategory . PHYSICAL , 80 , 100 , 20 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . SUBMISSION , Type . FIGHTING , MoveCategory . PHYSICAL , 80 , 80 , 20 , - 1 , 0 , 1 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LOW_KICK , Type . FIGHTING , MoveCategory . PHYSICAL , - 1 , 100 , 20 , - 1 , 0 , 1 )
2024-04-24 01:57:59 +10:00
. attr ( WeightPowerAttr )
. condition ( failOnMaxCondition ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . COUNTER , Type . FIGHTING , MoveCategory . PHYSICAL , - 1 , 100 , 20 , - 1 , - 5 , 1 )
2024-04-08 12:13:34 -04:00
. attr ( CounterDamageAttr , ( move : Move ) = > move . category === MoveCategory . PHYSICAL , 2 )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ATTACKER ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SEISMIC_TOSS , Type . FIGHTING , MoveCategory . PHYSICAL , - 1 , 100 , 20 , - 1 , 0 , 1 )
2023-07-05 16:25:09 -04:00
. attr ( LevelDamageAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STRENGTH , Type . NORMAL , MoveCategory . PHYSICAL , 80 , 100 , 15 , - 1 , 0 , 1 ) ,
new AttackMove ( Moves . ABSORB , Type . GRASS , MoveCategory . SPECIAL , 20 , 100 , 25 , - 1 , 0 , 1 )
2024-04-08 17:10:07 +03:00
. attr ( HitHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MEGA_DRAIN , Type . GRASS , MoveCategory . SPECIAL , 40 , 100 , 15 , - 1 , 0 , 1 )
2024-04-08 17:10:07 +03:00
. attr ( HitHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . LEECH_SEED , Type . GRASS , 90 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( AddBattlerTagAttr , BattlerTagType . SEEDED )
2023-12-10 17:57:12 -05:00
. condition ( ( user , target , move ) = > ! target . getTag ( BattlerTagType . SEEDED ) && ! target . isOfType ( Type . GRASS ) ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . GROWTH , Type . NORMAL , - 1 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( GrowthStatChangeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RAZOR_LEAF , Type . GRASS , MoveCategory . PHYSICAL , 55 , 95 , 25 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr )
2023-05-01 14:41:44 -04:00
. makesContact ( false )
2023-12-15 01:41:45 -06:00
. slicingMove ( )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SOLAR_BEAM , Type . GRASS , MoveCategory . SPECIAL , 120 , 100 , 10 , - 1 , 0 , 1 )
2024-05-23 17:03:10 +02:00
. attr ( SunlightChargeAttr , ChargeAnim . SOLAR_BEAM_CHARGING , "took\nin sunlight!" )
2024-03-09 21:57:33 -05:00
. attr ( AntiSunlightPowerDecreaseAttr )
2023-04-27 20:12:25 -04:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . POISON_POWDER , Type . POISON , 75 , 35 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. powderMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . STUN_SPORE , Type . GRASS , 75 , 30 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
. powderMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SLEEP_POWDER , Type . GRASS , 75 , 15 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP )
. powderMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PETAL_DANCE , Type . GRASS , MoveCategory . SPECIAL , 120 , 100 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FrenzyAttr )
. attr ( MissEffectAttr , frenzyMissFunc )
2023-05-01 14:41:44 -04:00
. makesContact ( )
2023-12-15 01:41:45 -06:00
. danceMove ( )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . RANDOM_NEAR_ENEMY ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . STRING_SHOT , Type . BUG , 95 , 40 , - 1 , 0 , 1 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 2 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_RAGE , Type . DRAGON , MoveCategory . SPECIAL , - 1 , 100 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FixedDamageAttr , 40 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FIRE_SPIN , Type . FIRE , MoveCategory . SPECIAL , 35 , 85 , 15 , 100 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( TrapAttr , BattlerTagType . FIRE_SPIN ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THUNDER_SHOCK , Type . ELECTRIC , MoveCategory . SPECIAL , 40 , 100 , 30 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THUNDERBOLT , Type . ELECTRIC , MoveCategory . SPECIAL , 90 , 100 , 15 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . THUNDER_WAVE , Type . ELECTRIC , 90 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
2024-03-04 20:28:55 -05:00
. attr ( StatusMoveTypeImmunityAttr , Type . GROUND ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THUNDER , Type . ELECTRIC , MoveCategory . SPECIAL , 110 , 70 , 10 , 30 , 0 , 1 )
2024-03-24 22:25:02 -05:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
2024-04-15 12:49:10 -07:00
. attr ( ThunderAccuracyAttr )
. attr ( HitsTagAttr , BattlerTagType . FLYING , false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ROCK_THROW , Type . ROCK , MoveCategory . PHYSICAL , 50 , 90 , 15 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EARTHQUAKE , Type . GROUND , MoveCategory . PHYSICAL , 100 , 100 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( HitsTagAttr , BattlerTagType . UNDERGROUND , true )
2023-05-01 14:41:44 -04:00
. makesContact ( false )
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-22 01:05:48 -04:00
new AttackMove ( Moves . FISSURE , Type . GROUND , MoveCategory . PHYSICAL , 200 , 30 , 5 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( OneHitKOAttr )
2023-11-30 16:37:16 -05:00
. attr ( OneHitKOAccuracyAttr )
2024-04-15 12:49:10 -07:00
. attr ( HitsTagAttr , BattlerTagType . UNDERGROUND , false )
2023-04-27 14:30:03 -04:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DIG , Type . GROUND , MoveCategory . PHYSICAL , 80 , 100 , 10 , - 1 , 0 , 1 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . DIG_CHARGING , "dug a hole!" , BattlerTagType . UNDERGROUND )
2023-04-27 20:12:25 -04:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TOXIC , Type . POISON , 90 , 10 , - 1 , 0 , 1 )
2024-04-09 18:44:13 +03:00
. attr ( StatusEffectAttr , StatusEffect . TOXIC )
. attr ( ToxicAccuracyAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CONFUSION , Type . PSYCHIC , MoveCategory . SPECIAL , 50 , 100 , 25 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYCHIC , Type . PSYCHIC , MoveCategory . SPECIAL , 90 , 100 , 10 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HYPNOSIS , Type . PSYCHIC , 60 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . MEDITATE , Type . PSYCHIC , - 1 , 40 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ATK , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . AGILITY , Type . PSYCHIC , - 1 , 30 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . QUICK_ATTACK , Type . NORMAL , MoveCategory . PHYSICAL , 40 , 100 , 30 , - 1 , 1 , 1 ) ,
new AttackMove ( Moves . RAGE , Type . NORMAL , MoveCategory . PHYSICAL , 20 , 100 , 20 , - 1 , 0 , 1 )
. partial ( ) ,
new SelfStatusMove ( Moves . TELEPORT , Type . PSYCHIC , - 1 , 20 , - 1 , - 6 , 1 )
2023-10-31 14:09:33 -04:00
. attr ( ForceSwitchOutAttr , true )
. hidesUser ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NIGHT_SHADE , Type . GHOST , MoveCategory . SPECIAL , - 1 , 100 , 15 , - 1 , 0 , 1 )
2023-07-05 16:25:09 -04:00
. attr ( LevelDamageAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MIMIC , Type . NORMAL , - 1 , 10 , - 1 , 0 , 1 )
2023-05-06 00:42:01 -04:00
. attr ( MovesetCopyMoveAttr )
2023-04-27 20:12:25 -04:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SCREECH , Type . NORMAL , 85 , 40 , - 1 , 0 , 1 )
2023-10-31 14:09:33 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , - 2 )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . DOUBLE_TEAM , Type . NORMAL , - 1 , 15 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . EVA , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . RECOVER , Type . NORMAL , - 1 , 5 , - 1 , 0 , 1 )
2024-04-08 17:10:07 +03:00
. attr ( HealAttr , 0.5 )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . HARDEN , Type . NORMAL , - 1 , 30 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . MINIMIZE , Type . NORMAL , - 1 , 10 , - 1 , 0 , 1 )
2024-05-15 06:36:34 -06:00
. attr ( AddBattlerTagAttr , BattlerTagType . MINIMIZED , true , false )
2024-04-03 21:31:42 -04:00
. attr ( StatChangeAttr , BattleStat . EVA , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SMOKESCREEN , Type . NORMAL , 100 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . CONFUSE_RAY , Type . GHOST , 100 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . WITHDRAW , Type . WATER , - 1 , 40 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . DEFENSE_CURL , Type . NORMAL , - 1 , 40 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . BARRIER , Type . PSYCHIC , - 1 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . LIGHT_SCREEN , Type . PSYCHIC , - 1 , 30 , - 1 , 0 , 1 )
2024-04-05 17:21:17 +02:00
. attr ( AddArenaTagAttr , ArenaTagType . LIGHT_SCREEN , 5 , true )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . USER_SIDE ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HAZE , Type . ICE , - 1 , 30 , - 1 , 0 , 1 )
. target ( MoveTarget . BOTH_SIDES )
2024-04-18 16:28:22 +10:00
. attr ( ResetStatsAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . REFLECT , Type . PSYCHIC , - 1 , 20 , - 1 , 0 , 1 )
2024-04-05 17:21:17 +02:00
. attr ( AddArenaTagAttr , ArenaTagType . REFLECT , 5 , true )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . USER_SIDE ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . FOCUS_ENERGY , Type . NORMAL , - 1 , 30 , - 1 , 0 , 1 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . CRIT_BOOST , true , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BIDE , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , - 1 , 10 , - 1 , 1 , 1 )
2023-05-01 14:41:44 -04:00
. ignoresVirtual ( )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . USER )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . METRONOME , Type . NORMAL , - 1 , 10 , - 1 , 0 , 1 )
2023-04-27 20:12:25 -04:00
. attr ( RandomMoveAttr )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MIRROR_MOVE , Type . FLYING , - 1 , 20 , - 1 , 0 , 1 )
2023-05-06 00:42:01 -04:00
. attr ( CopyMoveAttr )
2023-04-27 20:12:25 -04:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SELF_DESTRUCT , Type . NORMAL , MoveCategory . PHYSICAL , 200 , 100 , 5 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( SacrificialAttr )
2023-05-01 14:41:44 -04:00
. makesContact ( false )
2024-04-26 21:44:25 +10:00
. condition ( failIfDampCondition )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EGG_BOMB , Type . NORMAL , MoveCategory . PHYSICAL , 100 , 75 , 10 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. makesContact ( false )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LICK , Type . GHOST , MoveCategory . PHYSICAL , 30 , 100 , 30 , 30 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SMOG , Type . POISON , MoveCategory . SPECIAL , 30 , 70 , 20 , 40 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . POISON ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SLUDGE , Type . POISON , MoveCategory . SPECIAL , 65 , 100 , 20 , 30 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . POISON ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BONE_CLUB , Type . GROUND , MoveCategory . PHYSICAL , 65 , 85 , 20 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FIRE_BLAST , Type . FIRE , MoveCategory . SPECIAL , 110 , 85 , 5 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WATERFALL , Type . WATER , MoveCategory . PHYSICAL , 80 , 100 , 15 , 20 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CLAMP , Type . WATER , MoveCategory . PHYSICAL , 35 , 85 , 15 , 100 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( TrapAttr , BattlerTagType . CLAMP ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SWIFT , Type . NORMAL , MoveCategory . SPECIAL , 60 , - 1 , 20 , - 1 , 0 , 1 )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SKULL_BASH , Type . NORMAL , MoveCategory . PHYSICAL , 130 , 100 , 10 , 100 , 0 , 1 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . SKULL_BASH_CHARGING , "lowered\nits head!" , null , true )
2023-04-27 20:12:25 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 1 , true )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPIKE_CANNON , Type . NORMAL , MoveCategory . PHYSICAL , 20 , 100 , 15 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CONSTRICT , Type . NORMAL , MoveCategory . PHYSICAL , 10 , 100 , 35 , 10 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . AMNESIA , Type . PSYCHIC , - 1 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . KINESIS , Type . PSYCHIC , 80 , 15 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SOFT_BOILED , Type . NORMAL , - 1 , 5 , - 1 , 0 , 1 )
2024-04-08 17:10:07 +03:00
. attr ( HealAttr , 0.5 )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HIGH_JUMP_KICK , Type . FIGHTING , MoveCategory . PHYSICAL , 130 , 90 , 10 , - 1 , 0 , 1 )
2024-04-12 18:49:48 -07:00
. attr ( MissEffectAttr , crashDamageFunc )
. attr ( NoEffectAttr , crashDamageFunc )
2024-05-07 23:28:35 -05:00
. condition ( failOnGravityCondition )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . GLARE , Type . NORMAL , 100 , 30 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DREAM_EATER , Type . PSYCHIC , MoveCategory . SPECIAL , 100 , 100 , 15 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( HitHealAttr )
2024-05-27 05:01:03 -06:00
. condition ( targetSleptOrComatoseCondition )
2024-04-08 17:10:07 +03:00
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . POISON_GAS , Type . POISON , 90 , 40 , - 1 , 0 , 1 )
2023-05-01 14:41:44 -04:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BARRAGE , Type . NORMAL , MoveCategory . PHYSICAL , 15 , 85 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr )
2023-12-15 01:41:45 -06:00
. makesContact ( false )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LEECH_LIFE , Type . BUG , MoveCategory . PHYSICAL , 80 , 100 , 10 , - 1 , 0 , 1 )
2024-04-08 17:10:07 +03:00
. attr ( HitHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . LOVELY_KISS , Type . NORMAL , 75 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SKY_ATTACK , Type . FLYING , MoveCategory . PHYSICAL , 140 , 90 , 5 , 30 , 0 , 1 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . SKY_ATTACK_CHARGING , "is glowing!" )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr )
. attr ( FlinchAttr )
2023-04-27 20:12:25 -04:00
. makesContact ( false )
2023-11-30 16:37:16 -05:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TRANSFORM , Type . NORMAL , - 1 , 10 , - 1 , 0 , 1 )
2023-10-29 16:05:17 -04:00
. attr ( TransformAttr )
. ignoresProtect ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BUBBLE , Type . WATER , MoveCategory . SPECIAL , 40 , 100 , 30 , 10 , 0 , 1 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DIZZY_PUNCH , Type . NORMAL , MoveCategory . PHYSICAL , 70 , 100 , 10 , 20 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( ConfuseAttr )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SPORE , Type . GRASS , 100 , 15 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP )
. powderMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . FLASH , Type . NORMAL , 100 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYWAVE , Type . PSYCHIC , MoveCategory . SPECIAL , - 1 , 100 , 15 , - 1 , 0 , 1 )
2023-07-05 16:25:09 -04:00
. attr ( RandomLevelDamageAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SPLASH , Type . NORMAL , - 1 , 40 , - 1 , 0 , 1 )
2023-05-08 18:48:35 -04:00
. condition ( failOnGravityCondition ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . ACID_ARMOR , Type . POISON , - 1 , 20 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CRABHAMMER , Type . WATER , MoveCategory . PHYSICAL , 100 , 90 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EXPLOSION , Type . NORMAL , MoveCategory . PHYSICAL , 250 , 100 , 5 , - 1 , 0 , 1 )
2024-04-26 21:44:25 +10:00
. condition ( failIfDampCondition )
2023-04-27 14:30:03 -04:00
. attr ( SacrificialAttr )
2023-05-01 14:41:44 -04:00
. makesContact ( false )
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FURY_SWIPES , Type . NORMAL , MoveCategory . PHYSICAL , 18 , 80 , 15 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BONEMERANG , Type . GROUND , MoveCategory . PHYSICAL , 50 , 90 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr , MultiHitType . _2 )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . REST , Type . PSYCHIC , - 1 , 5 , - 1 , 0 , 1 )
2023-10-27 22:18:54 -04:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP , true , 3 , true )
2023-04-27 14:30:03 -04:00
. attr ( HealAttr , 1 , true )
2024-04-11 20:01:43 -04:00
. condition ( ( user , target , move ) = > user . getHpRatio ( ) < 1 && user . canSetStatus ( StatusEffect . SLEEP , true , true ) )
2024-04-08 17:10:07 +03:00
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ROCK_SLIDE , Type . ROCK , MoveCategory . PHYSICAL , 75 , 90 , 10 , 30 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr )
2023-05-01 14:41:44 -04:00
. makesContact ( false )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYPER_FANG , Type . NORMAL , MoveCategory . PHYSICAL , 80 , 90 , 15 , 10 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( FlinchAttr )
. bitingMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SHARPEN , Type . NORMAL , - 1 , 30 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ATK , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . CONVERSION , Type . NORMAL , - 1 , 30 , - 1 , 0 , 1 )
2024-03-11 22:57:07 +01:00
. attr ( FirstMoveTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TRI_ATTACK , Type . NORMAL , MoveCategory . SPECIAL , 80 , 100 , 10 , 20 , 0 , 1 )
2024-05-23 17:03:10 +02:00
. attr ( MultiStatusEffectAttr , [ StatusEffect . BURN , StatusEffect . FREEZE , StatusEffect . PARALYSIS ] ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SUPER_FANG , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , 90 , 10 , - 1 , 0 , 1 )
2023-04-27 14:30:03 -04:00
. attr ( TargetHalfHpDamageAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SLASH , Type . NORMAL , MoveCategory . PHYSICAL , 70 , 100 , 20 , - 1 , 0 , 1 )
2023-12-15 01:41:45 -06:00
. attr ( HighCritAttr )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SUBSTITUTE , Type . NORMAL , - 1 , 10 , - 1 , 0 , 1 )
. attr ( RecoilAttr )
. unimplemented ( ) ,
new AttackMove ( Moves . STRUGGLE , Type . NORMAL , MoveCategory . PHYSICAL , 50 , - 1 , 1 , - 1 , 0 , 1 )
2024-04-20 19:43:48 -04:00
. attr ( RecoilAttr , true , 0.25 , true )
2023-04-27 20:12:25 -04:00
. attr ( TypelessAttr )
2023-05-01 14:41:44 -04:00
. ignoresVirtual ( )
. target ( MoveTarget . RANDOM_NEAR_ENEMY ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SKETCH , Type . NORMAL , - 1 , 1 , - 1 , 0 , 2 )
2023-04-27 20:12:25 -04:00
. attr ( SketchAttr )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TRIPLE_KICK , Type . FIGHTING , MoveCategory . PHYSICAL , 10 , 90 , 10 , - 1 , 0 , 2 )
2024-05-28 19:07:35 -04:00
. attr ( MultiHitAttr , MultiHitType . _3 )
. attr ( MultiHitPowerIncrementAttr , 3 )
. checkAllHits ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THIEF , Type . DARK , MoveCategory . PHYSICAL , 60 , 100 , 25 , - 1 , 0 , 2 )
2024-03-04 21:51:28 -05:00
. attr ( StealHeldItemChanceAttr , 0.3 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SPIDER_WEB , Type . BUG , - 1 , 10 , - 1 , 0 , 2 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , false , true , 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MIND_READER , Type . NORMAL , - 1 , 5 , - 1 , 0 , 2 )
2023-04-27 20:12:25 -04:00
. attr ( IgnoreAccuracyAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . NIGHTMARE , Type . GHOST , 100 , 15 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( AddBattlerTagAttr , BattlerTagType . NIGHTMARE )
2024-05-27 05:01:03 -06:00
. condition ( targetSleptOrComatoseCondition ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLAME_WHEEL , Type . FIRE , MoveCategory . PHYSICAL , 60 , 100 , 25 , 10 , 0 , 2 )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SNORE , Type . NORMAL , MoveCategory . SPECIAL , 50 , 100 , 15 , 30 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( BypassSleepAttr )
. attr ( FlinchAttr )
2024-05-27 05:01:03 -06:00
. condition ( userSleptOrComatoseCondition )
2023-10-31 14:09:33 -04:00
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . CURSE , Type . GHOST , - 1 , 10 , - 1 , 0 , 2 )
2024-05-05 17:45:20 -04:00
. attr ( CurseAttr )
2024-05-19 19:40:56 +02:00
. ignoresProtect ( true )
. target ( MoveTarget . CURSE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLAIL , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , 100 , 15 , - 1 , 0 , 2 )
2023-04-27 20:12:25 -04:00
. attr ( LowHpPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . CONVERSION_2 , Type . NORMAL , - 1 , 30 , - 1 , 0 , 2 )
. unimplemented ( ) ,
new AttackMove ( Moves . AEROBLAST , Type . FLYING , MoveCategory . SPECIAL , 100 , 95 , 5 , - 1 , 0 , 2 )
2023-11-30 16:37:16 -05:00
. attr ( HighCritAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . COTTON_SPORE , Type . GRASS , 100 , 40 , - 1 , 0 , 2 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 2 )
2023-12-15 01:41:45 -06:00
. powderMove ( )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . REVERSAL , Type . FIGHTING , MoveCategory . PHYSICAL , - 1 , 100 , 15 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( LowHpPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SPITE , Type . GHOST , 100 , 10 , - 1 , 0 , 2 )
2024-03-11 15:40:56 -04:00
. attr ( ReducePpMoveAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POWDER_SNOW , Type . ICE , MoveCategory . SPECIAL , 40 , 100 , 25 , 10 , 0 , 2 )
2023-05-01 14:41:44 -04:00
. attr ( StatusEffectAttr , StatusEffect . FREEZE )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . PROTECT , Type . NORMAL , - 1 , 10 , - 1 , 4 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( ProtectAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MACH_PUNCH , Type . FIGHTING , MoveCategory . PHYSICAL , 40 , 100 , 30 , - 1 , 1 , 2 )
2023-12-15 01:41:45 -06:00
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SCARY_FACE , Type . NORMAL , 100 , 10 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FEINT_ATTACK , Type . DARK , MoveCategory . PHYSICAL , 60 , - 1 , 20 , - 1 , 0 , 2 ) ,
new StatusMove ( Moves . SWEET_KISS , Type . FAIRY , 75 , 10 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . BELLY_DRUM , Type . NORMAL , - 1 , 10 , - 1 , 0 , 2 )
2024-01-15 23:29:22 -05:00
. attr ( HalfHpStatMaxAttr , BattleStat . ATK ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SLUDGE_BOMB , Type . POISON , MoveCategory . SPECIAL , 90 , 100 , 10 , 30 , 0 , 2 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MUD_SLAP , Type . GROUND , MoveCategory . SPECIAL , 20 , 100 , 10 , 100 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . OCTAZOOKA , Type . WATER , MoveCategory . SPECIAL , 65 , 85 , 10 , 50 , 0 , 2 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SPIKES , Type . GROUND , - 1 , 20 , - 1 , 0 , 2 )
2023-05-01 14:41:44 -04:00
. attr ( AddArenaTrapTagAttr , ArenaTagType . SPIKES )
. target ( MoveTarget . ENEMY_SIDE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ZAP_CANNON , Type . ELECTRIC , MoveCategory . SPECIAL , 120 , 50 , 5 , 100 , 0 , 2 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . FORESIGHT , Type . NORMAL , - 1 , 40 , - 1 , 0 , 2 )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . DESTINY_BOND , Type . GHOST , - 1 , 5 , - 1 , 0 , 2 )
2024-04-01 15:34:46 -05:00
. ignoresProtect ( )
2024-05-24 22:23:23 +02:00
. attr ( DestinyBondAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . PERISH_SONG , Type . NORMAL , - 1 , 5 , - 1 , 0 , 2 )
2023-12-18 21:53:28 -04:00
. attr ( FaintCountdownAttr )
2023-05-01 14:41:44 -04:00
. ignoresProtect ( )
2023-11-30 16:37:16 -05:00
. soundBased ( )
2024-01-14 20:47:08 -05:00
. condition ( failOnBossCondition )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICY_WIND , Type . ICE , MoveCategory . SPECIAL , 55 , 95 , 15 , 100 , 0 , 2 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . DETECT , Type . FIGHTING , - 1 , 5 , - 1 , 4 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( ProtectAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BONE_RUSH , Type . GROUND , MoveCategory . PHYSICAL , 25 , 90 , 10 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . LOCK_ON , Type . NORMAL , - 1 , 5 , - 1 , 0 , 2 )
2023-04-27 20:12:25 -04:00
. attr ( IgnoreAccuracyAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . OUTRAGE , Type . DRAGON , MoveCategory . PHYSICAL , 120 , 100 , 10 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( FrenzyAttr )
. attr ( MissEffectAttr , frenzyMissFunc )
2023-07-04 17:50:51 -04:00
. target ( MoveTarget . RANDOM_NEAR_ENEMY ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SANDSTORM , Type . ROCK , - 1 , 10 , - 1 , 0 , 2 )
2023-05-01 14:41:44 -04:00
. attr ( WeatherChangeAttr , WeatherType . SANDSTORM )
2023-07-04 17:50:51 -04:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GIGA_DRAIN , Type . GRASS , MoveCategory . SPECIAL , 75 , 100 , 10 , - 1 , 0 , 2 )
2024-04-08 17:10:07 +03:00
. attr ( HitHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . ENDURE , Type . NORMAL , - 1 , 10 , - 1 , 4 , 2 )
2024-01-15 23:29:22 -05:00
. attr ( EndureAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . CHARM , Type . FAIRY , 100 , 20 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ATK , - 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ROLLOUT , Type . ROCK , MoveCategory . PHYSICAL , 30 , 90 , 20 , - 1 , 0 , 2 )
2023-05-08 10:03:57 -04:00
. attr ( ConsecutiveUseDoublePowerAttr , 5 , true , true , Moves . DEFENSE_CURL ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FALSE_SWIPE , Type . NORMAL , MoveCategory . PHYSICAL , 40 , 100 , 40 , - 1 , 0 , 2 )
2024-03-29 11:58:22 -04:00
. attr ( SurviveDamageAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SWAGGER , Type . NORMAL , 85 , 15 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ATK , 2 )
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . MILK_DRINK , Type . NORMAL , - 1 , 5 , - 1 , 0 , 2 )
2024-04-08 17:10:07 +03:00
. attr ( HealAttr , 0.5 )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPARK , Type . ELECTRIC , MoveCategory . PHYSICAL , 65 , 100 , 20 , 30 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FURY_CUTTER , Type . BUG , MoveCategory . PHYSICAL , 40 , 95 , 20 , - 1 , 0 , 2 )
2023-12-15 01:41:45 -06:00
. attr ( ConsecutiveUseDoublePowerAttr , 3 , true )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STEEL_WING , Type . STEEL , MoveCategory . PHYSICAL , 70 , 90 , 25 , 10 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MEAN_LOOK , Type . NORMAL , - 1 , 5 , - 1 , 0 , 2 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , false , true , 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ATTRACT , Type . NORMAL , 100 , 15 , - 1 , 0 , 2 )
2023-05-04 12:57:55 -04:00
. attr ( AddBattlerTagAttr , BattlerTagType . INFATUATED )
2023-12-10 17:57:12 -05:00
. condition ( ( user , target , move ) = > user . isOppositeGender ( target ) ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SLEEP_TALK , Type . NORMAL , - 1 , 10 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( BypassSleepAttr )
. attr ( RandomMovesetMoveAttr )
2024-05-27 05:01:03 -06:00
. condition ( userSleptOrComatoseCondition )
2024-06-07 05:38:22 -07:00
. target ( MoveTarget . ALL_ENEMIES )
2024-04-18 22:49:07 +03:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HEAL_BELL , Type . NORMAL , - 1 , 5 , - 1 , 0 , 2 )
2024-05-09 15:15:56 -04:00
. attr ( PartyStatusCureAttr , "A bell chimed!" , Abilities . SOUNDPROOF )
2023-11-30 16:37:16 -05:00
. soundBased ( )
2024-05-09 15:15:56 -04:00
. target ( MoveTarget . PARTY ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RETURN , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , 100 , 20 , - 1 , 0 , 2 )
2023-12-21 23:00:45 -05:00
. attr ( FriendshipPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PRESENT , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , 90 , 15 , - 1 , 0 , 2 )
2024-04-16 00:41:15 -04:00
. attr ( PresentPowerAttr )
2023-04-27 14:30:03 -04:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FRUSTRATION , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , 100 , 20 , - 1 , 0 , 2 )
2023-12-21 23:00:45 -05:00
. attr ( FriendshipPowerAttr , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SAFEGUARD , Type . NORMAL , - 1 , 25 , - 1 , 0 , 2 )
. target ( MoveTarget . USER_SIDE )
. unimplemented ( ) ,
new StatusMove ( Moves . PAIN_SPLIT , Type . NORMAL , - 1 , 20 , - 1 , 0 , 2 )
2024-01-14 20:47:08 -05:00
. attr ( HpSplitAttr )
. condition ( failOnBossCondition ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SACRED_FIRE , Type . FIRE , MoveCategory . PHYSICAL , 100 , 95 , 5 , 50 , 0 , 2 )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAGNITUDE , Type . GROUND , MoveCategory . PHYSICAL , - 1 , 100 , 30 , - 1 , 0 , 2 )
2024-03-18 22:05:21 -04:00
. attr ( PreMoveMessageAttr , magnitudeMessageFunc )
. attr ( MagnitudePowerAttr )
2024-04-15 12:49:10 -07:00
. attr ( HitsTagAttr , BattlerTagType . UNDERGROUND , true )
2023-05-01 14:41:44 -04:00
. makesContact ( false )
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DYNAMIC_PUNCH , Type . FIGHTING , MoveCategory . PHYSICAL , 100 , 50 , 5 , 100 , 0 , 2 )
2023-12-15 01:41:45 -06:00
. attr ( ConfuseAttr )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MEGAHORN , Type . BUG , MoveCategory . PHYSICAL , 120 , 85 , 10 , - 1 , 0 , 2 ) ,
new AttackMove ( Moves . DRAGON_BREATH , Type . DRAGON , MoveCategory . SPECIAL , 60 , 100 , 20 , 30 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . BATON_PASS , Type . NORMAL , - 1 , 40 , - 1 , 0 , 2 )
2023-10-31 14:09:33 -04:00
. attr ( ForceSwitchOutAttr , true , true )
. hidesUser ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ENCORE , Type . NORMAL , 100 , 5 , - 1 , 0 , 2 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . ENCORE , false , true )
2024-03-29 10:07:04 -04:00
. condition ( ( user , target , move ) = > new EncoreTag ( user . id ) . canAdd ( target ) ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PURSUIT , Type . DARK , MoveCategory . PHYSICAL , 40 , 100 , 20 , - 1 , 0 , 2 )
. partial ( ) ,
new AttackMove ( Moves . RAPID_SPIN , Type . NORMAL , MoveCategory . PHYSICAL , 50 , 100 , 40 , 100 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , 1 , true )
2024-05-24 01:45:04 +02:00
. attr ( RemoveBattlerTagAttr , [
2024-04-18 11:14:11 -04:00
BattlerTagType . BIND ,
BattlerTagType . WRAP ,
BattlerTagType . FIRE_SPIN ,
BattlerTagType . WHIRLPOOL ,
BattlerTagType . CLAMP ,
BattlerTagType . SAND_TOMB ,
BattlerTagType . MAGMA_STORM ,
2024-04-23 13:04:42 -05:00
BattlerTagType . SNAP_TRAP ,
2024-04-18 11:14:11 -04:00
BattlerTagType . THUNDER_CAGE ,
BattlerTagType . SEEDED ,
BattlerTagType . INFESTATION
] , true )
2024-05-06 23:00:31 -04:00
. attr ( RemoveArenaTrapAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SWEET_SCENT , Type . NORMAL , 100 , 20 , - 1 , 0 , 2 )
2024-06-07 18:42:17 -07:00
. attr ( StatChangeAttr , BattleStat . EVA , - 2 )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . IRON_TAIL , Type . STEEL , MoveCategory . PHYSICAL , 100 , 75 , 15 , 30 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . METAL_CLAW , Type . STEEL , MoveCategory . PHYSICAL , 50 , 95 , 35 , 10 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ATK , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . VITAL_THROW , Type . FIGHTING , MoveCategory . PHYSICAL , 70 , - 1 , 10 , - 1 , - 1 , 2 ) ,
new SelfStatusMove ( Moves . MORNING_SUN , Type . NORMAL , - 1 , 5 , - 1 , 0 , 2 )
2024-04-08 17:10:07 +03:00
. attr ( PlantHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SYNTHESIS , Type . GRASS , - 1 , 5 , - 1 , 0 , 2 )
2024-04-08 17:10:07 +03:00
. attr ( PlantHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . MOONLIGHT , Type . FAIRY , - 1 , 5 , - 1 , 0 , 2 )
2024-04-08 17:10:07 +03:00
. attr ( PlantHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HIDDEN_POWER , Type . NORMAL , MoveCategory . SPECIAL , 60 , 100 , 15 , - 1 , 0 , 2 )
2024-04-12 15:43:09 +10:00
. attr ( HiddenPowerTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CROSS_CHOP , Type . FIGHTING , MoveCategory . PHYSICAL , 100 , 80 , 5 , - 1 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TWISTER , Type . DRAGON , MoveCategory . SPECIAL , 40 , 100 , 20 , 20 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( HitsTagAttr , BattlerTagType . FLYING , true )
2023-07-11 11:32:56 -04:00
. attr ( FlinchAttr )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . RAIN_DANCE , Type . WATER , - 1 , 5 , - 1 , 0 , 2 )
2023-05-01 14:41:44 -04:00
. attr ( WeatherChangeAttr , WeatherType . RAIN )
2023-07-11 11:32:56 -04:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SUNNY_DAY , Type . FIRE , - 1 , 5 , - 1 , 0 , 2 )
2023-05-01 14:41:44 -04:00
. attr ( WeatherChangeAttr , WeatherType . SUNNY )
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CRUNCH , Type . DARK , MoveCategory . PHYSICAL , 80 , 100 , 15 , 20 , 0 , 2 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 )
. bitingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MIRROR_COAT , Type . PSYCHIC , MoveCategory . SPECIAL , - 1 , 100 , 20 , - 1 , - 5 , 2 )
2024-04-08 12:13:34 -04:00
. attr ( CounterDamageAttr , ( move : Move ) = > move . category === MoveCategory . SPECIAL , 2 )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ATTACKER ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . PSYCH_UP , Type . NORMAL , - 1 , 10 , - 1 , 0 , 2 )
2024-04-18 16:47:12 +10:00
. attr ( CopyStatsAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EXTREME_SPEED , Type . NORMAL , MoveCategory . PHYSICAL , 80 , 100 , 5 , - 1 , 2 , 2 ) ,
new AttackMove ( Moves . ANCIENT_POWER , Type . ROCK , MoveCategory . SPECIAL , 60 , 100 , 5 , 10 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHADOW_BALL , Type . GHOST , MoveCategory . SPECIAL , 80 , 100 , 15 , 20 , 0 , 2 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FUTURE_SIGHT , Type . PSYCHIC , MoveCategory . SPECIAL , 120 , 100 , 10 , - 1 , 0 , 2 )
2024-05-23 17:03:10 +02:00
. attr ( DelayedAttackAttr , ArenaTagType . FUTURE_SIGHT , ChargeAnim . FUTURE_SIGHT_CHARGING , "foresaw\nan attack!" ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ROCK_SMASH , Type . FIGHTING , MoveCategory . PHYSICAL , 40 , 100 , 15 , 50 , 0 , 2 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WHIRLPOOL , Type . WATER , MoveCategory . SPECIAL , 35 , 85 , 15 , 100 , 0 , 2 )
2024-04-15 12:49:10 -07:00
. attr ( TrapAttr , BattlerTagType . WHIRLPOOL )
. attr ( HitsTagAttr , BattlerTagType . UNDERWATER , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BEAT_UP , Type . DARK , MoveCategory . PHYSICAL , - 1 , 100 , 10 , - 1 , 0 , 2 )
2024-05-19 07:22:37 -07:00
. attr ( MultiHitAttr , MultiHitType . BEAT_UP )
. attr ( BeatUpAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FAKE_OUT , Type . NORMAL , MoveCategory . PHYSICAL , 40 , 100 , 10 , 100 , 3 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr )
2024-01-07 23:17:24 -05:00
. condition ( new FirstMoveCondition ( ) ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . UPROAR , Type . NORMAL , MoveCategory . SPECIAL , 90 , 100 , 10 , - 1 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. ignoresVirtual ( )
2023-11-30 16:37:16 -05:00
. soundBased ( )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . RANDOM_NEAR_ENEMY )
. partial ( ) ,
new SelfStatusMove ( Moves . STOCKPILE , Type . NORMAL , - 1 , 20 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new AttackMove ( Moves . SPIT_UP , Type . NORMAL , MoveCategory . SPECIAL , - 1 , 100 , 10 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . SWALLOW , Type . NORMAL , - 1 , 10 , - 1 , 0 , 3 )
. triageMove ( )
. unimplemented ( ) ,
new AttackMove ( Moves . HEAT_WAVE , Type . FIRE , MoveCategory . SPECIAL , 95 , 90 , 10 , 10 , 0 , 3 )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2023-05-01 14:41:44 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HAIL , Type . ICE , - 1 , 10 , - 1 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. attr ( WeatherChangeAttr , WeatherType . HAIL )
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TORMENT , Type . DARK , 100 , 15 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new StatusMove ( Moves . FLATTER , Type . DARK , 100 , 15 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , 1 )
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . WILL_O_WISP , Type . FIRE , 85 , 15 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MEMENTO , Type . DARK , 100 , 10 , - 1 , 0 , 3 )
2024-05-15 11:10:20 +02:00
. attr ( SacrificialAttrOnHit )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK ] , - 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FACADE , Type . NORMAL , MoveCategory . PHYSICAL , 70 , 100 , 20 , - 1 , 0 , 3 )
2023-12-10 17:57:12 -05:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . status
2024-05-13 11:06:15 -07:00
&& ( user . status . effect === StatusEffect . BURN || user . status . effect === StatusEffect . POISON || user . status . effect === StatusEffect . TOXIC || user . status . effect === StatusEffect . PARALYSIS ) ? 2 : 1 )
2024-05-15 06:36:34 -06:00
. attr ( BypassBurnDamageReductionAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FOCUS_PUNCH , Type . FIGHTING , MoveCategory . PHYSICAL , 150 , 100 , 20 , - 1 , - 3 , 3 )
2023-12-15 01:41:45 -06:00
. punchingMove ( )
2024-04-15 03:11:22 +10:00
. ignoresVirtual ( )
. condition ( ( user , target , move ) = > ! user . turnData . attacksReceived . find ( r = > r . damage ) ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SMELLING_SALTS , Type . NORMAL , MoveCategory . PHYSICAL , 70 , 100 , 10 , - 1 , 0 , 3 )
2023-12-10 17:57:12 -05:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . status ? . effect === StatusEffect . PARALYSIS ? 2 : 1 )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . FOLLOW_ME , Type . NORMAL , - 1 , 20 , - 1 , 2 , 3 )
. unimplemented ( ) ,
new StatusMove ( Moves . NATURE_POWER , Type . NORMAL , - 1 , 20 , - 1 , 0 , 3 )
2024-04-14 17:43:03 -04:00
. attr ( NaturePowerAttr )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . CHARGE , Type . ELECTRIC , - 1 , 20 , - 1 , 0 , 3 )
. attr ( StatChangeAttr , BattleStat . SPDEF , 1 , true )
2024-05-09 00:37:50 -04:00
. attr ( AddBattlerTagAttr , BattlerTagType . CHARGED , true , false ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TAUNT , Type . DARK , 100 , 20 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new StatusMove ( Moves . HELPING_HAND , Type . NORMAL , - 1 , 20 , - 1 , 5 , 3 )
2024-03-29 10:07:04 -04:00
. attr ( AddBattlerTagAttr , BattlerTagType . HELPING_HAND )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . NEAR_ALLY ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TRICK , Type . PSYCHIC , 100 , 10 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new StatusMove ( Moves . ROLE_PLAY , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 3 )
2024-04-14 13:21:34 +10:00
. attr ( AbilityCopyAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . WISH , Type . NORMAL , - 1 , 10 , - 1 , 0 , 3 )
. triageMove ( )
2024-04-30 11:38:24 -05:00
. attr ( AddArenaTagAttr , ArenaTagType . WISH , 2 , true ) ,
2024-04-30 13:39:16 -05:00
new SelfStatusMove ( Moves . ASSIST , Type . NORMAL , - 1 , 20 , - 1 , 0 , 3 )
2023-04-27 20:12:25 -04:00
. attr ( RandomMovesetMoveAttr , true )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . INGRAIN , Type . GRASS , - 1 , 20 , - 1 , 0 , 3 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . INGRAIN , true , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SUPERPOWER , Type . FIGHTING , MoveCategory . PHYSICAL , 120 , 100 , 5 , 100 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF ] , - 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . MAGIC_COAT , Type . PSYCHIC , - 1 , 15 , - 1 , 4 , 3 )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . RECYCLE , Type . NORMAL , - 1 , 10 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new AttackMove ( Moves . REVENGE , Type . FIGHTING , MoveCategory . PHYSICAL , 60 , 100 , 10 , - 1 , - 4 , 3 )
2024-04-15 03:11:22 +10:00
. attr ( TurnDamagedDoublePowerAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BRICK_BREAK , Type . FIGHTING , MoveCategory . PHYSICAL , 75 , 100 , 15 , - 1 , 0 , 3 )
2024-05-23 17:03:10 +02:00
. attr ( RemoveScreensAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . YAWN , Type . NORMAL , - 1 , 10 , - 1 , 0 , 3 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . DROWSY , false , true )
2023-12-10 17:57:12 -05:00
. condition ( ( user , target , move ) = > ! target . status ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . KNOCK_OFF , Type . DARK , MoveCategory . PHYSICAL , 65 , 100 , 20 , - 1 , 0 , 3 )
2024-06-15 22:26:54 -04:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . getHeldItems ( ) . filter ( i = > i . getTransferrable ( false ) ) . length > 0 ? 1.5 : 1 )
. attr ( RemoveHeldItemAttr , false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ENDEAVOR , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , 100 , 5 , - 1 , 0 , 3 )
2024-01-14 20:47:08 -05:00
. attr ( MatchHpAttr )
. condition ( failOnBossCondition ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ERUPTION , Type . FIRE , MoveCategory . SPECIAL , 150 , 100 , 5 , - 1 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. attr ( HpPowerAttr )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SKILL_SWAP , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 3 )
2024-03-04 21:32:11 -05:00
. attr ( SwitchAbilitiesAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . IMPRISON , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . REFRESH , Type . NORMAL , - 1 , 20 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . PARALYSIS , StatusEffect . POISON , StatusEffect . TOXIC , StatusEffect . BURN )
2023-12-10 17:57:12 -05:00
. condition ( ( user , target , move ) = > user . status && ( user . status . effect === StatusEffect . PARALYSIS || user . status . effect === StatusEffect . POISON || user . status . effect === StatusEffect . TOXIC || user . status . effect === StatusEffect . BURN ) ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . GRUDGE , Type . GHOST , - 1 , 5 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . SNATCH , Type . DARK , - 1 , 10 , - 1 , 4 , 3 )
. unimplemented ( ) ,
new AttackMove ( Moves . SECRET_POWER , Type . NORMAL , MoveCategory . PHYSICAL , 70 , 100 , 20 , 30 , 0 , 3 )
. makesContact ( false )
. partial ( ) ,
new AttackMove ( Moves . DIVE , Type . WATER , MoveCategory . PHYSICAL , 80 , 100 , 10 , - 1 , 0 , 3 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . DIVE_CHARGING , "hid\nunderwater!" , BattlerTagType . UNDERWATER )
2023-04-27 20:12:25 -04:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ARM_THRUST , Type . FIGHTING , MoveCategory . PHYSICAL , 15 , 100 , 20 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . CAMOUFLAGE , Type . NORMAL , - 1 , 20 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( CopyBiomeTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . TAIL_GLOW , Type . BUG , - 1 , 20 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , 3 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LUSTER_PURGE , Type . PSYCHIC , MoveCategory . SPECIAL , 95 , 100 , 5 , 50 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MIST_BALL , Type . PSYCHIC , MoveCategory . SPECIAL , 95 , 100 , 5 , 50 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . FEATHER_DANCE , Type . FLYING , 100 , 15 , - 1 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , - 2 )
. danceMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TEETER_DANCE , Type . NORMAL , 100 , 20 , - 1 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. attr ( ConfuseAttr )
2023-12-15 01:41:45 -06:00
. danceMove ( )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLAZE_KICK , Type . FIRE , MoveCategory . PHYSICAL , 85 , 90 , 10 , 10 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr )
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MUD_SPORT , Type . GROUND , - 1 , 15 , - 1 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. attr ( AddArenaTagAttr , ArenaTagType . MUD_SPORT , 5 )
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICE_BALL , Type . ICE , MoveCategory . PHYSICAL , 30 , 90 , 20 , - 1 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( ConsecutiveUseDoublePowerAttr , 5 , true , true , Moves . DEFENSE_CURL )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NEEDLE_ARM , Type . GRASS , MoveCategory . PHYSICAL , 60 , 100 , 15 , 30 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SLACK_OFF , Type . NORMAL , - 1 , 5 , - 1 , 0 , 3 )
2024-04-08 17:10:07 +03:00
. attr ( HealAttr , 0.5 )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYPER_VOICE , Type . NORMAL , MoveCategory . SPECIAL , 90 , 100 , 10 , - 1 , 0 , 3 )
2023-11-30 16:37:16 -05:00
. soundBased ( )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POISON_FANG , Type . POISON , MoveCategory . PHYSICAL , 50 , 100 , 15 , 50 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . TOXIC )
. bitingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CRUSH_CLAW , Type . NORMAL , MoveCategory . PHYSICAL , 75 , 95 , 10 , 50 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLAST_BURN , Type . FIRE , MoveCategory . SPECIAL , 150 , 90 , 5 , - 1 , 0 , 3 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYDRO_CANNON , Type . WATER , MoveCategory . SPECIAL , 150 , 90 , 5 , - 1 , 0 , 3 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . METEOR_MASH , Type . STEEL , MoveCategory . PHYSICAL , 90 , 90 , 10 , 20 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , 1 , true )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ASTONISH , Type . GHOST , MoveCategory . PHYSICAL , 30 , 100 , 15 , 30 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WEATHER_BALL , Type . NORMAL , MoveCategory . SPECIAL , 50 , 100 , 10 , - 1 , 0 , 3 )
2024-04-10 14:07:47 +10:00
. attr ( WeatherBallTypeAttr )
2024-04-15 22:35:35 +02:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > [ WeatherType . SUNNY , WeatherType . RAIN , WeatherType . SANDSTORM , WeatherType . HAIL , WeatherType . SNOW , WeatherType . FOG , WeatherType . HEAVY_RAIN , WeatherType . HARSH_SUN ] . includes ( user . scene . arena . weather ? . weatherType ) && ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) ? 2 : 1 )
2023-12-15 01:41:45 -06:00
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . AROMATHERAPY , Type . GRASS , - 1 , 5 , - 1 , 0 , 3 )
2024-05-09 15:15:56 -04:00
. attr ( PartyStatusCureAttr , "A soothing aroma wafted through the area!" , Abilities . SAP_SIPPER )
. target ( MoveTarget . PARTY ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . FAKE_TEARS , Type . DARK , 100 , 20 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AIR_CUTTER , Type . FLYING , MoveCategory . SPECIAL , 60 , 95 , 25 , - 1 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. attr ( HighCritAttr )
2023-12-15 01:41:45 -06:00
. slicingMove ( )
. windMove ( )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . OVERHEAT , Type . FIRE , MoveCategory . SPECIAL , 130 , 90 , 5 , 100 , 0 , 3 )
2024-02-28 15:15:27 -05:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 2 , true )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ODOR_SLEUTH , Type . NORMAL , - 1 , 40 , - 1 , 0 , 3 )
. unimplemented ( ) ,
new AttackMove ( Moves . ROCK_TOMB , Type . ROCK , MoveCategory . PHYSICAL , 60 , 95 , 15 , 100 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SILVER_WIND , Type . BUG , MoveCategory . SPECIAL , 60 , 100 , 5 , 10 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 1 , true )
. windMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . METAL_SOUND , Type . STEEL , 85 , 40 , - 1 , 0 , 3 )
2023-10-31 14:09:33 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 2 )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . GRASS_WHISTLE , Type . GRASS , 55 , 15 , - 1 , 0 , 3 )
2023-10-31 14:09:33 -04:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TICKLE , Type . NORMAL , 100 , 20 , - 1 , 0 , 3 )
2024-05-05 01:28:15 +03:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF ] , - 1 ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . COSMIC_POWER , Type . PSYCHIC , - 1 , 20 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF ] , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WATER_SPOUT , Type . WATER , MoveCategory . SPECIAL , 150 , 100 , 5 , - 1 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. attr ( HpPowerAttr )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SIGNAL_BEAM , Type . BUG , MoveCategory . SPECIAL , 75 , 100 , 15 , 10 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHADOW_PUNCH , Type . GHOST , MoveCategory . PHYSICAL , 60 , - 1 , 20 , - 1 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EXTRASENSORY , Type . PSYCHIC , MoveCategory . SPECIAL , 80 , 100 , 20 , 10 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SKY_UPPERCUT , Type . FIGHTING , MoveCategory . PHYSICAL , 85 , 90 , 15 , - 1 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( HitsTagAttr , BattlerTagType . FLYING )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SAND_TOMB , Type . GROUND , MoveCategory . PHYSICAL , 35 , 85 , 15 , 100 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( TrapAttr , BattlerTagType . SAND_TOMB )
. makesContact ( false ) ,
2024-05-14 14:01:37 -04:00
new AttackMove ( Moves . SHEER_COLD , Type . ICE , MoveCategory . SPECIAL , 200 , 20 , 5 , - 1 , 0 , 3 )
. attr ( IceNoEffectTypeAttr )
2023-11-30 16:37:16 -05:00
. attr ( OneHitKOAttr )
2024-05-14 14:01:37 -04:00
. attr ( SheerColdAccuracyAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MUDDY_WATER , Type . WATER , MoveCategory . SPECIAL , 90 , 85 , 10 , 30 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BULLET_SEED , Type . GRASS , MoveCategory . PHYSICAL , 25 , 100 , 30 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr )
2023-12-15 01:41:45 -06:00
. makesContact ( false )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AERIAL_ACE , Type . FLYING , MoveCategory . PHYSICAL , 60 , - 1 , 20 , - 1 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICICLE_SPEAR , Type . ICE , MoveCategory . PHYSICAL , 25 , 100 , 30 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . IRON_DEFENSE , Type . STEEL , - 1 , 15 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . BLOCK , Type . NORMAL , - 1 , 5 , - 1 , 0 , 3 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , false , true , 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HOWL , Type . NORMAL , - 1 , 40 , - 1 , 0 , 3 )
2024-03-06 22:41:55 -05:00
. attr ( StatChangeAttr , BattleStat . ATK , 1 )
2023-11-30 16:37:16 -05:00
. soundBased ( )
. target ( MoveTarget . USER_AND_ALLIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_CLAW , Type . DRAGON , MoveCategory . PHYSICAL , 80 , 100 , 15 , - 1 , 0 , 3 ) ,
new AttackMove ( Moves . FRENZY_PLANT , Type . GRASS , MoveCategory . SPECIAL , 150 , 90 , 5 , - 1 , 0 , 3 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . BULK_UP , Type . FIGHTING , - 1 , 20 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF ] , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BOUNCE , Type . FLYING , MoveCategory . PHYSICAL , 85 , 85 , 5 , 30 , 0 , 3 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . BOUNCE_CHARGING , "sprang up!" , BattlerTagType . FLYING )
2023-04-27 20:12:25 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
2023-05-08 18:48:35 -04:00
. condition ( failOnGravityCondition )
2023-11-30 16:37:16 -05:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MUD_SHOT , Type . GROUND , MoveCategory . SPECIAL , 55 , 95 , 15 , 100 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POISON_TAIL , Type . POISON , MoveCategory . PHYSICAL , 50 , 100 , 25 , 10 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr )
. attr ( StatusEffectAttr , StatusEffect . POISON ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . COVET , Type . NORMAL , MoveCategory . PHYSICAL , 60 , 100 , 25 , - 1 , 0 , 3 )
2024-03-04 21:51:28 -05:00
. attr ( StealHeldItemChanceAttr , 0.3 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . VOLT_TACKLE , Type . ELECTRIC , MoveCategory . PHYSICAL , 120 , 100 , 15 , 10 , 0 , 3 )
2024-04-04 15:17:38 -05:00
. attr ( RecoilAttr , false , 0.33 )
2024-05-07 23:28:35 -05:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAGICAL_LEAF , Type . GRASS , MoveCategory . SPECIAL , 60 , - 1 , 20 , - 1 , 0 , 3 ) ,
new StatusMove ( Moves . WATER_SPORT , Type . WATER , - 1 , 15 , - 1 , 0 , 3 )
2023-05-01 14:41:44 -04:00
. attr ( AddArenaTagAttr , ArenaTagType . WATER_SPORT , 5 )
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . CALM_MIND , Type . PSYCHIC , - 1 , 20 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . SPATK , BattleStat . SPDEF ] , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LEAF_BLADE , Type . GRASS , MoveCategory . PHYSICAL , 90 , 100 , 15 , - 1 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( HighCritAttr )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . DRAGON_DANCE , Type . DRAGON , - 1 , 20 , - 1 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPD ] , 1 , true )
. danceMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ROCK_BLAST , Type . ROCK , MoveCategory . PHYSICAL , 25 , 90 , 10 , - 1 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr )
2023-12-15 01:41:45 -06:00
. makesContact ( false )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHOCK_WAVE , Type . ELECTRIC , MoveCategory . SPECIAL , 60 , - 1 , 20 , - 1 , 0 , 3 ) ,
new AttackMove ( Moves . WATER_PULSE , Type . WATER , MoveCategory . SPECIAL , 60 , 100 , 20 , 20 , 0 , 3 )
2023-12-15 01:41:45 -06:00
. attr ( ConfuseAttr )
. pulseMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DOOM_DESIRE , Type . STEEL , MoveCategory . SPECIAL , 140 , 100 , 5 , - 1 , 0 , 3 )
2024-05-23 17:03:10 +02:00
. attr ( DelayedAttackAttr , ArenaTagType . DOOM_DESIRE , ChargeAnim . DOOM_DESIRE_CHARGING , "chose\nDoom Desire as its destiny!" ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYCHO_BOOST , Type . PSYCHIC , MoveCategory . SPECIAL , 140 , 90 , 5 , 100 , 0 , 3 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 2 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . ROOST , Type . FLYING , - 1 , 5 , - 1 , 0 , 4 )
2023-10-23 22:23:18 -04:00
. attr ( HealAttr , 0.5 )
2024-04-16 14:31:30 -04:00
. attr ( AddBattlerTagAttr , BattlerTagType . GROUNDED , true , false , 1 )
2024-04-08 17:10:07 +03:00
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . GRAVITY , Type . PSYCHIC , - 1 , 5 , - 1 , 0 , 4 )
2023-05-08 18:48:35 -04:00
. attr ( AddArenaTagAttr , ArenaTagType . GRAVITY , 5 )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MIRACLE_EYE , Type . PSYCHIC , - 1 , 40 , - 1 , 0 , 4 )
. unimplemented ( ) ,
new AttackMove ( Moves . WAKE_UP_SLAP , Type . FIGHTING , MoveCategory . PHYSICAL , 70 , 100 , 10 , - 1 , 0 , 4 )
2024-05-27 05:01:03 -06:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > targetSleptOrComatoseCondition ( user , target , move ) ? 2 : 1 )
2023-05-08 18:48:35 -04:00
. attr ( HealStatusEffectAttr , false , StatusEffect . SLEEP ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HAMMER_ARM , Type . FIGHTING , MoveCategory . PHYSICAL , 100 , 90 , 10 , 100 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 , true )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GYRO_BALL , Type . STEEL , MoveCategory . PHYSICAL , - 1 , 100 , 5 , - 1 , 0 , 4 )
2024-05-17 07:42:43 +02:00
. attr ( GyroBallPowerAttr )
2023-12-15 01:41:45 -06:00
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . HEALING_WISH , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 4 )
2024-04-08 17:10:07 +03:00
. attr ( SacrificialFullRestoreAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BRINE , Type . WATER , MoveCategory . SPECIAL , 65 , 100 , 10 , - 1 , 0 , 4 )
2023-12-10 17:57:12 -05:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . getHpRatio ( ) < 0.5 ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NATURAL_GIFT , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , 100 , 15 , - 1 , 0 , 4 )
. makesContact ( false )
. unimplemented ( ) ,
new AttackMove ( Moves . FEINT , Type . NORMAL , MoveCategory . PHYSICAL , 30 , 100 , 10 , - 1 , 2 , 4 )
2024-02-20 12:27:38 -05:00
. attr ( RemoveBattlerTagAttr , [ BattlerTagType . PROTECTED ] )
2024-05-25 04:22:10 -07:00
. attr ( RemoveArenaTagsAttr , [ ArenaTagType . QUICK_GUARD , ArenaTagType . WIDE_GUARD , ArenaTagType . MAT_BLOCK , ArenaTagType . CRAFTY_SHIELD ] , false )
2023-04-27 14:30:03 -04:00
. makesContact ( false )
. ignoresProtect ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PLUCK , Type . FLYING , MoveCategory . PHYSICAL , 60 , 100 , 20 , - 1 , 0 , 4 )
2024-05-19 18:47:30 -04:00
. attr ( StealEatBerryAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TAILWIND , Type . FLYING , - 1 , 15 , - 1 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. windMove ( )
2024-05-02 14:10:21 -05:00
. attr ( AddArenaTagAttr , ArenaTagType . TAILWIND , 4 , true )
. target ( MoveTarget . USER_SIDE ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ACUPRESSURE , Type . NORMAL , - 1 , 30 , - 1 , 0 , 4 )
2024-05-03 22:30:23 -04:00
. attr ( AcupressureStatChangeAttr )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . USER_OR_NEAR_ALLY ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . METAL_BURST , Type . STEEL , MoveCategory . PHYSICAL , - 1 , 100 , 10 , - 1 , 0 , 4 )
2024-04-08 12:13:34 -04:00
. attr ( CounterDamageAttr , ( move : Move ) = > ( move . category === MoveCategory . PHYSICAL || move . category === MoveCategory . SPECIAL ) , 1.5 )
2023-05-01 14:41:44 -04:00
. makesContact ( false )
. target ( MoveTarget . ATTACKER ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . U_TURN , Type . BUG , MoveCategory . PHYSICAL , 70 , 100 , 20 , - 1 , 0 , 4 )
2024-04-17 09:56:13 +07:00
. attr ( ForceSwitchOutAttr , true , false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CLOSE_COMBAT , Type . FIGHTING , MoveCategory . PHYSICAL , 120 , 100 , 5 , 100 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF ] , - 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PAYBACK , Type . DARK , MoveCategory . PHYSICAL , 50 , 100 , 10 , - 1 , 0 , 4 )
2024-05-24 01:45:04 +02:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . getLastXMoves ( 1 ) . find ( m = > m . turn === target . scene . currentBattle . turn ) || user . scene . currentBattle . turnCommands [ target . getBattlerIndex ( ) ] . command === Command . BALL ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ASSURANCE , Type . DARK , MoveCategory . PHYSICAL , 60 , 100 , 10 , - 1 , 0 , 4 )
2024-04-25 20:51:04 -04:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . turnData . damageTaken > 0 ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . EMBARGO , Type . DARK , 100 , 15 , - 1 , 0 , 4 )
. unimplemented ( ) ,
new AttackMove ( Moves . FLING , Type . DARK , MoveCategory . PHYSICAL , - 1 , 100 , 10 , - 1 , 0 , 4 )
. makesContact ( false )
. unimplemented ( ) ,
new StatusMove ( Moves . PSYCHO_SHIFT , Type . PSYCHIC , 100 , 10 , - 1 , 0 , 4 )
2024-04-16 13:00:55 -04:00
. attr ( PsychoShiftEffectAttr )
2024-04-16 14:34:57 -04:00
. condition ( ( user , target , move ) = > ( user . status ? . effect === StatusEffect . BURN
|| user . status ? . effect === StatusEffect . POISON
|| user . status ? . effect === StatusEffect . TOXIC
|| user . status ? . effect === StatusEffect . PARALYSIS
|| user . status ? . effect === StatusEffect . SLEEP )
2024-05-14 14:00:37 -04:00
&& target . canSetStatus ( user . status ? . effect , false , false , user )
2024-05-23 17:03:10 +02:00
) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TRUMP_CARD , Type . NORMAL , MoveCategory . SPECIAL , - 1 , - 1 , 5 , - 1 , 0 , 4 )
. makesContact ( )
2024-05-19 20:17:58 +02:00
. attr ( LessPPMorePowerAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HEAL_BLOCK , Type . PSYCHIC , 100 , 15 , - 1 , 0 , 4 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . WRING_OUT , Type . NORMAL , MoveCategory . SPECIAL , - 1 , 100 , 5 , - 1 , 0 , 4 )
2024-03-11 18:18:49 +01:00
. attr ( OpponentHighHpPowerAttr )
2023-04-27 14:30:03 -04:00
. makesContact ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . POWER_TRICK , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 4 )
. unimplemented ( ) ,
new StatusMove ( Moves . GASTRO_ACID , Type . POISON , 100 , 10 , - 1 , 0 , 4 )
2024-05-02 14:22:30 +10:00
. attr ( SuppressAbilitiesAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . LUCKY_CHANT , Type . NORMAL , - 1 , 30 , - 1 , 0 , 4 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . NO_CRIT , false , false , 5 )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . USER_SIDE )
. unimplemented ( ) ,
new StatusMove ( Moves . ME_FIRST , Type . NORMAL , - 1 , 20 , - 1 , 0 , 4 )
2023-05-01 14:41:44 -04:00
. ignoresVirtual ( )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . NEAR_ENEMY )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . COPYCAT , Type . NORMAL , - 1 , 20 , - 1 , 0 , 4 )
2023-04-27 20:12:25 -04:00
. attr ( CopyMoveAttr )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . POWER_SWAP , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 4 )
. unimplemented ( ) ,
new StatusMove ( Moves . GUARD_SWAP , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 4 )
. unimplemented ( ) ,
new AttackMove ( Moves . PUNISHMENT , Type . DARK , MoveCategory . PHYSICAL , - 1 , 100 , 5 , - 1 , 0 , 4 )
2024-05-30 17:01:42 -04:00
. makesContact ( true )
. attr ( PunishmentPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LAST_RESORT , Type . NORMAL , MoveCategory . PHYSICAL , 140 , 100 , 5 , - 1 , 0 , 4 )
2024-05-01 18:17:12 -04:00
. attr ( LastResortAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . WORRY_SEED , Type . GRASS , 100 , 10 , - 1 , 0 , 4 )
2024-04-14 13:21:34 +10:00
. attr ( AbilityChangeAttr , Abilities . INSOMNIA ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SUCKER_PUNCH , Type . DARK , MoveCategory . PHYSICAL , 70 , 100 , 5 , - 1 , 1 , 4 )
2024-04-15 02:05:32 +10:00
. condition ( ( user , target , move ) = > user . scene . currentBattle . turnCommands [ target . getBattlerIndex ( ) ] . command === Command . FIGHT && ! target . turnData . acted && allMoves [ user . scene . currentBattle . turnCommands [ target . getBattlerIndex ( ) ] . move . move ] . category !== MoveCategory . STATUS ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TOXIC_SPIKES , Type . POISON , - 1 , 20 , - 1 , 0 , 4 )
2023-05-01 14:41:44 -04:00
. attr ( AddArenaTrapTagAttr , ArenaTagType . TOXIC_SPIKES )
. target ( MoveTarget . ENEMY_SIDE ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HEART_SWAP , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 4 )
2024-05-11 15:42:57 +01:00
. attr ( SwapStatsAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . AQUA_RING , Type . WATER , - 1 , 20 , - 1 , 0 , 4 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . AQUA_RING , true , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . MAGNET_RISE , Type . ELECTRIC , - 1 , 10 , - 1 , 0 , 4 )
2024-05-03 22:10:40 -04:00
. attr ( AddBattlerTagAttr , BattlerTagType . MAGNET_RISEN , true , true )
2024-05-24 01:45:04 +02:00
. condition ( ( user , target , move ) = > ! user . scene . arena . getTag ( ArenaTagType . GRAVITY ) &&
2024-05-03 22:10:40 -04:00
! user . getTag ( BattlerTagType . IGNORE_FLYING ) && ! user . getTag ( BattlerTagType . INGRAIN ) &&
! user . getTag ( BattlerTagType . MAGNET_RISEN ) )
2024-04-16 20:29:32 +02:00
. unimplemented ( ) ,
new AttackMove ( Moves . FLARE_BLITZ , Type . FIRE , MoveCategory . PHYSICAL , 120 , 100 , 15 , 10 , 0 , 4 )
2024-04-04 15:17:38 -05:00
. attr ( RecoilAttr , false , 0.33 )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2023-05-08 18:48:35 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
2024-05-07 23:28:35 -05:00
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FORCE_PALM , Type . FIGHTING , MoveCategory . PHYSICAL , 60 , 100 , 10 , 30 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AURA_SPHERE , Type . FIGHTING , MoveCategory . SPECIAL , 80 , - 1 , 20 , - 1 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. pulseMove ( )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . ROCK_POLISH , Type . ROCK , - 1 , 20 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POISON_JAB , Type . POISON , MoveCategory . PHYSICAL , 80 , 100 , 20 , 30 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . POISON ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DARK_PULSE , Type . DARK , MoveCategory . SPECIAL , 80 , 100 , 15 , 20 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( FlinchAttr )
. pulseMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NIGHT_SLASH , Type . DARK , MoveCategory . PHYSICAL , 70 , 100 , 15 , - 1 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( HighCritAttr )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AQUA_TAIL , Type . WATER , MoveCategory . PHYSICAL , 90 , 90 , 10 , - 1 , 0 , 4 ) ,
new AttackMove ( Moves . SEED_BOMB , Type . GRASS , MoveCategory . PHYSICAL , 80 , 100 , 15 , - 1 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. makesContact ( false )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AIR_SLASH , Type . FLYING , MoveCategory . SPECIAL , 75 , 95 , 15 , 30 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( FlinchAttr )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . X_SCISSOR , Type . BUG , MoveCategory . PHYSICAL , 80 , 100 , 15 , - 1 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BUG_BUZZ , Type . BUG , MoveCategory . SPECIAL , 90 , 100 , 10 , 10 , 0 , 4 )
2023-10-31 14:09:33 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_PULSE , Type . DRAGON , MoveCategory . SPECIAL , 85 , 100 , 10 , - 1 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. pulseMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_RUSH , Type . DRAGON , MoveCategory . PHYSICAL , 100 , 75 , 10 , 20 , 0 , 4 )
2024-05-15 06:36:34 -06:00
. attr ( MinimizeAccuracyAttr )
. attr ( HitsTagAttr , BattlerTagType . MINIMIZED , true )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POWER_GEM , Type . ROCK , MoveCategory . SPECIAL , 80 , 100 , 20 , - 1 , 0 , 4 ) ,
new AttackMove ( Moves . DRAIN_PUNCH , Type . FIGHTING , MoveCategory . PHYSICAL , 75 , 100 , 10 , - 1 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( HitHealAttr )
2024-04-08 17:10:07 +03:00
. punchingMove ( )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . VACUUM_WAVE , Type . FIGHTING , MoveCategory . SPECIAL , 40 , 100 , 30 , - 1 , 1 , 4 ) ,
new AttackMove ( Moves . FOCUS_BLAST , Type . FIGHTING , MoveCategory . SPECIAL , 120 , 70 , 5 , 10 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ENERGY_BALL , Type . GRASS , MoveCategory . SPECIAL , 90 , 100 , 10 , 10 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BRAVE_BIRD , Type . FLYING , MoveCategory . PHYSICAL , 120 , 100 , 15 , - 1 , 0 , 4 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr , false , 0.33 )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EARTH_POWER , Type . GROUND , MoveCategory . SPECIAL , 90 , 100 , 10 , 10 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SWITCHEROO , Type . DARK , 100 , 10 , - 1 , 0 , 4 )
. unimplemented ( ) ,
new AttackMove ( Moves . GIGA_IMPACT , Type . NORMAL , MoveCategory . PHYSICAL , 150 , 90 , 5 , - 1 , 0 , 4 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . NASTY_PLOT , Type . DARK , - 1 , 20 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BULLET_PUNCH , Type . STEEL , MoveCategory . PHYSICAL , 40 , 100 , 30 , - 1 , 1 , 4 )
2023-12-15 01:41:45 -06:00
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AVALANCHE , Type . ICE , MoveCategory . PHYSICAL , 60 , 100 , 10 , - 1 , - 4 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( TurnDamagedDoublePowerAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICE_SHARD , Type . ICE , MoveCategory . PHYSICAL , 40 , 100 , 30 , - 1 , 1 , 4 )
2023-04-27 14:30:03 -04:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHADOW_CLAW , Type . GHOST , MoveCategory . PHYSICAL , 70 , 100 , 15 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THUNDER_FANG , Type . ELECTRIC , MoveCategory . PHYSICAL , 65 , 95 , 15 , 10 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
. bitingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICE_FANG , Type . ICE , MoveCategory . PHYSICAL , 65 , 95 , 15 , 10 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . FREEZE )
. bitingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FIRE_FANG , Type . FIRE , MoveCategory . PHYSICAL , 65 , 95 , 15 , 10 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
. bitingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHADOW_SNEAK , Type . GHOST , MoveCategory . PHYSICAL , 40 , 100 , 30 , - 1 , 1 , 4 ) ,
new AttackMove ( Moves . MUD_BOMB , Type . GROUND , MoveCategory . SPECIAL , 65 , 85 , 10 , 30 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYCHO_CUT , Type . PSYCHIC , MoveCategory . PHYSICAL , 70 , 100 , 20 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr )
2023-12-15 01:41:45 -06:00
. slicingMove ( )
2023-04-27 14:30:03 -04:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ZEN_HEADBUTT , Type . PSYCHIC , MoveCategory . PHYSICAL , 80 , 90 , 15 , 20 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MIRROR_SHOT , Type . STEEL , MoveCategory . SPECIAL , 65 , 85 , 10 , 30 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLASH_CANNON , Type . STEEL , MoveCategory . SPECIAL , 80 , 100 , 10 , 10 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ROCK_CLIMB , Type . NORMAL , MoveCategory . PHYSICAL , 90 , 85 , 20 , 20 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . DEFOG , Type . FLYING , - 1 , 15 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . EVA , - 1 )
2024-03-09 22:05:49 -05:00
. attr ( ClearWeatherAttr , WeatherType . FOG )
2024-04-14 22:26:58 -04:00
. attr ( ClearTerrainAttr )
2024-05-06 23:00:31 -04:00
. attr ( RemoveScreensAttr , false )
. attr ( RemoveArenaTrapAttr , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TRICK_ROOM , Type . PSYCHIC , - 1 , 5 , - 1 , - 7 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( AddArenaTagAttr , ArenaTagType . TRICK_ROOM , 5 )
2023-05-01 14:41:44 -04:00
. ignoresProtect ( )
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRACO_METEOR , Type . DRAGON , MoveCategory . SPECIAL , 130 , 90 , 5 , 100 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DISCHARGE , Type . ELECTRIC , MoveCategory . SPECIAL , 80 , 100 , 15 , 30 , 0 , 4 )
2023-05-01 14:41:44 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LAVA_PLUME , Type . FIRE , MoveCategory . SPECIAL , 80 , 100 , 15 , 30 , 0 , 4 )
2023-05-01 14:41:44 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LEAF_STORM , Type . GRASS , MoveCategory . SPECIAL , 130 , 90 , 5 , 100 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POWER_WHIP , Type . GRASS , MoveCategory . PHYSICAL , 120 , 85 , 10 , - 1 , 0 , 4 ) ,
new AttackMove ( Moves . ROCK_WRECKER , Type . ROCK , MoveCategory . PHYSICAL , 150 , 90 , 5 , - 1 , 0 , 4 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr )
2023-12-15 01:41:45 -06:00
. makesContact ( false )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CROSS_POISON , Type . POISON , MoveCategory . PHYSICAL , 70 , 100 , 20 , 10 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GUNK_SHOT , Type . POISON , MoveCategory . PHYSICAL , 120 , 80 , 5 , 30 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . IRON_HEAD , Type . STEEL , MoveCategory . PHYSICAL , 80 , 100 , 15 , 30 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAGNET_BOMB , Type . STEEL , MoveCategory . PHYSICAL , 60 , - 1 , 20 , - 1 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. makesContact ( false )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STONE_EDGE , Type . ROCK , MoveCategory . PHYSICAL , 100 , 80 , 5 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . CAPTIVATE , Type . NORMAL , 100 , 20 , - 1 , 0 , 4 )
2023-05-05 18:20:55 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 2 )
2023-12-10 17:57:12 -05:00
. condition ( ( user , target , move ) = > target . isOppositeGender ( user ) )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . STEALTH_ROCK , Type . ROCK , - 1 , 20 , - 1 , 0 , 4 )
2023-11-30 16:37:16 -05:00
. attr ( AddArenaTrapTagAttr , ArenaTagType . STEALTH_ROCK )
. target ( MoveTarget . ENEMY_SIDE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GRASS_KNOT , Type . GRASS , MoveCategory . SPECIAL , - 1 , 100 , 20 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( WeightPowerAttr )
2024-04-24 01:57:59 +10:00
. makesContact ( )
. condition ( failOnMaxCondition ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CHATTER , Type . FLYING , MoveCategory . SPECIAL , 65 , 100 , 20 , 100 , 0 , 4 )
2023-05-01 14:41:44 -04:00
. attr ( ConfuseAttr )
2023-10-31 14:09:33 -04:00
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . JUDGMENT , Type . NORMAL , MoveCategory . SPECIAL , 100 , 100 , 10 , - 1 , 0 , 4 )
2024-06-10 08:58:34 -05:00
. attr ( FormChangeItemTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BUG_BITE , Type . BUG , MoveCategory . PHYSICAL , 60 , 100 , 20 , - 1 , 0 , 4 )
2024-05-19 18:47:30 -04:00
. attr ( StealEatBerryAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CHARGE_BEAM , Type . ELECTRIC , MoveCategory . SPECIAL , 50 , 90 , 10 , 70 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WOOD_HAMMER , Type . GRASS , MoveCategory . PHYSICAL , 120 , 100 , 15 , - 1 , 0 , 4 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr , false , 0.33 )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AQUA_JET , Type . WATER , MoveCategory . PHYSICAL , 40 , 100 , 20 , - 1 , 1 , 4 ) ,
new AttackMove ( Moves . ATTACK_ORDER , Type . BUG , MoveCategory . PHYSICAL , 90 , 100 , 15 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . DEFEND_ORDER , Type . BUG , - 1 , 10 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF ] , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . HEAL_ORDER , Type . BUG , - 1 , 10 , - 1 , 0 , 4 )
2024-04-08 17:10:07 +03:00
. attr ( HealAttr , 0.5 )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HEAD_SMASH , Type . ROCK , MoveCategory . PHYSICAL , 150 , 80 , 5 , - 1 , 0 , 4 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr , false , 0.5 )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DOUBLE_HIT , Type . NORMAL , MoveCategory . PHYSICAL , 35 , 90 , 10 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr , MultiHitType . _2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ROAR_OF_TIME , Type . DRAGON , MoveCategory . SPECIAL , 150 , 90 , 5 , - 1 , 0 , 4 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPACIAL_REND , Type . DRAGON , MoveCategory . SPECIAL , 100 , 95 , 5 , - 1 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . LUNAR_DANCE , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 4 )
2024-05-15 11:10:20 +02:00
. attr ( SacrificialAttrOnHit )
2024-04-08 17:10:07 +03:00
. danceMove ( )
2024-04-16 20:29:32 +02:00
. triageMove ( )
. unimplemented ( ) ,
new AttackMove ( Moves . CRUSH_GRIP , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , 100 , 5 , - 1 , 0 , 4 )
2023-05-08 18:48:35 -04:00
. attr ( OpponentHighHpPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAGMA_STORM , Type . FIRE , MoveCategory . SPECIAL , 100 , 75 , 5 , 100 , 0 , 4 )
2023-04-27 14:30:03 -04:00
. attr ( TrapAttr , BattlerTagType . MAGMA_STORM ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . DARK_VOID , Type . DARK , 50 , 10 , - 1 , 0 , 4 )
2023-05-01 14:41:44 -04:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SEED_FLARE , Type . GRASS , MoveCategory . SPECIAL , 120 , 85 , 5 , 40 , 0 , 4 )
2024-05-16 00:12:19 -05:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . OMINOUS_WIND , Type . GHOST , MoveCategory . SPECIAL , 60 , 100 , 5 , 10 , 0 , 4 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 1 , true )
. windMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHADOW_FORCE , Type . GHOST , MoveCategory . PHYSICAL , 120 , 100 , 5 , - 1 , 0 , 4 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . SHADOW_FORCE_CHARGING , "vanished\ninstantly!" , BattlerTagType . HIDDEN )
2023-04-27 20:12:25 -04:00
. ignoresProtect ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . HONE_CLAWS , Type . DARK , - 1 , 15 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . ACC ] , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . WIDE_GUARD , Type . ROCK , - 1 , 10 , - 1 , 3 , 5 )
. target ( MoveTarget . USER_SIDE )
2024-05-25 04:22:10 -07:00
. attr ( AddArenaTagAttr , ArenaTagType . WIDE_GUARD , 1 , true , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . GUARD_SPLIT , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 5 )
2024-05-15 10:13:29 -04:00
. unimplemented ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . POWER_SPLIT , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 5 )
2024-05-15 10:13:29 -04:00
. unimplemented ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . WONDER_ROOM , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 5 )
2023-05-01 14:41:44 -04:00
. ignoresProtect ( )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . BOTH_SIDES )
. unimplemented ( ) ,
new AttackMove ( Moves . PSYSHOCK , Type . PSYCHIC , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 5 )
2024-03-11 18:18:55 -04:00
. attr ( DefDefAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . VENOSHOCK , Type . POISON , MoveCategory . SPECIAL , 65 , 100 , 10 , - 1 , 0 , 5 )
2023-12-10 17:57:12 -05:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . status && ( target . status . effect === StatusEffect . POISON || target . status . effect === StatusEffect . TOXIC ) ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . AUTOTOMIZE , Type . STEEL , - 1 , 15 , - 1 , 0 , 5 )
. attr ( StatChangeAttr , BattleStat . SPD , 2 , true )
. partial ( ) ,
new SelfStatusMove ( Moves . RAGE_POWDER , Type . BUG , - 1 , 20 , - 1 , 2 , 5 )
. powderMove ( )
. unimplemented ( ) ,
new StatusMove ( Moves . TELEKINESIS , Type . PSYCHIC , - 1 , 15 , - 1 , 0 , 5 )
. condition ( failOnGravityCondition )
. unimplemented ( ) ,
new StatusMove ( Moves . MAGIC_ROOM , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 5 )
2023-05-01 14:41:44 -04:00
. ignoresProtect ( )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . BOTH_SIDES )
. unimplemented ( ) ,
new AttackMove ( Moves . SMACK_DOWN , Type . ROCK , MoveCategory . PHYSICAL , 50 , 100 , 15 , 100 , 0 , 5 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . IGNORE_FLYING , false , false , 5 )
2024-05-02 22:20:41 -07:00
. attr ( AddBattlerTagAttr , BattlerTagType . INTERRUPTED )
. attr ( RemoveBattlerTagAttr , [ BattlerTagType . FLYING ] )
2024-04-15 12:55:35 -07:00
. attr ( HitsTagAttr , BattlerTagType . FLYING , false )
2023-04-27 14:30:03 -04:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STORM_THROW , Type . FIGHTING , MoveCategory . PHYSICAL , 60 , 100 , 10 , - 1 , 0 , 5 )
2023-05-05 18:20:55 -04:00
. attr ( CritOnlyAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLAME_BURST , Type . FIRE , MoveCategory . SPECIAL , 70 , 100 , 15 , - 1 , 0 , 5 )
. partial ( ) ,
new AttackMove ( Moves . SLUDGE_WAVE , Type . POISON , MoveCategory . SPECIAL , 95 , 100 , 10 , 10 , 0 , 5 )
2023-11-30 16:37:16 -05:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . QUIVER_DANCE , Type . BUG , - 1 , 20 , - 1 , 0 , 5 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , [ BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 1 , true )
. danceMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HEAVY_SLAM , Type . STEEL , MoveCategory . PHYSICAL , - 1 , 100 , 10 , - 1 , 0 , 5 )
2024-05-15 06:36:34 -06:00
. attr ( MinimizeAccuracyAttr )
2024-04-24 01:57:59 +10:00
. attr ( CompareWeightPowerAttr )
2024-05-15 06:36:34 -06:00
. attr ( HitsTagAttr , BattlerTagType . MINIMIZED , true )
2024-04-24 01:57:59 +10:00
. condition ( failOnMaxCondition ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SYNCHRONOISE , Type . PSYCHIC , MoveCategory . SPECIAL , 120 , 100 , 10 , - 1 , 0 , 5 )
. target ( MoveTarget . ALL_NEAR_OTHERS )
2024-05-01 16:14:19 -04:00
. condition ( unknownTypeCondition )
. attr ( hitsSameTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ELECTRO_BALL , Type . ELECTRIC , MoveCategory . SPECIAL , - 1 , 100 , 10 , - 1 , 0 , 5 )
2024-05-17 07:42:43 +02:00
. attr ( ElectroBallPowerAttr )
2023-12-15 01:41:45 -06:00
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SOAK , Type . WATER , 100 , 20 , - 1 , 0 , 5 )
2024-04-20 03:32:40 +10:00
. attr ( ChangeTypeAttr , Type . WATER ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLAME_CHARGE , Type . FIRE , MoveCategory . PHYSICAL , 50 , 100 , 20 , 100 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . COIL , Type . POISON , - 1 , 20 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . ACC ] , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LOW_SWEEP , Type . FIGHTING , MoveCategory . PHYSICAL , 65 , 100 , 20 , 100 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ACID_SPRAY , Type . POISON , MoveCategory . SPECIAL , 40 , 100 , 20 , 100 , 0 , 5 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 2 )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FOUL_PLAY , Type . DARK , MoveCategory . PHYSICAL , 95 , 100 , 15 , - 1 , 0 , 5 )
2024-04-02 18:03:49 -05:00
. attr ( TargetAtkUserAtkAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SIMPLE_BEAM , Type . NORMAL , 100 , 15 , - 1 , 0 , 5 )
2024-04-14 13:21:34 +10:00
. attr ( AbilityChangeAttr , Abilities . SIMPLE ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ENTRAINMENT , Type . NORMAL , 100 , 15 , - 1 , 0 , 5 )
2024-04-14 13:21:34 +10:00
. attr ( AbilityGiveAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . AFTER_YOU , Type . NORMAL , - 1 , 15 , - 1 , 0 , 5 )
. ignoresProtect ( )
. unimplemented ( ) ,
new AttackMove ( Moves . ROUND , Type . NORMAL , MoveCategory . SPECIAL , 60 , 100 , 15 , - 1 , 0 , 5 )
. soundBased ( )
. partial ( ) ,
new AttackMove ( Moves . ECHOED_VOICE , Type . NORMAL , MoveCategory . SPECIAL , 40 , 100 , 15 , - 1 , 0 , 5 )
2023-10-31 14:09:33 -04:00
. attr ( ConsecutiveUseMultiBasePowerAttr , 5 , false )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CHIP_AWAY , Type . NORMAL , MoveCategory . PHYSICAL , 70 , 100 , 20 , - 1 , 0 , 5 )
2024-04-02 20:51:38 +03:00
. attr ( IgnoreOpponentStatChangesAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CLEAR_SMOG , Type . POISON , MoveCategory . SPECIAL , 50 , - 1 , 15 , - 1 , 0 , 5 )
2024-04-18 16:28:22 +10:00
. attr ( ResetStatsAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STORED_POWER , Type . PSYCHIC , MoveCategory . SPECIAL , 20 , 100 , 10 , - 1 , 0 , 5 )
2024-04-05 01:33:42 +02:00
. attr ( StatChangeCountPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . QUICK_GUARD , Type . FIGHTING , - 1 , 15 , - 1 , 3 , 5 )
. target ( MoveTarget . USER_SIDE )
2024-05-25 04:22:10 -07:00
. attr ( AddArenaTagAttr , ArenaTagType . QUICK_GUARD , 1 , true , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . ALLY_SWITCH , Type . PSYCHIC , - 1 , 15 , - 1 , 2 , 5 )
. ignoresProtect ( )
. unimplemented ( ) ,
new AttackMove ( Moves . SCALD , Type . WATER , MoveCategory . SPECIAL , 80 , 100 , 15 , 30 , 0 , 5 )
2024-02-28 15:15:27 -05:00
. attr ( HealStatusEffectAttr , false , StatusEffect . FREEZE )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2023-07-11 11:32:56 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SHELL_SMASH , Type . NORMAL , - 1 , 15 , - 1 , 0 , 5 )
2023-11-28 15:19:30 -05:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK , BattleStat . SPD ] , 2 , true )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF ] , - 1 , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HEAL_PULSE , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 5 )
2023-12-15 01:41:45 -06:00
. attr ( HealAttr , 0.5 , false , false )
2024-04-08 17:10:07 +03:00
. pulseMove ( )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HEX , Type . GHOST , MoveCategory . SPECIAL , 65 , 100 , 10 , - 1 , 0 , 5 )
2024-05-27 05:01:03 -06:00
. attr (
MovePowerMultiplierAttr ,
( user , target , move ) = > target . status || target . hasAbility ( Abilities . COMATOSE ) ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SKY_DROP , Type . FLYING , MoveCategory . PHYSICAL , 60 , 100 , 10 , - 1 , 0 , 5 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . SKY_DROP_CHARGING , "took {TARGET}\ninto the sky!" , BattlerTagType . FLYING ) // TODO: Add 2nd turn message
2023-05-08 18:48:35 -04:00
. condition ( failOnGravityCondition )
2024-05-24 01:45:04 +02:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SHIFT_GEAR , Type . STEEL , - 1 , 10 , - 1 , 0 , 5 )
2023-11-30 16:37:16 -05:00
. attr ( StatChangeAttr , BattleStat . ATK , 1 , true )
. attr ( StatChangeAttr , BattleStat . SPD , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CIRCLE_THROW , Type . FIGHTING , MoveCategory . PHYSICAL , 60 , 90 , 10 , - 1 , - 6 , 5 )
2023-10-31 14:09:33 -04:00
. attr ( ForceSwitchOutAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . INCINERATE , Type . FIRE , MoveCategory . SPECIAL , 60 , 100 , 15 , - 1 , 0 , 5 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
2024-06-15 22:26:54 -04:00
. attr ( RemoveHeldItemAttr , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . QUASH , Type . DARK , 100 , 15 , - 1 , 0 , 5 )
. unimplemented ( ) ,
new AttackMove ( Moves . ACROBATICS , Type . FLYING , MoveCategory . PHYSICAL , 55 , 100 , 15 , - 1 , 0 , 5 )
2024-05-24 17:49:23 -03:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > Math . max ( 1 , 2 - 0.2 * user . getHeldItems ( ) . filter ( i = > i . getTransferrable ( true ) ) . reduce ( ( v , m ) = > v + m . stackCount , 0 ) ) ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . REFLECT_TYPE , Type . NORMAL , - 1 , 15 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( CopyTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RETALIATE , Type . NORMAL , MoveCategory . PHYSICAL , 70 , 100 , 5 , - 1 , 0 , 5 )
. partial ( ) ,
new AttackMove ( Moves . FINAL_GAMBIT , Type . FIGHTING , MoveCategory . SPECIAL , - 1 , 100 , 5 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( UserHpDamageAttr )
2024-05-15 11:10:20 +02:00
. attr ( SacrificialAttrOnHit ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . BESTOW , Type . NORMAL , - 1 , 15 , - 1 , 0 , 5 )
. ignoresProtect ( )
. unimplemented ( ) ,
new AttackMove ( Moves . INFERNO , Type . FIRE , MoveCategory . SPECIAL , 100 , 50 , 5 , 100 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WATER_PLEDGE , Type . WATER , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 5 )
. partial ( ) ,
new AttackMove ( Moves . FIRE_PLEDGE , Type . FIRE , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 5 )
. partial ( ) ,
new AttackMove ( Moves . GRASS_PLEDGE , Type . GRASS , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 5 )
. partial ( ) ,
new AttackMove ( Moves . VOLT_SWITCH , Type . ELECTRIC , MoveCategory . SPECIAL , 70 , 100 , 20 , - 1 , 0 , 5 )
2024-04-17 09:56:13 +07:00
. attr ( ForceSwitchOutAttr , true , false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STRUGGLE_BUG , Type . BUG , MoveCategory . SPECIAL , 50 , 100 , 20 , 100 , 0 , 5 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BULLDOZE , Type . GROUND , MoveCategory . PHYSICAL , 60 , 100 , 20 , 100 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
2023-05-01 14:41:44 -04:00
. makesContact ( false )
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FROST_BREATH , Type . ICE , MoveCategory . SPECIAL , 60 , 90 , 10 , 100 , 0 , 5 )
2023-05-05 18:20:55 -04:00
. attr ( CritOnlyAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_TAIL , Type . DRAGON , MoveCategory . PHYSICAL , 60 , 90 , 10 , - 1 , - 6 , 5 )
2023-10-31 14:09:33 -04:00
. attr ( ForceSwitchOutAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . WORK_UP , Type . NORMAL , - 1 , 30 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK ] , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ELECTROWEB , Type . ELECTRIC , MoveCategory . SPECIAL , 55 , 95 , 15 , 100 , 0 , 5 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WILD_CHARGE , Type . ELECTRIC , MoveCategory . PHYSICAL , 90 , 100 , 15 , - 1 , 0 , 5 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRILL_RUN , Type . GROUND , MoveCategory . PHYSICAL , 80 , 95 , 10 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( HighCritAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DUAL_CHOP , Type . DRAGON , MoveCategory . PHYSICAL , 40 , 90 , 15 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr , MultiHitType . _2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HEART_STAMP , Type . PSYCHIC , MoveCategory . PHYSICAL , 60 , 100 , 25 , 30 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HORN_LEECH , Type . GRASS , MoveCategory . PHYSICAL , 75 , 100 , 10 , - 1 , 0 , 5 )
2024-04-08 17:10:07 +03:00
. attr ( HitHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SACRED_SWORD , Type . FIGHTING , MoveCategory . PHYSICAL , 90 , 100 , 15 , - 1 , 0 , 5 )
2024-05-24 01:45:04 +02:00
. attr ( IgnoreOpponentStatChangesAttr )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RAZOR_SHELL , Type . WATER , MoveCategory . PHYSICAL , 75 , 95 , 10 , 50 , 0 , 5 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HEAT_CRASH , Type . FIRE , MoveCategory . PHYSICAL , - 1 , 100 , 10 , - 1 , 0 , 5 )
2024-05-15 06:36:34 -06:00
. attr ( MinimizeAccuracyAttr )
2024-04-24 01:57:59 +10:00
. attr ( CompareWeightPowerAttr )
2024-05-15 06:36:34 -06:00
. attr ( HitsTagAttr , BattlerTagType . MINIMIZED , true )
2024-04-24 01:57:59 +10:00
. condition ( failOnMaxCondition ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LEAF_TORNADO , Type . GRASS , MoveCategory . SPECIAL , 65 , 90 , 10 , 50 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STEAMROLLER , Type . BUG , MoveCategory . PHYSICAL , 65 , 100 , 20 , 30 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . COTTON_GUARD , Type . GRASS , - 1 , 10 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . DEF , 3 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NIGHT_DAZE , Type . DARK , MoveCategory . SPECIAL , 85 , 95 , 10 , 40 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , BattleStat . ACC , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYSTRIKE , Type . PSYCHIC , MoveCategory . SPECIAL , 100 , 100 , 10 , - 1 , 0 , 5 )
2024-03-17 20:00:20 -05:00
. attr ( DefDefAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TAIL_SLAP , Type . NORMAL , MoveCategory . PHYSICAL , 25 , 85 , 10 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HURRICANE , Type . FLYING , MoveCategory . SPECIAL , 110 , 70 , 10 , 30 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( ThunderAccuracyAttr )
2023-12-15 01:41:45 -06:00
. attr ( ConfuseAttr )
2024-04-15 12:49:10 -07:00
. attr ( HitsTagAttr , BattlerTagType . FLYING , false )
2023-12-15 01:41:45 -06:00
. windMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HEAD_CHARGE , Type . NORMAL , MoveCategory . PHYSICAL , 120 , 100 , 15 , - 1 , 0 , 5 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GEAR_GRIND , Type . STEEL , MoveCategory . PHYSICAL , 50 , 85 , 15 , - 1 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( MultiHitAttr , MultiHitType . _2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SEARING_SHOT , Type . FIRE , MoveCategory . SPECIAL , 100 , 100 , 5 , 30 , 0 , 5 )
2023-05-01 14:41:44 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
2023-12-15 01:41:45 -06:00
. ballBombMove ( )
2023-05-01 14:41:44 -04:00
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TECHNO_BLAST , Type . NORMAL , MoveCategory . SPECIAL , 120 , 100 , 5 , - 1 , 0 , 5 )
2024-05-04 19:45:07 -05:00
. attr ( TechnoBlastTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RELIC_SONG , Type . NORMAL , MoveCategory . SPECIAL , 75 , 100 , 10 , 10 , 0 , 5 )
2023-05-01 14:41:44 -04:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP )
2023-11-30 16:37:16 -05:00
. soundBased ( )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SECRET_SWORD , Type . FIGHTING , MoveCategory . SPECIAL , 85 , 100 , 10 , - 1 , 0 , 5 )
2024-04-10 15:48:26 +03:00
. attr ( DefDefAttr )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GLACIATE , Type . ICE , MoveCategory . SPECIAL , 65 , 95 , 10 , 100 , 0 , 5 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BOLT_STRIKE , Type . ELECTRIC , MoveCategory . PHYSICAL , 130 , 85 , 5 , 20 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLUE_FLARE , Type . FIRE , MoveCategory . SPECIAL , 130 , 85 , 5 , 20 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FIERY_DANCE , Type . FIRE , MoveCategory . SPECIAL , 80 , 100 , 10 , 50 , 0 , 5 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPATK , 1 , true )
. danceMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FREEZE_SHOCK , Type . ICE , MoveCategory . PHYSICAL , 140 , 90 , 5 , 30 , 0 , 5 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . FREEZE_SHOCK_CHARGING , "became cloaked\nin a freezing light!" )
2023-04-27 14:30:03 -04:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICE_BURN , Type . ICE , MoveCategory . SPECIAL , 140 , 90 , 5 , 30 , 0 , 5 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . ICE_BURN_CHARGING , "became cloaked\nin freezing air!" )
2023-04-27 20:12:25 -04:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SNARL , Type . DARK , MoveCategory . SPECIAL , 55 , 95 , 15 , 100 , 0 , 5 )
2023-05-01 14:41:44 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 )
2023-11-30 16:37:16 -05:00
. soundBased ( )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICICLE_CRASH , Type . ICE , MoveCategory . PHYSICAL , 85 , 90 , 10 , 30 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( FlinchAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . V_CREATE , Type . FIRE , MoveCategory . PHYSICAL , 180 , 95 , 5 , 100 , 0 , 5 )
2023-04-27 14:30:03 -04:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF , BattleStat . SPD ] , - 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FUSION_FLARE , Type . FIRE , MoveCategory . SPECIAL , 100 , 100 , 5 , - 1 , 0 , 5 )
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
. partial ( ) ,
new AttackMove ( Moves . FUSION_BOLT , Type . ELECTRIC , MoveCategory . PHYSICAL , 100 , 100 , 5 , - 1 , 0 , 5 )
. makesContact ( false )
. partial ( ) ,
new AttackMove ( Moves . FLYING_PRESS , Type . FIGHTING , MoveCategory . PHYSICAL , 100 , 95 , 10 , - 1 , 0 , 6 )
2024-05-15 06:36:34 -06:00
. attr ( MinimizeAccuracyAttr )
2024-04-23 17:42:45 -04:00
. attr ( FlyingTypeMultiplierAttr )
2024-05-15 06:36:34 -06:00
. attr ( HitsTagAttr , BattlerTagType . MINIMIZED , true )
2024-04-23 17:42:45 -04:00
. condition ( failOnGravityCondition ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MAT_BLOCK , Type . FIGHTING , - 1 , 10 , - 1 , 0 , 6 )
2024-05-25 04:22:10 -07:00
. target ( MoveTarget . USER_SIDE )
. attr ( AddArenaTagAttr , ArenaTagType . MAT_BLOCK , 1 , true , true )
. condition ( new FirstMoveCondition ( ) ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BELCH , Type . POISON , MoveCategory . SPECIAL , 120 , 90 , 10 , - 1 , 0 , 6 )
2024-05-02 06:36:47 +10:00
. condition ( ( user , target , move ) = > user . battleData . berriesEaten . length > 0 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ROTOTILLER , Type . GROUND , - 1 , 10 , 100 , 0 , 6 )
. target ( MoveTarget . ALL )
2024-06-06 23:22:04 +02:00
. condition ( ( user , target , move ) = > {
// If any fielded pokémon is grass-type and grounded.
return [ . . . user . scene . getEnemyParty ( ) , . . . user . scene . getParty ( ) ] . some ( ( poke ) = > poke . isOfType ( Type . GRASS ) && poke . isGrounded ( ) ) ;
} )
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK ] , 1 , false , ( user , target , move ) = > target . isOfType ( Type . GRASS ) && target . isGrounded ( ) ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . STICKY_WEB , Type . BUG , - 1 , 20 , - 1 , 0 , 6 )
2024-04-06 18:55:02 -04:00
. attr ( AddArenaTrapTagAttr , ArenaTagType . STICKY_WEB )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ENEMY_SIDE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FELL_STINGER , Type . BUG , MoveCategory . PHYSICAL , 50 , 100 , 25 , - 1 , 0 , 6 )
2024-05-08 05:44:55 +01:00
. attr ( PostVictoryStatChangeAttr , BattleStat . ATK , 3 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PHANTOM_FORCE , Type . GHOST , MoveCategory . PHYSICAL , 90 , 100 , 10 , - 1 , 0 , 6 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . PHANTOM_FORCE_CHARGING , "vanished\ninstantly!" , BattlerTagType . HIDDEN )
2023-04-27 20:12:25 -04:00
. ignoresProtect ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TRICK_OR_TREAT , Type . GHOST , 100 , 20 , - 1 , 0 , 6 )
2024-04-20 03:32:40 +10:00
. attr ( AddTypeAttr , Type . GHOST )
. partial ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . NOBLE_ROAR , Type . NORMAL , 100 , 30 , 100 , 0 , 6 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK ] , - 1 )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ION_DELUGE , Type . ELECTRIC , - 1 , 25 , - 1 , 1 , 6 )
. target ( MoveTarget . BOTH_SIDES )
. unimplemented ( ) ,
new AttackMove ( Moves . PARABOLIC_CHARGE , Type . ELECTRIC , MoveCategory . SPECIAL , 65 , 100 , 20 , - 1 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. attr ( HitHealAttr )
2024-04-08 17:10:07 +03:00
. target ( MoveTarget . ALL_NEAR_OTHERS )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . FORESTS_CURSE , Type . GRASS , 100 , 20 , - 1 , 0 , 6 )
2024-04-20 03:32:40 +10:00
. attr ( AddTypeAttr , Type . GRASS )
. partial ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PETAL_BLIZZARD , Type . GRASS , MoveCategory . PHYSICAL , 90 , 100 , 15 , - 1 , 0 , 6 )
2023-12-15 01:41:45 -06:00
. windMove ( )
2024-04-01 20:57:22 -05:00
. makesContact ( false )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FREEZE_DRY , Type . ICE , MoveCategory . SPECIAL , 70 , 100 , 20 , 10 , 0 , 6 )
2024-04-01 20:26:35 +03:00
. attr ( StatusEffectAttr , StatusEffect . FREEZE )
2024-04-02 16:16:35 +03:00
. attr ( WaterSuperEffectTypeMultiplierAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DISARMING_VOICE , Type . FAIRY , MoveCategory . SPECIAL , 40 , - 1 , 15 , - 1 , 0 , 6 )
2023-12-15 01:41:45 -06:00
. soundBased ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . PARTING_SHOT , Type . DARK , 100 , 20 , 100 , 0 , 6 )
2024-05-05 08:50:46 -07:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK ] , - 1 , false , null , true , true , MoveEffectTrigger . PRE_APPLY )
2024-04-17 09:56:13 +07:00
. attr ( ForceSwitchOutAttr , true , false )
2023-12-15 01:41:45 -06:00
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TOPSY_TURVY , Type . DARK , - 1 , 20 , - 1 , 0 , 6 )
2024-03-11 18:44:40 -04:00
. attr ( InvertStatsAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAINING_KISS , Type . FAIRY , MoveCategory . SPECIAL , 50 , 100 , 10 , - 1 , 0 , 6 )
2024-04-12 19:02:24 -05:00
. attr ( HitHealAttr , 0.75 )
2024-04-08 17:10:07 +03:00
. makesContact ( )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . CRAFTY_SHIELD , Type . FAIRY , - 1 , 10 , - 1 , 3 , 6 )
. target ( MoveTarget . USER_SIDE )
2024-05-25 04:22:10 -07:00
. attr ( AddArenaTagAttr , ArenaTagType . CRAFTY_SHIELD , 1 , true , true ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . FLOWER_SHIELD , Type . FAIRY , - 1 , 10 , 100 , 0 , 6 )
. target ( MoveTarget . ALL )
. unimplemented ( ) ,
new StatusMove ( Moves . GRASSY_TERRAIN , Type . GRASS , - 1 , 10 , - 1 , 0 , 6 )
2024-03-09 21:57:33 -05:00
. attr ( TerrainChangeAttr , TerrainType . GRASSY )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MISTY_TERRAIN , Type . FAIRY , - 1 , 10 , - 1 , 0 , 6 )
2024-03-09 21:57:33 -05:00
. attr ( TerrainChangeAttr , TerrainType . MISTY )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . ELECTRIFY , Type . ELECTRIC , - 1 , 20 , - 1 , 0 , 6 )
. unimplemented ( ) ,
new AttackMove ( Moves . PLAY_ROUGH , Type . FAIRY , MoveCategory . PHYSICAL , 90 , 90 , 10 , 10 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FAIRY_WIND , Type . FAIRY , MoveCategory . SPECIAL , 40 , 100 , 30 , - 1 , 0 , 6 )
2023-12-15 01:41:45 -06:00
. windMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MOONBLAST , Type . FAIRY , MoveCategory . SPECIAL , 95 , 100 , 15 , 30 , 0 , 6 )
2023-11-30 16:37:16 -05:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BOOMBURST , Type . NORMAL , MoveCategory . SPECIAL , 140 , 100 , 10 , - 1 , 0 , 6 )
2023-12-15 01:41:45 -06:00
. soundBased ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . FAIRY_LOCK , Type . FAIRY , - 1 , 10 , - 1 , 0 , 6 )
. target ( MoveTarget . BOTH_SIDES )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . KINGS_SHIELD , Type . STEEL , - 1 , 10 , - 1 , 4 , 6 )
2024-03-30 18:46:33 -04:00
. attr ( ProtectAttr , BattlerTagType . KINGS_SHIELD ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . PLAY_NICE , Type . NORMAL , - 1 , 20 , 100 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . CONFIDE , Type . NORMAL , - 1 , 20 , 100 , 0 , 6 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DIAMOND_STORM , Type . ROCK , MoveCategory . PHYSICAL , 100 , 95 , 5 , 50 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. attr ( StatChangeAttr , BattleStat . DEF , 2 , true )
2024-04-01 20:57:22 -05:00
. makesContact ( false )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STEAM_ERUPTION , Type . WATER , MoveCategory . SPECIAL , 110 , 95 , 5 , 30 , 0 , 6 )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2024-05-30 16:04:50 -04:00
. attr ( HealStatusEffectAttr , false , StatusEffect . FREEZE )
2023-12-08 16:29:03 -05:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYPERSPACE_HOLE , Type . PSYCHIC , MoveCategory . SPECIAL , 80 , - 1 , 5 , - 1 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. ignoresProtect ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WATER_SHURIKEN , Type . WATER , MoveCategory . SPECIAL , 15 , 100 , 20 , - 1 , 1 , 6 )
2024-05-04 18:50:12 -07:00
. attr ( MultiHitAttr )
. attr ( WaterShurikenPowerAttr )
. attr ( WaterShurikenMultiHitTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MYSTICAL_FIRE , Type . FIRE , MoveCategory . SPECIAL , 75 , 100 , 10 , 100 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SPIKY_SHIELD , Type . GRASS , - 1 , 10 , - 1 , 4 , 6 )
2024-04-06 21:50:17 -05:00
. attr ( ProtectAttr , BattlerTagType . SPIKY_SHIELD ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . AROMATIC_MIST , Type . FAIRY , - 1 , 20 , - 1 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. attr ( StatChangeAttr , BattleStat . SPDEF , 1 )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . NEAR_ALLY ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . EERIE_IMPULSE , Type . ELECTRIC , 100 , 15 , - 1 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 2 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . VENOM_DRENCH , Type . POISON , 100 , 20 , 100 , 0 , 6 )
2024-05-03 15:38:32 -05:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK , BattleStat . SPD ] , - 1 , false , ( user , target , move ) = > target . status ? . effect === StatusEffect . POISON || target . status ? . effect === StatusEffect . TOXIC )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . POWDER , Type . BUG , 100 , 20 , - 1 , 1 , 6 )
. powderMove ( )
. unimplemented ( ) ,
new SelfStatusMove ( Moves . GEOMANCY , Type . FAIRY , - 1 , 10 , - 1 , 0 , 6 )
2023-11-30 16:37:16 -05:00
. attr ( ChargeAttr , ChargeAnim . GEOMANCY_CHARGING , "is charging its power!" )
2023-04-27 20:12:25 -04:00
. attr ( StatChangeAttr , [ BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 2 , true )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . MAGNETIC_FLUX , Type . ELECTRIC , - 1 , 20 , - 1 , 0 , 6 )
2024-04-15 15:03:50 +10:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF ] , 1 , false , ( user , target , move ) = > ! ! [ Abilities . PLUS , Abilities . MINUS ] . find ( a = > target . hasAbility ( a , false ) ) )
2024-03-06 22:41:55 -05:00
. target ( MoveTarget . USER_AND_ALLIES )
2024-04-15 15:03:50 +10:00
. condition ( ( user , target , move ) = > ! ! [ user , user . getAlly ( ) ] . filter ( p = > p ? . isActive ( ) ) . find ( p = > ! ! [ Abilities . PLUS , Abilities . MINUS ] . find ( a = > p . hasAbility ( a , false ) ) ) ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . HAPPY_HOUR , Type . NORMAL , - 1 , 30 , - 1 , 0 , 6 ) // No animation
. target ( MoveTarget . USER_SIDE )
. unimplemented ( ) ,
new StatusMove ( Moves . ELECTRIC_TERRAIN , Type . ELECTRIC , - 1 , 10 , - 1 , 0 , 6 )
2024-03-09 21:57:33 -05:00
. attr ( TerrainChangeAttr , TerrainType . ELECTRIC )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DAZZLING_GLEAM , Type . FAIRY , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 6 )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . CELEBRATE , Type . NORMAL , - 1 , 40 , - 1 , 0 , 6 ) ,
new StatusMove ( Moves . HOLD_HANDS , Type . NORMAL , - 1 , 40 , - 1 , 0 , 6 )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . NEAR_ALLY ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . BABY_DOLL_EYES , Type . FAIRY , 100 , 30 , - 1 , 1 , 6 )
2023-11-30 19:38:54 -05:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NUZZLE , Type . ELECTRIC , MoveCategory . PHYSICAL , 20 , 100 , 20 , 100 , 0 , 6 )
2023-11-30 19:38:54 -05:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HOLD_BACK , Type . NORMAL , MoveCategory . PHYSICAL , 40 , 100 , 40 , - 1 , 0 , 6 )
2024-03-29 11:58:22 -04:00
. attr ( SurviveDamageAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . INFESTATION , Type . BUG , MoveCategory . SPECIAL , 20 , 100 , 20 , 100 , 0 , 6 )
. makesContact ( )
2024-04-18 11:14:11 -04:00
. attr ( TrapAttr , BattlerTagType . INFESTATION ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POWER_UP_PUNCH , Type . FIGHTING , MoveCategory . PHYSICAL , 40 , 100 , 20 , 100 , 0 , 6 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , 1 , true )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . OBLIVION_WING , Type . FLYING , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 6 )
2024-04-08 17:10:07 +03:00
. attr ( HitHealAttr , 0.75 )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THOUSAND_ARROWS , Type . GROUND , MoveCategory . PHYSICAL , 90 , 100 , 10 , 100 , 0 , 6 )
2024-04-03 16:33:11 +03:00
. attr ( NeutralDamageAgainstFlyingTypeMultiplierAttr )
2024-04-15 12:49:10 -07:00
. attr ( HitsTagAttr , BattlerTagType . FLYING , false )
2024-05-02 22:20:41 -07:00
. attr ( AddBattlerTagAttr , BattlerTagType . INTERRUPTED )
. attr ( RemoveBattlerTagAttr , [ BattlerTagType . FLYING ] )
2024-04-01 20:57:22 -05:00
. makesContact ( false )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THOUSAND_WAVES , Type . GROUND , MoveCategory . PHYSICAL , 90 , 100 , 10 , - 1 , 0 , 6 )
2024-04-09 18:44:13 +03:00
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , false , false , 1 )
2024-04-01 20:57:22 -05:00
. makesContact ( false )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LANDS_WRATH , Type . GROUND , MoveCategory . PHYSICAL , 90 , 100 , 10 , - 1 , 0 , 6 )
2024-04-01 20:57:22 -05:00
. makesContact ( false )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LIGHT_OF_RUIN , Type . FAIRY , MoveCategory . SPECIAL , 140 , 90 , 5 , - 1 , 0 , 6 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr , false , 0.5 )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ORIGIN_PULSE , Type . WATER , MoveCategory . SPECIAL , 110 , 85 , 10 , - 1 , 0 , 6 )
2023-12-15 01:41:45 -06:00
. pulseMove ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PRECIPICE_BLADES , Type . GROUND , MoveCategory . PHYSICAL , 120 , 85 , 10 , - 1 , 0 , 6 )
2024-04-01 20:57:22 -05:00
. makesContact ( false )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_ASCENT , Type . FLYING , MoveCategory . PHYSICAL , 120 , 100 , 5 , 100 , 0 , 6 )
2024-01-12 16:24:44 -05:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF ] , - 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYPERSPACE_FURY , Type . DARK , MoveCategory . PHYSICAL , 100 , - 1 , 5 , 100 , 0 , 6 )
2023-12-08 16:29:03 -05:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 , true )
2024-06-12 22:21:16 +09:00
. makesContact ( false )
2023-12-08 16:29:03 -05:00
. ignoresProtect ( ) ,
2023-11-30 16:37:16 -05:00
/* Unused */
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BREAKNECK_BLITZ__PHYSICAL , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BREAKNECK_BLITZ__SPECIAL , Type . NORMAL , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ALL_OUT_PUMMELING__PHYSICAL , Type . FIGHTING , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ALL_OUT_PUMMELING__SPECIAL , Type . FIGHTING , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SUPERSONIC_SKYSTRIKE__PHYSICAL , Type . FLYING , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SUPERSONIC_SKYSTRIKE__SPECIAL , Type . FLYING , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ACID_DOWNPOUR__PHYSICAL , Type . POISON , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ACID_DOWNPOUR__SPECIAL , Type . POISON , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TECTONIC_RAGE__PHYSICAL , Type . GROUND , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TECTONIC_RAGE__SPECIAL , Type . GROUND , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CONTINENTAL_CRUSH__PHYSICAL , Type . ROCK , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CONTINENTAL_CRUSH__SPECIAL , Type . ROCK , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SAVAGE_SPIN_OUT__PHYSICAL , Type . BUG , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SAVAGE_SPIN_OUT__SPECIAL , Type . BUG , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NEVER_ENDING_NIGHTMARE__PHYSICAL , Type . GHOST , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NEVER_ENDING_NIGHTMARE__SPECIAL , Type . GHOST , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CORKSCREW_CRASH__PHYSICAL , Type . STEEL , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CORKSCREW_CRASH__SPECIAL , Type . STEEL , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . INFERNO_OVERDRIVE__PHYSICAL , Type . FIRE , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . INFERNO_OVERDRIVE__SPECIAL , Type . FIRE , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYDRO_VORTEX__PHYSICAL , Type . WATER , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYDRO_VORTEX__SPECIAL , Type . WATER , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLOOM_DOOM__PHYSICAL , Type . GRASS , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLOOM_DOOM__SPECIAL , Type . GRASS , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GIGAVOLT_HAVOC__PHYSICAL , Type . ELECTRIC , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GIGAVOLT_HAVOC__SPECIAL , Type . ELECTRIC , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHATTERED_PSYCHE__PHYSICAL , Type . PSYCHIC , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHATTERED_PSYCHE__SPECIAL , Type . PSYCHIC , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SUBZERO_SLAMMER__PHYSICAL , Type . ICE , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SUBZERO_SLAMMER__SPECIAL , Type . ICE , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DEVASTATING_DRAKE__PHYSICAL , Type . DRAGON , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DEVASTATING_DRAKE__SPECIAL , Type . DRAGON , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLACK_HOLE_ECLIPSE__PHYSICAL , Type . DARK , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLACK_HOLE_ECLIPSE__SPECIAL , Type . DARK , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TWINKLE_TACKLE__PHYSICAL , Type . FAIRY , MoveCategory . PHYSICAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TWINKLE_TACKLE__SPECIAL , Type . FAIRY , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CATASTROPIKA , Type . ELECTRIC , MoveCategory . PHYSICAL , 210 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2023-12-11 19:09:38 -06:00
/* End Unused */
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SHORE_UP , Type . GROUND , - 1 , 5 , - 1 , 0 , 7 )
2024-04-08 17:10:07 +03:00
. attr ( SandHealAttr )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FIRST_IMPRESSION , Type . BUG , MoveCategory . PHYSICAL , 90 , 100 , 10 , - 1 , 2 , 7 )
2024-01-07 23:17:24 -05:00
. condition ( new FirstMoveCondition ( ) ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . BANEFUL_BUNKER , Type . POISON , - 1 , 10 , - 1 , 4 , 7 )
2024-03-13 22:09:23 +01:00
. attr ( ProtectAttr , BattlerTagType . BANEFUL_BUNKER ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPIRIT_SHACKLE , Type . GHOST , MoveCategory . PHYSICAL , 80 , 100 , 10 , - 1 , 0 , 7 )
2024-04-26 20:40:28 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , false , false , 1 )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DARKEST_LARIAT , Type . DARK , MoveCategory . PHYSICAL , 85 , 100 , 10 , - 1 , 0 , 7 )
2024-04-02 20:51:38 +03:00
. attr ( IgnoreOpponentStatChangesAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPARKLING_ARIA , Type . WATER , MoveCategory . SPECIAL , 90 , 100 , 10 , - 1 , 0 , 7 )
2024-02-27 16:33:02 -05:00
. attr ( HealStatusEffectAttr , false , StatusEffect . BURN )
2023-12-15 01:41:45 -06:00
. soundBased ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICE_HAMMER , Type . ICE , MoveCategory . PHYSICAL , 100 , 90 , 10 , 100 , 0 , 7 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 , true )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . FLORAL_HEALING , Type . FAIRY , - 1 , 10 , - 1 , 0 , 7 )
2024-05-13 11:27:38 +02:00
. attr ( BoostHealAttr , 0.5 , 2 / 3 , true , false , ( user , target , move ) = > user . scene . arena . terrain ? . terrainType === TerrainType . GRASSY )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HIGH_HORSEPOWER , Type . GROUND , MoveCategory . PHYSICAL , 95 , 95 , 10 , - 1 , 0 , 7 ) ,
new StatusMove ( Moves . STRENGTH_SAP , Type . GRASS , 100 , 10 , 100 , 0 , 7 )
2024-06-01 15:53:32 -04:00
. attr ( HitHealAttr , null , Stat . ATK )
2024-04-08 17:10:07 +03:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 )
2024-04-12 10:47:59 +10:00
. condition ( ( user , target , move ) = > target . summonData . battleStats [ BattleStat . ATK ] > - 6 )
2024-04-08 17:10:07 +03:00
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SOLAR_BLADE , Type . GRASS , MoveCategory . PHYSICAL , 125 , 100 , 10 , - 1 , 0 , 7 )
2024-03-09 21:57:33 -05:00
. attr ( SunlightChargeAttr , ChargeAnim . SOLAR_BLADE_CHARGING , "is glowing!" )
. attr ( AntiSunlightPowerDecreaseAttr )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LEAFAGE , Type . GRASS , MoveCategory . PHYSICAL , 40 , 100 , 40 , - 1 , 0 , 7 )
2024-04-01 20:57:22 -05:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SPOTLIGHT , Type . NORMAL , - 1 , 15 , - 1 , 3 , 7 )
. unimplemented ( ) ,
new StatusMove ( Moves . TOXIC_THREAD , Type . POISON , 100 , 20 , 100 , 0 , 7 )
2023-12-02 16:31:10 -05:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. attr ( StatChangeAttr , BattleStat . SPD , - 1 ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . LASER_FOCUS , Type . NORMAL , - 1 , 30 , - 1 , 0 , 7 )
2024-04-12 19:02:24 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . ALWAYS_CRIT , true , false ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . GEAR_UP , Type . STEEL , - 1 , 20 , - 1 , 0 , 7 )
2024-04-15 15:03:50 +10:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK ] , 1 , false , ( user , target , move ) = > ! ! [ Abilities . PLUS , Abilities . MINUS ] . find ( a = > target . hasAbility ( a , false ) ) )
2023-12-10 17:57:12 -05:00
. target ( MoveTarget . USER_AND_ALLIES )
2024-04-15 15:03:50 +10:00
. condition ( ( user , target , move ) = > ! ! [ user , user . getAlly ( ) ] . filter ( p = > p ? . isActive ( ) ) . find ( p = > ! ! [ Abilities . PLUS , Abilities . MINUS ] . find ( a = > p . hasAbility ( a , false ) ) ) ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THROAT_CHOP , Type . DARK , MoveCategory . PHYSICAL , 80 , 100 , 15 , 100 , 0 , 7 )
. partial ( ) ,
new AttackMove ( Moves . POLLEN_PUFF , Type . BUG , MoveCategory . SPECIAL , 90 , 100 , 15 , - 1 , 0 , 7 )
2024-06-03 22:26:15 +02:00
. attr ( StatusCategoryOnAllyAttr )
. attr ( HealOnAllyAttr , 0.5 , true , false )
. ballBombMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ANCHOR_SHOT , Type . STEEL , MoveCategory . PHYSICAL , 80 , 100 , 20 , - 1 , 0 , 7 )
2024-02-08 16:50:17 -06:00
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , false , false , 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . PSYCHIC_TERRAIN , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 7 )
2024-03-09 21:57:33 -05:00
. attr ( TerrainChangeAttr , TerrainType . PSYCHIC )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LUNGE , Type . BUG , MoveCategory . PHYSICAL , 80 , 100 , 15 , 100 , 0 , 7 )
2023-12-10 17:57:12 -05:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FIRE_LASH , Type . FIRE , MoveCategory . PHYSICAL , 80 , 100 , 15 , 100 , 0 , 7 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POWER_TRIP , Type . DARK , MoveCategory . PHYSICAL , 20 , 100 , 10 , - 1 , 0 , 7 )
2024-04-05 01:33:42 +02:00
. attr ( StatChangeCountPowerAttr ) ,
2024-04-16 15:22:19 -04:00
new AttackMove ( Moves . BURN_UP , Type . FIRE , MoveCategory . SPECIAL , 130 , 100 , 5 , - 1 , 0 , 7 )
2024-04-16 15:07:38 -04:00
. condition ( ( user ) = > {
const userTypes = user . getTypes ( true ) ;
return userTypes . includes ( Type . FIRE ) ;
} )
2024-04-16 20:29:32 +02:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2024-04-16 15:07:38 -04:00
. attr ( RemoveTypeAttr , Type . FIRE , ( user ) = > {
2024-05-23 17:03:10 +02:00
user . scene . queueMessage ( getPokemonMessage ( user , " burned itself out!" ) ) ;
2024-04-16 15:07:38 -04:00
} ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SPEED_SWAP , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 7 )
. unimplemented ( ) ,
new AttackMove ( Moves . SMART_STRIKE , Type . STEEL , MoveCategory . PHYSICAL , 70 , - 1 , 10 , - 1 , 0 , 7 ) ,
new StatusMove ( Moves . PURIFY , Type . POISON , - 1 , 20 , - 1 , 0 , 7 )
2024-05-25 05:01:23 -06:00
. condition (
( user : Pokemon , target : Pokemon , move : Move ) = > isNonVolatileStatusEffect ( user . status ? . effect ) )
. attr ( HealAttr , 0.5 )
. attr ( HealStatusEffectAttr , true , . . . getNonVolatileStatusEffects ( ) )
. triageMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . REVELATION_DANCE , Type . NORMAL , MoveCategory . SPECIAL , 90 , 100 , 15 , - 1 , 0 , 7 )
. danceMove ( )
2024-05-06 11:24:37 -04:00
. attr ( MatchUserTypeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CORE_ENFORCER , Type . DRAGON , MoveCategory . SPECIAL , 100 , 100 , 10 , - 1 , 0 , 7 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
2024-06-10 21:17:28 -04:00
. attr ( SuppressAbilitiesIfActedAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TROP_KICK , Type . GRASS , MoveCategory . PHYSICAL , 70 , 100 , 15 , 100 , 0 , 7 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . INSTRUCT , Type . PSYCHIC , - 1 , 15 , - 1 , 0 , 7 )
. unimplemented ( ) ,
new AttackMove ( Moves . BEAK_BLAST , Type . FLYING , MoveCategory . PHYSICAL , 100 , 100 , 15 , - 1 , 5 , 7 )
2024-02-20 13:15:53 -05:00
. attr ( ChargeAttr , ChargeAnim . BEAK_BLAST_CHARGING , "started\nheating up its beak!" , undefined , false , true , - 3 )
2024-04-01 20:57:22 -05:00
. ballBombMove ( )
2024-04-16 20:29:32 +02:00
. makesContact ( false )
. partial ( ) ,
new AttackMove ( Moves . CLANGING_SCALES , Type . DRAGON , MoveCategory . SPECIAL , 110 , 100 , 5 , 100 , 0 , 7 )
2023-12-10 17:57:12 -05:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 , true )
2023-12-15 01:41:45 -06:00
. soundBased ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_HAMMER , Type . DRAGON , MoveCategory . PHYSICAL , 90 , 100 , 15 , - 1 , 0 , 7 ) ,
new AttackMove ( Moves . BRUTAL_SWING , Type . DARK , MoveCategory . PHYSICAL , 60 , 100 , 20 , - 1 , 0 , 7 )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . AURORA_VEIL , Type . ICE , - 1 , 20 , - 1 , 0 , 7 )
2024-04-15 22:47:39 +02:00
. condition ( ( user , target , move ) = > ( user . scene . arena . weather ? . weatherType === WeatherType . HAIL || user . scene . arena . weather ? . weatherType === WeatherType . SNOW ) && ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) )
2024-04-05 17:21:17 +02:00
. attr ( AddArenaTagAttr , ArenaTagType . AURORA_VEIL , 5 , true )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . USER_SIDE ) ,
2023-12-11 19:09:38 -06:00
/* Unused */
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SINISTER_ARROW_RAID , Type . GHOST , MoveCategory . PHYSICAL , 180 , - 1 , 1 , - 1 , 0 , 7 )
. makesContact ( false )
2024-05-09 15:38:46 +10:00
. partial ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MALICIOUS_MOONSAULT , Type . DARK , MoveCategory . PHYSICAL , 180 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. partial ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . OCEANIC_OPERETTA , Type . WATER , MoveCategory . SPECIAL , 195 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. partial ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GUARDIAN_OF_ALOLA , Type . FAIRY , MoveCategory . SPECIAL , - 1 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SOUL_STEALING_7_STAR_STRIKE , Type . GHOST , MoveCategory . PHYSICAL , 195 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STOKED_SPARKSURFER , Type . ELECTRIC , MoveCategory . SPECIAL , 175 , - 1 , 1 , 100 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. partial ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PULVERIZING_PANCAKE , Type . NORMAL , MoveCategory . PHYSICAL , 210 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. partial ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . EXTREME_EVOBOOST , Type . NORMAL , - 1 , 1 , 100 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 2 , true )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GENESIS_SUPERNOVA , Type . PSYCHIC , MoveCategory . SPECIAL , 185 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. attr ( TerrainChangeAttr , TerrainType . PSYCHIC )
. ignoresVirtual ( ) ,
2023-12-11 19:09:38 -06:00
/* End Unused */
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHELL_TRAP , Type . FIRE , MoveCategory . SPECIAL , 150 , 100 , 5 , - 1 , - 3 , 7 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. partial ( ) ,
new AttackMove ( Moves . FLEUR_CANNON , Type . FAIRY , MoveCategory . SPECIAL , 130 , 90 , 5 , 100 , 0 , 7 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYCHIC_FANGS , Type . PSYCHIC , MoveCategory . PHYSICAL , 85 , 100 , 10 , - 1 , 0 , 7 )
2024-04-14 22:26:58 -04:00
. bitingMove ( )
. attr ( RemoveScreensAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STOMPING_TANTRUM , Type . GROUND , MoveCategory . PHYSICAL , 75 , 100 , 10 , - 1 , 0 , 7 )
2024-05-23 17:03:10 +02:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . getLastXMoves ( 2 ) [ 1 ] ? . result === MoveResult . MISS || user . getLastXMoves ( 2 ) [ 1 ] ? . result === MoveResult . FAIL ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHADOW_BONE , Type . GHOST , MoveCategory . PHYSICAL , 85 , 100 , 10 , 20 , 0 , 7 )
2024-04-01 20:57:22 -05:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ACCELEROCK , Type . ROCK , MoveCategory . PHYSICAL , 40 , 100 , 20 , - 1 , 1 , 7 ) ,
new AttackMove ( Moves . LIQUIDATION , Type . WATER , MoveCategory . PHYSICAL , 85 , 100 , 10 , 20 , 0 , 7 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PRISMATIC_LASER , Type . PSYCHIC , MoveCategory . SPECIAL , 160 , 100 , 10 , - 1 , 0 , 7 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPECTRAL_THIEF , Type . GHOST , MoveCategory . PHYSICAL , 90 , 100 , 10 , - 1 , 0 , 7 )
. partial ( ) ,
new AttackMove ( Moves . SUNSTEEL_STRIKE , Type . STEEL , MoveCategory . PHYSICAL , 100 , 100 , 5 , - 1 , 0 , 7 )
2024-04-18 15:44:03 +10:00
. ignoresAbilities ( )
2024-04-16 20:29:32 +02:00
. partial ( ) ,
new AttackMove ( Moves . MOONGEIST_BEAM , Type . GHOST , MoveCategory . SPECIAL , 100 , 100 , 5 , - 1 , 0 , 7 )
2024-04-18 15:44:03 +10:00
. ignoresAbilities ( )
2024-04-16 20:29:32 +02:00
. partial ( ) ,
new StatusMove ( Moves . TEARFUL_LOOK , Type . NORMAL , - 1 , 20 , 100 , 0 , 7 )
2024-05-05 01:28:15 +03:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK ] , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ZING_ZAP , Type . ELECTRIC , MoveCategory . PHYSICAL , 80 , 100 , 10 , 30 , 0 , 7 )
2023-12-10 21:52:11 -06:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NATURES_MADNESS , Type . FAIRY , MoveCategory . SPECIAL , - 1 , 90 , 10 , - 1 , 0 , 7 )
2023-12-10 21:52:11 -06:00
. attr ( TargetHalfHpDamageAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MULTI_ATTACK , Type . NORMAL , MoveCategory . PHYSICAL , 120 , 100 , 10 , - 1 , 0 , 7 )
2024-06-10 08:58:34 -05:00
. attr ( FormChangeItemTypeAttr ) ,
2023-12-11 19:09:38 -06:00
/* Unused */
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TEN_MILLION_VOLT_THUNDERBOLT , Type . ELECTRIC , MoveCategory . SPECIAL , 195 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. partial ( )
. ignoresVirtual ( ) ,
2023-12-11 19:09:38 -06:00
/* End Unused */
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MIND_BLOWN , Type . FIRE , MoveCategory . SPECIAL , 150 , 100 , 5 , - 1 , 0 , 7 )
2024-04-26 21:44:25 +10:00
. condition ( failIfDampCondition )
2024-04-25 21:42:41 -04:00
. attr ( HalfSacrificialAttr )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_OTHERS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PLASMA_FISTS , Type . ELECTRIC , MoveCategory . PHYSICAL , 100 , 100 , 15 , - 1 , 0 , 7 )
. punchingMove ( )
. partial ( ) ,
new AttackMove ( Moves . PHOTON_GEYSER , Type . PSYCHIC , MoveCategory . SPECIAL , 100 , 100 , 5 , - 1 , 0 , 7 )
. attr ( PhotonGeyserCategoryAttr )
2024-04-18 15:44:03 +10:00
. ignoresAbilities ( )
2024-04-16 20:29:32 +02:00
. partial ( ) ,
2023-11-30 16:37:16 -05:00
/* Unused */
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LIGHT_THAT_BURNS_THE_SKY , Type . PSYCHIC , MoveCategory . SPECIAL , 200 , - 1 , 1 , - 1 , 0 , 7 )
. attr ( PhotonGeyserCategoryAttr )
2024-05-09 15:38:46 +10:00
. ignoresAbilities ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SEARING_SUNRAZE_SMASH , Type . STEEL , MoveCategory . PHYSICAL , 200 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. ignoresAbilities ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MENACING_MOONRAZE_MAELSTROM , Type . GHOST , MoveCategory . SPECIAL , 200 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. ignoresAbilities ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LETS_SNUGGLE_FOREVER , Type . FAIRY , MoveCategory . PHYSICAL , 190 , - 1 , 1 , - 1 , 0 , 7 )
2024-05-09 15:38:46 +10:00
. partial ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPLINTERED_STORMSHARDS , Type . ROCK , MoveCategory . PHYSICAL , 190 , - 1 , 1 , - 1 , 0 , 7 )
2024-04-01 20:57:22 -05:00
. attr ( ClearTerrainAttr )
2024-05-09 15:38:46 +10:00
. makesContact ( false )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CLANGOROUS_SOULBLAZE , Type . DRAGON , MoveCategory . SPECIAL , 185 , - 1 , 1 , 100 , 0 , 7 )
2024-04-15 03:11:22 +10:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 1 , true )
2023-12-15 01:41:45 -06:00
. soundBased ( )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . ALL_NEAR_ENEMIES )
2024-05-09 15:38:46 +10:00
. partial ( )
. ignoresVirtual ( ) ,
2024-03-03 23:44:37 -06:00
/* End Unused */
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ZIPPY_ZAP , Type . ELECTRIC , MoveCategory . PHYSICAL , 80 , 100 , 10 , 100 , 2 , 7 )
2024-05-13 20:59:38 -05:00
. attr ( StatChangeAttr , BattleStat . EVA , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPLISHY_SPLASH , Type . WATER , MoveCategory . SPECIAL , 90 , 100 , 15 , 30 , 0 , 7 )
2024-02-20 22:43:43 -06:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLOATY_FALL , Type . FLYING , MoveCategory . PHYSICAL , 90 , 95 , 15 , 30 , 0 , 7 )
2024-02-20 22:43:43 -06:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PIKA_PAPOW , Type . ELECTRIC , MoveCategory . SPECIAL , - 1 , - 1 , 20 , - 1 , 0 , 7 )
2024-02-20 22:43:43 -06:00
. attr ( FriendshipPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BOUNCY_BUBBLE , Type . WATER , MoveCategory . SPECIAL , 60 , 100 , 20 , - 1 , 0 , 7 )
2024-05-06 02:01:39 +10:00
. attr ( HitHealAttr , 1.0 )
2024-05-07 23:01:54 -05:00
. triageMove ( )
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BUZZY_BUZZ , Type . ELECTRIC , MoveCategory . SPECIAL , 60 , 100 , 20 , 100 , 0 , 7 )
2024-02-20 22:43:43 -06:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SIZZLY_SLIDE , Type . FIRE , MoveCategory . PHYSICAL , 60 , 100 , 20 , 100 , 0 , 7 )
2024-02-20 22:43:43 -06:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GLITZY_GLOW , Type . PSYCHIC , MoveCategory . SPECIAL , 80 , 95 , 15 , - 1 , 0 , 7 )
2024-04-05 14:28:50 -05:00
. attr ( AddArenaTagAttr , ArenaTagType . LIGHT_SCREEN , 5 , false , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BADDY_BAD , Type . DARK , MoveCategory . SPECIAL , 80 , 95 , 15 , - 1 , 0 , 7 )
2024-04-05 14:28:50 -05:00
. attr ( AddArenaTagAttr , ArenaTagType . REFLECT , 5 , false , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SAPPY_SEED , Type . GRASS , MoveCategory . PHYSICAL , 100 , 90 , 10 , 100 , 0 , 7 )
2024-02-20 22:43:43 -06:00
. attr ( AddBattlerTagAttr , BattlerTagType . SEEDED ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FREEZY_FROST , Type . ICE , MoveCategory . SPECIAL , 100 , 90 , 10 , - 1 , 0 , 7 )
2024-04-18 16:28:22 +10:00
. attr ( ResetStatsAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPARKLY_SWIRL , Type . FAIRY , MoveCategory . SPECIAL , 120 , 85 , 5 , - 1 , 0 , 7 )
2024-05-17 15:37:34 -05:00
. attr ( PartyStatusCureAttr , null , Abilities . NONE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . VEEVEE_VOLLEY , Type . NORMAL , MoveCategory . PHYSICAL , - 1 , - 1 , 20 , - 1 , 0 , 7 )
2024-02-20 22:43:43 -06:00
. attr ( FriendshipPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DOUBLE_IRON_BASH , Type . STEEL , MoveCategory . PHYSICAL , 60 , 100 , 5 , 30 , 0 , 7 )
2023-12-10 21:52:11 -06:00
. attr ( MultiHitAttr , MultiHitType . _2 )
2023-12-15 01:41:45 -06:00
. attr ( FlinchAttr )
. punchingMove ( ) ,
2024-02-08 16:50:17 -06:00
/* Unused */
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . MAX_GUARD , Type . NORMAL , - 1 , 10 , - 1 , 4 , 8 )
2024-05-09 15:38:46 +10:00
. attr ( ProtectAttr )
. ignoresVirtual ( ) ,
2024-02-08 16:50:17 -06:00
/* End Unused */
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DYNAMAX_CANNON , Type . DRAGON , MoveCategory . SPECIAL , 100 , 100 , 5 , - 1 , 0 , 8 )
2023-12-10 17:57:12 -05:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . level > 200 ? 2 : 1 )
2024-01-13 12:24:24 -05:00
. attr ( DiscourageFrequentUseAttr )
2023-11-28 21:35:52 -05:00
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SNIPE_SHOT , Type . WATER , MoveCategory . SPECIAL , 80 , 100 , 15 , - 1 , 0 , 8 )
2024-05-24 01:45:04 +02:00
. attr ( HighCritAttr )
2024-05-10 11:40:21 -04:00
. attr ( BypassRedirectAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . JAW_LOCK , Type . DARK , MoveCategory . PHYSICAL , 80 , 100 , 10 , - 1 , 0 , 8 )
2024-04-01 20:28:03 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , false , false , 1 )
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , true , false , 1 )
2023-12-15 01:41:45 -06:00
. bitingMove ( ) ,
2024-06-13 16:24:32 -04:00
new SelfStatusMove ( Moves . STUFF_CHEEKS , Type . NORMAL , - 1 , 10 , 100 , 0 , 8 ) // TODO: Stuff Cheeks should not be selectable when the user does not have a berry, see wiki
. attr ( EatBerryAttr )
. attr ( StatChangeAttr , BattleStat . DEF , 2 , true )
. condition ( ( user ) = > {
const userBerries = user . scene . findModifiers ( m = > m instanceof BerryModifier ) ;
return userBerries . length > 0 ;
} )
. partial ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . NO_RETREAT , Type . FIGHTING , - 1 , 5 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 1 , true )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , true , true , 1 ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . TAR_SHOT , Type . ROCK , 100 , 15 , 100 , 0 , 8 )
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
. partial ( ) ,
new StatusMove ( Moves . MAGIC_POWDER , Type . PSYCHIC , 100 , 20 , - 1 , 0 , 8 )
2024-04-21 01:43:19 -04:00
. attr ( ChangeTypeAttr , Type . PSYCHIC )
. powderMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_DARTS , Type . DRAGON , MoveCategory . PHYSICAL , 50 , 100 , 10 , - 1 , 0 , 8 )
2024-04-01 20:57:22 -05:00
. attr ( MultiHitAttr , MultiHitType . _2 )
2024-04-16 20:29:32 +02:00
. makesContact ( false )
. partial ( ) ,
new StatusMove ( Moves . TEATIME , Type . NORMAL , - 1 , 10 , - 1 , 0 , 8 )
2024-05-19 18:47:30 -04:00
. attr ( EatBerryAttr )
. target ( MoveTarget . ALL ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . OCTOLOCK , Type . FIGHTING , 100 , 15 , - 1 , 0 , 8 )
. attr ( AddBattlerTagAttr , BattlerTagType . TRAPPED , false , true , 1 )
. partial ( ) ,
new AttackMove ( Moves . BOLT_BEAK , Type . ELECTRIC , MoveCategory . PHYSICAL , 85 , 100 , 10 , - 1 , 0 , 8 )
2024-03-18 22:05:21 -04:00
. attr ( FirstAttackDoublePowerAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FISHIOUS_REND , Type . WATER , MoveCategory . PHYSICAL , 85 , 100 , 10 , - 1 , 0 , 8 )
2024-03-18 22:05:21 -04:00
. attr ( FirstAttackDoublePowerAttr )
2023-12-15 01:41:45 -06:00
. bitingMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . COURT_CHANGE , Type . NORMAL , 100 , 10 , - 1 , 0 , 8 )
2024-06-07 10:27:11 -04:00
. attr ( SwapArenaTagsAttr , [ ArenaTagType . AURORA_VEIL , ArenaTagType . LIGHT_SCREEN , ArenaTagType . MIST , ArenaTagType . REFLECT , ArenaTagType . SPIKES , ArenaTagType . STEALTH_ROCK , ArenaTagType . STICKY_WEB , ArenaTagType . TAILWIND , ArenaTagType . TOXIC_SPIKES ] ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_FLARE , Type . FIRE , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_FLUTTERBY , Type . BUG , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_LIGHTNING , Type . ELECTRIC , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_STRIKE , Type . NORMAL , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_KNUCKLE , Type . FIGHTING , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_PHANTASM , Type . GHOST , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_HAILSTORM , Type . ICE , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_OOZE , Type . POISON , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_GEYSER , Type . WATER , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_AIRSTREAM , Type . FLYING , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_STARFALL , Type . FAIRY , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_WYRMWIND , Type . DRAGON , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_MINDSTORM , Type . PSYCHIC , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_ROCKFALL , Type . ROCK , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_QUAKE , Type . GROUND , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_DARKNESS , Type . DARK , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_OVERGROWTH , Type . GRASS , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAX_STEELSPIKE , Type . STEEL , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . NEAR_ENEMY )
2024-05-09 15:38:46 +10:00
. unimplemented ( )
. ignoresVirtual ( ) ,
2023-11-30 16:37:16 -05:00
/* End Unused */
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . CLANGOROUS_SOUL , Type . DRAGON , 100 , 5 , 100 , 0 , 8 )
2024-04-10 17:31:39 -04:00
. attr ( CutHpStatBoostAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPATK , BattleStat . SPDEF , BattleStat . SPD ] , 1 , 3 )
2023-12-15 01:41:45 -06:00
. soundBased ( )
. danceMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BODY_PRESS , Type . FIGHTING , MoveCategory . PHYSICAL , 80 , 100 , 10 , - 1 , 0 , 8 )
2024-03-11 21:45:32 +01:00
. attr ( DefAtkAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . DECORATE , Type . FAIRY , - 1 , 15 , 100 , 0 , 8 )
2024-05-05 01:28:15 +03:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPATK ] , 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRUM_BEATING , Type . GRASS , MoveCategory . PHYSICAL , 80 , 100 , 10 , 100 , 0 , 8 )
2024-04-01 20:57:22 -05:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SNAP_TRAP , Type . GRASS , MoveCategory . PHYSICAL , 35 , 100 , 15 , 100 , 0 , 8 )
2024-04-23 13:04:42 -05:00
. attr ( TrapAttr , BattlerTagType . SNAP_TRAP ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PYRO_BALL , Type . FIRE , MoveCategory . PHYSICAL , 120 , 90 , 5 , 10 , 0 , 8 )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2023-12-15 01:41:45 -06:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
2024-04-01 20:57:22 -05:00
. ballBombMove ( )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BEHEMOTH_BLADE , Type . STEEL , MoveCategory . PHYSICAL , 100 , 100 , 5 , - 1 , 0 , 8 )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BEHEMOTH_BASH , Type . STEEL , MoveCategory . PHYSICAL , 100 , 100 , 5 , - 1 , 0 , 8 ) ,
new AttackMove ( Moves . AURA_WHEEL , Type . ELECTRIC , MoveCategory . PHYSICAL , 110 , 100 , 10 , 100 , 0 , 8 )
2024-04-01 20:57:22 -05:00
. attr ( StatChangeAttr , BattleStat . SPD , 1 , true )
2024-04-09 21:02:41 +03:00
. makesContact ( false )
. attr ( AuraWheelTypeAttr )
. condition ( ( user , target , move ) = > [ user . species . speciesId , user . fusionSpecies ? . speciesId ] . includes ( Species . MORPEKO ) ) , // Missing custom fail message
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BREAKING_SWIPE , Type . DRAGON , MoveCategory . PHYSICAL , 60 , 100 , 15 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BRANCH_POKE , Type . GRASS , MoveCategory . PHYSICAL , 40 , 100 , 40 , - 1 , 0 , 8 ) ,
new AttackMove ( Moves . OVERDRIVE , Type . ELECTRIC , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 8 )
2023-12-15 01:41:45 -06:00
. soundBased ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . APPLE_ACID , Type . GRASS , MoveCategory . SPECIAL , 80 , 100 , 10 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GRAV_APPLE , Type . GRASS , MoveCategory . PHYSICAL , 80 , 100 , 10 , 100 , 0 , 8 )
2024-04-01 20:57:22 -05:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 )
2024-04-15 03:11:22 +10:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . scene . arena . getTag ( ArenaTagType . GRAVITY ) ? 1.5 : 1 )
2024-04-01 20:57:22 -05:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPIRIT_BREAK , Type . FAIRY , MoveCategory . PHYSICAL , 75 , 100 , 15 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STRANGE_STEAM , Type . FAIRY , MoveCategory . SPECIAL , 90 , 95 , 10 , 20 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( ConfuseAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . LIFE_DEW , Type . WATER , - 1 , 10 , - 1 , 0 , 8 )
2024-03-26 15:21:22 -05:00
. attr ( HealAttr , 0.25 , true , false )
2024-05-12 08:18:23 +01:00
. target ( MoveTarget . USER_AND_ALLIES )
. ignoresProtect ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . OBSTRUCT , Type . DARK , 100 , 10 , - 1 , 4 , 8 )
2024-03-30 18:05:21 -05:00
. attr ( ProtectAttr , BattlerTagType . OBSTRUCT ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FALSE_SURRENDER , Type . DARK , MoveCategory . PHYSICAL , 80 , - 1 , 10 , - 1 , 0 , 8 ) ,
new AttackMove ( Moves . METEOR_ASSAULT , Type . FIGHTING , MoveCategory . PHYSICAL , 150 , 100 , 5 , - 1 , 0 , 8 )
2024-04-01 20:57:22 -05:00
. attr ( RechargeAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ETERNABEAM , Type . DRAGON , MoveCategory . SPECIAL , 160 , 90 , 5 , - 1 , 0 , 8 )
2024-01-07 23:17:24 -05:00
. attr ( RechargeAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STEEL_BEAM , Type . STEEL , MoveCategory . SPECIAL , 140 , 95 , 5 , - 1 , 0 , 8 )
2024-04-25 21:42:41 -04:00
. attr ( HalfSacrificialAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EXPANDING_FORCE , Type . PSYCHIC , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 8 )
2024-05-04 11:52:24 -04:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . scene . arena . getTerrainType ( ) === TerrainType . PSYCHIC && user . isGrounded ( ) ? 1.5 : 1 )
. attr ( VariableTargetAttr , ( user , target , move ) = > user . scene . arena . getTerrainType ( ) === TerrainType . PSYCHIC && user . isGrounded ( ) ? 6 : 3 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . STEEL_ROLLER , Type . STEEL , MoveCategory . PHYSICAL , 130 , 100 , 5 , - 1 , 0 , 8 )
2024-03-09 22:05:49 -05:00
. attr ( ClearTerrainAttr )
. condition ( ( user , target , move ) = > ! ! user . scene . arena . terrain ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SCALE_SHOT , Type . DRAGON , MoveCategory . PHYSICAL , 25 , 90 , 20 , 100 , 0 , 8 )
2023-12-11 19:09:38 -06:00
//.attr(StatChangeAttr, BattleStat.SPD, 1, true) // TODO: Have boosts only apply at end of move, not after every hit
//.attr(StatChangeAttr, BattleStat.DEF, -1, true)
2024-04-01 20:57:22 -05:00
. attr ( MultiHitAttr )
2024-04-16 20:29:32 +02:00
. makesContact ( false )
. partial ( ) ,
new AttackMove ( Moves . METEOR_BEAM , Type . ROCK , MoveCategory . SPECIAL , 120 , 90 , 10 , 100 , 0 , 8 )
2024-05-23 17:03:10 +02:00
. attr ( ChargeAttr , ChargeAnim . METEOR_BEAM_CHARGING , "is overflowing\nwith space power!" , null , true )
2023-12-11 19:09:38 -06:00
. attr ( StatChangeAttr , BattleStat . SPATK , 1 , true )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SHELL_SIDE_ARM , Type . POISON , MoveCategory . SPECIAL , 90 , 100 , 10 , 20 , 0 , 8 )
2024-04-11 07:49:35 +10:00
. attr ( ShellSideArmCategoryAttr )
2024-04-16 20:29:32 +02:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. partial ( ) ,
new AttackMove ( Moves . MISTY_EXPLOSION , Type . FAIRY , MoveCategory . SPECIAL , 100 , 100 , 5 , - 1 , 0 , 8 )
2024-04-25 21:42:41 -04:00
. attr ( SacrificialAttr )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . ALL_NEAR_OTHERS )
2024-04-26 21:44:25 +10:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . scene . arena . getTerrainType ( ) === TerrainType . MISTY && user . isGrounded ( ) ? 1.5 : 1 )
2024-05-19 09:31:13 -04:00
. condition ( failIfDampCondition )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GRASSY_GLIDE , Type . GRASS , MoveCategory . PHYSICAL , 55 , 100 , 20 , - 1 , 0 , 8 )
2024-05-20 07:52:51 +09:00
. attr ( IncrementMovePriorityAttr , ( user , target , move ) = > user . scene . arena . getTerrainType ( ) === TerrainType . GRASSY && user . isGrounded ( ) ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RISING_VOLTAGE , Type . ELECTRIC , MoveCategory . SPECIAL , 70 , 100 , 20 , - 1 , 0 , 8 )
2024-04-10 16:10:34 +03:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . scene . arena . getTerrainType ( ) === TerrainType . ELECTRIC && target . isGrounded ( ) ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TERRAIN_PULSE , Type . NORMAL , MoveCategory . SPECIAL , 50 , 100 , 10 , - 1 , 0 , 8 )
2024-05-19 09:31:13 -04:00
. attr ( TerrainPulseTypeAttr )
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . scene . arena . getTerrainType ( ) !== TerrainType . NONE && user . isGrounded ( ) ? 2 : 1 )
. pulseMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SKITTER_SMACK , Type . BUG , MoveCategory . PHYSICAL , 70 , 90 , 10 , 100 , 0 , 8 )
2023-12-09 20:09:09 -05:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BURNING_JEALOUSY , Type . FIRE , MoveCategory . SPECIAL , 70 , 100 , 5 , 100 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. partial ( ) ,
new AttackMove ( Moves . LASH_OUT , Type . DARK , MoveCategory . PHYSICAL , 75 , 100 , 5 , - 1 , 0 , 8 )
. partial ( ) ,
new AttackMove ( Moves . POLTERGEIST , Type . GHOST , MoveCategory . PHYSICAL , 110 , 90 , 5 , - 1 , 0 , 8 )
2024-06-16 04:24:38 +02:00
. attr ( AttackedByItemAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . CORROSIVE_GAS , Type . POISON , 100 , 40 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_OTHERS )
. unimplemented ( ) ,
new StatusMove ( Moves . COACHING , Type . FIGHTING , - 1 , 10 , 100 , 0 , 8 )
2023-12-09 20:09:09 -05:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF ] , 1 )
2024-02-08 16:50:17 -06:00
. target ( MoveTarget . NEAR_ALLY ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLIP_TURN , Type . WATER , MoveCategory . PHYSICAL , 60 , 100 , 20 , - 1 , 0 , 8 )
2024-04-17 09:56:13 +07:00
. attr ( ForceSwitchOutAttr , true , false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TRIPLE_AXEL , Type . ICE , MoveCategory . PHYSICAL , 20 , 90 , 10 , - 1 , 0 , 8 )
2024-05-28 19:07:35 -04:00
. attr ( MultiHitAttr , MultiHitType . _3 )
. attr ( MultiHitPowerIncrementAttr , 3 )
. checkAllHits ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DUAL_WINGBEAT , Type . FLYING , MoveCategory . PHYSICAL , 40 , 90 , 10 , - 1 , 0 , 8 )
2023-12-09 20:09:09 -05:00
. attr ( MultiHitAttr , MultiHitType . _2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SCORCHING_SANDS , Type . GROUND , MoveCategory . SPECIAL , 70 , 100 , 10 , 30 , 0 , 8 )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2024-05-30 16:04:50 -04:00
. attr ( HealStatusEffectAttr , false , StatusEffect . FREEZE )
2023-12-09 20:09:09 -05:00
. attr ( StatusEffectAttr , StatusEffect . BURN ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . JUNGLE_HEALING , Type . GRASS , - 1 , 10 , - 1 , 0 , 8 )
2024-04-14 08:19:31 -05:00
. attr ( HealAttr , 0.25 , true , false )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . USER_AND_ALLIES )
. partial ( ) ,
new AttackMove ( Moves . WICKED_BLOW , Type . DARK , MoveCategory . PHYSICAL , 75 , 100 , 5 , - 1 , 0 , 8 )
2023-12-15 01:41:45 -06:00
. attr ( CritOnlyAttr )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SURGING_STRIKES , Type . WATER , MoveCategory . PHYSICAL , 25 , 100 , 5 , - 1 , 0 , 8 )
2023-12-09 20:09:09 -05:00
. attr ( MultiHitAttr , MultiHitType . _3 )
2023-12-15 01:41:45 -06:00
. attr ( CritOnlyAttr )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THUNDER_CAGE , Type . ELECTRIC , MoveCategory . SPECIAL , 80 , 90 , 15 , 100 , 0 , 8 )
2024-02-08 16:50:17 -06:00
. attr ( TrapAttr , BattlerTagType . THUNDER_CAGE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . DRAGON_ENERGY , Type . DRAGON , MoveCategory . SPECIAL , 150 , 100 , 5 , - 1 , 0 , 8 )
2024-02-08 16:50:17 -06:00
. attr ( HpPowerAttr )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FREEZING_GLARE , Type . PSYCHIC , MoveCategory . SPECIAL , 90 , 100 , 10 , 10 , 0 , 8 )
2023-12-09 20:09:09 -05:00
. attr ( StatusEffectAttr , StatusEffect . FREEZE ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FIERY_WRATH , Type . DARK , MoveCategory . SPECIAL , 90 , 100 , 10 , 20 , 0 , 8 )
2023-12-09 20:09:09 -05:00
. attr ( FlinchAttr )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THUNDEROUS_KICK , Type . FIGHTING , MoveCategory . PHYSICAL , 90 , 100 , 10 , 100 , 0 , 8 )
2023-12-09 20:09:09 -05:00
. attr ( StatChangeAttr , BattleStat . DEF , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GLACIAL_LANCE , Type . ICE , MoveCategory . PHYSICAL , 120 , 100 , 5 , - 1 , 0 , 8 )
2024-05-06 12:00:51 -04:00
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ASTRAL_BARRAGE , Type . GHOST , MoveCategory . SPECIAL , 120 , 100 , 5 , - 1 , 0 , 8 )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . EERIE_SPELL , Type . PSYCHIC , MoveCategory . SPECIAL , 80 , 100 , 5 , 100 , 0 , 8 )
. soundBased ( )
. partial ( ) ,
new AttackMove ( Moves . DIRE_CLAW , Type . POISON , MoveCategory . PHYSICAL , 80 , 100 , 15 , 50 , 0 , 8 )
2024-04-30 23:30:10 -04:00
. attr ( MultiStatusEffectAttr , [ StatusEffect . POISON , StatusEffect . PARALYSIS , StatusEffect . SLEEP ] ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYSHIELD_BASH , Type . PSYCHIC , MoveCategory . PHYSICAL , 70 , 90 , 10 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . DEF , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . POWER_SHIFT , Type . NORMAL , - 1 , 10 , 100 , 0 , 8 )
. unimplemented ( ) ,
new AttackMove ( Moves . STONE_AXE , Type . ROCK , MoveCategory . PHYSICAL , 65 , 90 , 15 , 100 , 0 , 8 )
2023-12-15 01:41:45 -06:00
. attr ( AddArenaTrapTagAttr , ArenaTagType . STEALTH_ROCK )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPRINGTIDE_STORM , Type . FAIRY , MoveCategory . SPECIAL , 100 , 80 , 5 , 30 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MYSTICAL_POWER , Type . PSYCHIC , MoveCategory . SPECIAL , 70 , 90 , 10 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPATK , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RAGING_FURY , Type . FIRE , MoveCategory . PHYSICAL , 120 , 100 , 10 , - 1 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( FrenzyAttr )
. attr ( MissEffectAttr , frenzyMissFunc )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . RANDOM_NEAR_ENEMY ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WAVE_CRASH , Type . WATER , MoveCategory . PHYSICAL , 120 , 100 , 10 , - 1 , 0 , 8 )
2024-05-07 23:28:35 -05:00
. attr ( RecoilAttr , false , 0.33 )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CHLOROBLAST , Type . GRASS , MoveCategory . SPECIAL , 150 , 95 , 5 , - 1 , 0 , 8 )
2024-03-26 17:01:55 -05:00
. attr ( RecoilAttr , true , 0.5 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MOUNTAIN_GALE , Type . ICE , MoveCategory . PHYSICAL , 100 , 85 , 10 , 30 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( FlinchAttr ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . VICTORY_DANCE , Type . FIGHTING , - 1 , 10 , 100 , 0 , 8 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . DEF , BattleStat . SPD ] , 1 , true )
. danceMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HEADLONG_RUSH , Type . GROUND , MoveCategory . PHYSICAL , 120 , 100 , 5 , 100 , 0 , 8 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF ] , - 1 , true )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BARB_BARRAGE , Type . POISON , MoveCategory . PHYSICAL , 60 , 100 , 10 , 50 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . status && ( target . status . effect === StatusEffect . POISON || target . status . effect === StatusEffect . TOXIC ) ? 2 : 1 )
. attr ( StatusEffectAttr , StatusEffect . POISON ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ESPER_WING , Type . PSYCHIC , MoveCategory . SPECIAL , 80 , 100 , 10 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( HighCritAttr )
. attr ( StatChangeAttr , BattleStat . SPD , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BITTER_MALICE , Type . GHOST , MoveCategory . SPECIAL , 75 , 100 , 10 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SHELTER , Type . STEEL , - 1 , 10 , 100 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . DEF , 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TRIPLE_ARROWS , Type . FIGHTING , MoveCategory . PHYSICAL , 90 , 100 , 10 , 30 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( HighCritAttr )
. attr ( StatChangeAttr , BattleStat . DEF , - 1 )
2024-04-16 20:29:32 +02:00
. attr ( FlinchAttr )
. partial ( ) ,
new AttackMove ( Moves . INFERNAL_PARADE , Type . GHOST , MoveCategory . SPECIAL , 60 , 100 , 15 , 30 , 0 , 8 )
2024-02-08 16:50:17 -06:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . status ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CEASELESS_EDGE , Type . DARK , MoveCategory . PHYSICAL , 65 , 90 , 15 , 100 , 0 , 8 )
2023-12-15 01:41:45 -06:00
. attr ( AddArenaTrapTagAttr , ArenaTagType . SPIKES )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLEAKWIND_STORM , Type . FLYING , MoveCategory . SPECIAL , 100 , 80 , 10 , 30 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( ThunderAccuracyAttr )
. attr ( StatChangeAttr , BattleStat . SPD , - 1 )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WILDBOLT_STORM , Type . ELECTRIC , MoveCategory . SPECIAL , 100 , 80 , 10 , 20 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( ThunderAccuracyAttr )
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SANDSEAR_STORM , Type . GROUND , MoveCategory . SPECIAL , 100 , 80 , 10 , 20 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( ThunderAccuracyAttr )
. attr ( StatusEffectAttr , StatusEffect . BURN )
2023-12-15 01:41:45 -06:00
. windMove ( )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . LUNAR_BLESSING , Type . PSYCHIC , - 1 , 5 , - 1 , 0 , 8 )
2023-12-10 21:52:11 -06:00
. attr ( HealAttr , 0.25 )
2024-04-08 17:10:07 +03:00
. target ( MoveTarget . USER_AND_ALLIES )
2024-04-16 20:29:32 +02:00
. triageMove ( )
. partial ( ) ,
new SelfStatusMove ( Moves . TAKE_HEART , Type . PSYCHIC , - 1 , 10 , - 1 , 0 , 8 )
. attr ( StatChangeAttr , [ BattleStat . SPATK , BattleStat . SPDEF ] , 1 , true )
2024-05-05 14:04:19 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . PARALYSIS , StatusEffect . POISON , StatusEffect . TOXIC , StatusEffect . BURN , StatusEffect . SLEEP ) ,
2024-03-10 21:55:18 -05:00
/ * U n u s e d
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . G_MAX_WILDFIRE , Type . FIRE , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_BEFUDDLE , Type . BUG , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_VOLT_CRASH , Type . ELECTRIC , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_GOLD_RUSH , Type . NORMAL , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_CHI_STRIKE , Type . FIGHTING , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_TERROR , Type . GHOST , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_RESONANCE , Type . ICE , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_CUDDLE , Type . NORMAL , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_REPLENISH , Type . NORMAL , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_MALODOR , Type . POISON , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_STONESURGE , Type . WATER , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_WIND_RAGE , Type . FLYING , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_STUN_SHOCK , Type . ELECTRIC , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_FINALE , Type . FAIRY , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_DEPLETION , Type . DRAGON , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_GRAVITAS , Type . PSYCHIC , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_VOLCALITH , Type . ROCK , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_SANDBLAST , Type . GROUND , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_SNOOZE , Type . DARK , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_TARTNESS , Type . GRASS , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_SWEETNESS , Type . GRASS , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_SMITE , Type . FAIRY , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_STEELSURGE , Type . STEEL , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_MELTDOWN , Type . STEEL , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_FOAM_BURST , Type . WATER , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_CENTIFERNO , Type . FIRE , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_VINE_LASH , Type . GRASS , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_CANNONADE , Type . WATER , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_DRUM_SOLO , Type . GRASS , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_FIREBALL , Type . FIRE , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_HYDROSNIPE , Type . WATER , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_ONE_BLOW , Type . DARK , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
new AttackMove ( Moves . G_MAX_RAPID_FLOW , Type . WATER , MoveCategory . PHYSICAL , 10 , - 1 , 10 , - 1 , 0 , 8 )
. target ( MoveTarget . ALL_NEAR_ENEMIES )
. unimplemented ( ) ,
2024-03-10 21:55:18 -05:00
End Unused * /
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TERA_BLAST , Type . NORMAL , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 9 )
. attr ( TeraBlastCategoryAttr )
2024-05-23 00:37:23 -04:00
. unimplemented ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SILK_TRAP , Type . BUG , - 1 , 10 , - 1 , 4 , 9 )
2024-03-30 18:05:21 -05:00
. attr ( ProtectAttr , BattlerTagType . SILK_TRAP ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AXE_KICK , Type . FIGHTING , MoveCategory . PHYSICAL , 120 , 90 , 10 , 30 , 0 , 9 )
2024-04-12 18:49:48 -07:00
. attr ( MissEffectAttr , crashDamageFunc )
. attr ( NoEffectAttr , crashDamageFunc )
2024-05-07 23:28:35 -05:00
. attr ( ConfuseAttr )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LAST_RESPECTS , Type . GHOST , MoveCategory . PHYSICAL , 50 , 100 , 10 , - 1 , 0 , 9 )
2024-05-30 01:07:59 +10:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > 1 + Math . min ( user . isPlayer ( ) ? user.scene.currentBattle.playerFaints : user.scene.currentBattle.enemyFaints , 100 ) )
2024-04-01 20:57:22 -05:00
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . LUMINA_CRASH , Type . PSYCHIC , MoveCategory . SPECIAL , 80 , 100 , 10 , 100 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPDEF , - 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ORDER_UP , Type . DRAGON , MoveCategory . PHYSICAL , 80 , 100 , 10 , - 1 , 0 , 9 )
. makesContact ( false )
. partial ( ) ,
new AttackMove ( Moves . JET_PUNCH , Type . WATER , MoveCategory . PHYSICAL , 60 , 100 , 15 , - 1 , 1 , 9 )
2023-12-15 01:41:45 -06:00
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SPICY_EXTRACT , Type . GRASS , - 1 , 15 , 100 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , 2 )
. attr ( StatChangeAttr , BattleStat . DEF , - 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SPIN_OUT , Type . STEEL , MoveCategory . PHYSICAL , 100 , 100 , 5 , 100 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPD , - 2 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POPULATION_BOMB , Type . NORMAL , MoveCategory . PHYSICAL , 20 , 90 , 10 , - 1 , 0 , 9 )
2024-05-28 19:07:35 -04:00
. attr ( MultiHitAttr , MultiHitType . _10 )
2024-04-16 20:29:32 +02:00
. slicingMove ( )
2024-05-28 19:07:35 -04:00
. checkAllHits ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ICE_SPINNER , Type . ICE , MoveCategory . PHYSICAL , 80 , 100 , 15 , - 1 , 0 , 9 )
2024-03-09 22:05:49 -05:00
. attr ( ClearTerrainAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GLAIVE_RUSH , Type . DRAGON , MoveCategory . PHYSICAL , 120 , 100 , 5 , - 1 , 0 , 9 )
. partial ( ) ,
new StatusMove ( Moves . REVIVAL_BLESSING , Type . NORMAL , - 1 , 1 , - 1 , 0 , 9 )
. triageMove ( )
2024-05-20 08:02:17 +09:00
. attr ( RevivalBlessingAttr )
. target ( MoveTarget . USER ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SALT_CURE , Type . ROCK , MoveCategory . PHYSICAL , 40 , 100 , 15 , - 1 , 0 , 9 )
2024-04-01 20:57:22 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . SALT_CURED )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TRIPLE_DIVE , Type . WATER , MoveCategory . PHYSICAL , 30 , 95 , 10 , - 1 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( MultiHitAttr , MultiHitType . _3 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MORTAL_SPIN , Type . POISON , MoveCategory . PHYSICAL , 30 , 100 , 15 , 100 , 0 , 9 )
2024-04-18 11:14:11 -04:00
. attr ( LapseBattlerTagAttr , [
BattlerTagType . BIND ,
BattlerTagType . WRAP ,
BattlerTagType . FIRE_SPIN ,
BattlerTagType . WHIRLPOOL ,
BattlerTagType . CLAMP ,
BattlerTagType . SAND_TOMB ,
BattlerTagType . MAGMA_STORM ,
2024-04-23 13:04:42 -05:00
BattlerTagType . SNAP_TRAP ,
2024-04-18 11:14:11 -04:00
BattlerTagType . THUNDER_CAGE ,
BattlerTagType . SEEDED ,
BattlerTagType . INFESTATION
] , true )
2024-02-08 16:50:17 -06:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
2024-05-06 23:00:31 -04:00
. attr ( RemoveArenaTrapAttr )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . DOODLE , Type . NORMAL , 100 , 10 , - 1 , 0 , 9 )
2024-04-14 13:21:34 +10:00
. attr ( AbilityCopyAttr , true ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . FILLET_AWAY , Type . NORMAL , - 1 , 10 , - 1 , 0 , 9 )
2024-04-10 17:31:39 -04:00
. attr ( CutHpStatBoostAttr , [ BattleStat . ATK , BattleStat . SPATK , BattleStat . SPD ] , 2 , 2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . KOWTOW_CLEAVE , Type . DARK , MoveCategory . PHYSICAL , 85 , - 1 , 10 , - 1 , 0 , 9 )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . FLOWER_TRICK , Type . GRASS , MoveCategory . PHYSICAL , 70 , - 1 , 10 , 100 , 0 , 9 )
2024-04-01 20:57:22 -05:00
. attr ( CritOnlyAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TORCH_SONG , Type . FIRE , MoveCategory . SPECIAL , 80 , 100 , 10 , 100 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPATK , 1 , true )
. soundBased ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AQUA_STEP , Type . WATER , MoveCategory . PHYSICAL , 80 , 100 , 10 , 100 , 0 , 9 )
2023-12-15 01:41:45 -06:00
. attr ( StatChangeAttr , BattleStat . SPD , 1 , true )
. danceMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RAGING_BULL , Type . NORMAL , MoveCategory . PHYSICAL , 90 , 100 , 10 , - 1 , 0 , 9 )
2024-04-14 22:26:58 -04:00
. attr ( RagingBullTypeAttr )
. attr ( RemoveScreensAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAKE_IT_RAIN , Type . STEEL , MoveCategory . SPECIAL , 120 , 100 , 5 , - 1 , 0 , 9 )
2024-04-03 22:52:39 -04:00
. attr ( MoneyAttr )
2024-03-18 17:15:20 -04:00
. attr ( StatChangeAttr , BattleStat . SPATK , - 1 , true , null , true , true )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . ALL_NEAR_ENEMIES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYBLADE , Type . PSYCHIC , MoveCategory . PHYSICAL , 80 , 100 , 15 , - 1 , 0 , 9 )
2024-05-24 01:45:04 +02:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . scene . arena . getTerrainType ( ) === TerrainType . ELECTRIC && user . isGrounded ( ) ? 1.5 : 1 )
2023-12-15 01:41:45 -06:00
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYDRO_STEAM , Type . WATER , MoveCategory . SPECIAL , 80 , 100 , 15 , - 1 , 0 , 9 )
2024-05-09 21:21:57 -04:00
. attr ( IgnoreWeatherTypeDebuffAttr , WeatherType . SUNNY )
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > [ WeatherType . SUNNY , WeatherType . HARSH_SUN ] . includes ( user . scene . arena . weather ? . weatherType ) && ! user . scene . arena . weather ? . isEffectSuppressed ( user . scene ) ? 1.5 : 1 ) ,
2024-04-22 01:53:24 +02:00
new AttackMove ( Moves . RUINATION , Type . DARK , MoveCategory . SPECIAL , - 1 , 90 , 10 , - 1 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( TargetHalfHpDamageAttr ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . COLLISION_COURSE , Type . FIGHTING , MoveCategory . PHYSICAL , 100 , 100 , 5 , - 1 , 0 , 9 )
2024-05-06 00:27:56 -05:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . getAttackTypeEffectiveness ( move . type , user ) >= 2 ? 5461 / 4096 : 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ELECTRO_DRIFT , Type . ELECTRIC , MoveCategory . SPECIAL , 100 , 100 , 5 , - 1 , 0 , 9 )
2024-05-06 00:27:56 -05:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > target . getAttackTypeEffectiveness ( move . type , user ) >= 2 ? 5461 / 4096 : 1 )
2024-04-01 20:57:22 -05:00
. makesContact ( ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . SHED_TAIL , Type . NORMAL , - 1 , 10 , - 1 , 0 , 9 )
. unimplemented ( ) ,
new StatusMove ( Moves . CHILLY_RECEPTION , Type . ICE , - 1 , 10 , - 1 , 0 , 9 )
2024-04-15 22:35:35 +02:00
. attr ( WeatherChangeAttr , WeatherType . SNOW )
2023-12-10 21:52:11 -06:00
. attr ( ForceSwitchOutAttr , true , false )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new SelfStatusMove ( Moves . TIDY_UP , Type . NORMAL , - 1 , 10 , 100 , 0 , 9 )
2024-05-10 12:31:27 -04:00
. attr ( StatChangeAttr , [ BattleStat . ATK , BattleStat . SPD ] , 1 , true , null , true , true )
. attr ( RemoveArenaTrapAttr )
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . SNOWSCAPE , Type . ICE , - 1 , 10 , - 1 , 0 , 9 )
2024-04-15 22:35:35 +02:00
. attr ( WeatherChangeAttr , WeatherType . SNOW )
2023-11-30 16:37:16 -05:00
. target ( MoveTarget . BOTH_SIDES ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . POUNCE , Type . BUG , MoveCategory . PHYSICAL , 50 , 100 , 20 , 100 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TRAILBLAZE , Type . GRASS , MoveCategory . PHYSICAL , 50 , 100 , 20 , 100 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . SPD , 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . CHILLING_WATER , Type . WATER , MoveCategory . SPECIAL , 50 , 100 , 20 , - 1 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , BattleStat . ATK , - 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HYPER_DRILL , Type . NORMAL , MoveCategory . PHYSICAL , 100 , 100 , 5 , - 1 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. ignoresProtect ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TWIN_BEAM , Type . PSYCHIC , MoveCategory . SPECIAL , 40 , 100 , 10 , - 1 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( MultiHitAttr , MultiHitType . _2 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . RAGE_FIST , Type . GHOST , MoveCategory . PHYSICAL , 50 , 100 , 10 , - 1 , 0 , 9 )
2023-12-15 01:41:45 -06:00
. attr ( HitCountPowerAttr )
. punchingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ARMOR_CANNON , Type . FIRE , MoveCategory . SPECIAL , 120 , 100 , 5 , - 1 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( StatChangeAttr , [ BattleStat . DEF , BattleStat . SPDEF ] , - 1 , true ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BITTER_BLADE , Type . FIRE , MoveCategory . PHYSICAL , 90 , 100 , 10 , - 1 , 0 , 9 )
2023-12-15 01:41:45 -06:00
. attr ( HitHealAttr )
2024-04-08 17:10:07 +03:00
. slicingMove ( )
. triageMove ( ) ,
2024-04-16 15:22:19 -04:00
new AttackMove ( Moves . DOUBLE_SHOCK , Type . ELECTRIC , MoveCategory . PHYSICAL , 120 , 100 , 5 , - 1 , 0 , 9 )
2024-05-23 17:03:10 +02:00
. condition ( ( user ) = > {
const userTypes = user . getTypes ( true ) ;
return userTypes . includes ( Type . ELECTRIC ) ;
} )
. attr ( RemoveTypeAttr , Type . ELECTRIC , ( user ) = > {
user . scene . queueMessage ( getPokemonMessage ( user , " used up all its electricity!" ) ) ;
} ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . GIGATON_HAMMER , Type . STEEL , MoveCategory . PHYSICAL , 160 , 100 , 5 , - 1 , 0 , 9 )
2024-04-15 03:11:22 +10:00
. makesContact ( false )
. condition ( ( user , target , move ) = > {
const turnMove = user . getLastXMoves ( 1 ) ;
return ! turnMove . length || turnMove [ 0 ] . move !== move . id || turnMove [ 0 ] . result !== MoveResult . SUCCESS ;
} ) , // TODO Add Instruct/Encore interaction
2024-05-14 02:48:22 +03:00
new AttackMove ( Moves . COMEUPPANCE , Type . DARK , MoveCategory . PHYSICAL , - 1 , 100 , 10 , - 1 , 0 , 9 )
2024-04-08 12:13:34 -04:00
. attr ( CounterDamageAttr , ( move : Move ) = > ( move . category === MoveCategory . PHYSICAL || move . category === MoveCategory . SPECIAL ) , 1.5 )
2024-05-02 14:01:57 -05:00
. target ( MoveTarget . ATTACKER ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . AQUA_CUTTER , Type . WATER , MoveCategory . PHYSICAL , 70 , 100 , 20 , - 1 , 0 , 9 )
2023-12-15 01:41:45 -06:00
. attr ( HighCritAttr )
2024-04-01 20:57:22 -05:00
. slicingMove ( )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLAZING_TORQUE , Type . FIRE , MoveCategory . PHYSICAL , 80 , 100 , 10 , 30 , 0 , 9 )
2024-04-01 20:57:22 -05:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . WICKED_TORQUE , Type . DARK , MoveCategory . PHYSICAL , 80 , 100 , 10 , 10 , 0 , 9 )
2024-04-01 20:57:22 -05:00
. attr ( StatusEffectAttr , StatusEffect . SLEEP )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . NOXIOUS_TORQUE , Type . POISON , MoveCategory . PHYSICAL , 100 , 100 , 10 , 30 , 0 , 9 )
2024-04-01 20:57:22 -05:00
. attr ( StatusEffectAttr , StatusEffect . POISON )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . COMBAT_TORQUE , Type . FIGHTING , MoveCategory . PHYSICAL , 100 , 100 , 10 , 30 , 0 , 9 )
2024-04-01 20:57:22 -05:00
. attr ( StatusEffectAttr , StatusEffect . PARALYSIS )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MAGICAL_TORQUE , Type . FAIRY , MoveCategory . PHYSICAL , 100 , 100 , 10 , 30 , 0 , 9 )
2024-04-01 20:57:22 -05:00
. attr ( ConfuseAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . BLOOD_MOON , Type . NORMAL , MoveCategory . SPECIAL , 140 , 100 , 5 , - 1 , 0 , 9 )
2024-04-15 03:11:22 +10:00
. condition ( ( user , target , move ) = > {
const turnMove = user . getLastXMoves ( 1 ) ;
return ! turnMove . length || turnMove [ 0 ] . move !== move . id || turnMove [ 0 ] . result !== MoveResult . SUCCESS ;
} ) , // TODO Add Instruct/Encore interaction
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MATCHA_GOTCHA , Type . GRASS , MoveCategory . SPECIAL , 80 , 90 , 15 , 20 , 0 , 9 )
2023-12-10 21:52:11 -06:00
. attr ( HitHealAttr )
2024-03-30 18:46:33 -04:00
. attr ( HealStatusEffectAttr , true , StatusEffect . FREEZE )
2024-05-30 16:04:50 -04:00
. attr ( HealStatusEffectAttr , false , StatusEffect . FREEZE )
2023-12-10 21:52:11 -06:00
. attr ( StatusEffectAttr , StatusEffect . BURN )
2024-04-08 17:10:07 +03:00
. target ( MoveTarget . ALL_NEAR_ENEMIES )
2024-04-16 20:29:32 +02:00
. triageMove ( )
. partial ( ) ,
new AttackMove ( Moves . SYRUP_BOMB , Type . GRASS , MoveCategory . SPECIAL , 60 , 85 , 10 , - 1 , 0 , 9 )
2024-02-08 16:50:17 -06:00
. attr ( StatChangeAttr , BattleStat . SPD , - 1 ) //Temporary
2024-04-16 20:29:32 +02:00
. ballBombMove ( )
. partial ( ) ,
new AttackMove ( Moves . IVY_CUDGEL , Type . GRASS , MoveCategory . PHYSICAL , 100 , 100 , 10 , - 1 , 0 , 9 )
2024-04-14 21:41:12 -05:00
. attr ( IvyCudgelTypeAttr )
2024-04-01 20:57:22 -05:00
. attr ( HighCritAttr )
. makesContact ( false ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . ELECTRO_SHOT , Type . ELECTRIC , MoveCategory . SPECIAL , 130 , 100 , 10 , 100 , 0 , 9 )
2023-12-14 03:03:00 -06:00
. attr ( ElectroShotChargeAttr )
. ignoresVirtual ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TERA_STARSTORM , Type . NORMAL , MoveCategory . SPECIAL , 120 , 100 , 5 , - 1 , 0 , 9 )
. attr ( TeraBlastCategoryAttr )
. partial ( ) ,
new AttackMove ( Moves . FICKLE_BEAM , Type . DRAGON , MoveCategory . SPECIAL , 80 , 100 , 5 , 30 , 0 , 9 )
2024-03-30 22:40:00 -05:00
. attr ( PreMoveMessageAttr , doublePowerChanceMessageFunc )
. attr ( DoublePowerChanceAttr ) ,
2024-05-08 19:39:22 +01:00
new SelfStatusMove ( Moves . BURNING_BULWARK , Type . FIRE , - 1 , 10 , 100 , 4 , 9 )
2024-03-13 16:37:36 -05:00
. attr ( ProtectAttr , BattlerTagType . BURNING_BULWARK ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . THUNDERCLAP , Type . ELECTRIC , MoveCategory . SPECIAL , 70 , 100 , 5 , - 1 , 1 , 9 )
2024-04-14 12:52:59 -05:00
. condition ( ( user , target , move ) = > user . scene . currentBattle . turnCommands [ target . getBattlerIndex ( ) ] . command === Command . FIGHT && ! target . turnData . acted && allMoves [ user . scene . currentBattle . turnCommands [ target . getBattlerIndex ( ) ] . move . move ] . category !== MoveCategory . STATUS ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . MIGHTY_CLEAVE , Type . ROCK , MoveCategory . PHYSICAL , 95 , 100 , 5 , - 1 , 0 , 9 )
2024-05-03 15:17:37 -05:00
. slicingMove ( )
2023-12-14 03:03:00 -06:00
. ignoresProtect ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . TACHYON_CUTTER , Type . STEEL , MoveCategory . SPECIAL , 50 , - 1 , 10 , - 1 , 0 , 9 )
2024-04-15 03:11:22 +10:00
. attr ( MultiHitAttr , MultiHitType . _2 )
. slicingMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . HARD_PRESS , Type . STEEL , MoveCategory . PHYSICAL , 100 , 100 , 5 , - 1 , 0 , 9 )
2023-12-14 03:03:00 -06:00
. attr ( OpponentHighHpPowerAttr ) ,
2024-04-16 20:29:32 +02:00
new StatusMove ( Moves . DRAGON_CHEER , Type . DRAGON , - 1 , 15 , 100 , 0 , 9 )
2024-01-02 21:31:59 -05:00
. attr ( AddBattlerTagAttr , BattlerTagType . CRIT_BOOST , false , true )
2024-04-16 20:29:32 +02:00
. target ( MoveTarget . NEAR_ALLY )
. partial ( ) ,
new AttackMove ( Moves . ALLURING_VOICE , Type . FAIRY , MoveCategory . SPECIAL , 80 , 100 , 10 , - 1 , 0 , 9 )
2024-05-08 19:39:22 +01:00
. soundBased ( )
2024-04-16 20:29:32 +02:00
. partial ( ) ,
new AttackMove ( Moves . TEMPER_FLARE , Type . FIRE , MoveCategory . PHYSICAL , 75 , 100 , 10 , - 1 , 0 , 9 )
2024-05-23 17:03:10 +02:00
. attr ( MovePowerMultiplierAttr , ( user , target , move ) = > user . getLastXMoves ( 2 ) [ 1 ] ? . result === MoveResult . MISS || user . getLastXMoves ( 2 ) [ 1 ] ? . result === MoveResult . FAIL ? 2 : 1 ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . SUPERCELL_SLAM , Type . ELECTRIC , MoveCategory . PHYSICAL , 100 , 95 , 15 , - 1 , 0 , 9 )
2024-04-12 18:49:48 -07:00
. attr ( MissEffectAttr , crashDamageFunc )
2024-05-07 23:28:35 -05:00
. attr ( NoEffectAttr , crashDamageFunc )
. recklessMove ( ) ,
2024-04-16 20:29:32 +02:00
new AttackMove ( Moves . PSYCHIC_NOISE , Type . PSYCHIC , MoveCategory . SPECIAL , 75 , 100 , 10 , - 1 , 0 , 9 )
. soundBased ( )
. partial ( ) ,
2024-05-19 07:04:19 -07:00
new AttackMove ( Moves . UPPER_HAND , Type . FIGHTING , MoveCategory . PHYSICAL , 65 , 100 , 15 , 100 , 3 , 9 )
. attr ( FlinchAttr )
. condition ( ( user , target , move ) = > user . scene . currentBattle . turnCommands [ target . getBattlerIndex ( ) ] . command === Command . FIGHT && ! target . turnData . acted && allMoves [ user . scene . currentBattle . turnCommands [ target . getBattlerIndex ( ) ] . move . move ] . category !== MoveCategory . STATUS && allMoves [ user . scene . currentBattle . turnCommands [ target . getBattlerIndex ( ) ] . move . move ] . priority > 0 )
//TODO: Should also apply when target move priority increased by ability ex. gale wings
2024-04-16 20:29:32 +02:00
. partial ( ) ,
new AttackMove ( Moves . MALIGNANT_CHAIN , Type . POISON , MoveCategory . SPECIAL , 100 , 100 , 5 , 50 , 0 , 9 )
2023-12-14 03:03:00 -06:00
. attr ( StatusEffectAttr , StatusEffect . TOXIC )
2023-04-27 14:30:03 -04:00
) ;
2024-05-24 01:45:04 +02:00
}