2024-02-22 04:57:49 +00:00
import { CommandPhase } from "../phases" ;
2024-05-05 15:30:00 +01:00
import BattleScene from "../battle-scene" ;
2024-03-01 01:08:50 +00:00
import { PlayerPokemon , PokemonMove } from "../field/pokemon" ;
2023-04-20 20:46:05 +01:00
import { addTextObject , TextStyle } from "./text" ;
2023-03-28 19:54:52 +01:00
import { Command } from "./command-ui-handler" ;
import MessageUiHandler from "./message-ui-handler" ;
2023-04-06 03:22:03 +01:00
import { Mode } from "./ui" ;
2023-04-11 06:31:18 +01:00
import * as Utils from "../utils" ;
2024-01-10 04:34:43 +00:00
import { PokemonFormChangeItemModifier , PokemonHeldItemModifier , SwitchEffectTransferModifier } from "../modifier/modifier" ;
2024-01-13 17:24:24 +00:00
import { allMoves } from "../data/move" ;
import { Moves } from "../data/enums/moves" ;
2023-07-05 05:29:22 +01:00
import { getGenderColor , getGenderSymbol } from "../data/gender" ;
import { StatusEffect } from "../data/status-effect" ;
2024-03-01 01:08:50 +00:00
import PokemonIconAnimHandler , { PokemonIconAnimMode } from "./pokemon-icon-anim-handler" ;
2023-12-14 17:55:11 +00:00
import { pokemonEvolutions } from "../data/pokemon-evolutions" ;
2024-04-01 02:14:35 +01:00
import { addWindow } from "./ui-theme" ;
2024-01-10 04:34:43 +00:00
import { SpeciesFormChangeItemTrigger } from "../data/pokemon-forms" ;
2024-04-19 03:52:26 +01:00
import { getVariantTint } from "#app/data/variant" ;
2024-05-05 15:30:00 +01:00
import { Button } from "../enums/buttons" ;
2023-03-28 19:54:52 +01:00
const defaultMessage = 'Choose a Pokémon.' ;
2023-04-06 03:22:03 +01:00
export enum PartyUiMode {
SWITCH ,
2023-04-06 05:15:33 +01:00
FAINT_SWITCH ,
POST_BATTLE_SWITCH ,
2023-04-11 06:31:18 +01:00
MODIFIER ,
2023-04-11 16:04:39 +01:00
MOVE_MODIFIER ,
2023-07-05 04:11:31 +01:00
TM_MODIFIER ,
2023-11-08 22:30:07 +00:00
REMEMBER_MOVE_MODIFIER ,
2023-04-21 19:05:16 +01:00
MODIFIER_TRANSFER ,
2023-11-04 04:32:12 +00:00
SPLICE ,
2023-04-11 06:31:18 +01:00
RELEASE
2023-04-06 03:22:03 +01:00
}
export enum PartyOption {
2023-04-21 19:05:16 +01:00
CANCEL = - 1 ,
2023-04-06 03:22:03 +01:00
SEND_OUT ,
2023-04-29 00:26:41 +01:00
PASS_BATON ,
2023-04-06 03:22:03 +01:00
APPLY ,
2023-07-05 04:11:31 +01:00
TEACH ,
2023-04-21 19:05:16 +01:00
TRANSFER ,
2023-04-06 03:22:03 +01:00
SUMMARY ,
2024-01-10 04:34:43 +00:00
UNPAUSE_EVOLUTION ,
2024-04-03 01:51:43 +01:00
SPLICE ,
UNSPLICE ,
2023-04-11 06:31:18 +01:00
RELEASE ,
2023-11-07 23:43:48 +00:00
SCROLL_UP = 1000 ,
SCROLL_DOWN = 1001 ,
2024-01-10 04:34:43 +00:00
FORM_CHANGE_ITEM = 2000 ,
MOVE_1 = 3000 ,
2023-04-11 16:04:39 +01:00
MOVE_2 ,
MOVE_3 ,
2023-04-21 19:05:16 +01:00
MOVE_4
2023-04-06 03:22:03 +01:00
}
2023-04-11 16:04:39 +01:00
export type PartySelectCallback = ( cursor : integer , option : PartyOption ) = > void ;
2023-04-21 19:05:16 +01:00
export type PartyModifierTransferSelectCallback = ( fromCursor : integer , index : integer , toCursor? : integer ) = > void ;
2023-11-04 04:32:12 +00:00
export type PartyModifierSpliceSelectCallback = ( fromCursor : integer , toCursor? : integer ) = > void ;
2023-04-11 16:04:39 +01:00
export type PokemonSelectFilter = ( pokemon : PlayerPokemon ) = > string ;
2023-04-21 19:05:16 +01:00
export type PokemonModifierTransferSelectFilter = ( pokemon : PlayerPokemon , modifier : PokemonHeldItemModifier ) = > string ;
2023-04-11 16:04:39 +01:00
export type PokemonMoveSelectFilter = ( pokemonMove : PokemonMove ) = > string ;
2023-03-28 19:54:52 +01:00
export default class PartyUiHandler extends MessageUiHandler {
2023-04-06 03:22:03 +01:00
private partyUiMode : PartyUiMode ;
2023-05-18 16:11:06 +01:00
private fieldIndex : integer ;
2023-04-06 03:22:03 +01:00
2023-05-18 16:11:06 +01:00
private partyBg : Phaser.GameObjects.Image ;
2023-03-28 19:54:52 +01:00
private partyContainer : Phaser.GameObjects.Container ;
private partySlotsContainer : Phaser.GameObjects.Container ;
private partySlots : PartySlot [ ] ;
private partyCancelButton : PartyCancelButton ;
2023-12-21 03:22:15 +00:00
private partyMessageBox : Phaser.GameObjects.NineSlice ;
2023-03-28 19:54:52 +01:00
2023-04-05 13:35:15 +01:00
private optionsMode : boolean ;
2023-11-07 23:43:48 +00:00
private optionsScroll : boolean ;
private optionsCursor : integer = 0 ;
private optionsScrollCursor : integer = 0 ;
private optionsScrollTotal : integer = 0 ;
2023-04-05 13:35:15 +01:00
private optionsContainer : Phaser.GameObjects.Container ;
2024-01-10 04:34:43 +00:00
private optionsBg : Phaser.GameObjects.NineSlice ;
2023-04-05 13:35:15 +01:00
private optionsCursorObj : Phaser.GameObjects.Image ;
2023-04-06 03:22:03 +01:00
private options : integer [ ] ;
2023-04-21 19:05:16 +01:00
private transferMode : boolean ;
private transferOptionCursor : integer ;
private transferCursor : integer ;
2023-04-05 13:35:15 +01:00
2023-03-28 19:54:52 +01:00
private lastCursor : integer = 0 ;
2023-04-21 19:05:16 +01:00
private selectCallback : PartySelectCallback | PartyModifierTransferSelectCallback ;
private selectFilter : PokemonSelectFilter | PokemonModifierTransferSelectFilter ;
2023-04-11 16:04:39 +01:00
private moveSelectFilter : PokemonMoveSelectFilter ;
2023-07-05 04:11:31 +01:00
private tmMoveId : Moves ;
2024-05-01 15:16:58 +01:00
private showMovePp : boolean ;
2023-03-28 19:54:52 +01:00
2023-12-07 05:52:20 +00:00
private iconAnimHandler : PokemonIconAnimHandler ;
2023-03-28 19:54:52 +01:00
private static FilterAll = ( _pokemon : PlayerPokemon ) = > null ;
public static FilterNonFainted = ( pokemon : PlayerPokemon ) = > {
2023-05-18 16:11:06 +01:00
if ( pokemon . isFainted ( ) )
2023-03-28 19:54:52 +01:00
return ` ${ pokemon . name } has no energy \ nleft to battle! ` ;
return null ;
} ;
2023-04-11 16:04:39 +01:00
private static FilterAllMoves = ( _pokemonMove : PokemonMove ) = > null ;
2023-04-21 19:05:16 +01:00
public static FilterItemMaxStacks = ( pokemon : PlayerPokemon , modifier : PokemonHeldItemModifier ) = > {
2024-02-17 05:40:03 +00:00
const matchingModifier = pokemon . scene . findModifier ( m = > m instanceof PokemonHeldItemModifier && m . pokemonId === pokemon . id && m . matchType ( modifier ) ) as PokemonHeldItemModifier ;
2023-12-09 05:33:29 +00:00
if ( matchingModifier && matchingModifier . stackCount === matchingModifier . getMaxStackCount ( pokemon . scene ) )
2023-04-21 19:05:16 +01:00
return ` ${ pokemon . name } has too many \ nof this item! ` ;
return null ;
} ;
2023-03-28 19:54:52 +01:00
public static NoEffectMessage = 'It won\'t have any effect.' ;
constructor ( scene : BattleScene ) {
super ( scene , Mode . PARTY ) ;
}
setup() {
const ui = this . getUi ( ) ;
const partyContainer = this . scene . add . container ( 0 , 0 ) ;
partyContainer . setVisible ( false ) ;
ui . add ( partyContainer ) ;
this . partyContainer = partyContainer ;
2023-05-18 16:11:06 +01:00
this . partyBg = this . scene . add . image ( 0 , 0 , 'party_bg' ) ;
partyContainer . add ( this . partyBg ) ;
2023-03-28 19:54:52 +01:00
2023-05-18 16:11:06 +01:00
this . partyBg . setOrigin ( 0 , 1 ) ;
2023-03-28 19:54:52 +01:00
const partySlotsContainer = this . scene . add . container ( 0 , 0 ) ;
partyContainer . add ( partySlotsContainer ) ;
this . partySlotsContainer = partySlotsContainer ;
const partyMessageBoxContainer = this . scene . add . container ( 0 , - 32 ) ;
partyContainer . add ( partyMessageBoxContainer ) ;
2023-12-21 03:22:15 +00:00
const partyMessageBox = addWindow ( this . scene , 1 , 31 , 262 , 30 ) ;
2023-03-28 19:54:52 +01:00
partyMessageBox . setOrigin ( 0 , 1 ) ;
partyMessageBoxContainer . add ( partyMessageBox ) ;
this . partyMessageBox = partyMessageBox ;
const partyMessageText = addTextObject ( this . scene , 8 , 10 , defaultMessage , TextStyle . WINDOW , { maxLines : 2 } ) ;
partyMessageText . setOrigin ( 0 , 0 ) ;
partyMessageBoxContainer . add ( partyMessageText ) ;
this . message = partyMessageText ;
const partyCancelButton = new PartyCancelButton ( this . scene , 291 , - 16 ) ;
partyContainer . add ( partyCancelButton ) ;
this . partyCancelButton = partyCancelButton ;
2023-04-05 13:35:15 +01:00
this . optionsContainer = this . scene . add . container ( ( this . scene . game . canvas . width / 6 ) - 1 , - 1 ) ;
partyContainer . add ( this . optionsContainer ) ;
2023-12-07 05:52:20 +00:00
this . iconAnimHandler = new PokemonIconAnimHandler ( ) ;
this . iconAnimHandler . setup ( this . scene ) ;
2023-04-06 03:22:03 +01:00
this . options = [ ] ;
2023-03-28 19:54:52 +01:00
this . partySlots = [ ] ;
}
2023-12-30 23:41:25 +00:00
show ( args : any [ ] ) : boolean {
2023-04-06 15:05:12 +01:00
if ( ! args . length || this . active )
2023-12-30 23:41:25 +00:00
return false ;
2023-04-06 03:22:03 +01:00
2023-03-28 19:54:52 +01:00
super . show ( args ) ;
2023-04-06 03:22:03 +01:00
this . partyUiMode = args [ 0 ] as PartyUiMode ;
2023-05-18 16:11:06 +01:00
this . fieldIndex = args . length > 1 ? args [ 1 ] as integer : - 1 ;
2023-10-25 14:12:39 +01:00
this . selectCallback = args . length > 2 && args [ 2 ] instanceof Function ? args [ 2 ] : undefined ;
2023-05-18 16:11:06 +01:00
this . selectFilter = args . length > 3 && args [ 3 ] instanceof Function
? args [ 3 ] as PokemonSelectFilter
2023-03-28 19:54:52 +01:00
: PartyUiHandler . FilterAll ;
2023-05-18 16:11:06 +01:00
this . moveSelectFilter = args . length > 4 && args [ 4 ] instanceof Function
? args [ 4 ] as PokemonMoveSelectFilter
2023-04-11 16:04:39 +01:00
: PartyUiHandler . FilterAllMoves ;
2023-07-05 04:11:31 +01:00
this . tmMoveId = args . length > 5 && args [ 5 ] ? args [ 5 ] : Moves . NONE ;
2024-05-01 15:16:58 +01:00
this . showMovePp = args . length > 6 && args [ 6 ] ;
2023-07-05 04:11:31 +01:00
this . partyContainer . setVisible ( true ) ;
this . partyBg . setTexture ( ` party_bg ${ this . scene . currentBattle . double ? '_double' : '' } ` ) ;
this . populatePartySlots ( ) ;
this . setCursor ( this . cursor < 6 ? this . cursor : 0 ) ;
2023-12-30 23:41:25 +00:00
return true ;
2023-03-28 19:54:52 +01:00
}
2023-11-12 05:31:40 +00:00
processInput ( button : Button ) : boolean {
2023-03-28 19:54:52 +01:00
const ui = this . getUi ( ) ;
if ( this . pendingPrompt )
2023-11-12 05:31:40 +00:00
return false ;
2023-03-28 19:54:52 +01:00
if ( this . awaitingActionInput ) {
2023-11-12 05:31:40 +00:00
if ( ( button === Button . ACTION || button === Button . CANCEL ) && this . onActionInput ) {
ui . playSelect ( ) ;
const originalOnActionInput = this . onActionInput ;
this . onActionInput = null ;
originalOnActionInput ( ) ;
this . awaitingActionInput = false ;
return true ;
2023-03-28 19:54:52 +01:00
}
2023-11-12 05:31:40 +00:00
return false ;
2023-03-28 19:54:52 +01:00
}
2023-04-05 13:35:15 +01:00
let success = false ;
if ( this . optionsMode ) {
2023-04-11 05:24:55 +01:00
if ( button === Button . ACTION ) {
2023-04-06 03:22:03 +01:00
const option = this . options [ this . optionsCursor ] ;
2023-04-11 06:31:18 +01:00
const pokemon = this . scene . getParty ( ) [ this . cursor ] ;
2023-04-21 19:05:16 +01:00
if ( this . partyUiMode === PartyUiMode . MODIFIER_TRANSFER && ! this . transferMode && option !== PartyOption . CANCEL ) {
this . startTransfer ( ) ;
this . clearOptions ( ) ;
ui . playSelect ( ) ;
2023-11-12 05:31:40 +00:00
return true ;
2023-11-08 22:30:07 +00:00
} else if ( this . partyUiMode === PartyUiMode . REMEMBER_MOVE_MODIFIER && option !== PartyOption . CANCEL ) {
let filterResult = ( this . selectFilter as PokemonSelectFilter ) ( pokemon ) ;
if ( filterResult === null ) {
this . selectCallback ( this . cursor , option ) ;
this . clearOptions ( ) ;
} else {
this . clearOptions ( ) ;
this . showText ( filterResult as string , null , ( ) = > this . showText ( null , 0 ) , null , true ) ;
}
ui . playSelect ( ) ;
2023-11-12 05:31:40 +00:00
return true ;
2024-04-03 01:51:43 +01:00
} else if ( ( option !== PartyOption . SUMMARY && option !== PartyOption . UNPAUSE_EVOLUTION && option !== PartyOption . UNSPLICE && option !== PartyOption . RELEASE && option !== PartyOption . CANCEL )
2023-04-11 16:04:39 +01:00
|| ( option === PartyOption . RELEASE && this . partyUiMode === PartyUiMode . RELEASE ) ) {
2023-04-21 19:05:16 +01:00
let filterResult : string ;
2023-11-04 04:32:12 +00:00
if ( option !== PartyOption . TRANSFER && option !== PartyOption . SPLICE ) {
2023-04-21 19:05:16 +01:00
filterResult = ( this . selectFilter as PokemonSelectFilter ) ( pokemon ) ;
2023-11-10 21:41:02 +00:00
if ( filterResult === null && this . partyUiMode === PartyUiMode . MOVE_MODIFIER )
2023-04-21 19:05:16 +01:00
filterResult = this . moveSelectFilter ( pokemon . moveset [ this . optionsCursor ] ) ;
} else {
2023-11-07 23:43:48 +00:00
const transferPokemon = this . scene . getParty ( ) [ this . transferCursor ] ;
2023-04-21 19:05:16 +01:00
const itemModifiers = this . scene . findModifiers ( m = > m instanceof PokemonHeldItemModifier
2023-11-07 23:43:48 +00:00
&& ( m as PokemonHeldItemModifier ) . getTransferrable ( true ) && ( m as PokemonHeldItemModifier ) . pokemonId === transferPokemon . id ) as PokemonHeldItemModifier [ ] ;
2023-04-21 19:05:16 +01:00
filterResult = ( this . selectFilter as PokemonModifierTransferSelectFilter ) ( pokemon , itemModifiers [ this . transferOptionCursor ] ) ;
}
2023-04-05 13:35:15 +01:00
if ( filterResult === null ) {
2023-11-04 04:32:12 +00:00
if ( this . partyUiMode !== PartyUiMode . SPLICE )
this . clearOptions ( ) ;
2023-04-05 13:35:15 +01:00
if ( this . selectCallback ) {
2023-04-21 19:05:16 +01:00
if ( option === PartyOption . TRANSFER ) {
( this . selectCallback as PartyModifierTransferSelectCallback ) ( this . transferCursor , this . transferOptionCursor , this . cursor ) ;
this . clearTransfer ( ) ;
2023-11-04 04:32:12 +00:00
} else if ( this . partyUiMode === PartyUiMode . SPLICE ) {
if ( option === PartyOption . SPLICE ) {
( this . selectCallback as PartyModifierSpliceSelectCallback ) ( this . transferCursor , this . cursor ) ;
this . clearTransfer ( ) ;
} else
this . startTransfer ( ) ;
this . clearOptions ( ) ;
2023-04-21 19:05:16 +01:00
} else if ( option === PartyOption . RELEASE )
2023-04-11 14:41:11 +01:00
this . doRelease ( this . cursor ) ;
else {
const selectCallback = this . selectCallback ;
2023-04-11 06:31:18 +01:00
this . selectCallback = null ;
2023-04-11 16:04:39 +01:00
selectCallback ( this . cursor , option ) ;
2023-04-11 06:31:18 +01:00
}
2024-01-10 04:34:43 +00:00
} else {
if ( option >= PartyOption . FORM_CHANGE_ITEM && this . scene . getCurrentPhase ( ) instanceof CommandPhase ) {
switch ( this . partyUiMode ) {
case PartyUiMode . SWITCH :
case PartyUiMode . FAINT_SWITCH :
case PartyUiMode . POST_BATTLE_SWITCH :
let formChangeItemModifiers = this . scene . findModifiers ( m = > m instanceof PokemonFormChangeItemModifier && m . pokemonId === pokemon . id ) as PokemonFormChangeItemModifier [ ] ;
if ( formChangeItemModifiers . find ( m = > m . active ) )
formChangeItemModifiers = formChangeItemModifiers . filter ( m = > m . active ) ;
const modifier = formChangeItemModifiers [ option - PartyOption . FORM_CHANGE_ITEM ] ;
modifier . active = ! modifier . active ;
this . scene . triggerPokemonFormChange ( pokemon , SpeciesFormChangeItemTrigger , false , true ) ;
break ;
}
} else if ( this . cursor )
( this . scene . getCurrentPhase ( ) as CommandPhase ) . handleCommand ( Command . POKEMON , this . cursor , option === PartyOption . PASS_BATON ) ;
}
2023-07-05 04:11:31 +01:00
if ( this . partyUiMode !== PartyUiMode . MODIFIER && this . partyUiMode !== PartyUiMode . TM_MODIFIER && this . partyUiMode !== PartyUiMode . MOVE_MODIFIER )
2023-04-10 00:15:21 +01:00
ui . playSelect ( ) ;
2023-11-12 05:31:40 +00:00
return true ;
2023-04-05 13:35:15 +01:00
} else {
this . clearOptions ( ) ;
2023-04-23 03:14:53 +01:00
this . showText ( filterResult as string , null , ( ) = > this . showText ( null , 0 ) , null , true ) ;
2023-04-05 13:35:15 +01:00
}
2023-04-06 03:22:03 +01:00
} else if ( option === PartyOption . SUMMARY ) {
2023-03-28 19:54:52 +01:00
ui . playSelect ( ) ;
2023-04-11 06:31:18 +01:00
ui . setModeWithoutClear ( Mode . SUMMARY , pokemon ) . then ( ( ) = > this . clearOptions ( ) ) ;
2023-11-12 05:31:40 +00:00
return true ;
2024-01-10 04:34:43 +00:00
} else if ( option === PartyOption . UNPAUSE_EVOLUTION ) {
2023-12-14 17:55:11 +00:00
this . clearOptions ( ) ;
ui . playSelect ( ) ;
pokemon . pauseEvolutions = false ;
this . showText ( ` Evolutions have been unpaused for ${ pokemon . name } . ` , null , ( ) = > this . showText ( null , 0 ) , null , true ) ;
2024-04-03 01:51:43 +01:00
} else if ( option === PartyOption . UNSPLICE ) {
this . clearOptions ( ) ;
ui . playSelect ( ) ;
this . showText ( ` Do you really want to unsplice ${ pokemon . fusionSpecies . name } \ nfrom ${ pokemon . name } ? ${ pokemon . fusionSpecies . name } will be lost. ` , null , ( ) = > {
ui . setModeWithoutClear ( Mode . CONFIRM , ( ) = > {
const fusionName = pokemon . name ;
pokemon . unfuse ( ) . then ( ( ) = > {
this . clearPartySlots ( ) ;
this . populatePartySlots ( ) ;
ui . setMode ( Mode . PARTY ) ;
this . showText ( ` ${ fusionName } was reverted to ${ pokemon . name } . ` , null , ( ) = > {
ui . setMode ( Mode . PARTY ) ;
this . showText ( null , 0 ) ;
} , null , true ) ;
} ) ;
} , ( ) = > {
ui . setMode ( Mode . PARTY ) ;
this . showText ( null , 0 ) ;
} ) ;
} ) ;
2023-04-11 14:41:11 +01:00
} else if ( option === PartyOption . RELEASE ) {
this . clearOptions ( ) ;
ui . playSelect ( ) ;
2023-05-18 16:11:06 +01:00
if ( this . cursor >= this . scene . currentBattle . getBattlerCount ( ) ) {
2023-04-11 14:41:11 +01:00
this . showText ( ` Do you really want to release ${ pokemon . name } ? ` , null , ( ) = > {
ui . setModeWithoutClear ( Mode . CONFIRM , ( ) = > {
ui . setMode ( Mode . PARTY ) ;
this . doRelease ( this . cursor ) ;
} , ( ) = > {
ui . setMode ( Mode . PARTY ) ;
2023-04-23 03:14:53 +01:00
this . showText ( null , 0 ) ;
2023-04-11 14:41:11 +01:00
} ) ;
} ) ;
} else
2023-10-18 23:01:15 +01:00
this . showText ( 'You can\'t release a Pokémon that\'s in battle!' , null , ( ) = > this . showText ( null , 0 ) , null , true ) ;
2023-11-12 05:31:40 +00:00
return true ;
2023-04-06 03:22:03 +01:00
} else if ( option === PartyOption . CANCEL )
2023-11-12 05:31:40 +00:00
return this . processInput ( Button . CANCEL ) ;
2023-04-11 05:24:55 +01:00
} else if ( button === Button . CANCEL ) {
2023-04-05 13:35:15 +01:00
this . clearOptions ( ) ;
ui . playSelect ( ) ;
2023-11-12 05:31:40 +00:00
return true ;
2023-11-08 22:30:07 +00:00
} else {
2023-04-11 05:24:55 +01:00
switch ( button ) {
case Button . UP :
2023-04-06 03:22:03 +01:00
success = this . setCursor ( this . optionsCursor ? this . optionsCursor - 1 : this.options.length - 1 ) ;
2023-04-05 13:35:15 +01:00
break ;
2023-04-11 05:24:55 +01:00
case Button . DOWN :
2023-04-06 03:22:03 +01:00
success = this . setCursor ( this . optionsCursor < this . options . length - 1 ? this . optionsCursor + 1 : 0 ) ;
2023-04-05 13:35:15 +01:00
break ;
}
}
} else {
2023-04-11 05:24:55 +01:00
if ( button === Button . ACTION ) {
2023-04-05 13:35:15 +01:00
if ( this . cursor < 6 ) {
this . showOptions ( ) ;
2023-03-28 19:54:52 +01:00
ui . playSelect ( ) ;
2023-04-06 05:15:33 +01:00
} else if ( this . partyUiMode === PartyUiMode . FAINT_SWITCH )
2023-04-05 13:35:15 +01:00
ui . playError ( ) ;
else
2023-11-12 05:31:40 +00:00
return this . processInput ( Button . CANCEL ) ;
return true ;
2023-04-11 05:24:55 +01:00
} else if ( button === Button . CANCEL ) {
2023-11-04 04:32:12 +00:00
if ( ( this . partyUiMode === PartyUiMode . MODIFIER_TRANSFER || this . partyUiMode === PartyUiMode . SPLICE ) && this . transferMode ) {
2023-04-21 19:05:16 +01:00
this . clearTransfer ( ) ;
ui . playSelect ( ) ;
} else if ( this . partyUiMode !== PartyUiMode . FAINT_SWITCH ) {
2023-04-05 13:35:15 +01:00
if ( this . selectCallback ) {
const selectCallback = this . selectCallback ;
this . selectCallback = null ;
2023-04-11 16:04:39 +01:00
selectCallback ( 6 , PartyOption . CANCEL ) ;
2023-04-05 13:35:15 +01:00
ui . playSelect ( ) ;
} else {
2023-10-20 16:38:41 +01:00
ui . setMode ( Mode . COMMAND , this . fieldIndex ) ;
2023-04-05 13:35:15 +01:00
ui . playSelect ( ) ;
}
2023-03-28 19:54:52 +01:00
}
2023-11-12 05:31:40 +00:00
return true ;
2023-03-28 19:54:52 +01:00
}
2023-04-05 13:35:15 +01:00
const slotCount = this . partySlots . length ;
2024-04-30 17:42:20 +01:00
const battlerCount = this . scene . currentBattle . getBattlerCount ( ) ;
2023-04-05 13:35:15 +01:00
2023-04-11 05:24:55 +01:00
switch ( button ) {
case Button . UP :
2023-04-05 13:35:15 +01:00
success = this . setCursor ( this . cursor ? this . cursor < 6 ? this . cursor - 1 : slotCount - 1 : 6 ) ;
break ;
2023-04-11 05:24:55 +01:00
case Button . DOWN :
2023-04-05 13:35:15 +01:00
success = this . setCursor ( this . cursor < 6 ? this . cursor < slotCount - 1 ? this . cursor + 1 : 6 : 0 ) ;
break ;
2023-04-11 05:24:55 +01:00
case Button . LEFT :
2024-04-30 17:42:20 +01:00
if ( this . cursor >= battlerCount && this . cursor <= 6 )
2023-04-05 13:35:15 +01:00
success = this . setCursor ( 0 ) ;
break ;
2023-04-11 05:24:55 +01:00
case Button . RIGHT :
2024-04-30 17:42:20 +01:00
if ( slotCount === battlerCount ) {
success = this . setCursor ( 6 ) ;
2023-04-05 13:35:15 +01:00
break ;
2024-04-30 17:42:20 +01:00
} else if ( battlerCount >= 2 && slotCount > battlerCount && this . getCursor ( ) === 0 && this . lastCursor === 1 ) {
success = this . setCursor ( 2 ) ;
break ;
} else if ( slotCount > battlerCount && this . cursor < battlerCount ) {
success = this . setCursor ( this . lastCursor < 6 ? this . lastCursor || battlerCount : battlerCount ) ;
break ;
}
2023-04-05 13:35:15 +01:00
}
2023-03-28 19:54:52 +01:00
}
if ( success )
ui . playSelect ( ) ;
2023-11-12 05:31:40 +00:00
return success ;
2023-03-28 19:54:52 +01:00
}
populatePartySlots() {
2023-04-14 23:21:33 +01:00
const party = this . scene . getParty ( ) ;
2023-03-28 19:54:52 +01:00
if ( this . cursor < 6 && this . cursor >= party . length )
this . cursor = party . length - 1 ;
else if ( this . cursor === 6 )
this . partyCancelButton . select ( ) ;
for ( let p in party ) {
const slotIndex = parseInt ( p ) ;
2023-12-07 05:52:20 +00:00
const partySlot = new PartySlot ( this . scene , slotIndex , party [ p ] , this . iconAnimHandler , this . partyUiMode , this . tmMoveId ) ;
2023-03-28 19:54:52 +01:00
this . scene . add . existing ( partySlot ) ;
this . partySlotsContainer . add ( partySlot ) ;
this . partySlots . push ( partySlot ) ;
if ( this . cursor === slotIndex )
partySlot . select ( ) ;
}
}
2023-04-05 13:35:15 +01:00
setCursor ( cursor : integer ) : boolean {
let changed : boolean ;
if ( this . optionsMode ) {
changed = this . optionsCursor !== cursor ;
2023-11-07 23:43:48 +00:00
let isScroll = false ;
if ( changed && this . optionsScroll ) {
if ( Math . abs ( cursor - this . optionsCursor ) === this . options . length - 1 ) {
this . optionsScrollCursor = cursor ? this . optionsScrollTotal - 8 : 0 ;
this . updateOptions ( ) ;
} else {
const isDown = cursor && cursor > this . optionsCursor ;
if ( isDown ) {
if ( this . options [ cursor ] === PartyOption . SCROLL_DOWN ) {
isScroll = true ;
this . optionsScrollCursor ++ ;
}
} else {
if ( ! cursor && this . optionsScrollCursor ) {
isScroll = true ;
this . optionsScrollCursor -- ;
}
}
if ( isScroll && this . optionsScrollCursor === 1 )
this . optionsScrollCursor += isDown ? 1 : - 1 ;
}
}
2024-02-21 20:47:44 +00:00
if ( isScroll )
2023-11-07 23:43:48 +00:00
this . updateOptions ( ) ;
2024-02-21 20:47:44 +00:00
else
2023-11-07 23:43:48 +00:00
this . optionsCursor = cursor ;
2023-04-05 13:35:15 +01:00
if ( ! this . optionsCursorObj ) {
this . optionsCursorObj = this . scene . add . image ( 0 , 0 , 'cursor' ) ;
this . optionsCursorObj . setOrigin ( 0 , 0 ) ;
this . optionsContainer . add ( this . optionsCursorObj ) ;
}
2024-01-10 04:34:43 +00:00
this . optionsCursorObj . setPosition ( 8 - this . optionsBg . displayWidth , - 19 - ( 16 * ( ( this . options . length - 1 ) - this . optionsCursor ) ) ) ;
2023-04-05 13:35:15 +01:00
} else {
changed = this . cursor !== cursor ;
if ( changed ) {
this . lastCursor = this . cursor ;
this . cursor = cursor ;
if ( this . lastCursor < 6 )
this . partySlots [ this . lastCursor ] . deselect ( ) ;
else if ( this . lastCursor === 6 )
this . partyCancelButton . deselect ( ) ;
if ( cursor < 6 )
this . partySlots [ cursor ] . select ( ) ;
else if ( cursor === 6 )
this . partyCancelButton . select ( ) ;
}
}
return changed ;
}
2023-04-23 03:14:53 +01:00
showText ( text : string , delay? : integer , callback? : Function , callbackDelay? : integer , prompt? : boolean , promptDelay? : integer ) {
if ( text === null )
text = defaultMessage ;
if ( text ? . indexOf ( '\n' ) === - 1 ) {
2023-12-21 03:22:15 +00:00
this . partyMessageBox . setSize ( 262 , 30 ) ;
2023-04-23 03:14:53 +01:00
this . message . setY ( 10 ) ;
} else {
2023-12-21 03:22:15 +00:00
this . partyMessageBox . setSize ( 262 , 42 ) ;
2023-04-23 03:14:53 +01:00
this . message . setY ( - 5 ) ;
}
super . showText ( text , delay , callback , callbackDelay , prompt , promptDelay ) ;
}
2023-04-05 13:35:15 +01:00
showOptions() {
if ( this . cursor === 6 )
return ;
this . optionsMode = true ;
2023-04-21 19:05:16 +01:00
let optionsMessage = 'Do what with this Pokémon?' ;
switch ( this . partyUiMode ) {
case PartyUiMode . MOVE_MODIFIER :
optionsMessage = 'Select a move.' ;
break ;
case PartyUiMode . MODIFIER_TRANSFER :
if ( ! this . transferMode )
optionsMessage = 'Select a held item to transfer.' ;
break ;
2023-11-04 04:32:12 +00:00
case PartyUiMode . SPLICE :
if ( ! this . transferMode )
optionsMessage = 'Select another Pokémon to splice.' ;
break ;
2023-04-21 19:05:16 +01:00
}
2023-04-23 03:14:53 +01:00
this . showText ( optionsMessage , 0 ) ;
2023-04-21 19:05:16 +01:00
2023-11-07 23:43:48 +00:00
this . updateOptions ( ) ;
2024-01-10 04:34:43 +00:00
this . partyMessageBox . setSize ( 262 - Math . max ( this . optionsBg . displayWidth - 56 , 0 ) , 30 ) ;
2023-12-21 03:22:15 +00:00
2023-11-07 23:43:48 +00:00
this . setCursor ( 0 ) ;
}
updateOptions ( ) : void {
2023-04-11 16:04:39 +01:00
const pokemon = this . scene . getParty ( ) [ this . cursor ] ;
2023-04-06 03:22:03 +01:00
2023-11-08 22:30:07 +00:00
const learnableLevelMoves = this . partyUiMode === PartyUiMode . REMEMBER_MOVE_MODIFIER
? pokemon . getLearnableLevelMoves ( )
: null ;
2023-04-21 19:05:16 +01:00
const itemModifiers = this . partyUiMode === PartyUiMode . MODIFIER_TRANSFER
2023-06-01 00:54:57 +01:00
? this . scene . findModifiers ( m = > m instanceof PokemonHeldItemModifier
&& ( m as PokemonHeldItemModifier ) . getTransferrable ( true ) && ( m as PokemonHeldItemModifier ) . pokemonId === pokemon . id ) as PokemonHeldItemModifier [ ]
2023-04-21 19:05:16 +01:00
: null ;
2023-11-07 23:43:48 +00:00
if ( this . options . length ) {
this . options . splice ( 0 , this . options . length ) ;
this . optionsContainer . removeAll ( true ) ;
this . eraseOptionsCursor ( ) ;
}
2024-01-10 04:34:43 +00:00
let formChangeItemModifiers : PokemonFormChangeItemModifier [ ] ;
2023-11-08 22:30:07 +00:00
if ( this . partyUiMode !== PartyUiMode . MOVE_MODIFIER && this . partyUiMode !== PartyUiMode . REMEMBER_MOVE_MODIFIER && ( this . transferMode || this . partyUiMode !== PartyUiMode . MODIFIER_TRANSFER ) ) {
2023-04-11 16:04:39 +01:00
switch ( this . partyUiMode ) {
case PartyUiMode . SWITCH :
case PartyUiMode . FAINT_SWITCH :
case PartyUiMode . POST_BATTLE_SWITCH :
2023-05-18 16:11:06 +01:00
if ( this . cursor >= this . scene . currentBattle . getBattlerCount ( ) ) {
2023-04-11 16:04:39 +01:00
this . options . push ( PartyOption . SEND_OUT ) ;
2023-04-29 00:26:41 +01:00
if ( this . partyUiMode !== PartyUiMode . FAINT_SWITCH
2023-05-18 16:11:06 +01:00
&& this . scene . findModifier ( m = > m instanceof SwitchEffectTransferModifier
&& ( m as SwitchEffectTransferModifier ) . pokemonId === this . scene . getPlayerField ( ) [ this . fieldIndex ] . id ) )
2023-04-29 00:26:41 +01:00
this . options . push ( PartyOption . PASS_BATON ) ;
}
2024-01-10 04:34:43 +00:00
if ( this . scene . getCurrentPhase ( ) instanceof CommandPhase ) {
formChangeItemModifiers = this . scene . findModifiers ( m = > m instanceof PokemonFormChangeItemModifier && m . pokemonId === pokemon . id ) as PokemonFormChangeItemModifier [ ] ;
if ( formChangeItemModifiers . find ( m = > m . active ) )
formChangeItemModifiers = formChangeItemModifiers . filter ( m = > m . active ) ;
for ( let i = 0 ; i < formChangeItemModifiers . length ; i ++ )
this . options . push ( PartyOption . FORM_CHANGE_ITEM + i ) ;
}
2023-04-11 16:04:39 +01:00
break ;
case PartyUiMode . MODIFIER :
this . options . push ( PartyOption . APPLY ) ;
break ;
2023-07-05 04:11:31 +01:00
case PartyUiMode . TM_MODIFIER :
this . options . push ( PartyOption . TEACH ) ;
break ;
2023-04-21 19:05:16 +01:00
case PartyUiMode . MODIFIER_TRANSFER :
this . options . push ( PartyOption . TRANSFER ) ;
break ;
2023-11-04 04:32:12 +00:00
case PartyUiMode . SPLICE :
if ( this . transferMode ) {
if ( this . cursor !== this . transferCursor )
this . options . push ( PartyOption . SPLICE ) ;
} else
this . options . push ( PartyOption . APPLY ) ;
break ;
2023-04-11 16:04:39 +01:00
case PartyUiMode . RELEASE :
this . options . push ( PartyOption . RELEASE ) ;
break ;
}
2023-04-11 14:41:11 +01:00
2023-04-11 16:04:39 +01:00
this . options . push ( PartyOption . SUMMARY ) ;
2023-12-14 17:55:11 +00:00
if ( pokemon . pauseEvolutions && pokemonEvolutions . hasOwnProperty ( pokemon . species . speciesId ) )
2024-01-10 04:34:43 +00:00
this . options . push ( PartyOption . UNPAUSE_EVOLUTION ) ;
2023-12-14 17:55:11 +00:00
2024-04-03 01:51:43 +01:00
if ( this . partyUiMode === PartyUiMode . SWITCH ) {
if ( pokemon . isFusion ( ) )
this . options . push ( PartyOption . UNSPLICE ) ;
2023-04-11 16:04:39 +01:00
this . options . push ( PartyOption . RELEASE ) ;
2024-04-03 01:51:43 +01:00
} else if ( this . partyUiMode === PartyUiMode . SPLICE && pokemon . isFusion ( ) )
this . options . push ( PartyOption . UNSPLICE ) ;
2023-04-21 19:05:16 +01:00
} else if ( this . partyUiMode === PartyUiMode . MOVE_MODIFIER ) {
2023-04-11 16:04:39 +01:00
for ( let m = 0 ; m < pokemon . moveset . length ; m ++ )
this . options . push ( PartyOption . MOVE_1 + m ) ;
2023-11-08 22:30:07 +00:00
} else if ( this . partyUiMode === PartyUiMode . REMEMBER_MOVE_MODIFIER ) {
const learnableMoves = pokemon . getLearnableLevelMoves ( ) ;
for ( let m = 0 ; m < learnableMoves . length ; m ++ )
this . options . push ( m ) ;
2023-04-21 19:05:16 +01:00
} else {
for ( let im = 0 ; im < itemModifiers . length ; im ++ )
this . options . push ( im ) ;
2023-04-11 16:04:39 +01:00
}
2023-04-11 14:41:11 +01:00
2023-11-07 23:43:48 +00:00
this . optionsScrollTotal = this . options . length ;
let optionStartIndex = this . optionsScrollCursor ;
let optionEndIndex = Math . min ( this . optionsScrollTotal , optionStartIndex + ( ! optionStartIndex || this . optionsScrollCursor + 8 >= this . optionsScrollTotal ? 8 : 7 ) ) ;
this . optionsScroll = this . optionsScrollTotal > 9 ;
if ( this . optionsScroll ) {
this . options . splice ( optionEndIndex , this . optionsScrollTotal ) ;
this . options . splice ( 0 , optionStartIndex ) ;
if ( optionStartIndex )
this . options . unshift ( PartyOption . SCROLL_UP ) ;
if ( optionEndIndex < this . optionsScrollTotal )
this . options . push ( PartyOption . SCROLL_DOWN ) ;
}
2023-04-11 14:41:11 +01:00
this . options . push ( PartyOption . CANCEL ) ;
2023-04-05 13:35:15 +01:00
2024-01-10 04:34:43 +00:00
this . optionsBg = addWindow ( this . scene , 0 , 0 , 0 , 16 * this . options . length + 13 ) ;
this . optionsBg . setOrigin ( 1 , 1 ) ;
2023-11-07 23:43:48 +00:00
2024-01-10 04:34:43 +00:00
this . optionsContainer . add ( this . optionsBg ) ;
2023-11-07 23:43:48 +00:00
optionStartIndex = 0 ;
optionEndIndex = this . options . length ;
2024-01-10 04:34:43 +00:00
let widestOptionWidth = 0 ;
let optionTexts : Phaser.GameObjects.Text [ ] = [ ] ;
2023-11-07 23:43:48 +00:00
for ( let o = optionStartIndex ; o < optionEndIndex ; o ++ ) {
2023-04-11 16:04:39 +01:00
const option = this . options [ this . options . length - ( o + 1 ) ] ;
2023-11-09 03:30:22 +00:00
let altText = false ;
2023-04-11 16:04:39 +01:00
let optionName : string ;
2024-04-26 06:18:08 +01:00
if ( option === PartyOption . SCROLL_UP )
optionName = '↑' ;
else if ( option === PartyOption . SCROLL_DOWN )
optionName = '↓' ;
else if ( ( this . partyUiMode !== PartyUiMode . REMEMBER_MOVE_MODIFIER && ( this . partyUiMode !== PartyUiMode . MODIFIER_TRANSFER || this . transferMode ) ) || option === PartyOption . CANCEL ) {
2023-04-21 19:05:16 +01:00
switch ( option ) {
case PartyOption . MOVE_1 :
case PartyOption . MOVE_2 :
case PartyOption . MOVE_3 :
case PartyOption . MOVE_4 :
2024-05-01 15:16:58 +01:00
const move = pokemon . moveset [ option - PartyOption . MOVE_1 ] ;
if ( this . showMovePp ) {
const maxPP = move . getMovePp ( ) ;
const currPP = maxPP - move . ppUsed ;
optionName = ` ${ move . getName ( ) } ${ currPP } / ${ maxPP } ` ;
} else {
optionName = move . getName ( ) ;
}
2023-04-21 19:05:16 +01:00
break ;
default :
2024-01-10 04:34:43 +00:00
if ( formChangeItemModifiers && option >= PartyOption . FORM_CHANGE_ITEM ) {
const modifier = formChangeItemModifiers [ option - PartyOption . FORM_CHANGE_ITEM ] ;
optionName = ` ${ modifier . active ? 'Deactivate' : 'Activate' } ${ modifier . type . name } ` ;
} else
optionName = Utils . toReadableString ( PartyOption [ option ] ) ;
2023-04-21 19:05:16 +01:00
break ;
}
2024-04-26 06:18:08 +01:00
} else if ( this . partyUiMode === PartyUiMode . REMEMBER_MOVE_MODIFIER ) {
2023-11-08 22:30:07 +00:00
const move = learnableLevelMoves [ option ] ;
optionName = allMoves [ move ] . name ;
2023-11-09 04:37:12 +00:00
altText = ! pokemon . getSpeciesForm ( ) . getLevelMoves ( ) . find ( plm = > plm [ 1 ] === move ) ;
2023-11-08 22:30:07 +00:00
} else {
2023-04-21 19:05:16 +01:00
const itemModifier = itemModifiers [ option ] ;
optionName = itemModifier . type . name ;
if ( itemModifier . stackCount > 1 )
optionName += ` ( ${ itemModifier . stackCount } ) ` ;
2023-04-11 16:04:39 +01:00
}
2023-04-05 13:35:15 +01:00
const yCoord = - 6 - 16 * o ;
2024-01-10 04:34:43 +00:00
const optionText = addTextObject ( this . scene , 0 , yCoord - 16 , optionName , TextStyle . WINDOW ) ;
2023-11-09 03:30:22 +00:00
if ( altText ) {
optionText . setColor ( '#40c8f8' ) ;
optionText . setShadowColor ( '#006090' )
}
2023-04-05 13:35:15 +01:00
optionText . setOrigin ( 0 , 0 ) ;
2024-01-10 04:34:43 +00:00
optionTexts . push ( optionText ) ;
widestOptionWidth = Math . max ( optionText . displayWidth , widestOptionWidth ) ;
2023-04-05 13:35:15 +01:00
this . optionsContainer . add ( optionText ) ;
}
2024-01-10 04:34:43 +00:00
this . optionsBg . width = Math . max ( widestOptionWidth + 24 , 94 ) ;
for ( let optionText of optionTexts )
optionText . x = 15 - this . optionsBg . width ;
2023-04-05 13:35:15 +01:00
}
2023-04-21 19:05:16 +01:00
startTransfer ( ) : void {
this . transferMode = true ;
this . transferCursor = this . cursor ;
2023-11-08 22:30:07 +00:00
this . transferOptionCursor = this . getOptionsCursorWithScroll ( ) ;
2023-04-21 19:05:16 +01:00
this . partySlots [ this . transferCursor ] . setTransfer ( true ) ;
}
clearTransfer ( ) : void {
this . transferMode = false ;
this . partySlots [ this . transferCursor ] . setTransfer ( false ) ;
}
2023-04-11 14:41:11 +01:00
doRelease ( slotIndex : integer ) : void {
this . showText ( this . getReleaseMessage ( this . scene . getParty ( ) [ slotIndex ] . name ) , null , ( ) = > {
this . clearPartySlots ( ) ;
this . scene . removePartyMemberModifiers ( slotIndex ) ;
2023-04-14 04:50:48 +01:00
const releasedPokemon = this . scene . getParty ( ) . splice ( slotIndex , 1 ) [ 0 ] ;
releasedPokemon . destroy ( ) ;
2023-04-11 14:41:11 +01:00
this . populatePartySlots ( ) ;
if ( this . cursor >= this . scene . getParty ( ) . length )
this . setCursor ( this . cursor - 1 ) ;
if ( this . partyUiMode === PartyUiMode . RELEASE ) {
const selectCallback = this . selectCallback ;
this . selectCallback = null ;
2023-04-11 16:04:39 +01:00
selectCallback ( this . cursor , PartyOption . RELEASE ) ;
2023-12-20 05:35:41 +00:00
}
this . showText ( null , 0 ) ;
2023-04-11 14:41:11 +01:00
} , null , true ) ;
}
2023-04-11 06:31:18 +01:00
getReleaseMessage ( pokemonName : string ) : string {
const rand = Utils . randInt ( 128 ) ;
2023-04-11 14:41:11 +01:00
if ( rand < 20 )
2023-04-11 06:31:18 +01:00
return ` Goodbye, ${ pokemonName } ! ` ;
2023-04-11 14:41:11 +01:00
else if ( rand < 40 )
return ` Byebye, ${ pokemonName } ! ` ;
else if ( rand < 60 )
2023-04-11 06:31:18 +01:00
return ` Farewell, ${ pokemonName } ! ` ;
2023-04-11 14:41:11 +01:00
else if ( rand < 80 )
return ` So long, ${ pokemonName } ! ` ;
else if ( rand < 100 )
2023-04-11 06:31:18 +01:00
return ` This is where we part, ${ pokemonName } ! ` ;
else if ( rand < 108 )
return ` I'll miss you, ${ pokemonName } ! ` ;
else if ( rand < 116 )
return ` I'll never forget you, ${ pokemonName } ! ` ;
else if ( rand < 124 )
return ` Until we meet again, ${ pokemonName } ! ` ;
else if ( rand < 127 )
return ` Sayonara, ${ pokemonName } ! `
else
return ` Smell ya later, ${ pokemonName } ! ` ;
}
2023-11-08 22:30:07 +00:00
getOptionsCursorWithScroll ( ) : integer {
return this . optionsCursor + this . optionsScrollCursor + ( this . options && this . options [ 0 ] === PartyOption . SCROLL_UP ? - 1 : 0 ) ;
}
2023-04-05 13:35:15 +01:00
clearOptions() {
this . optionsMode = false ;
2023-11-07 23:43:48 +00:00
this . optionsScroll = false ;
this . optionsScrollCursor = 0 ;
this . optionsScrollTotal = 0 ;
2023-04-06 03:22:03 +01:00
this . options . splice ( 0 , this . options . length ) ;
2023-04-05 13:35:15 +01:00
this . optionsContainer . removeAll ( true ) ;
this . eraseOptionsCursor ( ) ;
2023-12-21 03:22:15 +00:00
this . partyMessageBox . setSize ( 262 , 30 ) ;
2023-04-23 03:14:53 +01:00
this . showText ( null , 0 ) ;
2023-04-05 13:35:15 +01:00
}
eraseOptionsCursor() {
if ( this . optionsCursorObj )
this . optionsCursorObj . destroy ( ) ;
this . optionsCursorObj = null ;
}
2023-03-28 19:54:52 +01:00
clear() {
super . clear ( ) ;
this . partyContainer . setVisible ( false ) ;
this . clearPartySlots ( ) ;
}
clearPartySlots() {
this . partySlots . splice ( 0 , this . partySlots . length ) ;
this . partySlotsContainer . removeAll ( true ) ;
}
}
class PartySlot extends Phaser . GameObjects . Container {
private selected : boolean ;
2023-04-21 19:05:16 +01:00
private transfer : boolean ;
2023-03-28 19:54:52 +01:00
private slotIndex : integer ;
private pokemon : PlayerPokemon ;
private slotBg : Phaser.GameObjects.Image ;
private slotPb : Phaser.GameObjects.Sprite ;
2024-04-10 15:57:06 +01:00
private pokemonIcon : Phaser.GameObjects.Container ;
2023-12-07 05:52:20 +00:00
private iconAnimHandler : PokemonIconAnimHandler ;
constructor ( scene : BattleScene , slotIndex : integer , pokemon : PlayerPokemon , iconAnimHandler : PokemonIconAnimHandler , partyUiMode : PartyUiMode , tmMoveId : Moves ) {
2023-05-18 16:11:06 +01:00
super ( scene , slotIndex >= scene . currentBattle . getBattlerCount ( ) ? 230.5 : 64 ,
2024-02-15 04:33:55 +00:00
slotIndex >= scene . currentBattle . getBattlerCount ( ) ? - 184 + ( scene . currentBattle . double ? - 40 : 0 )
+ ( 28 + ( scene . currentBattle . double ? 8 : 0 ) ) * slotIndex : - 124 + ( scene . currentBattle . double ? - 8 : 0 ) + slotIndex * 64 ) ;
2023-03-28 19:54:52 +01:00
this . slotIndex = slotIndex ;
this . pokemon = pokemon ;
2023-12-07 05:52:20 +00:00
this . iconAnimHandler = iconAnimHandler ;
2023-03-28 19:54:52 +01:00
2023-07-05 04:11:31 +01:00
this . setup ( partyUiMode , tmMoveId ) ;
2023-03-28 19:54:52 +01:00
}
2023-07-05 04:11:31 +01:00
setup ( partyUiMode : PartyUiMode , tmMoveId : Moves ) {
2023-05-18 16:11:06 +01:00
const battlerCount = ( this . scene as BattleScene ) . currentBattle . getBattlerCount ( ) ;
const slotKey = ` party_slot ${ this . slotIndex >= battlerCount ? '' : '_main' } ` ;
2023-03-28 19:54:52 +01:00
const slotBg = this . scene . add . sprite ( 0 , 0 , slotKey , ` ${ slotKey } ${ this . pokemon . hp ? '' : '_fnt' } ` ) ;
this . slotBg = slotBg ;
this . add ( slotBg ) ;
2023-05-18 16:11:06 +01:00
const slotPb = this . scene . add . sprite ( this . slotIndex >= battlerCount ? - 85.5 : - 51 , this . slotIndex >= battlerCount ? 0 : - 20.5 , 'party_pb' ) ;
2023-03-28 19:54:52 +01:00
this . slotPb = slotPb ;
this . add ( slotPb ) ;
2024-04-10 15:57:06 +01:00
this . pokemonIcon = ( this . scene as BattleScene ) . addPokemonIcon ( this . pokemon , slotPb . x , slotPb . y , 0.5 , 0.5 , true ) ;
2023-12-07 05:52:20 +00:00
this . add ( this . pokemonIcon ) ;
2023-03-28 19:54:52 +01:00
2023-12-07 05:52:20 +00:00
this . iconAnimHandler . addOrUpdate ( this . pokemonIcon , PokemonIconAnimMode . PASSIVE ) ;
2023-03-28 19:54:52 +01:00
const slotInfoContainer = this . scene . add . container ( 0 , 0 ) ;
this . add ( slotInfoContainer ) ;
2023-12-10 04:41:36 +00:00
let displayName = this . pokemon . name ;
let nameTextWidth : number ;
let nameSizeTest = addTextObject ( this . scene , 0 , 0 , displayName , TextStyle . PARTY ) ;
nameTextWidth = nameSizeTest . displayWidth ;
2024-03-07 04:57:11 +00:00
while ( nameTextWidth > ( this . slotIndex >= battlerCount ? 52 : ( 76 - ( this . pokemon . fusionSpecies ? 8 : 0 ) ) ) ) {
2023-12-10 04:41:36 +00:00
displayName = ` ${ displayName . slice ( 0 , displayName . endsWith ( '.' ) ? - 2 : - 1 ) . trimEnd ( ) } . ` ;
nameSizeTest . setText ( displayName ) ;
nameTextWidth = nameSizeTest . displayWidth ;
}
nameSizeTest . destroy ( ) ;
const slotName = addTextObject ( this . scene , 0 , 0 , displayName , TextStyle . PARTY ) ;
2023-07-05 05:29:22 +01:00
slotName . setPositionRelative ( slotBg , this . slotIndex >= battlerCount ? 21 : 24 , this . slotIndex >= battlerCount ? 2 : 10 ) ;
2023-03-28 19:54:52 +01:00
slotName . setOrigin ( 0 , 0 ) ;
const slotLevelLabel = this . scene . add . image ( 0 , 0 , 'party_slot_overlay_lv' ) ;
slotLevelLabel . setPositionRelative ( slotName , 8 , 12 ) ;
slotLevelLabel . setOrigin ( 0 , 0 ) ;
2023-10-03 17:50:31 +01:00
const slotLevelText = addTextObject ( this . scene , 0 , 0 , this . pokemon . level . toString ( ) , this . pokemon . level < ( this . scene as BattleScene ) . getMaxExpLevel ( ) ? TextStyle.PARTY : TextStyle.PARTY_RED ) ;
2023-03-28 19:54:52 +01:00
slotLevelText . setPositionRelative ( slotLevelLabel , 9 , 0 ) ;
slotLevelText . setOrigin ( 0 , 0.25 ) ;
2023-07-05 04:11:31 +01:00
slotInfoContainer . add ( [ slotName , slotLevelLabel , slotLevelText ] ) ;
2023-10-29 05:28:56 +00:00
const genderSymbol = getGenderSymbol ( this . pokemon . getGender ( true ) ) ;
2023-07-05 05:29:22 +01:00
if ( genderSymbol ) {
const slotGenderText = addTextObject ( this . scene , 0 , 0 , genderSymbol , TextStyle . PARTY ) ;
2023-10-29 05:28:56 +00:00
slotGenderText . setColor ( getGenderColor ( this . pokemon . getGender ( true ) ) ) ;
slotGenderText . setShadowColor ( getGenderColor ( this . pokemon . getGender ( true ) , true ) ) ;
2023-07-10 16:21:05 +01:00
if ( this . slotIndex >= battlerCount )
slotGenderText . setPositionRelative ( slotLevelLabel , 36 , 0 ) ;
else
slotGenderText . setPositionRelative ( slotName , 76 , 3 ) ;
2023-07-05 05:29:22 +01:00
slotGenderText . setOrigin ( 0 , 0.25 ) ;
slotInfoContainer . add ( slotGenderText ) ;
}
2024-03-07 04:20:53 +00:00
if ( this . pokemon . fusionSpecies ) {
const splicedIcon = this . scene . add . image ( 0 , 0 , 'icon_spliced' ) ;
splicedIcon . setScale ( 0.5 ) ;
splicedIcon . setOrigin ( 0 , 0 ) ;
if ( this . slotIndex >= battlerCount )
splicedIcon . setPositionRelative ( slotLevelLabel , 36 - ( genderSymbol ? 8 : 0 ) , 0.5 ) ;
else
splicedIcon . setPositionRelative ( slotName , 76 - ( genderSymbol ? 8 : 0 ) , 3.5 ) ;
slotInfoContainer . add ( splicedIcon ) ;
}
2023-07-05 05:29:22 +01:00
if ( this . pokemon . status ) {
const statusIndicator = this . scene . add . sprite ( 0 , 0 , 'statuses' ) ;
2023-07-10 16:21:05 +01:00
statusIndicator . setFrame ( StatusEffect [ this . pokemon . status ? . effect ] . toLowerCase ( ) ) ;
2023-07-05 05:29:22 +01:00
statusIndicator . setOrigin ( 0 , 0 ) ;
statusIndicator . setPositionRelative ( slotLevelLabel , this . slotIndex >= battlerCount ? 43 : 55 , 0 ) ;
slotInfoContainer . add ( statusIndicator ) ;
}
2023-11-06 04:48:04 +00:00
if ( this . pokemon . isShiny ( ) ) {
2024-04-26 16:31:39 +01:00
const doubleShiny = this . pokemon . isFusion ( ) && this . pokemon . shiny && this . pokemon . fusionShiny ;
const shinyStar = this . scene . add . image ( 0 , 0 , ` shiny_star_small ${ doubleShiny ? '_1' : '' } ` ) ;
2023-07-05 05:29:22 +01:00
shinyStar . setOrigin ( 0 , 0 ) ;
2024-04-19 03:52:26 +01:00
shinyStar . setPositionRelative ( slotName , - 9 , 3 ) ;
2024-04-26 16:31:39 +01:00
shinyStar . setTint ( getVariantTint ( ! doubleShiny ? this . pokemon . getVariant ( ) : this . pokemon . variant ) ) ;
2023-07-05 05:29:22 +01:00
slotInfoContainer . add ( shinyStar ) ;
2024-04-26 16:31:39 +01:00
if ( doubleShiny ) {
const fusionShinyStar = this . scene . add . image ( 0 , 0 , ` shiny_star_small_2 ` ) ;
fusionShinyStar . setOrigin ( 0 , 0 ) ;
fusionShinyStar . setPosition ( shinyStar . x , shinyStar . y ) ;
fusionShinyStar . setTint ( getVariantTint ( this . pokemon . fusionVariant ) ) ;
slotInfoContainer . add ( fusionShinyStar ) ;
}
2023-07-05 05:29:22 +01:00
}
2023-07-05 04:11:31 +01:00
if ( partyUiMode !== PartyUiMode . TM_MODIFIER ) {
const slotHpBar = this . scene . add . image ( 0 , 0 , 'party_slot_hp_bar' ) ;
2023-07-05 05:29:22 +01:00
slotHpBar . setPositionRelative ( slotBg , this . slotIndex >= battlerCount ? 72 : 8 , this . slotIndex >= battlerCount ? 6 : 31 ) ;
2023-07-05 04:11:31 +01:00
slotHpBar . setOrigin ( 0 , 0 ) ;
2023-03-28 19:54:52 +01:00
2023-07-05 04:11:31 +01:00
const hpRatio = this . pokemon . getHpRatio ( ) ;
2023-03-28 19:54:52 +01:00
2023-07-05 04:11:31 +01:00
const slotHpOverlay = this . scene . add . sprite ( 0 , 0 , 'party_slot_hp_overlay' , hpRatio > 0.5 ? 'high' : hpRatio > 0.25 ? 'medium' : 'low' ) ;
slotHpOverlay . setPositionRelative ( slotHpBar , 16 , 2 ) ;
slotHpOverlay . setOrigin ( 0 , 0 ) ;
slotHpOverlay . setScale ( hpRatio , 1 ) ;
2023-03-28 19:54:52 +01:00
2023-07-05 04:11:31 +01:00
const slotHpText = addTextObject ( this . scene , 0 , 0 , ` ${ this . pokemon . hp } / ${ this . pokemon . getMaxHp ( ) } ` , TextStyle . PARTY ) ;
slotHpText . setPositionRelative ( slotHpBar , slotHpBar . width - 3 , slotHpBar . height - 2 ) ;
slotHpText . setOrigin ( 1 , 0 ) ;
2023-03-28 19:54:52 +01:00
2023-07-05 04:11:31 +01:00
slotInfoContainer . add ( [ slotHpBar , slotHpOverlay , slotHpText ] ) ;
} else {
let slotTmText : string ;
switch ( true ) {
case ( this . pokemon . compatibleTms . indexOf ( tmMoveId ) === - 1 ) :
2023-10-18 23:01:15 +01:00
slotTmText = 'Not Able' ;
2023-07-05 04:11:31 +01:00
break ;
case ( this . pokemon . getMoveset ( ) . filter ( m = > m ? . moveId === tmMoveId ) . length > 0 ) :
2023-10-18 23:01:15 +01:00
slotTmText = 'Learned' ;
2023-07-05 04:11:31 +01:00
break ;
default :
2023-10-18 23:01:15 +01:00
slotTmText = 'Able' ;
2023-07-05 04:11:31 +01:00
break ;
}
2023-03-28 19:54:52 +01:00
2023-07-05 05:29:22 +01:00
const slotTmLabel = addTextObject ( this . scene , 0 , 0 , slotTmText , TextStyle . MESSAGE ) ;
slotTmLabel . setPositionRelative ( slotBg , this . slotIndex >= battlerCount ? 94 : 32 , this . slotIndex >= battlerCount ? 16 : 46 ) ;
slotTmLabel . setOrigin ( 0 , 1 ) ;
slotInfoContainer . add ( slotTmLabel ) ;
2023-07-05 04:11:31 +01:00
}
2023-03-28 19:54:52 +01:00
}
2023-04-21 19:05:16 +01:00
select ( ) : void {
2023-03-28 19:54:52 +01:00
if ( this . selected )
return ;
this . selected = true ;
2023-12-07 05:52:20 +00:00
this . iconAnimHandler . addOrUpdate ( this . pokemonIcon , PokemonIconAnimMode . ACTIVE ) ;
2023-03-28 19:54:52 +01:00
2023-04-21 19:05:16 +01:00
this . updateSlotTexture ( ) ;
2023-03-28 19:54:52 +01:00
this . slotPb . setFrame ( 'party_pb_sel' ) ;
}
2023-04-21 19:05:16 +01:00
deselect ( ) : void {
2023-03-28 19:54:52 +01:00
if ( ! this . selected )
return ;
this . selected = false ;
2023-12-07 05:52:20 +00:00
this . iconAnimHandler . addOrUpdate ( this . pokemonIcon , PokemonIconAnimMode . PASSIVE ) ;
2023-03-28 19:54:52 +01:00
2023-04-21 19:05:16 +01:00
this . updateSlotTexture ( ) ;
2023-03-28 19:54:52 +01:00
this . slotPb . setFrame ( 'party_pb' ) ;
}
2023-04-21 19:05:16 +01:00
setTransfer ( transfer : boolean ) : void {
if ( this . transfer === transfer )
return ;
this . transfer = transfer ;
this . updateSlotTexture ( ) ;
}
private updateSlotTexture ( ) : void {
2023-05-18 16:11:06 +01:00
const battlerCount = ( this . scene as BattleScene ) . currentBattle . getBattlerCount ( ) ;
this . slotBg . setTexture ( ` party_slot ${ this . slotIndex >= battlerCount ? '' : '_main' } ` ,
` party_slot ${ this . slotIndex >= battlerCount ? '' : '_main' } ${ this . transfer ? '_swap' : this . pokemon . hp ? '' : '_fnt' } ${ this . selected ? '_sel' : '' } ` ) ;
2023-04-21 19:05:16 +01:00
}
2023-03-28 19:54:52 +01:00
}
class PartyCancelButton extends Phaser . GameObjects . Container {
private selected : boolean ;
private partyCancelBg : Phaser.GameObjects.Sprite ;
private partyCancelPb : Phaser.GameObjects.Sprite ;
constructor ( scene : BattleScene , x : number , y : number ) {
super ( scene , x , y ) ;
this . setup ( ) ;
}
setup() {
const partyCancelBg = this . scene . add . sprite ( 0 , 0 , 'party_cancel' ) ;
this . add ( partyCancelBg ) ;
this . partyCancelBg = partyCancelBg ;
const partyCancelPb = this . scene . add . sprite ( - 17 , 0 , 'party_pb' ) ;
this . add ( partyCancelPb ) ;
this . partyCancelPb = partyCancelPb ;
2023-10-18 23:01:15 +01:00
const partyCancelText = addTextObject ( this . scene , - 7 , - 6 , 'Cancel' , TextStyle . PARTY ) ;
2023-03-28 19:54:52 +01:00
this . add ( partyCancelText ) ;
}
select() {
if ( this . selected )
return ;
this . selected = true ;
this . partyCancelBg . setFrame ( ` party_cancel_sel ` ) ;
this . partyCancelPb . setFrame ( 'party_pb_sel' ) ;
}
deselect() {
if ( ! this . selected )
return ;
this . selected = false ;
this . partyCancelBg . setFrame ( 'party_cancel' ) ;
this . partyCancelPb . setFrame ( 'party_pb' ) ;
}
}