diff --git a/src/constants.asm b/src/constants.asm index 813cbf8..49b7af1 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -1,3 +1,4 @@ +INCLUDE "constants/animation_constants.asm" INCLUDE "constants/attack_animation_constants.asm" INCLUDE "constants/card_constants.asm" INCLUDE "constants/card_data_constants.asm" @@ -29,5 +30,6 @@ INCLUDE "constants/text_constants.asm" INCLUDE "constants/tilemap_constants.asm" INCLUDE "constants/tileset_constants.asm" INCLUDE "constants/var_constants.asm" +INCLUDE "constants/npc_constants.asm" INCLUDE "constants/charmaps.asm" diff --git a/src/constants/animation_constants.asm b/src/constants/animation_constants.asm new file mode 100644 index 0000000..33b18f8 --- /dev/null +++ b/src/constants/animation_constants.asm @@ -0,0 +1,107 @@ + const_def + ; Normal animations + const DUEL_ANIM_NONE ; $00 + const DUEL_ANIM_GLOW ; $01 + const DUEL_ANIM_PARALYSIS ; $02 + const DUEL_ANIM_SLEEP ; $03 + const DUEL_ANIM_CONFUSION ; $04 + const DUEL_ANIM_POISON ; $05 + const DUEL_ANIM_SINGLE_HIT ; $06 + const DUEL_ANIM_HIT ; $07 + const DUEL_ANIM_BIG_HIT ; $08 + const DUEL_ANIM_SHOW_DAMAGE ; $09 + const DUEL_ANIM_THUNDER_SHOCK ; $0a + const DUEL_ANIM_LIGHTNING ; $0b + const DUEL_ANIM_BORDER_SPARK ; $0c + const DUEL_ANIM_BIG_LIGHTNING ; $0d + const DUEL_ANIM_SMALL_FLAME ; $0e + const DUEL_ANIM_BIG_FLAME ; $0f + const DUEL_ANIM_FIRE_SPIN ; $10 + const DUEL_ANIM_DIVE_BOMB ; $11 + const DUEL_ANIM_WATER_JETS ; $12 + const DUEL_ANIM_WATER_GUN ; $13 + const DUEL_ANIM_WHIRLPOOL ; $14 + const DUEL_ANIM_HYDRO_PUMP ; $15 + const DUEL_ANIM_BLIZZARD ; $16 + const DUEL_ANIM_PSYCHIC ; $17 + const DUEL_ANIM_LEER ; $18 + const DUEL_ANIM_BEAM ; $19 + const DUEL_ANIM_HYPER_BEAM ; $1a + const DUEL_ANIM_ROCK_THROW ; $1b + const DUEL_ANIM_STONE_BARRAGE ; $1c + const DUEL_ANIM_PUNCH ; $1d + const DUEL_ANIM_THUNDERPUNCH ; $1e + const DUEL_ANIM_FIRE_PUNCH ; $1f + const DUEL_ANIM_STRETCH_KICK ; $20 + const DUEL_ANIM_SLASH ; $21 + const DUEL_ANIM_WHIP ; $22 + const DUEL_ANIM_SONICBOOM ; $23 + const DUEL_ANIM_FURY_SWIPES ; $24 + const DUEL_ANIM_DRILL ; $25 + const DUEL_ANIM_POT_SMASH ; $26 + const DUEL_ANIM_BONEMERANG ; $27 + const DUEL_ANIM_SEISMIC_TOSS ; $28 + const DUEL_ANIM_NEEDLES ; $29 + const DUEL_ANIM_WHITE_GAS ; $2a + const DUEL_ANIM_POWDER ; $2b + const DUEL_ANIM_GOO ; $2c + const DUEL_ANIM_BUBBLES ; $2d + const DUEL_ANIM_STRING_SHOT ; $2e + const DUEL_ANIM_BOYFRIENDS ; $2f + const DUEL_ANIM_LURE ; $30 + const DUEL_ANIM_TOXIC ; $31 + const DUEL_ANIM_CONFUSE_RAY ; $32 + const DUEL_ANIM_SING ; $33 + const DUEL_ANIM_SUPERSONIC ; $34 + const DUEL_ANIM_PETAL_DANCE ; $35 + const DUEL_ANIM_PROTECT ; $36 + const DUEL_ANIM_BARRIER ; $37 + const DUEL_ANIM_SPEED ; $38 + const DUEL_ANIM_WHIRLWIND ; $39 + const DUEL_ANIM_CRY ; $3a + const DUEL_ANIM_QUESTION_MARK ; $3b + const DUEL_ANIM_SELFDESTRUCT ; $3c + const DUEL_ANIM_BIG_SELFDESTRUCT_1 ; $3d + const DUEL_ANIM_HEAL ; $3e + const DUEL_ANIM_DRAIN ; $3f + const DUEL_ANIM_DARK_GAS ; $40 + const DUEL_ANIM_BIG_SELFDESTRUCT_2 ; $41 + const DUEL_ANIM_UNUSED_42 ; $42 + const DUEL_ANIM_UNUSED_43 ; $43 + const DUEL_ANIM_BENCH_THUNDER ; $44 + const DUEL_ANIM_QUICKFREEZE ; $45 + const DUEL_ANIM_BENCH_GLOW ; $46 + const DUEL_ANIM_FIREGIVER_START ; $47 + const DUEL_ANIM_UNUSED_48 ; $48 + const DUEL_ANIM_HEALING_WIND ; $49 + const DUEL_ANIM_BENCH_WHIRLWIND ; $4a + const DUEL_ANIM_EXPAND ; $4b + const DUEL_ANIM_CAT_PUNCH ; $4c + const DUEL_ANIM_THUNDER_WAVE ; $4d + const DUEL_ANIM_FIREGIVER_PLAYER ; $4e + const DUEL_ANIM_FIREGIVER_OPP ; $4f + const DUEL_ANIM_UNUSED_50 ; $50 + const DUEL_ANIM_PLAYER_SHUFFLE ; $51 + const DUEL_ANIM_OPP_SHUFFLE ; $52 + const DUEL_ANIM_BOTH_SHUFFLE ; $53 + const DUEL_ANIM_UNUSED_54 ; $54 + const DUEL_ANIM_BOTH_DRAW ; $55 + const DUEL_ANIM_PLAYER_DRAW ; $56 + const DUEL_ANIM_OPP_DRAW ; $57 + const DUEL_ANIM_COIN_SPIN ; $58 + const DUEL_ANIM_COIN_TOSS1 ; $59 + const DUEL_ANIM_COIN_TOSS2 ; $5a + const DUEL_ANIM_COIN_TAILS ; $5b + const DUEL_ANIM_COIN_HEADS ; $5c + const DUEL_ANIM_DUEL_WIN ; $5d + const DUEL_ANIM_DUEL_LOSS ; $5e + const DUEL_ANIM_DUEL_DRAW ; $5f + const DUEL_ANIM_UNUSED_60 ; $60 + +DEF NUM_REGULAR_DUEL_ANIMS EQU const_value + +; Animation duel screen constants (see wDuelAnimationScreen) + const_def + const DUEL_ANIM_SCREEN_MAIN_SCENE + const DUEL_ANIM_SCREEN_PLAYER_PLAY_AREA + const DUEL_ANIM_SCREEN_OPP_PLAY_AREA diff --git a/src/constants/deck_constants.asm b/src/constants/deck_constants.asm index cf8d751..104e2a9 100644 --- a/src/constants/deck_constants.asm +++ b/src/constants/deck_constants.asm @@ -1,6 +1,6 @@ MACRO deck_const - IF const_value >= 3 - DEF \1_ID EQU const_value - 3 + IF const_value >= 2 + DEF \1_ID EQU const_value - 2 ENDC const \1 ENDM @@ -8,7 +8,7 @@ ENDM ; Both *_DECK and *_DECK_ID constants are defined here. ; *_DECK constants are to be used with LoadDeck and related routines. ; *_DECK_ID constants are specific to be loaded into wOpponentDeckID. -; Always, *_DECK_ID = *_DECK - 3. UNKNOWN_POISON_STORM_DECK_ID, +; Always, *_DECK_ID = *_DECK - 2. UNKNOWN_POISON_STORM_DECK_ID, ; GB1_STRANGE_PSYSHOCK_DECK_ID and UNKNOWN_SAMS_PRACTICE_DECK_ID do not exist. const_def deck_const UNKNOWN_POISON_STORM_DECK ; $00 diff --git a/src/constants/duel_constants.asm b/src/constants/duel_constants.asm index 2846c7f..6a849b0 100644 --- a/src/constants/duel_constants.asm +++ b/src/constants/duel_constants.asm @@ -1,5 +1,6 @@ DEF MAX_BENCH_POKEMON EQU 5 DEF MAX_PLAY_AREA_POKEMON EQU 6 ; arena + bench +DEF MAX_SMALL_BENCH_PLAY_AREA_POKEMON EQU 4 ; arena + bench DEF MAX_HP EQU 120 DEF HP_BAR_LENGTH EQU MAX_HP / 10 @@ -25,67 +26,68 @@ DEF DUEL_WIN EQU $0 DEF DUEL_LOSS EQU $1 ; wPlayerDuelVariables or wOpponentDuelVariables constants -DEF DUELVARS_CARD_LOCATIONS EQU $00 ; EQUS "LOW(wPlayerCardLocations)" ; 00 +DEF DUELVARS_CARD_LOCATIONS EQUS "LOW(wPlayerCardLocations)" ; 00 DEF DUELVARS_PRIZE_CARDS EQUS "LOW(wPlayerPrizeCards)" ; 3c -DEF DUELVARS_HAND EQU $42 ; EQUS "LOW(wPlayerHand)" ; 42 -DEF DUELVARS_DECK_CARDS EQU $7e ; EQUS "LOW(wPlayerDeckCards)" ; 7e -DEF DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK EQU $ba ; EQUS "LOW(wPlayerNumberOfCardsNotInDeck)" ; ba -DEF DUELVARS_ARENA_CARD EQU $bb ; EQUS "LOW(wPlayerArenaCard)" ; bb +DEF DUELVARS_HAND EQUS "LOW(wPlayerHand)" ; 42 +DEF DUELVARS_DECK_CARDS EQUS "LOW(wPlayerDeckCards)" ; 7e +DEF DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK EQUS "LOW(wPlayerNumberOfCardsNotInDeck)" ; ba +DEF DUELVARS_ARENA_CARD EQUS "LOW(wPlayerArenaCard)" ; bb DEF DUELVARS_BENCH EQUS "LOW(wPlayerBench)" ; bc -DEF DUELVARS_ARENA_CARD_FLAGS EQU $c2 ; EQUS "LOW(wPlayerArenaCardFlags)" ; c2 -DEF DUELVARS_ARENA_CARD_HP EQU $c8 ; EQUS "LOW(wPlayerArenaCardHP)" ; c8 +DEF DUELVARS_ARENA_CARD_FLAGS EQUS "LOW(wPlayerArenaCardFlags)" ; c2 +DEF DUELVARS_ARENA_CARD_HP EQUS "LOW(wPlayerArenaCardHP)" ; c8 DEF DUELVARS_BENCH1_CARD_HP EQUS "LOW(wPlayerBench1CardHP)" ; c9 DEF DUELVARS_BENCH2_CARD_HP EQUS "LOW(wPlayerBench2CardHP)" ; ca DEF DUELVARS_BENCH3_CARD_HP EQUS "LOW(wPlayerBench3CardHP)" ; cb DEF DUELVARS_BENCH4_CARD_HP EQUS "LOW(wPlayerBench4CardHP)" ; cc DEF DUELVARS_BENCH5_CARD_HP EQUS "LOW(wPlayerBench5CardHP)" ; cd -DEF DUELVARS_ARENA_CARD_STAGE EQU $ce ; EQUS "LOW(wPlayerArenaCardStage)" ; ce +DEF DUELVARS_ARENA_CARD_STAGE EQUS "LOW(wPlayerArenaCardStage)" ; ce DEF DUELVARS_BENCH1_CARD_STAGE EQUS "LOW(wPlayerBench1CardStage)" ; cf DEF DUELVARS_BENCH2_CARD_STAGE EQUS "LOW(wPlayerBench2CardStage)" ; d0 DEF DUELVARS_BENCH3_CARD_STAGE EQUS "LOW(wPlayerBench3CardStage)" ; d1 DEF DUELVARS_BENCH4_CARD_STAGE EQUS "LOW(wPlayerBench4CardStage)" ; d2 DEF DUELVARS_BENCH5_CARD_STAGE EQUS "LOW(wPlayerBench5CardStage)" ; d3 -DEF DUELVARS_ARENA_CARD_CHANGED_TYPE EQU $d4 ; EQUS "LOW(wPlayerArenaCardChangedType)" ; d4 +DEF DUELVARS_ARENA_CARD_CHANGED_TYPE EQUS "LOW(wPlayerArenaCardChangedType)" ; d4 DEF DUELVARS_BENCH1_CARD_CHANGED_COLOR EQUS "LOW(wPlayerBench1CardChangedType)" ; d5 DEF DUELVARS_BENCH2_CARD_CHANGED_COLOR EQUS "LOW(wPlayerBench2CardChangedType)" ; d6 DEF DUELVARS_BENCH3_CARD_CHANGED_COLOR EQUS "LOW(wPlayerBench3CardChangedType)" ; d7 DEF DUELVARS_BENCH4_CARD_CHANGED_COLOR EQUS "LOW(wPlayerBench4CardChangedType)" ; d8 DEF DUELVARS_BENCH5_CARD_CHANGED_COLOR EQUS "LOW(wPlayerBench5CardChangedType)" ; d9 -DEF DUELVARS_ARENA_CARD_ATTACHED_DEFENDER EQU $da ; EQUS "LOW(wPlayerArenaCardAttachedDefender)" ; da +DEF DUELVARS_ARENA_CARD_ATTACHED_DEFENDER EQUS "LOW(wPlayerArenaCardAttachedDefender)" ; da DEF DUELVARS_BENCH1_CARD_ATTACHED_DEFENDER EQUS "LOW(wPlayerBench1CardAttachedDefender)" ; db DEF DUELVARS_BENCH2_CARD_ATTACHED_DEFENDER EQUS "LOW(wPlayerBench2CardAttachedDefender)" ; dc DEF DUELVARS_BENCH3_CARD_ATTACHED_DEFENDER EQUS "LOW(wPlayerBench3CardAttachedDefender)" ; dd DEF DUELVARS_BENCH4_CARD_ATTACHED_DEFENDER EQUS "LOW(wPlayerBench4CardAttachedDefender)" ; de DEF DUELVARS_BENCH5_CARD_ATTACHED_DEFENDER EQUS "LOW(wPlayerBench5CardAttachedDefender)" ; df -DEF DUELVARS_ARENA_CARD_ATTACHED_PLUSPOWER EQU $e0 ; EQUS "LOW(wPlayerArenaCardAttachedPluspower)" ; e0 +DEF DUELVARS_ARENA_CARD_ATTACHED_PLUSPOWER EQUS "LOW(wPlayerArenaCardAttachedPluspower)" ; e0 DEF DUELVARS_BENCH1_CARD_ATTACHED_PLUSPOWER EQUS "LOW(wPlayerBench1CardAttachedPluspower)" ; e1 DEF DUELVARS_BENCH2_CARD_ATTACHED_PLUSPOWER EQUS "LOW(wPlayerBench2CardAttachedPluspower)" ; e2 DEF DUELVARS_BENCH3_CARD_ATTACHED_PLUSPOWER EQUS "LOW(wPlayerBench3CardAttachedPluspower)" ; e3 DEF DUELVARS_BENCH4_CARD_ATTACHED_PLUSPOWER EQUS "LOW(wPlayerBench4CardAttachedPluspower)" ; e4 DEF DUELVARS_BENCH5_CARD_ATTACHED_PLUSPOWER EQUS "LOW(wPlayerBench5CardAttachedPluspower)" ; e5 -DEF DUELVARS_ARENA_CARD_FOOD_COUNTERS EQU $e6 ; EQUS "LOW(wPlayerArenaCardFoodCounters)" ; e6 -DEF DUELVARS_BENCH1_CARD_FOOD_COUNTERS EQU $e7 ; EQUS "LOW(wPlayerBench1FoodCounters)" ; e7 -DEF DUELVARS_BENCH2_CARD_FOOD_COUNTERS EQU $e8 ; EQUS "LOW(wPlayerBench2FoodCounters)" ; e8 -DEF DUELVARS_BENCH3_CARD_FOOD_COUNTERS EQU $e9 ; EQUS "LOW(wPlayerBench3FoodCounters)" ; e9 -DEF DUELVARS_BENCH4_CARD_FOOD_COUNTERS EQU $ea ; EQUS "LOW(wPlayerBench4FoodCounters)" ; ea -DEF DUELVARS_BENCH5_CARD_FOOD_COUNTERS EQU $eb ; EQUS "LOW(wPlayerBench5FoodCounters)" ; eb -DEF DUELVARS_ARENA_CARD_STATUS EQU $ec ; EQUS "LOW(wPlayerArenaCardStatus)" ; f0 -DEF DUELVARS_ARENA_CARD_SUBSTATUS1 EQU $ed ; EQUS "LOW(wPlayerArenaCardSubstatus1)" ; e7 -DEF DUELVARS_ARENA_CARD_SUBSTATUS2 EQU $ee ; EQUS "LOW(wPlayerArenaCardSubstatus2)" ; e8 -DEF DUELVARS_ARENA_CARD_CHANGED_WEAKNESS EQU $ef ; EQUS "LOW(wPlayerArenaCardChangedWeakness)" ; e9 -DEF DUELVARS_ARENA_CARD_CHANGED_RESISTANCE EQU $f0 ; EQUS "LOW(wPlayerArenaCardChangedResistance)" ; ea -DEF DUELVARS_ARENA_CARD_SUBSTATUS3 EQU $f1 ; EQUS "LOW(wPlayerArenaCardSubstatus3)" ; eb -DEF DUELVARS_PRIZES EQU $f2 ; EQUS "LOW(wPlayerPrizes)" ; ec -DEF DUELVARS_NUMBER_OF_CARDS_IN_DISCARD_PILE EQU $f3 ; EQUS "LOW(wPlayerNumberOfCardsInDiscardPile)" ; ed -DEF DUELVARS_NUMBER_OF_CARDS_IN_HAND EQU $f4 ; EQUS "LOW(wPlayerNumberOfCardsInHand)" ; ee -DEF DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA EQU $f5 ; EQUS "LOW(wPlayerNumberOfPokemonInPlayArea)" ; ef -DEF DUELVARS_DUELIST_TYPE EQU $f6 ; EQUS "LOW(wPlayerDuelistType)" ; f1 -DEF DUELVARS_ARENA_CARD_DISABLED_ATTACK_INDEX EQU $f7 ; EQUS "LOW(wPlayerArenaCardDisabledAttackIndex)" ; f2 -DEF DUELVARS_ARENA_CARD_LAST_TURN_DAMAGE EQUS "LOW(wPlayerArenaCardLastTurnDamage)" ; f3 -DEF DUELVARS_ARENA_CARD_LAST_TURN_STATUS EQUS "LOW(wPlayerArenaCardLastTurnStatus)" ; f5 -DEF DUELVARS_ARENA_CARD_LAST_TURN_SUBSTATUS2 EQUS "LOW(wPlayerArenaCardLastTurnSubstatus2)" ; f6 -DEF DUELVARS_ARENA_CARD_LAST_TURN_CHANGE_WEAK EQUS "LOW(wPlayerArenaCardLastTurnChangeWeak)" ; f7 -DEF DUELVARS_ARENA_CARD_LAST_TURN_EFFECT EQUS "LOW(wPlayerArenaCardLastTurnEffect)" ; f8 +DEF DUELVARS_ARENA_CARD_FOOD_COUNTERS EQUS "LOW(wPlayerArenaCardFoodCounters)" ; e6 +DEF DUELVARS_BENCH1_CARD_FOOD_COUNTERS EQUS "LOW(wPlayerBench1FoodCounters)" ; e7 +DEF DUELVARS_BENCH2_CARD_FOOD_COUNTERS EQUS "LOW(wPlayerBench2FoodCounters)" ; e8 +DEF DUELVARS_BENCH3_CARD_FOOD_COUNTERS EQUS "LOW(wPlayerBench3FoodCounters)" ; e9 +DEF DUELVARS_BENCH4_CARD_FOOD_COUNTERS EQUS "LOW(wPlayerBench4FoodCounters)" ; ea +DEF DUELVARS_BENCH5_CARD_FOOD_COUNTERS EQUS "LOW(wPlayerBench5FoodCounters)" ; eb +DEF DUELVARS_ARENA_CARD_STATUS EQUS "LOW(wPlayerArenaCardStatus)" ; ec +DEF DUELVARS_ARENA_CARD_SUBSTATUS1 EQUS "LOW(wPlayerArenaCardSubstatus1)" ; ed +DEF DUELVARS_ARENA_CARD_SUBSTATUS2 EQUS "LOW(wPlayerArenaCardSubstatus2)" ; ee +DEF DUELVARS_ARENA_CARD_CHANGED_WEAKNESS EQUS "LOW(wPlayerArenaCardChangedWeakness)" ; ef +DEF DUELVARS_ARENA_CARD_CHANGED_RESISTANCE EQUS "LOW(wPlayerArenaCardChangedResistance)" ; f0 +DEF DUELVARS_ARENA_CARD_SUBSTATUS3 EQUS "LOW(wPlayerArenaCardSubstatus3)" ; f1 +DEF DUELVARS_PRIZES EQUS "LOW(wPlayerPrizes)" ; f2 +DEF DUELVARS_NUMBER_OF_CARDS_IN_DISCARD_PILE EQUS "LOW(wPlayerNumberOfCardsInDiscardPile)" ; f3 +DEF DUELVARS_NUMBER_OF_CARDS_IN_HAND EQUS "LOW(wPlayerNumberOfCardsInHand)" ; f4 +DEF DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA EQUS "LOW(wPlayerNumberOfPokemonInPlayArea)" ; f5 +DEF DUELVARS_DUELIST_TYPE EQUS "LOW(wPlayerDuelistType)" ; f6 +DEF DUELVARS_ARENA_CARD_DISABLED_ATTACK_INDEX EQUS "LOW(wPlayerArenaCardDisabledAttackIndex)" ; f7 +DEF DUELVARS_ARENA_CARD_LAST_TURN_DAMAGE EQUS "LOW(wPlayerArenaCardLastTurnDamage)" ; f8 +DEF DUELVARS_ARENA_CARD_LAST_TURN_STATUS EQUS "LOW(wPlayerArenaCardLastTurnStatus)" ; fa +DEF DUELVARS_ARENA_CARD_LAST_TURN_SUBSTATUS2 EQUS "LOW(wPlayerArenaCardLastTurnSubstatus2)" ; fb +DEF DUELVARS_ARENA_CARD_LAST_TURN_CHANGE_WEAK EQUS "LOW(wPlayerArenaCardLastTurnChangeWeak)" ; fc +DEF DUELVARS_ARENA_CARD_LAST_TURN_EFFECT EQUS "LOW(wPlayerArenaCardLastTurnEffect)" ; fd +DEF DUELVARS_UNK_FE EQUS "LOW(wPlayerUnkfe)" ; fe ; card location constants (DUELVARS_CARD_LOCATIONS) DEF CARD_LOCATION_DECK EQU $00 @@ -140,41 +142,56 @@ DEF DBLPSN_DAMAGE EQU 20 ; substatus conditions (DUELVARS_ARENA_CARD_SUBSTATUS*) ; SUBSTATUS1 are checked on a defending Pokemon -DEF SUBSTATUS1_AGILITY EQU $0c -DEF SUBSTATUS1_FLY EQU $0d -DEF SUBSTATUS1_HARDEN EQU $0e -DEF SUBSTATUS1_NO_DAMAGE_STIFFEN EQU $0f -DEF SUBSTATUS1_NO_DAMAGE_10 EQU $10 -DEF SUBSTATUS1_NO_DAMAGE_11 EQU $11 -DEF SUBSTATUS1_REDUCE_BY_20 EQU $13 -DEF SUBSTATUS1_BARRIER EQU $14 -DEF SUBSTATUS1_HALVE_DAMAGE EQU $15 -DEF SUBSTATUS1_DESTINY_BOND EQU $16 -DEF SUBSTATUS1_NO_DAMAGE_17 EQU $17 -DEF SUBSTATUS1_NEXT_TURN_DOUBLE_DAMAGE EQU $19 -DEF SUBSTATUS1_REDUCE_BY_10 EQU $1e +DEF SUBSTATUS1_UNK_0D EQU $0d +DEF SUBSTATUS1_AGILITY EQU $11 +DEF SUBSTATUS1_FLY EQU $12 +DEF SUBSTATUS1_HARDEN EQU $13 +DEF SUBSTATUS1_NO_DAMAGE_STIFFEN EQU $14 +DEF SUBSTATUS1_NO_DAMAGE_10 EQU $15 +DEF SUBSTATUS1_NO_DAMAGE_11 EQU $16 +DEF SUBSTATUS1_REDUCE_BY_20 EQU $18 +DEF SUBSTATUS1_BARRIER EQU $19 +DEF SUBSTATUS1_HALVE_DAMAGE EQU $1a +DEF SUBSTATUS1_DESTINY_BOND EQU $1b +DEF SUBSTATUS1_NO_DAMAGE_17 EQU $1c +DEF SUBSTATUS1_NEXT_TURN_DOUBLE_DAMAGE EQU $1e +DEF SUBSTATUS1_REDUCE_BY_10 EQU $23 +DEF SUBSTATUS1_HIDE EQU $2a +DEF SUBSTATUS1_USED_DRILL_DIVE EQU $30 ; SUBSTATUS2 are checked on an attacking Pokemon -DEF SUBSTATUS2_SMOKESCREEN EQU $01 -DEF SUBSTATUS2_SAND_ATTACK EQU $02 -DEF SUBSTATUS2_REDUCE_BY_20 EQU $03 -DEF SUBSTATUS2_AMNESIA EQU $04 -DEF SUBSTATUS2_TAIL_WAG EQU $05 -DEF SUBSTATUS2_LEER EQU $06 -DEF SUBSTATUS2_POUNCE EQU $07 -DEF SUBSTATUS2_CONVERSION2 EQU $08 -DEF SUBSTATUS2_UNABLE_RETREAT EQU $09 -DEF SUBSTATUS2_BONE_ATTACK EQU $0b -DEF SUBSTATUS2_GROWL EQU $12 +DEF SUBSTATUS2_SMOKESCREEN EQU $01 +DEF SUBSTATUS2_SAND_ATTACK EQU $02 +DEF SUBSTATUS2_REDUCE_BY_20 EQU $03 +DEF SUBSTATUS2_AMNESIA EQU $04 +DEF SUBSTATUS2_TAIL_WAG EQU $05 +DEF SUBSTATUS2_LEER EQU $06 +DEF SUBSTATUS2_POUNCE EQU $07 +DEF SUBSTATUS2_CONVERSION2 EQU $08 +DEF SUBSTATUS2_ACID EQU $09 +DEF SUBSTATUS2_BONE_ATTACK EQU $0b +DEF SUBSTATUS2_ROCK_SEAL EQU $0e +DEF SUBSTATUS2_DISABLE EQU $0f +DEF SUBSTATUS2_GROWL EQU $17 -DEF SUBSTATUS3_THIS_TURN_DOUBLE_DAMAGE EQU 0 -DEF SUBSTATUS3_HEADACHE EQU 1 +DEF SUBSTATUS3_THIS_TURN_DOUBLE_DAMAGE_F EQU 0 +DEF SUBSTATUS3_HEADACHE_F EQU 2 +DEF SUBSTATUS3_SPOOKIFY_F EQU 3 +DEF SUBSTATUS3_UNK_4_F EQU 4 +DEF SUBSTATUS3_UNK_5_F EQU 5 +DEF SUBSTATUS3_UNK_6_F EQU 6 +DEF SUBSTATUS3_PERPLEX_F EQU 7 ; DUELVARS_ARENA_CARD_FLAGS constants +DEF PLAY_AREA_FLAG_UNK_1_F EQU 1 +DEF PLAY_AREA_FLAG_UNK_2_F EQU 2 +DEF PLAY_AREA_FLAG_UNK_3_F EQU 3 +DEF AFFECTED_BY_STARE_F EQU 4 DEF USED_PKMN_POWER_THIS_TURN_F EQU 5 DEF USED_LEEK_SLAP_THIS_DUEL_F EQU 6 DEF CAN_EVOLVE_THIS_TURN_F EQU 7 +DEF AFFECTED_BY_STARE EQU 1 << AFFECTED_BY_STARE_F DEF USED_PKMN_POWER_THIS_TURN EQU 1 << USED_PKMN_POWER_THIS_TURN_F DEF USED_LEEK_SLAP_THIS_DUEL EQU 1 << USED_LEEK_SLAP_THIS_DUEL_F DEF CAN_EVOLVE_THIS_TURN EQU 1 << CAN_EVOLVE_THIS_TURN_F @@ -243,12 +260,18 @@ DEF NO_DAMAGE_OR_EFFECT_NSHIELD EQU $05 const OPPACTION_USE_METRONOME_ATTACK ; $15 const OPPACTION_6B15 ; $16 const OPPACTION_DUEL_MAIN_SCENE ; $17 + const OPPACTION_UNK_18 ; $18 + const OPPACTION_UNK_19 ; $19 + const OPPACTION_UNK_1A ; $1a + const OPPACTION_UNK_1B ; $1b + const OPPACTION_UNK_1C ; $1c +DEF NUM_OPP_ACTIONS EQU const_value ; constants for PracticeDuelActionTable entries const_def 1 const PRACTICEDUEL_DRAW_SEVEN_CARDS - const PRACTICEDUEL_PLAY_GOLDEEN - const PRACTICEDUEL_PUT_STARYU_IN_BENCH + const PRACTICEDUEL_PLAY_DIGLETT + const PRACTICEDUEL_PUT_NIDORANM_IN_BENCH const PRACTICEDUEL_VERIFY_INITIAL_PLAY const PRACTICEDUEL_DONE_PUTTING_ON_BENCH const PRACTICEDUEL_PRINT_TURN_INSTRUCTIONS @@ -281,14 +304,14 @@ DEF PRIZES_6 EQU $06 ; special rule constants, stored in wSpecialRule const_def - const NO_RULES ; $0 - const CHLOROPHYLL ; $1 - const THUNDER_CHARGE ; $2 - const FLAME_ARMOR ; $3 - const SMALL_BENCH ; $4 - const RUNNING_WATER ; $5 - const EARTH_POWER ; $6 - const LOW_RESISTANCE ; $7 - const ENERGY_RETURN ; $8 - const TOUGH_ESCAPE ; $9 - const BLACK_HOLE ; $a + const NO_SPECIAL_RULE ; $0 + const CHLOROPHYLL ; $1 + const THUNDER_CHARGE ; $2 + const FLAME_ARMOR ; $3 + const SMALL_BENCH ; $4 + const RUNNING_WATER ; $5 + const EARTH_POWER ; $6 + const LOW_RESISTANCE ; $7 + const ENERGY_RETURN ; $8 + const TOUGH_ESCAPE ; $9 + const BLACK_HOLE ; $a diff --git a/src/constants/duel_interface_constants.asm b/src/constants/duel_interface_constants.asm index 5951ea0..833d106 100644 --- a/src/constants/duel_interface_constants.asm +++ b/src/constants/duel_interface_constants.asm @@ -10,6 +10,12 @@ DEF CARDPAGE_ENERGY_2 EQU $0a DEF CARDPAGE_TRAINER_1 EQU $0d DEF CARDPAGE_TRAINER_2 EQU $0e +; wAttackPageNumber constants +DEF ATTACKPAGE_ATTACK1_1 EQU $00 +DEF ATTACKPAGE_ATTACK1_2 EQU $01 +DEF ATTACKPAGE_ATTACK2_1 EQU $02 +DEF ATTACKPAGE_ATTACK2_2 EQU $03 + ; wCardPageType constants DEF CARDPAGETYPE_NOT_PLAY_AREA EQU $00 DEF CARDPAGETYPE_PLAY_AREA EQU $01 @@ -18,3 +24,29 @@ DEF CARDPAGETYPE_PLAY_AREA EQU $01 DEF HEADER_TRAINER EQU $00 DEF HEADER_ENERGY EQU $01 DEF HEADER_POKEMON EQU $02 + +; Box message id's + const_def + const BOXMSG_PLAYERS_TURN + const BOXMSG_OPPONENTS_TURN + const BOXMSG_BETWEEN_TURNS + const BOXMSG_DECISION + const BOXMSG_BENCH_POKEMON + const BOXMSG_ARENA_POKEMON + const BOXMSG_COIN_TOSS + +; wDuelDisplayedScreen constants +DEF DUEL_MAIN_SCENE EQU $01 +DEF PLAY_AREA_CARD_LIST EQU $02 +DEF UNKNOWN_SCREEN_4 EQU $04 ; used for some animations +DEF UNKNOWN_SCREEN_5 EQU $05 ; used for some animations +DEF COIN_TOSS EQU $06 +DEF DRAW_CARDS EQU $07 +DEF LARGE_CARD_PICTURE EQU $08 +DEF SHUFFLE_DECK EQU $09 +DEF CHECK_PLAY_AREA EQU $0a + +; wCardListItemSelectionMenuType constants +;NONE EQU $00 +DEF PLAY_CHECK EQU $01 +DEF SELECT_CHECK EQU $02 diff --git a/src/constants/npc_constants.asm b/src/constants/npc_constants.asm new file mode 100644 index 0000000..ba60211 --- /dev/null +++ b/src/constants/npc_constants.asm @@ -0,0 +1,98 @@ + const_def + const NPC_MARK ; $00 + const NPC_MINT ; $01 + const NPC_MARK_LINK ; $02 + const NPC_MINT_LINK ; $03 + const NPC_RONALD ; $04 + const NPC_SAM ; $05 + const NPC_AARON ; $06 + const NPC_ISHIHARA ; $07 + const NPC_IMAKUNI_BLACK ; $08 + const NPC_IMAKUNI_RED ; $09 + const NPC_ISAAC ; $0a + const NPC_JENNIFER ; $0b + const NPC_NICHOLAS ; $0c + const NPC_BRANDON ; $0d + const NPC_MURRAY ; $0e + const NPC_STEPHANIE ; $0f + const NPC_DANIEL ; $10 + const NPC_ROBERT ; $11 + const NPC_GENE ; $12 + const NPC_MATTHEW ; $13 + const NPC_RYAN ; $14 + const NPC_ANDREW ; $15 + const NPC_MITCH ; $16 + const NPC_MICHAEL ; $17 + const NPC_CHRIS ; $18 + const NPC_JESSICA ; $19 + const NPC_NIKKI ; $1a + const NPC_BRITTANY ; $1b + const NPC_KRISTIN ; $1c + const NPC_HEATHER ; $1d + const NPC_RICK ; $1e + const NPC_JOSEPH ; $1f + const NPC_DAVID ; $20 + const NPC_ERIK ; $21 + const NPC_AMY ; $22 + const NPC_JOSHUA ; $23 + const NPC_SARA ; $24 + const NPC_AMANDA ; $25 + const NPC_KEN ; $26 + const NPC_JOHN ; $27 + const NPC_ADAM ; $28 + const NPC_JONATHAN ; $29 + const NPC_COURTNEY ; $2a + const NPC_STEVE ; $2b + const NPC_JACK ; $2c + const NPC_ROD ; $2d + const NPC_EIJI ; $2e + const NPC_MAGICIAN ; $2f + const NPC_YUI ; $30 + const NPC_TOSHIRON ; $31 + const NPC_PIERROT ; $32 + const NPC_ANNA ; $33 + const NPC_DEE ; $34 + const NPC_MASQUERADE ; $35 + const NPC_PAWN ; $36 + const NPC_KNIGHT ; $37 + const NPC_BISHOP ; $38 + const NPC_ROOK ; $39 + const NPC_QUEEN ; $3a + const NPC_GR_1 ; $3b + const NPC_GR_2 ; $3c + const NPC_GR_3 ; $3d + const NPC_GR_4 ; $3e + const NPC_MIDORI ; $3f + const NPC_YUUTA ; $40 + const NPC_MIYUKI ; $41 + const NPC_MORINO ; $42 + const NPC_RENNA ; $43 + const NPC_ICHIKAWA ; $44 + const NPC_CATHERINE ; $45 + const NPC_TAP ; $46 + const NPC_JES ; $47 + const NPC_YUKI ; $48 + const NPC_SHOKO ; $49 + const NPC_HIDERO ; $4a + const NPC_MIYAJIMA ; $4b + const NPC_SENTA ; $4c + const NPC_AIRA ; $4d + const NPC_KANOKO ; $4e + const NPC_GODA ; $4f + const NPC_GRACE ; $50 + const NPC_KAMIYA ; $51 + const NPC_MIWA ; $52 + const NPC_KEVIN ; $53 + const NPC_YOSUKE ; $54 + const NPC_RYOKO ; $55 + const NPC_MAMI ; $56 + const NPC_NISHIJIMA ; $57 + const NPC_ISHII ; $58 + const NPC_SAMEJIMA ; $59 + const NPC_KANZAKI ; $5a + const NPC_RUI ; $5b + const NPC_BIRURITCHI ; $5c + const NPC_GR_X ; $5d + const NPC_TOBI_CHAN ; $5e + const NPC_DR_MASON ; $5f +DEF NUM_NPC_IDS EQU const_value diff --git a/src/constants/portrait_constants.asm b/src/constants/portrait_constants.asm index 665cd40..d22c2fb 100644 --- a/src/constants/portrait_constants.asm +++ b/src/constants/portrait_constants.asm @@ -1,100 +1,100 @@ const_def - const PORTRAIT_00 ; $00 - const PORTRAIT_01 ; $01 - const PORTRAIT_02 ; $02 - const PORTRAIT_03 ; $03 - const PORTRAIT_04 ; $04 - const PORTRAIT_05 ; $05 - const PORTRAIT_06 ; $06 - const PORTRAIT_07 ; $07 - const PORTRAIT_08 ; $08 - const PORTRAIT_09 ; $09 - const PORTRAIT_0A ; $0a - const PORTRAIT_0B ; $0b - const PORTRAIT_0C ; $0c - const PORTRAIT_0D ; $0d - const PORTRAIT_0E ; $0e - const PORTRAIT_0F ; $0f - const PORTRAIT_10 ; $10 - const PORTRAIT_11 ; $11 - const PORTRAIT_12 ; $12 - const PORTRAIT_13 ; $13 - const PORTRAIT_14 ; $14 - const PORTRAIT_15 ; $15 - const PORTRAIT_16 ; $16 - const PORTRAIT_17 ; $17 - const PORTRAIT_18 ; $18 - const PORTRAIT_19 ; $19 - const PORTRAIT_1A ; $1a - const PORTRAIT_1B ; $1b - const PORTRAIT_1C ; $1c - const PORTRAIT_1D ; $1d - const PORTRAIT_1E ; $1e - const PORTRAIT_1F ; $1f - const PORTRAIT_20 ; $20 - const PORTRAIT_21 ; $21 - const PORTRAIT_22 ; $22 - const PORTRAIT_23 ; $23 - const PORTRAIT_24 ; $24 - const PORTRAIT_25 ; $25 - const PORTRAIT_26 ; $26 - const PORTRAIT_27 ; $27 - const PORTRAIT_28 ; $28 - const PORTRAIT_29 ; $29 - const PORTRAIT_2A ; $2a - const PORTRAIT_2B ; $2b - const PORTRAIT_2C ; $2c - const PORTRAIT_2D ; $2d - const PORTRAIT_2E ; $2e - const PORTRAIT_2F ; $2f - const PORTRAIT_30 ; $30 - const PORTRAIT_31 ; $31 - const PORTRAIT_32 ; $32 - const PORTRAIT_33 ; $33 - const PORTRAIT_34 ; $34 - const PORTRAIT_35 ; $35 - const PORTRAIT_36 ; $36 - const PORTRAIT_37 ; $37 - const PORTRAIT_38 ; $38 - const PORTRAIT_39 ; $39 - const PORTRAIT_3A ; $3a - const PORTRAIT_3B ; $3b - const PORTRAIT_3C ; $3c - const PORTRAIT_3D ; $3d - const PORTRAIT_3E ; $3e - const PORTRAIT_3F ; $3f - const PORTRAIT_40 ; $40 - const PORTRAIT_41 ; $41 - const PORTRAIT_42 ; $42 - const PORTRAIT_43 ; $43 - const PORTRAIT_44 ; $44 - const PORTRAIT_45 ; $45 - const PORTRAIT_46 ; $46 - const PORTRAIT_47 ; $47 - const PORTRAIT_48 ; $48 - const PORTRAIT_49 ; $49 - const PORTRAIT_4A ; $4a - const PORTRAIT_4B ; $4b - const PORTRAIT_4C ; $4c - const PORTRAIT_4D ; $4d - const PORTRAIT_4E ; $4e - const PORTRAIT_4F ; $4f - const PORTRAIT_50 ; $50 - const PORTRAIT_51 ; $51 - const PORTRAIT_52 ; $52 - const PORTRAIT_53 ; $53 - const PORTRAIT_54 ; $54 - const PORTRAIT_55 ; $55 - const PORTRAIT_56 ; $56 - const PORTRAIT_57 ; $57 - const PORTRAIT_58 ; $58 - const PORTRAIT_59 ; $59 - const PORTRAIT_5A ; $5a - const PORTRAIT_5B ; $5b - const PORTRAIT_5C ; $5c - const PORTRAIT_5D ; $5d - const PORTRAIT_5E ; $5e - const PORTRAIT_5F ; $5f + const PORTRAIT_MARK ; $00 + const PORTRAIT_MINT ; $01 + const PORTRAIT_MARK_LINK ; $02 + const PORTRAIT_MINT_LINK ; $03 + const PORTRAIT_RONALD ; $04 + const PORTRAIT_SAM ; $05 + const PORTRAIT_AARON ; $06 + const PORTRAIT_ISHIHARA ; $07 + const PORTRAIT_ISAAC ; $08 + const PORTRAIT_JENNIFER ; $09 + const PORTRAIT_NICHOLAS ; $0a + const PORTRAIT_BRANDON ; $0b + const PORTRAIT_MURRAY ; $0c + const PORTRAIT_STEPHANIE ; $0d + const PORTRAIT_DANIEL ; $0e + const PORTRAIT_ROBERT ; $0f + const PORTRAIT_GENE ; $10 + const PORTRAIT_MATTHEW ; $11 + const PORTRAIT_RYAN ; $12 + const PORTRAIT_ANDREW ; $13 + const PORTRAIT_MITCH ; $14 + const PORTRAIT_MICHAEL ; $15 + const PORTRAIT_CHRIS ; $16 + const PORTRAIT_JESSICA ; $17 + const PORTRAIT_NIKKI ; $18 + const PORTRAIT_BRITTANY ; $19 + const PORTRAIT_KRISTIN ; $1a + const PORTRAIT_HEATHER ; $1b + const PORTRAIT_RICK ; $1c + const PORTRAIT_JOSEPH ; $1d + const PORTRAIT_DAVID ; $1e + const PORTRAIT_ERIK ; $1f + const PORTRAIT_AMY ; $20 + const PORTRAIT_JOSHUA ; $21 + const PORTRAIT_SARA ; $22 + const PORTRAIT_AMANDA ; $23 + const PORTRAIT_KEN ; $24 + const PORTRAIT_JOHN ; $25 + const PORTRAIT_ADAM ; $26 + const PORTRAIT_JONATHAN ; $27 + const PORTRAIT_COURTNEY ; $28 + const PORTRAIT_STEVE ; $29 + const PORTRAIT_JACK ; $2a + const PORTRAIT_ROD ; $2b + const PORTRAIT_EIJI ; $2c + const PORTRAIT_MAGICIAN ; $2d + const PORTRAIT_YUI ; $2e + const PORTRAIT_TOSHIRON ; $2f + const PORTRAIT_PIERROT ; $30 + const PORTRAIT_ANNA ; $31 + const PORTRAIT_DEE ; $32 + const PORTRAIT_MASQUERADE ; $33 + const PORTRAIT_PAWN ; $34 + const PORTRAIT_KNIGHT ; $35 + const PORTRAIT_BISHOP ; $36 + const PORTRAIT_ROOK ; $37 + const PORTRAIT_QUEEN ; $38 + const PORTRAIT_GR_1 ; $39 + const PORTRAIT_GR_2 ; $3a + const PORTRAIT_GR_3 ; $3b + const PORTRAIT_GR_4 ; $3c + const PORTRAIT_MIDORI ; $3d + const PORTRAIT_YUUTA ; $3e + const PORTRAIT_MIYUKI ; $3f + const PORTRAIT_MORINO ; $40 + const PORTRAIT_RENNA ; $41 + const PORTRAIT_ICHIKAWA ; $42 + const PORTRAIT_CATHERINE ; $43 + const PORTRAIT_TAP ; $44 + const PORTRAIT_JES ; $45 + const PORTRAIT_YUKI ; $46 + const PORTRAIT_SHOKO ; $47 + const PORTRAIT_HIDERO ; $48 + const PORTRAIT_MIYAJIMA ; $49 + const PORTRAIT_SENTA ; $4a + const PORTRAIT_AIRA ; $4b + const PORTRAIT_KANOKO ; $4c + const PORTRAIT_GODA ; $4d + const PORTRAIT_GRACE ; $4e + const PORTRAIT_KAMIYA ; $4f + const PORTRAIT_MIWA ; $50 + const PORTRAIT_KEVIN ; $51 + const PORTRAIT_YOSUKE ; $52 + const PORTRAIT_RYOKO ; $53 + const PORTRAIT_MAMI ; $54 + const PORTRAIT_NISHIJIMA ; $55 + const PORTRAIT_ISHII ; $56 + const PORTRAIT_SAMEJIMA ; $57 + const PORTRAIT_KANZAKI ; $58 + const PORTRAIT_RUI ; $59 + const PORTRAIT_BIRURITCHI ; $5a + const PORTRAIT_GR_X ; $5b + const PORTRAIT_TOBI_CHAN ; $5c + const PORTRAIT_DR_MASON ; $5d + const PORTRAIT_IMAKUNI_BLACK ; $5e + const PORTRAIT_IMAKUNI_RED ; $5f ; each portrait has 3 variants const_def diff --git a/src/constants/var_constants.asm b/src/constants/var_constants.asm index ea0cf20..cdb9570 100644 --- a/src/constants/var_constants.asm +++ b/src/constants/var_constants.asm @@ -59,6 +59,6 @@ const VAR_39 ; $39 const VAR_3A ; $3a const VAR_3B ; $3b - const VAR_3C ; $3c + const VAR_NPC_DECK_ID ; $3c const VAR_3D ; $3d const VAR_3E ; $3e diff --git a/src/data/credits.asm b/src/data/credits.asm index 6575fbe..717886c 100644 --- a/src/data/credits.asm +++ b/src/data/credits.asm @@ -19,10 +19,10 @@ Credits: credits_wait 20 credits_draw_box 0, 0, 20, 18 - credits_show_portrait $07, 2, 6, PORTRAITVARIANT_NORMAL + credits_show_portrait NPC_ISHIHARA, 2, 6, PORTRAITVARIANT_NORMAL credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 - credits_show_portrait $07, 2, 6, PORTRAITVARIANT_HAPPY + credits_show_portrait NPC_ISHIHARA, 2, 6, PORTRAITVARIANT_HAPPY credits_print_header 7, 2, 2, Text07aa credits_print_text 10, 6, Text07ab credits_fade_in CREDITS_FADE_HEADER_TEXT, $05 @@ -33,10 +33,10 @@ Credits: credits_wait 20 credits_draw_box 0, 0, 20, 18 - credits_show_portrait $06, 2, 6, PORTRAITVARIANT_NORMAL + credits_show_portrait NPC_AARON, 2, 6, PORTRAITVARIANT_NORMAL credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 - credits_show_portrait $06, 2, 6, PORTRAITVARIANT_HAPPY + credits_show_portrait NPC_AARON, 2, 6, PORTRAITVARIANT_HAPPY credits_print_header 7, 2, 2, Text07ac credits_print_text 10, 8, Text07ad credits_fade_in CREDITS_FADE_HEADER_TEXT, $05 @@ -47,10 +47,10 @@ Credits: credits_wait 20 credits_draw_box 0, 0, 20, 18 - credits_show_portrait $51, 2, 6, PORTRAITVARIANT_NORMAL + credits_show_portrait NPC_KAMIYA, 2, 6, PORTRAITVARIANT_NORMAL credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 - credits_show_portrait $51, 2, 6, PORTRAITVARIANT_HAPPY + credits_show_portrait NPC_KAMIYA, 2, 6, PORTRAITVARIANT_HAPPY credits_print_header 4, 2, 2, Text07ae credits_print_text 10, 8, Text07af credits_fade_in CREDITS_FADE_HEADER_TEXT, $05 @@ -61,10 +61,10 @@ Credits: credits_wait 20 credits_draw_box 0, 0, 20, 18 - credits_show_portrait $46, 2, 6, PORTRAITVARIANT_HAPPY + credits_show_portrait NPC_TAP, 2, 6, PORTRAITVARIANT_HAPPY credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 - credits_show_portrait $46, 2, 6, PORTRAITVARIANT_HAPPY + credits_show_portrait NPC_TAP, 2, 6, PORTRAITVARIANT_HAPPY credits_print_header 5, 2, 2, Text07b0 credits_print_text 10, 8, Text07b1 credits_fade_in CREDITS_FADE_HEADER_TEXT, $05 @@ -75,7 +75,7 @@ Credits: credits_wait 20 credits_draw_box 0, 0, 20, 18 - credits_show_portrait $5e, 2, 6, PORTRAITVARIANT_NORMAL + credits_show_portrait NPC_TOBI_CHAN, 2, 6, PORTRAITVARIANT_NORMAL credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 credits_print_header 5, 2, 2, Text07b2 @@ -215,7 +215,7 @@ Credits: credits_wait 20 credits_draw_box 0, 0, 20, 18 - credits_show_portrait $26, 2, 6, PORTRAITVARIANT_NORMAL + credits_show_portrait NPC_KEN, 2, 6, PORTRAITVARIANT_NORMAL credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 credits_print_header 10, 2, 2, Text07c5 @@ -229,7 +229,7 @@ Credits: credits_draw_box 2, 6, 6, 6 credits_draw_box 10, 6, 10, 6 - credits_show_portrait $5f, 2, 6, PORTRAITVARIANT_HAPPY + credits_show_portrait NPC_DR_MASON, 2, 6, PORTRAITVARIANT_HAPPY credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 credits_print_text 10, 8, Text07c7 @@ -242,7 +242,7 @@ Credits: credits_draw_box 2, 6, 6, 6 credits_draw_box 10, 6, 10, 6 - credits_show_portrait $0e, 2, 6, PORTRAITVARIANT_NORMAL + credits_show_portrait NPC_MURRAY, 2, 6, PORTRAITVARIANT_NORMAL credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 credits_print_text 10, 8, Text07c8 @@ -332,7 +332,7 @@ Credits: credits_wait 20 credits_draw_box 0, 0, 20, 18 - credits_show_portrait $09, 2, 6, PORTRAITVARIANT_SAD + credits_show_portrait NPC_IMAKUNI_RED, 2, 6, PORTRAITVARIANT_SAD credits_fade_in CREDITS_FADE_BACKGROUND, $0a credits_wait 60 credits_print_header 12, 2, 2, Text07d0 diff --git a/src/data/duel/practice_text.asm b/src/data/duel/practice_text.asm new file mode 100644 index 0000000..cfa3791 --- /dev/null +++ b/src/data/duel/practice_text.asm @@ -0,0 +1,53 @@ +PracticeDuelTextPointerTable: + dw PracticeDuelText_Turn1 + dw PracticeDuelText_Turn2 + dw PracticeDuelText_Turn3 + dw PracticeDuelText_Turn4 + dw PracticeDuelText_Turn5 + dw PracticeDuelText_Turn6 + +MACRO practicetext + db \1 ; Y coord to place the point-by-point instruction + tx \2 ; Dr. Mason's instruction + tx \3 ; static point-by-point instruction +ENDM + +PracticeDuelText_Turn1: + practicetext 2, Text0502, Text04ff + practicetext 5, Text0503, Text0500 + practicetext 8, Text0504, Text0501 + db $00 + +PracticeDuelText_Turn2: + practicetext 2, Text050a, Text0508 + practicetext 5, Text050b, Text0509 + db $00 + +PracticeDuelText_Turn3: + practicetext 2, Text050f, Text050c + practicetext 5, Text0510, Text050d + practicetext 8, Text0511, Text050e + db $00 + +PracticeDuelText_Turn4: + practicetext 2, Text0515, Text0512 + practicetext 5, Text0516, Text0513 + practicetext 8, Text0517, Text0514 + db $00 + +PracticeDuelText_Turn5: + practicetext 2, Text0520, Text051d + practicetext 5, Text0521, Text051e + practicetext 8, Text0522, Text051f + db $00 + +PracticeDuelText_Turn6: + practicetext 2, Text0526, Text0523 + practicetext 5, Text0527, Text0524 + practicetext 8, Text0528, Text0525 + db $00 + +PracticeDuelText_SamTurn4: + practicetext 2, Text051a, Text0518 + practicetext 6, Text051b, Text0519 + db $00 diff --git a/src/engine/bank01.asm b/src/engine/bank01.asm index 997f7e1..3ee017d 100644 --- a/src/engine/bank01.asm +++ b/src/engine/bank01.asm @@ -1,6 +1,278 @@ -SECTION "Bank 1@4278", ROMX[$4278], BANK[$1] +SECTION "Bank 1@4074", ROMX[$4074], BANK[$1] -Func_4278: +StartDuelFromSRAM: + call SetupDuel + farcall Func_24048 + ldtx hl, Text00f1 + jr c, .corrupted + ld hl, sp+$00 + ld a, l + ld [wDuelReturnAddress + 0], a + ld a, h + ld [wDuelReturnAddress + 1], a + call ClearJoypad + ld a, [wDuelTheme] + call PlaySong + xor a + ld [wDuelFinished], a + call DuelMainInterface + jp MainDuelLoop.between_turns +.corrupted + call DrawWideTextBox_WaitForInput + call ResetSerial + scf + ret + +; this function begins the duel after the opponent's graphics, name and deck have been introduced +; loads both player's decks and sets up the variables and resources required to begin a duel. +StartDuel_VSAIOpp: + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + ld a, DUELIST_TYPE_PLAYER + ld [wPlayerDuelistType], a + ld a, [wNPCDuelDeckID] + ld [wOpponentDeckID], a + call LoadPlayerDeck + call SwapTurn + call LoadOpponentDeck + call SwapTurn + jr StartDuel + + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + ld a, DUELIST_TYPE_PLAYER + ld [wPlayerDuelistType], a + ld [wOpponentDuelistType], a + ld a, $17 + ld [wcc18], a + ld a, $06 + ld [wcc15], a + xor a + ld [wcc19], a + ld a, NUM_NPC_IDS + call Random + ld [wOpponentNPCID], a + ld hl, wOpponentName + xor a + ld [hli], a + ld [hl], a + ld [wOpponentDeckID], a + ld [wSpecialRule], a + ld [wIsPracticeDuel], a +; fallthrough + +StartDuel: + ld hl, sp+$00 + ld a, l + ld [wDuelReturnAddress], a + ld a, h + ld [wDuelReturnAddress + 1], a + xor a + ld [wCurrentDuelMenuItem], a + call SetupDuel + ld a, [wcc15] + ld [wDuelInitialPrizes], a + call InitVariablesToBeginDuel + ld a, [wDuelTheme] + call PlaySong + call HandleDuelSetup + ret c +; fallthrough + +; the loop returns here after every turn switch +MainDuelLoop: + xor a + ld [wCurrentDuelMenuItem], a + call UpdateSubstatusConditions_StartOfTurn + call DisplayDuelistTurnScreen + call HandleTurn + +.between_turns + call ExchangeRNG + ld a, [wDuelFinished] + or a + jr nz, .duel_finished + call UpdateSubstatusConditions_EndOfTurn + call HandleBetweenTurnsEvents + call FinishQueuedAnimations + call ExchangeRNG + ld a, [wDuelFinished] + or a + jr nz, .duel_finished + ld hl, wDuelTurns + inc [hl] + ld a, [wDuelType] + cp DUELTYPE_PRACTICE + jr z, .practice_duel + +.next_turn + call SwapTurn + jr MainDuelLoop + +.practice_duel + ld a, [wIsPracticeDuel] + or a + jr z, .next_turn + ld a, [hl] + cp 15 ; the practice duel lasts 15 turns (8 player turns and 7 opponent turns) + jr c, .next_turn + xor a ; DUEL_WIN + ld [wDuelResult], a + ret + +.duel_finished + call ZeroObjectPositionsAndToggleOAMCopy + call EmptyScreen + ld a, BOXMSG_DECISION + call DrawDuelBoxMessage + ldtx hl, Text0078 ; DecisionText + call DrawWideTextBox_WaitForInput + call EmptyScreen + call ResetAnimationQueue + + ld a, [wDuelFinished] + cp TURN_PLAYER_WON + jr z, .turn_player_won + cp TURN_PLAYER_LOST + jr z, .asm_41b3 + ld b, DUEL_ANIM_DUEL_DRAW + ld c, MUSIC_MATCHDRAW + ldtx hl, Text0079 + ld a, $2 + jr .set_duel_result +.turn_player_won + ldh a, [hWhoseTurn] + cp PLAYER_TURN + jr nz, .asm_41b9 +.asm_4192 + ld a, DUELVARS_DUELIST_TYPE + call GetNonTurnDuelistVariable + cp DUELIST_TYPE_LINK_OPP + jr nz, .not_link_duel + + ; is link duel, increment duel counter + call EnableSRAM + ld hl, sLinkDuelCounter + inc [hl] + jr nz, .done_increment_link_duel_count + inc hl + inc [hl] +.done_increment_link_duel_count + call DisableSRAM + +.not_link_duel + ld b, DUEL_ANIM_DUEL_WIN + ld c, MUSIC_MATCH_VICTORY + ldtx hl, Text007a + xor a + jr .set_duel_result +.asm_41b3 + ldh a, [hWhoseTurn] + cp PLAYER_TURN + jr nz, .asm_4192 +.asm_41b9 + ld b, DUEL_ANIM_DUEL_LOSS + ld c, MUSIC_MATCHLOSS + ldtx hl, Text007b + ld a, $1 +.set_duel_result + ld [wDuelResult], a + + push hl + push bc + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + farcall DrawDuelistPortraitsAndNames + call PrintDuelResultStats + pop bc + pop hl + ld a, b + call PlayDuelAnimation + ld a, c + call PlaySong + + ld a, OPPONENT_TURN + ldh [hWhoseTurn], a + call DrawWideTextBox_PrintText + call EnableLCD + + ld a, [wDuelFinished] + cp TURN_PLAYER_TIED + jr z, .wait_song + + call EnableSRAM + ld hl, sTotalDuelCounter + inc [hl] + jr nz, .done_increment_total_duel_count + inc hl + inc [hl] +.done_increment_total_duel_count + call DisableSRAM + +.wait_song + call DoFrame + call UpdateRNGSources + call AssertSongFinished + or a + jr nz, .wait_song + ld a, [wDuelFinished] + cp TURN_PLAYER_TIED + jr z, .tied_duel + call StubbedPlayDefaultSong + call WaitForWideTextBoxInput_AdvanceRNG + call FinishQueuedAnimations + call ResetSerial + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + ret + +.tied_duel + call WaitForWideTextBoxInput + call FinishQueuedAnimations + ld a, [wDuelTheme] + call PlaySong + ldtx hl, Text007c ; StartSuddenDeathMatchText + call DrawWideTextBox_WaitForInput + ld a, 1 + ld [wDuelInitialPrizes], a + call InitVariablesToBeginDuel + ld a, [wDuelType] + cp DUELTYPE_LINK + jr z, .link_duel + + ; load player's and opponent's decks + call LoadPlayerDeck + ld a, [wOpponentDeckID] + or a + jr z, .skip_opp_deck + ld a, OPPONENT_TURN + ldh [hWhoseTurn], a + ld a, [wOpponentDeckID] + call LoadOpponentDeck + +.skip_opp_deck + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + call HandleDuelSetup + jp MainDuelLoop + +.link_duel + call LoadPlayerDeck + call ExchangeRNG + ld h, PLAYER_TURN + ld a, [wSerialOp] + cp $92 + jr z, .got_turn + ld h, OPPONENT_TURN +.got_turn + ld a, h + ldh [hWhoseTurn], a + call HandleDuelSetup + jp nc, MainDuelLoop + ret + +; empty the screen, and setup text and graphics for a duel +SetupDuel: xor a ld [wTileMapFill], a call ZeroObjectPositionsAndToggleOAMCopy @@ -11,9 +283,1603 @@ Func_4278: call SetupText call EnableLCD ret -; 0x4292 -SECTION "Bank 1@4cd7", ROMX[$4cd7], BANK[$1] +; handle the turn of the duelist identified by hWhoseTurn. +; if player's turn, display the animation of the player drawing the card at +; hTempCardIndex_ff98, and save the duel state to SRAM. +HandleTurn: + ld a, DUELVARS_DUELIST_TYPE + get_turn_duelist_var + ld [wDuelistType], a + ld a, [wDuelTurns] + cp 2 + jr c, .skip_let_evolve ; jump if it's the turn holder's first turn + call SetAllPlayAreaPokemonCanEvolve +.skip_let_evolve + call InitVariablesToBeginTurn + call CheckIfCannotDrawDueToPerplex + jr nc, .can_draw + call DrawWideTextBox_WaitForInput + xor a + farcall DisplayDrawNCardsScreen + jr .save_duel + +.can_draw + farcall DisplayDrawOneCardScreen + call DrawCardFromDeck + jr nc, .deck_not_empty + ld a, TURN_PLAYER_LOST + ld [wDuelFinished], a + ret + +.deck_not_empty + ldh [hTempCardIndex_ff98], a + call AddCardToHand + ld a, [wDuelistType] + cp DUELIST_TYPE_PLAYER + jr z, .player_turn + +; opponent's turn + call SwapTurn + call IsClairvoyanceActive + call SwapTurn + call c, DisplayPlayerDrawCardScreen + jr DuelMainInterface + +; player's turn +.player_turn + call DisplayPlayerDrawCardScreen + +.save_duel + farcall SaveDuelStateToSRAM +; fallthrough + +; when a practice duel turn needs to be restarted because the player did not +; follow the instructions correctly, the game loops back here +RestartPracticeDuelTurn: + ld a, PRACTICEDUEL_PRINT_TURN_INSTRUCTIONS + call DoPracticeDuelAction +; fallthrough + +; print the main interface during a duel, including background, Pokemon, HUDs and a text box. +; the bottom text box changes depending on whether the turn belongs to the player (show the duel menu), +; an AI opponent (print "Waiting..." and a reduced menu) or a link opponent (print " is thinking"). +DuelMainInterface: + ld a, [wcd09] + or a + jp nz, DuelMenu_Done + call DrawDuelMainScene + ld a, [wDuelistType] + cp DUELIST_TYPE_PLAYER + jr z, PrintDuelMenuAndHandleInput + cp DUELIST_TYPE_LINK_OPP + jr nz, .ai_opp + ; DUELIST_TYPE_LINK_OPP + farcall DoLinkOpponentTurn + ret +.ai_opp + ; DUELIST_TYPE_AI_OPP + farcall DoAIOpponentTurn + ret + +PrintDuelMenuAndHandleInput: + call DrawWideTextBox + ld hl, DuelMenuData + call PlaceTextItems +.menu_items_printed + farcall SaveDuelData + ld a, [wDuelFinished] + or a + ret nz + ld a, [wCurrentDuelMenuItem] + call SetMenuItem + +.handle_input + call DoFrame + ldh a, [hKeysHeld] + and B_BUTTON + jr z, .b_not_held + ldh a, [hKeysPressed] + bit D_UP_F, a + jr nz, DuelMenuShortcut_OpponentPlayArea + bit D_DOWN_F, a + jr nz, DuelMenuShortcut_PlayerPlayArea + bit D_LEFT_F, a + jr nz, DuelMenuShortcut_PlayerDiscardPile + bit D_RIGHT_F, a + jr nz, DuelMenuShortcut_OpponentDiscardPile + bit START_F, a + jp nz, DuelMenuShortcut_OpponentActivePokemon + +.b_not_held + ldh a, [hKeysPressed] + and START + jp nz, DuelMenuShortcut_PlayerActivePokemon + ldh a, [hKeysPressed] + bit SELECT_F, a + jp nz, DuelMenuShortcut_BothActivePokemon + ld a, [wDebugSkipDuelMenuInput] + or a + jr nz, .handle_input + call HandleDuelMenuInput + ld a, e + ld [wCurrentDuelMenuItem], a + jr nc, .handle_input + ldh a, [hCurScrollMenuItem] + ld hl, DuelMenuFunctionTable + jp JumpToFunctionInTable + +DuelMenuFunctionTable: + dw DuelMenu_Hand + dw DuelMenu_Attack + dw DuelMenu_Check + dw DuelMenu_PkmnPower + dw DuelMenu_Retreat + dw DuelMenu_Done + +; unreferenced +UnreferencedDrawCardFromDeckToHand: + call DrawCardFromDeck + call nc, AddCardToHand + ld a, OPPACTION_DRAW_CARD + call SetOppAction_SerialSendDuelData + jp PrintDuelMenuAndHandleInput.menu_items_printed + +; triggered by pressing B + UP in the duel menu +DuelMenuShortcut_OpponentPlayArea: + call OpenNonTurnHolderPlayAreaScreen + jp DuelMainInterface + +; triggered by pressing B + DOWN in the duel menu +DuelMenuShortcut_PlayerPlayArea: + call OpenTurnHolderPlayAreaScreen + jp DuelMainInterface + +; triggered by pressing B + RIGHT in the duel menu +DuelMenuShortcut_OpponentDiscardPile: + call OpenNonTurnHolderDiscardPileScreen + jp c, PrintDuelMenuAndHandleInput + jp DuelMainInterface + +; triggered by pressing B + LEFT in the duel menu +DuelMenuShortcut_PlayerDiscardPile: + call OpenTurnHolderDiscardPileScreen + jp c, PrintDuelMenuAndHandleInput + jp DuelMainInterface +; 0x439d + +SECTION "Bank 1@43be", ROMX[$43be], BANK[$1] + +; draw the non-turn holder's play area screen +OpenNonTurnHolderPlayAreaScreen: + call SwapTurn + call OpenTurnHolderPlayAreaScreen + jp SwapTurn + +; draw the turn holder's play area screen +OpenTurnHolderPlayAreaScreen: + call HasAlivePokemonInPlayArea + jp OpenPlayAreaScreenForViewing + +; draw the non-turn holder's discard pile screen +OpenNonTurnHolderDiscardPileScreen: + call SwapTurn + call OpenDiscardPileScreen + jp SwapTurn + +; draw the turn holder's discard pile screen +OpenTurnHolderDiscardPileScreen: + jp OpenDiscardPileScreen +; 0x43d9 + +SECTION "Bank 1@43e2", ROMX[$43e2], BANK[$1] + +; draw the turn holder's hand screen. simpler version of OpenPlayerHandScreen +; used only for checking the cards rather than for playing them. +; used for example in the "Your Play Area" screen of the Check menu +OpenTurnHolderHandScreen_Simple: + call CreateHandCardList + jr nc, .got_cards_in_hand + ldtx hl, Text00ab ; NoCardsInHandText + jp DrawWideTextBox_WaitForInput +.got_cards_in_hand + call InitAndDrawCardListScreenLayout + ld a, START + A_BUTTON + ld [wNoItemSelectionMenuKeys], a + jp DisplayCardList + +; triggered by pressing B + START in the duel menu +DuelMenuShortcut_OpponentActivePokemon: + call SwapTurn + call OpenActivePokemonScreen + call SwapTurn + jp DuelMainInterface + +; triggered by pressing START in the duel menu +DuelMenuShortcut_PlayerActivePokemon: + call OpenActivePokemonScreen + jp DuelMainInterface + +; draw the turn holder's active Pokemon screen if it exists +OpenActivePokemonScreen: + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + cp -1 + ret z + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + ld hl, wCurPlayAreaSlot + xor a + ld [hli], a + ld [hl], a ; wCurPlayAreaY + call OpenCardPage_FromCheckPlayArea + ret + +; triggered by selecting the "Pkmn Power" item in the duel menu +DuelMenu_PkmnPower: + call DisplayPlayAreaScreenToUsePkmnPower + jp c, DuelMainInterface + call UseAttackOrPokemonPower + jp DuelMainInterface + +; triggered by selecting the "Done" item in the duel menu +DuelMenu_Done: + ld a, PRACTICEDUEL_REPEAT_INSTRUCTIONS + call DoPracticeDuelAction + jp c, RestartPracticeDuelTurn + ld a, OPPACTION_FINISH_NO_ATTACK + call SetOppAction_SerialSendDuelData + call ClearNonTurnTemporaryDuelvars + ret + +; triggered by selecting the "Retreat" item in the duel menu +DuelMenu_Retreat: + ld a, DUELVARS_ARENA_CARD_STATUS + get_turn_duelist_var + and CNF_SLP_PRZ + cp CONFUSED + ldh [hTemp_ffa0], a + jr nz, .not_confused + ld a, [wGotHeadsFromConfusionCheckDuringRetreat] + or a + jr nz, .unable_due_to_confusion + call CheckAbleToRetreat + jr c, .unable_to_retreat + call DisplayRetreatScreen + jr c, .done + ldtx hl, Text0164 ; SelectPkmnOnBenchToSwitchWithActiveText + call DrawWideTextBox_WaitForInput + call OpenPlayAreaScreenForSelection + jr c, .done + ld [wBenchSelectedPokemon], a + ld a, [wBenchSelectedPokemon] ; unnecessary + ldh [hTempPlayAreaLocation_ffa1], a + ld a, OPPACTION_ATTEMPT_RETREAT + call SetOppAction_SerialSendDuelData + call AttemptRetreat + jr nc, .done + call DrawDuelMainScene + +.unable_due_to_confusion + ldtx hl, Text003e ; UnableToRetreatText + call DrawWideTextBox_WaitForInput + jp PrintDuelMenuAndHandleInput + +.not_confused + ; note that the energy cards are discarded (DiscardRetreatCostCards), then returned + ; (ReturnRetreatCostCardsToArena), then discarded again for good (AttemptRetreat). + ; It's done this way so that the retreating Pokemon is listed with its energies updated + ; when the Play Area screen is shown to select the Pokemon to switch to. The reason why + ; AttemptRetreat is responsible for discarding the energy cards is because, if the + ; Pokemon is confused, it may not be able to retreat, so they cannot be discarded earlier. + call CheckAbleToRetreat + jr c, .unable_to_retreat + call DisplayRetreatScreen + jr c, .done + call DiscardRetreatCostCards + ldtx hl, Text0164 ; SelectPkmnOnBenchToSwitchWithActiveText + call DrawWideTextBox_WaitForInput + call OpenPlayAreaScreenForSelection + ld [wBenchSelectedPokemon], a + ldh [hTempPlayAreaLocation_ffa1], a + push af + call ReturnRetreatCostCardsToArena + pop af + jp c, DuelMainInterface + ld a, OPPACTION_ATTEMPT_RETREAT + call SetOppAction_SerialSendDuelData + call AttemptRetreat + +.done + jp DuelMainInterface + +.unable_to_retreat + call DrawWideTextBox_WaitForInput + jp PrintDuelMenuAndHandleInput + +; triggered by selecting the "Hand" item in the duel menu +DuelMenu_Hand: + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + get_turn_duelist_var + or a + jr nz, OpenPlayerHandScreen + ldtx hl, Text00ab ; NoCardsInHandText + call DrawWideTextBox_WaitForInput + jp PrintDuelMenuAndHandleInput + +; draw the screen for the player's hand and handle user input to for example check +; a card or attempt to use a card, playing the card if possible in that case. +OpenPlayerHandScreen: + call CreateHandCardList + call InitAndDrawCardListScreenLayout + ldtx hl, Text00b2 ; PleaseSelectHandText + call SetCardListInfoBoxText + ld a, PLAY_CHECK + ld [wCardListItemSelectionMenuType], a +.handle_input + call DisplayCardList + push af + ld a, [wSortCardListByID] + or a + jr z, .skip_sort + call SortHandCardsByID +.skip_sort + pop af + jp c, DuelMainInterface + ldh a, [hTempCardIndex_ff98] + call LoadCardDataToBuffer1_FromDeckIndex + ld a, [wLoadedCard1Type] + ld c, a + bit TYPE_TRAINER_F, c + jr nz, .trainer_card + bit TYPE_ENERGY_F, c + jr nz, PlayEnergyCard + call PlayPokemonCard + jr c, ReloadCardListScreen ; jump if card not played + jp DuelMainInterface +.trainer_card + call PlayTrainerCard + jr c, ReloadCardListScreen ; jump if card not played + jp DuelMainInterface + +; play the energy card with deck index at hTempCardIndex_ff98 +; c contains the type of energy card being played +PlayEnergyCard: + ld a, c + cp TYPE_ENERGY_WATER + jr nz, .not_water_energy + call IsRainDanceActive + jr c, .rain_dance_active + +.not_water_energy + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .already_played_energy + call HasAlivePokemonInPlayArea + call OpenPlayAreaScreenForSelection ; choose card to play energy card on + jp c, DuelMainInterface ; exit if no card was chosen +.play_energy_set_played + ld a, TRUE + ld [wAlreadyPlayedEnergy], a +.play_energy + ldh a, [hTempPlayAreaLocation_ff9d] + ldh [hTempPlayAreaLocation_ffa1], a + ld e, a + ldh a, [hTempCardIndex_ff98] + ldh [hTemp_ffa0], a + call PutHandCardInPlayArea + call PrintPlayAreaCardList_EnableLCD + ld a, OPPACTION_PLAY_ENERGY + call SetOppAction_SerialSendDuelData + farcall PrintAttachedEnergyToPokemon + call Func_6986 + jp DuelMainInterface + +.rain_dance_active + call HasAlivePokemonInPlayArea + call OpenPlayAreaScreenForSelection ; choose card to play energy card on + jp c, DuelMainInterface ; exit if no card was chosen + call CheckRainDanceScenario + jr c, .play_energy + ld a, [wAlreadyPlayedEnergy] + or a + jr z, .play_energy_set_played + ldtx hl, Text003f ; MayOnlyAttachOneEnergyCardText + call DrawWideTextBox_WaitForInput + jp OpenPlayerHandScreen + +.already_played_energy + ldtx hl, Text003f ; MayOnlyAttachOneEnergyCardText + call DrawWideTextBox_WaitForInput +; fallthrough + +; reload the card list screen after the card trying to play couldn't be played +ReloadCardListScreen: + call CreateHandCardList + ; skip doing the things that have already been done when initially opened + call DrawCardListScreenLayout + jp OpenPlayerHandScreen.handle_input + +; place a basic Pokemon card on the arena or bench, or place an stage 1 or 2 +; Pokemon card over a Pokemon card already in play to evolve it. +; the card to use is loaded in wLoadedCard1 and its deck index is at hTempCardIndex_ff98. +; return nc if the card was played, carry if it wasn't. +PlayPokemonCard: + ld a, [wLoadedCard1Stage] + or a ; BASIC + jr nz, .try_evolve ; jump if the card being played is a Stage 1 or 2 Pokemon + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld hl, wMaxNumPlayAreaPokemon + cp [hl] + jr nc, .no_space + ldh a, [hTempCardIndex_ff98] + ldh [hTemp_ffa0], a + call PutHandPokemonCardInPlayArea + ldh [hTempPlayAreaLocation_ff9d], a + ldh [hTempPlayAreaLocation_ffa1], a + add DUELVARS_ARENA_CARD_STAGE + get_turn_duelist_var + ld [hl], BASIC + ld a, OPPACTION_PLAY_BASIC_PKMN + call SetOppAction_SerialSendDuelData + ldh a, [hTempCardIndex_ff98] + call LoadCardDataToBuffer1_FromDeckIndex + ld a, 20 + call CopyCardNameAndLevel + ld [hl], $00 + ld hl, $0000 + call LoadTxRam2 + ldtx hl, Text0063 ; PlacedOnTheBenchText + call DrawWideTextBox_WaitForInput + call ProcessPlayedPokemonCard + or a + ret + +.no_space + ldtx hl, Text00bb ; NoSpaceOnTheBenchText + call DrawWideTextBox_WaitForInput + scf + ret + +.try_evolve + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld c, a + ldh a, [hTempCardIndex_ff98] + ld d, a + ld e, PLAY_AREA_ARENA + push de + push bc +.next_play_area_pkmn + push de + call CheckIfCanEvolveInto + pop de + jr nc, .can_evolve + inc e + dec c + jr nz, .next_play_area_pkmn + pop bc + pop de +.find_cant_evolve_reason_loop + push de + call CheckIfCanEvolveInto + pop de + ldtx hl, Text00bd ; CantEvolvePokemonInSameTurnItsPlacedText + jr nz, .cant_same_turn + inc e + dec c + jr nz, .find_cant_evolve_reason_loop + ldtx hl, Text00bc ; NoPokemonCapableOfEvolvingText +.cant_same_turn + ; don't bother opening the selection screen if there are no pokemon capable of evolving + call DrawWideTextBox_WaitForInput + scf + ret + +.can_evolve + pop bc + pop de + call IsPrehistoricPowerActive + jr c, .prehistoric_power + call HasAlivePokemonInPlayArea +.try_evolve_loop + call OpenPlayAreaScreenForSelection + jr c, .done + ldh a, [hTempCardIndex_ff98] + ldh [hTemp_ffa0], a + ldh a, [hTempPlayAreaLocation_ff9d] + ldh [hTempPlayAreaLocation_ffa1], a + call EvolvePokemonCardIfPossible + jr c, .try_evolve_loop ; jump if evolution wasn't successful somehow + ld a, OPPACTION_EVOLVE_PKMN + call SetOppAction_SerialSendDuelData + call PrintPlayAreaCardList_EnableLCD + farcall PrintPokemonEvolvedIntoPokemon + call ProcessPlayedPokemonCard +.done + or a + ret + +.prehistoric_power + call DrawWideTextBox_WaitForInput + scf + ret + +; triggered by selecting the "Check" item in the duel menu +DuelMenu_Check: + call FinishQueuedAnimations + call OpenDuelCheckMenu + jp DuelMainInterface + +; triggered by pressing SELECT in the duel menu +DuelMenuShortcut_BothActivePokemon: + call FinishQueuedAnimations + call Func_4597 + jp DuelMainInterface + +Func_4597: + call OpenInPlayAreaScreen_FromSelectButton + ret c + call .Func_45a9 + ret c + call SwapTurn + call .Func_45a9 + call SwapTurn + ret + +.Func_45a9 + call HasAlivePokemonInPlayArea + ld a, $02 + ld [wPlayAreaSelectAction], a + call OpenPlayAreaScreenForViewing + ldh a, [hKeysPressed] + and B_BUTTON + ret z + scf + ret + +; check if the turn holder's arena Pokemon is unable to retreat due to +; some status condition or due the bench containing no alive Pokemon. +; return carry if unable, nc if able. +CheckAbleToRetreat: + call CheckUnableToRetreatDueToEffect + ret c + call HasAlivePokemonInBench + jr c, .unable_to_retreat + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + ld a, [wLoadedCard1Type] + cp TYPE_TRAINER + jr z, .unable_to_retreat + call CheckIfEnoughEnergiesToRetreat + jr c, .not_enough_energies + or a + ret +.not_enough_energies + ld a, [wEnergyCardsRequiredToRetreat] + ld l, a + ld h, $00 + call LoadTxRam3 + ldtx hl, Text00c9 ; EnergyCardsRequiredToRetreatText + jr .done +.unable_to_retreat + ldtx hl, Text003e ; UnableToRetreatText +.done + scf + ret + +; check if the turn holder's arena Pokemon has enough energies attached to it +; in order to retreat. Return carry if it doesn't. +; load amount of energies required to wEnergyCardsRequiredToRetreat. +CheckIfEnoughEnergiesToRetreat: + ld e, PLAY_AREA_ARENA + call GetPlayAreaCardAttachedEnergies + xor a + ldh [hTempPlayAreaLocation_ff9d], a + call GetPlayAreaCardRetreatCost + ld [wEnergyCardsRequiredToRetreat], a + ld c, a + ld a, [wTotalAttachedEnergies] + cp c + ret c + ld [wNumRetreatEnergiesSelected], a + ld a, c + ld [wEnergyCardsRequiredToRetreat], a + or a + ret + +; display the screen that prompts the player to select energy cards to discard +; in order to retreat a Pokemon card. also handle input in order to display +; the amount of energy cards already selected, and return whenever enough +; energy cards have been selected or if the player declines to retreat. +DisplayRetreatScreen: + ld a, $ff + ldh [hTempRetreatCostCards], a + ld a, [wEnergyCardsRequiredToRetreat] + or a + ret z ; return if no energy cards are required at all + xor a + ld [wNumRetreatEnergiesSelected], a + call CreateArenaOrBenchEnergyCardList + ld a, LOW(hTempRetreatCostCards) + ld [wTempRetreatCostCardsPos], a + xor a + call DisplayEnergyDiscardMenu + ld a, [wEnergyCardsRequiredToRetreat] + ld [wAttachedEnergyMenuDenominator], a +.select_energies_loop + ld a, [wNumRetreatEnergiesSelected] + ld [wAttachedEnergyMenuNumerator], a + call HandleAttachedEnergyMenuInput + ret c + ldh a, [hTempCardIndex_ff98] + call LoadCardDataToBuffer2_FromDeckIndex + ; append selected energy card to hTempRetreatCostCards + ld hl, wTempRetreatCostCardsPos + ld c, [hl] + inc [hl] + ldh a, [hTempCardIndex_ff98] + ld [$ff00+c], a + ; accumulate selected energy card + ld c, 1 + ld a, [wLoadedCard2Type] + cp TYPE_ENERGY_DOUBLE_COLORLESS + jr nz, .not_double + inc c +.not_double + ld hl, wNumRetreatEnergiesSelected + ld a, [hl] + add c + ld [hl], a + ld hl, wEnergyCardsRequiredToRetreat + cp [hl] + jr nc, .enough + ; not enough energies selected yet + ldh a, [hTempCardIndex_ff98] + call RemoveCardFromDuelTempList + call UpdateAttachedEnergyMenu + jr .select_energies_loop +.enough + ; terminate hTempRetreatCostCards array with $ff + ld a, [wTempRetreatCostCardsPos] + ld c, a + ld a, $ff + ld [$ff00+c], a + or a + ret + +DisplayEnergyDiscardMenu: + ldtx de, Text0052 ; ChooseEnergyCardToDiscardText +; fallthrough + +; display the screen that shows the player the energy attached +; to a Play Area Pokemon, this is used both for the discard +; effects of cards and retreat cost, and also just as an +; informative screen when viewing the Play Area +; input: +; - a = PLAY_AREA_* of the Pokemon +; - de = text ID to show in the text box +DisplayAttachedEnergyMenu: + ld hl, wAttachedEnergyMenuTextID + ld [hl], e + inc hl + ld [hl], d + ld [wAttachedEnergyMenuPlayAreaLocation], a + call SortCardsInDuelTempListByID + call EmptyScreen + call LoadDuelCardSymbolTiles + call LoadDuelFaceDownCardTiles + call Func_6c12 + call FlushAllPalettesIfNotDMG + ld a, [wAttachedEnergyMenuPlayAreaLocation] + ld hl, wCurPlayAreaSlot + ld [hli], a + ld [hl], 0 ; wCurPlayAreaY + call PrintPlayAreaCardInformation + xor a + ld [wAttachedEnergyMenuNumerator], a + ld [wcbeb], a + inc a + ld [wAttachedEnergyMenuDenominator], a +; fallthrough + +UpdateAttachedEnergyMenu: + lb de, 0, 3 + lb bc, 20, 10 + call DrawRegularTextBox + ld hl, wAttachedEnergyMenuTextID + ld a, [hli] + ld h, [hl] + ld l, a + call DrawWideTextBox_PrintTextNoDelay + call EnableLCD + call CountCardsInDuelTempList + ld hl, AttachedEnergyCardListParameters + lb de, 0, 0 ; initial page scroll offset, initial item (in the visible page) + call PrintCardListItems + ld a, 4 + ld [wCardListIndicatorYPosition], a + ret + +; if [wAttachedEnergyMenuDenominator] non-0: + ; prints "[wAttachedEnergyMenuNumerator]/[wAttachedEnergyMenuDenominator]" at 16,16 + ; where [wAttachedEnergyMenuNumerator] is the number of energy cards already selected to discard + ; and [wAttachedEnergyMenuDenominator] is the total number of energies that are required to discard. +; if [wAttachedEnergyMenuDenominator] == 0: + ; prints only "[wAttachedEnergyMenuNumerator]" +HandleAttachedEnergyMenuInput: + ld a, [wcbeb] + or a + jr nz, .wait_input + + lb bc, 16, 16 + ld a, [wAttachedEnergyMenuDenominator] + or a + jr z, .print_single_number + ld a, [wAttachedEnergyMenuNumerator] + add SYM_0 + call WriteByteToBGMap0 + inc b + ld a, SYM_SLASH + call WriteByteToBGMap0 + inc b + ld a, [wAttachedEnergyMenuDenominator] + add SYM_0 + call WriteByteToBGMap0 + jr .wait_input +.print_single_number + ld a, [wAttachedEnergyMenuNumerator] + inc b + call WriteTwoDigitNumberInTxSymbolFormat +.wait_input + call DoFrame + call HandleCardListInput + jr nc, .wait_input + cp $ff ; B pressed? + jr z, .return_carry + ld a, [wcbeb] + or a + jr nz, .wait_input + ldh a, [hCurScrollMenuItem] + call GetCardInDuelTempList_OnlyDeckIndex + or a + ret +.return_carry + scf + ret + +AttachedEnergyCardListParameters: + db 1, 5 ; cursor x, cursor y + db 4 ; item x + db 14 ; maximum length, in tiles, occupied by the name and level string of each card in the list + db 4 ; number of items selectable without scrolling + db SYM_CURSOR_R ; cursor tile number + db SYM_SPACE ; tile behind cursor + dw NULL ; function pointer if non-0 + +; triggered by selecting the "Attack" item in the duel menu +DuelMenu_Attack: + call CheckIfArencaCardIsUnableToAttack + jr nc, .can_attack + call DrawWideTextBox_WaitForInput + jp PrintDuelMenuAndHandleInput + +.can_attack + xor a + ld [wSelectedDuelSubMenuItem], a +.try_open_attack_menu + call PrintAndLoadAttacksToDuelTempList + or a + jr nz, .init_menu + ldtx hl, Text003d ; NoSelectableAttackText + call DrawWideTextBox_WaitForInput + jp PrintDuelMenuAndHandleInput + +.init_menu + push af + ld a, [wSelectedDuelSubMenuItem] + ld hl, AttackMenuParameters + call InitializeMenuParameters + pop af + +.open_attack_menu + ld [wNumScrollMenuItems], a + ldh a, [hWhoseTurn] + ld h, a + ld l, DUELVARS_ARENA_CARD + ld a, [hl] + call LoadCardDataToBuffer1_FromDeckIndex + +.wait_for_input + call DoFrame + ldh a, [hKeysPressed] + and START + jr nz, .display_selected_attack_info + call HandleMenuInput + jr nc, .wait_for_input + cp -1 ; was B pressed? + jp z, PrintDuelMenuAndHandleInput + ld [wSelectedDuelSubMenuItem], a + call CheckIfEnoughEnergiesToAttack + jr nc, .enough_energy + ldtx hl, Text00ca ; NotEnoughEnergyCardsText + call DrawWideTextBox_WaitForInput + jr .try_open_attack_menu + +.enough_energy + ldh a, [hCurScrollMenuItem] + add a + ld e, a + ld d, $00 + ld hl, wDuelTempList + add hl, de + ld d, [hl] ; card's deck index (0 to 59) + inc hl + ld e, [hl] ; attack index (0 or 1) + call CopyAttackDataAndDamage_FromDeckIndex + call HandleAmnesiaSubstatus + jr c, .cannot_use_due_to_amnesia + ld a, PRACTICEDUEL_VERIFY_PLAYER_TURN_ACTIONS + call DoPracticeDuelAction + ; if player did something wrong in the practice duel, jump in order to restart turn + jp c, RestartPracticeDuelTurn + call UseAttackOrPokemonPower + jp c, DuelMainInterface + ret + +.cannot_use_due_to_amnesia + call DrawWideTextBox_WaitForInput + jr .try_open_attack_menu + +.display_selected_attack_info + call OpenAttackPage + call DrawDuelMainScene + jp .try_open_attack_menu + +; draw the attack page of the card at wLoadedCard1 and of the attack selected in the Attack +; menu by hCurScrollMenuItem, and listen for input in order to switch the page or to exit. +OpenAttackPage: + ld a, CARDPAGE_POKEMON_OVERVIEW + ld [wCardPageNumber], a + xor a + ld [wCurPlayAreaSlot], a + call EmptyScreen + call FinishQueuedAnimations + ld de, v0Tiles1 + $20 tiles + call LoadLoadedCard1Gfx + call DrawCardPageCardGfx + call Func_6c12 + call FlushAllPalettesIfNotDMG + ldh a, [hCurScrollMenuItem] + ld [wSelectedDuelSubMenuItem], a + add a + ld e, a + ld d, $00 + ld hl, wDuelTempList + 1 + add hl, de + ld a, [hl] + or a + jr nz, .attack_2 + xor a ; ATTACKPAGE_ATTACK1_1 + jr .attack_1 + +.attack_2 + ld a, ATTACKPAGE_ATTACK2_1 + +.attack_1 + ld [wAttackPageNumber], a + +.open_page + call DisplayAttackPage + call EnableLCD + +.loop + call DoFrame + ; switch page (see SwitchAttackPage) if Right or Left pressed + ldh a, [hDPadHeld] + and D_RIGHT | D_LEFT + jr nz, .open_page + ; return to Attack menu if A or B pressed + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON + jr z, .loop + ret + +AttackMenuParameters: + db 1, 13 ; cursor x, cursor y + db 2 ; y displacement between items + db 2 ; number of items + db SYM_CURSOR_R ; cursor tile number + db SYM_SPACE ; tile behind cursor + dw NULL ; function pointer if non-0 + +; display the card page with id at wAttackPageNumber of wLoadedCard1 +DisplayAttackPage: + ld a, [wAttackPageNumber] + ld hl, AttackPageDisplayPointerTable + jp JumpToFunctionInTable + +AttackPageDisplayPointerTable: + dw DisplayAttackPage_Attack1Page1 ; ATTACKPAGE_ATTACK1_1 + dw DisplayAttackPage_Attack1Page2 ; ATTACKPAGE_ATTACK1_2 + dw DisplayAttackPage_Attack2Page1 ; ATTACKPAGE_ATTACK2_1 + dw DisplayAttackPage_Attack2Page2 ; ATTACKPAGE_ATTACK2_2 + +; display ATTACKPAGE_ATTACK1_1 +DisplayAttackPage_Attack1Page1: + call DisplayCardPage_PokemonAttack1Page1 + jr SwitchAttackPage + +; display ATTACKPAGE_ATTACK1_2 if it exists. otherwise return in order +; to switch back to ATTACKPAGE_ATTACK1_1 and display it instead. +DisplayAttackPage_Attack1Page2: + ld hl, wLoadedCard1Atk1Description + 2 + ld a, [hli] + or [hl] + ret z + call DisplayCardPage_PokemonAttack1Page2 + jr SwitchAttackPage + +; display ATTACKPAGE_ATTACK2_1 +DisplayAttackPage_Attack2Page1: + call DisplayCardPage_PokemonAttack2Page1 + jr SwitchAttackPage + +; display ATTACKPAGE_ATTACK2_2 if it exists. otherwise return in order +; to switch back to ATTACKPAGE_ATTACK2_1 and display it instead. +DisplayAttackPage_Attack2Page2: + ld hl, wLoadedCard1Atk2Description + 2 + ld a, [hli] + or [hl] + ret z + call DisplayCardPage_PokemonAttack2Page2 +; fallthrough + +; switch to ATTACKPAGE_ATTACK*_2 if in ATTACKPAGE_ATTACK*_1 and vice versa. +; sets the next attack page to switch to if Right or Left are pressed. +SwitchAttackPage: + ld hl, wAttackPageNumber + ld a, $01 + xor [hl] + ld [hl], a + ret + +; given the card at hTempCardIndex_ff98, for each non-empty, non-Pokemon Power attack slot, +; prints its information at lines 13 (first attack, if any), and 15 (second attack, if any) +; also, copies zero, one, or both of the following to wDuelTempList, $ff terminated: +; if pokemon's first attack slot isn't empty or a Pokemon Power: , 0 +; if pokemon's second attack slot isn't empty or a Pokemon Power: , 1 +; return the amount of non-empty, non-Pokemon Power attacks in a. +PrintAndLoadAttacksToDuelTempList: + call DrawWideTextBox + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + ldh [hTempCardIndex_ff98], a + call LoadCardDataToBuffer1_FromDeckIndex + ld c, 0 + ld b, 13 + ld hl, wDuelTempList + ld a, [wMetronomeEnergyCost] + push af + xor a + ld [wCardPageNumber], a + ld [wMetronomeEnergyCost], a + ld de, wLoadedCard1Atk1Name + call .CheckAttackSlotEmptyOrPokemonPower + jr c, .check_second_atk_slot + ldh a, [hTempCardIndex_ff98] + ld [hli], a + xor a + ld [hli], a + inc c + push hl + push bc + ld e, b + ld hl, wLoadedCard1Atk1Name + call PrintAttackOrPkmnPowerInformation + pop bc + pop hl + inc b + inc b ; 15 + +.check_second_atk_slot + ld de, wLoadedCard1Atk2Name + call .CheckAttackSlotEmptyOrPokemonPower + jr c, .done + ldh a, [hTempCardIndex_ff98] + ld [hli], a + ld a, $01 + ld [hli], a + inc c + push hl + push bc + ld e, b + ld hl, wLoadedCard1Atk2Name + call PrintAttackOrPkmnPowerInformation + pop bc + pop hl + +.done + pop af + ld [wMetronomeEnergyCost], a + ld a, c + ret + +; given de = wLoadedCard*Atk*Name, return carry if the attack is a +; Pkmn Power or if the attack slot is empty. +.CheckAttackSlotEmptyOrPokemonPower: + push hl + push de + push bc + ld a, [de] + ld c, a + inc de + ld a, [de] + or c + jr z, .return_no_atk_found + ld hl, CARD_DATA_ATTACK1_CATEGORY - (CARD_DATA_ATTACK1_NAME + 1) + add hl, de + ld a, [hl] + and $ff ^ RESIDUAL + cp POKEMON_POWER + jr z, .return_no_atk_found + or a +.return + pop bc + pop de + pop hl + ret +.return_no_atk_found + scf + jr .return + +; check if the arena pokemon card has enough energy attached to it +; in order to use the selected attack. +; returns: carry if not enough energy, nc if enough energy. +CheckIfEnoughEnergiesToAttack: + push hl + push bc + ld e, PLAY_AREA_ARENA + call GetPlayAreaCardAttachedEnergies + call HandleEnergyBurn + ldh a, [hCurScrollMenuItem] + add a + ld e, a + ld d, $0 + ld hl, wDuelTempList + add hl, de + ld d, [hl] ; card's deck index (0 to 59) + inc hl + ld e, [hl] ; attack index (0 or 1) + call .CheckEnergy + pop bc + pop hl + ret + +; returns carry if no enough energy +.CheckEnergy: + push hl + push de + push bc + call GetLoadedAttackEnergyCost + jr c, .done + ld de, wAttachedEnergies + ld hl, wAttackEnergyCost + lb bc, NUM_COLORED_TYPES, 0 +.loop + ld a, [de] + sub [hl] + jr nc, .cost_fulfilled + ; not enough, check for Rainbow energy + ld a, [wAttachedEnergies + RAINBOW] + or a + scf ; not enough energy, set carry + jr z, .done + ; consume an attached rainbow energy, + ; then loop back to check if cost ir fulfilled + dec a + ld [wAttachedEnergies + RAINBOW], a + dec [hl] + jr .loop +.cost_fulfilled + add c + ld c, a + inc hl + inc de + dec b + jr nz, .loop + ; colorless energy check + ld a, [de] + add c + ld c, a + inc de + ld a, [de] + add c + cp [hl] +.done + pop bc + pop de + pop hl + ret + +; print the number of prizes left, of active Pokemon, and of cards left in the deck +; of both duelists. this is called when the duel ends. +PrintDuelResultStats: + lb de, 8, 8 + call .PrintDuelistResultStats + lb de, 2, 1 + call SwapTurn + call .PrintDuelistResultStats + call SwapTurn + ret + +; print, at d,e, the number of prizes left, of active Pokemon, and of cards left in +; the deck of the turn duelist. b,c are used throughout as input coords for +; WriteTwoDigitNumberInTxSymbolFormat, and d,e for InitTextPrinting_ProcessTextFromID. +.PrintDuelistResultStats: + call SetNoLineSeparation + ldtx hl, Text007d ; PrizesLeftActivePokemonCardsInDeckText + call InitTextPrinting_ProcessTextFromID + call SetOneLineSeparation + ld c, e + ld a, d + add 7 + ld b, a + inc a + inc a + ld d, a + call CountPrizes + call .print_x_cards + inc e + inc c + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ldtx hl, Text007f ; YesText + or a + jr nz, .pkmn_in_play_area + ldtx hl, Text007e ; NoneText +.pkmn_in_play_area + dec d + call InitTextPrinting_ProcessTextFromID + inc e + inc d + inc c + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + get_turn_duelist_var + ld a, DECK_SIZE + sub [hl] +.print_x_cards + call WriteTwoDigitNumberInTxSymbolFormat + ldtx hl, Text0080 ; CardsText + call InitTextPrinting_ProcessTextFromID + ret + +; display the animation of the player drawing the card at hTempCardIndex_ff98 +DisplayPlayerDrawCardScreen: + ldtx hl, Text0072 ; YouDrewText + ldh a, [hTempCardIndex_ff98] +; fallthrough + +; display card detail when a card is drawn or played +; hl is text to display +; a is the card's deck index +DisplayCardDetailScreen: + call LoadCardDataToBuffer1_FromDeckIndex + farcall _DisplayCardDetailScreen + ret +; 0x49e8 + +SECTION "Bank 1@4a0d", ROMX[$4a0d], BANK[$1] + +; handles the initial duel actions: +; - drawing starting hand and placing the Basic Pokemon cards +; - placing the appropriate number of prize cards +; - tossing coin to determine first player to go +HandleDuelSetup: +; init variables and shuffle cards + call InitializeDuelVariables + call SwapTurn + call InitializeDuelVariables + call SwapTurn + farcall PlayShuffleAndDrawCardsAnimation_BothDuelists + call ShuffleDeckAndDrawSevenCards + ldh [hTemp_ffa0], a + call SwapTurn + call ShuffleDeckAndDrawSevenCards + call SwapTurn + ld c, a + +; check if any Basic Pokémon cards were drawn + ldh a, [hTemp_ffa0] + ld b, a + and c + jr nz, .hand_cards_ok + ld a, b + or c + jr z, .neither_drew_basic_pkmn + ld a, b + or a + jr nz, .opp_drew_no_basic_pkmn + +;.player_drew_no_basic_pkmn +.ensure_player_basic_pkmn_loop + call DisplayNoBasicPokemonInHandScreenAndText + call InitializeDuelVariables + farcall PlayShuffleAndDrawCardsAnimation_TurnDuelist + call ShuffleDeckAndDrawSevenCards + jr c, .ensure_player_basic_pkmn_loop + jr .hand_cards_ok + +.opp_drew_no_basic_pkmn + call SwapTurn +.ensure_opp_basic_pkmn_loop + call DisplayNoBasicPokemonInHandScreenAndText + call InitializeDuelVariables + farcall PlayShuffleAndDrawCardsAnimation_TurnDuelist + call ShuffleDeckAndDrawSevenCards + jr c, .ensure_opp_basic_pkmn_loop + call SwapTurn + jr .hand_cards_ok + +.neither_drew_basic_pkmn + ldtx hl, Text006d ; NeitherPlayerHasBasicPkmnText + call DrawWideTextBox_WaitForInput + call DisplayNoBasicPokemonInHandScreen + call InitializeDuelVariables + call SwapTurn + call DisplayNoBasicPokemonInHandScreen + call InitializeDuelVariables + call SwapTurn + call PrintReturnCardsToDeckDrawAgain + jp HandleDuelSetup + +.hand_cards_ok + ldh a, [hWhoseTurn] + push af + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + call ChooseInitialArenaAndBenchPokemon + call SwapTurn + call ChooseInitialArenaAndBenchPokemon + call SwapTurn + jp c, .error + call DrawPlayAreaToPlacePrizeCards + ldtx hl, Text0074 ; PlacingThePrizesText + call DrawWideTextBox_WaitForInput + call ExchangeRNG + + ld a, [wDuelInitialPrizes] + ld l, a + ld h, 0 + call LoadTxRam3 + ldtx hl, Text0075 ; PleasePlacePrizesText + call DrawWideTextBox_PrintText + call EnableLCD + farcall PlacePrizes + call WaitForWideTextBoxInput + pop af + + ldh [hWhoseTurn], a + call InitTurnDuelistPrizes + call SwapTurn + call InitTurnDuelistPrizes + call SwapTurn + call EmptyScreen + ld a, BOXMSG_COIN_TOSS + call DrawDuelBoxMessage + ldtx hl, Text0077 ; CoinTossToDecideWhoPlaysFirstText + call DrawWideTextBox_WaitForInput + ldh a, [hWhoseTurn] + cp PLAYER_TURN + jr nz, .opponent_turn + +; player flips coin + ld de, wDefaultText + call CopyPlayerName + ld hl, $0000 + call LoadTxRam2 + ldtx hl, Text0055 ; YouPlayFirstText + ldtx de, Text0076 ; IfHeadsDuelistPlaysFirstText + call TossCoin + jr c, .play_first + call SwapTurn + ldtx hl, Text0056 ; YouPlaySecondText +.play_first + call DrawWideTextBox_WaitForInput + call ExchangeRNG + or a + ret + +.opponent_turn +; opp flips coin + ld de, wDefaultText + call CopyOpponentName + ld hl, $0000 + call LoadTxRam2 + ldtx hl, Text0056 ; YouPlaySecondText + ldtx de, Text0076 ; IfHeadsDuelistPlaysFirstText + call TossCoin + jr c, .play_second + call SwapTurn + ldtx hl, Text0055 ; YouPlayFirstText +.play_second + call DrawWideTextBox_WaitForInput + call ExchangeRNG + or a + ret + +.error + pop af + ldh [hWhoseTurn], a + scf + ret + +; have the turn duelist place, at the beginning of the duel, the active Pokemon +; and 0 more bench Pokemon, all of which must be basic Pokemon cards. +; also transmits the turn holder's duelvars to the other duelist in a link duel. +; called twice, once for each duelist. +ChooseInitialArenaAndBenchPokemon: + ld a, DUELVARS_DUELIST_TYPE + get_turn_duelist_var + cp DUELIST_TYPE_PLAYER + jr z, .choose_arena + cp DUELIST_TYPE_LINK_OPP + jr z, .exchange_duelvars + +; AI opponent's turn + push af + push hl + call AIDoAction_StartDuel + pop hl + pop af + ld [hl], a + or a + ret + +; link opponent's turn +.exchange_duelvars + ldtx hl, Text0059 ; TransmittingDataText + call DrawWideTextBox_PrintText + call ExchangeRNG + ld hl, wPlayerDuelVariables + ld de, wOpponentDuelVariables + ld c, (wOpponentDuelVariables - wPlayerDuelVariables) / 2 + call SerialExchangeBytes + jr c, .error + ld c, (wOpponentDuelVariables - wPlayerDuelVariables) / 2 + call SerialExchangeBytes + jr c, .error + ld a, DUELVARS_DUELIST_TYPE + get_turn_duelist_var + ld [hl], DUELIST_TYPE_LINK_OPP + or a + ret +.error + jp DuelTransmissionError + +; player's turn (either AI or link duel) +; prompt (force) the player to choose a basic Pokemon card to place in the arena +.choose_arena + call EmptyScreen + ld a, BOXMSG_ARENA_POKEMON + call DrawDuelBoxMessage + ldtx hl, Text006b ; ChooseBasicPkmnToPlaceInArenaText + call DrawWideTextBox_WaitForInput + ld a, PRACTICEDUEL_DRAW_SEVEN_CARDS + call DoPracticeDuelAction +.choose_arena_loop + xor a + ldtx hl, Text0070 ; PleaseChooseAnActivePokemonText + call DisplayPlaceInitialPokemonCardsScreen + jr c, .choose_arena_loop + ldh a, [hTempCardIndex_ff98] + call LoadCardDataToBuffer1_FromDeckIndex + ld a, PRACTICEDUEL_PLAY_DIGLETT + call DoPracticeDuelAction + jr c, .choose_arena_loop + ldh a, [hTempCardIndex_ff98] + call PutHandPokemonCardInPlayArea + ldh a, [hTempCardIndex_ff98] + ldtx hl, Text0064 ; PlacedInTheArenaText + call DisplayCardDetailScreen + jr .choose_bench + +; after choosing the active Pokemon, let the player place 0 or more basic Pokemon +; cards in the bench. loop until the player decides to stop placing Pokemon cards. +.choose_bench + call EmptyScreen + ld a, BOXMSG_BENCH_POKEMON + call DrawDuelBoxMessage + ld a, [wMaxNumPlayAreaPokemon] + dec a + ld l, a + ld h, $00 + call LoadTxRam3 + ldtx hl, Text006f ; ChooseUpTo5BasicPkmnToPlaceOnBenchText + call PrintScrollableText_NoTextBoxLabel + ld a, PRACTICEDUEL_PUT_NIDORANM_IN_BENCH + call DoPracticeDuelAction +.bench_loop + ld a, TRUE + ldtx hl, Text0071 ; ChooseYourBenchPokemonText + call DisplayPlaceInitialPokemonCardsScreen + jr c, .bench_done + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld hl, wMaxNumPlayAreaPokemon + cp [hl] + jr nc, .no_space + ldh a, [hTempCardIndex_ff98] + call PutHandPokemonCardInPlayArea + ldh a, [hTempCardIndex_ff98] + ldtx hl, Text0063 ; PlacedOnTheBenchText + call DisplayCardDetailScreen + ld a, PRACTICEDUEL_DONE_PUTTING_ON_BENCH + call DoPracticeDuelAction + jr .bench_loop + +.no_space + ldtx hl, Text00bb ; NoSpaceOnTheBenchText + call DrawWideTextBox_WaitForInput + jr .bench_loop + +.bench_done + ld a, PRACTICEDUEL_VERIFY_INITIAL_PLAY + call DoPracticeDuelAction + jr c, .bench_loop + or a + ret + +; the turn duelist shuffles the deck unless it's a practice duel, then draws 7 cards +; returns $00 in a and carry if no basic Pokemon cards are drawn, and $01 in a otherwise +ShuffleDeckAndDrawSevenCards: + call InitializeDuelVariables + ld a, [wcd17] + or a + jr nz, .deck_ready + call ShuffleDeck + call ShuffleDeck +.deck_ready + ld b, 7 +.draw_loop + call DrawCardFromDeck + call AddCardToHand + dec b + jr nz, .draw_loop + ld a, DUELVARS_HAND + get_turn_duelist_var + ld b, $00 + ld c, 7 +.cards_loop + ld a, [hli] + push hl + push bc + call LoadCardDataToBuffer1_FromDeckIndex + call IsLoadedCard1BasicPokemon.skip_mysterious_fossil_clefairy_doll + pop bc + pop hl + or b + ld b, a + dec c + jr nz, .cards_loop + ld a, b + or a + ret nz + xor a + scf + ret + +; return nc if the card at wLoadedCard1 is a basic Pokemon card +; MYSTERIOUS_FOSSIL and CLEFAIRY_DOLL do count as basic Pokemon cards +IsLoadedCard1BasicPokemon: + ld hl, wLoadedCard1ID + inc hl + ld a, [hld] + cp HIGH(MYSTERIOUS_FOSSIL) + jr nz, .asm_4c38 + ld a, [hl] + cp LOW(MYSTERIOUS_FOSSIL) +.asm_4c38 + jr z, .basic + inc hl + ld a, [hld] + cp HIGH(CLEFAIRY_DOLL) + jr nz, .asm_4c43 + ld a, [hl] + cp LOW(CLEFAIRY_DOLL) +.asm_4c43 + jr z, .basic +; fallthrough + +; return nc if the card at wLoadedCard1 is a basic Pokemon card +; MYSTERIOUS_FOSSIL and CLEFAIRY_DOLL do NOT count unless already checked +.skip_mysterious_fossil_clefairy_doll + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .energy_trainer_nonbasic + ld a, [wLoadedCard1Stage] + or a + jr nz, .energy_trainer_nonbasic + +; basic + ld a, $01 + ret ; z + +.energy_trainer_nonbasic + xor a + scf + ret + +.basic ; MYSTERIOUS_FOSSIL or CLEFAIRY_DOLL + ld a, $01 + or a + ret ; nz + +DisplayNoBasicPokemonInHandScreenAndText: + ldtx hl, Text006c ; ThereAreNoBasicPokemonInHand + call DrawWideTextBox_WaitForInput + call DisplayNoBasicPokemonInHandScreen +; fallthrough + +; prints ReturnCardsToDeckAndDrawAgainText in a textbox and calls ExchangeRNG +PrintReturnCardsToDeckDrawAgain: + ldtx hl, Text006e ; ReturnCardsToDeckAndDrawAgainText + call DrawWideTextBox_WaitForInput + call ExchangeRNG + ret + +; display a bare list of seven hand cards of the turn duelist, and the duelist's name above +; used to let the player know that there are no basic Pokemon in the hand and need to redraw +DisplayNoBasicPokemonInHandScreen: + call EmptyScreen + call Func_6c12 + call LoadDuelCardSymbolTiles + lb de, 0, 0 + lb bc, 20, 18 + call DrawRegularTextBox + call CreateHandCardList + call CountCardsInDuelTempList + ld hl, NoBasicPokemonCardListParameters + lb de, 0, 0 + call PrintCardListItems + ldtx hl, Text00ae ; DuelistHandText + lb de, 1, 1 + call PrintTextNoDelay_Init + call EnableLCD + call WaitForWideTextBoxInput + ret + +NoBasicPokemonCardListParameters: + db 1, 3 ; cursor x, cursor y + db 4 ; item x + db 14 ; maximum length, in tiles, occupied by the name and level string of each card in the list + db 7 ; number of items selectable without scrolling + db SYM_CURSOR_R ; cursor tile number + db SYM_SPACE ; tile behind cursor + dw NULL ; function pointer if non-0 + +; used only during the practice duel with Sam. +; displays the list with the player's cards in hand, and the player's name above the list. +DisplayPracticeDuelPlayerHandScreen: + call CreateHandCardList + call EmptyScreen + call LoadDuelCardSymbolTiles + call Func_6c12 + lb de, 0, 0 + lb bc, 20, 13 + call DrawRegularTextBox + call CountCardsInDuelTempList ; list length + ld hl, CardListParameters ; other list params + lb de, 0, 0 ; initial page scroll offset, initial item (in the visible page) + call PrintCardListItems + ldtx hl, Text00ae ; DuelistHandText + lb de, 1, 1 + call PrintTextNoDelay_Init + call EnableLCD + ret DrawDuelMainScene: ld a, [wDuelType] @@ -21,7 +1887,7 @@ DrawDuelMainScene: jr nz, .asm_4ced ldh a, [hWhoseTurn] push af - ld a, [wcbfd] + ld a, [wWhoseTurn] ldh [hWhoseTurn], a call .Draw pop af @@ -109,7 +1975,7 @@ DrawDuelHUDs: ld a, [wDuelType] cp $00 jr nz, .asm_4d95 - ld a, [wcbfd] + ld a, [wWhoseTurn] ld e, a .asm_4d95 ldh a, [hWhoseTurn] @@ -293,7 +2159,772 @@ DrawDuelHUD: call WriteByteToBGMap0 .done ret -; 0x4ec6 + +; if this is a practice duel, execute the practice duel action at wPracticeDuelAction +; if not a practice duel, always return nc +; the practice duel functions below return carry when something's wrong +DoPracticeDuelAction: + ld [wPracticeDuelAction], a + ld a, [wIsPracticeDuel] + or a + ret z + ld a, [wPracticeDuelAction] + ld hl, PracticeDuelActionTable + jp JumpToFunctionInTable + +PracticeDuelActionTable: + dw NULL + dw PracticeDuel_DrawSevenCards + dw PracticeDuel_PlayDiglett + dw PracticeDuel_PutPidgeyInBench + dw PracticeDuel_VerifyInitialPlay + dw PracticeDuel_DonePuttingOnBench + dw PracticeDuel_PrintTurnInstructions + dw PracticeDuel_VerifyPlayerTurnActions + dw PracticeDuel_RepeatInstructions + dw PracticeDuel_PlayNidoranMFromBench + dw PracticeDuel_ReplaceKnockedOutPokemon + +PracticeDuel_DrawSevenCards: + call DisplayPracticeDuelPlayerHandScreen + call EnableLCD + ldtx hl, Text04fa ; DrawSevenCardsPracticeDuelText + jp PrintPracticeDuelDrMasonInstructions + +PracticeDuel_PlayDiglett: + ld hl, wLoadedCard1ID + inc hl + ld a, [hld] + cp HIGH(DIGLETT_LV8) + jr nz, .asm_4f05 + ld a, [hl] + cp LOW(DIGLETT_LV8) +.asm_4f05 + ret z + ldtx hl, Text04fb ; ChooseDiglettPracticeDuelText + scf + jp PrintPracticeDuelDrMasonInstructions + +PracticeDuel_PutPidgeyInBench: + call DisplayPracticeDuelPlayerHandScreen + call EnableLCD + ldtx hl, Text04fc ; PutPokemonOnBenchPracticeDuelText + jp PrintPracticeDuelDrMasonInstructions + +PracticeDuel_VerifyInitialPlay: + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + cp 2 + ret z + ldtx hl, Text04fd ; ChoosePidgeyPracticeDuelText + scf + jp PrintPracticeDuelDrMasonInstructions + +PracticeDuel_DonePuttingOnBench: + call DisplayPracticeDuelPlayerHandScreen + call EnableLCD + ld a, $ff + ld [wPracticeDuelTurn], a + ldtx hl, Text04fe ; PressBToFinishPracticeDuelText + jp PrintPracticeDuelDrMasonInstructions + +PracticeDuel_PrintTurnInstructions: + call EmptyScreen + ld a, [wDuelTurns] + srl a + inc a + ld l, a + ld h, $00 + call LoadTxRam3 + ld de, $0 + lb bc, 20, 12 + call DrawRegularTextBox + lb de, 1, 0 + ldtx hl, Text04f8 + call Func_2c4b + call EnableLCD + ld a, [wDuelTurns] + ld hl, wPracticeDuelTurn + cp [hl] + ld [hl], a + ; calling PrintPracticeDuelInstructionsForCurrentTurn with a = 0 means that Dr. Mason's + ; instructions are also printed along with each of the point-by-point instructions + ld a, 0 + jp nz, PrintPracticeDuelInstructionsForCurrentTurn + ; if we're here, the player followed the current turn actions wrong and has to + ; repeat them. ask the player whether to show detailed instructions again, in + ; order to call PrintPracticeDuelInstructionsForCurrentTurn with a = 0 or a = 1. + ldtx de, Text04f7 ; DrMasonText + ldtx hl, Text0507 ; NeedPracticeAgainPracticeDuelText + call PrintScrollableText_WithTextBoxLabel_NoWait + call YesOrNoMenu + jp PrintPracticeDuelInstructionsForCurrentTurn + +PracticeDuel_VerifyPlayerTurnActions: + ld a, [wDuelTurns] + srl a + ld hl, PracticeDuelTurnVerificationPointerTable + call JumpToFunctionInTable + ; return nc if player followed instructions correctly + ret nc +; fallthrough + +PracticeDuel_RepeatInstructions: + ldtx hl, Text0506 ; FollowMyGuidancePracticeDuelText + call PrintPracticeDuelDrMasonInstructions + ; restart the turn from the saved data of the previous turn + ld a, $02 + call BankswitchSRAM + ld de, sCurrentDuel + farcall LoadSavedDuelData + xor a + call BankswitchSRAM + call DisableSRAM + ; return carry in order to repeat instructions + scf + ret + +PracticeDuel_PlayNidoranMFromBench: + ld a, [wDuelTurns] + cp 7 + jr z, .its_sam_turn_4 +.no_carry + or a + ret +.its_sam_turn_4 + call EmptyScreen + lb de, 0, 0 + lb bc, 20, 12 + call DrawRegularTextBox + lb de, 1, 0 + ldtx hl, Text04f9 + call Func_2c4b + call EnableLCD + ld hl, PracticeDuelText_SamTurn4 + jp PrintPracticeDuelInstructions + +PracticeDuel_ReplaceKnockedOutPokemon: + ld a, [wDuelTurns] + cp 7 + jr nz, PracticeDuel_PlayNidoranMFromBench.no_carry + ldh a, [hTempPlayAreaLocation_ff9d] + cp PLAY_AREA_BENCH_2 + ret z + ; if player selected other Pokemon instead + call HasAlivePokemonInBench + ldtx hl, Text051c + scf +; fallthrough + +; print a text box with given the text id at hl, labeled as 'Dr. Mason' +PrintPracticeDuelDrMasonInstructions: + push af + ldtx de, Text04f7 ; DrMasonText + call PrintScrollableText_WithTextBoxLabel + pop af + ret + +INCLUDE "data/duel/practice_text.asm" + +; print the instructions of the current practice duel turn, taken from +; one of the structs in PracticeDuelTextPointerTable. +; if a != 0, only the point-by-point instructions are printed, otherwise +; Dr. Mason instructions are also shown in a textbox at the bottom of the screen. +PrintPracticeDuelInstructionsForCurrentTurn: + push af + ld a, [wDuelTurns] + and %11111110 + ld e, a + ld d, $00 + ld hl, PracticeDuelTextPointerTable + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + pop af + or a + jr nz, PrintPracticeDuelInstructions_Fast +; fallthrough + +; print practice duel instructions given hl = PracticeDuelText_* +; each practicetext entry (see above) contains a Dr. Mason text along with +; a numbered instruction text, that is later printed without text delay. +PrintPracticeDuelInstructions: + ld a, [hli] + ld [wPracticeDuelTextY], a + or a + jr z, PrintPracticeDuelLetsPlayTheGame + ld e, [hl] + inc hl + ld d, [hl] + inc hl + push hl + ld l, e + ld h, d + call PrintPracticeDuelDrMasonInstructions + pop hl + ld e, [hl] + inc hl + ld d, [hl] + inc hl + push hl + call SetNoLineSeparation + ld l, e + ld h, d + ld a, [wPracticeDuelTextY] + ld e, a + ld d, 1 + call InitTextPrinting_ProcessTextFromID + call SetOneLineSeparation + pop hl + jr PrintPracticeDuelInstructions + +; print the generic Dr. Mason's text that completes all his practice duel instructions +PrintPracticeDuelLetsPlayTheGame: + ldtx hl, Text0505 ; LetsPlayTheGamePracticeDuelText + call PrintPracticeDuelDrMasonInstructions + ret + +; simplified version of PrintPracticeDuelInstructions that skips Dr. Mason's text +; and instead places the point-by-point instructions all at once. +PrintPracticeDuelInstructions_Fast: + ld a, [hli] + or a + jr z, PrintPracticeDuelLetsPlayTheGame + ld e, a ; y + ld d, 1 ; x + inc hl + inc hl + ld c, [hl] + inc hl + ld b, [hl] + inc hl + push hl + ld l, c + ld h, b + call SetNoLineSeparation + call InitTextPrinting_ProcessTextFromID + call SetOneLineSeparation + pop hl + jr PrintPracticeDuelInstructions_Fast + +PracticeDuelTurnVerificationPointerTable: + dw PracticeDuelVerify_Turn1 + dw PracticeDuelVerify_Turn2 + dw PracticeDuelVerify_Turn3 + dw PracticeDuelVerify_Turn4 + dw PracticeDuelVerify_Turn5 + dw PracticeDuelVerify_Turn6 + +PracticeDuelVerify_Turn1: + ld hl, wTempCardID_ccc2 + inc hl + ld a, [hld] + cp HIGH(DIGLETT_LV8) + jr nz, .asm_50cd + ld a, [hl] + cp LOW(DIGLETT_LV8) +.asm_50cd + jp nz, ReturnWrongAction + ret + +PracticeDuelVerify_Turn2: + ld hl, wTempCardID_ccc2 + inc hl + ld a, [hld] + cp HIGH(DIGLETT_LV8) + jr nz, .asm_50dd + ld a, [hl] + cp LOW(DIGLETT_LV8) +.asm_50dd + jp nz, ReturnWrongAction + ld a, [wSelectedAttack] + cp 1 + jp nz, ReturnWrongAction + ret + +PracticeDuelVerify_Turn3: + ld hl, wTempCardID_ccc2 + inc hl + ld a, [hld] + cp HIGH(DUGTRIO_LV36) + jr nz, .asm_50f5 + ld a, [hl] + cp LOW(DUGTRIO_LV36) +.asm_50f5 + jp nz, ReturnWrongAction + ld e, PLAY_AREA_ARENA + call GetPlayAreaCardAttachedEnergies + ld a, [wAttachedEnergies + FIGHTING] + cp 3 + jr nz, ReturnWrongAction + or a + ret + +PracticeDuelVerify_Turn4: + ld a, [wPlayerNumberOfPokemonInPlayArea] + cp 3 + jr nz, ReturnWrongAction + ld e, PLAY_AREA_BENCH_2 + call GetPlayAreaCardAttachedEnergies + ld a, [wAttachedEnergies + GRASS] + or a + jr z, ReturnWrongAction + ld hl, wTempCardID_ccc2 + inc hl + ld a, [hld] + cp HIGH(DUGTRIO_LV36) + jr nz, .asm_5124 + ld a, [hl] + cp LOW(DUGTRIO_LV36) +.asm_5124 + jp nz, ReturnWrongAction + or a + ret + +PracticeDuelVerify_Turn5: + ld a, [wPlayerNumberOfPokemonInPlayArea] + cp 3 + jr nz, ReturnWrongAction + ld e, PLAY_AREA_ARENA + call GetPlayAreaCardAttachedEnergies + ld a, [wAttachedEnergies + GRASS] + cp 2 + jr nz, ReturnWrongAction + ld hl, wTempCardID_ccc2 + inc hl + ld a, [hld] + cp HIGH(NIDORANM_LV20) + jr nz, .asm_5148 + ld a, [hl] + cp LOW(NIDORANM_LV20) +.asm_5148 + jr nz, ReturnWrongAction + ret + +PracticeDuelVerify_Turn6: + ld hl, wTempCardID_ccc2 + inc hl + ld a, [hld] + cp HIGH(NIDORINO_LV25) + jr nz, .asm_5157 + ld a, [hl] + cp LOW(NIDORINO_LV25) +.asm_5157 + jr nz, ReturnWrongAction + or a + ret + +ReturnWrongAction: + scf + ret + +; display BOXMSG_PLAYERS_TURN or BOXMSG_OPPONENTS_TURN and print +; DuelistTurnText in a textbox. also call ExchangeRNG. +DisplayDuelistTurnScreen: + call EmptyScreen + ld c, BOXMSG_PLAYERS_TURN + ldh a, [hWhoseTurn] + cp PLAYER_TURN + jr z, .got_turn + inc c ; BOXMSG_OPPONENTS_TURN +.got_turn + ld a, c + call DrawDuelBoxMessage + ldtx hl, Text0060 ; DuelistTurnText + call DrawWideTextBox_WaitForInput + call ExchangeRNG + ret +; 0x5177 + +SECTION "Bank 1@517e", ROMX[$517e], BANK[$1] + +DuelMenuData: + ; x, y, text id + textitem 3, 14, Text0001 ; HandText + textitem 9, 14, Text0002 ; CheckText + textitem 15, 14, Text0007 ; RetreatText + textitem 3, 16, Text0003 ; AttackText + textitem 9, 16, Text0004 ; PKMNPowerText + textitem 15, 16, Text0005 ; DoneText + db $ff + +; display the screen that prompts the player to choose a Pokemon card to +; place in the arena or in the bench at the beginning of the duel. +; input: + ; a = 0 -> prompted to place Pokemon card in arena + ; a = 1 -> prompted to place Pokemon card in bench +; return carry if no card was placed (only allowed for bench) +DisplayPlaceInitialPokemonCardsScreen: + ld [wPlacingInitialBenchPokemon], a + push hl + call CreateHandCardList + call InitAndDrawCardListScreenLayout + pop hl + call SetCardListInfoBoxText + ld a, PLAY_CHECK + ld [wCardListItemSelectionMenuType], a +.display_card_list + call DisplayCardList + jr nc, .card_selected + ; attempted to exit screen + ld a, [wPlacingInitialBenchPokemon] + or a + ; player is forced to place a Pokemon card in the arena + jr z, .display_card_list + ; in the bench, however, we can get away without placing anything + ; alternatively, the player doesn't want or can't place more bench Pokemon + scf + jr .done +.card_selected + ldh a, [hTempCardIndex_ff98] + call LoadCardDataToBuffer1_FromDeckIndex + call IsLoadedCard1BasicPokemon + jr nc, .done + ; invalid card selected, tell the player and go back + ldtx hl, Text0073 ; YouCannotSelectThisCardText + call DrawWideTextBox_WaitForInput + call DrawCardListScreenLayout + jr .display_card_list +.done + ; valid basic Pokemon card selected, or no card selected (bench only) + push af + ld a, [wSortCardListByID] + or a + jr z, .skip_sorting + call SortHandCardsByID +.skip_sorting + pop af + ret +; 0x51d9 + +SECTION "Bank 1@51ed", ROMX[$51ed], BANK[$1] + +; draw the turn holder's discard pile screen +OpenDiscardPileScreen: + call CreateDiscardPileCardList + jr c, .discard_pile_empty + call InitAndDrawCardListScreenLayout + ldtx hl, Text0058 + ldtx de, Text00ad + call SetCardListHeaderAndInfoText + ld a, START + A_BUTTON + ld [wNoItemSelectionMenuKeys], a + call DisplayCardList + or a + ret +.discard_pile_empty + ; this might be either because there are no cards + ; in the Discard Pile, or that Black Hole is active + ; in which case the "No cards in Discard Pile" text + ; will always show here regardless + ldtx hl, Text00ac ; TheDiscardPileHasNoCardsText + call DrawWideTextBox_WaitForInput + scf + ret + +; hl = info text ID +; de = header text ID +SetCardListHeaderAndInfoText: + ld a, e + ld [wCardListHeaderText], a + ld a, d + ld [wCardListHeaderText + 1], a +; fallthrough + +SetCardListInfoBoxText: + ld a, l + ld [wCardListInfoBoxText + 0], a + ld a, h + ld [wCardListInfoBoxText + 1], a + ret +; 0x5221 + +SECTION "Bank 1@522a", ROMX[$522a], BANK[$1] + +; draw the layout of the screen that displays the player's Hand card list or a +; Discard Pile card list, including a bottom-right image of the current card. +; since this loads the text for the Hand card list screen, SetDiscardPileScreenTexts +; is called after this if the screen corresponds to a Discard Pile list. +; the dimensions of text box where the card list is printed are 20x13, in order to accommodate +; another text box below it (wCardListInfoBoxText) as well as the image of the selected card. +InitAndDrawCardListScreenLayout: + xor a + ld hl, wSelectedDuelSubMenuItem + ld [hli], a + ld [hl], a + ld [wSortCardListByID], a + ld hl, wPrintSortNumberInCardListPtr + ld [hli], a + ld [hl], a + ld [wCardListItemSelectionMenuType], a + ld a, START + ld [wNoItemSelectionMenuKeys], a + ld hl, wCardListInfoBoxText + ldtx [hl], Text00b2, & $ff + inc hl + ldtx [hl], Text00b2, >> 8 + inc hl ; wCardListHeaderText + ldtx [hl], Text00ae, & $ff + inc hl + ldtx [hl], Text00ae, >> 8 +; fallthrough + +; same as InitAndDrawCardListScreenLayout, except that variables like wSelectedDuelSubMenuItem, +; wNoItemSelectionMenuKeys, wCardListInfoBoxText, wCardListHeaderText, etc already set by caller. +DrawCardListScreenLayout: + call ZeroObjectPositionsAndToggleOAMCopy + call EmptyScreen + call LoadSymbolsFont + call LoadDuelCardSymbolTiles + call Func_6c12 + ; draw the surrounding box + lb de, 0, 0 + lb bc, 20, 13 + call DrawRegularTextBox + ; draw the image of the selected card + ld a, $a0 + lb hl, 6, 1 + lb de, 12, 12 + lb bc, 8, 6 + call FillRectangle + call Func_53cb + ld a, [wDuelTempList] + cp $ff + scf + ret z + or a + ret + +; displays a list of cards and handles input in order to navigate through the list, +; select a card, open a card page, etc. +; input: + ; - text IDs at wCardListInfoBoxText and wCardListHeaderText + ; - $ff-terminated list of cards to display at wDuelTempList + ; - wSelectedDuelSubMenuItem (initial item) and wSelectedDuelSubMenuScrollOffset + ; (initial page scroll offset). Usually both 0 to begin with the first card. +; returns carry if B is pressed to exit the card list screen. +; otherwise returns the selected card at hTempCardIndex_ff98 and at a. +DisplayCardList: + call DrawNarrowTextBox + call PrintCardListHeaderAndInfoBoxTexts +.reload_list + ; get the list length + call CountCardsInDuelTempList + ; get the position and scroll within the list + ld hl, wSelectedDuelSubMenuItem + ld e, [hl] ; initial item (in the visible page) + inc hl + ld d, [hl] ; initial page scroll offset + ld hl, CardListParameters ; other list params + call PrintCardListItems + call LoadSelectedCardGfx + call EnableLCD +.wait_button + call DoFrame + call .UpdateListOnDPadInput + call HandleCardListInput + jr nc, .wait_button + ; refresh the position of the last checked card of the list, so that + ; the cursor points to said card when the list is reloaded + ld hl, wSelectedDuelSubMenuItem + ld [hl], e + inc hl + ld [hl], d + ldh a, [hKeysPressed] + ld b, a + bit SELECT_F, b + jr nz, .select_pressed + bit B_BUTTON_F, b + jr nz, .b_pressed + ld a, [wNoItemSelectionMenuKeys] + and b + jr nz, .open_card_page + ; display the item selection menu (PLAY|CHECK or SELECT|CHECK) for the selected card + ; open the card page if CHECK is selected + ldh a, [hCurScrollMenuItem] + call GetCardInDuelTempList_OnlyDeckIndex + call CardListItemSelectionMenu + ; jump back if B pressed to exit the item selection menu + jr c, DisplayCardList + ldh a, [hTempCardIndex_ff98] + or a + ret +.select_pressed + ; sort cards by ID if SELECT is pressed and return to the first item + ld a, [wSortCardListByID] + or a + jr nz, .wait_button + call SortCardsInDuelTempListByID + xor a + ld hl, wSelectedDuelSubMenuItem + ld [hli], a + ld [hl], a + ld a, 1 + ld [wSortCardListByID], a + call EraseCursor + jr .reload_list +.open_card_page + ; open the card page directly, without an item selection menu + ; in this mode, D_UP and D_DOWN can be used to open the card page + ; of the card above and below the current card + ldh a, [hCurScrollMenuItem] + call GetCardInDuelTempList + call LoadCardDataToBuffer1_FromDeckIndex + call OpenCardPage_FromCheckHandOrDiscardPile + ldh a, [hDPadHeld] + bit D_UP_F, a + jr nz, .up_pressed + bit D_DOWN_F, a + jr nz, .down_pressed + ; if B pressed, exit card page and reload the card list + call DrawCardListScreenLayout + jp DisplayCardList +.up_pressed + ldh a, [hCurScrollMenuItem] + or a + jr z, .open_card_page ; if can't go up, reload card page of current card + dec a + jr .move_to_another_card +.down_pressed + call CountCardsInDuelTempList + ld b, a + ldh a, [hCurScrollMenuItem] + inc a + cp b + jr nc, .open_card_page ; if can't go down, reload card page of current card +.move_to_another_card + ; update hCurScrollMenuItem, and wSelectedDuelSubMenuScrollOffset. + ; this means that when navigating up/down through card pages, the page is + ; scrolled to reflect the movement, rather than the cursor going up/down. + ldh [hCurScrollMenuItem], a + ld hl, wSelectedDuelSubMenuItem + ld [hl], $00 + inc hl + ld [hl], a + jr .open_card_page +.b_pressed + ldh a, [hCurScrollMenuItem] + scf + ret + +.UpdateListOnDPadInput: + ldh a, [hDPadHeld] + and D_PAD + ret z + ld a, $01 + ldh [hffbb], a + call PrintCardListHeaderAndInfoBoxTexts + xor a + ldh [hffbb], a + ret + +; prints the text ID at wCardListHeaderText at 1,1 +; and the text ID at wCardListInfoBoxText at 1,14 +PrintCardListHeaderAndInfoBoxTexts: + ld hl, wCardListInfoBoxText + ld a, [hli] + ld h, [hl] + ld l, a + lb de, 1, 14 + call PrintTextNoDelay_Init + ld hl, wCardListHeaderText + ld a, [hli] + ld h, [hl] + ld l, a + lb de, 1, 1 + call PrintTextNoDelay_Init + ret + +; display the SELECT|CHECK or PLAY|CHECK menu when a card of a list is selected +; and handle input. return carry if b is pressed. +; input: wCardListItemSelectionMenuType +CardListItemSelectionMenu: + ld a, [wCardListItemSelectionMenuType] + or a + ret z + ldtx hl, Text008b ; SelectCheckText + ld a, [wCardListItemSelectionMenuType] + cp PLAY_CHECK + jr nz, .got_text + ldh a, [hTempCardIndex_ff98] + call LoadCardDataToBuffer1_FromDeckIndex + ldtx hl, Text008a ; PlayCheck2Text + ld a, [wLoadedCard1Type] + cp TYPE_TRAINER + jr nz, .got_text + ldtx hl, Text0089 ; PlayCheck1Text +.got_text + call DrawNarrowTextBox_PrintTextNoDelay + ld hl, ItemSelectionMenuParameters + xor a + call InitializeMenuParameters +.wait_a_or_b + call DoFrame + call HandleMenuInput + jr nc, .wait_a_or_b + cp -1 + jr z, .b_pressed + ; A pressed + or a + ret z + ; CHECK option selected: open the card page + ldh a, [hTempCardIndex_ff98] + call LoadCardDataToBuffer1_FromDeckIndex + call OpenCardPage_FromHand + call DrawCardListScreenLayout +.b_pressed + scf + ret + +ItemSelectionMenuParameters: + db 1, 14 ; cursor x, cursor y + db 2 ; y displacement between items + db 2 ; number of items + db SYM_CURSOR_R ; cursor tile number + db SYM_SPACE ; tile behind cursor + dw NULL ; function pointer if non-0 + +CardListParameters: + db 1, 3 ; cursor x, cursor y + db 4 ; item x + db 14 ; maximum length, in tiles, occupied by the name and level string of each card in the list + db 5 ; number of items selectable without scrolling + db SYM_CURSOR_R ; cursor tile number + db SYM_SPACE ; tile behind cursor + dw CardListFunction ; function pointer if non-0 + +; return carry if any of the buttons is pressed, and load the graphics +; of the card pointed to by the cursor whenever a d-pad key is released. +; also return $ff unto hCurScrollMenuItem if B is pressed. +CardListFunction: + ldh a, [hKeysPressed] + bit B_BUTTON_F, a + jr nz, .exit + and A_BUTTON | SELECT | START + jr nz, .action_button + ldh a, [hKeysReleased] + and D_PAD + jr nz, .reload_card_image ; jump if the D_PAD key was released this frame + ret +.exit + ld a, $ff + ldh [hCurScrollMenuItem], a +.action_button + scf + ret +.reload_card_image + call LoadSelectedCardGfx + or a + ret +; 0x53bc + +SECTION "Bank 1@53cb", ROMX[$53cb], BANK[$1] + +Func_53cb: + ld hl, wPrintSortNumberInCardListPtr + jp CallIndirect +; 0x53d1 SECTION "Bank 1@53e9", ROMX[$53e9], BANK[$1] @@ -396,7 +3027,102 @@ DrawCardPageCardGfx: ret ; 0x5475 -SECTION "Bank 1@553d", ROMX[$553d], BANK[$1] +SECTION "Bank 1@549b", ROMX[$549b], BANK[$1] + +; has turn duelist take amount of prizes that are in wNumberPrizeCardsToTake +; returns carry if all prize cards were taken +TurnDuelistTakePrizes: + call FinishQueuedAnimations + ld a, [wNumberPrizeCardsToTake] + ld l, a + ld h, $00 + call LoadTxRam3 + ld a, DUELVARS_DUELIST_TYPE + get_turn_duelist_var + cp DUELIST_TYPE_PLAYER + jr nz, .opponent + +; player + ldtx hl, Text0043 ; WillDrawNPrizesText + call DrawWideTextBox_WaitForInput + ld a, [wNumberPrizeCardsToTake] + call SelectPrizeCards + ld hl, hTemp_ffa0 + ld d, [hl] + inc hl + ld e, [hl] + call SerialSend8Bytes + +.return_has_prizes + call ExchangeRNG + ld a, DUELVARS_PRIZES + get_turn_duelist_var + or a + ret nz + scf + ret + +.opponent + call .Func_588a + ldtx hl, Text0043 ; WillDrawNPrizesText + call DrawWideTextBox_PrintText + call CountPrizes + ld [wTempNumRemainingPrizeCards], a + ld a, DUELVARS_DUELIST_TYPE + get_turn_duelist_var + cp DUELIST_TYPE_LINK_OPP + jr z, .link_opponent + ld c, 60 +.delay_loop + call DoFrame + dec c + jr nz, .delay_loop + call AIDoAction_TakePrize + jr .asm_586f + +.link_opponent + call SerialRecv8Bytes + ld a, DUELVARS_PRIZES + get_turn_duelist_var + ld [hl], d + ld a, e + cp $ff + jr z, .asm_586f + call AddCardToHand + call .Func_551d + +.asm_586f + ld a, [wTempNumRemainingPrizeCards] + ld hl, wNumberPrizeCardsToTake + cp [hl] + jr nc, .asm_587e + ld l, a + ld h, $00 + call LoadTxRam3 +.asm_587e + farcall Func_82b6 + ldtx hl, Text0044 ; DrewNPrizesText + call DrawWideTextBox_WaitForInput + jr .return_has_prizes + +.Func_551d: + ld e, a + ld a, [wcc07] + or a + ret z + ld a, e + call LoadCardDataToBuffer1_FromDeckIndex + ldtx hl, Text0081 + farcall _DisplayCardDetailScreen + call OpenCardPage_FromHand + call .Func_588a ; can be fallthrough + ret + +.Func_588a: + ld l, PLAYER_TURN + ldh a, [hWhoseTurn] + ld h, a + jp DrawYourOrOppPlayAreaScreen_Bank0 ; display the previous valid card page DisplayPreviousCardPage: @@ -418,9 +3144,19 @@ DisplayCardPage: call EnableLCD or a ret -; 0x5555 -SECTION "Bank 1@5570", ROMX[$5570], BANK[$1] +; load the tiles and palette of the card selected in card list screen +LoadSelectedCardGfx: + ldh a, [hCurScrollMenuItem] + call GetCardInDuelTempList + call LoadCardDataToBuffer1_FromCardID + ld de, v0Tiles1 + $20 tiles + call LoadLoadedCard1Gfx + lb de, 12, 12 + call DrawCardGfxToDE_BGPalIndex5 + call Func_6c12 + call FlushAllPalettesIfNotDMG + ret CardPageDisplayPointerTable: dw DrawDuelMainScene ; $0 @@ -1302,9 +4038,380 @@ PrintNumberAsMeasurement: add d ld d, a ret -; 0x5a42 -SECTION "Bank 1@5cb7", ROMX[$5cb7], BANK[$1] +; return carry if the turn holder has any Pokemon with non-zero HP on the bench. +; return how many Pokemon with non-zero HP in b. +; does this by calculating how many Pokemon in play area minus one +HasAlivePokemonInBench: + ld a, $01 + jr _HasAlivePokemonInPlayArea + +; return carry if the turn holder has any Pokemon with non-zero HP in the play area. +; return how many Pokemon with non-zero HP in b. +HasAlivePokemonInPlayArea: + xor a +; fallthrough + +_HasAlivePokemonInPlayArea: + ld [wExcludeArenaPokemon], a + ld b, a + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + sub b + ld c, a + ld a, DUELVARS_ARENA_CARD_HP + add b + get_turn_duelist_var + ld b, 0 + inc c + xor a + ld [wPlayAreaScreenLoaded], a + ld [wPlayAreaSelectAction], a + jr .next_pkmn +.loop + ld a, [hli] + or a + jr z, .next_pkmn ; jump if this play area Pokemon has 0 HP + inc b +.next_pkmn + dec c + jr nz, .loop + ld a, b + or a + ret nz + scf + ret + +OpenPlayAreaScreenForViewing: + ld a, START + A_BUTTON + jr DisplayPlayAreaScreen + +OpenPlayAreaScreenForSelection: + ld a, START +; fallthrough + +DisplayPlayAreaScreen: + ld [wNoItemSelectionMenuKeys], a + ldh a, [hTempCardIndex_ff98] + push af + ld a, [wPlayAreaScreenLoaded] + or a + jr nz, .skip_ahead + xor a + ld [wSelectedDuelSubMenuItem], a + ld a, $01 + ld [wPlayAreaScreenLoaded], a +.asm_6022 + call ZeroObjectPositionsAndToggleOAMCopy + call EmptyScreen + call LoadSymbolsFont + call LoadDuelCardSymbolTiles + call LoadDuelCheckPokemonScreenTiles + call PrintPlayAreaCardList + call FlushAllPalettesIfNotDMG + call EnableLCD +.skip_ahead + ld hl, PlayAreaScreenMenuParameters_ActivePokemonIncluded + ld a, [wExcludeArenaPokemon] + or a + jr z, .init_menu_params + ld hl, PlayAreaScreenMenuParameters_ActivePokemonExcluded +.init_menu_params + ld a, [wSelectedDuelSubMenuItem] + call InitializeMenuParameters + ld a, [wNumPlayAreaItems] + ld [wNumScrollMenuItems], a +.asm_604c + call DoFrame + call SelectingBenchPokemonMenu + jr nc, .asm_6061 + cp $02 + jp z, .asm_60ac + cp $03 + jr z, .asm_6022 + pop af + ldh [hTempCardIndex_ff98], a + jr OpenPlayAreaScreenForSelection +.asm_6061 + call HandleMenuInput + jr nc, .asm_604c + ld a, e + ld [wSelectedDuelSubMenuItem], a + ld a, [wExcludeArenaPokemon] + add e + ld [wCurPlayAreaSlot], a + ld a, [wNoItemSelectionMenuKeys] + ld b, a + ldh a, [hKeysPressed] + and b + jr z, .asm_6091 + ld a, [wCurPlayAreaSlot] + add DUELVARS_ARENA_CARD + get_turn_duelist_var + cp -1 + jr z, .asm_6022 + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + call OpenCardPage_FromCheckPlayArea + jr .asm_6022 +.asm_6091 + ld a, [wExcludeArenaPokemon] + ld c, a + ldh a, [hCurScrollMenuItem] + add c + ldh [hTempPlayAreaLocation_ff9d], a + ldh a, [hCurScrollMenuItem] + cp $ff + jr z, .asm_60b5 + ldh a, [hTempPlayAreaLocation_ff9d] + add DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + or a + jr nz, .asm_60ac + jr .skip_ahead +.asm_60ac + pop af + ldh [hTempCardIndex_ff98], a + ldh a, [hTempPlayAreaLocation_ff9d] + ldh [hCurScrollMenuItem], a + or a + ret +.asm_60b5 + pop af + ldh [hTempCardIndex_ff98], a + ldh a, [hTempPlayAreaLocation_ff9d] + ldh [hCurScrollMenuItem], a + scf + ret + +PlayAreaScreenMenuParameters_ActivePokemonIncluded: + db 0, 0 ; cursor x, cursor y + db 3 ; y displacement between items + db 6 ; number of items + db SYM_CURSOR_R ; cursor tile number + db SYM_SPACE ; tile behind cursor + dw PlayAreaScreenMenuFunction ; function pointer if non-0 + +PlayAreaScreenMenuParameters_ActivePokemonExcluded: + db 0, 3 ; cursor x, cursor y + db 3 ; y displacement between items + db 6 ; number of items + db SYM_CURSOR_R ; cursor tile number + db SYM_SPACE ; tile behind cursor + dw PlayAreaScreenMenuFunction ; function pointer if non-0 + +PlayAreaScreenMenuFunction: + ldh a, [hKeysPressed] + and A_BUTTON | B_BUTTON | START + ret z + bit B_BUTTON_F, a + jr z, .start_or_a + ld a, $ff + ldh [hCurScrollMenuItem], a +.start_or_a + scf + ret + +SECTION "Bank 1@5b46", ROMX[$5b46], BANK[$1] + +SelectingBenchPokemonMenu: + ldh a, [hKeysPressed] + and SELECT + ret z ; Select not pressed + ld a, [wPlayAreaSelectAction] + or a + jr nz, .asm_5b76 + + ; get the energy cards attached to + ; selected Play Area Pokémon + ldh a, [hCurScrollMenuItem] + ld [wSelectedDuelSubMenuItem], a + ld e, a + ld a, [wExcludeArenaPokemon] + add e + ldh [hTempPlayAreaLocation_ff9d], a + call CreateArenaOrBenchEnergyCardList + jr c, .no_energy_cards + ldh a, [hTempPlayAreaLocation_ff9d] + ldtx de, Text00b3 + call DisplayAttachedEnergyMenu + ld a, $01 + ld [wcbeb], a + call HandleAttachedEnergyMenuInput +.no_energy_cards + ld a, $03 + scf + ret + +.asm_5b76 + ld a, [wPlayAreaSelectAction] + cp $02 + jr z, .return_carry + xor a + ld [wCurrentDuelMenuItem], a +.duel_main_scene + call DrawDuelMainScene + ldtx hl, Text005b ; SelectingBenchPokemonHandExamineBackText + call DrawWideTextBox_PrintTextNoDelay + call .InitMenu +.loop_input + call DoFrame + ldh a, [hKeysPressed] + and A_BUTTON + jr nz, .a_pressed + call .HandleInput + call RefreshMenuCursor + xor a + call HandleSpecialDuelMainSceneHotkeys + jr nc, .loop_input + ldh a, [hKeysPressed] + and SELECT + jr z, .duel_main_scene +.back + call HasAlivePokemonInBench + ld a, $01 + ld [wPlayAreaSelectAction], a +.return_carry + scf + ret + +.a_pressed + ld a, [wCurrentDuelMenuItem] + cp 2 + jr z, .back + or a + jr z, .check_hand +; examine + call OpenDuelCheckMenu + jr .duel_main_scene +.check_hand + call OpenTurnHolderHandScreen_Simple + jr .duel_main_scene + +.HandleInput: + ldh a, [hDPadHeld] + bit B_BUTTON_F, a + ret nz + and D_RIGHT | D_LEFT + ret z + + ; right or left pressed + ld b, a + ld a, [wCurrentDuelMenuItem] + bit D_LEFT_F, b + jr z, .right_pressed + dec a + bit 7, a + jr z, .got_menu_item + ld a, 2 + jr .got_menu_item +.right_pressed + inc a + cp 3 + jr c, .got_menu_item + xor a +.got_menu_item + ld [wCurrentDuelMenuItem], a + call EraseCursor +; fallthrough + +.InitMenu: + ld a, [wCurrentDuelMenuItem] + ld d, a + add a + add d + add a + add 2 + ld d, a + ld e, 16 + lb bc, SYM_CURSOR_R, SYM_SPACE + jp SetCursorParametersForTextBox +; 0x5bfd + +SECTION "Bank 1@5c47", ROMX[$5c47], BANK[$1] + +; for each turn holder's play area Pokemon card, print the name, level, +; face down stage card, color symbol, status symbol (if any), pluspower/defender +; symbols (if any), attached energies (if any), and HP bar. +; also print the play area locations (ACT/BPx indicators) for each of the six slots. +; return the value of wNumPlayAreaItems (as returned from PrintPlayAreaCardList) in a. +PrintPlayAreaCardList_EnableLCD: + ld a, PLAY_AREA_CARD_LIST + ld [wDuelDisplayedScreen], a + call PrintPlayAreaCardList + call EnableLCD + ld a, [wNumPlayAreaItems] + ret + +; for each turn holder's play area Pokemon card, print the name, level, +; face down stage card, color symbol, status symbol (if any), pluspower/defender +; symbols (if any), attached energies (if any), and HP bar. +; also print the play area locations (ACT/BPx indicators) for each of the six slots. +PrintPlayAreaCardList: + ld a, PLAY_AREA_CARD_LIST + ld [wDuelDisplayedScreen], a + ld de, wcbf5 + call SetListPointer2 + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld c, a + ld b, $00 +.print_cards_info_loop + ; for each Pokemon card in play area, print its information (and location) + push hl + push bc + ld a, b + ld [wCurPlayAreaSlot], a + ld a, b + add a + add b + ld [wCurPlayAreaY], a + ld a, b + add DUELVARS_ARENA_CARD + get_turn_duelist_var + call SetNextElementOfList2 + call PrintPlayAreaCardInformationAndLocation + pop bc + pop hl + inc b + dec c + jr nz, .print_cards_info_loop + push bc +.print_locations_loop + ; print all play area location indicators (even if there's no Pokemon card on it) + ld a, b + ld hl, wMaxNumPlayAreaPokemon + cp [hl] + jr nc, .locations_printed + ld [wCurPlayAreaSlot], a + add a + add b + ld [wCurPlayAreaY], a + push bc + call PrintPlayAreaCardLocation + pop bc + inc b + jr .print_locations_loop +.locations_printed + pop bc + ld a, b + ld [wNumPlayAreaItems], a + ld a, [wExcludeArenaPokemon] + or a + ret z + ; if wExcludeArenaPokemon is set, decrement [wNumPlayAreaItems] and shift back wcbf5 + dec b + ld a, b + ld [wNumPlayAreaItems], a + ld hl, wcbf5 + 1 + ld de, wcbf5 +.shift_back_loop + ld a, [hli] + ld [de], a + inc de + dec b + jr nz, .shift_back_loop + ret ; print a turn holder's play area Pokemon card's name, level, face down stage card, ; color symbol, status symbol (if any), pluspower/defender symbols (if any), @@ -1320,6 +4427,10 @@ PrintPlayAreaCardInformationAndLocation: cp -1 ret z call PrintPlayAreaCardInformation +; fallthrough + +; print a turn holder's play area Pokemon card's location (ACT/BPx indicator) +PrintPlayAreaCardLocation: ld de, PlayerPlayAreaLocationTileNumbers ldh a, [hWhoseTurn] cp PLAYER_TURN @@ -1702,7 +4813,123 @@ PrintPlayAreaCardAttachedEnergies: ret ; 0x5efe -SECTION "Bank 1@5fea", ROMX[$5fea], BANK[$1] +SECTION "Bank 1@5f0c", ROMX[$5f0c], BANK[$1] + +DisplayPlayAreaScreenToUsePkmnPower: + xor a + ld [wSelectedDuelSubMenuItem], a + +.asm_6435 + call .DrawScreen + ld hl, PlayAreaScreenMenuParameters_ActivePokemonIncluded + ld a, [wSelectedDuelSubMenuItem] + call InitializeMenuParameters + ld a, [wNumPlayAreaItems] + ld [wNumScrollMenuItems], a +.asm_6447 + call DoFrame + call HandleMenuInput + ldh [hTempPlayAreaLocation_ff9d], a + ld [wHUDEnergyAndHPBarsX], a + jr nc, .asm_6447 + cp $ff + jr z, .asm_649b + ld [wSelectedDuelSubMenuItem], a + ldh a, [hKeysPressed] + and START + jr nz, .asm_649d + ldh a, [hCurScrollMenuItem] + add a + ld e, a + ld d, $00 + ld hl, wDuelTempList + 1 + add hl, de + ld a, [hld] + cp $04 + jr nz, .asm_6447 + ld a, [hl] + ldh [hTempCardIndex_ff98], a + ld d, a + ld e, $00 + call CopyAttackDataAndDamage_FromDeckIndex + ld a, EFFECTCMDTYPE_INITIAL_EFFECT_1 + call TryExecuteEffectCommandFunction + jr nc, .asm_648c + ldtx hl, Text0041 ; PokemonPowerSelectNotRequiredText + farcall DisplayUsePokemonPowerScreen + call WaitForWideTextBoxInput + jp .asm_6435 +.asm_648c + ldtx hl, Text0040 ; UseThisPokemonPowerText + farcall DisplayUsePokemonPowerScreen + call YesOrNoMenu + jp c, .asm_6435 + ldh a, [hTempCardIndex_ff98] + ldh [hTemp_ffa0], a + or a + ret +.asm_649b + scf + ret +.asm_649d + ldh a, [hCurScrollMenuItem] + add DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + call OpenCardPage_FromCheckPlayArea + jp .asm_6435 + +.DrawScreen: + call ZeroObjectPositionsAndToggleOAMCopy + call EmptyScreen + call LoadDuelCardSymbolTiles + call LoadDuelCheckPokemonScreenTiles + ld de, wDuelTempList + call SetListPointer2 + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld c, a + ld b, $00 +.asm_64ca + push hl + push bc + ld a, b + ld [wHUDEnergyAndHPBarsX], a + ld a, b + add a + add b + ld [wCurPlayAreaY], a + ld a, b + add DUELVARS_ARENA_CARD + get_turn_duelist_var + call SetNextElementOfList2 + call PrintPlayAreaCardHeader + call PrintPlayAreaCardLocation + call .PrintCardNameIfHasPkmnPower + ld a, [wLoadedCard1Atk1Category] + call SetNextElementOfList2 + pop bc + pop hl + inc b + dec c + jr nz, .asm_64ca + ld a, b + ld [wNumPlayAreaItems], a + call EnableLCD + ret + +.PrintCardNameIfHasPkmnPower: + ld a, [wLoadedCard1Atk1Category] + cp POKEMON_POWER + ret nz + ld a, [wCurPlayAreaY] + inc a + ld e, a + ld d, 4 + ld hl, wLoadedCard1Atk1Name + call InitTextPrinting_ProcessTextFromPointerToID + ret ; print the description of an attack, a Pokemon power, or a trainer or energy card ; x,y coordinates of where to start printing the text are given at de @@ -1722,9 +4949,74 @@ PrintAttackOrCardDescription: call ProcessTextFromID call SetOneLineSeparation ret -; 0x6004 -SECTION "Bank 1@6061", ROMX[$6061], BANK[$1] +; moves the cards loaded by deck index at hTempRetreatCostCards to the discard pile +DiscardRetreatCostCards: + ld hl, hTempRetreatCostCards +.discard_loop + ld a, [hli] + cp $ff + ret z + call PutCardInDiscardPile + jr .discard_loop + +; moves the discard pile cards that were loaded to hTempRetreatCostCards back to the active Pokemon. +; this exists because they will be discarded again during the call to AttemptRetreat, so +; it prevents the energy cards from being discarded twice. +ReturnRetreatCostCardsToArena: + ld hl, hTempRetreatCostCards +.loop + ld a, [hli] + cp $ff + ret z + push hl + call MoveDiscardPileCardToHand + call AddCardToHand + ld e, PLAY_AREA_ARENA + call PutHandCardInPlayArea + pop hl + jr .loop + +; discard retreat cost energy cards and attempt retreat of the arena card. +; return carry if unable to retreat this turn due to unsuccessful confusion check +; if successful, the retreated card is replaced with a bench Pokemon card +AttemptRetreat: + ld hl, hTempRetreatCostCards +.discard_loop + ld a, [hli] + cp $ff + jr z, .asm_6033 + call Func_0ffa + jr .discard_loop + +.asm_6033 + ldh a, [hTemp_ffa0] + and CNF_SLP_PRZ + cp CONFUSED + jr nz, .success + ldtx de, Text0118 ; ConfusionCheckRetreatText + call TossCoin + jr c, .success + ld a, 1 + ld [wGotHeadsFromConfusionCheckDuringRetreat], a + scf + ret +.success + xor a + ld [wGotHeadsFromConfusionCheckDuringRetreat], a + + call HandleRetreatPkmnPowers + ld a, DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + + push af + ldh a, [hTempPlayAreaLocation_ffa1] + ld e, a + call SwapArenaWithBenchPokemon + call Func_6518 + pop af + or a + ret WriteTwoByteNumberInTxSymbolFormat: push de @@ -1866,7 +5158,1047 @@ LoadPlayerDeck: ret ; 0x6128 -SECTION "Bank 1@6897", ROMX[$6897], BANK[$1] +SECTION "Bank 1@6128", ROMX[$6128], BANK[$1] + +; returns carry if wSkipDelayAllowed is non-0 and B is being held in order to branch +; out of the caller's wait frames loop. probably only used for debugging. +CheckSkipDelayAllowed: + ld a, [wSkipDelayAllowed] + or a + ret z + ldh a, [hKeysHeld] + and B_BUTTON + ret z + scf + ret + +; handles the key shortcuts to access some duel functions +; while inside the Duel Main scene in some situations +; (while waiting for Link Opponent's turn & when +; selecting a bench Pokémon, and choosing 'Examine') +; hotkeys: +; - Start = Arena's card page +; - Select = if a == 0: In Play Area +; otherwise: In Play Area then both Play Areas +; - B + down = player's Play Area +; - B + left = player's Discard Pile +; - B + up = opponent's Play Area +; - B + right = opponent's Discard Pile +HandleSpecialDuelMainSceneHotkeys: + ld [wDuelMainSceneSelectHotkeyAction], a + ldh a, [hKeysPressed] + bit START_F, a + jr nz, .start_pressed + bit SELECT_F, a + jr nz, .select_pressed + ldh a, [hKeysHeld] + and B_BUTTON + ret z ; exit if no B btn + ldh a, [hKeysPressed] + bit D_DOWN_F, a + jr nz, .down_pressed + bit D_LEFT_F, a + jr nz, .left_pressed + bit D_UP_F, a + jr nz, .up_pressed + bit D_RIGHT_F, a + jr nz, .right_pressed + or a + ret +.start_pressed + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + cp -1 + jr z, .return_carry + call GetCardIDFromDeckIndex + call LoadCardDataToBuffer1_FromCardID + ld hl, wCurPlayAreaSlot + xor a + ld [hli], a + ld [hl], a ; wCurPlayAreaY + call OpenCardPage_FromCheckPlayArea +.return_carry + scf + ret +.select_pressed + ld a, [wDuelMainSceneSelectHotkeyAction] + or a + jr nz, .both_duelist_play_areas + call OpenInPlayAreaScreen_FromSelectButton + jr .return_carry +.both_duelist_play_areas + call Func_4597 + jr .return_carry +.down_pressed + call OpenTurnHolderPlayAreaScreen + jr .return_carry +.left_pressed + call OpenTurnHolderDiscardPileScreen + jr .return_carry +.up_pressed + call OpenNonTurnHolderPlayAreaScreen + jr .return_carry +.right_pressed + call OpenNonTurnHolderDiscardPileScreen + jr .return_carry + +Func_6196: + ld hl, wTempTurnDuelistCardID + ld [wccd8], a + jr Func_61a4 + +Func_619e: + ld hl, wTempNonTurnDuelistCardID + ld [wccd9], a +; fallthrough + +Func_61a4: + push de + push hl + add DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + pop hl + ld [hl], e + inc hl + ld [hl], d + pop de + ret + +; when playing a Pokemon card, initializes some variables according to the +; card played, and checks if the played card has Pokemon Power to show it to +; the player, and possibly to use it if it triggers when the card is played. +ProcessPlayedPokemonCard: + ldh a, [hTempCardIndex_ff98] + ldh [hTempCardIndex_ff9f], a + ldh a, [hTempPlayAreaLocation_ff9d] + ldh [hTemp_ffa0], a + ld a, OPPACTION_UNK_18 + call SetOppAction_SerialSendDuelData + call .Process + ret c + ld a, EFFECTCMDTYPE_REQUIRE_SELECTION + call TryExecuteEffectCommandFunction + ld a, OPPACTION_UNK_19 + call SetOppAction_SerialSendDuelData + call .TriggerPkmnPower + ret + +.Process: + ldh a, [hTempCardIndex_ff9f] + ldh [hTempCardIndex_ff98], a + call ClearChangedTypesIfMuk + ldh a, [hTempCardIndex_ff9f] + ld d, a + ld e, $00 + call CopyAttackDataAndDamage_FromDeckIndex + call ClearTwoTurnDuelVars + ldh a, [hTempCardIndex_ff9f] + call GetCardIDFromDeckIndex + ld hl, wTempTurnDuelistCardID + ld [hl], e + inc hl + ld [hl], d + ld a, [wLoadedAttackCategory] + cp POKEMON_POWER + jr nz, .not_using_pkmn_power + + ; has Pkmn Power + ldh a, [hTempCardIndex_ff98] + call LoadCardDataToBuffer1_FromDeckIndex + ld hl, wLoadedCard1Name + ld a, [hli] + ld h, [hl] + ld l, a + call LoadTxRam2 + ldtx hl, Text0085 ; HavePokemonPowerText + farcall DisplayUsePokemonPowerScreen + call WaitForWideTextBoxInput + ld hl, wLoadedCard1ID + inc hl + ld a, [hld] + cp HIGH(MUK) + jr nz, .asm_6219 + ld a, [hl] + cp LOW(MUK) +.asm_6219 + jr z, .use_pokemon_power + ldh a, [hTempPlayAreaLocation_ff9d] + call CheckIsIncapableOfUsingPkmnPower + jr nc, .use_pokemon_power + ldtx hl, Text0086 ; UnableToUsePkmnPowerDueToGoopGasAttack + dec a + jr nz, .asm_622b + ldtx hl, Text0087 ; UnableToUsePkmnPowerDueToToxicGasText +.asm_622b + call DrawWideTextBox_WaitForInput + +.not_using_pkmn_power + xor a + ld [wcd18], a + scf + ret + +.use_pokemon_power + ld hl, wLoadedAttackEffectCommands + ld a, [hli] + ld h, [hl] + ld l, a + ld a, EFFECTCMDTYPE_PKMN_POWER_TRIGGER + call CheckMatchingCommand + jr c, .not_using_pkmn_power + call DrawDuelMainScene + ldh a, [hTempCardIndex_ff9f] + call LoadCardDataToBuffer1_FromDeckIndex + ld de, wLoadedCard1Name + ld hl, wTxRam2 + ld a, [de] + inc de + ld [hli], a + ld a, [de] + ld [hli], a + ld de, wLoadedAttackName + ld a, [de] + inc de + ld [hli], a + ld a, [de] + ld [hl], a + ldtx hl, Text005e ; WillUseThePokemonPowerText + call DrawWideTextBox_WaitForInput + ld a, $01 + ld [wcd18], a + or a + ret + +.TriggerPkmnPower: + farcall Func_18a14 + ld a, EFFECTCMDTYPE_PKMN_POWER_TRIGGER + call TryExecuteEffectCommandFunction + ret + +; apply and/or refresh status conditions and other events that trigger between turns +HandleBetweenTurnsEvents: + call IsArenaPokemonAsleepOrPoisoned + jr c, .something_to_handle + cp PARALYZED + jr z, .something_to_handle + call SwapTurn + call IsArenaPokemonAsleepOrPoisoned + call SwapTurn + jr c, .something_to_handle + call DiscardAttachedPluspowers + call SwapTurn + call DiscardAttachedDefenders + call SwapTurn + ret + +.something_to_handle + ; either: + ; 1. turn holder's arena Pokemon is paralyzed, asleep, poisoned or double poisoned + ; 2. non-turn holder's arena Pokemon is asleep, poisoned or double poisoned + call ResetAnimationQueue + call ZeroObjectPositionsAndToggleOAMCopy + call EmptyScreen + ld a, BOXMSG_BETWEEN_TURNS + call DrawDuelBoxMessage + ldtx hl, Text002c ; BetweenTurnsText + call DrawWideTextBox_WaitForInput + + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + ld a, e + ld [wTempNonTurnDuelistCardID + 0], a + ld a, d + ld [wTempNonTurnDuelistCardID + 1], a + ld l, DUELVARS_ARENA_CARD_STATUS + ld a, [hl] + or a + jr z, .discard_pluspower + ; has status condition + call HandlePoisonDamage + jr c, .discard_pluspower + call HandleSleepCheck + ld a, [hl] + and CNF_SLP_PRZ + cp PARALYZED + jr nz, .discard_pluspower + ; heal paralysis + ld a, DOUBLE_POISONED + and [hl] + ld [hl], a + call RedrawTurnDuelistsMainSceneOrDuelHUD + ldtx hl, Text002b ; IsCuredOfParalysisText + call PrintCardNameFromCardIDInTextBox + ld a, DUEL_ANIM_HEAL + call PlayBetweenTurnsAnimation + call WaitForWideTextBoxInput + +.discard_pluspower + call DiscardAttachedPluspowers + call SwapTurn + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + ld a, e + ld [wTempNonTurnDuelistCardID + 0], a + ld a, d + ld [wTempNonTurnDuelistCardID + 1], a + ld l, DUELVARS_ARENA_CARD_STATUS + ld a, [hl] + or a + jr z, .asm_6c3a + call HandlePoisonDamage + jr c, .asm_6c3a + call HandleSleepCheck +.asm_6c3a + call DiscardAttachedDefenders + call SwapTurn + call HandleBetweenTurnKnockOuts + ret + +; discard any PLUSPOWER attached to the turn holder's arena and/or bench Pokemon +DiscardAttachedPluspowers: + ld a, DUELVARS_ARENA_CARD_ATTACHED_PLUSPOWER + get_turn_duelist_var + ld e, MAX_PLAY_AREA_POKEMON + xor a +.unattach_pluspower_loop + ld [hli], a + dec e + jr nz, .unattach_pluspower_loop + ld de, PLUSPOWER + jp MoveCardToDiscardPileIfInArena + +; discard any DEFENDER attached to the turn holder's arena and/or bench Pokemon +DiscardAttachedDefenders: + ld a, DUELVARS_ARENA_CARD_ATTACHED_DEFENDER + get_turn_duelist_var + ld e, MAX_PLAY_AREA_POKEMON + xor a +.unattach_defender_loop + ld [hli], a + dec e + jr nz, .unattach_defender_loop + ld de, DEFENDER + jp MoveCardToDiscardPileIfInArena + +; return carry if the turn holder's arena Pokemon card is asleep, poisoned, or double poisoned. +; also, if confused, paralyzed, or asleep, return the status condition in a. +IsArenaPokemonAsleepOrPoisoned: + ld a, DUELVARS_ARENA_CARD_STATUS + get_turn_duelist_var + or a + ret z + ; note that POISONED | DOUBLE_POISONED is the same as just DOUBLE_POISONED ($c0) + ; poison status masking is normally done with PSN_DBLPSN ($f0) + and POISONED | DOUBLE_POISONED + jr nz, .set_carry + ld a, [hl] + and CNF_SLP_PRZ + cp ASLEEP + jr z, .set_carry + or a + ret +.set_carry + scf + ret + +RedrawTurnDuelistsMainSceneOrDuelHUD: + ld a, [wDuelDisplayedScreen] + cp DUEL_MAIN_SCENE + jr z, RedrawTurnDuelistsDuelHUD + ld hl, wWhoseTurn + ldh a, [hWhoseTurn] + cp [hl] + jp z, DrawDuelMainScene + call SwapTurn + call DrawDuelMainScene + call SwapTurn + ret + +RedrawTurnDuelistsDuelHUD: + ld hl, wWhoseTurn + ldh a, [hWhoseTurn] + cp [hl] + jp z, DrawDuelHUDs + call SwapTurn + call DrawDuelHUDs + call SwapTurn + ret + +; input: +; a = animation ID +PlayBetweenTurnsAnimation: + push af + ld a, [wDuelType] + or a + jr nz, .store_duelist_turn + ld a, [wWhoseTurn] + cp PLAYER_TURN + jr z, .store_duelist_turn + call SwapTurn + ldh a, [hWhoseTurn] + ld [wDuelAnimDuelistSide], a + call SwapTurn + jr .asm_6ccb + +.store_duelist_turn + ldh a, [hWhoseTurn] + ld [wDuelAnimDuelistSide], a + +.asm_6ccb + xor a + ld [wDuelAnimLocationParam], a + ld a, DUEL_ANIM_SCREEN_MAIN_SCENE + ld [wDuelAnimationScreen], a + pop af + +; play animation + call PlayDuelAnimation +.loop_anim + call DoFrame + call CheckAnyAnimationPlaying + jr c, .loop_anim + call RedrawTurnDuelistsDuelHUD + ret + +; prints the name of the card at wTempNonTurnDuelistCardID in a text box +PrintCardNameFromCardIDInTextBox: + push hl + ld hl, wTempNonTurnDuelistCardID + ld e, [hl] + inc hl + ld d, [hl] + call LoadCardDataToBuffer1_FromCardID + ld hl, wLoadedCard1Name + ld a, [hli] + ld h, [hl] + ld l, a + call LoadTxRam2 + pop hl + call DrawWideTextBox_PrintText + ret + +; handles the sleep check for the NonTurn Duelist +; heals sleep status if coin is heads, else +; it plays sleeping animation +HandleSleepCheck: + ld a, [hl] + and CNF_SLP_PRZ + cp ASLEEP + ret nz ; quit if not asleep + + push hl + ld hl, wTempNonTurnDuelistCardID + ld e, [hl] + inc hl + ld d, [hl] + call LoadCardDataToBuffer1_FromCardID + ld a, 18 + call CopyCardNameAndLevel + ld [hl], TX_END + ld hl, wTxRam2 + xor a + ld [hli], a + ld [hl], a + ldtx de, Text0119 ; PokemonsSleepCheckText + call TossCoin + ld a, DUEL_ANIM_SLEEP + ldtx hl, Text0029 ; IsStillAsleepText + jr nc, .tails + +; coin toss was heads, cure sleep status + pop hl + push hl + ld a, DOUBLE_POISONED + and [hl] + ld [hl], a + ld a, DUEL_ANIM_HEAL + ldtx hl, Text002a ; IsCuredOfSleepText + +.tails + push af + push hl + call RedrawTurnDuelistsMainSceneOrDuelHUD + pop hl + call PrintCardNameFromCardIDInTextBox + pop af + call PlayBetweenTurnsAnimation + pop hl + call WaitForWideTextBoxInput + ret + +HandlePoisonDamage: + or a + bit POISONED_F , [hl] + ret z ; quit if not poisoned + +; load damage and text according to normal/double poison + push hl + bit DOUBLE_POISONED_F, [hl] + ld a, DBLPSN_DAMAGE + ldtx hl, Text0028 ; Received20DamageDueToPoisonText + jr nz, .got_damage + call GetPoisonDamage + ldtx hl, Text0027 ; Received10DamageDueToPoisonText + +.got_damage + push af + push hl + ld l, a + ld [wDuelAnimDamage + 0], a + xor a + ld h, a + ld [wDuelAnimDamage + 1], a + call LoadTxRam3 + call RedrawTurnDuelistsMainSceneOrDuelHUD + pop hl + call PrintCardNameFromCardIDInTextBox + +; play animation + ld a, DUEL_ANIM_POISON + call PlayBetweenTurnsAnimation + pop af + +; deal poison damage + ld e, a + ld d, $00 + ld a, DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + call SubtractHP + push hl + ld a, $8d + call PlayBetweenTurnsAnimation + pop hl + + call PrintKnockedOutIfHLZero + push af + call WaitForWideTextBoxInput + pop af + pop hl + ret + +; move the turn holder's card with ID at de to the discard pile +; if it's currently in the arena. +MoveCardToDiscardPileIfInArena: + ld c, e + ld b, d + ld l, DUELVARS_CARD_LOCATIONS +.next_card + ld a, [hl] + and CARD_LOCATION_ARENA + jr z, .skip ; jump if card not in arena + ld a, l + call GetCardIDFromDeckIndex + ld a, c + cp e + jr nz, .skip + ld a, b + cp d + jr nz, .skip ; jump if not the card id provided in de + ld a, l + push bc + call Func_0ffa + pop bc +.skip + inc l + ld a, l + cp DECK_SIZE + jr c, .next_card + ret +; 0x6470 + +SECTION "Bank 1@6518", ROMX[$6518], BANK[$1] + +Func_6518: + call Func_7234 +; fallthrough + +HandleBetweenTurnKnockOuts: + call .ClearDamageReductionSubstatus2OfKnockedOutPokemon + xor a + ld [wDuelFinishParam], a + call SwapTurn + call .Func_6ef6 + call SwapTurn + ld a, [wDuelFinishParam] + or a + jr z, .asm_6e86 + call CheckIfTurnDuelistPlayAreaPokemonAreAllKnockedOut + jr c, .asm_6e86 + call CountKnockedOutPokemon + ld c, a + call SwapTurn + call CountPrizes + call SwapTurn + dec a + cp c + jr c, .asm_6e86 + ld a, c + call SwapTurn + call TakeAPrizes + call SwapTurn + ld a, TURN_PLAYER_WON + jr .set_duel_finished +.asm_6e86 + call .Func_6ef6 + ld a, [wDuelFinishParam] + cp TRUE + jr nz, .asm_6e9f + call SwapTurn + call CheckIfTurnDuelistPlayAreaPokemonAreAllKnockedOut + call SwapTurn + jr c, .asm_6e9f + ld a, TURN_PLAYER_LOST + jr .set_duel_finished +.asm_6e9f + call SwapTurn + call .Func_6eff + call SwapTurn + call .Func_6eff + ld a, [wDuelFinishParam] + or a + jr nz, .asm_6ec4 + xor a +.asm_6eb2 + push af + call MoveAllTurnHolderKnockedOutPokemonToDiscardPile + call SwapTurn + call MoveAllTurnHolderKnockedOutPokemonToDiscardPile + call SwapTurn + call ShiftAllPokemonToFirstPlayAreaSlots + call Func_7943 + pop af + ret + +.asm_6ec4 + ld e, a + ld d, $00 + ld hl, .Data_6ed2 + add hl, de + ld a, [hl] +.set_duel_finished + ld [wDuelFinished], a + scf + jr .asm_6eb2 + +.Data_6ed2: + db DUEL_NOT_FINISHED, TURN_PLAYER_LOST, TURN_PLAYER_WON, TURN_PLAYER_TIED + db TURN_PLAYER_LOST, TURN_PLAYER_LOST, TURN_PLAYER_TIED, TURN_PLAYER_LOST + db TURN_PLAYER_WON, TURN_PLAYER_TIED, TURN_PLAYER_WON, TURN_PLAYER_WON + db TURN_PLAYER_TIED, TURN_PLAYER_LOST, TURN_PLAYER_WON, TURN_PLAYER_TIED + +; clears SUBSTATUS2_REDUCE_BY_20, SUBSTATUS2_POUNCE, SUBSTATUS2_GROWL, +; SUBSTATUS2_TAIL_WAG, and SUBSTATUS2_LEER for each arena Pokemon with 0 HP +.ClearDamageReductionSubstatus2OfKnockedOutPokemon: + call SwapTurn + call .clear + call SwapTurn +.clear + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + or a + ret nz + call ClearDamageReductionSubstatus2 + ret + +.Func_6ef6: + call Func_6fa5 + ld hl, wDuelFinishParam + rl [hl] + ret + +.Func_6eff: + call ReplaceKnockedOutPokemon + ld hl, wDuelFinishParam + rl [hl] + ret + +; for each Pokemon in the turn holder's play area (arena and bench), +; move that card to the discard pile if its HP is 0 +MoveAllTurnHolderKnockedOutPokemonToDiscardPile: + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld d, a + ld l, DUELVARS_ARENA_CARD_HP + ld e, PLAY_AREA_ARENA +.loop + ld a, [hl] + or a + jr nz, .next + push hl + push de + call Func_12fc + pop de + pop hl +.next + inc hl + inc e + dec d + jr nz, .loop + ret + +; have the turn holder replace the arena Pokemon card when it's been knocked out. +; if there are no Pokemon cards in the turn holder's bench, return carry. +ReplaceKnockedOutPokemon: + ld a, DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + or a + ret nz + call FinishQueuedAnimations + call ClearAllStatusConditions + call HasAlivePokemonInBench + jr nc, .can_replace_pokemon + +; if we made it here, the duelist can't replace the knocked out Pokemon + call DrawDuelMainScene + ldtx hl, Text0083 ; ThereAreNoPokemonInPlayAreaText + call DrawWideTextBox_WaitForInput + call ExchangeRNG + scf + ret + +.can_replace_pokemon + ld a, DUELVARS_DUELIST_TYPE + get_turn_duelist_var + cp DUELIST_TYPE_PLAYER + jr nz, .opponent + +; prompt the player to replace the knocked out Pokemon with one from bench + call DrawDuelMainScene + ldtx hl, Text0165 ; SelectPokemonToPlaceInTheArenaText + call DrawWideTextBox_WaitForInput + ld a, $01 + ld [wPlayAreaSelectAction], a + ld a, PRACTICEDUEL_PLAY_STARYU_FROM_BENCH + call DoPracticeDuelAction +.select_pokemon + call OpenPlayAreaScreenForSelection + jr c, .select_pokemon + ldh a, [hTempPlayAreaLocation_ff9d] + call SerialSend8Bytes + +; replace the arena Pokemon with the one at location [hTempPlayAreaLocation_ff9d] +.replace_pokemon + ld a, PRACTICEDUEL_REPLACE_KNOCKED_OUT_POKEMON + call DoPracticeDuelAction + jr c, .select_pokemon + ldh a, [hTempPlayAreaLocation_ff9d] + ld d, a + ld e, PLAY_AREA_ARENA + call SwapPlayAreaPokemon + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + ldtx hl, Text0045 ; DuelistPlacedACardText + call DisplayCardDetailScreen + call ExchangeRNG + or a + ret + +; the AI opponent replaces the knocked out Pokemon with one from bench +.opponent + cp DUELIST_TYPE_LINK_OPP + jr z, .link_opponent + call AIDoAction_KOSwitch + ldh a, [hTemp_ffa0] + ldh [hTempPlayAreaLocation_ff9d], a + jr .replace_pokemon + +; wait for link opponent to replace the knocked out Pokemon with one from bench +.link_opponent + call DrawDuelMainScene + ldtx hl, Text0166 ; DuelistIsSelectingPokemonToPlaceInArenaText + call DrawWideTextBox_PrintText + call SerialRecv8Bytes + ldh [hTempPlayAreaLocation_ff9d], a + jr .replace_pokemon + +Func_6fa5: + call CountKnockedOutPokemon + ret nc + ; at least one Pokemon knocked out + call SwapTurn + call TurnDuelistTakePrizes + call SwapTurn + ret nc + call SwapTurn + call DrawDuelMainScene + ldtx hl, Text0082 ; TookAllThePrizesText + call DrawWideTextBox_WaitForInput + call ExchangeRNG + call SwapTurn + scf + ret + +; return in wNumberPrizeCardsToTake the amount of Pokemon in the turn holder's +; play area that are still there despite having 0 HP. +; that is, the number of Pokemon that have just been knocked out. +; Clefairy Doll and Mysterious Fossil don't count. +CountKnockedOutPokemon: + ld a, DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + ld d, h + ld e, DUELVARS_ARENA_CARD + ld b, PLAY_AREA_ARENA + ld c, MAX_PLAY_AREA_POKEMON +.loop + ld a, [de] + cp -1 + jr z, .next ; jump if no Pokemon in this location + ld a, [hl] + or a + jr nz, .next ; jump if this Pokemon's HP isn't 0 + ; this Pokemon's HP has just become 0 + ld a, [de] + push de + call GetCardIDFromDeckIndex + call GetCardType + pop de + cp TYPE_TRAINER + jr z, .next ; jump if this is a trainer card (Clefairy Doll or Mysterious Fossil) + inc b +.next + inc hl + inc de + dec c + jr nz, .loop + ld a, b + ld [wNumberPrizeCardsToTake], a + or a + ret z + scf + ret + +; returns carry if turn duelist has no Play Area Pokémon +; with non-zero HP, that is, all Pokémon are knocked out +CheckIfTurnDuelistPlayAreaPokemonAreAllKnockedOut: + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld c, a + ld l, DUELVARS_ARENA_CARD_HP +.loop + ld a, [hli] + or a + jr nz, .non_zero_hp + dec c + jr nz, .loop + scf + ret +.non_zero_hp + or a + ret +; 0x66d0 + +SECTION "Bank 1@6774", ROMX[$6774], BANK[$1] + +; initializes variables when a duel begins, such as zeroing wDuelFinished or wDuelTurns, +; and setting wDuelType based on wPlayerDuelistType and wOpponentDuelistType +InitVariablesToBeginDuel: + xor a + ld [wDuelFinished], a + ld [wDuelTurns], a + ld [wccfc], a + ld [wGoopGasAttackActive], a + ld [wcc07], a + + ld a, $ff + ld [wcc0f], a + ld [wPlayerAttackingCardIndex], a + ld [wPlayerAttackingAttackIndex], a + + ld a, [wdc08] + ld [wcc19], a + call Func_6838 + + ld b, MAX_PLAY_AREA_POKEMON + ld a, [wSpecialRule] + cp SMALL_BENCH + jr nz, .got_bench_size + ld b, MAX_SMALL_BENCH_PLAY_AREA_POKEMON +.got_bench_size + ld a, b + ld [wMaxNumPlayAreaPokemon], a + + call GetDuelInitialPrizesBits + ld [wPlayerPrizes], a + ld [wOpponentPrizes], a + + ld a, [wPlayerDuelistType] + cp DUELIST_TYPE_LINK_OPP + jr z, .set_duel_type + bit 7, a ; DUELIST_TYPE_AI_OPP + jr nz, .set_duel_type + ld a, [wOpponentDuelistType] + cp DUELIST_TYPE_LINK_OPP + jr z, .set_duel_type + bit 7, a ; DUELIST_TYPE_AI_OPP + jr nz, .set_duel_type + xor a +.set_duel_type + ld [wDuelType], a + ret + +; init variables that last a single player's turn +InitVariablesToBeginTurn: + xor a + ld [wAlreadyPlayedEnergy], a + ld [wGotHeadsFromConfusionCheckDuringRetreat], a + ld [wcc03], a + ld [wcd09], a + ld [wEffectFailed], a + ld [wMetronomeEnergyCost], a + ld a, $ff + ld [wcc1b], a + ldh a, [hWhoseTurn] + ld [wWhoseTurn], a + farcall Func_18a14 + ret + +; make all Pokemon in the turn holder's play area able to evolve. called from the +; player's second turn on, in order to allow evolution of all Pokemon already played. +SetAllPlayAreaPokemonCanEvolve: + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld c, a + ld l, DUELVARS_ARENA_CARD_FLAGS +.loop_turn_holder_play_area + res PLAY_AREA_FLAG_UNK_2_F, [hl] + res USED_PKMN_POWER_THIS_TURN_F, [hl] + set CAN_EVOLVE_THIS_TURN_F, [hl] + inc l + dec c + jr nz, .loop_turn_holder_play_area + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + ld c, a + ld l, DUELVARS_ARENA_CARD_FLAGS +.loop_non_turn_holder_play_area + res PLAY_AREA_FLAG_UNK_2_F, [hl] + inc l + dec c + jr nz, .loop_non_turn_holder_play_area + ret + +; initializes duel variables such as cards in deck and in hand, or Pokemon in play area +; player turn: [c200, c2ff] +; opponent turn: [c300, c3ff] +InitializeDuelVariables: + ldh a, [hWhoseTurn] + ld h, a + ld l, DUELVARS_DUELIST_TYPE + ld a, [hl] + push hl + push af + xor a + ld l, a +.zero_duel_variables_loop + ld [hl], a + inc l + jr nz, .zero_duel_variables_loop + pop af + pop hl + ld [hl], a + lb bc, DUELVARS_CARD_LOCATIONS, DECK_SIZE + ld l, DUELVARS_DECK_CARDS +.init_duel_variables_loop +; zero card locations and cards in hand, and init order of cards in deck + push hl + ld [hl], b + ld l, b + ld [hl], $0 + pop hl + inc l + inc b + dec c + jr nz, .init_duel_variables_loop + ld l, DUELVARS_ARENA_CARD + ld c, MAX_PLAY_AREA_POKEMON + 1 +.init_play_area +; initialize to $ff card in arena as well as cards in bench (plus a terminator) + ld [hl], -1 + inc l + dec c + jr nz, .init_play_area + ret + +Func_6838: + call EnableSRAM + ld a, [sSkipDelayAllowed] + ld [wSkipDelayAllowed], a + ld a, [s0a00b] + ld [wcd14], a + call DisableSRAM + ret + +; draw [wDuelInitialPrizes] cards from the turn holder's deck and place them as prizes: +; write their deck indexes to DUELVARS_PRIZE_CARDS, set their location to +; CARD_LOCATION_PRIZE, and set [wDuelInitialPrizes] bits of DUELVARS_PRIZES. +InitTurnDuelistPrizes: + ldh a, [hWhoseTurn] + ld d, a + ld e, DUELVARS_PRIZE_CARDS + ld a, [wDuelInitialPrizes] + ld c, a + ld b, 0 +.draw_prizes_loop + call DrawCardFromDeck + ld [de], a + inc de + ld h, d + ld l, a + ld [hl], CARD_LOCATION_PRIZE + inc b + ld a, b + cp c + jr nz, .draw_prizes_loop + call GetDuelInitialPrizesBits + ld l, DUELVARS_PRIZES + ld [hl], a + ret + +; calculates bits set up to the number of initial prizes: +GetDuelInitialPrizesBits: + push hl + ld a, [wDuelInitialPrizes] + ld e, a + ld d, $00 + ld hl, PrizeBitmasks + add hl, de + ld a, [hl] + pop hl + ret + +PrizeBitmasks: + db %000000 ; 0 + db %000001 ; PRIZES_1 + db %000011 ; PRIZES_2 + db %000111 ; PRIZES_3 + db %001111 ; PRIZES_4 + db %011111 ; PRIZES_5 + db %111111 ; PRIZES_6 + +; update the turn holder's DUELVARS_PRIZES following that duelist +; drawing a number of prizes equal to register a +TakeAPrizes: + or a + ret z + ld c, a + call CountPrizes + sub c + jr nc, .no_underflow + xor a +.no_underflow + ld c, a + ld b, $00 + ld hl, PrizeBitmasks + add hl, bc + ld b, [hl] + ld a, DUELVARS_PRIZES + get_turn_duelist_var + ld [hl], b + ret ; writes the cards in de to hl ; in a compressed format @@ -1933,7 +6265,180 @@ DecompressSRAMDeck: pop de pop hl ret -; 0x68da + +; outputs in wAttackEnergyCost the energy cost of one of wLoadedCard1's attacks +; input: +; d = deck index of card (0 to 59) +; e = attack index (0 or 1) +; returns: carry if not a valid attack +GetLoadedAttackEnergyCost: + ld c, e + ld a, d + call LoadCardDataToBuffer1_FromDeckIndex + ld de, wLoadedCard1Atk1EnergyCost + dec c + jr nz, .got_atk + ld de, wLoadedCard1Atk2EnergyCost + +.got_atk + ld hl, CARD_DATA_ATTACK1_NAME - CARD_DATA_ATTACK1_ENERGY_COST + add hl, de + ld a, [hli] + or [hl] + jr z, .set_carry + ld hl, CARD_DATA_ATTACK1_CATEGORY - CARD_DATA_ATTACK1_ENERGY_COST + add hl, de + ld a, [hl] + cp POKEMON_POWER + jr z, .set_carry + ld c, (NUM_TYPES) / 2 + ld hl, wAttackEnergyCost + +.next_energy_type_pair + ld a, [de] + swap a + and $0f + ld [hli], a + ld a, [de] + and $0f + ld [hli], a + inc de + dec c + jr nz, .next_energy_type_pair + or a + ret +.set_carry + scf + ret + +; play the trainer card with deck index at hTempCardIndex_ff98. +; a trainer card is like an attack effect, with its own effect commands. +; return nc if the card was played, carry if it wasn't. +PlayTrainerCard: + call CheckCantUseTrainerDueToEffect + jr c, .cant_use + ldh a, [hWhoseTurn] + ld h, a + ldh a, [hTempCardIndex_ff98] + ldh [hTempCardIndex_ff9f], a + call LoadNonPokemonCardEffectCommands + ld a, EFFECTCMDTYPE_INITIAL_EFFECT_1 + call TryExecuteEffectCommandFunction + jr nc, .can_use +.cant_use + call DrawWideTextBox_WaitForInput + scf + ret +.can_use + ld a, EFFECTCMDTYPE_INITIAL_EFFECT_2 + call TryExecuteEffectCommandFunction + jr c, .done + ld a, OPPACTION_PLAY_TRAINER + call SetOppAction_SerialSendDuelData + farcall DisplayUsedTrainerCardDetailScreen + call ExchangeRNG + ld a, EFFECTCMDTYPE_DISCARD_ENERGY + call TryExecuteEffectCommandFunction + ld a, EFFECTCMDTYPE_REQUIRE_SELECTION + call TryExecuteEffectCommandFunction + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + call SetOppAction_SerialSendDuelData + ld a, EFFECTCMDTYPE_BEFORE_DAMAGE + call TryExecuteEffectCommandFunction + ldh a, [hTempCardIndex_ff9f] + call MoveHandCardToDiscardPile + call ExchangeRNG + ld a, [wcd15] + cp $ff + jr z, .done + ldh [hTempCardIndex_ff98], a + call ProcessPlayedPokemonCard +.done + or a + ret + +; loads the effect commands of a (trainer or energy) card with deck index (0-59) at hTempCardIndex_ff9f +; into wLoadedAttackEffectCommands. in practice, only used for trainer cards +LoadNonPokemonCardEffectCommands: + ldh a, [hTempCardIndex_ff9f] + call LoadCardDataToBuffer1_FromDeckIndex + ld hl, wLoadedCard1EffectCommands + ld de, wLoadedAttackEffectCommands + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + ld a, DUELVARS_ARENA_CARD_SUBSTATUS1 + call GetNonTurnDuelistVariable + ld [wcd0b], a + ld a, $ff + ld [wcd15], a + ret + +Func_6986: + ldh a, [hTempCardIndex_ff98] + ldh [hTempCardIndex_ff9f], a + call LoadNonPokemonCardEffectCommands + ld hl, wLoadedAttackEffectCommands + ld a, [hli] + ld h, [hl] + ld l, a + ld a, EFFECTCMDTYPE_PKMN_POWER_TRIGGER + call CheckMatchingCommand + ret c + farcall Func_18a14 + ld a, EFFECTCMDTYPE_PKMN_POWER_TRIGGER + call TryExecuteEffectCommandFunction + ret + +; returns carry if Black Hole rule is active +; when attempting to open the Discard Pile +IsBlackHoleRuleActive: + ld a, [wSpecialRule] + cp BLACK_HOLE + jr z, .black_hole_rule + or a + ret +.black_hole_rule + ld a, $ff + ld [wDuelTempList], a + ldtx hl, Text00c5 ; this text ID is always discarded + xor a + scf + ret + +; fill wDuelTempList with the turn holder's discard pile cards (their 0-59 deck indexes) +; return carry if the turn holder has no cards in the discard pile +CreateDiscardPileCardList: + call IsBlackHoleRuleActive + ret c ; no Discard Pile + ldh a, [hWhoseTurn] + ld h, a + ld l, DUELVARS_NUMBER_OF_CARDS_IN_DISCARD_PILE + ld b, [hl] + ld a, DUELVARS_DECK_CARDS - 1 + add [hl] ; point to last card in discard pile + ld l, a + ld de, wDuelTempList + inc b + jr .begin_loop +.next_card_loop + ld a, [hld] + ld [de], a + inc de +.begin_loop + dec b + jr nz, .next_card_loop + ld a, $ff ; $ff-terminated + ld [de], a + ld l, DUELVARS_NUMBER_OF_CARDS_IN_DISCARD_PILE + ld a, [hl] + or a + ret nz + scf + ret +; 0x69db SECTION "Bank 1@6a0c", ROMX[$6a0c], BANK[$1] @@ -1980,9 +6485,51 @@ CreateTempCardCollection:: ld d, h ret +SECTION "Bank 1@6a50", ROMX[$6a50], BANK[$1] + +; sort the turn holder's hand cards by ID (highest to lowest ID) +; makes use of wDuelTempList +SortHandCardsByID: + call FindLastCardInHand +.loop + ld a, [hld] + ld [de], a + inc de + dec b + jr nz, .loop + ld a, $ff + ld [de], a + call SortCardsInDuelTempListByID + call FindLastCardInHand +.loop2 + ld a, [de] + inc de + ld [hld], a + dec b + jr nz, .loop2 + ret + +; shuffles the turn holder's deck +; if less than 60 cards remain in the deck, it makes sure that the rest are ignored +ShuffleDeck: + ldh a, [hWhoseTurn] + ld h, a + ld d, a + ld a, DECK_SIZE + ld l, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + sub [hl] + ld b, a + ld a, DUELVARS_DECK_CARDS + add [hl] + ld l, a ; hl = DUELVARS_DECK_CARDS + [DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK] + ld a, b ; a = number of cards in the deck + call ShuffleCards + ret +; 0x6a7c + SECTION "Bank 1@6a96", ROMX[$6a96], BANK[$1] -SortDuelTempListByCardID: +SortCardsInDuelTempListByID: ld hl, hTempListPtr_ff99 ld [hl], LOW(wDuelTempList) inc hl @@ -2058,9 +6605,140 @@ SortDuelTempListByCardID: ld b, [hl] pop hl ret -; 0x6af6 -SECTION "Bank 1@6bc8", ROMX[$6bc8], BANK[$1] +; return [wDuelTempList + a] in a and in hTempCardIndex_ff98 +GetCardInDuelTempList_OnlyDeckIndex: + push hl + push de + ld e, a + ld d, $0 + ld hl, wDuelTempList + add hl, de + ld a, [hl] + ldh [hTempCardIndex_ff98], a + pop de + pop hl + ret + +SECTION "Bank 1@6b05", ROMX[$6b05], BANK[$1] + +; clear the non-turn holder's duelvars starting at DUELVARS_ARENA_CARD_DISABLED_ATTACK_INDEX +; these duelvars only last a two-player turn at most. +ClearNonTurnTemporaryDuelvars: + ld a, DUELVARS_ARENA_CARD_DISABLED_ATTACK_INDEX + call GetNonTurnDuelistVariable + xor a + ld [hli], a ; DUELVARS_ARENA_CARD_DISABLED_ATTACK_INDEX + ld [hli], a ; DUELVARS_ARENA_CARD_LAST_TURN_DAMAGE + ld [hli], a ; DUELVARS_ARENA_CARD_LAST_TURN_STATUS + ld [hli], a ; DUELVARS_ARENA_CARD_LAST_TURN_SUBSTATUS2 + ld [hli], a ; DUELVARS_ARENA_CARD_LAST_TURN_CHANGE_WEAK + ld [hli], a ; DUELVARS_ARENA_CARD_LAST_TURN_EFFECT + ld [hl], a ; DUELVARS_UNK_FE + ret + +; same as ClearNonTurnTemporaryDuelvars, except the non-turn holder's arena +; Pokemon status condition is copied to wccc5 +ClearNonTurnTemporaryDuelvars_CopyStatus:: + ld a, DUELVARS_ARENA_CARD_STATUS + call GetNonTurnDuelistVariable + ld [wccc5], a + call ClearNonTurnTemporaryDuelvars + ret +; 0x6b1f + +SECTION "Bank 1@6b37", ROMX[$6b37], BANK[$1] + +; given the deck index (0-59) of a card in [wDuelTempList + a], return: +; - the id of the card with that deck index in register de +; - [wDuelTempList + a] in hTempCardIndex_ff98 and in register a +GetCardInDuelTempList: + push hl + ld e, a + ld d, $0 + ld hl, wDuelTempList + add hl, de + ld a, [hl] + ldh [hTempCardIndex_ff98], a + call GetCardIDFromDeckIndex + pop hl + ldh a, [hTempCardIndex_ff98] + ret + +; b = attacking card Play Area location +; c = defending card Play Area location +; de = base damage +DamageCalculation: + push bc + ld a, c + ld [wTempPlayAreaLocation_cceb], a + xor a + ld [wDamageEffectiveness], a + ld a, b + or a + jr nz, .skip_damage_modifiers + call HandleDamageModifiersEffects +.skip_damage_modifiers + pop bc + ld a, e + or d + ret z ; no damage + ld a, b + call GetPlayAreaCardColor + call TranslateColorToWR + ld b, a + call CheckWhetherToApplyWeakness + jr c, .check_resistance + ld a, [wIsDamageToSelf] + or a + jr z, .not_self_damage_1 + ld a, [wTempPlayAreaLocation_cceb] + call GetArenaOrBenchCardWeakness + jr .got_weakness +.not_self_damage_1 + call SwapTurn + ld a, [wTempPlayAreaLocation_cceb] + call GetArenaOrBenchCardWeakness + call SwapTurn +.got_weakness + and b + jr z, .check_resistance + ; double the damage + sla e + rl d + ld hl, wDamageEffectiveness + set WEAKNESS, [hl] + +.check_resistance + call CheckWhetherToApplyResistance + jr c, .no_resistance + ld a, [wIsDamageToSelf] + or a + jr z, .not_self_damage_2 + ld a, [wTempPlayAreaLocation_cceb] + call GetArenaOrBenchCardResistance + jr .got_resistance +.not_self_damage_2 + call SwapTurn + ld a, [wTempPlayAreaLocation_cceb] + call GetArenaOrBenchCardResistance + call SwapTurn +.got_resistance + and b + jr z, .no_resistance + ld hl, -30 + ld a, [wSpecialRule] + cp LOW_RESISTANCE + jr nz, .got_resistance_modifier + ld hl, -10 +.got_resistance_modifier + add hl, de + ld e, l + ld d, h + ld hl, wDamageEffectiveness + set RESISTANCE, [hl] +.no_resistance + ret SetDefaultPalettes: call SetFontAndTextBoxFrameColor @@ -2109,11 +6787,298 @@ Func_6c12: jp CopyFontsOrDuelGraphicsBytes ; 0x6c1d -SECTION "Bank 1@70b4", ROMX[$70b4], BANK[$1] +SECTION "Bank 1@6c22", ROMX[$6c22], BANK[$1] -; returns carry if Pokemon in turn holder's -; Play Area location in register a cannot -; use its Pkmn Power +HandleDamageModifiersEffects: + call HandlePrehistoricDreamDamageBoost + call HandleThunderChargeDamageBoost + call Func_6f25 + + ld a, DUELVARS_ARENA_CARD_SUBSTATUS1 + get_turn_duelist_var + or a + call nz, .HandleSubstatus1DamageModifiers + ld a, DUELVARS_ARENA_CARD_SUBSTATUS2 + get_turn_duelist_var + or a + call nz, .HandleSubstatus2DamageModifiers + ret + +.HandleSubstatus1DamageModifiers: + cp SUBSTATUS1_NEXT_TURN_DOUBLE_DAMAGE + jr z, .double_damage + cp SUBSTATUS1_UNK_0D + jr z, .triple_damage + ret +.double_damage + call .Func_6c5a + ret nz + ld a, e + or d + ret z + sla e + rl d + ret +.triple_damage + call .Func_6c5a + ret nz + ld l, e + ld h, d + add hl, hl + add hl, de + ld e, l + ld d, h + ret + +; compares loaded attack name with +; turn holder's DUELVARS_UNK_FE +; if it's the same, then return z +.Func_6c5a: + push hl + push de + ld l, DUELVARS_UNK_FE + ld e, [hl] + inc hl + ld d, [hl] + ld hl, wLoadedAttackName + ld a, [hli] + cp e + jr nz, .not_same + ld a, [hl] + cp d +.not_same + pop de + pop hl + ret + +.HandleSubstatus2DamageModifiers: + ret +; 0x6c6e + +SECTION "Bank 1@6f25", ROMX[$6f25], BANK[$1] + +; de = damage +Func_6f25: + push de + ld hl, wTempTurnDuelistCardID + ld e, [hl] + inc hl + ld d, [hl] + call Func_2d3f + pop de + or a + jr nz, .asm_6f37 + ret + + ld a, b + or a + ret z + +.asm_6f37 + ld a, e + or d + ret z ; no damage + ld a, [wMetronomeEnergyCost] + or a + ret nz + ld hl, wcd10 + ld a, [hli] + add e + ld e, a + ld a, [hl] + adc d + ld d, a + ret + +; e = PLAY_AREA_* location +Func_6f49: + ld a, e + ld [wTempPlayAreaLocation_cceb], a + or a + jr nz, .bench + +; arena card + push de + ld hl, wTempNonTurnDuelistCardID + ld e, [hl] + inc hl + ld d, [hl] + push hl + push de + ld a, [wTempPlayAreaLocation_cceb] + call GetCardIDFromDeckIndex + ld [hl], d + dec hl + ld [hl], e + call .Func_6fcc + jr nc, .asm_6f76 + push af + call DrawWideTextBox_PrintText + ld a, [wDuelDisplayedScreen] + cp DUEL_MAIN_SCENE + jr z, .skip_wait_for_input + call WaitForWideTextBoxInput +.skip_wait_for_input + pop af +.asm_6f76 + pop de + pop hl + ld [hl], d + dec hl + ld [hl], e + pop de + ret c ; exit if no damage + +.bench + push de + ld a, [wTempPlayAreaLocation_cceb] + call CheckIsIncapableOfUsingPkmnPower + jr c, .no_carry + call CheckArticunoAuroraVeil + jr c, .asm_6fbb + ld a, [wTempPlayAreaLocation_cceb] + add DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + cp16 MEW_LV8 + jr z, .mew_lv8_1 + cp16 HAUNTER_LV17 + jr z, .haunter_lv17 +.no_carry + pop de + or a + ret + +.mew_lv8_1 + ld a, DUELVARS_ARENA_CARD_STAGE + call GetNonTurnDuelistVariable + or a + jr z, .no_carry + ld a, $05 + ld [wNoDamageOrEffect], a + ldtx hl, Text015e +.asm_6fbb + call DrawWideTextBox_WaitForInput + pop de + scf + ret + +.haunter_lv17 + call CheckHaunterTransparency + jr nc, .no_carry + call DrawWideTextBox_WaitForInput + pop de + scf + ret + +.Func_6fcc: + xor a + ld [wNoDamageOrEffect], a + ld a, [wLoadedAttackCategory] + cp POKEMON_POWER + ret z ; return if Pkmn Power + ld a, DUELVARS_ARENA_CARD_SUBSTATUS1 + ld e, $06 + ldtx hl, Text015c + get_turn_duelist_var + cp SUBSTATUS1_HIDE + jr z, .no_damage + ld e, $03 + ldtx hl, Text0159 + cp SUBSTATUS1_FLY + jr z, .no_damage + ld e, $02 + ldtx hl, Text015a + cp SUBSTATUS1_BARRIER + jr z, .no_damage + ld e, $01 + ldtx hl, Text015b + cp SUBSTATUS1_AGILITY + jr z, .no_damage + + ; check Mew lv8 + call CheckIsIncapableOfUsingPkmnPower_ArenaCard + ccf + ret nc + ld hl, wTempNonTurnDuelistCardID + inc hl + ld a, [hld] + cp HIGH(MEW_LV8) + jr nz, .asm_700e + ld a, [hl] + cp LOW(MEW_LV8) +.asm_700e + jr z, .mew_lv8_2 + or a + ret + +.no_damage + ld a, e + ld [wNoDamageOrEffect], a + scf + ret + +.mew_lv8_2 + ld a, [wIsDamageToSelf] + or a + ret nz + ld hl, wTempTurnDuelistCardID + ld e, [hl] + inc hl + ld d, [hl] + call LoadCardDataToBuffer2_FromCardID + ld a, [wLoadedCard2Type] + cp TYPE_ENERGY + ret nc ; not Pkmn card + ld a, [wLoadedCard2Stage] + or a + ret z ; is basic card + ld e, $05 + ldtx hl, Text015e + jr .no_damage +; 0x7038 + +SECTION "Bank 1@7057", ROMX[$7057], BANK[$1] + +CheckHaunterTransparency: + xor a + ld [wDuelDisplayedScreen], a + ld a, [wTempPlayAreaLocation_cceb] + add DUELVARS_ARENA_CARD_FLAGS + get_turn_duelist_var + bit PLAY_AREA_FLAG_UNK_2_F, [hl] + jr nz, .asm_707e + set PLAY_AREA_FLAG_UNK_2_F, [hl] + res PLAY_AREA_FLAG_UNK_1_F, [hl] + push hl + ldtx de, Text0116 + call TossCoin + pop hl + ret nc + set PLAY_AREA_FLAG_UNK_1_F, [hl] +.asm_7074 + ld a, $04 + ld [wNoDamageOrEffect], a + ldtx hl, Text015f + scf + ret +.asm_707e + bit PLAY_AREA_FLAG_UNK_1_F, [hl] + jr nz, .asm_7074 + or a + ret + +SECTION "Bank 1@70b3", ROMX[$70b3], BANK[$1] + +CheckIsIncapableOfUsingPkmnPower_ArenaCard: + xor a ; PLAY_AREA_ARENA +; fallthrough + +; returns carry if Pokemon in turn holder's Play Area location in register a +; cannot use its Pkmn Power, and if so outputs in a the reason: +; - $0 = Muk's Toxic Gas +; - $1 = Goop Gas Attack +; - $2 = Dark Arbok's Stare CheckIsIncapableOfUsingPkmnPower: ld [wce0c], a or a @@ -2130,11 +7095,11 @@ CheckIsIncapableOfUsingPkmnPower: ld a, [wce0c] add DUELVARS_ARENA_CARD_FLAGS get_turn_duelist_var - and $10 + and AFFECTED_BY_STARE jr z, .can_use - ; used this turn - ldtx hl, Text00e0 ; can't use due to "Shock Eye"? - ld a, $02 + ; can't use due to Dark Arbok's Stare attack + ldtx hl, Text00e0 + ld a, $2 scf ret .can_use @@ -2160,9 +7125,21 @@ CountPokemonWithActivePkmnPowerInBothPlayAreas: .none_found pop bc ret -; 0x70f1 -SECTION "Bank 1@7100", ROMX[$7100], BANK[$1] +; same as CountTurnDuelistPokemonWithActivePkmnPower +; but does not account Arena Card +; de = card ID +CountTurnDuelistBenchWithActivePkmnPower: + push hl + push de + push bc + ld c, $00 + ld hl, wTempCardID_ce08 + ld [hl], e + inc hl + ld [hl], d + ld a, DUELVARS_ARENA_CARD + jr CountTurnDuelistPokemonWithActivePkmnPower.bench ; counts how many Pokemon with card ID in de ; is in Turn Duelist's Play Area with its Pkmn Power active @@ -2172,13 +7149,13 @@ CountTurnDuelistPokemonWithActivePkmnPower: push de push bc ld c, 0 - call .CheckArenaCard - jr nc, .check_bench + call CheckArenaCardIDAndHasActivePkmnPower + jr nc, .bench inc c ; if a Bench card is the same as wTempCardID_ce08, ; and its flag 4 is not set, then add to count -.check_bench +.bench ld b, PLAY_AREA_BENCH_1 ldh a, [hWhoseTurn] ld h, a @@ -2221,9 +7198,8 @@ CountTurnDuelistPokemonWithActivePkmnPower: ; returns carry if turn duelist's Arena card ; is the card in input registers de, -; is not affected by a status condition and -; flag 4 is not set -.CheckArenaCard: +; is not affected either by a status condition or by Stare +CheckArenaCardIDAndHasActivePkmnPower: ld hl, wTempCardID_ce08 ld [hl], e inc hl @@ -2245,7 +7221,7 @@ CountTurnDuelistPokemonWithActivePkmnPower: and CNF_SLP_PRZ jr nz, .false ld l, DUELVARS_ARENA_CARD_FLAGS - bit 4, [hl] + bit AFFECTED_BY_STARE_F, [hl] jr nz, .false ; true scf @@ -2253,9 +7229,112 @@ CountTurnDuelistPokemonWithActivePkmnPower: .false or a ret -; 0x716a -SECTION "Bank 1@71ea", ROMX[$71ea], BANK[$1] +; clears some SUBSTATUS2 conditions from the turn holder's active Pokemon. +; more specifically, those conditions that reduce the damage from an attack +; or prevent the opposing Pokemon from attacking the substatus condition inducer. +ClearDamageReductionSubstatus2: + ld a, DUELVARS_ARENA_CARD_SUBSTATUS2 + get_turn_duelist_var + or a + ret z + cp SUBSTATUS2_REDUCE_BY_20 + jr z, .zero + cp SUBSTATUS2_POUNCE + jr z, .zero + cp SUBSTATUS2_GROWL + jr z, .zero + cp SUBSTATUS2_TAIL_WAG + jr z, .zero + cp SUBSTATUS2_LEER + jr z, .zero + ret +.zero + ld [hl], 0 + ret + +; clears the SUBSTATUS1 and updates the double damage condition of the player about to start his turn +UpdateSubstatusConditions_StartOfTurn: + xor a + ld [wcc1a], a + ld [wcd0c], a + + ; reset bit flag 3 in all Play Area Pokémon + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld c, a + ld l, DUELVARS_ARENA_CARD_FLAGS +.loop_play_area + res PLAY_AREA_FLAG_UNK_3_F, [hl] + inc hl + dec c + jr nz, .loop_play_area + + ld a, DUELVARS_ARENA_CARD_SUBSTATUS3 + get_turn_duelist_var + res SUBSTATUS3_UNK_6_F, [hl] + + ld a, DUELVARS_ARENA_CARD_SUBSTATUS3 + get_turn_duelist_var + bit SUBSTATUS3_UNK_5_F, [hl] + ret nz + ld l, DUELVARS_ARENA_CARD_SUBSTATUS1 + ld [hl], $00 + ret + +; clears the SUBSTATUS2, Headache, and updates the double damage condition of the player ending his turn +UpdateSubstatusConditions_EndOfTurn: + ld a, DUELVARS_ARENA_CARD_FLAGS + get_turn_duelist_var + ld c, MAX_PLAY_AREA_POKEMON +.loop_play_area + res AFFECTED_BY_STARE_F, [hl] + inc l + dec c + jr nz, .loop_play_area + + ; reset Goop Gas attack flag + ld hl, wGoopGasAttackActive + ld a, [hl] + or a + jr z, .goop_gas_attack_not_active + dec [hl] +.goop_gas_attack_not_active + + ld a, DUELVARS_ARENA_CARD_SUBSTATUS3 + get_turn_duelist_var + res SUBSTATUS3_HEADACHE_F, [hl] + res SUBSTATUS3_SPOOKIFY_F, [hl] + res SUBSTATUS3_PERPLEX_F, [hl] + + bit SUBSTATUS3_UNK_5_F, [hl] + jr z, .asm_71d0 + res SUBSTATUS3_UNK_4_F, [hl] + res SUBSTATUS3_UNK_5_F, [hl] + jr .reset_substatus2 +.asm_71d0 + bit SUBSTATUS3_UNK_4_F, [hl] + jr z, .reset_substatus2 + set SUBSTATUS3_UNK_5_F, [hl] + +.reset_substatus2 + ld a, DUELVARS_ARENA_CARD_SUBSTATUS2 + get_turn_duelist_var + ld [hl], $00 + ret + +; return carry if turn player cannot draw due to Perplex +CheckIfCannotDrawDueToPerplex: + ld a, DUELVARS_ARENA_CARD_SUBSTATUS3 + get_turn_duelist_var + bit SUBSTATUS3_PERPLEX_F, [hl] + jr nz, .perplex_active + or a + ret +.perplex_active + ldtx hl, Text0162 + scf + ret ; checks if Goop Gas Attack is active and if so, ; returns carry and a = $1 @@ -2277,9 +7356,255 @@ CheckGoopGasAttackAndToxicGasActive: ldtx hl, Text024a scf ret -; 0x7205 -SECTION "Bank 1@755d", ROMX[$755d], BANK[$1] +; return carry if turn holder has Blastoise and its Rain Dance Pkmn Power is active +IsRainDanceActive: + ld de, BLASTOISE_LV52 + call CountTurnDuelistPokemonWithActivePkmnPower + jr c, .has_rain_dance + ld de, BLASTOISE_ALT_LV52 + call CountTurnDuelistPokemonWithActivePkmnPower + jr c, .has_rain_dance + ret +.has_rain_dance + call CheckGoopGasAttackAndToxicGasActive + ccf + ret + +; return carry if card at [hTempCardIndex_ff98] is a water energy card AND +; if card at [hTempPlayAreaLocation_ff9d] is a water Pokemon card. +CheckRainDanceScenario: + ldh a, [hTempCardIndex_ff98] + call GetCardIDFromDeckIndex + call GetCardType + cp TYPE_ENERGY_WATER + jr nz, .no_carry + ldh a, [hTempPlayAreaLocation_ff9d] + call GetPlayAreaCardColor + cp TYPE_PKMN_WATER + jr nz, .no_carry + scf + ret +.no_carry + or a + ret + +SECTION "Bank 1@7234", ROMX[$7234], BANK[$1] + +Func_7234: + call HandleDestinyBondSubstatus + call HandleFinalBeam + ret + +; if the defending (non-turn) card's HP is 0 and the attacking (turn) card's HP +; is not, the attacking card faints if it was affected by destiny bond +HandleDestinyBondSubstatus: + ld a, [wcd0b] + cp SUBSTATUS1_DESTINY_BOND + ret nz + + ld a, DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + cp -1 + ret z + ld a, [wccef] + add DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + or a + ret nz + + ; don't apply Destiny Bond if target is in Bench + ; and Articuno's Aurora Veil is active + ld a, [wcd0a] + ld [wTempPlayAreaLocation_cceb], a + call CheckArticunoAuroraVeil + jr c, .draw_text_box_and_exit + + ld a, [wcd0a] + add DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + or a + ret z + ld [hl], 0 + call DrawDuelMainScene + call DrawDuelHUDs + ld a, [wcd0a] + add DUELVARS_ARENA_CARD + get_turn_duelist_var + call LoadCardDataToBuffer2_FromDeckIndex + ld hl, wLoadedCard2Name + ld a, [hli] + ld h, [hl] + ld l, a + call LoadTxRam2 + ldtx hl, Text0156 ; KnockedOutDueToDestinyBondText +.draw_text_box_and_exit + call DrawWideTextBox_WaitForInput + ret + +HandleFinalBeam: + ; exit if turn holder's Arena cards has no HP + ld a, [wcd0a] + add DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + or a + ret z + + ; exit if the knock out was due to Pkmn Power + ld a, [wLoadedAttackCategory] + cp POKEMON_POWER + ret z + + ; look for Dark Gyarados in Bench with 0 HP + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + ld c, a + ld b, PLAY_AREA_ARENA +.loop_play_area + push bc + ld a, [wcd0a] + add DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + or a + jr z, .next_card + ld a, b + add DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + or a + jr nz, .next_card ; has HP, skip + + ; check if this card in Dark Gyarados + call SwapTurn + ld a, b + add DUELVARS_ARENA_CARD + get_turn_duelist_var + ld de, $0 + cp $ff + call nz, GetCardIDFromDeckIndex + call SwapTurn + cp16 DARK_GYARADOS + jr nz, .next_card + + ; check if it can use its Pkmn Power + ld a, b + call SwapTurn + call CheckIsIncapableOfUsingPkmnPower + call SwapTurn + jr c, .next_card + pop bc + push bc + call .ProcessFinalBeam +.next_card + pop bc + inc b + dec c + jr nz, .loop_play_area + ret + +.ProcessFinalBeam: + ; count all Water and Rainbow energy cards attached + call SwapTurn + ld a, b + ld [wTempPlayAreaLocation_cceb], a + ld e, b + call GetPlayAreaCardAttachedEnergies + ld a, [wAttachedEnergies + RAINBOW] + ld hl, wAttachedEnergies + WATER + add [hl] + ld [wTotalAttachedEnergies], a + call SwapTurn + or a + ret z ; no attached Water energy cards + + ; wTotalAttachedEnergies = (Water + Rainbow energy cards) + call SwapTurn + ld a, b + add DUELVARS_ARENA_CARD_FLAGS + get_turn_duelist_var + set AFFECTED_BY_STARE_F, [hl] + xor a + ld [wDuelDisplayedScreen], a + + ; flip a coin to determine if successful + ldtx de, Text011d + call TossCoin + call SwapTurn + ret nc ; not sucessful + + ld a, [wTotalAttachedEnergies] + ld l, a + ld h, 20 + call HtimesL ; does (20 * wTotalAttachedEnergies) damage + push hl + call DrawDuelMainScene + pop de + ld a, [wcd0a] + call Func_619e + call SwapTurn + ld a, [wTempPlayAreaLocation_cceb] + call Func_6196 + ld a, [wcd0a] + ld c, a + ld a, [wTempPlayAreaLocation_cceb] + ld b, a + call DamageCalculation + call SwapTurn + ld l, e + ld h, d + bit 7, h + jr z, .non_negative + ld hl, 0 ; at least 0 damage +.non_negative + ldtx de, Text01ad + call Func_7518 + call nc, WaitForWideTextBoxInput + ret +; 0x7352 + +SECTION "Bank 1@7518", ROMX[$7518], BANK[$1] + +; hl = damage +; de = text ID +Func_7518: + push hl + call LoadTxRam3 + ld a, e + ld [wce0a + 0], a + ld a, d + ld [wce0a + 1], a + ld hl, wTempTurnDuelistCardID + ld e, [hl] + inc hl + ld d, [hl] + call LoadCardDataToBuffer2_FromCardID + ld hl, wLoadedCard2Name + ld a, [hli] + ld h, [hl] + ld l, a + call LoadTxRam2 + + ld a, [wcd0a] + add DUELVARS_ARENA_CARD_HP + get_turn_duelist_var + pop de + push af + push hl + call SubtractHP + ld hl, wce0a + ld a, [hli] + ld h, [hl] + ld l, a + call DrawWideTextBox_PrintText + pop hl + pop af + or a + ret z + call WaitForWideTextBoxInput + ld a, [wcd0a] + call PrintPlayAreaCardKnockedOutIfNoHP + call DrawDuelHUDs + scf + ret ; return the turn holder's arena card's color in a, accounting for Venomoth's Shift Pokemon Power if active GetArenaCardColor: @@ -2287,7 +7612,7 @@ GetArenaCardColor: ; input: a = play area location offset (PLAY_AREA_*) of the desired card ; return the turn holder's card's color in a, accounting for Venomoth's Shift Pokemon Power if active -GetPlayAreaCardColor:: +GetPlayAreaCardColor: push hl push de ld e, a @@ -2319,25 +7644,40 @@ GetPlayAreaCardColor:: pop hl and $f ret -; 0x758a -SECTION "Bank 1@7591", ROMX[$7591], BANK[$1] - -; return in a the weakness of the turn holder's arena Pokemon +; return in a the weakness of the turn holder's Play Area Pokemon ; if [DUELVARS_ARENA_CARD_CHANGED_WEAKNESS] != 0, return it instead +; input: +; - a = PLAY_AREA_* constant +GetArenaOrBenchCardWeakness: + or a + jr z, GetArenaCardWeakness + add DUELVARS_ARENA_CARD + jr GetPlayAreaCardWeakness + GetArenaCardWeakness: ld a, DUELVARS_ARENA_CARD_CHANGED_WEAKNESS get_turn_duelist_var or a ret nz ld a, DUELVARS_ARENA_CARD +; fallthrough + +GetPlayAreaCardWeakness: get_turn_duelist_var call LoadCardDataToBuffer2_FromDeckIndex ld a, [wLoadedCard2Weakness] ret -; 0x75a0 -SECTION "Bank 1@75a7", ROMX[$75a7], BANK[$1] +; return in a the resistance of the turn holder's Play Area Pokemon +; if [DUELVARS_ARENA_CARD_CHANGED_RESISTANCE] != 0, return it instead +; input: +; - a = PLAY_AREA_* constant +GetArenaOrBenchCardResistance: + or a + jr z, GetArenaCardResistance + add DUELVARS_ARENA_CARD + jr GetPlayAreaCardResistance GetArenaCardResistance: ld a, DUELVARS_ARENA_CARD_CHANGED_RESISTANCE @@ -2345,8 +7685,816 @@ GetArenaCardResistance: or a ret nz ld a, DUELVARS_ARENA_CARD + ; fallthrough + +GetPlayAreaCardResistance: get_turn_duelist_var call LoadCardDataToBuffer2_FromDeckIndex ld a, [wLoadedCard2Resistance] ret -; 0x75b6 + +; this function checks if turn holder's CHARIZARD energy burn is active, and if so, turns +; all energies at wAttachedEnergies except double colorless energies into fire energies +HandleEnergyBurn: + ld a, e + ld c, a + add DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + cp16 CHARIZARD_LV76 + jr z, .has_energy_burn + cp16 CHARIZARD_ALT_LV76 + ret nz +.has_energy_burn + ld a, c + call CheckIsIncapableOfUsingPkmnPower + ret c + ld hl, wAttachedEnergies + ld c, NUM_COLORED_TYPES + xor a +.zero_next_energy + ld [hli], a + dec c + jr nz, .zero_next_energy + ld a, [wTotalAttachedEnergies] + ld [wAttachedEnergies], a + ret + +SECTION "Bank 1@7650", ROMX[$7650], BANK[$1] + +CheckUnableToRetreatDueToEffect: + ; can't retreat if affected by sleep or paralysis + call CheckIfArenaCardIsParalyzedOrAsleep + ret c + + ; can't retreat if opponent has Snorlax lv35 + ; and its Pkmn Power is active + call CheckGoopGasAttackAndToxicGasActive + jr c, .no_pkmn_powers + call SwapTurn + ld de, SNORLAX_LV35 + call CheckArenaCardIDAndHasActivePkmnPower + call SwapTurn + ldtx hl, Text014d + jr c, .set_carry ; can just be ret c + +.no_pkmn_powers + ; can't retreat if used Drill Dive last turn + call CheckIfArenaCardUsedDrillDiveLastTurn + ldtx hl, Text014c + ret c + + ; can't retreat if affected by Acid or Rock Seal + ld a, DUELVARS_ARENA_CARD_SUBSTATUS2 + get_turn_duelist_var + or a + jr z, .can_retreat + ldtx hl, Text014a + cp SUBSTATUS2_ACID + jr z, .set_carry + ldtx hl, Text014b + cp SUBSTATUS2_ROCK_SEAL + jr z, .set_carry +.can_retreat + or a + ret + +.set_carry + scf + ret + +; returns carry if Arena Card's substatus1 is SUBSTATUS1_USED_DRILL_DIVE +CheckIfArenaCardUsedDrillDiveLastTurn: + ld a, DUELVARS_ARENA_CARD_SUBSTATUS1 + get_turn_duelist_var + cp SUBSTATUS1_USED_DRILL_DIVE + jr nz, .no_carry + scf + ret +.no_carry + or a + ret + +; handles Pkmn Powers that trigger when +; an Arena Card retreats to the bench +HandleRetreatPkmnPowers: + call CheckGoopGasAttackAndToxicGasActive + ret c + call .HandleVinePull + call .HandleSinkhole + ret + +.HandleVinePull: + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + cp16 DARK_IVYSAUR + ret nz ; not Dark Ivysaur + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + cp 2 + ret c ; no Bench Pokémon + + ld a, DUELVARS_ARENA_CARD_FLAGS + get_turn_duelist_var + and AFFECTED_BY_STARE | USED_PKMN_POWER_THIS_TURN + ret nz ; Dark Ivysaur cannot use Vine Pull + set USED_PKMN_POWER_THIS_TURN_F, [hl] + + xor a + ldh [hTempPlayAreaLocation_ff9d], a + ld a, $f4 + farcall $6, $4a87 + ; select random Bench Pokémon to switch + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + dec a + call Random + inc a + call SwapTurn + ld e, a + call SwapArenaWithBenchPokemon + call SwapTurn + ldtx hl, Text01df + call DrawWideTextBox_WaitForInput + xor a + ld [wDuelDisplayedScreen], a + ret + +.HandleSinkhole: + call SwapTurn + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld c, a + ld b, PLAY_AREA_ARENA + ld l, DUELVARS_ARENA_CARD +.loop_play_area + push hl + push bc + ld a, [hl] + call GetCardIDFromDeckIndex + cp16 DARK_DUGTRIO + jr nz, .next_card + ld a, b + call CheckIsIncapableOfUsingPkmnPower + jr c, .next_card + call SwapTurn + call .DealSinkholeDamage + call SwapTurn +.next_card + pop bc + pop hl + inc hl + inc b + dec c + jr nz, .loop_play_area + call SwapTurn + ret + +.DealSinkholeDamage: + ldtx de, Text0122 + call TossCoin + ret c ; exit if heads + xor a + ld [wNoDamageOrEffect], a + ld a, POKEMON_POWER + ld [wLoadedAttackCategory], a + ld a, TRUE + ld [wIsDamageToSelf], a + ld a, ATK_ANIM_RECOIL_HIT + ld [wLoadedAttackAnimation], a + ld b, PLAY_AREA_ARENA + ld de, 20 + call DealDamageToPlayAreaPokemon + xor a + ld [wDuelDisplayedScreen], a + ret +; 0x7742 + +SECTION "Bank 1@7765", ROMX[$7765], BANK[$1] + +; return carry if the turn holder is affected by an effect +; that doesn't allow trainer cards to be used +CheckCantUseTrainerDueToEffect: + ld a, DUELVARS_ARENA_CARD_SUBSTATUS3 + get_turn_duelist_var + ldtx de, Text014e ; UnableToUseTrainerDueToHeadacheText + bit SUBSTATUS3_HEADACHE_F, [hl] + jr nz, .cannot_use + ldtx de, Text014f + bit SUBSTATUS3_SPOOKIFY_F, [hl] + jr nz, .cannot_use + call CheckGoopGasAttackAndToxicGasActive + jr c, .skip_hay_fever_check + ; check Dark Vileplume's Hay Fever + ld de, DARK_VILEPLUME + call CountPokemonWithActivePkmnPowerInBothPlayAreas + ldtx hl, Text0160 + ret c +.skip_hay_fever_check + or a + ret +.cannot_use + ld l, e + ld h, d + scf + ret + +; return carry if the turn holder's arena Pokemon cannot use +; selected attack at wSelectedAttack due to amnesia +HandleAmnesiaSubstatus: + ld a, DUELVARS_ARENA_CARD_SUBSTATUS2 + get_turn_duelist_var + or a + jr nz, .check_disable + ret +.check_disable + ldtx de, Text0155 + cp SUBSTATUS2_DISABLE + jr z, .affected_by_disable_or_amnesia + ldtx de, Text0154 ; UnableToUseAttackDueToAmnesiaText + cp SUBSTATUS2_AMNESIA + jr z, .affected_by_disable_or_amnesia +.not_the_disabled_atk + or a + ret +.affected_by_disable_or_amnesia + ld a, DUELVARS_ARENA_CARD_DISABLED_ATTACK_INDEX + get_turn_duelist_var + ld a, [wSelectedAttack] + cp [hl] + jr nz, .not_the_disabled_atk + ld l, e + ld h, d + scf + ret + +; return carry if any duelist has Aerodactyl and its Prehistoric Power Pkmn Power is active +IsPrehistoricPowerActive: + ld de, AERODACTYL_LV28 + call CountPokemonWithActivePkmnPowerInBothPlayAreas + ret nc + call CheckGoopGasAttackAndToxicGasActive + ldtx hl, Text0158 ; UnableToEvolveDueToPrehistoricPowerText + ccf + ret + +; if the id of the card provided in register a as a deck index is MUK, +; clear the changed type of all arena and bench Pokemon +ClearChangedTypesIfMuk: + call GetCardIDFromDeckIndex + cp16 MUK + ret nz + call .ResetChangedTypes + ret + +.ResetChangedTypes: + call SwapTurn + call .zero_changed_types + call SwapTurn +.zero_changed_types + ld a, DUELVARS_ARENA_CARD_CHANGED_TYPE + get_turn_duelist_var + ld c, MAX_PLAY_AREA_POKEMON +.zero_changed_types_loop + xor a + ld [hli], a + dec c + jr nz, .zero_changed_types_loop + ret + +; return carry if turn holder has Omanyte and its Clairvoyance Pkmn Power is active +IsClairvoyanceActive: + call CheckGoopGasAttackAndToxicGasActive + ccf + ret nc + ld de, OMANYTE_LV19 + call CountTurnDuelistPokemonWithActivePkmnPower + ret + +CheckIfArencaCardIsUnableToAttack: + ld a, DUELVARS_ARENA_CARD_SUBSTATUS2 + get_turn_duelist_var + or a + jr z, .skip_check_substatus2 + + ldtx hl, Text0150 + cp SUBSTATUS2_TAIL_WAG + jr z, .set_carry + ldtx hl, Text0151 + cp SUBSTATUS2_LEER + jr z, .set_carry + ldtx hl, Text0152 + cp SUBSTATUS2_BONE_ATTACK + jr z, .set_carry + +.skip_check_substatus2 + call CheckIfArenaCardUsedDrillDiveLastTurn + ldtx hl, Text0153 + ret c ; cannot attack due to Drill Dive + + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + cp16 SLOWBRO_LV35 + jr z, .slowbro_lv35 + call CheckIfArenaCardIsParalyzedOrAsleep + ret + +.slowbro_lv35 + ; Slowbro lv35 can potentially select an attack + ; while asleep, so only return carry if it's paralyzed + ld a, DUELVARS_ARENA_CARD_STATUS + get_turn_duelist_var + and CNF_SLP_PRZ + cp PARALYZED + jr z, .set_carry + or a + ret +.set_carry + ; bug, missing load text ID into hl + ; ldtx hl, Text0026 + scf + ret + +; returns carry if turn holder's Arena Card is paralyzed or asleep +; and outputs in hl text to display accordingly +CheckIfArenaCardIsParalyzedOrAsleep: + ld a, DUELVARS_ARENA_CARD_STATUS + get_turn_duelist_var + and CNF_SLP_PRZ + cp PARALYZED + jr z, .paralyzed + cp ASLEEP + jr z, .asleep + or a + ret +.paralyzed + ldtx hl, Text0026 + jr .has_status_condition +.asleep + ldtx hl, Text0025 +.has_status_condition + scf + ret +; 0x784a + +SECTION "Bank 1@7881", ROMX[$7881], BANK[$1] + +; return carry if turn duelist's Arena Card +; is protected from Status Conditions +CheckIfArenaCardIsProtectedFromStatusCondition: + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + + ; Clefairy Doll and Mysterious Fossil cannot be statused + cp16 CLEFAIRY_DOLL + jr z, .return_carry + cp16 MYSTERIOUS_FOSSIL + jr z, .return_carry + + ; Snorlax lv20 cannot be statused if its Pkmn Power is active + cp16 SNORLAX_LV20 + jr nz, .check_chlorophyll + push de + xor a + call CheckIsIncapableOfUsingPkmnPower + pop de + jr c, .check_chlorophyll +.return_carry + scf + ret + +.check_chlorophyll + ; Grass Pokémon cannot be statused if Chlorophyll is active + ld a, [wSpecialRule] + cp CHLOROPHYLL + jr z, .chlorophyll_active + or a + ret +.chlorophyll_active + call GetArenaCardColor + cp GRASS + jr z, .return_carry + or a + ret + +; returns carry if weakness should not be applied +; in the current damage calculation +CheckWhetherToApplyWeakness: + call HandleFlameArmorWaterWeakness + ret c ; don't apply Water weakness on Fire types + call CheckGoopGasAttackAndToxicGasActive + jr c, .no_pkmn_powers + call CheckIfDampeningShieldIsActive + ret c ; Dampening Shield active, no Weakness/Resistance + call .SwapTurnIfNotDamageToSelf + call GetDefendingCardType + call .SwapTurnIfNotDamageToSelf + cp TYPE_PKMN_GRASS + jr nz, .no_pkmn_powers + call .CheckGreenShield + ret c ; no Weakness/Resistance to Grass Pokémon +.no_pkmn_powers + call .SwapTurnIfNotDamageToSelf + ld a, DUELVARS_ARENA_CARD_SUBSTATUS3 + get_turn_duelist_var + call .SwapTurnIfNotDamageToSelf + bit SUBSTATUS3_UNK_6_F, a + jr z, .no_carry + call .Func_78f2 + ret c +.no_carry + or a + ret + +.Func_78f2: + call .SwapTurnIfNotDamageToSelf + call GetDefendingCardType + call .SwapTurnIfNotDamageToSelf + cp TYPE_PKMN_WATER + jr nz, .no_carry + scf + ret + +.CheckGreenShield: + call .SwapTurnIfNotDamageToSelf + push de + ld de, METAPOD_LV20 + call CountTurnDuelistPokemonWithActivePkmnPower + pop de + call .SwapTurnIfNotDamageToSelf + ret + +.SwapTurnIfNotDamageToSelf: + push af + ld a, [wIsDamageToSelf] + or a + call z, SwapTurn + pop af + ret + +; returns carry if resistance should not be applied +; in the current damage calculation +CheckWhetherToApplyResistance: + call HandleEarthPowerRockResistance + ret c ; don't apply Fighting resistance + call CheckGoopGasAttackAndToxicGasActive + ccf + ret nc + call CheckIfDampeningShieldIsActive + ret + +; checks in both duelists' Bench whether Mr. Mime lv20 +; exists and has its Pkmn Power active +; if there is at least one, return carry +CheckIfDampeningShieldIsActive: + push de + push bc + ld de, MR_MIME_LV20 + call CountTurnDuelistBenchWithActivePkmnPower + ld c, a + call SwapTurn + ld de, MR_MIME_LV20 + call CountTurnDuelistBenchWithActivePkmnPower + call SwapTurn + add c + jr z, .no_carry + scf +.no_carry + pop bc + pop de + ret + +Func_7943: + ld a, [wcd0c] + or a + ret z + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + or a + ret z ; hp == 0 + call SwapTurn + call CheckIfArenaCardIsProtectedFromStatusCondition + jr c, .no_poison + ld e, $00 + call Func_6f49 + jr c, .no_poison + ld a, DUELVARS_ARENA_CARD_STATUS + get_turn_duelist_var + ld [hl], POISONED + xor a + ld [wcd0c], a +.no_poison + call SwapTurn + ret + +Func_796b: + call CheckGoopGasAttackAndToxicGasActive + ccf + ret nc + call .Func_797f + jr c, .done + call SwapTurn + call .Func_797f + call SwapTurn +.done + ret + +.Func_797f: + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + get_turn_duelist_var + ld c, a + ld b, PLAY_AREA_ARENA + ld l, DUELVARS_ARENA_CARD_FLAGS +.loop_play_area_pkmn + bit PLAY_AREA_FLAG_UNK_3_F, [hl] + jr z, .next_pkmn + push hl + push bc + ld a, b + call CheckIsIncapableOfUsingPkmnPower + pop bc + pop hl + ccf + ret c +.next_pkmn + inc l + inc b + dec c + jr nz, .loop_play_area_pkmn + or a + ret + +; de = damage +HandlePrehistoricDreamDamageBoost: + ld a, [wcc1a] + or a + ret z ; no boost + ld a, [wIsDamageToSelf] + or a + ret nz + call CheckGoopGasAttackAndToxicGasActive + ret c ; can't use Pkmn Power + + ; check if the attacking Pokémon + ; is a fossil card, by checking its Pokédex number + ld hl, wTempTurnDuelistCardID + push de + ld e, [hl] + inc hl + ld d, [hl] + call LoadCardDataToBuffer2_FromCardID + pop de + ld a, [wLoadedCard2PokedexNumber] + cp $8a + jr c, .not_fossil_card + cp $8f + jr nc, .not_fossil_card + ld a, [wcc1a] + call ATimes10 + add e + ld e, a + ld a, 0 + adc d + ld d, a +.not_fossil_card + ret + +; returns carry if Articuno lv34 is Arena Card and its Pkmn Power is active, +; and if the attack target is a card in the Bench +CheckArticunoAuroraVeil: + ld a, [wLoadedAttackCategory] + cp POKEMON_POWER + jr z, .no_carry + ld a, [wTempPlayAreaLocation_cceb] + or a + jr z, .no_carry + push de + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + cp16 ARTICUNO_LV34 + pop de + jr nz, .no_carry + call CheckIsIncapableOfUsingPkmnPower_ArenaCard + jr c, .no_carry + ld a, $07 + ld [wNoDamageOrEffect], a + ldtx hl, Text01c9 + scf + ret +.no_carry + or a + ret +; 0x79fd + +SECTION "Bank 1@7a2d", ROMX[$7a2d], BANK[$1] + +; returns carry if: +; - turn duelist has a Hypno lv30 in the Play Area; +; - Hypno is able to use its Pkmn Power; +; - Hypno has enough energy to pay for its Mind Shock attack +CheckHypnoPuppetMaster: + push hl + ldh a, [hWhoseTurn] + ld hl, wWhoseTurn + cp [hl] + jr nz, .no_carry + ld b, PLAY_AREA_ARENA - 1 + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var +.loop_play_area + inc b + ld a, [hli] + cp $ff + jr z, .no_carry + call GetCardIDFromDeckIndex + cp16 HYPNO_LV30 + jr nz, .loop_play_area + ; is Hypno lv30, check if it can use its Pkmn Power + push hl + push bc + ld a, b + call CheckIsIncapableOfUsingPkmnPower + pop bc + pop hl + jr c, .loop_play_area ; not able to use, skip + + ; Hypno lv30 is in Play Area, check if it + ; has enough energy to pay for its Mind Shock attack + ; loop through all card locations and count + ; how many Rainbow or Psychic energy cards + ; are attached to the found Play Area location + push hl + push de + ld a, b + or CARD_LOCATION_ARENA + ld e, a + ld c, 0 ; tracks the energy count + ld a, DUELVARS_CARD_LOCATIONS + get_turn_duelist_var +.loop_card_locations + ld a, [hl] + cp e + jr nz, .next_card_location + push de + ld a, l + call GetCardIDFromDeckIndex + cp16 RAINBOW_ENERGY + jr z, .check_energy + cp16 PSYCHIC_ENERGY +.check_energy + pop de + jr nz, .next_card_location + inc c +.next_card_location + inc l + ld a, l + cp DECK_SIZE + jr c, .loop_card_locations + ; no more cards to check, tally energy count + pop de + pop hl + ld a, c ; number of energy cards + cp 2 + jr c, .loop_play_area + ; enough energy + pop hl + scf + ret +.no_carry + pop hl + or a + ret + +; de = damage +HandleThunderChargeDamageBoost: + ld a, [wSpecialRule] + cp THUNDER_CHARGE + ret nz ; Thunder Charge not active + call GetAttackingCardType + cp TYPE_PKMN_LIGHTNING + ret nz ; not a lightning card + ld a, [wIsDamageToSelf] + or a + ret nz + ld a, [wLoadedAttackCategory] + cp POKEMON_POWER + ret z + ; add boost + ld hl, 10 + add hl, de + ld e, l + ld d, h + ret + +; returns carry if Flame Armor rule is active +; and if the attacking Pokémon is Water type +; and the defending Pokémon is Fire Type +HandleFlameArmorWaterWeakness: + ld a, [wSpecialRule] + cp FLAME_ARMOR + jr z, .is_active +.no_carry + or a + ret + +.is_active + ; no carry if attacking Pokémon is Water + call GetAttackingCardType + cp TYPE_PKMN_WATER + jr nz, .no_carry + ; no carry if defending Pokémon is Fire + call SwapTurn + call GetDefendingCardType + call SwapTurn + cp TYPE_PKMN_FIRE + jr nz, .no_carry + scf + ret + +; returns carry if Earth Power rule is active +; and if the attacking Pokémon is Fighting type +HandleEarthPowerRockResistance: + ld a, [wSpecialRule] + cp EARTH_POWER + jr z, .is_active +.no_carry + or a + ret + +.is_active + push de + call GetAttackingCardType + pop de + cp TYPE_PKMN_FIGHTING + jr nz, .no_carry + scf + ret +; 0x7ae6 + +SECTION "Bank 1@7b00", ROMX[$7b00], BANK[$1] + +GetDefendingCardType: + ld hl, wTempNonTurnDuelistCardID + call GetPlayAreaPokemonType + ret nc + ld a, [wccd9] +; fallthrough +Func_7b0a: + call GetPlayAreaCardColor + ret + +GetAttackingCardType: + ld hl, wTempTurnDuelistCardID + call GetPlayAreaPokemonType + ret nc + ; is Venomoth, get its color + ld a, [wccd8] + jr Func_7b0a + +; gets type of Pokémon with ID given in [hl] +; if it's Venomoth lv28, then get its color +; taking into account Color Change +GetPlayAreaPokemonType: + push de + ld e, [hl] + inc hl + ld d, [hl] + cp16 VENOMOTH_LV28 + jr z, .is_venomoth + call GetCardType + cp TYPE_TRAINER + jr nz, .not_trainer + ld a, TYPE_PKMN_COLORLESS +.not_trainer + pop de + or a + ret +.is_venomoth + pop de + scf + ret +; 0x7b37 + +SECTION "Bank 1@7b44", ROMX[$7b44], BANK[$1] + +GetPoisonDamage: + ld a, DUELVARS_ARENA_CARD_STATUS + get_turn_duelist_var + and DOUBLE_POISONED + ret z + cp DOUBLE_POISONED + ld a, DBLPSN_DAMAGE + ret z + push de + call Func_796b + pop de + ld a, PSN_DAMAGE + ret nc + ld a, DBLPSN_DAMAGE + ret +; 0x7b5a diff --git a/src/engine/bank02.asm b/src/engine/bank02.asm index 0a874b6..20c7733 100644 --- a/src/engine/bank02.asm +++ b/src/engine/bank02.asm @@ -1,3 +1,132 @@ +SECTION "Bank 2@43b3", ROMX[$43b3], BANK[$2] + +Func_82b6: + ld a, [wCheckMenuPlayAreaWhichDuelist] + ld b, a + ld a, [wCheckMenuPlayAreaWhichLayout] + cp b + jr nz, .not_equal + + ld hl, PrizeCardsCoordinateData_YourOrOppPlayArea.player + call DrawPlayArea_PrizeCards + ret + +.not_equal + ld hl, PrizeCardsCoordinateData_YourOrOppPlayArea.opponent + call DrawPlayArea_PrizeCards + ret +; 0x83cb + +SECTION "Bank 2@4587", ROMX[$4587], BANK[$2] + +; draws prize cards depending on the turn +; loaded in wCheckMenuPlayAreaWhichDuelist +; input: +; hl = pointer to coordinates +DrawPlayArea_PrizeCards: + push hl + call GetDuelInitialPrizesUpperBitsSet + ld a, [wCheckMenuPlayAreaWhichDuelist] + ld h, a + ld l, DUELVARS_PRIZES + ld a, [hl] + + pop hl + ld b, 0 + push af +; loop each prize card +.loop + inc b + ld a, [wDuelInitialPrizes] + inc a + cp b + jr z, .done + + pop af + srl a ; right shift prize cards left + push af + jr c, .not_taken + ld a, $e0 ; tile byte for empty slot + jr .draw +.not_taken + ld a, [wcc07] + or a + jr z, .asm_85b2 + ld a, $f9 + jr .draw +.asm_85b2 + ld a, $dc ; tile byte for card +.draw + ld e, [hl] + inc hl + ld d, [hl] + inc hl + + push hl + push bc + lb hl, $01, $02 ; card tile gfx + lb bc, 2, 2 ; rectangle size + call FillRectangle + + ld a, [wConsole] + cp CONSOLE_CGB + jr nz, .not_cgb + ld a, $03 ; blue colour + lb bc, 2, 2 + lb hl, 0, 0 + call BankswitchVRAM1 + call FillRectangle + call BankswitchVRAM0 +.not_cgb + pop bc + pop hl + jr .loop +.done + pop af + ret + +PrizeCardsCoordinateData_YourOrOppPlayArea: +; x and y coordinates for player prize cards +.player + db 2, 1 + db 2, 3 + db 4, 1 + db 4, 3 + db 6, 1 + db 6, 3 +; x and y coordinates for opponent prize cards +.opponent + db 9, 17 + db 9, 15 + db 7, 17 + db 7, 15 + db 5, 17 + db 5, 15 + +SECTION "Bank 2@4629", ROMX[$4629], BANK[$2] + +; calculates bits set up to the number of initial prizes, with upper 2 bits set, i.e: +; 6 prizes: a = %11111111 +; 4 prizes: a = %11001111 +; 3 prizes: a = %11000111 +; 2 prizes: a = %11000011 +GetDuelInitialPrizesUpperBitsSet: + ld a, [wDuelInitialPrizes] + ld b, $01 +.loop + or a + jr z, .done + sla b + dec a + jr .loop +.done + dec b + ld a, b + or %11000000 + ld [wDuelInitialPrizesUpperBitsSet], a + ret +; 0x863e + SECTION "Bank 2@4acb", ROMX[$4acb], BANK[$2] LoadMenuCursorTile: @@ -84,7 +213,7 @@ HandleMultiDirectionalMenu: .make_bitmask_done ; check if the moved cursor refers to an existing item. - ld a, [wd0c4] + ld a, [wDuelInitialPrizesUpperBitsSet] and b jr nz, .sfx ld a, [wd0d0] diff --git a/src/engine/bank03.asm b/src/engine/bank03.asm index 6dbce52..19c5d95 100644 --- a/src/engine/bank03.asm +++ b/src/engine/bank03.asm @@ -103,12 +103,12 @@ StartMenu_ContinueFromDiary: call DoFrame ld a, $0e call Func_3154 - ld a, VAR_3C + ld a, VAR_NPC_DECK_ID call GetVarValue - ld [wcc16], a + ld [wNPCDuelDeckID], a ld a, VAR_3D call GetVarValue - ld [wdd03], a + ld [wDuelStartTheme], a call Func_3087 scf ret @@ -876,11 +876,11 @@ Func_d299:: call Func_3154 ret .asm_d357 - ld a, [wcc16] + ld a, [wNPCDuelDeckID] ld c, a - ld a, VAR_3C + ld a, VAR_NPC_DECK_ID call SetVarValue - ld a, [wdd03] + ld a, [wDuelStartTheme] ld c, a ld a, VAR_3D call SetVarValue @@ -899,7 +899,7 @@ Func_d299:: call Func_e9a7 ld a, EVENT_F0 call ZeroOutEventValue - farcall $11, $4943 + farcall PlayCurrentSong ld a, $09 ld [wd582], a xor a @@ -1877,7 +1877,7 @@ GeneralVarMasks: db $28, %11111111 ; VAR_39 db $29, %00000111 ; VAR_3A db $2a, %11111111 ; VAR_3B - db $2b, %11111111 ; VAR_3C + db $2b, %11111111 ; VAR_NPC_DECK_ID db $2c, %11111111 ; VAR_3D db $33, %11111111 ; VAR_3E diff --git a/src/engine/bank04.asm b/src/engine/bank04.asm index a40dac5..6750a90 100644 --- a/src/engine/bank04.asm +++ b/src/engine/bank04.asm @@ -1635,6 +1635,12 @@ SetSpriteAnimAnimation:: ret ; 0x10cd9 +SECTION "Bank 4@4cfe", ROMX[$4cfe], BANK[$4] + +Func_10cfe: + ret +; 0x10cff + SECTION "Bank 4@4d17", ROMX[$4d17], BANK[$4] Func_10d17: @@ -1642,7 +1648,7 @@ Func_10d17: push bc push hl sla b - sla b + sla b ; *4 inc hl ld a, [hl] ; SPRITEANIMSTRUCT_1 and $fb @@ -1681,6 +1687,7 @@ GetOWObjectSpriteAnimFlags:: SECTION "Bank 4@4d77", ROMX[$4d77], BANK[$4] +; a = OW_* constant LoadOWObjectInMap:: push af push bc @@ -2253,6 +2260,7 @@ DrawWideTextBox_PrintTextWithYesOrNoMenu: SECTION "Bank 4@507c", ROMX[$507c], BANK[$4] +; hl = text ID Func_1107c: push af push bc @@ -4598,10 +4606,10 @@ ShowProloguePortraitAndText: ret .Func_13bdf: - ld a, $3b + ld a, NPC_GR_1 lb bc, 7, 3 ld e, PORTRAITVARIANT_NORMAL - call Func_3ab2 + call DrawNPCPortrait ret .PrintText: @@ -4834,14 +4842,14 @@ PlayerGenderSelection: .LoadPortraitsAndMenuParams: ; male portrait - ld a, PORTRAIT_00 + ld a, PORTRAIT_MARK ld b, 0 ld c, PORTRAITVARIANT_NORMAL lb de, 2, 4 farcall DrawPortrait ; female portrait - ld a, PORTRAIT_01 + ld a, PORTRAIT_MINT ld b, 1 ld c, PORTRAITVARIANT_NORMAL lb de, 12, 4 diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm new file mode 100644 index 0000000..8a216a8 --- /dev/null +++ b/src/engine/bank05.asm @@ -0,0 +1,131 @@ +DeckAIPointerTable:: + dw $41d6 ; UNKNOWN_SAMS_PRACTICE_DECK_ID + dw $4180 ; PLAYER_PRACTICE_DECK_ID + dw $4180 ; STARTER_DECK_ID + dw $4180 ; SWEAT_ANTI_GR1_DECK_ID + dw $4180 ; GIVE_IN_ANTI_GR2_DECK_ID + dw $4180 ; VENGEFUL_ANTI_GR3_DECK_ID + dw $4180 ; UNFORGIVING_ANTI_GR4_DECK_ID + dw $4180 ; SAMS_PRACTICE_DECK_ID + dw $4180 ; AARON_PRACTICE_DECK1_ID + dw $423f ; AARONS_STEP1_DECK_ID + dw $4180 ; AARON_PRACTICE_DECK2_ID + dw $4274 ; AARONS_STEP2_DECK_ID + dw $4180 ; AARON_PRACTICE_DECK3_ID + dw $42a9 ; AARONS_STEP3_DECK_ID + dw $4180 ; BRICK_WALK_DECK_ID + dw $4180 ; BENCH_TRAP_DECK_ID + dw $42e4 ; SKY_SPARK_DECK_ID + dw $4376 ; ELECTRIC_SELFDESTRUCT_DECK_ID + dw $4180 ; OVERFLOW_DECK_ID + dw $4180 ; TRIPLE_ZAPDOS_DECK_ID + dw $4180 ; I_LOVE_PIKACHU_DECK_ID + dw $4180 ; TEN_THOUSAND_VOLTS_DECK_ID + dw $41ab ; HAND_OVER_GR_DECK_ID + dw $4408 ; PSYCHIC_ELITE_DECK_ID + dw $4180 ; PSYCHOKINESIS_DECK_ID + dw $4180 ; PHANTOM_DECK_ID + dw $44aa ; PUPPET_MASTER_DECK_ID + dw $4532 ; EVEN3_YEARS_ON_A_ROCK_DECK_ID + dw $4180 ; ROLLING_STONE_DECK_ID + dw $4180 ; GREAT_EARTHQUAKE_DECK_ID + dw $4180 ; AWESOME_FOSSIL_DECK_ID + dw $45b4 ; RAGING_BILLOW_OF_FISTS_DECK_ID + dw $4180 ; YOU_CAN_DO_IT_MACHOP_DECK_ID + dw $4180 ; NEW_MACHOKE_DECK_ID + dw $41ab ; SKILLED_WARRIOR_DECK_ID + dw $4180 ; I_LOVE_TO_FIGHT_DECK_ID + dw $464c ; MAX_ENERGY_DECK_ID + dw $4180 ; REMAINING_GREEN_DECK_ID + dw $4180 ; POISON_CURSE_DECK_ID + dw $4180 ; GLITTERING_SCALES_DECK_ID + dw $4180 ; STEADY_INCREASE_DECK_ID + dw $46d4 ; DARK_SCIENCE_DECK_ID + dw $4180 ; NATURAL_SCIENCE_DECK_ID + dw $4180 ; POISONOUS_SWAMP_DECK_ID + dw $4180 ; GATHERING_NIDORAN_DECK_ID + dw $475d ; RAIN_DANCE_CONFUSION_DECK_ID + dw $4180 ; CONSERVING_WATER_DECK_ID + dw $4180 ; ENERGY_REMOVAL_DECK_ID + dw $47e5 ; SPLASHING_ABOUT_DECK_ID + dw $4843 ; BEACH_DECK_ID + dw $489d ; GO_ARCANINE_DECK_ID + dw $4180 ; FLAME_FESTIVAL_DECK_ID + dw $4180 ; IMMORTAL_FLAME_DECK_ID + dw $4180 ; ELECTRIC_CURRENT_SHOCK_DECK_ID + dw $4946 ; GREAT_ROCKET4_DECK_ID + dw $49ec ; GREAT_ROCKET1_DECK_ID + dw $4a95 ; GREAT_ROCKET2_DECK_ID + dw $4b56 ; GREAT_ROCKET3_DECK_ID + dw $4bfa ; GRAND_FIRE_DECK_ID + dw $4ca6 ; LEGENDARY_FOSSIL_DECK_ID + dw $4d2b ; WATER_LEGEND_DECK_ID + dw $4dc2 ; GREAT_DRAGON_DECK_ID + dw $4180 ; BUG_COLLECTING_DECK_ID + dw $4180 ; DEMONIC_FOREST_DECK_ID + dw $4180 ; STICKY_POISON_GAS_DECK_ID + dw $4e6c ; MAD_PETALS_DECK_ID + dw $4f02 ; DANGEROUS_BENCH_DECK_ID + dw $4180 ; CHAIN_LIGHTNING_BY_PIKACHU_DECK_ID + dw $4180 ; THIS_IS_THE_POWER_OF_ELECTRICITY_DECK_ID + dw $4f6c ; QUICK_ATTACK_DECK_ID + dw $4ffa ; COMPLETE_COMBUSTION_DECK_ID + dw $4180 ; FIREBALL_DECK_ID + dw $4180 ; EEVEE_SHOWDOWN_DECK_ID + dw $5057 ; GAZE_UPON_THE_POWER_OF_FIRE_DECK_ID + dw $4180 ; WHIRLPOOL_SHOWER_DECK_ID + dw $4180 ; PARALYZED_PARALYZED_DECK_ID + dw $4180 ; BENCH_CALL_DECK_ID + dw $50df ; WATER_STREAM_DECK_ID + dw $4180 ; ROCK_BLAST_DECK_ID + dw $4180 ; FULL_STRENGTH_DECK_ID + dw $515d ; RUNNING_WILD_DECK_ID + dw $4180 ; DIRECT_HIT_DECK_ID + dw $4180 ; SUPERDESTRUCTIVE_POWER_DECK_ID + dw $4180 ; BAD_DREAM_DECK_ID + dw $4180 ; POKEMON_POWER_DECK_ID + dw $51e4 ; SPIRITED_AWAY_DECK_ID + dw $5262 ; SNORLAX_GUARD_DECK_ID + dw $52d8 ; EYE_OF_THE_STORM_DECK_ID + dw $5368 ; SUDDEN_GROWTH_DECK_ID + dw $53fb ; VERY_RARE_CARD_DECK_ID + dw $5478 ; BAD_GUYS_DECK_ID + dw $5506 ; POISON_MIST_DECK_ID + dw $558c ; ULTRA_REMOVAL_DECK_ID + dw $5600 ; PSYCHIC_BATTLE_DECK_ID + dw $567c ; STOP_LIFE_DECK_ID + dw $5713 ; SCORCHER_DECK_ID + dw $57a7 ; TSUNAMI_STARTER_DECK_ID + dw $583b ; SMASH_TO_MINCEMEAT_DECK_ID + dw $4180 ; TEST_YOUR_LUCK_DECK_ID + dw $4180 ; PROTOHISTORIC_DECK_ID + dw $58d5 ; TEXTURE_TUNER7_DECK_ID + dw $596a ; COLORLESS_ENERGY_DECK_ID + dw $5a0e ; POWERFUL_POKEMON_DECK_ID + dw $4180 ; WEIRD_DECK_ID + dw $4180 ; STRANGE_DECK_ID + dw $4180 ; RONALDS_UNCOOL_DECK_ID + dw $4180 ; RONALDS_GRX_DECK_ID + dw $4180 ; RONALDS_POWER_DECK_ID + dw $5a8c ; RONALDS_PSYCHIC_DECK_ID + dw $5b1c ; RONALDS_ULTRA_DECK_ID + dw $5b98 ; EVERYBODYS_FRIEND_DECK_ID + dw $5c17 ; IMMORTAL_POKEMON_DECK_ID + dw $5cbb ; TORRENTIAL_FLOOD_DECK_ID + dw $5d46 ; TRAINER_IMPRISON_DECK_ID + dw $5dd7 ; BLAZING_FLAME_DECK_ID + dw $5e54 ; DAMAGE_CHAOS_DECK_ID + dw $5ee4 ; BIG_THUNDER_DECK_ID + dw $5f57 ; POWER_OF_DARKNESS_DECK_ID + dw $5fe1 ; POISON_STORM_DECK_ID + dw $4180 + dw $4180 + dw $40f4 + dw $4102 + dw $4102 + dw $4129 + dw $412d + dw $4131 + dw $4135 + dw $4139 +; 0x14102 diff --git a/src/engine/bank06.asm b/src/engine/bank06.asm index 0b99c77..6ba3ba7 100644 --- a/src/engine/bank06.asm +++ b/src/engine/bank06.asm @@ -3,6 +3,14 @@ SECTION "Bank 6@46a6", ROMX[$46a6], BANK[$6] INCLUDE "engine/glossary.asm" ; 0x1897e +SECTION "Bank 6@4a14", ROMX[$4a14], BANK[$6] + +Func_18a14:: + xor a + ld [wd0d3], a + ret +; 0x18a19 + SECTION "Bank 6@5657", ROMX[$5657], BANK[$6] ; if carry flag is set, only delays @@ -618,10 +626,10 @@ InitSaveData: or b jr nz, .loop_collection - ld hl, sSavedDuel + ld hl, sCurrentDuel xor a ld [hli], a - ld [hli], a ; sSavedDuelChecksum + ld [hli], a ; sCurrentDuelChecksum ld [hl], a ; clears Card Pop! names @@ -643,21 +651,21 @@ InitSaveData: ; saved configuration options ld a, 2 ld [sPrinterContrastLevel], a - ld a, $2 + ld a, 2 ld [sTextSpeed], a ld [wTextSpeed], a ; miscellaneous data xor a ld [s0a007], a - ld [s0a009], a + ld [sSkipDelayAllowed], a ld [s0a004], a ld [sTotalCardPopsDone], a ld [sClearedGame], a - ld hl, s0a020 - ld [hli], a + ld hl, sTotalDuelCounter ld [hli], a ld [hli], a + ld [hli], a ; sLinkDuelCounter ld [hli], a farcall Func_8f10 @@ -669,7 +677,7 @@ InitSaveData: push de push bc push hl - ld [wcc16], a + ld [wNPCDuelDeckID], a call LoadDeck jr c, .done call .LoadDeckName @@ -698,7 +706,7 @@ InitSaveData: ret .LoadDeckName: - ld a, [wcc16] + ld a, [wNPCDuelDeckID] sub 3 farcall LoadDeckIDData ld hl, wOpponentDeckName @@ -1035,9 +1043,9 @@ DoCardPop: ; hl = text ID Func_19d24: - farcall Func_24158 + farcall _DisplayCardDetailScreen call ResumeSong - bank1call Func_4278 + bank1call SetupDuel call DisableLCD bank1call OpenCardPage_FromHand ret @@ -1473,7 +1481,7 @@ FillCardPopSummary: ld de, wCardPopSummary call CopyWordFromHLToDE call EnableSRAM - ld hl, s0a020 + ld hl, sTotalDuelCounter call CopyWordFromHLToDE call DisableSRAM call GetAmountOfCardsOwned @@ -1550,7 +1558,7 @@ ViewCardPopRecords: ret .init_list - bank1call Func_4278 + bank1call SetupDuel call .DrawSlashAndTopLineSeparator ld hl, .MenuParams ld a, [wCurMenuItem] @@ -1629,12 +1637,12 @@ ViewCardPopRecords: ld a, [wCardPopRecordName + $d] ld e, a ld d, $00 - ld hl, .portraits + ld hl, .DuelistIDs add hl, de ld a, [hl] ld e, PORTRAITVARIANT_NORMAL lb bc, 1, 2 - call Func_3ab2 + call DrawNPCPortrait call EnableLCD .loop_record_page_input @@ -1710,8 +1718,12 @@ ViewCardPopRecords: textitem 1, 15, Text026c db $ff ; end -.portraits - db $00, $01, $04, $08, $09 +.DuelistIDs + db NPC_MARK + db NPC_MINT + db NPC_RONALD + db NPC_IMAKUNI_BLACK + db NPC_IMAKUNI_RED .DrawSlashAndTopLineSeparator: lb bc, 17, 1 diff --git a/src/engine/bank07.asm b/src/engine/bank07.asm index 116cc47..a835bcf 100644 --- a/src/engine/bank07.asm +++ b/src/engine/bank07.asm @@ -157,18 +157,19 @@ Func_1c0ec:: farcall GetEventValue jr nz, .female ; male - ld a, $00 + ld a, NPC_MARK jr .asm_1c0fd .female - ld a, $01 + ld a, NPC_MINT .asm_1c0fd pop hl pop de pop bc ret -; converts a into PORTRAIT_* constant -Func_1c101:: +; converts NPC_* in a +; into PORTRAIT_* constant +GetDuelistPortrait:: push bc push hl ld c, a @@ -181,126 +182,126 @@ Func_1c101:: ret .PortraitIDs - db PORTRAIT_00 ; $00 - db PORTRAIT_01 ; $01 - db PORTRAIT_02 ; $02 - db PORTRAIT_03 ; $03 - db PORTRAIT_04 ; $04 - db PORTRAIT_05 ; $05 - db PORTRAIT_06 ; $06 - db PORTRAIT_07 ; $07 - db PORTRAIT_5E ; $08 - db PORTRAIT_5F ; $09 - db PORTRAIT_08 ; $0a - db PORTRAIT_09 ; $0b - db PORTRAIT_0A ; $0c - db PORTRAIT_0B ; $0d - db PORTRAIT_0C ; $0e - db PORTRAIT_0D ; $0f - db PORTRAIT_0E ; $10 - db PORTRAIT_0F ; $11 - db PORTRAIT_10 ; $12 - db PORTRAIT_11 ; $13 - db PORTRAIT_12 ; $14 - db PORTRAIT_13 ; $15 - db PORTRAIT_14 ; $16 - db PORTRAIT_15 ; $17 - db PORTRAIT_16 ; $18 - db PORTRAIT_17 ; $19 - db PORTRAIT_18 ; $1a - db PORTRAIT_19 ; $1b - db PORTRAIT_1A ; $1c - db PORTRAIT_1B ; $1d - db PORTRAIT_1C ; $1e - db PORTRAIT_1D ; $1f - db PORTRAIT_1E ; $20 - db PORTRAIT_1F ; $21 - db PORTRAIT_20 ; $22 - db PORTRAIT_21 ; $23 - db PORTRAIT_22 ; $24 - db PORTRAIT_23 ; $25 - db PORTRAIT_24 ; $26 - db PORTRAIT_25 ; $27 - db PORTRAIT_26 ; $28 - db PORTRAIT_27 ; $29 - db PORTRAIT_28 ; $2a - db PORTRAIT_29 ; $2b - db PORTRAIT_2A ; $2c - db PORTRAIT_2B ; $2d - db PORTRAIT_2C ; $2e - db PORTRAIT_2D ; $2f - db PORTRAIT_2E ; $30 - db PORTRAIT_2F ; $31 - db PORTRAIT_30 ; $32 - db PORTRAIT_31 ; $33 - db PORTRAIT_32 ; $34 - db PORTRAIT_33 ; $35 - db PORTRAIT_34 ; $36 - db PORTRAIT_35 ; $37 - db PORTRAIT_36 ; $38 - db PORTRAIT_37 ; $39 - db PORTRAIT_38 ; $3a - db PORTRAIT_39 ; $3b - db PORTRAIT_3A ; $3c - db PORTRAIT_3B ; $3d - db PORTRAIT_3C ; $3e - db PORTRAIT_3D ; $3f - db PORTRAIT_3E ; $40 - db PORTRAIT_3F ; $41 - db PORTRAIT_40 ; $42 - db PORTRAIT_41 ; $43 - db PORTRAIT_42 ; $44 - db PORTRAIT_43 ; $45 - db PORTRAIT_44 ; $46 - db PORTRAIT_45 ; $47 - db PORTRAIT_46 ; $48 - db PORTRAIT_47 ; $49 - db PORTRAIT_48 ; $4a - db PORTRAIT_49 ; $4b - db PORTRAIT_4A ; $4c - db PORTRAIT_4B ; $4d - db PORTRAIT_4C ; $4e - db PORTRAIT_4D ; $4f - db PORTRAIT_4E ; $50 - db PORTRAIT_4F ; $51 - db PORTRAIT_50 ; $52 - db PORTRAIT_51 ; $53 - db PORTRAIT_52 ; $54 - db PORTRAIT_53 ; $55 - db PORTRAIT_54 ; $56 - db PORTRAIT_55 ; $57 - db PORTRAIT_56 ; $58 - db PORTRAIT_57 ; $59 - db PORTRAIT_58 ; $5a - db PORTRAIT_59 ; $5b - db PORTRAIT_5A ; $5c - db PORTRAIT_5B ; $5d - db PORTRAIT_5C ; $5e - db PORTRAIT_5D ; $5f + db PORTRAIT_MARK ; NPC_MARK + db PORTRAIT_MINT ; NPC_MINT + db PORTRAIT_MARK_LINK ; NPC_MARK_LINK + db PORTRAIT_MINT_LINK ; NPC_MINT_LINK + db PORTRAIT_RONALD ; NPC_RONALD + db PORTRAIT_SAM ; NPC_SAM + db PORTRAIT_AARON ; NPC_AARON + db PORTRAIT_ISHIHARA ; NPC_ISHIHARA + db PORTRAIT_IMAKUNI_BLACK ; NPC_IMAKUNI_BLACK + db PORTRAIT_IMAKUNI_RED ; NPC_IMAKUNI_RED + db PORTRAIT_ISAAC ; NPC_ISAAC + db PORTRAIT_JENNIFER ; NPC_JENNIFER + db PORTRAIT_NICHOLAS ; NPC_NICHOLAS + db PORTRAIT_BRANDON ; NPC_BRANDON + db PORTRAIT_MURRAY ; NPC_MURRAY + db PORTRAIT_STEPHANIE ; NPC_STEPHANIE + db PORTRAIT_DANIEL ; NPC_DANIEL + db PORTRAIT_ROBERT ; NPC_ROBERT + db PORTRAIT_GENE ; NPC_GENE + db PORTRAIT_MATTHEW ; NPC_MATTHEW + db PORTRAIT_RYAN ; NPC_RYAN + db PORTRAIT_ANDREW ; NPC_ANDREW + db PORTRAIT_MITCH ; NPC_MITCH + db PORTRAIT_MICHAEL ; NPC_MICHAEL + db PORTRAIT_CHRIS ; NPC_CHRIS + db PORTRAIT_JESSICA ; NPC_JESSICA + db PORTRAIT_NIKKI ; NPC_NIKKI + db PORTRAIT_BRITTANY ; NPC_BRITTANY + db PORTRAIT_KRISTIN ; NPC_KRISTIN + db PORTRAIT_HEATHER ; NPC_HEATHER + db PORTRAIT_RICK ; NPC_RICK + db PORTRAIT_JOSEPH ; NPC_JOSEPH + db PORTRAIT_DAVID ; NPC_DAVID + db PORTRAIT_ERIK ; NPC_ERIK + db PORTRAIT_AMY ; NPC_AMY + db PORTRAIT_JOSHUA ; NPC_JOSHUA + db PORTRAIT_SARA ; NPC_SARA + db PORTRAIT_AMANDA ; NPC_AMANDA + db PORTRAIT_KEN ; NPC_KEN + db PORTRAIT_JOHN ; NPC_JOHN + db PORTRAIT_ADAM ; NPC_ADAM + db PORTRAIT_JONATHAN ; NPC_JONATHAN + db PORTRAIT_COURTNEY ; NPC_COURTNEY + db PORTRAIT_STEVE ; NPC_STEVE + db PORTRAIT_JACK ; NPC_JACK + db PORTRAIT_ROD ; NPC_ROD + db PORTRAIT_EIJI ; NPC_EIJI + db PORTRAIT_MAGICIAN ; NPC_MAGICIAN + db PORTRAIT_YUI ; NPC_YUI + db PORTRAIT_TOSHIRON ; NPC_TOSHIRON + db PORTRAIT_PIERROT ; NPC_PIERROT + db PORTRAIT_ANNA ; NPC_ANNA + db PORTRAIT_DEE ; NPC_DEE + db PORTRAIT_MASQUERADE ; NPC_MASQUERADE + db PORTRAIT_PAWN ; NPC_PAWN + db PORTRAIT_KNIGHT ; NPC_KNIGHT + db PORTRAIT_BISHOP ; NPC_BISHOP + db PORTRAIT_ROOK ; NPC_ROOK + db PORTRAIT_QUEEN ; NPC_QUEEN + db PORTRAIT_GR_1 ; NPC_GR_1 + db PORTRAIT_GR_2 ; NPC_GR_2 + db PORTRAIT_GR_3 ; NPC_GR_3 + db PORTRAIT_GR_4 ; NPC_GR_4 + db PORTRAIT_MIDORI ; NPC_MIDORI + db PORTRAIT_YUUTA ; NPC_YUUTA + db PORTRAIT_MIYUKI ; NPC_MIYUKI + db PORTRAIT_MORINO ; NPC_MORINO + db PORTRAIT_RENNA ; NPC_RENNA + db PORTRAIT_ICHIKAWA ; NPC_ICHIKAWA + db PORTRAIT_CATHERINE ; NPC_CATHERINE + db PORTRAIT_TAP ; NPC_TAP + db PORTRAIT_JES ; NPC_JES + db PORTRAIT_YUKI ; NPC_YUKI + db PORTRAIT_SHOKO ; NPC_SHOKO + db PORTRAIT_HIDERO ; NPC_HIDERO + db PORTRAIT_MIYAJIMA ; NPC_MIYAJIMA + db PORTRAIT_SENTA ; NPC_SENTA + db PORTRAIT_AIRA ; NPC_AIRA + db PORTRAIT_KANOKO ; NPC_KANOKO + db PORTRAIT_GODA ; NPC_GODA + db PORTRAIT_GRACE ; NPC_GRACE + db PORTRAIT_KAMIYA ; NPC_KAMIYA + db PORTRAIT_MIWA ; NPC_MIWA + db PORTRAIT_KEVIN ; NPC_KEVIN + db PORTRAIT_YOSUKE ; NPC_YOSUKE + db PORTRAIT_RYOKO ; NPC_RYOKO + db PORTRAIT_MAMI ; NPC_MAMI + db PORTRAIT_NISHIJIMA ; NPC_NISHIJIMA + db PORTRAIT_ISHII ; NPC_ISHII + db PORTRAIT_SAMEJIMA ; NPC_SAMEJIMA + db PORTRAIT_KANZAKI ; NPC_KANZAKI + db PORTRAIT_RUI ; NPC_RUI + db PORTRAIT_BIRURITCHI ; NPC_BIRURITCHI + db PORTRAIT_GR_X ; NPC_GR_X + db PORTRAIT_TOBI_CHAN ; NPC_TOBI_CHAN + db PORTRAIT_DR_MASON ; NPC_DR_MASON ; 0x1c116 SECTION "Bank 7@4395", ROMX[$4395], BANK[$7] -Func_1c395: +LoadSavedOptions: call EnableSRAM - call Func_1c3a8 - call Func_1c3b9 - call Func_1c3c7 - call Func_1c3ce + call .LoadTextSpeed + call .LoadDuelAnimation + call .LoadCoinTossAnimation + call .LoadTextFrameColor call DisableSRAM ret -Func_1c3a8: +.LoadTextSpeed: ld a, [sTextSpeed] ld [wTextSpeed], a call Func_1c448 ld b, a - ld a, $04 + ld a, 4 sub b ld [wd9d5], a ret -Func_1c3b9: +.LoadDuelAnimation: ld a, [s0a007] ld [wd9d3], a srl a @@ -308,12 +309,12 @@ Func_1c3b9: ld [wdc0f], a ret -Func_1c3c7: +.LoadCoinTossAnimation: ld a, [s0a00b] ld [wd9d4], a ret -Func_1c3ce: +.LoadTextFrameColor: ld a, [sTextBoxFrameColor] ld [wTextBoxFrameColor], a ret @@ -350,7 +351,7 @@ Func_1c3f9: ld hl, .data add hl, bc ld a, [hl] - ld [s0a009], a + ld [sSkipDelayAllowed], a ret .data @@ -1655,7 +1656,7 @@ ShowStartMenu: add 0 lb bc, 13, 1 ld e, PORTRAITVARIANT_NORMAL - call Func_3ab2 + call DrawNPCPortrait ; print player's name farcall LoadPlayerName @@ -2178,11 +2179,11 @@ Func_1d475: farcall Func_111f0 call Func_1c425 call Func_1c3d5 - call Func_1c395 + call LoadSavedOptions ret .Read: - call Func_1c395 + call LoadSavedOptions ld a, $01 farcall Func_108c9 ret @@ -2293,7 +2294,7 @@ Func_1dfb9:: ld [wdce2], a ld [wdc59], a ld [wdce8], a - ld [wdce5], a + ld [wDuelAnimLocationParam], a ld [wdcf0], a ld [wdc57], a ld a, $ff @@ -2319,6 +2320,243 @@ Func_1e419: ret ; 0x1e420 +SECTION "Bank 7@65a2", ROMX[$65a2], BANK[$7] + +; returns carry if player lost +Func_1e5a2:: + push bc + push de + push hl + ld a, EVENT_F0 + farcall GetEventValue + jr nz, .from_sram + call .RunDuel + jr .check_result +.from_sram + call RunDuelFromSRAM +.check_result + scf + ccf + ld a, [wDuelResult] + and a + jr z, .won + scf ; lost +.won + pop hl + pop de + pop bc + ret + +.RunDuel: + farcall Func_1022a + call Func_1e73a + ld a, EVENT_EB + farcall GetEventValue + jr nz, .start_duel + call Func_1e60c + ld a, [wSpecialRule] + and a + jr z, .start_duel + call ShowSpecialRuleDescription +.start_duel + bank1call StartDuel_VSAIOpp + farcall Func_10252 + ret +; 0x1e5e5 + +SECTION "Bank 7@65f8", ROMX[$65f8], BANK[$7] + +RunDuelFromSRAM: + farcall Func_10cfe + farcall Func_1109f + farcall Func_1022a + bank1call StartDuelFromSRAM + farcall Func_10252 + ret + +Func_1e60c: + push af + push bc + push de + push hl + farcall ClearSpriteAnimsAndSetInitialGraphicsConfiguration + + ; show opponent portrait + ld a, [wOpponentNPCID] + lb bc, 7, 3 + ld e, PORTRAITVARIANT_NORMAL + call DrawNPCPortrait + + farcall SetFrameFuncAndFadeFromWhite + + ; play duel start theme + ld a, [wDuelStartTheme] + push af + ld a, a ; wow + call Func_3d09 + pop af + + ; print duelist intro text + ld a, [wOpponentName + 0] + ld [wTxRam2 + 0], a + ld a, [wOpponentName + 1] + ld [wTxRam2 + 1], a + ld a, [wOpponentDeckName + 0] + ld [wTxRam2_b + 0], a + ld a, [wOpponentDeckName + 1] + ld [wTxRam2_b + 1], a + ld a, [wcd0f] + dec a + add a ; *2 + ld c, a + ld b, $00 + ld hl, .DuelistIntroTextIDs + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + farcall Func_1107c + + call WaitForSongToFinish + call WaitForWideTextBoxInput + farcall FadeToWhiteAndUnsetFrameFunc + pop hl + pop de + pop bc + pop af + ret + +.DuelistIntroTextIDs + tx Text0651 + tx Text0652 + tx Text0653 + tx Text0654 + tx Text0655 + tx Text0656 + tx Text0657 + tx Text0658 + tx Text0659 + tx Text065a + tx Text065b + tx Text065c + tx Text065d + tx Text065e + tx Text065f + tx Text0660 + tx Text0661 + tx Text0662 + tx Text0663 + tx Text0664 + tx Text0665 + tx Text0666 + tx Text0667 + tx Text0668 + tx Text0669 + tx Text066a + tx Text066b + tx Text066c + tx Text066d + tx Text066e + tx Text066f + tx Text0670 + tx Text0671 + tx Text0672 + tx Text0673 + tx Text0674 + tx Text0675 + tx Text0676 + tx Text0677 + tx Text0678 + +ShowSpecialRuleDescription: + push af + push bc + push de + push hl + farcall ClearSpriteAnimsAndSetInitialGraphicsConfiguration + call .DrawScreen + farcall SetFrameFuncAndFadeFromWhite + call WaitForWideTextBoxInput + farcall FadeToWhiteAndUnsetFrameFunc + pop hl + pop de + pop bc + pop af + ret + +.DrawScreen: + ld a, [wSpecialRule] + add a + add a + ld c, a ; *4 + ld b, $00 + ld hl, .TitleAndDescriptionTextIDs + add hl, bc + + ; draws scene with text box drawn around + lb de, 0, 0 + lb bc, 20, 6 + call DrawRegularTextBoxVRAM0 + ld a, SCENE_SPECIAL_RULES + lb bc, 5, 1 + call LoadScene + + ; print title + push hl + ld a, [hli] + ld h, [hl] + ld l, a + lb de, 3, 4 + call Func_35af + pop hl + + ; print description + inc hl + inc hl + lb de, 0, 6 + lb bc, 20, 12 + call DrawRegularTextBoxVRAM0 + ld a, [hli] + ld h, [hl] + ld l, a + lb de, 1, 8 + call Func_35af + ret + +.TitleAndDescriptionTextIDs: + ; title, description + dw NULL, NULL ; NO_SPECIAL_RULE + tx Text063b, Text063c ; CHLOROPHYLL + tx Text063d, Text063e ; THUNDER_CHARGE + tx Text063f, Text0640 ; FLAME_ARMOR + tx Text0641, Text0642 ; SMALL_BENCH + tx Text0643, Text0644 ; RUNNING_WATER + tx Text0645, Text0646 ; EARTH_POWER + tx Text0647, Text0648 ; LOW_RESISTANCE + tx Text0649, Text064a ; ENERGY_RETURN + tx Text064b, Text064c ; TOUGH_ESCAPE + tx Text064d, Text064e ; BLACK_HOLE +; 0x1e73a + +SECTION "Bank 7@673a", ROMX[$673a], BANK[$7] + +Func_1e73a: + push af + push bc + push de + push hl + ld a, [wNPCDuelDeckID] + push af + farcall LoadDeckIDData + pop af + ld [wNPCDuelDeckID], a + pop hl + pop de + pop bc + pop af + ret +; 0x1e74f + SECTION "Bank 7@6767", ROMX[$6767], BANK[$7] Func_1e767: diff --git a/src/engine/bank09.asm b/src/engine/bank09.asm index 3e06c9e..39b534f 100644 --- a/src/engine/bank09.asm +++ b/src/engine/bank09.asm @@ -1,26 +1,151 @@ -SECTION "Bank 9@409a", ROMX[$409a], BANK[$9] +; save data of the current duel to sCurrentDuel +; byte 0 is $01, bytes 1 and 2 are the checksum, byte 3 is [wDuelType] +; next $33a bytes come from DuelDataToSave +SaveDuelData:: + ld de, sCurrentDuel +; fallthrough + +; save data of the current duel to de (in SRAM) +; byte 0 is $01, bytes 1 and 2 are the checksum, byte 3 is [wDuelType] +; next $33a bytes come from DuelDataToSave +SaveDuelDataToDE:: + call EnableSRAM + push de + inc de + inc de + inc de + inc de + ld hl, DuelDataToSave + push de +.save_duel_data_loop + ; start copying data to de = sCurrentDuelData + $1 + ld c, [hl] + inc hl + ld b, [hl] + inc hl + ld a, c + or b + jr z, .data_done + push hl + push bc + ld c, [hl] + inc hl + ld b, [hl] + inc hl + pop hl + call CopyDataHLtoDE + pop hl + inc hl + inc hl + jr .save_duel_data_loop +.data_done + pop hl + ; save a checksum to hl = sCurrentDuelData + $1 + lb de, $23, $45 + ld bc, $352 +.checksum_loop + ld a, e + sub [hl] + ld e, a + ld a, [hli] + xor d + ld d, a + dec bc + ld a, c + or b + jr nz, .checksum_loop + pop hl + ld a, $01 + ld [hli], a ; sCurrentDuel + ld [hl], e ; sCurrentDuelChecksum + inc hl + ld [hl], d ; sCurrentDuelChecksum + inc hl + ld a, [wDuelType] + ld [hl], a ; sCurrentDuelData + call DisableSRAM + ret + +Func_24048: + ld hl, sCurrentDuel + call CheckSavedDuelChecksum_FromHL + ret c + ld de, sCurrentDuel + call LoadSavedDuelData + or a + ret + +; load the data saved in sCurrentDuelData to WRAM according to the distribution +; of DuelDataToSave. assumes saved data exists and that the checksum is valid. +LoadSavedDuelData: + call EnableSRAM + inc de + inc de + inc de + inc de + ld hl, DuelDataToSave +.loop + ld c, [hl] + inc hl + ld b, [hl] + inc hl + ld a, c + or b + jr z, .done + push hl + push bc + ld c, [hl] + inc hl + ld b, [hl] + inc hl + pop hl +.loop_copy + ld a, [de] + inc de + ld [hli], a + dec bc + ld a, c + or b + jr nz, .loop_copy + pop hl + inc hl + inc hl + jr .loop +.done + call DisableSRAM + bank1call Func_6838 + ret + +DuelDataToSave: +; dw address, number of bytes to copy + dw STARTOF("WRAM0 Duels 1"), wNameBuffer + NAME_BUFFER_LENGTH - STARTOF("WRAM0 Duels 1") + dw wWhoseTurn, $24 + dw hWhoseTurn, $1 + dw wRNG1, $3 + dw $d023, $20 + dw NULL ; return carry if saved duel checksum ; in SRAM is not valid CheckSavedDuelChecksum: call EnableSRAM - ld hl, sSavedDuel - ld a, [sSavedDuelChecksum + $2] + ld hl, sCurrentDuel + ld a, [sCurrentDuelChecksum + $2] call DisableSRAM cp $01 - jr nz, .continue + jr nz, CheckSavedDuelChecksum_FromHL scf ret -.continue +CheckSavedDuelChecksum_FromHL: call EnableSRAM push de - ld a, [hli] ; sSavedDuel + ld a, [hli] ; sCurrentDuel or a jr z, .set_carry lb de, $23, $45 ld bc, $352 - ld a, [hl] ; sSavedDuelChecksum + ld a, [hl] ; sCurrentDuelChecksum sub e ld e, a inc hl @@ -29,7 +154,7 @@ CheckSavedDuelChecksum: ld d, a inc hl inc hl - ; hl = sSavedDuelData + ; hl = sCurrentDuelData .loop_data ld a, [hl] add e @@ -53,46 +178,114 @@ CheckSavedDuelChecksum: ClearSavedDuel: call EnableSRAM - ld hl, sSavedDuel + ld hl, sCurrentDuel xor a ld [hli], a ld [hli], a ld [hl], a call DisableSRAM ret -; 0x240e6 -SECTION "Bank 9@4158", ROMX[$4158], BANK[$9] - -Func_24158: +; save duel state to SRAM +; called between each two-player turn, just after player draws card (ROM bank 1 loaded) +SaveDuelStateToSRAM: + ld a, $2 + call BankswitchSRAM + ; save duel data to sCurrentDuel + call SaveDuelData + xor a + call BankswitchSRAM + call EnableSRAM + ld hl, s0a008 + ld a, [hl] + inc [hl] + call DisableSRAM + ; select hl = SRAM3:(a000 + $400 * [s0a008] & $3) + ; save wDuelTurns, non-turn holder's arena card ID, turn holder's arena card ID + and $3 + add HIGH($a000) / 4 + ld l, $0 + ld h, a + add hl, hl + add hl, hl + ld a, $3 + call BankswitchSRAM push hl - call .Func_2416e - ld a, $12 + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + ld hl, wTempTurnDuelistCardID + ld [hl], e + inc hl + ld [hl], d + call SwapTurn + ld a, DUELVARS_ARENA_CARD + get_turn_duelist_var + call GetCardIDFromDeckIndex + ld hl, wTempNonTurnDuelistCardID + ld [hl], e + inc hl + ld [hl], d + call SwapTurn + pop hl + push hl + call EnableSRAM + ld a, [wDuelTurns] + ld [hli], a + ld a, [wTempNonTurnDuelistCardID] + ld [hli], a + ld a, [wTempNonTurnDuelistCardID + 1] + ld [hli], a + ld a, [wTempTurnDuelistCardID] + ld [hli], a + ld a, [wTempTurnDuelistCardID + 1] + ld [hli], a + ; save duel data to SRAM3:(a000 + $400 * [s0a008] & $3) + $10 + pop hl + ld de, $10 + add hl, de + ld e, l + ld d, h + call DisableSRAM + call SaveDuelDataToDE + xor a + call BankswitchSRAM + call DisableSRAM + ret + +; display the card details of the card in wLoadedCard1 +; print the text at hl +_DisplayCardDetailScreen: + push hl + call DrawLargePictureOfCard + ld a, 18 call CopyCardNameAndLevel ld [hl], TX_END - ld hl, $0 + ld hl, 0 call LoadTxRam2 pop hl call DrawWideTextBox_WaitForInput ret -.Func_2416e: +; draw a large picture of the card loaded in wLoadedCard1, including its image +; and a header indicating the type of card (TRAINER, ENERGY, PoKéMoN) +DrawLargePictureOfCard: bank1call ZeroObjectPositionsAndToggleOAMCopy call EmptyScreen call LoadSymbolsFont bank1call SetDefaultPalettes - ld a, $08 + ld a, LARGE_CARD_PICTURE ld [wDuelDisplayedScreen], a call LoadCardOrDuelMenuBorderTiles - ld e, $00 ; trainer + ld e, HEADER_TRAINER ld a, [wLoadedCard1Type] cp TYPE_TRAINER - jr z, .asm_24193 - ld e, $01 ; energy + jr z, .draw + ld e, HEADER_ENERGY and TYPE_ENERGY - jr nz, .asm_24193 - ld e, $02 ; pkmn -.asm_24193 + jr nz, .draw + ld e, HEADER_POKEMON +.draw push de ld a, e call LoadCardTypeHeaderTiles @@ -163,7 +356,797 @@ DrawDuelHorizontalSeparator: db 9, 6, $01, $21, 0 db 9, 7, $61, $61, $01, $01, $01, $01, $01, $01, $01, $01, $01, 0 db $ff ; end -; 0x242c5 + +; handles menu for when player is waiting for +; Link Opponent to make a decision, where it's +; possible to examine the hand or duel main scene +HandleWaitingLinkOpponentMenu: + ld a, 10 +.delay_loop + call DoFrame + dec a + jr nz, .delay_loop + ld [wCurrentDuelMenuItem], a ; 0 +.loop_outer + ld a, PLAYER_TURN + ldh [hWhoseTurn], a + ldtx hl, Text005a ; WaitingHandExamineText + call DrawWideTextBox_PrintTextNoDelay + call .InitTextBoxMenu +.loop_inner + call DoFrame + call .HandleInput + call RefreshMenuCursor + ldh a, [hKeysPressed] + bit A_BUTTON_F, a + jr nz, .a_pressed + ld a, $01 + bank1call HandleSpecialDuelMainSceneHotkeys + jr nc, .loop_inner +.duel_main_scene + bank1call DrawDuelMainScene + jr .loop_outer +.a_pressed + ld a, [wCurrentDuelMenuItem] + or a + jr z, .open_hand +; duel check + call OpenDuelCheckMenu + jr .duel_main_scene +.open_hand + bank1call OpenTurnHolderHandScreen_Simple + jr .duel_main_scene + +.HandleInput: + ldh a, [hDPadHeld] + bit B_BUTTON_F, a + ret nz + and D_LEFT | D_RIGHT + ret z + ld a, SFX_01 + call PlaySFX + call EraseCursor + ld hl, wCurrentDuelMenuItem + ld a, [hl] + xor $01 + ld [hl], a + +.InitTextBoxMenu: + ld d, 2 + ld a, [wCurrentDuelMenuItem] + or a + jr z, .set_cursor_params + ld d, 8 +.set_cursor_params + ld e, 16 + lb bc, SYM_CURSOR_R, SYM_SPACE + call SetCursorParametersForTextBox + ret + +SetLinkDuelTransmissionFrameFunction: + call FinishQueuedAnimations + ld hl, sp+$00 + ld a, l + ld [wLinkOpponentTurnReturnAddress], a + ld a, h + ld [wLinkOpponentTurnReturnAddress + 1], a + ld de, LinkOpponentTurnFrameFunction + ld hl, wDoFrameFunction + ld [hl], e + inc hl + ld [hl], d + ret + +ResetDoFrameFunction_Bank9: + xor a + ld hl, wDoFrameFunction + ld [hli], a + ld [hl], a + ret +; 0x24350 + +SECTION "Bank 9@43ee", ROMX[$43ee], BANK[$9] + +Func_243ee: + push de + push hl + dec e + lb bc, 18, 7 + lb hl, 0, 0 + ld a, $00 + call FillRectangle + pop hl + pop de + bank1call PrintAttackOrCardDescription + ret + +; display the screen that prompts the player to use the selected card's +; Pokemon Power. Includes the card's information above, and the Pokemon Power's +; description below. +; input: hTempPlayAreaLocation_ff9d +DisplayUsePokemonPowerScreen: + push hl + ldh a, [hTempPlayAreaLocation_ff9d] + ld [wCurPlayAreaSlot], a + xor a + ld [wCurPlayAreaY], a + bank1call ZeroObjectPositionsAndToggleOAMCopy + call EmptyScreen + call LoadDuelCardSymbolTiles + call LoadDuelCheckPokemonScreenTiles + bank1call Func_6c12 + pop hl + call Func_24494 + bank1call PrintPlayAreaCardInformationAndLocation + lb de, 1, 4 + call InitTextPrinting + ld hl, wLoadedCard1Atk1Name + call InitTextPrinting_ProcessTextFromPointerToID + lb de, 1, 6 + ld hl, wLoadedCard1Atk1Description + bank1call PrintAttackOrCardDescription + ld hl, wLoadedCard1Atk1Description + $2 + ld a, [hli] + or [hl] + ret z ; no second page + ; print second page info + call WaitForWideTextBoxInput + bank1call PrintPlayAreaCardInformationAndLocation + lb de, 1, 4 + call InitTextPrinting + ld hl, wLoadedCard1Atk1Name + call InitTextPrinting_ProcessTextFromPointerToID + ld hl, wLoadedCard1Atk1Description + $2 + lb de, 1, 6 + call Func_243ee + ret +; 0x24459 + +SECTION "Bank 9@4494", ROMX[$4494], BANK[$9] + +Func_24494: + push hl + call DrawWideTextBox + ld a, 19 + lb de, 1, 14 + call AdjustCoordinatesForBGScroll + call InitTextPrintingInTextbox + pop hl + jp PrintTextNoDelay + +; display card detail when a trainer card is used, and print "Used xxx" +; hTempCardIndex_ff9f contains the card's deck index +DisplayUsedTrainerCardDetailScreen: + ldh a, [hTempCardIndex_ff9f] + ldtx hl, Text0034 ; UsedText + bank1call DisplayCardDetailScreen + ret + +SECTION "Bank 9@44b0", ROMX[$44b0], BANK[$9] + +; print the AttachedEnergyToPokemonText, given the energy card to attach in hTempCardIndex_ff98, +; and the PLAY_AREA_* of the turn holder's Pokemon to attach the energy to in hTempPlayAreaLocation_ff9d +PrintAttachedEnergyToPokemon: + ldh a, [hTempPlayAreaLocation_ff9d] + add DUELVARS_ARENA_CARD + get_turn_duelist_var + call LoadCardNameToTxRam2_b + ldh a, [hTempCardIndex_ff98] + call LoadCardNameToTxRam2 + ldtx hl, Text0061 ; AttachedEnergyToPokemonText + call DrawWideTextBox_WaitForInput + ret + +; print the PokemonEvolvedIntoPokemonText, given the Pokemon card to evolve in wPreEvolutionPokemonCard, +; and the evolved Pokemon card in hTempCardIndex_ff98. also play a sound effect. +PrintPokemonEvolvedIntoPokemon: + ld a, SFX_5E + call PlaySFX + ld a, [wPreEvolutionPokemonCard] + call LoadCardNameToTxRam2 + ldh a, [hTempCardIndex_ff98] + call LoadCardNameToTxRam2_b + ldtx hl, Text0062 ; AttachedEnergyToPokemonText + call DrawWideTextBox_WaitForInput + ret + +DoAIOpponentTurn: + xor a + ld [wVBlankCounter], a + ld [wSkipDuelistIsThinkingDelay], a + ldtx hl, Text008d ; DuelistIsThinkingText + call DrawWideTextBox_PrintTextNoDelay + call AIDoAction_Turn + ld a, $ff + ld [wPlayerAttackingCardIndex], a + ld [wPlayerAttackingAttackIndex], a + ret +; 0x244f4 + +SECTION "Bank 9@4531", ROMX[$4531], BANK[$9] + +; handle the opponent's turn in a link duel +; loop until either [wOpponentTurnEnded] or [wDuelFinished] is non-0 +DoLinkOpponentTurn: + xor a + ld [wOpponentTurnEnded], a + xor a + ld [wSkipDuelistIsThinkingDelay], a +.link_opp_turn_loop + ld a, [wSkipDuelistIsThinkingDelay] + or a + jr nz, .asm_6932 + call SetLinkDuelTransmissionFrameFunction + call HandleWaitingLinkOpponentMenu + ld a, [wDuelDisplayedScreen] + cp CHECK_PLAY_AREA + jr nz, .asm_6932 + lb de, $38, $9f + call SetupText +.asm_6932 + call ResetDoFrameFunction_Bank9 + call SerialRecvDuelData + ld a, OPPONENT_TURN + ldh [hWhoseTurn], a + ld a, [wSerialFlags] + or a + jp nz, DuelTransmissionError + xor a + ld [wSkipDuelistIsThinkingDelay], a + ldh a, [hOppActionTableIndex] + cp NUM_OPP_ACTIONS + jp nc, DuelTransmissionError + ld hl, $457e ; OppActionTable + call JumpToFunctionInTable + ld a, [wDuelFinished] + ld hl, wOpponentTurnEnded + or [hl] + jr z, .link_opp_turn_loop + ret + +SECTION "Bank 9@4829", ROMX[$4829], BANK[$9] + +; load the text ID of the card name with deck index given in a to TxRam2 +; also loads the card to wLoadedCard1 +LoadCardNameToTxRam2: + call LoadCardDataToBuffer1_FromDeckIndex + ld a, [wLoadedCard1Name] + ld [wTxRam2], a + ld a, [wLoadedCard1Name + 1] + ld [wTxRam2 + 1], a + ret + +; load the text ID of the card name with deck index given in a to TxRam2_b +; also loads the card to wLoadedCard1 +LoadCardNameToTxRam2_b: + call LoadCardDataToBuffer1_FromDeckIndex + ld a, [wLoadedCard1Name] + ld [wTxRam2_b], a + ld a, [wLoadedCard1Name + 1] + ld [wTxRam2_b + 1], a + ret + +; draw the portraits of the two duelists and print their names. +; also draw an horizontal line separating the two sides. +DrawDuelistPortraitsAndNames: + ld a, $00 + ld [wcd77], a + call AIDoAction_06 + + call LoadSymbolsFont + + ; player's name + ld de, wDefaultText + push de + call CopyPlayerName + lb de, 0, 11 + call InitTextPrinting + pop hl + call ProcessText + ; player's portrait + lb bc, 0, 5 + call DrawPlayerPortrait + + ; opponent's name (aligned to the right) + ld de, wDefaultText + push de + call CopyOpponentName + pop hl + call GetTextLengthInTiles + push hl + add SCREEN_WIDTH + ld d, a + ld e, 0 + call InitTextPrinting + pop hl + call ProcessText + ; opponent's portrait + call DrawOpponentPortrait + ; middle line + call DrawDuelHorizontalSeparator + call FlushAllPalettes + ret + +DrawOpponentPortrait: + ld a, [wcd78] + ld e, a + ld a, [wOpponentNPCID] + lb bc, 13, 1 + call DrawNPCPortrait + ret + +PlayShuffleAndDrawCardsAnimation_TurnDuelist: + ld b, DUEL_ANIM_PLAYER_SHUFFLE + ld c, DUEL_ANIM_PLAYER_DRAW + ldh a, [hWhoseTurn] + cp PLAYER_TURN + jr z, .play_anim + ld b, DUEL_ANIM_OPP_SHUFFLE + ld c, DUEL_ANIM_OPP_DRAW +.play_anim + ldtx hl, Text0065 ; ShufflesTheDeckText + ldtx de, Text0069 ; Drew7CardsText + jr PlayShuffleAndDrawCardsAnimation + +PlayShuffleAndDrawCardsAnimation_BothDuelists: + ld b, DUEL_ANIM_BOTH_SHUFFLE + ld c, DUEL_ANIM_BOTH_DRAW + ldtx hl, Text0067 ; EachPlayerShuffleOpponentsDeckText + ldtx de, Text0068 ; EachPlayerDraw7CardsText + ld a, [wcd17] + or a + jr z, PlayShuffleAndDrawCardsAnimation + ldtx hl, Text0066 ; ThisIsJustPracticeDoNotShuffleText +; fallthrough + +; animate the shuffle and drawing screen +; input: +; b = shuffling animation index +; c = drawing animation index +; hl = text to print while shuffling +; de = text to print while drawing +PlayShuffleAndDrawCardsAnimation: + push bc + push de + push hl + bank1call ZeroObjectPositionsAndToggleOAMCopy + call EmptyScreen + call DrawDuelistPortraitsAndNames + call LoadDuelDrawCardsScreenTiles + ld a, SHUFFLE_DECK + ld [wDuelDisplayedScreen], a + pop hl + call DrawWideTextBox_PrintText + call EnableLCD + ld a, [wcd17] + or a + jr z, .not_practice + call WaitForWideTextBoxInput + jr .print_deck_info + +.not_practice +; get the shuffling animation from input value of b + call ResetAnimationQueue + ld hl, sp+$03 + ; play animation 3 times + ld a, [hl] + call PlayDuelAnimation + ld a, [hl] + call PlayDuelAnimation + ld a, [hl] + call PlayDuelAnimation + +.loop_shuffle_anim + call DoFrame + bank1call CheckSkipDelayAllowed + jr c, .done_shuffle + call CheckAnyAnimationPlaying + jr c, .loop_shuffle_anim +.done_shuffle + call FinishQueuedAnimations + +.print_deck_info + xor a + ld [wNumCardsBeingDrawn], a + call PrintDeckAndHandIconsAndNumberOfCards + call ResetAnimationQueue + pop hl + call DrawWideTextBox_PrintText +.draw_card +; get the draw animation from input value of c + ld hl, sp+$00 + ld a, [hl] + call PlayDuelAnimation + +.loop_drawing_anim + call DoFrame + bank1call CheckSkipDelayAllowed + jr c, .done_draw + call CheckAnyAnimationPlaying + jr c, .loop_drawing_anim + +.done_draw + ld hl, wNumCardsBeingDrawn + inc [hl] + ld hl, sp+$00 + ld a, [hl] + cp DUEL_ANIM_BOTH_DRAW + jr nz, .one_duelist_shuffled + ; if both duelists shuffled + call PrintDeckAndHandIconsAndNumberOfCards.not_cgb + jr .check_num_cards +.one_duelist_shuffled + call PrintNumberOfHandAndDeckCards + +.check_num_cards + ld a, [wNumCardsBeingDrawn] + cp 7 + jr c, .draw_card + + ld c, 30 +.wait_loop + call DoFrame + bank1call CheckSkipDelayAllowed + jr c, .done + dec c + jr nz, .wait_loop + +.done + call FinishQueuedAnimations + pop bc + ret + +SECTION "Bank 9@49c6", ROMX[$49c6], BANK[$9] + +; places the prize cards on both sides +; of the Play Area (player & opp) +PlacePrizes: + ld hl, .PrizeCardCoordinates + ld e, DECK_SIZE - 7 - 1 ; deck size - cards drawn - 1 + ld a, [wDuelInitialPrizes] + ld d, a + +.place_prize + push de + ld b, 20 ; frames to delay +.loop_delay + call DoFrame + bank1call CheckSkipDelayAllowed + jr c, .skip_delay + dec b + jr nz, .loop_delay +.skip_delay + call .DrawPrizeTile + call .DrawPrizeTile + + push hl + ld a, SFX_08 + call PlaySFX + ; print new deck card number + lb bc, 3, 5 + ld a, e + bank1call WriteTwoDigitNumberInTxSymbolFormat + lb bc, 18, 7 + ld a, e + bank1call WriteTwoDigitNumberInTxSymbolFormat + pop hl + pop de + dec e ; decrease number of cards in deck + dec d ; decrease number of prize cards left + jr nz, .place_prize + ret + +.DrawPrizeTile: + ld b, [hl] + inc hl + ld c, [hl] + inc hl + ld a, $ac ; prize card tile + jp WriteByteToBGMap0 + +.PrizeCardCoordinates: +; player x, player y, opp x, opp y + db 5, 6, 14, 5 ; Prize 1 + db 6, 6, 13, 5 ; Prize 2 + db 5, 7, 14, 4 ; Prize 3 + db 6, 7, 13, 4 ; Prize 4 + db 5, 8, 14, 3 ; Prize 5 + db 6, 8, 13, 3 ; Prize 6 + +SECTION "Bank 9@4a1f", ROMX[$4a1f], BANK[$9] + +; display the animation of the turn duelist drawing one card at the beginning of the turn +; if there isn't any card left in the deck, let the player know with a text message +DisplayDrawOneCardScreen: + ld a, 1 +; fallthrough + +; display the animation of the turn duelist drawing number of cards that is in a. +; if there isn't any card left in the deck, let the player know with a text message. +; input: +; - a = number of cards to draw +DisplayDrawNCardsScreen: + push hl + push de + push bc + ld [wNumCardsTryingToDraw], a + xor a + ld [wNumCardsBeingDrawn], a + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + get_turn_duelist_var + ld a, DECK_SIZE + sub [hl] + ld hl, wNumCardsTryingToDraw + cp [hl] + jr nc, .has_cards_left + ; trying to draw more cards than there are left in the deck + ld [hl], a ; 0 +.has_cards_left + ld a, [wDuelDisplayedScreen] + cp DRAW_CARDS + jr z, .portraits_drawn + cp SHUFFLE_DECK + jr z, .portraits_drawn + call EmptyScreen + call DrawDuelistPortraitsAndNames +.portraits_drawn + ld a, DRAW_CARDS + ld [wDuelDisplayedScreen], a + call PrintDeckAndHandIconsAndNumberOfCards + ld a, [wNumCardsTryingToDraw] + or a + jr nz, .can_draw + ; if wNumCardsTryingToDraw set to 0 before, it's because not enough cards in deck + ldtx hl, Text016f ; CannotDrawCardBecauseNoCardsInDeckText + call DrawWideTextBox_WaitForInput + jr .done +.can_draw + ld l, a + ld h, 0 + call LoadTxRam3 + ldtx hl, Text016e ; DrawCardsFromTheDeckText + call DrawWideTextBox_PrintText + call EnableLCD +.anim_drawing_cards_loop + call PlayTurnDuelistDrawAnimation + ld hl, wNumCardsBeingDrawn + inc [hl] + call PrintNumberOfHandAndDeckCards + ld a, [wNumCardsBeingDrawn] + ld hl, wNumCardsTryingToDraw + cp [hl] + jr c, .anim_drawing_cards_loop + + ld a, [wNumCardsTryingToDraw] + ld [wcd77], a + call AIDoAction_06 + call DrawOpponentPortrait + + ld c, 30 +.wait_loop + call DoFrame + bank1call CheckSkipDelayAllowed + jr c, .done + dec c + jr nz, .wait_loop +.done + pop bc + pop de + pop hl + ret + +; animates the screen for Turn Duelist drawing a card +PlayTurnDuelistDrawAnimation: + call ResetAnimationQueue + ld e, DUEL_ANIM_PLAYER_DRAW + ldh a, [hWhoseTurn] + cp PLAYER_TURN + jr z, .got_duelist + ld e, DUEL_ANIM_OPP_DRAW +.got_duelist + ld a, e + call PlayDuelAnimation + +.loop_anim + call DoFrame + bank1call CheckSkipDelayAllowed + jr c, .done_anim + call CheckAnyAnimationPlaying + jr c, .loop_anim + +.done_anim + call FinishQueuedAnimations + ret + +; prints, for each duelist, the number of cards in the hand along with the +; hand icon, and the number of cards in the deck, along with the deck icon, +; according to each element's placement in the draw card(s) screen. +PrintDeckAndHandIconsAndNumberOfCards: + call LoadDuelDrawCardsScreenTiles + ld hl, DeckAndHandIconsTileData + call WriteDataBlocksToBGMap0 + ld a, [wConsole] + cp CONSOLE_CGB ; useless cp + jr nz, .not_cgb +.not_cgb + call PrintPlayerNumberOfHandAndDeckCards + call PrintOpponentNumberOfHandAndDeckCards + ret + +; prints, for each duelist, the number of cards in the hand, and the number +; of cards in the deck, according to their placement in the draw card(s) screen. +; input: wNumCardsBeingDrawn = number of cards being drawn (in order to add +; them to the hand cards and subtract them from the deck cards). +PrintNumberOfHandAndDeckCards: + ldh a, [hWhoseTurn] + cp PLAYER_TURN + jr nz, PrintOpponentNumberOfHandAndDeckCards +; fallthrough + +PrintPlayerNumberOfHandAndDeckCards: + ld a, [wPlayerNumberOfCardsInHand] + ld hl, wNumCardsBeingDrawn + add [hl] + ld d, a + ld a, DECK_SIZE + ld hl, wPlayerNumberOfCardsNotInDeck + sub [hl] + ld hl, wNumCardsBeingDrawn + sub [hl] + ld e, a + ld a, d + lb bc, 16, 10 + bank1call WriteTwoDigitNumberInTxSymbolFormat + ld a, e + lb bc, 10, 10 + bank1call WriteTwoDigitNumberInTxSymbolFormat + ret + +PrintOpponentNumberOfHandAndDeckCards: + ld a, [wOpponentNumberOfCardsInHand] + ld hl, wNumCardsBeingDrawn + add [hl] + ld d, a + ld a, DECK_SIZE + ld hl, wOpponentNumberOfCardsNotInDeck + sub [hl] + ld hl, wNumCardsBeingDrawn + sub [hl] + ld e, a + ld a, d + lb bc, 5, 3 + bank1call WriteTwoDigitNumberInTxSymbolFormat + ld a, e + lb bc, 11, 3 + bank1call WriteTwoDigitNumberInTxSymbolFormat + ret + +DeckAndHandIconsTileData: +; x, y, tiles[], 0 + db 4, 3, SYM_CROSS, 0 ; x for opponent's hand + db 10, 3, SYM_CROSS, 0 ; x for opponent's deck + db 8, 2, $f4, $f5, 0 ; opponent's deck icon + db 8, 3, $f6, $f7, 0 ; opponent's deck icon + db 2, 2, $f8, $f9, 0 ; opponent's hand icon + db 2, 3, $fa, $fb, 0 ; opponent's hand icon + db 9, 10, SYM_CROSS, 0 ; x for player's deck + db 15, 10, SYM_CROSS, 0 ; x for player's hand + db 7, 9, $f4, $f5, 0 ; player's deck icon + db 7, 10, $f6, $f7, 0 ; player's deck icon + db 13, 9, $f8, $f9, 0 ; player's hand icon + db 13, 10, $fa, $fb, 0 ; player's hand icon + db $ff + +; unreferenced, copied over from TCG1 +DeckAndHandIconsCGBPalData: +; x, y, pals[], 0 + db 8, 2, $03, $03, 0 + db 8, 3, $03, $03, 0 + db 2, 2, $03, $03, 0 + db 2, 3, $03, $03, 0 + db 7, 9, $03, $03, 0 + db 7, 10, $03, $03, 0 + db 13, 9, $03, $03, 0 + db 13, 10, $03, $03, 0 + db $ff +; 0x24b83 + +SECTION "Bank 9@4e25", ROMX[$4e25], BANK[$9] + +; given the deck index of a turn holder's card in register a, +; and a pointer in hl to the wLoadedCard* buffer where the card data is loaded, +; check if the card is Clefairy Doll or Mysterious Fossil, and, if so, convert it +; to a Pokemon card in the wLoadedCard* buffer, using .trainer_to_pkmn_data_1. +ConvertSpecialTrainerCardToPokemon:: + ld c, a + ld a, [hl] + cp TYPE_TRAINER + ret nz ; return if the card is not TRAINER type + push hl + ldh a, [hWhoseTurn] + ld h, a + ld l, c + ld a, [hl] + and CARD_LOCATION_PLAY_AREA + pop hl + ret z ; return if the card is not in the arena or bench + ld a, e + cp LOW(MYSTERIOUS_FOSSIL) + jr nz, .check_for_clefairy_doll + ld a, d + cp HIGH(MYSTERIOUS_FOSSIL) + jr z, .OverwriteCardData + ret +.check_for_clefairy_doll + cp LOW(CLEFAIRY_DOLL) + ret nz + ld a, d + cp HIGH(CLEFAIRY_DOLL) + ret nz + bank1call CheckHypnoPuppetMaster + jr nc, .OverwriteCardData + call .OverwriteCardData + ld bc, $21 + add hl, bc + ld c, $13 + ld de, .trainer_to_pkmn_data_2 +.loop_copy_1 + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .loop_copy_1 + ret + +.OverwriteCardData + push hl + push de + ld [hl], TYPE_PKMN_COLORLESS + ld bc, $a ; CARD_DATA_HP + add hl, bc + ld de, .trainer_to_pkmn_data_1 + ld c, $38 ; CARD_DATA_UNKNOWN2 - CARD_DATA_HP +.loop_copy_2 + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .loop_copy_2 + pop de + pop hl + ret + +.trainer_to_pkmn_data_1 + db 10 ; CARD_DATA_HP + ds $07 ; CARD_DATA_ATTACK1_NAME - (CARD_DATA_HP + 1) + tx Text0031 ; DiscardName ; CARD_DATA_ATTACK1_NAME + tx Text0042 ; DiscardDescription ; CARD_DATA_ATTACK1_DESCRIPTION + ds $03 ; CARD_DATA_ATTACK1_CATEGORY - (CARD_DATA_ATTACK1_DESCRIPTION + 2) + db POKEMON_POWER ; CARD_DATA_ATTACK1_CATEGORY + dw $4896; TrainerCardAsPokemonEffectCommands ; CARD_DATA_ATTACK1_EFFECT_COMMANDS + ds $18 ; CARD_DATA_RETREAT_COST - (CARD_DATA_ATTACK1_EFFECT_COMMANDS + 2) + db UNABLE_RETREAT ; CARD_DATA_RETREAT_COST + ds $0d ; PKMN_CARD_DATA_LENGTH - (CARD_DATA_RETREAT_COST + 1) + +.trainer_to_pkmn_data_2 + db $00 + db $00 + db $00 + db $00 + tx Text01ce + tx Text01cf + db $00 + db $00 + db $1e + db $00 + db $ab + db $50 + db $00 + db $00 + db $00 + db $00 + db $00 +; 0x24ebf SECTION "Bank 9@4fe0", ROMX[$4fe0], BANK[$9] @@ -171,7 +1154,7 @@ DeckDiagnosis: farcall GetNumberOfDeckDiagnosisStepsUnlocked ld [wNumDeckDiagnosisSteps], a - bank1call Func_4278 + bank1call SetupDuel call DisableLCD call LoadDeckDiagnosisScene @@ -446,9 +1429,9 @@ LoadDeckDiagnosisScene: lb bc, 2, 6 ; fallthrough DrawDrMasonsPortrait: - ld a, $5f + ld a, NPC_DR_MASON ld e, PORTRAITVARIANT_NORMAL - call Func_3ab2 + call DrawNPCPortrait call FlushAllPalettes ret @@ -848,19 +1831,19 @@ CheckDeck: .skip_portrait_switch push de call DoFrame - ld a, $5f + ld a, NPC_DR_MASON lb bc, 7, 4 - call Func_3ab2 + call DrawNPCPortrait call FlushAllPalettes pop de dec d jr nz, .check_delay ; show happy portrait - ld a, $5f + ld a, NPC_DR_MASON ld e, PORTRAITVARIANT_HAPPY lb bc, 7, 4 - call Func_3ab2 + call DrawNPCPortrait call FlushAllPalettes call WaitForWideTextBoxInput @@ -1070,7 +2053,7 @@ CheckDeck: jr c, .loop_fill_list_sequence ld [hl], $ff - bank1call SortDuelTempListByCardID + bank1call SortCardsInDuelTempListByID ld hl, wDuelTempList .loop_filter_only_pkmn @@ -1699,7 +2682,7 @@ CreateCardPopCandidateList: ; a = deck ID LoadDeckIDData: - ld [wcc16], a + ld [wNPCDuelDeckID], a ld c, a ld hl, DeckIDData .loop_find @@ -1726,7 +2709,7 @@ LoadDeckIDData: ld a, [hli] ld [wOpponentName + 1], a ld a, [hli] - ld [wcc12], a + ld [wOpponentNPCID], a ld a, [hli] ld [wcc15], a ld a, [hli] @@ -1734,7 +2717,7 @@ LoadDeckIDData: ld a, [hli] ld [wcd0e], a ld a, [hli] - ld [wcc17], a + ld [wDuelTheme], a ld a, [hli] ld [wcd0f], a ld a, [hli] @@ -1743,1312 +2726,1312 @@ LoadDeckIDData: ret DeckIDData: - db PLAYER_PRACTICE_DECK_ID + db UNKNOWN_SAMS_PRACTICE_DECK_ID tx Text04d6 ; deck name tx Text04d5 ; opponent name - db $05 ; ? - db $02 ; ? - db NO_RULES ; special duel rules + db NPC_SAM ; NPC ID + db PRIZES_2 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $12 ; ? db $00 ; ? - db STARTER_DECK_ID + db PLAYER_PRACTICE_DECK_ID tx Text0448 ; deck name tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? + + db STARTER_DECK_ID + tx Text044d ; deck name + tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? db $00 ; ? db SWEAT_ANTI_GR1_DECK_ID - tx Text044d ; deck name + tx Text0466 ; deck name tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? db $00 ; ? db GIVE_IN_ANTI_GR2_DECK_ID - tx Text0466 ; deck name + tx Text0449 ; deck name tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? db $00 ; ? db VENGEFUL_ANTI_GR3_DECK_ID - tx Text0449 ; deck name + tx Text0470 ; deck name tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? db $00 ; ? db UNFORGIVING_ANTI_GR4_DECK_ID - tx Text0470 ; deck name + tx Text04f1 ; deck name tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? db $00 ; ? db SAMS_PRACTICE_DECK_ID - tx Text04f1 ; deck name - tx Text04f6 ; opponent name - db $00 ; ? - db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $00 ; ? + tx Text04d6 ; deck name + tx Text04d5 ; opponent name + db NPC_SAM ; NPC ID + db PRIZES_2 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $12 ; ? db $00 ; ? db AARON_PRACTICE_DECK1_ID - tx Text04d6 ; deck name - tx Text04d5 ; opponent name - db $05 ; ? - db $02 ; ? - db NO_RULES ; special duel rules + tx Text04af ; deck name + tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? - db $02 ; ? - db $12 ; ? db $00 ; ? db AARONS_STEP1_DECK_ID - tx Text04af ; deck name - tx Text04f6 ; opponent name - db $00 ; ? - db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $00 ; ? + tx Text0433 ; deck name + tx Text0432 ; opponent name + db NPC_AARON ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $12 ; ? db $00 ; ? db AARON_PRACTICE_DECK2_ID - tx Text0433 ; deck name - tx Text0432 ; opponent name - db $06 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text04b0 ; deck name + tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? - db $02 ; ? - db $12 ; ? db $00 ; ? db AARONS_STEP2_DECK_ID - tx Text04b0 ; deck name - tx Text04f6 ; opponent name - db $00 ; ? - db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $00 ; ? - db $00 ; ? - db $00 ; ? - - db AARON_PRACTICE_DECK3_ID tx Text0434 ; deck name tx Text0432 ; opponent name - db $06 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_AARON ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $12 ; ? db $00 ; ? - db AARONS_STEP3_DECK_ID + db AARON_PRACTICE_DECK3_ID tx Text04b1 ; deck name tx Text04f6 ; opponent name + db NPC_MARK ; NPC ID + db 0 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $00 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $00 ; ? + db MUSIC_STOP ; duel theme db $00 ; ? db $00 ; ? - db BRICK_WALK_DECK_ID + db AARONS_STEP3_DECK_ID tx Text0435 ; deck name tx Text0432 ; opponent name - db $06 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_AARON ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $12 ; ? + db $00 ; ? + + db BRICK_WALK_DECK_ID + tx Text043e ; deck name + tx Text0432 ; opponent name + db NPC_AARON ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $12 ; ? db $00 ; ? db BENCH_TRAP_DECK_ID - tx Text043e ; deck name + tx Text044b ; deck name tx Text0432 ; opponent name - db $06 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_AARON ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $12 ; ? db $00 ; ? db SKY_SPARK_DECK_ID - tx Text044b ; deck name - tx Text0432 ; opponent name - db $06 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $12 ; ? - db $00 ; ? - - db ELECTRIC_SELFDESTRUCT_DECK_ID tx Text049d ; deck name tx Text04a3 ; opponent name - db $0a ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_ISAAC ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_DUELTHEME_2 ; duel theme + db $09 ; ? + db $05 ; ? + + db ELECTRIC_SELFDESTRUCT_DECK_ID + tx Text04c1 ; deck name + tx Text04a3 ; opponent name + db NPC_ISAAC ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $09 ; ? db $05 ; ? db OVERFLOW_DECK_ID - tx Text04c1 ; deck name - tx Text04a3 ; opponent name - db $0a ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $03 ; ? - db $09 ; ? - db $05 ; ? - - db TRIPLE_ZAPDOS_DECK_ID tx Text0481 ; deck name tx Text04a0 ; opponent name - db $0c ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_NICHOLAS ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $01 ; ? db $00 ; ? - db I_LOVE_PIKACHU_DECK_ID + db TRIPLE_ZAPDOS_DECK_ID tx Text04ad ; deck name tx Text04a0 ; opponent name - db $0c ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_NICHOLAS ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $01 ; ? db $05 ; ? - db TEN_THOUSAND_VOLTS_DECK_ID + db I_LOVE_PIKACHU_DECK_ID tx Text04c4 ; deck name tx Text04e4 ; opponent name - db $0b ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_JENNIFER ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $01 ; ? + db $00 ; ? + + db TEN_THOUSAND_VOLTS_DECK_ID + tx Text0426 ; deck name + tx Text04aa ; opponent name + db NPC_BRANDON ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $01 ; ? db $00 ; ? db HAND_OVER_GR_DECK_ID - tx Text0426 ; deck name - tx Text04aa ; opponent name - db $0d ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $01 ; ? - db $00 ; ? - - db PSYCHIC_ELITE_DECK_ID tx Text0471 ; deck name tx Text04d4 ; opponent name - db $0e ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_MURRAY ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_DUELTHEME_2 ; duel theme + db $0a ; ? + db $06 ; ? + + db PSYCHIC_ELITE_DECK_ID + tx Text0453 ; deck name + tx Text04d4 ; opponent name + db NPC_MURRAY ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $0a ; ? db $06 ; ? db PSYCHOKINESIS_DECK_ID - tx Text0453 ; deck name - tx Text04d4 ; opponent name - db $0e ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $03 ; ? - db $0a ; ? - db $06 ; ? - - db PHANTOM_DECK_ID tx Text0496 ; deck name tx Text04ec ; opponent name - db $0f ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_STEPHANIE ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $02 ; ? + db $00 ; ? + + db PHANTOM_DECK_ID + tx Text046e ; deck name + tx Text04bd ; opponent name + db NPC_ROBERT ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $02 ; ? db $00 ; ? db PUPPET_MASTER_DECK_ID - tx Text046e ; deck name - tx Text04bd ; opponent name - db $11 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text045f ; deck name + tx Text0491 ; opponent name + db NPC_DANIEL ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $02 ; ? db $00 ; ? db EVEN3_YEARS_ON_A_ROCK_DECK_ID - tx Text045f ; deck name - tx Text0491 ; opponent name - db $10 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $02 ; ? - db $00 ; ? - - db ROLLING_STONE_DECK_ID tx Text0438 ; deck name tx Text0493 ; opponent name - db $12 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_GENE ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $0b ; ? db $07 ; ? - db GREAT_EARTHQUAKE_DECK_ID + db ROLLING_STONE_DECK_ID tx Text04f3 ; deck name tx Text04de ; opponent name - db $13 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_MATTHEW ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $03 ; ? + db $00 ; ? + + db GREAT_EARTHQUAKE_DECK_ID + tx Text044f ; deck name + tx Text04b8 ; opponent name + db NPC_RYAN ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $03 ; ? db $00 ; ? db AWESOME_FOSSIL_DECK_ID - tx Text044f ; deck name - tx Text04b8 ; opponent name - db $14 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text0498 ; deck name + tx Text049c ; opponent name + db NPC_ANDREW ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $03 ; ? db $00 ; ? db RAGING_BILLOW_OF_FISTS_DECK_ID - tx Text0498 ; deck name - tx Text049c ; opponent name - db $15 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $03 ; ? - db $00 ; ? - - db YOU_CAN_DO_IT_MACHOP_DECK_ID tx Text04b2 ; deck name tx Text04e0 ; opponent name - db $16 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_MITCH ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $0c ; ? db $0c ; ? - db NEW_MACHOKE_DECK_ID + db YOU_CAN_DO_IT_MACHOP_DECK_ID tx Text0440 ; deck name tx Text04ce ; opponent name - db $17 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_MICHAEL ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $04 ; ? + db $00 ; ? + + db NEW_MACHOKE_DECK_ID + tx Text04b7 ; deck name + tx Text04ce ; opponent name + db NPC_MICHAEL ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $04 ; ? db $00 ; ? db SKILLED_WARRIOR_DECK_ID - tx Text04b7 ; deck name - tx Text04ce ; opponent name - db $17 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text046a ; deck name + tx Text04a5 ; opponent name + db NPC_CHRIS ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $04 ; ? db $00 ; ? db I_LOVE_TO_FIGHT_DECK_ID - tx Text046a ; deck name - tx Text04a5 ; opponent name - db $18 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text04bb ; deck name + tx Text04b5 ; opponent name + db NPC_JESSICA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $04 ; ? db $00 ; ? db MAX_ENERGY_DECK_ID - tx Text04bb ; deck name - tx Text04b5 ; opponent name - db $19 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $04 ; ? - db $00 ; ? - - db REMAINING_GREEN_DECK_ID tx Text042c ; deck name tx Text0489 ; opponent name - db $1a ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_NIKKI ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $0d ; ? db $02 ; ? - db POISON_CURSE_DECK_ID + db REMAINING_GREEN_DECK_ID tx Text0461 ; deck name tx Text0475 ; opponent name - db $1b ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_BRITTANY ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $05 ; ? db $00 ; ? - db GLITTERING_SCALES_DECK_ID + db POISON_CURSE_DECK_ID tx Text045d ; deck name tx Text0475 ; opponent name - db $1b ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_BRITTANY ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $05 ; ? db $02 ; ? - db STEADY_INCREASE_DECK_ID + db GLITTERING_SCALES_DECK_ID tx Text043c ; deck name tx Text04b9 ; opponent name - db $1c ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_KRISTIN ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $05 ; ? + db $00 ; ? + + db STEADY_INCREASE_DECK_ID + tx Text04b3 ; deck name + tx Text04d7 ; opponent name + db NPC_HEATHER ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $05 ; ? db $00 ; ? db DARK_SCIENCE_DECK_ID - tx Text04b3 ; deck name - tx Text04d7 ; opponent name - db $1d ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $05 ; ? - db $00 ; ? - - db NATURAL_SCIENCE_DECK_ID tx Text04a6 ; deck name tx Text048a ; opponent name - db $1e ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_RICK ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $0e ; ? db $08 ; ? - db POISONOUS_SWAMP_DECK_ID + db NATURAL_SCIENCE_DECK_ID tx Text044a ; deck name tx Text04df ; opponent name - db $20 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_DAVID ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $06 ; ? + db $00 ; ? + + db POISONOUS_SWAMP_DECK_ID + tx Text045b ; deck name + tx Text04a1 ; opponent name + db NPC_JOSEPH ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $06 ; ? db $00 ; ? db GATHERING_NIDORAN_DECK_ID - tx Text045b ; deck name - tx Text04a1 ; opponent name - db $1f ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text042f ; deck name + tx Text04cc ; opponent name + db NPC_ERIK ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $06 ; ? db $00 ; ? db RAIN_DANCE_CONFUSION_DECK_ID - tx Text042f ; deck name - tx Text04cc ; opponent name - db $21 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $06 ; ? - db $00 ; ? - - db CONSERVING_WATER_DECK_ID tx Text0431 ; deck name tx Text047d ; opponent name - db $22 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_AMY ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $0f ; ? db $04 ; ? - db ENERGY_REMOVAL_DECK_ID + db CONSERVING_WATER_DECK_ID tx Text0460 ; deck name tx Text049a ; opponent name - db $23 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_JOSHUA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $07 ; ? db $00 ; ? - db SPLASHING_ABOUT_DECK_ID + db ENERGY_REMOVAL_DECK_ID tx Text0480 ; deck name tx Text049a ; opponent name - db $23 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_JOSHUA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $07 ; ? db $04 ; ? - db BEACH_DECK_ID + db SPLASHING_ABOUT_DECK_ID tx Text0467 ; deck name tx Text04d3 ; opponent name - db $24 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_SARA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $07 ; ? + db $00 ; ? + + db BEACH_DECK_ID + tx Text045e ; deck name + tx Text04dc ; opponent name + db NPC_AMANDA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $07 ; ? db $00 ; ? db GO_ARCANINE_DECK_ID - tx Text045e ; deck name - tx Text04dc ; opponent name - db $25 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $07 ; ? - db $00 ; ? - - db FLAME_FESTIVAL_DECK_ID tx Text046f ; deck name tx Text0474 ; opponent name - db $26 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_KEN ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $10 ; ? db $03 ; ? - db IMMORTAL_FLAME_DECK_ID + db FLAME_FESTIVAL_DECK_ID tx Text0465 ; deck name tx Text04a2 ; opponent name - db $27 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_JOHN ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $08 ; ? + db $00 ; ? + + db IMMORTAL_FLAME_DECK_ID + tx Text0463 ; deck name + tx Text04cd ; opponent name + db NPC_JONATHAN ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $08 ; ? db $00 ; ? db ELECTRIC_CURRENT_SHOCK_DECK_ID - tx Text0463 ; deck name - tx Text04cd ; opponent name - db $29 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text0459 ; deck name + tx Text04f5 ; opponent name + db NPC_ADAM ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $08 ; ? db $00 ; ? db GREAT_ROCKET4_DECK_ID - tx Text0459 ; deck name - tx Text04f5 ; opponent name - db $28 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $02 ; ? - db $08 ; ? - db $00 ; ? - - db GREAT_ROCKET1_DECK_ID tx Text0490 ; deck name tx Text042a ; opponent name - db $3e ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_GR_4 ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme + db $16 ; ? + db $01 ; ? + + db GREAT_ROCKET1_DECK_ID + tx Text048d ; deck name + tx Text0427 ; opponent name + db NPC_GR_1 ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $16 ; ? db $01 ; ? db GREAT_ROCKET2_DECK_ID - tx Text048d ; deck name - tx Text0427 ; opponent name - db $3b ; ? - db $06 ; ? - db NO_RULES ; special duel rules + tx Text048e ; deck name + tx Text0428 ; opponent name + db NPC_GR_2 ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $16 ; ? db $01 ; ? db GREAT_ROCKET3_DECK_ID - tx Text048e ; deck name - tx Text0428 ; opponent name - db $3c ; ? - db $06 ; ? - db NO_RULES ; special duel rules + tx Text048f ; deck name + tx Text0429 ; opponent name + db NPC_GR_3 ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $16 ; ? db $01 ; ? db GRAND_FIRE_DECK_ID - tx Text048f ; deck name - tx Text0429 ; opponent name - db $3d ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $1f ; ? - db $16 ; ? - db $01 ; ? - - db LEGENDARY_FOSSIL_DECK_ID tx Text048b ; deck name tx Text04be ; opponent name - db $2a ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_COURTNEY ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $04 ; ? + db MUSIC_DUELTHEME_3 ; duel theme db $11 ; ? db $03 ; ? - db WATER_LEGEND_DECK_ID + db LEGENDARY_FOSSIL_DECK_ID tx Text0458 ; deck name tx Text049e ; opponent name - db $2b ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_STEVE ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $04 ; ? + db MUSIC_DUELTHEME_3 ; duel theme db $11 ; ? db $05 ; ? - db GREAT_DRAGON_DECK_ID + db WATER_LEGEND_DECK_ID tx Text047c ; deck name tx Text0482 ; opponent name - db $2c ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_JACK ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $04 ; ? + db MUSIC_DUELTHEME_3 ; duel theme db $11 ; ? db $04 ; ? - db BUG_COLLECTING_DECK_ID + db GREAT_DRAGON_DECK_ID tx Text0450 ; deck name tx Text04ed ; opponent name - db $2d ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_ROD ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $04 ; ? + db MUSIC_DUELTHEME_3 ; duel theme db $11 ; ? db $00 ; ? - db DEMONIC_FOREST_DECK_ID + db BUG_COLLECTING_DECK_ID tx Text0447 ; deck name tx Text04d8 ; opponent name - db $3f ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_MIDORI ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme + db $17 ; ? + db $01 ; ? + + db DEMONIC_FOREST_DECK_ID + tx Text042e ; deck name + tx Text04e3 ; opponent name + db NPC_YUUTA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $17 ; ? db $01 ; ? db STICKY_POISON_GAS_DECK_ID - tx Text042e ; deck name - tx Text04e3 ; opponent name - db $40 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $1f ; ? + tx Text045c ; deck name + tx Text04da ; opponent name + db NPC_MIYUKI ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $01 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $17 ; ? db $01 ; ? db MAD_PETALS_DECK_ID - tx Text045c ; deck name - tx Text04da ; opponent name - db $41 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $01 ; ? - db $1f ; ? - db $17 ; ? - db $01 ; ? - - db DANGEROUS_BENCH_DECK_ID tx Text0445 ; deck name tx Text04dd ; opponent name - db $42 ; ? - db $06 ; ? + db NPC_MORINO ; NPC ID + db PRIZES_6 ; number of prize cards db $01 ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $1d ; ? db $08 ; ? - db CHAIN_LIGHTNING_BY_PIKACHU_DECK_ID + db DANGEROUS_BENCH_DECK_ID tx Text0441 ; deck name tx Text04a4 ; opponent name - db $46 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_TAP ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme db $26 ; ? db $00 ; ? - db THIS_IS_THE_POWER_OF_ELECTRICITY_DECK_ID + db CHAIN_LIGHTNING_BY_PIKACHU_DECK_ID tx Text04c5 ; deck name tx Text04f2 ; opponent name - db $43 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_RENNA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $07 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme + db $18 ; ? + db $01 ; ? + + db THIS_IS_THE_POWER_OF_ELECTRICITY_DECK_ID + tx Text0456 ; deck name + tx Text0479 ; opponent name + db NPC_ICHIKAWA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $02 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $18 ; ? db $01 ; ? db QUICK_ATTACK_DECK_ID - tx Text0456 ; deck name - tx Text0479 ; opponent name - db $44 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $02 ; ? - db $1f ; ? - db $18 ; ? - db $01 ; ? - - db COMPLETE_COMBUSTION_DECK_ID tx Text0457 ; deck name tx Text0487 ; opponent name - db $45 ; ? - db $06 ; ? + db NPC_CATHERINE ; NPC ID + db PRIZES_6 ; number of prize cards db $02 ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $1e ; ? db $09 ; ? - db FIREBALL_DECK_ID + db COMPLETE_COMBUSTION_DECK_ID tx Text043f ; deck name tx Text049b ; opponent name - db $47 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_JES ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme + db $19 ; ? + db $01 ; ? + + db FIREBALL_DECK_ID + tx Text04c6 ; deck name + tx Text04e2 ; opponent name + db NPC_YUKI ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $03 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $19 ; ? db $01 ; ? db EEVEE_SHOWDOWN_DECK_ID - tx Text04c6 ; deck name - tx Text04e2 ; opponent name - db $48 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $03 ; ? - db $1f ; ? + tx Text0477 ; deck name + tx Text0499 ; opponent name + db NPC_SHOKO ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $08 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $19 ; ? db $01 ; ? db GAZE_UPON_THE_POWER_OF_FIRE_DECK_ID - tx Text0477 ; deck name - tx Text0499 ; opponent name - db $49 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $08 ; ? - db $1f ; ? - db $19 ; ? - db $01 ; ? - - db WHIRLPOOL_SHOWER_DECK_ID tx Text0468 ; deck name tx Text04bc ; opponent name - db $4a ; ? - db $06 ; ? + db NPC_HIDERO ; NPC ID + db PRIZES_6 ; number of prize cards db $03 ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $1f ; ? db $0a ; ? - db PARALYZED_PARALYZED_DECK_ID + db WHIRLPOOL_SHOWER_DECK_ID tx Text0439 ; deck name tx Text04d9 ; opponent name - db $4b ; ? + db NPC_MIYAJIMA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $04 ; ? - db NO_RULES ; special duel rules - db $04 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme + db $1a ; ? + db $01 ; ? + + db PARALYZED_PARALYZED_DECK_ID + tx Text04d1 ; deck name + tx Text049f ; opponent name + db NPC_SENTA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $09 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $1a ; ? db $01 ; ? db BENCH_CALL_DECK_ID - tx Text04d1 ; deck name - tx Text049f ; opponent name - db $4c ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $09 ; ? - db $1f ; ? + tx Text04c7 ; deck name + tx Text0473 ; opponent name + db NPC_AIRA ; NPC ID + db PRIZES_4 ; number of prize cards + db $04 ; special duel rules + db $00 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $1a ; ? db $01 ; ? db WATER_STREAM_DECK_ID - tx Text04c7 ; deck name - tx Text0473 ; opponent name - db $4d ; ? - db $04 ; ? - db $04 ; special duel rules - db $00 ; ? - db $1f ; ? - db $1a ; ? - db $01 ; ? - - db ROCK_BLAST_DECK_ID tx Text047b ; deck name tx Text0483 ; opponent name - db $4e ; ? - db $06 ; ? + db NPC_KANOKO ; NPC ID + db PRIZES_6 ; number of prize cards db $05 ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $20 ; ? db $0b ; ? - db FULL_STRENGTH_DECK_ID + db ROCK_BLAST_DECK_ID tx Text04f4 ; deck name tx Text0494 ; opponent name - db $4f ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_GODA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $0c ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme + db $1b ; ? + db $01 ; ? + + db FULL_STRENGTH_DECK_ID + tx Text0451 ; deck name + tx Text048c ; opponent name + db NPC_GRACE ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $05 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $1b ; ? db $01 ; ? db RUNNING_WILD_DECK_ID - tx Text0451 ; deck name - tx Text048c ; opponent name - db $50 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $05 ; ? - db $1f ; ? - db $1b ; ? - db $01 ; ? - - db DIRECT_HIT_DECK_ID tx Text0430 ; deck name tx Text0485 ; opponent name - db $51 ; ? - db $06 ; ? + db NPC_KAMIYA ; NPC ID + db PRIZES_6 ; number of prize cards db $06 ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $21 ; ? db $0c ; ? - db SUPERDESTRUCTIVE_POWER_DECK_ID + db DIRECT_HIT_DECK_ID tx Text0454 ; deck name tx Text04db ; opponent name - db $52 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_MIWA ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $06 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme + db $1c ; ? + db $01 ; ? + + db SUPERDESTRUCTIVE_POWER_DECK_ID + tx Text0452 ; deck name + tx Text0492 ; opponent name + db NPC_KEVIN ; NPC ID + db PRIZES_4 ; number of prize cards + db $07 ; special duel rules + db $00 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $1c ; ? db $01 ; ? db BAD_DREAM_DECK_ID - tx Text0452 ; deck name - tx Text0492 ; opponent name - db $53 ; ? - db $04 ; ? - db $07 ; special duel rules - db $00 ; ? - db $1f ; ? + tx Text04ba ; deck name + tx Text04e5 ; opponent name + db NPC_YOSUKE ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $0a ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $1c ; ? db $01 ; ? db POKEMON_POWER_DECK_ID - tx Text04ba ; deck name - tx Text04e5 ; opponent name - db $54 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $0a ; ? - db $1f ; ? + tx Text04cb ; deck name + tx Text04ee ; opponent name + db NPC_RYOKO ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $0d ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $1c ; ? db $01 ; ? db SPIRITED_AWAY_DECK_ID - tx Text04cb ; deck name - tx Text04ee ; opponent name - db $55 ; ? - db $04 ; ? - db NO_RULES ; special duel rules - db $0d ; ? - db $1f ; ? - db $1c ; ? - db $01 ; ? - - db SNORLAX_GUARD_DECK_ID tx Text043d ; deck name tx Text04d2 ; opponent name - db $56 ; ? - db $06 ; ? + db NPC_MAMI ; NPC ID + db PRIZES_6 ; number of prize cards db $08 ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $22 ; ? db $0d ; ? - db EYE_OF_THE_STORM_DECK_ID + db SNORLAX_GUARD_DECK_ID tx Text0484 ; deck name tx Text04b6 ; opponent name - db $57 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_NISHIJIMA ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $0e ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme + db $23 ; ? + db $0e ; ? + + db EYE_OF_THE_STORM_DECK_ID + tx Text044c ; deck name + tx Text0478 ; opponent name + db NPC_ISHII ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $0f ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $23 ; ? db $0e ; ? db SUDDEN_GROWTH_DECK_ID - tx Text044c ; deck name - tx Text0478 ; opponent name - db $58 ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $0f ; ? - db $20 ; ? + tx Text0443 ; deck name + tx Text0497 ; opponent name + db NPC_SAMEJIMA ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $10 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $23 ; ? db $0e ; ? db VERY_RARE_CARD_DECK_ID - tx Text0443 ; deck name - tx Text0497 ; opponent name - db $59 ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $10 ; ? - db $20 ; ? - db $23 ; ? - db $0e ; ? - - db BAD_GUYS_DECK_ID tx Text045a ; deck name tx Text042d ; opponent name - db $07 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_ISHIHARA ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $23 ; ? + db MUSIC_ISHIHARA ; duel theme db $14 ; ? db $13 ; ? - db POISON_MIST_DECK_ID + db BAD_GUYS_DECK_ID tx Text0472 ; deck name tx Text0486 ; opponent name - db $5a ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_KANZAKI ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $0b ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $24 ; ? db $11 ; ? - db ULTRA_REMOVAL_DECK_ID + db POISON_MIST_DECK_ID tx Text04ca ; deck name tx Text04f0 ; opponent name - db $5b ; ? - db $06 ; ? + db NPC_RUI ; NPC ID + db PRIZES_6 ; number of prize cards db $09 ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $24 ; ? db $12 ; ? - db PSYCHIC_BATTLE_DECK_ID + db ULTRA_REMOVAL_DECK_ID tx Text047e ; deck name tx Text04f0 ; opponent name - db $5b ; ? - db $06 ; ? + db NPC_RUI ; NPC ID + db PRIZES_6 ; number of prize cards db $0a ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $24 ; ? db $13 ; ? - db STOP_LIFE_DECK_ID + db PSYCHIC_BATTLE_DECK_ID tx Text0495 ; deck name tx Text04f0 ; opponent name - db $5b ; ? - db $06 ; ? + db NPC_RUI ; NPC ID + db PRIZES_6 ; number of prize cards db $07 ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $24 ; ? db $15 ; ? - db SCORCHER_DECK_ID + db STOP_LIFE_DECK_ID tx Text0437 ; deck name tx Text04c2 ; opponent name - db $5c ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_BIRURITCHI ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $21 ; ? + db MUSIC_GRDUELTHEME_3 ; duel theme + db $25 ; ? + db $0f ; ? + + db SCORCHER_DECK_ID + tx Text046d ; deck name + tx Text04c2 ; opponent name + db NPC_BIRURITCHI ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_GRDUELTHEME_3 ; duel theme db $25 ; ? db $0f ; ? db TSUNAMI_STARTER_DECK_ID - tx Text046d ; deck name + tx Text044e ; deck name tx Text04c2 ; opponent name - db $5c ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_BIRURITCHI ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $21 ; ? + db MUSIC_GRDUELTHEME_3 ; duel theme db $25 ; ? db $0f ; ? db SMASH_TO_MINCEMEAT_DECK_ID - tx Text044e ; deck name + tx Text0455 ; deck name tx Text04c2 ; opponent name - db $5c ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_BIRURITCHI ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $21 ; ? + db MUSIC_GRDUELTHEME_3 ; duel theme db $25 ; ? db $0f ; ? db TEST_YOUR_LUCK_DECK_ID - tx Text0455 ; deck name - tx Text04c2 ; opponent name - db $5c ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $21 ; ? - db $25 ; ? - db $0f ; ? - - db PROTOHISTORIC_DECK_ID tx Text043a ; deck name tx Text04c8 ; opponent name - db $36 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + db NPC_PAWN ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $02 ; ? + db MUSIC_DUELTHEME_1 ; duel theme + db $27 ; ? + db $13 ; ? + + db PROTOHISTORIC_DECK_ID + tx Text0446 ; deck name + tx Text04b4 ; opponent name + db NPC_KNIGHT ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_DUELTHEME_2 ; duel theme db $27 ; ? db $13 ; ? db TEXTURE_TUNER7_DECK_ID - tx Text0446 ; deck name - tx Text04b4 ; opponent name - db $37 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text04a8 ; deck name + tx Text04bf ; opponent name + db NPC_BISHOP ; NPC ID + db PRIZES_4 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $03 ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $27 ; ? db $13 ; ? db COLORLESS_ENERGY_DECK_ID - tx Text04a8 ; deck name - tx Text04bf ; opponent name - db $38 ; ? - db $04 ; ? - db NO_RULES ; special duel rules + tx Text046b ; deck name + tx Text04ef ; opponent name + db NPC_ROOK ; NPC ID + db PRIZES_5 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_1 ; duel theme db $27 ; ? db $13 ; ? db POWERFUL_POKEMON_DECK_ID - tx Text046b ; deck name - tx Text04ef ; opponent name - db $39 ; ? - db $05 ; ? - db NO_RULES ; special duel rules + tx Text0444 ; deck name + tx Text0488 ; opponent name + db NPC_QUEEN ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $1f ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $27 ; ? db $13 ; ? db WEIRD_DECK_ID - tx Text0444 ; deck name - tx Text0488 ; opponent name - db $3a ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $20 ; ? - db $27 ; ? - db $13 ; ? - - db STRANGE_DECK_ID tx Text0464 ; deck name tx Text047a ; opponent name - db $08 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_IMAKUNI_BLACK ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $10 ; ? + db MUSIC_IMAKUNI ; duel theme db $13 ; ? db $0b ; ? - db RONALDS_UNCOOL_DECK_ID + db STRANGE_DECK_ID tx Text0442 ; deck name tx Text047a ; opponent name - db $09 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_IMAKUNI_RED ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $24 ; ? + db MUSIC_IMAKUNI2 ; duel theme db $13 ; ? db $13 ; ? - db RONALDS_GRX_DECK_ID + db RONALDS_UNCOOL_DECK_ID tx Text04e8 ; deck name tx Text04e6 ; opponent name - db $04 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_RONALD ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $0f ; ? + db MUSIC_RONALD ; duel theme db $15 ; ? db $16 ; ? - db RONALDS_POWER_DECK_ID + db RONALDS_GRX_DECK_ID tx Text04e7 ; deck name tx Text042b ; opponent name - db $5d ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_GR_X ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $0f ; ? + db MUSIC_RONALD ; duel theme db $16 ; ? db $16 ; ? - db RONALDS_PSYCHIC_DECK_ID + db RONALDS_POWER_DECK_ID tx Text04eb ; deck name tx Text04e6 ; opponent name - db $04 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_RONALD ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $0f ; ? + db MUSIC_RONALD ; duel theme + db $15 ; ? + db $16 ; ? + + db RONALDS_PSYCHIC_DECK_ID + tx Text04ea ; deck name + tx Text04e6 ; opponent name + db NPC_RONALD ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_RONALD ; duel theme db $15 ; ? db $16 ; ? db RONALDS_ULTRA_DECK_ID - tx Text04ea ; deck name + tx Text04e9 ; deck name tx Text04e6 ; opponent name - db $04 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_RONALD ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $0f ; ? + db MUSIC_RONALD ; duel theme db $15 ; ? db $16 ; ? db EVERYBODYS_FRIEND_DECK_ID - tx Text04e9 ; deck name - tx Text04e6 ; opponent name - db $04 ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $0f ; ? - db $15 ; ? - db $16 ; ? - - db IMMORTAL_POKEMON_DECK_ID tx Text0469 ; deck name tx Text047f ; opponent name - db $2e ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_EIJI ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme + db $28 ; ? + db $17 ; ? + + db IMMORTAL_POKEMON_DECK_ID + tx Text0462 ; deck name + tx Text04cf ; opponent name + db NPC_MAGICIAN ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules + db $00 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $28 ; ? db $17 ; ? db TORRENTIAL_FLOOD_DECK_ID - tx Text0462 ; deck name - tx Text04cf ; opponent name - db $2f ; ? - db $06 ; ? - db NO_RULES ; special duel rules + tx Text043b ; deck name + tx Text04e1 ; opponent name + db NPC_YUI ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $28 ; ? db $17 ; ? db TRAINER_IMPRISON_DECK_ID - tx Text043b ; deck name - tx Text04e1 ; opponent name - db $30 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + tx Text04ae ; deck name + tx Text04ab ; opponent name + db NPC_TOSHIRON ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $28 ; ? db $17 ; ? db BLAZING_FLAME_DECK_ID - tx Text04ae ; deck name - tx Text04ab ; opponent name - db $31 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + tx Text046c ; deck name + tx Text04c3 ; opponent name + db NPC_PIERROT ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $28 ; ? db $17 ; ? db DAMAGE_CHAOS_DECK_ID - tx Text046c ; deck name - tx Text04c3 ; opponent name - db $32 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + tx Text04a7 ; deck name + tx Text0476 ; opponent name + db NPC_ANNA ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $28 ; ? db $17 ; ? db BIG_THUNDER_DECK_ID - tx Text04a7 ; deck name - tx Text0476 ; opponent name - db $33 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + tx Text04c0 ; deck name + tx Text04a9 ; opponent name + db NPC_DEE ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $28 ; ? db $17 ; ? db POWER_OF_DARKNESS_DECK_ID - tx Text04c0 ; deck name - tx Text04a9 ; opponent name - db $34 ; ? - db $06 ; ? - db NO_RULES ; special duel rules + tx Text0436 ; deck name + tx Text04d0 ; opponent name + db NPC_MASQUERADE ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $28 ; ? db $17 ; ? db POISON_STORM_DECK_ID - tx Text0436 ; deck name - tx Text04d0 ; opponent name - db $35 ; ? - db $06 ; ? - db NO_RULES ; special duel rules - db $00 ; ? - db $20 ; ? - db $28 ; ? - db $17 ; ? - - db DECK_7269_ID tx Text04c9 ; deck name tx Text04ac ; opponent name - db $5e ; ? - db $06 ; ? - db NO_RULES ; special duel rules + db NPC_TOBI_CHAN ; NPC ID + db PRIZES_6 ; number of prize cards + db NO_SPECIAL_RULE ; special duel rules db $00 ; ? - db $20 ; ? + db MUSIC_GRDUELTHEME_2 ; duel theme db $28 ; ? db $17 ; ? diff --git a/src/engine/bank11.asm b/src/engine/bank11.asm index b418b7e..a4b1f06 100644 --- a/src/engine/bank11.asm +++ b/src/engine/bank11.asm @@ -490,7 +490,12 @@ PlayAfterCurrentSong: ld [wdd04], a call PlaySong ret -; 0x44943 + +PlayCurrentSong: + ld a, [wCurMusic] + call PlaySong + ret +; 0x4494a SECTION "Bank 11@4954", ROMX[$4954], BANK[$11] diff --git a/src/engine/bank4b.asm b/src/engine/bank4b.asm index 2061c95..97e0a99 100644 --- a/src/engine/bank4b.asm +++ b/src/engine/bank4b.asm @@ -831,7 +831,7 @@ _LoadOWObject: ld [hli], a ; OWOBJSTRUCT_4 ld [hli], a ; OWOBJSTRUCT_5 ld [hli], a ; OWOBJSTRUCT_6 - ld [hl], a ; OWOBJSTRUCT_7 + ld [hl], a ; pop hl pop de pop bc diff --git a/src/engine/bank4c.asm b/src/engine/bank4c.asm index 0a6d9b2..78bd181 100644 --- a/src/engine/bank4c.asm +++ b/src/engine/bank4c.asm @@ -305,99 +305,99 @@ Data_13005b:: dw OWSPRITE_STRONGHOLD_PLATFORM ; OW_STRONGHOLD_PLATFORM Portraits: - dw TILESET_MARK_PORTRAIT, PALETTE_078, TILEMAP_0D3, TILEMAP_0D3, TILEMAP_0D3 ; PORTRAIT_00 - dw TILESET_MINT_PORTRAIT, PALETTE_079, TILEMAP_0D4, TILEMAP_0D4, TILEMAP_0D4 ; PORTRAIT_01 - dw TILESET_MARK_LINK_PORTRAIT, PALETTE_07A, TILEMAP_0D5, TILEMAP_0D5, TILEMAP_0D5 ; PORTRAIT_02 - dw TILESET_MINT_LINK_PORTRAIT, PALETTE_07B, TILEMAP_0D6, TILEMAP_0D6, TILEMAP_0D6 ; PORTRAIT_03 - dw TILESET_RONALD_PORTRAIT, PALETTE_07C, TILEMAP_0D7, TILEMAP_0D8, TILEMAP_0D9 ; PORTRAIT_04 - dw TILESET_SAM_PORTRAIT, PALETTE_07D, TILEMAP_0DA, TILEMAP_0DB, TILEMAP_0DC ; PORTRAIT_05 - dw TILESET_AARON_PORTRAIT, PALETTE_07E, TILEMAP_0DD, TILEMAP_0DE, TILEMAP_0DF ; PORTRAIT_06 - dw TILESET_ISHIHARA_PORTRAIT, PALETTE_07F, TILEMAP_0E0, TILEMAP_0E1, TILEMAP_0E2 ; PORTRAIT_07 - dw TILESET_ISAAC_PORTRAIT, PALETTE_082, TILEMAP_0E9, TILEMAP_0EA, TILEMAP_0EB ; PORTRAIT_08 - dw TILESET_JENNIFER_PORTRAIT, PALETTE_083, TILEMAP_0EC, TILEMAP_0ED, TILEMAP_0EE ; PORTRAIT_09 - dw TILESET_NICHOLAS_PORTRAIT, PALETTE_084, TILEMAP_0EF, TILEMAP_0F0, TILEMAP_0F1 ; PORTRAIT_0A - dw TILESET_BRANDON_PORTRAIT, PALETTE_085, TILEMAP_0F2, TILEMAP_0F3, TILEMAP_0F4 ; PORTRAIT_0B - dw TILESET_MURRAY_PORTRAIT, PALETTE_086, TILEMAP_0F5, TILEMAP_0F6, TILEMAP_0F7 ; PORTRAIT_0C - dw TILESET_STEPHANIE_PORTRAIT, PALETTE_087, TILEMAP_0F8, TILEMAP_0F9, TILEMAP_0FA ; PORTRAIT_0D - dw TILESET_DANIEL_PORTRAIT, PALETTE_088, TILEMAP_0FB, TILEMAP_0FC, TILEMAP_0FD ; PORTRAIT_0E - dw TILESET_ROBERT_PORTRAIT, PALETTE_089, TILEMAP_0FE, TILEMAP_0FF, TILEMAP_100 ; PORTRAIT_0F - dw TILESET_GENE_PORTRAIT, PALETTE_08A, TILEMAP_101, TILEMAP_102, TILEMAP_103 ; PORTRAIT_10 - dw TILESET_MATTHEW_PORTRAIT, PALETTE_08B, TILEMAP_104, TILEMAP_105, TILEMAP_106 ; PORTRAIT_11 - dw TILESET_RYAN_PORTRAIT, PALETTE_08C, TILEMAP_107, TILEMAP_108, TILEMAP_109 ; PORTRAIT_12 - dw TILESET_ANDREW_PORTRAIT, PALETTE_08D, TILEMAP_10A, TILEMAP_10B, TILEMAP_10C ; PORTRAIT_13 - dw TILESET_MITCH_PORTRAIT, PALETTE_08E, TILEMAP_10D, TILEMAP_10E, TILEMAP_10F ; PORTRAIT_14 - dw TILESET_MICHAEL_PORTRAIT, PALETTE_08F, TILEMAP_110, TILEMAP_111, TILEMAP_112 ; PORTRAIT_15 - dw TILESET_CHRIS_PORTRAIT, PALETTE_090, TILEMAP_113, TILEMAP_114, TILEMAP_115 ; PORTRAIT_16 - dw TILESET_JESSICA_PORTRAIT, PALETTE_091, TILEMAP_116, TILEMAP_117, TILEMAP_118 ; PORTRAIT_17 - dw TILESET_NIKKI_PORTRAIT, PALETTE_092, TILEMAP_119, TILEMAP_11A, TILEMAP_11B ; PORTRAIT_18 - dw TILESET_BRITTANY_PORTRAIT, PALETTE_093, TILEMAP_11C, TILEMAP_11D, TILEMAP_11E ; PORTRAIT_19 - dw TILESET_KRISTIN_PORTRAIT, PALETTE_094, TILEMAP_11F, TILEMAP_120, TILEMAP_121 ; PORTRAIT_1A - dw TILESET_HEATHER_PORTRAIT, PALETTE_095, TILEMAP_122, TILEMAP_123, TILEMAP_124 ; PORTRAIT_1B - dw TILESET_RICK_PORTRAIT, PALETTE_096, TILEMAP_125, TILEMAP_126, TILEMAP_127 ; PORTRAIT_1C - dw TILESET_JOSEPH_PORTRAIT, PALETTE_097, TILEMAP_128, TILEMAP_129, TILEMAP_12A ; PORTRAIT_1D - dw TILESET_DAVID_PORTRAIT, PALETTE_098, TILEMAP_12B, TILEMAP_12C, TILEMAP_12D ; PORTRAIT_1E - dw TILESET_ERIK_PORTRAIT, PALETTE_099, TILEMAP_12E, TILEMAP_12F, TILEMAP_130 ; PORTRAIT_1F - dw TILESET_AMY_PORTRAIT, PALETTE_09A, TILEMAP_131, TILEMAP_132, TILEMAP_133 ; PORTRAIT_20 - dw TILESET_JOSHUA_PORTRAIT, PALETTE_09B, TILEMAP_134, TILEMAP_135, TILEMAP_136 ; PORTRAIT_21 - dw TILESET_SARA_PORTRAIT, PALETTE_09C, TILEMAP_137, TILEMAP_138, TILEMAP_139 ; PORTRAIT_22 - dw TILESET_AMANDA_PORTRAIT, PALETTE_09D, TILEMAP_13A, TILEMAP_13B, TILEMAP_13C ; PORTRAIT_23 - dw TILESET_KEN_PORTRAIT, PALETTE_09E, TILEMAP_13D, TILEMAP_13E, TILEMAP_13F ; PORTRAIT_24 - dw TILESET_JOHN_PORTRAIT, PALETTE_09F, TILEMAP_140, TILEMAP_141, TILEMAP_142 ; PORTRAIT_25 - dw TILESET_ADAM_PORTRAIT, PALETTE_0A0, TILEMAP_143, TILEMAP_144, TILEMAP_145 ; PORTRAIT_26 - dw TILESET_JONATHAN_PORTRAIT, PALETTE_0A1, TILEMAP_146, TILEMAP_147, TILEMAP_148 ; PORTRAIT_27 - dw TILESET_COURTNEY_PORTRAIT, PALETTE_0A2, TILEMAP_149, TILEMAP_14A, TILEMAP_14B ; PORTRAIT_28 - dw TILESET_STEVE_PORTRAIT, PALETTE_0A3, TILEMAP_14C, TILEMAP_14D, TILEMAP_14E ; PORTRAIT_29 - dw TILESET_JACK_PORTRAIT, PALETTE_0A4, TILEMAP_14F, TILEMAP_150, TILEMAP_151 ; PORTRAIT_2A - dw TILESET_ROD_PORTRAIT, PALETTE_0A5, TILEMAP_152, TILEMAP_153, TILEMAP_154 ; PORTRAIT_2B - dw TILESET_EIJI_PORTRAIT, PALETTE_0A6, TILEMAP_155, TILEMAP_156, TILEMAP_157 ; PORTRAIT_2C - dw TILESET_MAGICIAN_PORTRAIT, PALETTE_0A7, TILEMAP_158, TILEMAP_159, TILEMAP_15A ; PORTRAIT_2D - dw TILESET_YUI_PORTRAIT, PALETTE_0A8, TILEMAP_15B, TILEMAP_15C, TILEMAP_15D ; PORTRAIT_2E - dw TILESET_TOSHIRON_PORTRAIT, PALETTE_0A9, TILEMAP_15E, TILEMAP_15F, TILEMAP_160 ; PORTRAIT_2F - dw TILESET_PIERROT_PORTRAIT, PALETTE_0AA, TILEMAP_161, TILEMAP_162, TILEMAP_163 ; PORTRAIT_30 - dw TILESET_ANNA_PORTRAIT, PALETTE_0AB, TILEMAP_164, TILEMAP_165, TILEMAP_166 ; PORTRAIT_31 - dw TILESET_DEE_PORTRAIT, PALETTE_0AC, TILEMAP_167, TILEMAP_168, TILEMAP_169 ; PORTRAIT_32 - dw TILESET_MASQUERADE_PORTRAIT, PALETTE_0AD, TILEMAP_16A, TILEMAP_16B, TILEMAP_16C ; PORTRAIT_33 - dw TILESET_PAWN_PORTRAIT, PALETTE_0AE, TILEMAP_16D, TILEMAP_16E, TILEMAP_16F ; PORTRAIT_34 - dw TILESET_KNIGHT_PORTRAIT, PALETTE_0AF, TILEMAP_170, TILEMAP_171, TILEMAP_172 ; PORTRAIT_35 - dw TILESET_BISHOP_PORTRAIT, PALETTE_0B0, TILEMAP_173, TILEMAP_174, TILEMAP_175 ; PORTRAIT_36 - dw TILESET_ROOK_PORTRAIT, PALETTE_0B1, TILEMAP_176, TILEMAP_177, TILEMAP_178 ; PORTRAIT_37 - dw TILESET_QUEEN_PORTRAIT, PALETTE_0B2, TILEMAP_179, TILEMAP_17A, TILEMAP_17B ; PORTRAIT_38 - dw TILESET_GR_1_PORTRAIT, PALETTE_0B3, TILEMAP_17C, TILEMAP_17D, TILEMAP_17E ; PORTRAIT_39 - dw TILESET_GR_2_PORTRAIT, PALETTE_0B4, TILEMAP_17F, TILEMAP_180, TILEMAP_181 ; PORTRAIT_3A - dw TILESET_GR_3_PORTRAIT, PALETTE_0B5, TILEMAP_182, TILEMAP_183, TILEMAP_184 ; PORTRAIT_3B - dw TILESET_GR_4_PORTRAIT, PALETTE_0B6, TILEMAP_185, TILEMAP_186, TILEMAP_187 ; PORTRAIT_3C - dw TILESET_MIDORI_PORTRAIT, PALETTE_0B7, TILEMAP_188, TILEMAP_189, TILEMAP_18A ; PORTRAIT_3D - dw TILESET_YUUTA_PORTRAIT, PALETTE_0B8, TILEMAP_18B, TILEMAP_18C, TILEMAP_18D ; PORTRAIT_3E - dw TILESET_MIYUKI_PORTRAIT, PALETTE_0B9, TILEMAP_18E, TILEMAP_18F, TILEMAP_190 ; PORTRAIT_3F - dw TILESET_MORINO_PORTRAIT, PALETTE_0BA, TILEMAP_191, TILEMAP_192, TILEMAP_193 ; PORTRAIT_40 - dw TILESET_RENNA_PORTRAIT, PALETTE_0BB, TILEMAP_194, TILEMAP_195, TILEMAP_196 ; PORTRAIT_41 - dw TILESET_ICHIKAWA_PORTRAIT, PALETTE_0BC, TILEMAP_197, TILEMAP_198, TILEMAP_199 ; PORTRAIT_42 - dw TILESET_CATHERINE_PORTRAIT, PALETTE_0BD, TILEMAP_19A, TILEMAP_19B, TILEMAP_19C ; PORTRAIT_43 - dw TILESET_TAP_PORTRAIT, PALETTE_0BE, TILEMAP_19D, TILEMAP_19E, TILEMAP_19F ; PORTRAIT_44 - dw TILESET_JES_PORTRAIT, PALETTE_0BF, TILEMAP_1A0, TILEMAP_1A1, TILEMAP_1A2 ; PORTRAIT_45 - dw TILESET_YUKI_PORTRAIT, PALETTE_0C0, TILEMAP_1A3, TILEMAP_1A4, TILEMAP_1A5 ; PORTRAIT_46 - dw TILESET_SHOKO_PORTRAIT, PALETTE_0C1, TILEMAP_1A6, TILEMAP_1A7, TILEMAP_1A8 ; PORTRAIT_47 - dw TILESET_HIDERO_PORTRAIT, PALETTE_0C2, TILEMAP_1A9, TILEMAP_1AA, TILEMAP_1AB ; PORTRAIT_48 - dw TILESET_MIYAJIMA_PORTRAIT, PALETTE_0C3, TILEMAP_1AC, TILEMAP_1AD, TILEMAP_1AE ; PORTRAIT_49 - dw TILESET_SENTA_PORTRAIT, PALETTE_0C4, TILEMAP_1AF, TILEMAP_1B0, TILEMAP_1B1 ; PORTRAIT_4A - dw TILESET_AIRA_PORTRAIT, PALETTE_0C5, TILEMAP_1B2, TILEMAP_1B3, TILEMAP_1B4 ; PORTRAIT_4B - dw TILESET_KANOKO_PORTRAIT, PALETTE_0C6, TILEMAP_1B5, TILEMAP_1B6, TILEMAP_1B7 ; PORTRAIT_4C - dw TILESET_GODA_PORTRAIT, PALETTE_0C7, TILEMAP_1B8, TILEMAP_1B9, TILEMAP_1BA ; PORTRAIT_4D - dw TILESET_GRACE_PORTRAIT, PALETTE_0C8, TILEMAP_1BB, TILEMAP_1BC, TILEMAP_1BD ; PORTRAIT_4E - dw TILESET_KAMIYA_PORTRAIT, PALETTE_0C9, TILEMAP_1BE, TILEMAP_1BF, TILEMAP_1C0 ; PORTRAIT_4F - dw TILESET_MIWA_PORTRAIT, PALETTE_0CA, TILEMAP_1C1, TILEMAP_1C2, TILEMAP_1C3 ; PORTRAIT_50 - dw TILESET_KEVIN_PORTRAIT, PALETTE_0CB, TILEMAP_1C4, TILEMAP_1C5, TILEMAP_1C6 ; PORTRAIT_51 - dw TILESET_YOSUKE_PORTRAIT, PALETTE_0CC, TILEMAP_1C7, TILEMAP_1C8, TILEMAP_1C9 ; PORTRAIT_52 - dw TILESET_RYOKO_PORTRAIT, PALETTE_0CD, TILEMAP_1CA, TILEMAP_1CB, TILEMAP_1CC ; PORTRAIT_53 - dw TILESET_MAMI_PORTRAIT, PALETTE_0CE, TILEMAP_1CD, TILEMAP_1CE, TILEMAP_1CF ; PORTRAIT_54 - dw TILESET_NISHIJIMA_PORTRAIT, PALETTE_0CF, TILEMAP_1D0, TILEMAP_1D1, TILEMAP_1D2 ; PORTRAIT_55 - dw TILESET_ISHII_PORTRAIT, PALETTE_0D0, TILEMAP_1D3, TILEMAP_1D4, TILEMAP_1D5 ; PORTRAIT_56 - dw TILESET_SAMEJIMA_PORTRAIT, PALETTE_0D1, TILEMAP_1D6, TILEMAP_1D7, TILEMAP_1D8 ; PORTRAIT_57 - dw TILESET_KANZAKI_PORTRAIT, PALETTE_0D2, TILEMAP_1D9, TILEMAP_1DA, TILEMAP_1DB ; PORTRAIT_58 - dw TILESET_RUI_PORTRAIT, PALETTE_0D3, TILEMAP_1DC, TILEMAP_1DD, TILEMAP_1DE ; PORTRAIT_59 - dw TILESET_BIRURITCHI_PORTRAIT, PALETTE_0D4, TILEMAP_1DF, TILEMAP_1E0, TILEMAP_1E1 ; PORTRAIT_5A - dw TILESET_GR_X_PORTRAIT, PALETTE_0D5, TILEMAP_1E2, TILEMAP_1E3, TILEMAP_1E4 ; PORTRAIT_5B - dw TILESET_TOBI_CHAN_PORTRAIT, PALETTE_0D6, TILEMAP_1E5, TILEMAP_1E6, TILEMAP_1E7 ; PORTRAIT_5C - dw TILESET_DR_MASON_PORTRAIT, PALETTE_0D7, TILEMAP_1E8, TILEMAP_1E9, TILEMAP_1EA ; PORTRAIT_5D - dw TILESET_IMAKUNI_BLACK_PORTRAIT, PALETTE_080, TILEMAP_0E3, TILEMAP_0E4, TILEMAP_0E5 ; PORTRAIT_5E - dw TILESET_IMAKUNI_RED_PORTRAIT, PALETTE_081, TILEMAP_0E6, TILEMAP_0E7, TILEMAP_0E8 ; PORTRAIT_5F + dw TILESET_MARK_PORTRAIT, PALETTE_078, TILEMAP_0D3, TILEMAP_0D3, TILEMAP_0D3 ; PORTRAIT_MARK + dw TILESET_MINT_PORTRAIT, PALETTE_079, TILEMAP_0D4, TILEMAP_0D4, TILEMAP_0D4 ; PORTRAIT_MINT + dw TILESET_MARK_LINK_PORTRAIT, PALETTE_07A, TILEMAP_0D5, TILEMAP_0D5, TILEMAP_0D5 ; PORTRAIT_MARK_LINK + dw TILESET_MINT_LINK_PORTRAIT, PALETTE_07B, TILEMAP_0D6, TILEMAP_0D6, TILEMAP_0D6 ; PORTRAIT_MINT_LINK + dw TILESET_RONALD_PORTRAIT, PALETTE_07C, TILEMAP_0D7, TILEMAP_0D8, TILEMAP_0D9 ; PORTRAIT_RONALD + dw TILESET_SAM_PORTRAIT, PALETTE_07D, TILEMAP_0DA, TILEMAP_0DB, TILEMAP_0DC ; PORTRAIT_SAM + dw TILESET_AARON_PORTRAIT, PALETTE_07E, TILEMAP_0DD, TILEMAP_0DE, TILEMAP_0DF ; PORTRAIT_AARON + dw TILESET_ISHIHARA_PORTRAIT, PALETTE_07F, TILEMAP_0E0, TILEMAP_0E1, TILEMAP_0E2 ; PORTRAIT_ISHIHARA + dw TILESET_ISAAC_PORTRAIT, PALETTE_082, TILEMAP_0E9, TILEMAP_0EA, TILEMAP_0EB ; PORTRAIT_ISAAC + dw TILESET_JENNIFER_PORTRAIT, PALETTE_083, TILEMAP_0EC, TILEMAP_0ED, TILEMAP_0EE ; PORTRAIT_JENNIFER + dw TILESET_NICHOLAS_PORTRAIT, PALETTE_084, TILEMAP_0EF, TILEMAP_0F0, TILEMAP_0F1 ; PORTRAIT_NICHOLAS + dw TILESET_BRANDON_PORTRAIT, PALETTE_085, TILEMAP_0F2, TILEMAP_0F3, TILEMAP_0F4 ; PORTRAIT_BRANDON + dw TILESET_MURRAY_PORTRAIT, PALETTE_086, TILEMAP_0F5, TILEMAP_0F6, TILEMAP_0F7 ; PORTRAIT_MURRAY + dw TILESET_STEPHANIE_PORTRAIT, PALETTE_087, TILEMAP_0F8, TILEMAP_0F9, TILEMAP_0FA ; PORTRAIT_STEPHANIE + dw TILESET_DANIEL_PORTRAIT, PALETTE_088, TILEMAP_0FB, TILEMAP_0FC, TILEMAP_0FD ; PORTRAIT_DANIEL + dw TILESET_ROBERT_PORTRAIT, PALETTE_089, TILEMAP_0FE, TILEMAP_0FF, TILEMAP_100 ; PORTRAIT_ROBERT + dw TILESET_GENE_PORTRAIT, PALETTE_08A, TILEMAP_101, TILEMAP_102, TILEMAP_103 ; PORTRAIT_GENE + dw TILESET_MATTHEW_PORTRAIT, PALETTE_08B, TILEMAP_104, TILEMAP_105, TILEMAP_106 ; PORTRAIT_MATTHEW + dw TILESET_RYAN_PORTRAIT, PALETTE_08C, TILEMAP_107, TILEMAP_108, TILEMAP_109 ; PORTRAIT_RYAN + dw TILESET_ANDREW_PORTRAIT, PALETTE_08D, TILEMAP_10A, TILEMAP_10B, TILEMAP_10C ; PORTRAIT_ANDREW + dw TILESET_MITCH_PORTRAIT, PALETTE_08E, TILEMAP_10D, TILEMAP_10E, TILEMAP_10F ; PORTRAIT_MITCH + dw TILESET_MICHAEL_PORTRAIT, PALETTE_08F, TILEMAP_110, TILEMAP_111, TILEMAP_112 ; PORTRAIT_MICHAEL + dw TILESET_CHRIS_PORTRAIT, PALETTE_090, TILEMAP_113, TILEMAP_114, TILEMAP_115 ; PORTRAIT_CHRIS + dw TILESET_JESSICA_PORTRAIT, PALETTE_091, TILEMAP_116, TILEMAP_117, TILEMAP_118 ; PORTRAIT_JESSICA + dw TILESET_NIKKI_PORTRAIT, PALETTE_092, TILEMAP_119, TILEMAP_11A, TILEMAP_11B ; PORTRAIT_NIKKI + dw TILESET_BRITTANY_PORTRAIT, PALETTE_093, TILEMAP_11C, TILEMAP_11D, TILEMAP_11E ; PORTRAIT_BRITTANY + dw TILESET_KRISTIN_PORTRAIT, PALETTE_094, TILEMAP_11F, TILEMAP_120, TILEMAP_121 ; PORTRAIT_KRISTIN + dw TILESET_HEATHER_PORTRAIT, PALETTE_095, TILEMAP_122, TILEMAP_123, TILEMAP_124 ; PORTRAIT_HEATHER + dw TILESET_RICK_PORTRAIT, PALETTE_096, TILEMAP_125, TILEMAP_126, TILEMAP_127 ; PORTRAIT_RICK + dw TILESET_JOSEPH_PORTRAIT, PALETTE_097, TILEMAP_128, TILEMAP_129, TILEMAP_12A ; PORTRAIT_JOSEPH + dw TILESET_DAVID_PORTRAIT, PALETTE_098, TILEMAP_12B, TILEMAP_12C, TILEMAP_12D ; PORTRAIT_DAVID + dw TILESET_ERIK_PORTRAIT, PALETTE_099, TILEMAP_12E, TILEMAP_12F, TILEMAP_130 ; PORTRAIT_ERIK + dw TILESET_AMY_PORTRAIT, PALETTE_09A, TILEMAP_131, TILEMAP_132, TILEMAP_133 ; PORTRAIT_AMY + dw TILESET_JOSHUA_PORTRAIT, PALETTE_09B, TILEMAP_134, TILEMAP_135, TILEMAP_136 ; PORTRAIT_JOSHUA + dw TILESET_SARA_PORTRAIT, PALETTE_09C, TILEMAP_137, TILEMAP_138, TILEMAP_139 ; PORTRAIT_SARA + dw TILESET_AMANDA_PORTRAIT, PALETTE_09D, TILEMAP_13A, TILEMAP_13B, TILEMAP_13C ; PORTRAIT_AMANDA + dw TILESET_KEN_PORTRAIT, PALETTE_09E, TILEMAP_13D, TILEMAP_13E, TILEMAP_13F ; PORTRAIT_KEN + dw TILESET_JOHN_PORTRAIT, PALETTE_09F, TILEMAP_140, TILEMAP_141, TILEMAP_142 ; PORTRAIT_JOHN + dw TILESET_ADAM_PORTRAIT, PALETTE_0A0, TILEMAP_143, TILEMAP_144, TILEMAP_145 ; PORTRAIT_ADAM + dw TILESET_JONATHAN_PORTRAIT, PALETTE_0A1, TILEMAP_146, TILEMAP_147, TILEMAP_148 ; PORTRAIT_JONATHAN + dw TILESET_COURTNEY_PORTRAIT, PALETTE_0A2, TILEMAP_149, TILEMAP_14A, TILEMAP_14B ; PORTRAIT_COURTNEY + dw TILESET_STEVE_PORTRAIT, PALETTE_0A3, TILEMAP_14C, TILEMAP_14D, TILEMAP_14E ; PORTRAIT_STEVE + dw TILESET_JACK_PORTRAIT, PALETTE_0A4, TILEMAP_14F, TILEMAP_150, TILEMAP_151 ; PORTRAIT_JACK + dw TILESET_ROD_PORTRAIT, PALETTE_0A5, TILEMAP_152, TILEMAP_153, TILEMAP_154 ; PORTRAIT_ROD + dw TILESET_EIJI_PORTRAIT, PALETTE_0A6, TILEMAP_155, TILEMAP_156, TILEMAP_157 ; PORTRAIT_EIJI + dw TILESET_MAGICIAN_PORTRAIT, PALETTE_0A7, TILEMAP_158, TILEMAP_159, TILEMAP_15A ; PORTRAIT_MAGICIAN + dw TILESET_YUI_PORTRAIT, PALETTE_0A8, TILEMAP_15B, TILEMAP_15C, TILEMAP_15D ; PORTRAIT_YUI + dw TILESET_TOSHIRON_PORTRAIT, PALETTE_0A9, TILEMAP_15E, TILEMAP_15F, TILEMAP_160 ; PORTRAIT_TOSHIRON + dw TILESET_PIERROT_PORTRAIT, PALETTE_0AA, TILEMAP_161, TILEMAP_162, TILEMAP_163 ; PORTRAIT_PIERROT + dw TILESET_ANNA_PORTRAIT, PALETTE_0AB, TILEMAP_164, TILEMAP_165, TILEMAP_166 ; PORTRAIT_ANNA + dw TILESET_DEE_PORTRAIT, PALETTE_0AC, TILEMAP_167, TILEMAP_168, TILEMAP_169 ; PORTRAIT_DEE + dw TILESET_MASQUERADE_PORTRAIT, PALETTE_0AD, TILEMAP_16A, TILEMAP_16B, TILEMAP_16C ; PORTRAIT_MASQUERADE + dw TILESET_PAWN_PORTRAIT, PALETTE_0AE, TILEMAP_16D, TILEMAP_16E, TILEMAP_16F ; PORTRAIT_PAWN + dw TILESET_KNIGHT_PORTRAIT, PALETTE_0AF, TILEMAP_170, TILEMAP_171, TILEMAP_172 ; PORTRAIT_KNIGHT + dw TILESET_BISHOP_PORTRAIT, PALETTE_0B0, TILEMAP_173, TILEMAP_174, TILEMAP_175 ; PORTRAIT_BISHOP + dw TILESET_ROOK_PORTRAIT, PALETTE_0B1, TILEMAP_176, TILEMAP_177, TILEMAP_178 ; PORTRAIT_ROOK + dw TILESET_QUEEN_PORTRAIT, PALETTE_0B2, TILEMAP_179, TILEMAP_17A, TILEMAP_17B ; PORTRAIT_QUEEN + dw TILESET_GR_1_PORTRAIT, PALETTE_0B3, TILEMAP_17C, TILEMAP_17D, TILEMAP_17E ; PORTRAIT_GR_1 + dw TILESET_GR_2_PORTRAIT, PALETTE_0B4, TILEMAP_17F, TILEMAP_180, TILEMAP_181 ; PORTRAIT_GR_2 + dw TILESET_GR_3_PORTRAIT, PALETTE_0B5, TILEMAP_182, TILEMAP_183, TILEMAP_184 ; PORTRAIT_GR_3 + dw TILESET_GR_4_PORTRAIT, PALETTE_0B6, TILEMAP_185, TILEMAP_186, TILEMAP_187 ; PORTRAIT_GR_4 + dw TILESET_MIDORI_PORTRAIT, PALETTE_0B7, TILEMAP_188, TILEMAP_189, TILEMAP_18A ; PORTRAIT_MIDORI + dw TILESET_YUUTA_PORTRAIT, PALETTE_0B8, TILEMAP_18B, TILEMAP_18C, TILEMAP_18D ; PORTRAIT_YUUTA + dw TILESET_MIYUKI_PORTRAIT, PALETTE_0B9, TILEMAP_18E, TILEMAP_18F, TILEMAP_190 ; PORTRAIT_MIYUKI + dw TILESET_MORINO_PORTRAIT, PALETTE_0BA, TILEMAP_191, TILEMAP_192, TILEMAP_193 ; PORTRAIT_MORINO + dw TILESET_RENNA_PORTRAIT, PALETTE_0BB, TILEMAP_194, TILEMAP_195, TILEMAP_196 ; PORTRAIT_RENNA + dw TILESET_ICHIKAWA_PORTRAIT, PALETTE_0BC, TILEMAP_197, TILEMAP_198, TILEMAP_199 ; PORTRAIT_ICHIKAWA + dw TILESET_CATHERINE_PORTRAIT, PALETTE_0BD, TILEMAP_19A, TILEMAP_19B, TILEMAP_19C ; PORTRAIT_CATHERINE + dw TILESET_TAP_PORTRAIT, PALETTE_0BE, TILEMAP_19D, TILEMAP_19E, TILEMAP_19F ; PORTRAIT_TAP + dw TILESET_JES_PORTRAIT, PALETTE_0BF, TILEMAP_1A0, TILEMAP_1A1, TILEMAP_1A2 ; PORTRAIT_JES + dw TILESET_YUKI_PORTRAIT, PALETTE_0C0, TILEMAP_1A3, TILEMAP_1A4, TILEMAP_1A5 ; PORTRAIT_YUKI + dw TILESET_SHOKO_PORTRAIT, PALETTE_0C1, TILEMAP_1A6, TILEMAP_1A7, TILEMAP_1A8 ; PORTRAIT_SHOKO + dw TILESET_HIDERO_PORTRAIT, PALETTE_0C2, TILEMAP_1A9, TILEMAP_1AA, TILEMAP_1AB ; PORTRAIT_HIDERO + dw TILESET_MIYAJIMA_PORTRAIT, PALETTE_0C3, TILEMAP_1AC, TILEMAP_1AD, TILEMAP_1AE ; PORTRAIT_MIYAJIMA + dw TILESET_SENTA_PORTRAIT, PALETTE_0C4, TILEMAP_1AF, TILEMAP_1B0, TILEMAP_1B1 ; PORTRAIT_SENTA + dw TILESET_AIRA_PORTRAIT, PALETTE_0C5, TILEMAP_1B2, TILEMAP_1B3, TILEMAP_1B4 ; PORTRAIT_AIRA + dw TILESET_KANOKO_PORTRAIT, PALETTE_0C6, TILEMAP_1B5, TILEMAP_1B6, TILEMAP_1B7 ; PORTRAIT_KANOKO + dw TILESET_GODA_PORTRAIT, PALETTE_0C7, TILEMAP_1B8, TILEMAP_1B9, TILEMAP_1BA ; PORTRAIT_GODA + dw TILESET_GRACE_PORTRAIT, PALETTE_0C8, TILEMAP_1BB, TILEMAP_1BC, TILEMAP_1BD ; PORTRAIT_GRACE + dw TILESET_KAMIYA_PORTRAIT, PALETTE_0C9, TILEMAP_1BE, TILEMAP_1BF, TILEMAP_1C0 ; PORTRAIT_KAMIYA + dw TILESET_MIWA_PORTRAIT, PALETTE_0CA, TILEMAP_1C1, TILEMAP_1C2, TILEMAP_1C3 ; PORTRAIT_MIWA + dw TILESET_KEVIN_PORTRAIT, PALETTE_0CB, TILEMAP_1C4, TILEMAP_1C5, TILEMAP_1C6 ; PORTRAIT_KEVIN + dw TILESET_YOSUKE_PORTRAIT, PALETTE_0CC, TILEMAP_1C7, TILEMAP_1C8, TILEMAP_1C9 ; PORTRAIT_YOSUKE + dw TILESET_RYOKO_PORTRAIT, PALETTE_0CD, TILEMAP_1CA, TILEMAP_1CB, TILEMAP_1CC ; PORTRAIT_RYOKO + dw TILESET_MAMI_PORTRAIT, PALETTE_0CE, TILEMAP_1CD, TILEMAP_1CE, TILEMAP_1CF ; PORTRAIT_MAMI + dw TILESET_NISHIJIMA_PORTRAIT, PALETTE_0CF, TILEMAP_1D0, TILEMAP_1D1, TILEMAP_1D2 ; PORTRAIT_NISHIJIMA + dw TILESET_ISHII_PORTRAIT, PALETTE_0D0, TILEMAP_1D3, TILEMAP_1D4, TILEMAP_1D5 ; PORTRAIT_ISHII + dw TILESET_SAMEJIMA_PORTRAIT, PALETTE_0D1, TILEMAP_1D6, TILEMAP_1D7, TILEMAP_1D8 ; PORTRAIT_SAMEJIMA + dw TILESET_KANZAKI_PORTRAIT, PALETTE_0D2, TILEMAP_1D9, TILEMAP_1DA, TILEMAP_1DB ; PORTRAIT_KANZAKI + dw TILESET_RUI_PORTRAIT, PALETTE_0D3, TILEMAP_1DC, TILEMAP_1DD, TILEMAP_1DE ; PORTRAIT_RUI + dw TILESET_BIRURITCHI_PORTRAIT, PALETTE_0D4, TILEMAP_1DF, TILEMAP_1E0, TILEMAP_1E1 ; PORTRAIT_BIRURITCHI + dw TILESET_GR_X_PORTRAIT, PALETTE_0D5, TILEMAP_1E2, TILEMAP_1E3, TILEMAP_1E4 ; PORTRAIT_GR_X + dw TILESET_TOBI_CHAN_PORTRAIT, PALETTE_0D6, TILEMAP_1E5, TILEMAP_1E6, TILEMAP_1E7 ; PORTRAIT_TOBI_CHAN + dw TILESET_DR_MASON_PORTRAIT, PALETTE_0D7, TILEMAP_1E8, TILEMAP_1E9, TILEMAP_1EA ; PORTRAIT_DR_MASON + dw TILESET_IMAKUNI_BLACK_PORTRAIT, PALETTE_080, TILEMAP_0E3, TILEMAP_0E4, TILEMAP_0E5 ; PORTRAIT_IMAKUNI_BLACK + dw TILESET_IMAKUNI_RED_PORTRAIT, PALETTE_081, TILEMAP_0E6, TILEMAP_0E7, TILEMAP_0E8 ; PORTRAIT_IMAKUNI_RED diff --git a/src/engine/credits_commands.asm b/src/engine/credits_commands.asm index 598bf11..7304e62 100644 --- a/src/engine/credits_commands.asm +++ b/src/engine/credits_commands.asm @@ -226,7 +226,7 @@ CreditsCmd_ShowPortrait: ld a, [wCreditsCmdArg5] ld e, a ld a, [wCreditsCmdArg1] - call Func_3ab2 + call DrawNPCPortrait ret CreditsCmd_PrintHeader: diff --git a/src/engine/game_loop.asm b/src/engine/game_loop.asm index 4087221..49ea670 100644 --- a/src/engine/game_loop.asm +++ b/src/engine/game_loop.asm @@ -7,8 +7,8 @@ GameLoop:: call EnableSRAM ld a, [sTextSpeed] ld [wTextSpeed], a - ld a, [s0a009] - ld [wcd08], a + ld a, [sSkipDelayAllowed] + ld [wSkipDelayAllowed], a call DisableSRAM ld a, DECK_SIZE ld [wDeckSize], a diff --git a/src/home/ai.asm b/src/home/ai.asm index eee82fc..aa07f4a 100644 --- a/src/home/ai.asm +++ b/src/home/ai.asm @@ -1,7 +1,7 @@ ; loads opponent deck at wOpponentDeckID to wOpponentDeck, and initializes wPlayerDuelistType. ; on a duel against Sam, also loads PRACTICE_PLAYER_DECK to wPlayerDeck. ; also, sets wRNG1 and wRNGCounter to $20 and wRNG2 to 0. -LoadOpponentDeck: +LoadOpponentDeck:: xor a ld [wIsPracticeDuel], a ld [wcd17], a @@ -36,7 +36,7 @@ LoadOpponentDeck: call SwapTurn ld a, e add $02 - call $2e85 ; LoadDeck + call LoadDeck call SwapTurn ld hl, wRNG1 ld a, $20 @@ -48,7 +48,7 @@ LoadOpponentDeck: ld a, [wOpponentDeckID] inc a inc a ; convert from *_DECK_ID constant read from wOpponentDeckID to *_DECK constant - call $2e85 ; LoadDeck + call LoadDeck ld a, [wOpponentDeckID] cp $7a ; DECKS_END jr c, .valid_deck @@ -63,11 +63,11 @@ LoadOpponentDeck: ld [hl], a ret -AIDoAction_Turn: +AIDoAction_Turn:: ld a, AIACTION_DO_TURN jr AIDoAction -AIDoAction_StartDuel: +AIDoAction_StartDuel:: ld a, AIACTION_START_DUEL jr AIDoAction @@ -77,17 +77,17 @@ AIDoAction_ForcedSwitch: ldh [hTempPlayAreaLocation_ff9d], a ret -AIDoAction_KOSwitch: +AIDoAction_KOSwitch:: ld a, AIACTION_KO_SWITCH call AIDoAction ldh [hTemp_ffa0], a ret -AIDoAction_TakePrize: +AIDoAction_TakePrize:: ld a, AIACTION_TAKE_PRIZE jr AIDoAction -AIDoAction_06: +AIDoAction_06:: ld a, AIACTION_06 jr AIDoAction @@ -133,7 +133,7 @@ AIDoAction: ; load bank for Opponent Deck pointer table ldh a, [hBankROM] push af - ld a, $05 ; BANK(DeckAIPointerTable) + ld a, BANK(DeckAIPointerTable) call BankswitchROM ; load hl with the corresponding pointer diff --git a/src/home/card_collection.asm b/src/home/card_collection.asm index 46cbf54..f5565f5 100644 --- a/src/home/card_collection.asm +++ b/src/home/card_collection.asm @@ -217,16 +217,19 @@ GetCardAlbumProgress:: call DisableSRAM ret -Func_1bca: +; frame function during Link Opponent's turn +; if opponent makes a decision, jump directly +; to the address in wLinkOpponentTurnReturnAddress +LinkOpponentTurnFrameFunction:: ld a, [wSerialFlags] or a - jr nz, .asm_1bd4 + jr nz, .return call Func_0e32 ret nc -.asm_1bd4 +.return ld a, $09 call BankswitchROM - ld hl, wcd1a + ld hl, wLinkOpponentTurnReturnAddress ld a, [hli] ld h, [hl] ld l, a diff --git a/src/home/card_data.asm b/src/home/card_data.asm index fe74d25..9f2b349 100644 --- a/src/home/card_data.asm +++ b/src/home/card_data.asm @@ -101,7 +101,7 @@ GetCardType:: pop hl ret -Func_2d3f: +Func_2d3f:: push hl push de call GetCardPointer diff --git a/src/home/coin_toss.asm b/src/home/coin_toss.asm index d7f95fa..797426c 100644 --- a/src/home/coin_toss.asm +++ b/src/home/coin_toss.asm @@ -16,7 +16,7 @@ TossCoinATimes: ; text at de is printed in a text box during the coin toss. ; returns: - carry, and 1 in a and in wCoinTossNumHeads if heads ; - nc, and 0 in a and in wCoinTossNumHeads if tails -TossCoin: +TossCoin:: push hl ld hl, wCoinTossScreenTextID ld [hl], e diff --git a/src/home/duel.asm b/src/home/duel.asm index e8e4f16..3688027 100644 --- a/src/home/duel.asm +++ b/src/home/duel.asm @@ -72,7 +72,7 @@ CountPrizes:: ; draw a card from the turn holder's deck, saving its location as CARD_LOCATION_JUST_DRAWN. ; returns carry if deck is empty, nc if a card was successfully drawn. ; AddCardToHand is meant to be called next (unless this function returned carry). -DrawCardFromDeck: +DrawCardFromDeck:: push hl ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK get_turn_duelist_var @@ -153,7 +153,7 @@ SearchCardInDeckAndAddToHand: ; adds a card to the turn holder's hand and increments the number of cards in the hand ; the card is identified by register a, which contains the deck index (0-59) of the card -AddCardToHand: +AddCardToHand:: push af push hl push de @@ -218,7 +218,7 @@ RemoveCardFromHand: pop af ret -Func_0ffa: +Func_0ffa:: push bc push de ld c, a @@ -239,7 +239,7 @@ Func_0ffa: ; moves a card to the turn holder's discard pile, as long as it is in the hand ; the card is identified by register a, which contains the deck index (0-59) of the card -MoveHandCardToDiscardPile: +MoveHandCardToDiscardPile:: call CheckDeckIndexRange get_turn_duelist_var ld a, [hl] @@ -251,7 +251,7 @@ MoveHandCardToDiscardPile: ; fallthrough ; puts the turn holder's card with the deck index (0-59) given in a into the discard pile -PutCardInDiscardPile: +PutCardInDiscardPile:: push af push hl push de @@ -273,7 +273,7 @@ PutCardInDiscardPile: ; search a card in the turn holder's discard pile, extract it, and set its location to ; CARD_LOCATION_JUST_DRAWN. AddCardToHand is meant to be called next. ; the card is identified by register a, which contains the deck index (0-59) of the card -MoveDiscardPileCardToHand: +MoveDiscardPileCardToHand:: push hl push de push bc @@ -365,7 +365,7 @@ CreateDeckCardList: ; if a == 0: search in CARD_LOCATION_ARENA ; if a != 0: search in CARD_LOCATION_BENCH_[A] ; return carry if no energy cards were found -CreateArenaOrBenchEnergyCardList: +CreateArenaOrBenchEnergyCardList:: or CARD_LOCATION_PLAY_AREA ld c, a ld b, $00 @@ -402,7 +402,7 @@ CreateArenaOrBenchEnergyCardList: ; fill wDuelTempList with the turn holder's hand cards (their 0-59 deck indexes) ; return carry if the turn holder has no cards in hand ; and outputs in a number of cards. -CreateHandCardList: +CreateHandCardList:: call FindLastCardInHand inc b jr .skip_card @@ -433,7 +433,7 @@ CreateHandCardList: ; b = turn holder's number of cards in hand (DUELVARS_NUMBER_OF_CARDS_IN_HAND) ; hl = pointer to turn holder's last (newest) card in DUELVARS_HAND ; de = wDuelTempList -FindLastCardInHand: +FindLastCardInHand:: ldh a, [hWhoseTurn] ld h, a ld l, DUELVARS_NUMBER_OF_CARDS_IN_HAND @@ -448,7 +448,7 @@ FindLastCardInHand: ; input: ; a = how many cards to shuffle ; hl = DUELVARS_DECK_CARDS + [DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK] -ShuffleCards: +ShuffleCards:: cp 1 ret c ; return if less than 2 cards in deck push hl @@ -546,7 +546,7 @@ RemoveCardFromDuelTempList:: ret ; return the number of cards in wDuelTempList in a -CountCardsInDuelTempList: +CountCardsInDuelTempList:: push hl push bc ld hl, wDuelTempList @@ -585,10 +585,10 @@ LoadCardDataToBuffer1_FromDeckIndex:: push bc push af call GetCardIDFromDeckIndex - call $2d0a ; LoadCardDataToBuffer1_FromCardID + call LoadCardDataToBuffer1_FromCardID pop af ld hl, wLoadedCard1 - farcall $9, $4e25 ; ConvertSpecialTrainerCardToPokemon + farcall ConvertSpecialTrainerCardToPokemon pop bc pop de pop hl @@ -604,7 +604,7 @@ LoadCardDataToBuffer2_FromDeckIndex:: call LoadCardDataToBuffer2_FromCardID pop af ld hl, wLoadedCard2 - farcall $9, $4e25 ; ConvertSpecialTrainerCardToPokemon + farcall ConvertSpecialTrainerCardToPokemon pop bc pop de pop hl @@ -613,7 +613,7 @@ LoadCardDataToBuffer2_FromDeckIndex:: ; evolve a turn holder's Pokemon card in the play area slot determined by hTempPlayAreaLocation_ff9d ; into another turn holder's Pokemon card identifier by its deck index (0-59) in hTempCardIndex_ff98. ; return nc if evolution was successful. -EvolvePokemonCardIfPossible: +EvolvePokemonCardIfPossible:: ; first make sure the attempted evolution is viable ldh a, [hTempCardIndex_ff98] ld d, a @@ -678,7 +678,7 @@ EvolvePokemonCard: ; e is the play area location offset (PLAY_AREA_*) of the Pokemon trying to evolve. ; d is the deck index (0-59) of the Pokemon card that was selected to be the evolution target. ; return carry if can't evolve, plus nz if the reason for it is the card was played this turn. -CheckIfCanEvolveInto: +CheckIfCanEvolveInto:: push de ld a, e add DUELVARS_ARENA_CARD @@ -749,7 +749,7 @@ CheckIfCanEvolveInto_BasicToStage2: ld e, [hl] inc hl ld d, [hl] - call $2cbb ; LoadCardDataToBuffer1_FromName + call LoadCardDataToBuffer1_FromName ld hl, wLoadedCard2Name ld de, wLoadedCard1PreEvoName ld a, [de] @@ -770,7 +770,7 @@ CheckIfCanEvolveInto_BasicToStage2: ; clear the status, all substatuses, and temporary duelvars of the turn holder's ; arena Pokemon. called when sending a new Pokemon into the arena. ; does not reset Headache, since it targets a player rather than a Pokemon. -ClearAllStatusConditions: +ClearAllStatusConditions:: push hl ldh a, [hWhoseTurn] ld h, a @@ -804,13 +804,13 @@ ClearAllStatusConditions: ; input: ; a = deck index of the card ; return carry if there is no room for more Pokemon -PutHandPokemonCardInPlayArea: +PutHandPokemonCardInPlayArea:: push af call CheckDeckIndexRange ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA get_turn_duelist_var push hl - ld hl, wcc01 ; max play area pokemon ? + ld hl, wMaxNumPlayAreaPokemon ; max play area pokemon ? cp [hl] pop hl jr nc, .already_max_pkmn_in_play @@ -874,7 +874,7 @@ PutHandPokemonCardInPlayArea: ; e = play area location offset (PLAY_AREA_*) ; returns: ; a = CARD_LOCATION_PLAY_AREA + e -PutHandCardInPlayArea: +PutHandCardInPlayArea:: call RemoveCardFromHand get_turn_duelist_var ld a, e @@ -882,7 +882,7 @@ PutHandCardInPlayArea: ld [hl], a ret -Func_12fc: +Func_12fc:: ld a, [wSpecialRule] cp ENERGY_RETURN jr nz, MovePlayAreaCardToDiscardPile @@ -921,7 +921,7 @@ Func_12fc: ; move the Pokemon card of the turn holder in the ; PLAY_AREA_* location given in e to the discard pile -MovePlayAreaCardToDiscardPile: +MovePlayAreaCardToDiscardPile:: call EmptyPlayAreaSlot ld l, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA dec [hl] @@ -969,7 +969,7 @@ EmptyPlayAreaSlot: ret ; shift play area Pokemon of both players to the first available play area (arena + benchx) slots -ShiftAllPokemonToFirstPlayAreaSlots: +ShiftAllPokemonToFirstPlayAreaSlots:: call ShiftTurnPokemonToFirstPlayAreaSlots call SwapTurn call ShiftTurnPokemonToFirstPlayAreaSlots @@ -998,7 +998,7 @@ ShiftTurnPokemonToFirstPlayAreaSlots: ; data of the turn holder's Pokemon card in play area e. ; reset the status and all substatuses of the arena Pokemon before swapping. ; e is the play area location offset of the bench Pokemon (PLAY_AREA_*). -SwapArenaWithBenchPokemon: +SwapArenaWithBenchPokemon:: push de call ClearAllStatusConditions ld d, PLAY_AREA_ARENA @@ -1009,7 +1009,7 @@ SwapArenaWithBenchPokemon: ; swap the data of the turn holder's Pokemon card in play area d with the ; data of the turn holder's Pokemon card in play area e. ; d and e are play area location offsets (PLAY_AREA_*). -SwapPlayAreaPokemon: +SwapPlayAreaPokemon:: push bc push de push hl @@ -1225,7 +1225,7 @@ CopyAttackDataAndDamage_FromCardID: ld a, d ldh [hTempCardIndex_ff9f], a pop de - call $2d0a ; LoadCardDataToBuffer1_FromCardID + call LoadCardDataToBuffer1_FromCardID pop de jr CopyAttackDataAndDamage @@ -1234,7 +1234,7 @@ CopyAttackDataAndDamage_FromCardID: ; - Attack1 (if e == 0) or Attack2 (if e == 1) data into wLoadedAttack ; - Also from that attack, its Damage field into wDamage ; finally, clears wNoDamageOrEffect and wDealtDamage -CopyAttackDataAndDamage_FromDeckIndex: +CopyAttackDataAndDamage_FromDeckIndex:: ld a, e ld [wSelectedAttack], a ld a, d @@ -1276,7 +1276,7 @@ Func_14e5: get_turn_duelist_var ldh [hTempCardIndex_ff9f], a call Func_14f1 - call Func_1500 + call ClearTwoTurnDuelVars ret Func_14f1: @@ -1288,7 +1288,9 @@ Func_14f1: call SwapTurn ret -Func_1500: +; zeroes temp variables that only last between each two-player turn. +; this is called when a Pokemon card is played or when an attack is used +ClearTwoTurnDuelVars:: xor a ld [wccec], a ld [wEffectFunctionsFeedbackIndex], a @@ -1306,14 +1308,14 @@ Func_1500: ld [hli], a ld [hli], a ld [hl], a - bank1call $6b13 ; Func_6b13 - ld a, $ed + bank1call ClearNonTurnTemporaryDuelvars_CopyStatus + ld a, DUELVARS_ARENA_CARD_SUBSTATUS1 call GetNonTurnDuelistVariable ld [wcd0b], a ret ; Use an attack (from DuelMenu_Attack) or a Pokemon Power (from DuelMenu_PkmnPower) -UseAttackOrPokemonPower: +UseAttackOrPokemonPower:: ld a, [wSelectedAttack] ld [wPlayerAttackingAttackIndex], a ldh a, [hTempCardIndex_ff9f] @@ -1329,10 +1331,10 @@ UseAttackOrPokemonPower: ldh [hTempPlayAreaLocation_ff9d], a call Func_14e5 ld a, EFFECTCMDTYPE_INITIAL_EFFECT_1 - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction jp c, DrawWideTextBox_WaitForInput_ReturnCarry farcall $9, $4375 ; Func_24375 - call $27fa ; WaitForWideTextBoxInput + call WaitForWideTextBoxInput call SendAttackDataToLinkOpponent bank1call $784a ; HandleSandAttackOrSmokescreenSubstatus ? jp c, ClearNonTurnTemporaryDuelvars_ResetCarry @@ -1343,7 +1345,7 @@ UseAttackOrPokemonPower: call ExchangeRNG .asm_1580 ld a, EFFECTCMDTYPE_INITIAL_EFFECT_2 - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction jr nc, .asm_159b ld a, [wcd16] or a @@ -1357,9 +1359,9 @@ UseAttackOrPokemonPower: ret .asm_159b ld a, EFFECTCMDTYPE_DISCARD_ENERGY - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction ld a, EFFECTCMDTYPE_REQUIRE_SELECTION - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction ld a, OPPACTION_ATTACK_ANIM_AND_DAMAGE call SetOppAction_SerialSendDuelData ; fallthrough @@ -1367,7 +1369,7 @@ UseAttackOrPokemonPower: PlayAttackAnimation_DealAttackDamage: call Func_14f1 bank1call $6e68 ; Func_6e68 - farcall $6, $4a14 ; Func_18a14 + farcall Func_18a14 ld a, [wLoadedAttackCategory] and RESIDUAL jr nz, .deal_damage @@ -1378,7 +1380,7 @@ PlayAttackAnimation_DealAttackDamage: xor a ldh [hTempPlayAreaLocation_ff9d], a ld a, EFFECTCMDTYPE_BEFORE_DAMAGE - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction call ApplyDamageModifiers_DamageToTarget call Func_189d ld a, e @@ -1409,7 +1411,7 @@ PlayAttackAnimation_DealAttackDamage: jr Func_17fb Func_17ed: - call $27f7 ; DrawWideTextBox_WaitForInput + call DrawWideTextBox_WaitForInput xor a ld hl, wDamage ld [hli], a @@ -1426,7 +1428,7 @@ Func_17fb: push hl push de ld a, EFFECTCMDTYPE_AFTER_DAMAGE - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction pop de pop hl ld [hl], d @@ -1443,7 +1445,7 @@ Func_17fb: ret DrawWideTextBox_WaitForInput_ReturnCarry: - call $27f7 ; DrawWideTextBox_WaitForInput + call DrawWideTextBox_WaitForInput ; fallthrough ReturnCarry: @@ -1466,9 +1468,9 @@ HandleConfusionDamageToSelf: bank1call $4cd7 ; DrawDuelMainScene pop hl push hl - call $2cb2 ; Func_2cb2 + call LoadTxRam3 ld hl, $50 ; DamageToSelfDueToConfusionText - call $27a5 ; DrawWideTextBox_PrintText + call DrawWideTextBox_PrintText ld a, ATK_ANIM_CONFUSION_HIT ld [wLoadedAttackAnimation], a pop hl @@ -1482,10 +1484,10 @@ HandleConfusionDamageToSelf: ; use Pokemon Power UsePokemonPower: - call Func_1500 - farcall $6, $4a14 ; Func_18a14 + call ClearTwoTurnDuelVars + farcall Func_18a14 ld a, EFFECTCMDTYPE_INITIAL_EFFECT_2 - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction jr c, DrawWideTextBox_WaitForInput_ReturnCarry ld a, [wcd0d] or a @@ -1494,7 +1496,7 @@ UsePokemonPower: call SetOppAction_SerialSendDuelData .asm_1687 ld a, EFFECTCMDTYPE_REQUIRE_SELECTION - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction jr c, ReturnCarry ld a, OPPACTION_USE_PKMN_POWER call SetOppAction_SerialSendDuelData @@ -1502,7 +1504,7 @@ UsePokemonPower: ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT call SetOppAction_SerialSendDuelData ld a, EFFECTCMDTYPE_BEFORE_DAMAGE - call $2e33 ; TryExecuteEffectCommandFunction + call TryExecuteEffectCommandFunction ld a, OPPACTION_DUEL_MAIN_SCENE call SetOppAction_SerialSendDuelData ret @@ -1578,7 +1580,7 @@ Func_189d: push hl bank1call $4cd7 ; DrawDuelMainScene pop hl - call $27a5 ; DrawWideTextBox_PrintText + call DrawWideTextBox_PrintText ld a, DUELVARS_ARENA_CARD_SUBSTATUS2 call GetNonTurnDuelistVariable ld [hl], $0 @@ -1598,7 +1600,7 @@ CheckSelfConfusionDamage: ret .confused ld de, $117 ; ConfusionCheckDamageText - call $2ebb ; TossCoin + call TossCoin jr c, .no_confusion_damage ld a, 1 ld [wGotHeadsFromConfusionCheck], a @@ -1629,7 +1631,7 @@ DealConfusionDamageToSelf: ld [wNoDamageOrEffect], a ld a, $01 ld [wIsDamageToSelf], a - farcall $6, $4a14 ; Func_18a14 + farcall Func_18a14 ld hl, wTempNonTurnDuelistCardID ld e, [hl] inc hl @@ -1741,7 +1743,7 @@ ApplyDamageModifiers_DamageToTarget: ret ; convert a color to its equivalent WR_* (weakness/resistance) value -TranslateColorToWR: +TranslateColorToWR:: push hl add LOW(InvertedPowersOf2) ld l, a @@ -1843,7 +1845,7 @@ ApplyAttachedDefender: ; hl: address to subtract HP from ; de: how much HP to subtract (damage to deal) ; returns carry if the HP does not become 0 as a result -SubtractHP: +SubtractHP:: push hl push de ld a, [hl] @@ -1866,7 +1868,7 @@ SubtractHP: ; given a play area location offset in a, check if the turn holder's Pokemon card in ; that location has no HP left, and, if so, print that it was knocked out. -PrintPlayAreaCardKnockedOutIfNoHP: +PrintPlayAreaCardKnockedOutIfNoHP:: ld c, a add DUELVARS_ARENA_CARD_HP get_turn_duelist_var @@ -1895,7 +1897,7 @@ PrintPlayAreaCardKnockedOutIfNoHP: scf ret -PrintKnockedOutIfHLZero: +PrintKnockedOutIfHLZero:: ld a, [hl] ; this is supposed to point to a remaining HP value after some form of damage calculation or a ret nz @@ -1908,14 +1910,14 @@ PrintKnockedOut: ld e, [hl] inc hl ld d, [hl] - call $2d0a ; LoadCardDataToBuffer1_FromCardID + call LoadCardDataToBuffer1_FromCardID ld hl, wLoadedCard1Name ld a, [hli] ld h, [hl] ld l, a - call $2ca9 ; LoadTxRam2 + call LoadTxRam2 ld hl, $84 ; WasKnockedOutText - call $27a5 ; DrawWideTextBox_PrintText + call DrawWideTextBox_PrintText ld a, 40 .wait_frames call DoFrame @@ -1938,7 +1940,7 @@ DealDamageToPlayAreaPokemon_RegularAnim: ; shows the defending player's play area screen when dealing the damage ; instead of the main duel interface. ; plays animation that is loaded in wLoadedAttackAnimation. -DealDamageToPlayAreaPokemon: +DealDamageToPlayAreaPokemon:: xor a ld [wNoDamageOrEffect], a ld a, b @@ -2045,7 +2047,7 @@ Func_1bb4: xor a ldh [hTempPlayAreaLocation_ff9d], a call Func_19e1 - call $27fa ; WaitForWideTextBoxInput + call WaitForWideTextBoxInput call ExchangeRNG ret @@ -2059,12 +2061,12 @@ Func_19e1: jr z, .no_effect_from_status call Func_19fd ld hl, $1a1 ; WasUnsuccessfulText - call $27a5 ; DrawWideTextBox_PrintText + call DrawWideTextBox_PrintText scf ret .no_effect_from_status bank1call $66d0 ; PrintThereWasNoEffectFromStatusText - call $27a5 ; DrawWideTextBox_PrintText + call DrawWideTextBox_PrintText scf ret @@ -2074,11 +2076,11 @@ Func_19fd: get_turn_duelist_var call LoadCardDataToBuffer1_FromDeckIndex ld a, 18 - call $26da ; CopyCardNameAndLevel + call CopyCardNameAndLevel ; zero wTxRam2 so that the name & level text just loaded to wDefaultText is printed ld [hl], $0 ld hl, $0000 - call $2ca9 ; LoadTxRam2 + call LoadTxRam2 ld hl, wLoadedAttackName ld de, $cdd8 ; wTxRam2_b ld a, [hli] @@ -2092,11 +2094,11 @@ Func_1a1e: bank1call $6b05 ; ClearNonTurnTemporaryDuelvars call Func_19fd ld hl, $1a2 - jp $27f7 ; DrawWideTextBox_WaitForInput + jp DrawWideTextBox_WaitForInput ; return in a the retreat cost of the turn holder's arena or bench Pokemon ; given the PLAY_AREA_* value in hTempPlayAreaLocation_ff9d -GetPlayAreaCardRetreatCost: +GetPlayAreaCardRetreatCost:: ldh a, [hTempPlayAreaLocation_ff9d] add DUELVARS_ARENA_CARD get_turn_duelist_var @@ -2197,7 +2199,7 @@ CopyPlayerName:: ; if text ID at wOpponentName is non-0, copy it from there ; else, if text at wc500 is non-0, copy if from there ; else, copy Player2Text -CopyOpponentName: +CopyOpponentName:: ld hl, wOpponentName ld a, [hli] or [hl] diff --git a/src/home/duel_menus.asm b/src/home/duel_menus.asm index 61b2739..d8d79e0 100644 --- a/src/home/duel_menus.asm +++ b/src/home/duel_menus.asm @@ -1,4 +1,4 @@ -OpenDuelCheckMenu: +OpenDuelCheckMenu:: ldh a, [hBankROM] push af ld a, $02 ; BANK(_OpenDuelCheckMenu) @@ -8,7 +8,7 @@ OpenDuelCheckMenu: call BankswitchROM ret -OpenInPlayAreaScreen_FromSelectButton: +OpenInPlayAreaScreen_FromSelectButton:: ldh a, [hBankROM] push af ld a, $06 ; BANK(OpenInPlayAreaScreen) @@ -27,7 +27,7 @@ OpenInPlayAreaScreen_FromSelectButton: ; similar to DrawYourOrOppPlayArea (bank 2) except it also draws a wide text box. ; this is because bank 2's DrawYourOrOppPlayArea is supposed to come from the Check Menu, ; so the text box is always already there. -DrawYourOrOppPlayAreaScreen_Bank0: +DrawYourOrOppPlayAreaScreen_Bank0:: ld a, h ld [wCheckMenuPlayAreaWhichDuelist], a ld a, l @@ -76,7 +76,7 @@ DrawAIPeekScreen: ret ; a = number of prize cards for player to select to take -SelectPrizeCards: +SelectPrizeCards:: ld [wNumberOfPrizeCardsToSelect], a ldh a, [hBankROM] push af @@ -87,7 +87,7 @@ SelectPrizeCards: call BankswitchROM ret -DrawPlayAreaToPlacePrizeCards: +DrawPlayAreaToPlacePrizeCards:: ldh a, [hBankROM] push af ld a, $02 ; BANK(_DrawPlayAreaToPlacePrizeCards) diff --git a/src/home/effect_commands.asm b/src/home/effect_commands.asm index 1878bbe..43d15fd 100644 --- a/src/home/effect_commands.asm +++ b/src/home/effect_commands.asm @@ -3,7 +3,7 @@ ; input: ; a = command type to check ; [wLoadedAttackEffectCommands] = pointer to list of commands of current attack or trainer card -TryExecuteEffectCommandFunction: +TryExecuteEffectCommandFunction:: push af ; grab pointer to command list from wLoadedAttackEffectCommands ld hl, wLoadedAttackEffectCommands @@ -38,7 +38,7 @@ TryExecuteEffectCommandFunction: ; a = command type to check ; hl = list of commands of current attack or trainer card ; return nc if command type matching a is found, carry otherwise -CheckMatchingCommand: +CheckMatchingCommand:: ld c, a ld a, l or h diff --git a/src/home/list.asm b/src/home/list.asm index 0c1183c..53602b7 100644 --- a/src/home/list.asm +++ b/src/home/list.asm @@ -56,7 +56,7 @@ SetNextElementOfList_Common: inc de jr SetListToNextPosition -SetNextElementOfList2: +SetNextElementOfList2:: push hl push de ld hl, wListPointer2 diff --git a/src/home/math.asm b/src/home/math.asm index 60cc076..87f2681 100644 --- a/src/home/math.asm +++ b/src/home/math.asm @@ -1,5 +1,5 @@ ; returns a *= 10 -ATimes10: +ATimes10:: push de ld e, a add a diff --git a/src/home/menus.asm b/src/home/menus.asm index 6d146b2..75e1f95 100644 --- a/src/home/menus.asm +++ b/src/home/menus.asm @@ -1049,7 +1049,7 @@ HandleYesOrNoMenu:: PrintYesOrNoItems:: call AdjustCoordinatesForBGScroll ld hl, $30 ; YesOrNoText - call $29d8 ; InitTextPrinting_ProcessTextFromID + call InitTextPrinting_ProcessTextFromID ret BuildVersion:: diff --git a/src/home/serial.asm b/src/home/serial.asm index cd2f765..9efccd7 100644 --- a/src/home/serial.asm +++ b/src/home/serial.asm @@ -331,7 +331,7 @@ SerialRecvByte: ret ; exchange c bytes. send bytes at hl and store received bytes in de -SerialExchangeBytes: +SerialExchangeBytes:: ld b, c .asm_e64 ld a, b @@ -493,13 +493,13 @@ Func_0f05: ; load the number at wSerialFlags (error code?) to TxRam3, print ; TransmissionErrorText, exit the duel, and reset serial registers. -DuelTransmissionError: +DuelTransmissionError:: ld a, [wSerialFlags] ld l, a ld h, 0 - call $2cb2 ; LoadTxRam3 + call LoadTxRam3 ld hl, $0057 ; TransmissionErrorText - call $27f7 ; DrawWideTextBox_WaitForInput + call DrawWideTextBox_WaitForInput ld a, -1 ld [wDuelResult], a ld hl, wDuelReturnAddress @@ -513,7 +513,7 @@ DuelTransmissionError: ret ; exchange RNG during a link duel between both games -ExchangeRNG: +ExchangeRNG:: ld a, [wDuelType] cp DUELTYPE_LINK jr z, .link_duel @@ -542,7 +542,7 @@ ExchangeRNG: ; finally exchange RNG data. ; the receiving side will use this data to read the OPPACTION_* value in ; [hOppActionTableIndex] and match it by calling the corresponding OppAction* function -SetOppAction_SerialSendDuelData: +SetOppAction_SerialSendDuelData:: push hl push bc ldh [hOppActionTableIndex], a @@ -561,7 +561,7 @@ SetOppAction_SerialSendDuelData: ; receive 18 bytes of data from wSerialRecvBuf and store them into hOppActionTableIndex, ; hTempCardIndex_ff9f, hTemp_ffa0, and hTempPlayAreaLocation_ffa1, ; and hTempRetreatCostCards. also exchange RNG data. -SerialRecvDuelData: +SerialRecvDuelData:: push hl push bc ld hl, hOppActionTableIndex @@ -574,7 +574,7 @@ SerialRecvDuelData: ; serial send 8 bytes at f, a, l, h, e, d, c, b ; only during a duel against a link opponent -SerialSend8Bytes: +SerialSend8Bytes:: push hl push af ld a, [wDuelType] @@ -624,7 +624,7 @@ SerialSend8Bytes: ret ; serial recv 8 bytes to f, a, l, h, e, d, c, b -SerialRecv8Bytes: +SerialRecv8Bytes:: ld hl, wTempSerialBuf ld bc, 8 push hl diff --git a/src/home/text_box.asm b/src/home/text_box.asm index 5474be5..841aaec 100644 --- a/src/home/text_box.asm +++ b/src/home/text_box.asm @@ -34,7 +34,7 @@ DECoordToBGMap0Address: ret ; Apply SCX and SCY correction to xy coordinates at de -AdjustCoordinatesForBGScroll: +AdjustCoordinatesForBGScroll:: push af ldh a, [hSCX] rra diff --git a/src/home/tiles.asm b/src/home/tiles.asm index d45af6d..0bab018 100644 --- a/src/home/tiles.asm +++ b/src/home/tiles.asm @@ -197,7 +197,7 @@ Func_212f:: ld de, sGfxBuffer1 + $30 tiles ld b, $8 call CopyFontsOrDuelGraphicsTiles - call $2684 ; GetCardSymbolData + call GetCardSymbolData sub $d0 ld l, a ld h, $00 diff --git a/src/home/time.asm b/src/home/time.asm index 35fd3a5..9d20f1c 100644 --- a/src/home/time.asm +++ b/src/home/time.asm @@ -25,9 +25,9 @@ TimerHandler: set IN_TIMER, [hl] ldh a, [hBankROM] push af - ld a, $77 ; BANK(SoundTimerHandler) + ld a, BANK(SoundTimerHandler) call BankswitchROM - call $4003 ; SoundTimerHandler + call SoundTimerHandler pop af call BankswitchROM ; clear in-timer flag diff --git a/src/home/unsorted.asm b/src/home/unsorted.asm index 8b2c9af..11947c3 100644 --- a/src/home/unsorted.asm +++ b/src/home/unsorted.asm @@ -87,12 +87,13 @@ Func_30b7:: Func_30d6:: ld a, $02 ld [wd54c], a - farcall $7, $65a2 - jr c, .asm_30e8 + farcall Func_1e5a2 + jr c, .lost +; won ld a, EVENT_F1 farcall MaxOutEventValue ret -.asm_30e8 +.lost ld a, EVENT_F1 farcall ZeroOutEventValue ret @@ -1931,18 +1932,20 @@ DrawPlayerPortrait:: pop af ret +; a = NPC_* constant ; bc = coordinates ; e = PORTRAITVARIANT_* constant -Func_3ab2:: +DrawNPCPortrait:: push af push bc push de push hl - cp $04 + cp NPC_MINT_LINK + 1 jr nc, .ok + ; Mark and Mint don't have portrait variants ld e, PORTRAITVARIANT_NORMAL .ok - farcall Func_1c101 + farcall GetDuelistPortrait ld h, e ld d, b ld e, c @@ -2228,14 +2231,15 @@ Func_3c2e:: pop af ret -Func_3c3c:: +; PlayDefaultSong in TCG1 +StubbedPlayDefaultSong:: ret Func_3c3d:: farcall $7, $5ef1 ret -Func_3c42:: +ResetAnimationQueue:: push af call FinishQueuedAnimations farcall Func_1dfb9 @@ -2260,7 +2264,12 @@ FinishQueuedAnimations:: pop af ret -Func_3c70:: +; plays duel animation +; the animations are loaded to a buffer +; and played in order, so they can be stacked +; input: +; - a = animation index +PlayDuelAnimation:: ld [$dce2], a call Func_3c77 ret @@ -2274,7 +2283,9 @@ Func_3c77:: call BankswitchROM ret -Func_3c86:: +; return nc if wActiveScreenAnim, wd4c0, and wAnimationQueue[] are all equal to $ff +; nc means no animation is playing (or animation(s) has/have ended) +CheckAnyAnimationPlaying:: farcall $7, $6420 scf ret nz @@ -2400,13 +2411,13 @@ Func_3d3a:: call SetVolume ret -Func_3d3e:: +WaitForSongToFinish:: push af -.asm_3d3f +.wait call DoFrame call AssertSongFinished or a - jr nz, .asm_3d3f + jr nz, .wait pop af ret diff --git a/src/hram.asm b/src/hram.asm index 4eadf27..31f62d9 100644 --- a/src/hram.asm +++ b/src/hram.asm @@ -86,7 +86,15 @@ hTempCardIndex_ff9f:: ; ffa1 hTemp_ffa0:: ; ffa2 ds $1 - ds $10 +; a PLAY_AREA_* constant (0: arena card, 1-5: bench card) +hTempPlayAreaLocation_ffa1:: ; ffa3 + ds $1 + +; $ff-terminated list of cards to be discarded upon retreat +hTempRetreatCostCards:: ; ffa4 + ds $6 + + ds $9 ; hffa8 through hffbb belong to the text engine hffa8:: ; ffb3 diff --git a/src/layout.link b/src/layout.link index 4b8d3d2..b4c90d7 100644 --- a/src/layout.link +++ b/src/layout.link @@ -40,6 +40,8 @@ ROMX $03 "Bank 3" ROMX $04 "Bank 4" +ROMX $05 + "Bank 5" ROMX $06 "Bank 6" ROMX $07 @@ -225,8 +227,8 @@ WRAM0 "WRAM0 Serial Transfer" org $cbda "WRAM0 Duels 2" - org $cc29 - "WRAM0 Duels 2@cc29" + org $cc21 + "WRAM0 Duels 2@cc21" org $cd5b "WRAM0 2" WRAMX 1 diff --git a/src/macros/credits_commands.asm b/src/macros/credits_commands.asm index bfbae6f..51f5490 100644 --- a/src/macros/credits_commands.asm +++ b/src/macros/credits_commands.asm @@ -84,7 +84,7 @@ MACRO credits_show_set db $00, $00 ENDM -; \1 = ID +; \1 = NPC_* constant ; \2 = x ; \3 = y ; \4 = portrait variant diff --git a/src/macros/data.asm b/src/macros/data.asm index 420748f..704b0ea 100644 --- a/src/macros/data.asm +++ b/src/macros/data.asm @@ -54,7 +54,10 @@ MACRO textpointer ENDM MACRO tx +REPT _NARG dw \1_ + SHIFT +ENDR ENDM MACRO gfx_ptr diff --git a/src/macros/wram.asm b/src/macros/wram.asm index c8336b4..a0366ed 100644 --- a/src/macros/wram.asm +++ b/src/macros/wram.asm @@ -85,6 +85,137 @@ MACRO deck_struct \1Cards:: ds DECK_COMPRESSED_SIZE ENDM +MACRO duel_vars + ASSERT (LOW(@) == 0), "must be aligned to $100" + +; 60-byte array that indicates where each of the 60 cards is. +; $00 - deck +; $01 - hand +; $02 - discard pile +; $08 - prize +; $10 - arena (active pokemon or a card attached to it) +; $1X - bench (where X is bench position from 1 to 5) +\1CardLocations:: ds DECK_SIZE + +; deck indexes of the up to 6 cards placed as prizes +\1PrizeCards:: ds $6 + +; deck indexes of the cards that are in the duelist's hand +\1Hand:: ds DECK_SIZE + +; 60-byte array that maps each card to its position in the deck or anywhere else +; This array is initialized to 00, 01, 02, ..., 59, until deck is shuffled. +; Cards in the discard pile go first, cards still in the deck go last, and others go in-between. +\1DeckCards:: ds DECK_SIZE + +; Stores x = (60 - deck remaining cards). +; The first x cards in the \1DeckCards array are no longer in the drawable deck this duel. +; The top card of the duelist's deck is at \1DeckCards + [\1NumberOfCardsNotInDeck]. +\1NumberOfCardsNotInDeck:: ds $1 + +; Deck index of the card that is in duelist's side of the field +; -1 indicates no pokemon +\1ArenaCard:: ds $1 + +; Deck indexes of the cards that are in duelist's bench, plus an $ff (-1) terminator +; -1 indicates no pokemon +\1Bench:: ds MAX_BENCH_POKEMON + 1 + +\1ArenaCardFlags:: ds $1 + + ds $5 + +\1ArenaCardHP:: ds $1 +\1Bench1CardHP:: ds $1 +\1Bench2CardHP:: ds $1 +\1Bench3CardHP:: ds $1 +\1Bench4CardHP:: ds $1 +\1Bench5CardHP:: ds $1 +\1ArenaCardStage:: ds $1 +\1Bench1CardStage:: ds $1 +\1Bench2CardStage:: ds $1 +\1Bench3CardStage:: ds $1 +\1Bench4CardStage:: ds $1 +\1Bench5CardStage:: ds $1 + +; changed type from Venomoth's Shift Pokemon Power +; if bit 7 == 1, then bits 0-3 override the Pokemon's actual color +\1ArenaCardChangedType:: ds $1 +\1Bench1CardChangedType:: ds $1 +\1Bench2CardChangedType:: ds $1 +\1Bench3CardChangedType:: ds $1 +\1Bench4CardChangedType:: ds $1 +\1Bench5CardChangedType:: ds $1 + +\1ArenaCardAttachedDefender:: ds $1 +\1Bench1CardAttachedDefender:: ds $1 +\1Bench2CardAttachedDefender:: ds $1 +\1Bench3CardAttachedDefender:: ds $1 +\1Bench4CardAttachedDefender:: ds $1 +\1Bench5CardAttachedDefender:: ds $1 + +\1ArenaCardAttachedPluspower:: ds $1 +\1Bench1CardAttachedPluspower:: ds $1 +\1Bench2CardAttachedPluspower:: ds $1 +\1Bench3CardAttachedPluspower:: ds $1 +\1Bench4CardAttachedPluspower:: ds $1 +\1Bench5CardAttachedPluspower:: ds $1 + +\1ArenaCardFoodCounters:: ds $1 +\1Bench1FoodCounters:: ds $1 +\1Bench2FoodCounters:: ds $1 +\1Bench3FoodCounters:: ds $1 +\1Bench4FoodCounters:: ds $1 +\1Bench5FoodCounters:: ds $1 + +\1ArenaCardStatus:: ds $1 +\1ArenaCardSubstatus1:: ds $1 +\1ArenaCardSubstatus2:: ds $1 + +; changed weakness from Conversion 1 +\1ArenaCardChangedWeakness:: ds $1 +; changed resistance from Conversion 2 +\1ArenaCardChangedResistance:: ds $1 + +\1ArenaCardSubstatus3:: ds $1 + +; each bit represents a prize that this duelist can draw (1 = not drawn ; 0 = drawn) +\1Prizes:: ds $1 + +\1NumberOfCardsInDiscardPile:: ds $1 +\1NumberOfCardsInHand:: ds $1 + +; Pokemon cards in arena + bench +\1NumberOfPokemonInPlayArea:: ds $1 + +; $00 - player +; $01 - link +; other - AI controlled +\1DuelistType:: ds $1 + +; if under the effects of amnesia, which attack (0 or 1) can't be used +\1ArenaCardDisabledAttackIndex:: ds $1 + +; damage taken the last time the opponent attacked (0 if no damage) +\1ArenaCardLastTurnDamage:: ds $2 + +; status condition received the last time the opponent attacked (0 if none) +\1ArenaCardLastTurnStatus:: ds $1 + +; substatus2 that the opponent card got last turn +\1ArenaCardLastTurnSubstatus2:: ds $1 + +; indicates color of weakness that was changed +; for this card last turn +\1ArenaCardLastTurnChangeWeak:: ds $1 + +; stores an effect that was used on the Arena card last turn. +; see LAST_TURN_EFFECT_* constants. +\1ArenaCardLastTurnEffect:: ds $1 + +\1Unkfe:: ds $2 +ENDM + MACRO sprite_anim_struct \1Unk0:: ds 1 \1Unk1:: ds 1 diff --git a/src/main.asm b/src/main.asm index fdb4a9c..63e5240 100644 --- a/src/main.asm +++ b/src/main.asm @@ -19,6 +19,9 @@ INCLUDE "engine/bank04.asm" SECTION "Scenes", ROMX[$6eb9], BANK[$4] INCLUDE "engine/scenes.asm" +SECTION "Bank 5", ROMX +INCLUDE "engine/bank05.asm" + SECTION "Bank 6", ROMX INCLUDE "engine/bank06.asm" diff --git a/src/sram.asm b/src/sram.asm index 72d58a6..7245af9 100644 --- a/src/sram.asm +++ b/src/sram.asm @@ -18,9 +18,10 @@ sTextSpeed:: ; a006 s0a007:: ; a007 ds $1 +s0a008:: ; a008 ds $1 -s0a009:: ; a009 +sSkipDelayAllowed:: ; a009 ds $1 sClearedGame:: ; a00a @@ -37,8 +38,12 @@ sTextBoxFrameColor:: ; a00c sPlayerName:: ; a010 ds NAME_BUFFER_LENGTH -s0a020:: ; a020 - ds $4 +sTotalDuelCounter:: ; a020 + ds $2 + +; number of link battles the player has played +sLinkDuelCounter:: ; a022 + ds $2 ds $dc @@ -84,11 +89,11 @@ sCardAndDeckSaveDataEnd:: ; saved data of the current duel, including a two-byte checksum ; see SaveDuelDataToDE -sSavedDuel:: ; bb00 +sCurrentDuel:: ; bb00 ds $1 -sSavedDuelChecksum:: ; bb01 +sCurrentDuelChecksum:: ; bb01 ds $3 -sSavedDuelData:: ; bb04 +sCurrentDuelData:: ; bb04 ds $352 SECTION "SRAM1", SRAM diff --git a/src/wram.asm b/src/wram.asm index 96ad1d9..f10882b 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -50,13 +50,8 @@ SECTION "WRAM0 Duels 1", WRAM0 UNION -wPlayerDuelVariables:: ; c200 - - ds $100 - -wOpponentDuelVariables:: ; c300 - - ds $100 +wPlayerDuelVariables:: duel_vars wPlayer ; c200 +wOpponentDuelVariables:: duel_vars wOpponent ; c300 NEXTU @@ -352,6 +347,9 @@ wSerialRecvBuf:: ; cb9f wSerialEnd:: ; cbbf +; In a duel, the main menu current or last selected menu item +; From 0 to 5: Hand, Attack, Check, Pkmn Power, Retreat, Done +wCurrentDuelMenuItem:: ; cbbf ds $1 ; When we're viewing a card's information, the page we are currently at. @@ -362,6 +360,10 @@ wSerialEnd:: ; cbbf wCardPageNumber:: ; cbc0 ds $1 +; how many selectable items are in a play area screen. used to set wNumMenuItems +; in order to navigate through a play area screen. this becomes the number of bench +; Pokemon cards if wExcludeArenaPokemon is 1, and that number plus 1 if it's 0. +wNumPlayAreaItems:: ; cbc1 ds $1 ; selects a PLAY_AREA_* slot in order to display information related to it. used by functions @@ -380,22 +382,90 @@ wCurPlayAreaY:: ; cbc3 ; current Y coordinate where some play area information is being printed at. used by functions ; such as PrintPlayAreaCardLocation, PrintPlayAreaCardInformation and PrintPlayAreaCardHeader wHUDEnergyAndHPBarsY:: ; cbc3 + +wPracticeDuelTextY:: ; cbc3 ds $1 - ds $6 +; selected bench slot (1-5, that is, a PLAY_AREA_BENCH_* constant) +wBenchSelectedPokemon:: ; cbc4 + ds $1 + +; used by CheckIfEnoughEnergiesToRetreat and DisplayRetreatScreen +wEnergyCardsRequiredToRetreat:: ; cbc5 + ds $1 + +wNumRetreatEnergiesSelected:: ; cbc6 + ds $1 + + ds $1 + +; when you're in a duel submenu like the cards in your hand and you press A, +; the following two addresses keep track of which item was selected by the cursor +wSelectedDuelSubMenuItem:: ; cbc8 + ds $1 + + ds $1 ; CARDPAGETYPE_PLAY_AREA or CARDPAGETYPE_NOT_PLAY_AREA ; some of the elements displayed in a card page change depending on which value wCardPageType:: ; cbca ds $1 - ds $5 +; when processing or displaying the play area Pokemon cards of a duelist, +; whether to account for only the benched Pokemon ($01) or also the arena Pokemon ($00). +wExcludeArenaPokemon:: ; cbcb + ds $1 + +wPlayAreaScreenLoaded:: ; cbcc + ds $1 + +; determines what to do when player presses the Select button +; while viewing the Play Area: +; - if $0 or $2: no action +; - if $1: menu is accessible where player can examine Hand or other screens +; $2 is reserved for Func_4597 +wPlayAreaSelectAction:: ; cbcd + ds $1 + +; low byte of the address of the next slot in the hTempRetreatCostCards array to be used +wTempRetreatCostCardsPos:: ; cbce + ds $1 + +; in a card list, which keys (among START and A_BUTTON) do not open the item selection +; menu when a card is selected, directly "submitting" the selected card instead. +wNoItemSelectionMenuKeys:: ; cbcf + ds $1 ; when viewing a card page, which keys (among B_BUTTON, D_UP, and D_DOWN) will exit the page, ; either to go back to the previous menu or list, or to load the card page of the card above/below it wCardPageExitKeys:: ; cbd0 ds $1 +; used to store function pointer for printing card order +; in card list reordering screen. +wPrintSortNumberInCardListPtr:: ; cbd1 + ds $2 + +; in the hand or discard pile card screen, id of the text printed in the bottom-left box +wCardListInfoBoxText:: ; cbd3 + ds $2 + +; in the hand or discard pile card screen, id of the text printed as the header title +wCardListHeaderText:: ; cbd5 + ds $2 + +; when selecting an item of a list of cards which type of menu shows up. +; PLAY_CHECK, SELECT_CHECK, or $00 for none. +wCardListItemSelectionMenuType:: ; cbd7 + ds $1 + +; flag indicating whether a list of cards should be sorted by ID +wSortCardListByID:: ; cbd8 + ds $1 + +wAttachedEnergyMenuPlayAreaLocation:: ; cbd9 + ds $1 + SECTION "WRAM0 Duels 2", WRAM0 wOppRNG1:: ; cbda @@ -408,43 +478,122 @@ wOppRNG1:: ; cbda wDuelReturnAddress:: ; cbdd ds $2 - ds $3 +; if non-zero, duel menu input is not checked +wDebugSkipDuelMenuInput:: ; cbdf + ds $1 + + ds $2 ; temporarily stores 8 bytes for serial send/recv. ; used by SerialSend8Bytes and SerialRecv8Bytes wTempSerialBuf:: ; cbe2 ds $8 - ds $13 - -wcbfd:: ; cbfd ds $1 +wcbeb:: ; cbeb + ds $1 + +wAttachedEnergyMenuDenominator:: ; cbec + ds $1 + +wAttachedEnergyMenuNumerator:: ; cbed + ds $1 + +; text ID to show in the Attached Energy screen +wAttachedEnergyMenuTextID:: ; cbee ds $2 +; used by TurnDuelistTakePrizes to store the remaining Prizes, so that if more than that +; amount would be taken, only the remaining amount is taken +wTempNumRemainingPrizeCards:: ; cbf0 + ds $1 + +; if FALSE, player is placing initial arena pokemon +; if TRUE, player is placing initial bench pokemon +wPlacingInitialBenchPokemon:: ; cbf1 + ds $1 + +; during a practice duel, identifies an entry of PracticeDuelActionTable +wPracticeDuelAction:: ; cbf2 + ds $1 + +wDuelMainSceneSelectHotkeyAction:: ; cbf3 + ds $1 + +wPracticeDuelTurn:: ; cbf4 + ds $1 + +wcbf5:: ; cbf5 + ds $1 + + ds $6 + +; used when opening the card page of an attack when attacking, +; serving as an index for AttackPageDisplayPointerTable. +; see ATTACKPAGE_* constants +wAttackPageNumber:: ; cbfc + ds $1 + +; the value of hWhoseTurn gets loaded here at the beginning of each duelist's turn. +; more reliable than hWhoseTurn, as hWhoseTurn may change temporarily in order to handle status +; conditions or other events of the non-turn duelist. used mostly between turns (to check which +; duelist's turn just finished), or to restore the value of hWhoseTurn at some point. +wWhoseTurn:: ; cbfd + ds $1 + +; number of turns taken by both players +wDuelTurns:: ; cbfe + ds $1 + +; used to signal that the current duel has finished, not to be mistaken with wDuelResult +; 0 = no one has won duel yet +; 1 = player whose turn it is has won the duel +; 2 = player whose turn it is has lost the duel +; 3 = duel ended in a draw (start sudden death match) +wDuelFinished:: ; cbff + ds $1 + ; current duel is a [wDuelInitialPrizes]-prize match wDuelInitialPrizes:: ; cc00 ds $1 -wcc01:: ; cc01 +; maximum number of Pokémon in Play Area +; normally it's 6, but when dueling with the +; Small Bench rule, it's reduced to 4 +wMaxNumPlayAreaPokemon:: ; cc01 ds $1 ; a DUELTYPE_* constant. note that for a practice duel, wIsPracticeDuel must also be set to $1 wDuelType:: ; cc02 ds $1 - ds $3 +wcc03:: ; cc03 + ds $1 + +wAlreadyPlayedEnergy:: ; cc04 + ds $1 + +; set to 1 if the confusion check coin toss in AttemptRetreat is heads +wGotHeadsFromConfusionCheckDuringRetreat:: ; cc05 + ds $1 wGoopGasAttackActive:: ; cc06 ds $1 - ds $2 +wcc07:: ; cc07 + ds $1 + +; DUELIST_TYPE_* of the turn holder +wDuelistType:: ; cc08 + ds $1 ; this holds the current opponent's deck minus 2 (that is, a *_DECK_ID constant), ; in order to account for the two unused pointers at the beginning of DeckPointers. wOpponentDeckID:: ; cc09 ds $1 +wcc0f:: ; cc0a ds $1 ; index (0-1) of the attack or Pokemon Power being used by the player's arena card @@ -470,7 +619,7 @@ wSpecialRule:: ; cc10 ds $1 -wcc12:: ; cc12 +wOpponentNPCID:: ; cc12 ds $1 ; text id of the opponent's name @@ -480,16 +629,29 @@ wOpponentName:: ; cc13 wcc15:: ; cc15 ds $1 -wcc16:: ; cc16 +wNPCDuelDeckID:: ; cc16 ds $1 -wcc17:: ; cc17 +; song played during a duel +wDuelTheme:: ; cc17 ds $1 wcc18:: ; cc18 ds $1 -SECTION "WRAM0 Duels 2@cc29", WRAM0 +wcc19:: ; cc19 + ds $1 + +wcc1a:: ; cc1a + ds $1 + +wcc1b:: ; cc1b + ds $1 + +SECTION "WRAM0 Duels 2@cc21", WRAM0 + +wAttackEnergyCost:: ; cc21 + ds NUM_TYPES ; holds the energies attached to a given pokemon card. 1 byte for each of the ; 8 energy types (includes the unused one that shares byte with the colorless energy) @@ -535,7 +697,15 @@ wTempTurnDuelistCardID:: ; ccd4 wTempNonTurnDuelistCardID:: ; ccd6 ds $2 - ds $3 +wccd8:: ; ccd8 + ds $1 + +wccd9:: ; ccd9 + ds $1 + +; the status condition of the defending Pokemon is loaded here after an attack +wccc5:: ; ccda + ds $1 ; *_ATTACK constants for selected attack ; 0 for the first attack (or PKMN Power) @@ -573,7 +743,11 @@ wEffectFunctionsFeedback:: ; cce3 wIsDamageToSelf:: ; ccfb ds $1 - ds $2 +wccfc:: ; ccfc + ds $1 + +wDuelFinishParam:: ; cce8 + ds $1 wOpponentDeckName:: ; ccfe ds $2 @@ -614,9 +788,12 @@ wNoEffectFromWhichStatus:: ; cd06 wDeckSize:: ; cd07 ds $1 -wcd08:: ; cd08 +; when non-0, allows the player to skip some delays during a duel by pressing B. +; value read from sSkipDelayAllowed. probably only used for debugging. +wSkipDelayAllowed:: ; cd08 ds $1 +wcd09:: ; cd09 ds $1 wcd0a:: ; cd0a @@ -640,18 +817,42 @@ wcd0f:: ; cd0f wcd10:: ; cd10 ds $4 - ds $2 +wcd14:: ; cd14 + ds $1 + +wcd15:: ; cd15 + ds $1 wcd16:: ; cd16 ds $1 wcd17:: ; cd17 - ds $3 - -wcd1a:: ; cd1a ds $1 - ds $9 +wcd18:: ; cd18 + ds $1 + +; when non-0, AIMakeDecision doesn't wait 60 frames and print DuelistIsThinkingText +wSkipDuelistIsThinkingDelay:: ; cd19 + ds $1 + +; return address for when the Link Opponent has +; made a decision on his turn, so that the duel continues +wLinkOpponentTurnReturnAddress:: ; cd1a + ds $2 + +wNumCardsTryingToDraw:: ; cd1c + ds $1 + +; number of cards being drawn in order to animate the number of cards in +; the hand and in the deck in the draw card screen +wNumCardsBeingDrawn:: ; cd1d + ds $1 + +wOpponentTurnEnded:: ; cd1e + ds $1 + + ds $5 wDeckDiagnosisTextIDsPtr:: ; cd24 ds $2 @@ -817,7 +1018,11 @@ wTextMaxLength:: ; cd75 wUppercaseHalfWidthLetters:: ; cd76 ds $1 - ds $2 +wcd77:: ; cd77 + ds $1 + +wcd78:: ; cd78 + ds $1 ; During a duel, this is always $b after the first attack. ; $b is the bank where the functions associated to card or effect commands are. @@ -931,6 +1136,7 @@ wSerialDataPtr:: ; cdf6 wTempCardID_ce08:: ; ce08 ds $2 +wce0a:: ; ce0a ds $2 wce0c:: ; ce0c @@ -1164,6 +1370,9 @@ wd0c1:: ; d0c1 wTransitionTablePtr:: ; d0c2 ds $2 +; same as wDuelInitialPrizes but with upper 2 bits set +wDuelInitialPrizesUpperBitsSet:: ; d0c4 + wd0c4:: ; d0c4 ds $1 @@ -1191,7 +1400,10 @@ wGlossaryMenu:: ; d0d1 wd0d2:: ; d0d2 ds $1 - ds $6 +wd0d3:: ; d0d3 + ds $1 + + ds $5 ; buffer to store data that will be sent/received through IR wIRDataBuffer:: ; d0d9 @@ -2241,11 +2453,28 @@ wdc60:: ; dc60 wdce2:: ; dce2 ds $1 - ds $2 - -wdce5:: ; dce5 +; used to know what coordinate offsets to use to place animations +; for use in GetAnimCoordsAndFlags +; DUEL_ANIM_SCREEN_MAIN_SCENE = main scene +; DUEL_ANIM_SCREEN_PLAYER_PLAY_AREA = Player's Play Area screen +; DUEL_ANIM_SCREEN_OPP_PLAY_AREA = Opponent's Play Area screen +wDuelAnimationScreen:: ; dce3 ds $1 +; which side to play animation +; uses PLAYER_TURN and OPPONENT_TURN constants +wDuelAnimDuelistSide:: ; dce4 + ds $1 + +; used in GetAnimCoordsAndFlags to determine +; what coordinates to draw the animation in. +; e.g. used to know what Play Area card +; to draw a hit animation in the Play Area screen. +wDuelAnimLocationParam:: ; dce5 + ds $1 + +; damage value to display with animation +wDuelAnimDamage:: ; dce6 ds $2 wdce8:: ; dce8 @@ -2268,7 +2497,7 @@ SECTION "WRAM1@dd02", WRAMX wDuelResult:: ; dd02 ds $1 -wdd03:: ; dd03 +wDuelStartTheme:: ; dd03 ds $1 wdd04:: ; dd04