2023-04-18 09:30:47 -07:00
import { CommonAnim , CommonBattleAnim } from "./battle-anims" ;
import { CommonAnimPhase , DamagePhase , MessagePhase , MovePhase , PokemonHealPhase } from "./battle-phases" ;
2023-04-14 22:32:16 -07:00
import { getPokemonMessage } from "./messages" ;
import Pokemon from "./pokemon" ;
import { Stat } from "./pokemon-stat" ;
import * as Utils from "./utils" ;
2023-04-13 09:16:36 -07:00
export enum BattleTagType {
NONE ,
2023-04-15 14:40:18 -07:00
FLINCHED ,
2023-04-14 22:32:16 -07:00
CONFUSED ,
2023-04-18 09:30:47 -07:00
SEEDED ,
2023-04-16 15:40:32 -07:00
NIGHTMARE ,
2023-04-14 22:32:16 -07:00
FRENZY ,
2023-04-18 09:30:47 -07:00
PROTECTED ,
2023-04-13 09:16:36 -07:00
FLYING ,
2023-04-15 21:29:55 -07:00
UNDERGROUND ,
2023-04-16 15:40:32 -07:00
BYPASS_SLEEP ,
2023-04-15 21:29:55 -07:00
IGNORE_FLYING
2023-04-13 09:16:36 -07:00
}
export enum BattleTagLapseType {
FAINT ,
MOVE ,
2023-04-16 15:40:32 -07:00
AFTER_MOVE ,
2023-04-14 22:32:16 -07:00
MOVE_EFFECT ,
TURN_END ,
CUSTOM
2023-04-13 09:16:36 -07:00
}
export class BattleTag {
public tagType : BattleTagType ;
public lapseType : BattleTagLapseType ;
public turnCount : integer ;
constructor ( tagType : BattleTagType , lapseType : BattleTagLapseType , turnCount : integer ) {
this . tagType = tagType ;
this . lapseType = lapseType ;
this . turnCount = turnCount ;
}
2023-04-14 22:32:16 -07:00
onAdd ( pokemon : Pokemon ) : void { }
onRemove ( pokemon : Pokemon ) : void { }
onOverlap ( pokemon : Pokemon ) : void { }
2023-04-16 15:40:32 -07:00
lapse ( pokemon : Pokemon , lapseType : BattleTagLapseType ) : boolean {
2023-04-15 14:40:18 -07:00
return -- this . turnCount > 0 ;
}
}
export class FlinchedTag extends BattleTag {
constructor ( ) {
2023-04-18 09:30:47 -07:00
super ( BattleTagType . FLINCHED , BattleTagLapseType . MOVE , 0 ) ;
2023-04-15 14:40:18 -07:00
}
2023-04-16 15:40:32 -07:00
lapse ( pokemon : Pokemon , lapseType : BattleTagLapseType ) : boolean {
super . lapse ( pokemon , lapseType ) ;
2023-04-15 14:40:18 -07:00
( pokemon . scene . getCurrentPhase ( ) as MovePhase ) . cancel ( ) ;
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' flinched!' ) ) ) ;
return true ;
2023-04-14 22:32:16 -07:00
}
}
export class PseudoStatusTag extends BattleTag {
2023-04-16 15:40:32 -07:00
constructor ( tagType : BattleTagType , lapseType : BattleTagLapseType , turnCount : integer ) {
super ( tagType , lapseType , turnCount ) ;
2023-04-14 22:32:16 -07:00
}
}
export class ConfusedTag extends PseudoStatusTag {
2023-04-16 15:40:32 -07:00
constructor ( turnCount : integer ) {
super ( BattleTagType . CONFUSED , BattleTagLapseType . MOVE , turnCount ) ;
2023-04-14 22:32:16 -07:00
}
onAdd ( pokemon : Pokemon ) : void {
super . onAdd ( pokemon ) ;
pokemon . scene . unshiftPhase ( new CommonAnimPhase ( pokemon . scene , pokemon . isPlayer ( ) , CommonAnim . CONFUSION ) ) ;
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' became\nconfused!' ) ) ) ;
}
onRemove ( pokemon : Pokemon ) : void {
super . onRemove ( pokemon ) ;
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' snapped\nout of confusion!' ) ) ) ;
}
onOverlap ( pokemon : Pokemon ) : void {
super . onOverlap ( pokemon ) ;
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' is\nalready confused!' ) ) ) ;
}
2023-04-16 15:40:32 -07:00
lapse ( pokemon : Pokemon , lapseType : BattleTagLapseType ) : boolean {
const ret = super . lapse ( pokemon , lapseType ) ;
2023-04-14 22:32:16 -07:00
if ( ret ) {
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' is\nconfused!' ) ) ) ;
pokemon . scene . unshiftPhase ( new CommonAnimPhase ( pokemon . scene , pokemon . isPlayer ( ) , CommonAnim . CONFUSION ) ) ;
if ( Utils . randInt ( 2 ) ) {
const atk = pokemon . getBattleStat ( Stat . ATK ) ;
const def = pokemon . getBattleStat ( Stat . DEF ) ;
const damage = Math . ceil ( ( ( ( ( 2 * pokemon . level / 5 + 2 ) * 40 * atk / def ) / 50 ) + 2 ) * ( ( Utils . randInt ( 15 ) + 85 ) / 100 ) ) ;
pokemon . hp = Math . max ( pokemon . hp - damage , 0 ) ;
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , 'It hurt itself in its\nconfusion!' ) ) ;
2023-04-16 15:40:32 -07:00
pokemon . scene . unshiftPhase ( new DamagePhase ( pokemon . scene , pokemon . isPlayer ( ) ) ) ;
2023-04-14 22:32:16 -07:00
( pokemon . scene . getCurrentPhase ( ) as MovePhase ) . cancel ( ) ;
}
2023-04-13 09:16:36 -07:00
}
2023-04-14 22:32:16 -07:00
return ret ;
}
}
2023-04-18 09:30:47 -07:00
export class SeedTag extends PseudoStatusTag {
constructor ( ) {
super ( BattleTagType . SEEDED , BattleTagLapseType . AFTER_MOVE , 1 ) ;
}
onAdd ( pokemon : Pokemon ) : void {
super . onAdd ( pokemon ) ;
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' was seeded!' ) ) ) ;
}
lapse ( pokemon : Pokemon , lapseType : BattleTagLapseType ) : boolean {
console . trace ( lapseType ) ;
const ret = lapseType !== BattleTagLapseType . CUSTOM || super . lapse ( pokemon , lapseType ) ;
if ( ret ) {
pokemon . scene . unshiftPhase ( new CommonAnimPhase ( pokemon . scene , ! pokemon . isPlayer ( ) , CommonAnim . LEECH_SEED ) ) ;
const damage = Math . max ( Math . floor ( pokemon . getMaxHp ( ) / 8 ) , 1 ) ;
pokemon . hp = Math . max ( pokemon . hp - damage , 0 ) ;
pokemon . scene . unshiftPhase ( new DamagePhase ( pokemon . scene , pokemon . isPlayer ( ) ) ) ;
pokemon . scene . unshiftPhase ( new PokemonHealPhase ( pokemon . scene , ! pokemon . isPlayer ( ) , damage , getPokemonMessage ( pokemon , '\'s health is\nsapped by LEECH SEED!' ) , false , true ) ) ;
}
return ret ;
}
}
2023-04-16 15:40:32 -07:00
export class NightmareTag extends PseudoStatusTag {
constructor ( ) {
super ( BattleTagType . NIGHTMARE , BattleTagLapseType . AFTER_MOVE , 1 ) ;
}
onAdd ( pokemon : Pokemon ) : void {
super . onAdd ( pokemon ) ;
2023-04-18 09:30:47 -07:00
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' began\nhaving a NIGHTMARE!' ) ) ) ;
2023-04-16 15:40:32 -07:00
}
onOverlap ( pokemon : Pokemon ) : void {
super . onOverlap ( pokemon ) ;
2023-04-18 09:30:47 -07:00
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' is\nalready locked in a NIGHTMARE!' ) ) ) ;
2023-04-16 15:40:32 -07:00
}
lapse ( pokemon : Pokemon , lapseType : BattleTagLapseType ) : boolean {
const ret = lapseType !== BattleTagLapseType . CUSTOM || super . lapse ( pokemon , lapseType ) ;
if ( ret ) {
2023-04-18 09:30:47 -07:00
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , ' is locked\nin a NIGHTMARE!' ) ) ) ;
2023-04-16 15:40:32 -07:00
pokemon . scene . unshiftPhase ( new CommonAnimPhase ( pokemon . scene , pokemon . isPlayer ( ) , CommonAnim . CURSE ) ) ; // TODO: Update animation type
const damage = Math . ceil ( pokemon . getMaxHp ( ) / 4 ) ;
pokemon . hp = Math . max ( pokemon . hp - damage , 0 ) ;
pokemon . scene . unshiftPhase ( new DamagePhase ( pokemon . scene , pokemon . isPlayer ( ) ) ) ;
}
return ret ;
}
}
2023-04-18 09:30:47 -07:00
export class ProtectedTag extends BattleTag {
constructor ( ) {
super ( BattleTagType . PROTECTED , BattleTagLapseType . CUSTOM , 0 ) ;
}
onAdd ( pokemon : Pokemon ) : void {
super . onAdd ( pokemon ) ;
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , '\nprotected itself!' ) ) ) ;
}
lapse ( pokemon : Pokemon , lapseType : BattleTagLapseType ) : boolean {
console . log ( pokemon , BattleTagLapseType [ lapseType ] ) ;
if ( lapseType === BattleTagLapseType . CUSTOM ) {
new CommonBattleAnim ( CommonAnim . PROTECT , pokemon ) . play ( pokemon . scene ) ;
pokemon . scene . unshiftPhase ( new MessagePhase ( pokemon . scene , getPokemonMessage ( pokemon , '\nprotected itself!' ) ) ) ;
return true ;
}
return super . lapse ( pokemon , lapseType ) ;
}
}
2023-04-14 22:32:16 -07:00
export class HideSpriteTag extends BattleTag {
constructor ( tagType : BattleTagType , turnCount : integer ) {
super ( tagType , BattleTagLapseType . MOVE_EFFECT , turnCount ) ;
}
onAdd ( pokemon : Pokemon ) : void {
super . onAdd ( pokemon ) ;
pokemon . setVisible ( false ) ;
}
onRemove ( pokemon : Pokemon ) : void {
// Wait 2 frames before setting visible for battle animations that don't immediately show the sprite invisible
pokemon . scene . tweens . addCounter ( {
duration : 2 ,
useFrames : true ,
onComplete : ( ) = > pokemon . setVisible ( true )
} ) ;
}
}
2023-04-13 09:16:36 -07:00
2023-04-14 22:32:16 -07:00
export function getBattleTag ( tagType : BattleTagType , turnCount : integer ) : BattleTag {
switch ( tagType ) {
2023-04-15 14:40:18 -07:00
case BattleTagType . FLINCHED :
return new FlinchedTag ( ) ;
2023-04-14 22:32:16 -07:00
case BattleTagType . CONFUSED :
2023-04-16 15:40:32 -07:00
return new ConfusedTag ( turnCount ) ;
2023-04-18 09:30:47 -07:00
case BattleTagType . SEEDED :
return new SeedTag ( ) ;
2023-04-16 15:40:32 -07:00
case BattleTagType . NIGHTMARE :
return new NightmareTag ( ) ;
2023-04-18 09:30:47 -07:00
case BattleTagType . PROTECTED :
return new ProtectedTag ( ) ;
2023-04-14 22:32:16 -07:00
case BattleTagType . FLYING :
case BattleTagType . UNDERGROUND :
return new HideSpriteTag ( tagType , turnCount ) ;
2023-04-16 15:40:32 -07:00
case BattleTagType . BYPASS_SLEEP :
return new BattleTag ( BattleTagType . BYPASS_SLEEP , BattleTagLapseType . TURN_END , turnCount ) ;
2023-04-15 21:29:55 -07:00
case BattleTagType . IGNORE_FLYING :
return new BattleTag ( tagType , BattleTagLapseType . TURN_END , turnCount ) ;
2023-04-14 22:32:16 -07:00
default :
return new BattleTag ( tagType , BattleTagLapseType . CUSTOM , turnCount ) ;
2023-04-13 09:16:36 -07:00
}
}