diff --git a/.gitignore b/.gitignore index 0acf0dab9..f45da18f0 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ prefabs.json .vscode/*.* *.js *.sym +src/data/map_group_count.h diff --git a/Makefile b/Makefile index ffcf1d162..82ede08b3 100644 --- a/Makefile +++ b/Makefile @@ -307,7 +307,7 @@ mostlyclean: tidynonmodern tidymodern tidycheck rm -f $(MID_SUBDIR)/*.s find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.rl' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} + rm -f $(DATA_ASM_SUBDIR)/layouts/layouts.inc $(DATA_ASM_SUBDIR)/layouts/layouts_table.inc - rm -f $(DATA_ASM_SUBDIR)/maps/connections.inc $(DATA_ASM_SUBDIR)/maps/events.inc $(DATA_ASM_SUBDIR)/maps/groups.inc $(DATA_ASM_SUBDIR)/maps/headers.inc + rm -f $(DATA_ASM_SUBDIR)/maps/connections.inc $(DATA_ASM_SUBDIR)/maps/events.inc $(DATA_ASM_SUBDIR)/maps/groups.inc $(DATA_ASM_SUBDIR)/maps/headers.inc $(DATA_SRC_SUBDIR)/map_group_count.h find $(DATA_ASM_SUBDIR)/maps \( -iname 'connections.inc' -o -iname 'events.inc' -o -iname 'header.inc' \) -exec rm {} + rm -f $(AUTO_GEN_TARGETS) @$(MAKE) clean -C libagbsyscall diff --git a/asm/macros/event.inc b/asm/macros/event.inc index b4c36bea3..5d1393363 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1679,6 +1679,38 @@ .2byte \quantity .endm + .macro _dynmultichoice left:req, top:req, ignoreBPress:req, maxBeforeScroll:req, shouldSort:req, initialSelected:req, callbacks:req argv:vararg + .byte 0xe3 + .2byte \left + .2byte \top + .byte \ignoreBPress + .byte \maxBeforeScroll + .byte \shouldSort + .2byte \initialSelected + .byte \callbacks + .byte (.Ldynmultichoice_\@_2 - .Ldynmultichoice_\@_1) / 4 +.Ldynmultichoice_\@_1: + .4byte \argv +.Ldynmultichoice_\@_2: + .endm + + @ Displays a multichoice box from which the user can choose a selection, and blocks script execution until a selection is made. + @ Lists of options are provided in argv. + @ If ignoreBPress is set to a non-zero value, then the user will not be allowed to back out of the multichoice with the B button. + .macro dynmultichoice left:req, top:req, ignoreBPress:req, maxBeforeScroll:req, initialSelected:req, callbacks:req argv:vararg + _dynmultichoice \left, \top, \ignoreBPress, \maxBeforeScroll, FALSE, \initialSelected, \callbacks, \argv + .endm + + .macro dynmultipush name:req, id:req + .byte 0xe4 + .4byte \name + .2byte \id + .endm + + .macro dynmultistack left:req, top:req, ignoreBPress:req, maxBeforeScroll:req, shouldSort:req, initialSelected:req, callbacks:req + _dynmultichoice \left, \top, \ignoreBPress, \maxBeforeScroll, \shouldSort, \initialSelected, \callbacks, NULL + .endm + @ Supplementary @@ -1934,3 +1966,55 @@ .2byte \slot .endm + @ Sets VAR_RESULT to one of the arguments (via setorcopyvar). + .macro randomelement element:req, elements:vararg + .set _randomelement_n, 0 + .irp el, \element, \elements + .set _randomelement_n, _randomelement_n + 1 + .endr + random _randomelement_n + + .set _randomelement_n, 0 + .irp el, \element, \elements + goto_if_ne VAR_RESULT, _randomelement_n, 1f + setorcopyvar VAR_RESULT, \el + goto 2f + 1: + .set _randomelement_n, _randomelement_n + 1 + .endr + 2: + .endm + + @ Sets VAR_RESULT to TRUE with probability 'percent', and FALSE + @ with probability '100% - percent'. + .macro randompercentage percent:req + random 100 + goto_if_lt VAR_RESULT, \percent, 1f + setvar VAR_RESULT, FALSE + goto 2f + 1: + setvar VAR_RESULT, TRUE + 2: + .endm + + @ Inflicts \status1 to the Pokémon in \slot. + @ If \slot is greater or equal than PARTY_SIZE, the status is inflicted on each of the Player's Pokémon. + .macro setstatus1 status1:req, slot:req + callnative Script_SetStatus1 + .2byte \status1 + .2byte \slot + .endm + + @ Sets VAR_RESULT to the Pokémon in \slot's Tera Type + .macro checkteratype slot:req + callnative CheckTeraType + .2byte \slot + .endm + + @ Sets the Pokémon in \slot's Tera Type + .macro setteratype type:req, slot:req + callnative SetTeraType + .byte \type + .2byte \slot + .endm + diff --git a/charmap.txt b/charmap.txt index 7898fb519..66b8b5393 100644 --- a/charmap.txt +++ b/charmap.txt @@ -78,6 +78,7 @@ SUPER_RE = A0 '?' = AC '.' = AD '-' = AE +'_' = AE '·' = AF '…' = B0 '“' = B1 diff --git a/constants/constants.inc b/constants/constants.inc index fd9715170..039f6b6a6 100644 --- a/constants/constants.inc +++ b/constants/constants.inc @@ -1,3 +1,7 @@ .include "constants/gba_constants.inc" .include "constants/misc_constants.inc" - .include "constants/version.inc" + @ .include "constants/version.inc" + + .set FALSE, 0 + .set TRUE, 1 + .set NULL, 0 diff --git a/constants/version.inc b/constants/version.inc deleted file mode 100644 index 55eac837d..000000000 --- a/constants/version.inc +++ /dev/null @@ -1,6 +0,0 @@ - .ifdef FIRERED - .equiv GAME_VERSION, 4 - .else - .equiv GAME_VERSION, 5 - .endif - diff --git a/data/event_scripts.s b/data/event_scripts.s index cb325cc3a..ade90fa14 100644 --- a/data/event_scripts.s +++ b/data/event_scripts.s @@ -1,3 +1,4 @@ +#include "config.h" #include "constants/global.h" #include "constants/flags.h" #include "constants/event_objects.h" @@ -41,8 +42,7 @@ #include "constants/mystery_gift.h" .include "asm/macros.inc" .include "asm/macros/event.inc" - .set FALSE, 0 - .set TRUE, 1 + .include "constants/constants.inc" .section script_data, "aw", %progbits @@ -807,6 +807,8 @@ gStdScriptsEnd:: .include "data/scripts/std_msgbox.inc" .include "data/scripts/trainer_battle.inc" + + .include "data/scripts/debug.inc" @ Unused Text_WouldYouLikeToMixRecords:: diff --git a/data/maps/CeladonCity_GameCorner/scripts.inc b/data/maps/CeladonCity_GameCorner/scripts.inc index a0e4e67b4..b169961a6 100644 --- a/data/maps/CeladonCity_GameCorner/scripts.inc +++ b/data/maps/CeladonCity_GameCorner/scripts.inc @@ -247,14 +247,14 @@ CeladonCity_GameCorner_EventScript_SlotMachine:: msgbox CeladonCity_GameCorner_Text_SlotMachineWantToPlay, MSGBOX_YESNO goto_if_eq VAR_RESULT, NO, CeladonCity_GameCorner_EventScript_DontPlaySlotMachine setfieldeffectargument 0, OBJ_EVENT_ID_PLAYER -.ifdef BUGFIX +#ifdef BUGFIX setfieldeffectargument 1, MAP_NUM(CELADON_CITY_GAME_CORNER) setfieldeffectargument 2, MAP_GROUP(CELADON_CITY_GAME_CORNER) -.else +#else @ Map num/group were provided in the wrong order setfieldeffectargument 1, MAP_GROUP(CELADON_CITY_GAME_CORNER) setfieldeffectargument 2, MAP_NUM(CELADON_CITY_GAME_CORNER) -.endif +#endif dofieldeffect FLDEFF_SMILEY_FACE_ICON waitfieldeffect FLDEFF_SMILEY_FACE_ICON specialvar VAR_RESULT, GetRandomSlotMachineId diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc new file mode 100644 index 000000000..9fa2f4e73 --- /dev/null +++ b/data/scripts/debug.inc @@ -0,0 +1,424 @@ +.if DEBUG_OVERWORLD_MENU == TRUE +Debug_MessageEnd: + waitmessage + waitbuttonpress + releaseall + end + +Debug_ShowFieldMessageStringVar4:: + special ShowFieldMessageStringVar4 + goto Debug_MessageEnd + +Debug_CheatStart:: +@ setflag FLAG_SYS_POKEMON_GET +@ setflag FLAG_RESCUED_BIRCH +@ setflag FLAG_HIDE_ROUTE_101_BIRCH_ZIGZAGOON_BATTLE +@ setflag FLAG_ADVENTURE_STARTED +@ clearflag FLAG_HIDE_LITTLEROOT_TOWN_BIRCHS_LAB_BIRCH +@ setflag FLAG_HIDE_ROUTE_101_BIRCH_STARTERS_BAG +@ setvar VAR_BIRCH_LAB_STATE, 2 +@ setvar VAR_ROUTE101_STATE, 3 +@ givemon SPECIES_TREECKO, 20, ITEM_NONE +@ givemon SPECIES_TORCHIC, 20, ITEM_NONE +@ givemon SPECIES_MUDKIP, 20, ITEM_NONE +@ setflag FLAG_SYS_POKEDEX_GET +@ special SetUnlockedPokedexFlags +@ setflag FLAG_RECEIVED_POKEDEX_FROM_BIRCH +@ setvar VAR_CABLE_CLUB_TUTORIAL_STATE, 2 +@ setflag FLAG_SYS_NATIONAL_DEX +@ special EnableNationalPokedex +@ setflag FLAG_RECEIVED_RUNNING_SHOES +@ setflag FLAG_SYS_B_DASH +@ setvar VAR_LITTLEROOT_TOWN_STATE, 4 @ 4: Received Running Shoes +@ setvar VAR_LITTLEROOT_INTRO_STATE, 7 @ 7: Told to go meet rival +@ setvar VAR_LITTLEROOT_HOUSES_STATE_BRENDAN, 2 @ 2: Met Rival's Mom (and is corresponding gender) +@ setvar VAR_LITTLEROOT_HOUSES_STATE_MAY, 2 @ 2: Met Rival's Mom (and is corresponding gender) +@ setvar VAR_LITTLEROOT_RIVAL_STATE, 4 @ 4: Received Pokedex +@ setflag FLAG_RECEIVED_BIKE +@ additem ITEM_ACRO_BIKE +@ setvar VAR_BRINEY_HOUSE_STATE, 1 +@ setvar VAR_ROUTE116_STATE, 2 +@ setflag FLAG_HIDE_ROUTE_116_MR_BRINEY +@ setflag FLAG_BADGE01_GET +@ setflag FLAG_BADGE02_GET +@ setflag FLAG_BADGE03_GET +@ setflag FLAG_BADGE04_GET +@ setflag FLAG_BADGE05_GET +@ setflag FLAG_BADGE06_GET +@ setflag FLAG_BADGE07_GET +@ setflag FLAG_BADGE08_GET +@ setflag FLAG_VISITED_LITTLEROOT_TOWN +@ setflag FLAG_VISITED_OLDALE_TOWN +@ setflag FLAG_VISITED_DEWFORD_TOWN +@ setflag FLAG_VISITED_LAVARIDGE_TOWN +@ setflag FLAG_VISITED_FALLARBOR_TOWN +@ setflag FLAG_VISITED_VERDANTURF_TOWN +@ setflag FLAG_VISITED_PACIFIDLOG_TOWN +@ setflag FLAG_VISITED_PETALBURG_CITY +@ setflag FLAG_VISITED_SLATEPORT_CITY +@ setflag FLAG_VISITED_MAUVILLE_CITY +@ setflag FLAG_VISITED_RUSTBORO_CITY +@ setflag FLAG_VISITED_FORTREE_CITY +@ setflag FLAG_VISITED_LILYCOVE_CITY +@ setflag FLAG_VISITED_MOSSDEEP_CITY +@ setflag FLAG_VISITED_SOOTOPOLIS_CITY +@ setflag FLAG_VISITED_EVER_GRANDE_CITY +@ setflag FLAG_LANDMARK_POKEMON_LEAGUE +@ setflag FLAG_LANDMARK_BATTLE_FRONTIER +@ clearflag FLAG_HIDE_BRINEYS_HOUSE_MR_BRINEY +@ clearflag FLAG_HIDE_BRINEYS_HOUSE_PEEKO +@ release + end + +Debug_FlagsNotSetOverworldConfigMessage:: + message Debug_FlagsNotSetOverworldConfigMessage_Text + goto Debug_MessageEnd + +Debug_FlagsNotSetOverworldConfigMessage_Text: + .string "Feature unavailable!\n" + .string "Please define a usable flag in:\l" + .string "'include/config/overworld.h'!$" + +Debug_FlagsNotSetBattleConfigMessage:: + message Debug_FlagsNotSetBattleConfigMessage_Text + goto Debug_MessageEnd + +Debug_FlagsNotSetBattleConfigMessage_Text: + .string "Feature unavailable!\n" + .string "Please define a usable flag in:\l" + .string "'include/config/battle.h'!$" + +Debug_BoxFilledMessage:: + message Debug_BoxFilledMessage_Text + goto Debug_MessageEnd + +Debug_BoxFilledMessage_Text: + .string "Storage boxes filled!$" + +Debug_EventScript_CheckEVs:: + lockall + getpartysize + goto_if_eq VAR_RESULT, 0, Debug_NoPokemon + special ChoosePartyMon + waitstate + goto_if_ge VAR_0x8004, PARTY_SIZE, Debug_EventScript_CheckEVs_End + callnative Script_GetChosenMonOffensiveEVs + msgbox Debug_EventScript_Text_OffensiveEVs, MSGBOX_DEFAULT + callnative Script_GetChosenMonDefensiveEVs + msgbox Debug_EventScript_Text_DefensiveEVs, MSGBOX_DEFAULT +Debug_EventScript_CheckEVs_End:: + releaseall + end + +Debug_EventScript_Text_OffensiveEVs: + .string "ATK EVs: {STR_VAR_1}, SPATK EVs: {STR_VAR_2}, SPEED EVs: {STR_VAR_3}$" + +Debug_EventScript_Text_DefensiveEVs: + .string "HP EVs: {STR_VAR_1}, DEF EVs: {STR_VAR_2}, SPDEF EVs: {STR_VAR_3}$" + +Debug_EventScript_CheckIVs:: + lockall + getpartysize + goto_if_eq VAR_RESULT, 0, Debug_NoPokemon + special ChoosePartyMon + waitstate + goto_if_ge VAR_0x8004, PARTY_SIZE, Debug_EventScript_CheckIVs_End + callnative Script_GetChosenMonOffensiveIVs + msgbox Debug_EventScript_Text_OffensiveIVs, MSGBOX_DEFAULT + callnative Script_GetChosenMonDefensiveIVs + msgbox Debug_EventScript_Text_DefensiveIVs, MSGBOX_DEFAULT +Debug_EventScript_CheckIVs_End:: + releaseall + end + +Debug_EventScript_Text_OffensiveIVs: + .string "ATK IVs: {STR_VAR_1}, SPATK IVs: {STR_VAR_2}, SPEED IVs: {STR_VAR_3}$" + +Debug_EventScript_Text_DefensiveIVs: + .string "HP IVs: {STR_VAR_1}, DEF IVs: {STR_VAR_2}, SPDEF IVs: {STR_VAR_3}$" + +Debug_EventScript_Script_1:: + release + end + +Debug_EventScript_Script_2:: + release + end + +Debug_EventScript_Script_3:: + release + end + +Debug_EventScript_Script_4:: + release + end + +Debug_EventScript_Script_5:: + release + end + +Debug_EventScript_Script_6:: + release + end + +Debug_EventScript_Script_7:: + release + end + +Debug_EventScript_Script_8:: + release + end + +Debug_CheckSaveBlock:: + callnative CheckSaveBlock1Size + msgbox Debug_SaveBlock1Size, MSGBOX_DEFAULT + callnative CheckSaveBlock2Size + msgbox Debug_SaveBlock2Size, MSGBOX_DEFAULT + @callnative CheckSaveBlock3Size + @msgbox Debug_SaveBlock3Size, MSGBOX_DEFAULT + callnative CheckPokemonStorageSize + msgbox Debug_PokemonStorageSize, MSGBOX_DEFAULT + release + end + +Debug_SaveBlock1Size:: + .string "SaveBlock1 size: {STR_VAR_1}b/{STR_VAR_2}b.\n" + .string "Free space: {STR_VAR_3}b.$" + +Debug_SaveBlock2Size:: + .string "SaveBlock2 size: {STR_VAR_1}b/{STR_VAR_2}b.\n" + .string "Free space: {STR_VAR_3}b.$" + +Debug_SaveBlock3Size:: + .string "SaveBlock3 size: {STR_VAR_1}b/{STR_VAR_2}b.\n" + .string "Free space: {STR_VAR_3}b.$" + +Debug_PokemonStorageSize:: + .string "{PKMN}Storage size: {STR_VAR_1}b/{STR_VAR_2}b.\n" + .string "Free space: {STR_VAR_3}b.$" + +Debug_CheckROMSpace:: + callnative CheckROMSize + msgbox Debug_ROMSize, MSGBOX_DEFAULT + release + end + +Debug_ROMSize:: + .string "ROM size: {STR_VAR_1}MB/32MB.\n" + .string "Free space: {STR_VAR_2}MB.$" + +Debug_HatchAnEgg:: + lockall + getpartysize + goto_if_eq VAR_RESULT, 0, Debug_NoPokemon + special ChoosePartyMon + waitstate + goto_if_ge VAR_0x8004, PARTY_SIZE, Debug_HatchAnEgg_End + specialvar VAR_RESULT, GetPartyMonSpecies + goto_if_ne VAR_RESULT, SPECIES_EGG, DebugScript_HatchAnEgg_CantForceHatch + special EggHatch + waitstate +Debug_HatchAnEgg_End:: + releaseall + end + +Debug_NoPokemon:: + msgbox DebugScript_Text_EmptyParty, MSGBOX_DEFAULT + releaseall + end + +DebugScript_HatchAnEgg_CantForceHatch:: + msgbox DebugScript_HatchAnEgg_Text_NotAnEgg, MSGBOX_DEFAULT + releaseall + end + +DebugScript_Text_EmptyParty:: + .string "You have no Pokémon nor Eggs.$" + +DebugScript_HatchAnEgg_Text_NotAnEgg:: + .string "That's not a Pokémon Egg.$" + +DebugScript_ZeroDaycareMons:: + msgbox DebugText_DaycareNoPokemon, MSGBOX_DEFAULT + releaseall + end + +DebugScript_OneDaycareMons:: + msgbox DebugText_DaycareOnePokemon, MSGBOX_DEFAULT + releaseall + end + +DebugScript_DaycareMonsNotCompatible:: + msgbox DebugText_DaycarePokemonNotCompatible, MSGBOX_DEFAULT + releaseall + end + +DebugText_DaycareNoPokemon: + .string "You have no Pokémon at Daycare.$" + +DebugText_DaycareOnePokemon: + .string "You have only one Pokémon at Daycare.$" + +DebugText_DaycarePokemonNotCompatible: + .string "Your Pokémon at Daycare can't\nhave babies together!$" + +@Debug_ShowExpansionVersion:: +@ callnative BufferExpansionVersion +@ msgbox Debug_ExpansionVersion, MSGBOX_DEFAULT +@ release +@ end + +Debug_ExpansionVersion: + .string "pokeemerald-expansion {STR_VAR_1}$" + +Debug_EventScript_InflictStatus1:: + lockall + getpartysize + goto_if_eq VAR_RESULT, 0, Debug_NoPokemon + dynmultipush Debug_EventScript_InflictStatus1_Text_Single, 0 + dynmultipush Debug_EventScript_InflictStatus1_Text_PartyWide, 1 + dynmultipush Debug_EventScript_InflictStatus1_Text_Close, 2 + dynmultistack 0, 0, FALSE, 3 FALSE, 0, NULL + switch VAR_RESULT + case 0, Debug_EventScript_InflictStatus1_Single + case 1, Debug_EventScript_InflictStatus1_Party + case 2, Debug_EventScript_InflictStatus1_Close +Debug_EventScript_InflictStatus1_Close: + releaseall + end + +Debug_EventScript_InflictStatus1_Single: + special ChoosePartyMon + waitstate + goto_if_ge VAR_0x8004, PARTY_SIZE, Debug_EventScript_InflictStatus1_Close + specialvar VAR_RESULT, GetPartyMonSpecies + goto_if_eq VAR_RESULT, SPECIES_EGG, Debug_EventScript_InflictStatus1_Close + dynmultipush Debug_EventScript_InflictStatus1_Text_Poison, 0 + dynmultipush Debug_EventScript_InflictStatus1_Text_Paralysis, 1 + dynmultipush Debug_EventScript_InflictStatus1_Text_Sleep, 2 + dynmultipush Debug_EventScript_InflictStatus1_Text_Burn, 3 + dynmultipush Debug_EventScript_InflictStatus1_Text_Freeze, 4 + dynmultipush Debug_EventScript_InflictStatus1_Text_Frostbite, 5 + dynmultipush Debug_EventScript_InflictStatus1_Text_Close, 6 + dynmultistack 0, 0, FALSE, 7, FALSE, 0, NULL + switch VAR_RESULT + case 0, Debug_EventScript_InflictStatus1_Single_Poison + case 1, Debug_EventScript_InflictStatus1_Single_Paralysis + case 2, Debug_EventScript_InflictStatus1_Single_Sleep + case 3, Debug_EventScript_InflictStatus1_Single_Burn + case 4, Debug_EventScript_InflictStatus1_Single_Freeze + case 5, Debug_EventScript_InflictStatus1_Single_Frostbite + case 6, Debug_EventScript_InflictStatus1_Close + case SCR_MENU_CANCEL, Debug_EventScript_InflictStatus1_Close + releaseall + end + +Debug_EventScript_InflictStatus1_Single_Poison: + setstatus1 STATUS1_POISON, VAR_0x8004 + releaseall + end + +Debug_EventScript_InflictStatus1_Single_Paralysis: + setstatus1 STATUS1_PARALYSIS, VAR_0x8004 + releaseall + end + +Debug_EventScript_InflictStatus1_Single_Sleep: + setstatus1 STATUS1_SLEEP, VAR_0x8004 + releaseall + end + +Debug_EventScript_InflictStatus1_Single_Burn: + setstatus1 STATUS1_BURN, VAR_0x8004 + releaseall + end + +Debug_EventScript_InflictStatus1_Single_Freeze: + setstatus1 STATUS1_FREEZE, VAR_0x8004 + releaseall + end + +Debug_EventScript_InflictStatus1_Single_Frostbite: + setstatus1 STATUS1_FROSTBITE, VAR_0x8004 + releaseall + end + +Debug_EventScript_InflictStatus1_Party: + dynmultipush Debug_EventScript_InflictStatus1_Text_Poison, 0 + dynmultipush Debug_EventScript_InflictStatus1_Text_Paralysis, 1 + dynmultipush Debug_EventScript_InflictStatus1_Text_Sleep, 2 + dynmultipush Debug_EventScript_InflictStatus1_Text_Burn, 3 + dynmultipush Debug_EventScript_InflictStatus1_Text_Freeze, 4 + dynmultipush Debug_EventScript_InflictStatus1_Text_Frostbite, 5 + dynmultipush Debug_EventScript_InflictStatus1_Text_Close, 6 + dynmultistack 0, 0, FALSE, 7, FALSE, 0, NULL + switch VAR_RESULT + case 0, Debug_EventScript_InflictStatus1_Party_Poison + case 1, Debug_EventScript_InflictStatus1_Party_Paralysis + case 2, Debug_EventScript_InflictStatus1_Party_Sleep + case 3, Debug_EventScript_InflictStatus1_Party_Burn + case 4, Debug_EventScript_InflictStatus1_Party_Freeze + case 5, Debug_EventScript_InflictStatus1_Party_Frostbite + case 6, Debug_EventScript_InflictStatus1_Close + case SCR_MENU_CANCEL, Debug_EventScript_InflictStatus1_Close + releaseall + end + +Debug_EventScript_InflictStatus1_Party_Poison: + setstatus1 STATUS1_POISON, PARTY_SIZE + releaseall + end + +Debug_EventScript_InflictStatus1_Party_Paralysis: + setstatus1 STATUS1_PARALYSIS, PARTY_SIZE + releaseall + end + +Debug_EventScript_InflictStatus1_Party_Sleep: + setstatus1 STATUS1_SLEEP, PARTY_SIZE + releaseall + end + +Debug_EventScript_InflictStatus1_Party_Burn: + setstatus1 STATUS1_BURN, PARTY_SIZE + releaseall + end + +Debug_EventScript_InflictStatus1_Party_Freeze: + setstatus1 STATUS1_FREEZE, PARTY_SIZE + releaseall + end + +Debug_EventScript_InflictStatus1_Party_Frostbite: + setstatus1 STATUS1_FROSTBITE, PARTY_SIZE + releaseall + end + +Debug_EventScript_InflictStatus1_Text_Single: + .string "Single$" + +Debug_EventScript_InflictStatus1_Text_PartyWide: + .string "Party-wide$" + +Debug_EventScript_InflictStatus1_Text_Close: + .string "Close$" + +Debug_EventScript_InflictStatus1_Text_Poison: + .string "Poison$" + +Debug_EventScript_InflictStatus1_Text_Paralysis: + .string "Paralysis$" + +Debug_EventScript_InflictStatus1_Text_Sleep: + .string "Sleep$" + +Debug_EventScript_InflictStatus1_Text_Burn: + .string "Burn$" + +Debug_EventScript_InflictStatus1_Text_Freeze: + .string "Freeze$" + +Debug_EventScript_InflictStatus1_Text_Frostbite: + .string "Frostbite$" + +.endif diff --git a/data/scripts/repel.inc b/data/scripts/repel.inc index 85af0c533..5f13b5e30 100644 --- a/data/scripts/repel.inc +++ b/data/scripts/repel.inc @@ -108,7 +108,7 @@ EventScript_ChooseWhichSpray:: waitmessage callnative DrawSprayMenu waitstate - compare VAR_RESULT, 127 @ TODO: MULTI_B_PRESSED + compare VAR_RESULT, SCR_MENU_CANCEL goto_if_ne EventScript_ChooseWhichSpray_3 EventScript_ChooseWhichSpray_1: closemessage diff --git a/include/battle.h b/include/battle.h index 29d17bbd0..0f92dd4a4 100644 --- a/include/battle.h +++ b/include/battle.h @@ -12,7 +12,7 @@ #include "battle_util2.h" #include "battle_bg.h" #include "pokeball.h" -// #include "battle_debug.h" +#include "battle_debug.h" #include "battle_dynamax.h" #include "battle_terastal.h" #include "random.h" // for rng_value_t @@ -70,6 +70,7 @@ #define B_ACTION_FINISHED 12 #define B_ACTION_CANCEL_PARTNER 12 // when choosing an action #define B_ACTION_NOTHING_FAINTED 13 // when choosing an action +#define B_ACTION_DEBUG 20 #define B_ACTION_NONE 0xFF diff --git a/include/battle_bg.h b/include/battle_bg.h index 63cc22d04..e71552e3a 100644 --- a/include/battle_bg.h +++ b/include/battle_bg.h @@ -3,6 +3,15 @@ #include "bg.h" +struct BattleBackground +{ + const void *tileset; + const void *tilemap; + const void *entryTileset; + const void *entryTilemap; + const void *palette; +}; + extern const struct BgTemplate gBattleBgTemplates[]; void InitBattleBgsVideo(void); diff --git a/include/battle_controllers.h b/include/battle_controllers.h index efb724eaf..d9957a049 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -198,6 +198,7 @@ enum CONTROLLER_LINKSTANDBYMSG, CONTROLLER_RESETACTIONMOVESELECTION, CONTROLLER_ENDLINKBATTLE, + CONTROLLER_DEBUGMENU, /*new controllers should go here*/ CONTROLLER_TERMINATOR_NOP, CONTROLLER_CMDS_COUNT @@ -258,6 +259,7 @@ void BtlController_EmitBattleAnimation(u32 battler, u32 bufferId, u8 animationId void BtlController_EmitLinkStandbyMsg(u32 battler, u32 bufferId, u8 mode, bool32 record); void BtlController_EmitResetActionMoveSelection(u32 battler, u32 bufferId, u8 caseId); void BtlController_EmitEndLinkBattle(u32 battler, u32 bufferId, u8 battleOutcome); +void BtlController_EmitDebugMenu(u32 battler, u32 bufferId); void BattleControllerComplete(u32 battler); // Can be used for all the controllers. void BtlController_Empty(u32 battler); // Empty command, does nothing, only completes the execution. diff --git a/include/battle_debug.h b/include/battle_debug.h new file mode 100644 index 000000000..db2c92296 --- /dev/null +++ b/include/battle_debug.h @@ -0,0 +1,6 @@ +#ifndef GUARD_BATTLE_DEBUG_H +#define GUARD_BATTLE_DEBUG_H + +void CB2_BattleDebugMenu(void); + +#endif // GUARD_BATTLE_DEBUG_H diff --git a/include/battle_setup.h b/include/battle_setup.h index 6937d2e9a..d221633df 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -36,5 +36,6 @@ void ShowTrainerCantBattleSpeech(void); void PlayTrainerEncounterMusic(void); const u8 *GetTrainerALoseText(void); const u8 *GetTrainerWonSpeech(void); +void BattleSetup_StartTrainerBattle_Debug(void); #endif // GUARD_BATTLE_SETUP_H diff --git a/include/config.h b/include/config.h index 6d54c10b5..4c3337e2c 100644 --- a/include/config.h +++ b/include/config.h @@ -33,6 +33,9 @@ #define LOG_HANDLER (LOG_HANDLER_MGBA_PRINT) #endif // NDEBUG +// Uncomment to fix some identified minor bugs +#define BUGFIX + // Define the game version for use elsewhere #if defined(FIRERED) #define GAME_VERSION VERSION_FIRE_RED @@ -44,14 +47,13 @@ #define CODE_ROOT "C:/WORK/POKeFRLG/Src/pm_lgfr_ose/source/" #define ABSPATH(x) (CODE_ROOT x) -// Crashes may occur due to section reordering in the modern build, -// so we force BUGFIX here. -#ifndef BUGFIX -#define BUGFIX -#endif // BUGFIX +// Various undefined behavior bugs may or may not prevent compilation with +// newer compilers. So always fix them when using a modern compiler. +#if MODERN || defined(BUGFIX) #ifndef UBFIX #define UBFIX -#endif // UBFIX +#endif +#endif // Generation constants used in configs to define behavior #define GEN_1 0 diff --git a/include/config/battle.h b/include/config/battle.h index 6bcd7b3cb..e0bb6d548 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -123,7 +123,7 @@ #define B_HEAL_BELL_SOUNDPROOF GEN_LATEST // In Gen5, Heal Bell affects all mons with Soundproof. In Gen6-8 it affects inactive mons, but not battlers. In Gen9 it always affects the user. // Ability settings -#define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters. +#define B_EXPANDED_ABILITY_NAMES FALSE // If TRUE, ability names are increased from 12 characters to 16 characters. #define B_ABILITY_WEATHER GEN_LATEST // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. #define B_GALE_WINGS GEN_LATEST // In Gen7+ requires full HP to trigger. #define B_STANCE_CHANGE_FAIL GEN_LATEST // In Gen7+, Stance Change fails if the Pokémon is unable to use a move because of confusion, paralysis, etc. In Gen6, it doesn't. diff --git a/include/config/debug.h b/include/config/debug.h index eea676b30..f5e1b55fb 100644 --- a/include/config/debug.h +++ b/include/config/debug.h @@ -2,16 +2,16 @@ #define GUARD_CONFIG_DEBUG_H // Overworld Debug -#define DEBUG_OVERWORLD_MENU TRUE // Enables an overworld debug menu to change flags, variables, giving pokemon and more, accessed by holding R and pressing START while in the overworld by default. +#define DEBUG_OVERWORLD_MENU FALSE // Enables an overworld debug menu to change flags, variables, giving pokemon and more, accessed by holding R and pressing START while in the overworld by default. #define DEBUG_OVERWORLD_HELD_KEYS (R_BUTTON) // The keys required to be held to open the debug menu. #define DEBUG_OVERWORLD_TRIGGER_EVENT pressedStartButton // The event that opens the menu when holding the key(s) defined in DEBUG_OVERWORLD_HELD_KEYS. #define DEBUG_OVERWORLD_IN_MENU FALSE // Replaces the overworld debug menu button combination with a start menu entry (above Pokédex). // Battle Debug Menu -#define DEBUG_BATTLE_MENU TRUE // If set to TRUE, enables a debug menu to use in battles by pressing the Select button. +#define DEBUG_BATTLE_MENU FALSE // If set to TRUE, enables a debug menu to use in battles by pressing the Select button. #define DEBUG_AI_DELAY_TIMER FALSE // If set to TRUE, displays the number of frames it takes for the AI to choose a move. Replaces the "What will PKMN do" text. Useful for devs or anyone who modifies the AI code and wants to see if it doesn't take too long to run. // Pokémon Debug -#define DEBUG_POKEMON_MENU TRUE // Enables a debug menu for pokemon sprites and icons, accessed by pressing SELECT in the summary screen. +#define DEBUG_POKEMON_SPRITE_VISUALIZER FALSE // Enables a debug menu for Pokémon sprites and icons, accessed by pressing Select in the summary screen. #endif // GUARD_CONFIG_DEBUG_H diff --git a/include/constants/global.h b/include/constants/global.h index 6d562c479..69f8b98f8 100644 --- a/include/constants/global.h +++ b/include/constants/global.h @@ -2,9 +2,12 @@ #define GUARD_CONSTANTS_GLOBAL_H #include "config/battle.h" +#include "config/debug.h" #include "config/item.h" +// #include "config/level_caps.h" #include "config/pokemon.h" #include "config/overworld.h" + // Invalid Versions show as "----------" in Gen 4 and Gen 5's summary screen. // In Gens 6 and 7, invalid versions instead show "a distant land" in the summary screen. // In Gen 4 only, migrated Pokemon with Diamond, Pearl, or Platinum's ID show as "----------". diff --git a/include/constants/pokemon_sprite_visualizer.h b/include/constants/pokemon_sprite_visualizer.h new file mode 100644 index 000000000..36afdb5b8 --- /dev/null +++ b/include/constants/pokemon_sprite_visualizer.h @@ -0,0 +1,53 @@ +#ifndef GUARD_CONSTANTS_POKEMON_SPRITE_VISUALIZER_H +#define GUARD_CONSTANTS_POKEMON_SPRITE_VISUALIZER_H + +//Defines +#define VISUALIZER_MON_BACK_X 62 +#define VISUALIZER_MON_BACK_Y 80 +#define VISUALIZER_ICON_X 224 +#define VISUALIZER_ICON_Y 144 +#define VISUALIZER_FOLLOWER_X 176 +#define VISUALIZER_FOLLOWER_Y 128 + +#define MODIFY_DIGITS_MAX 4 +#define MODIFY_DIGITS_ARROW_X 129 +#define MODIFY_DIGITS_ARROW1_Y 94 +#define MODIFY_DIGITS_ARROW2_Y 113 + +#define OPTIONS_ARROW_1_X 4 +#define OPTIONS_ARROW_2_X 236 +#define OPTIONS_ARROW_Y 119 + +#define GENDER_MALE 0 +#define GENDER_FEMALE 1 +#define MON_PIC_BACK 0 +#define MON_PIC_FRONT 1 + +//Sprite offset +#define MAX_Y_OFFSET 20 + +//Windows +#define WIN_NAME_NUMBERS 0 +#define WIN_INSTRUCTIONS 1 +#define WIN_BOTTOM_LEFT 2 +#define WIN_BOTTOM_RIGHT 3 +#define WIN_FOOTPRINT 4 +#define WIN_END 5 + +//Battle backgrounds +#define MAP_BATTLE_SCENE_NORMAL 0 +#define MAP_BATTLE_SCENE_GYM 1 +#define MAP_BATTLE_SCENE_MAGMA 2 +#define MAP_BATTLE_SCENE_AQUA 3 +#define MAP_BATTLE_SCENE_SIDNEY 4 +#define MAP_BATTLE_SCENE_PHOEBE 5 +#define MAP_BATTLE_SCENE_GLACIA 6 +#define MAP_BATTLE_SCENE_DRAKE 7 +#define MAP_BATTLE_SCENE_FRONTIER 8 +#define MAP_BATTLE_SCENE_LEADER 9 +#define MAP_BATTLE_SCENE_WALLACE 10 +#define MAP_BATTLE_SCENE_GROUDON 11 +#define MAP_BATTLE_SCENE_KYOGRE 12 +#define MAP_BATTLE_SCENE_RAYQUAZA 13 + +#endif // GUARD_CONSTANTS_POKEMON_SPRITE_VISUALIZER_H diff --git a/include/constants/songs.h b/include/constants/songs.h index 7addf89ec..5d2d609a5 100644 --- a/include/constants/songs.h +++ b/include/constants/songs.h @@ -259,7 +259,10 @@ #define SE_DEOXYS_MOVE 253 // SE_RG_DEOMOV #define SE_POKE_JUMP_SUCCESS 254 // SE_RG_EXCELLENT #define SE_POKE_JUMP_FAILURE 255 // SE_RG_NAWAMISS +#define END_SE SE_POKE_JUMP_FAILURE + // Music kept from RS +#define START_MUS 256 #define MUS_HEAL 256 // MUS_ME_ASA #define MUS_LEVEL_UP 257 // MUS_FANFA1 #define MUS_OBTAIN_ITEM 258 // MUS_FANFA4 @@ -352,6 +355,7 @@ #define MUS_TRAINER_TOWER 344 // MUS_RG_T_TOWER #define MUS_SLOW_PALLET 345 // MUS_RG_SLOWMASARA #define MUS_TEACHY_TV_MENU 346 // MUS_RG_TVNOIZE +#define END_MUS MUS_TEACHY_TV_MENU #define MUS_NONE 0xFFFF diff --git a/include/credits.h b/include/credits.h index 8207b703c..ac9a92f09 100644 --- a/include/credits.h +++ b/include/credits.h @@ -19,4 +19,7 @@ extern bool8 gHasHallOfFameRecords; #define CREDITSOVWLDEND \ { CREDITSOVWLDCMD_END, CREDITSOVWLDCMD_END, CREDITSOVWLDCMD_END } + +void DoCredits(void); + #endif //GUARD_CREDITS_H diff --git a/include/daycare.h b/include/daycare.h index 8b0ca8de5..48102b8e3 100644 --- a/include/daycare.h +++ b/include/daycare.h @@ -1,12 +1,13 @@ #ifndef GUARD_DAYCARE_H #define GUARD_DAYCARE_H -#include "global.h" +#include "constants/daycare.h" u8 *GetMonNick(struct Pokemon *mon, u8 *dest); u8 *GetBoxMonNick(struct BoxPokemon *mon, u8 *dest); u8 CountPokemonInDaycare(struct DayCare *daycare); void InitDaycareMailRecordMixing(struct DayCare *daycare, struct RecordMixingDayCareMail *daycareMail); +s8 Daycare_FindEmptySpot(struct DayCare *daycare); void StoreSelectedPokemonInDaycare(void); u16 TakePokemonFromDaycare(void); void GetDaycareCost(void); @@ -19,6 +20,7 @@ bool8 DoEggActions_CheckHatch(void); u16 GetSelectedMonNickAndSpecies(void); void GetDaycareMonNicknames(void); u8 GetDaycareState(void); +u8 GetDaycareCompatibilityScore(struct DayCare *daycare); void SetDaycareCompatibilityString(void); bool8 NameHasGenderSymbol(const u8 *name, u8 genderRatio); void ShowDaycareLevelMenu(void); diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 000000000..e25392091 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,10 @@ +#ifndef GUARD_DEBUG_H +#define GUARD_DEBUG_H + +void Debug_ShowMainMenu(void); +extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[]; + +extern EWRAM_DATA bool8 gIsDebugBattle; +extern EWRAM_DATA u32 gDebugAIFlags; + +#endif // GUARD_DEBUG_H diff --git a/include/event_data.h b/include/event_data.h index fe17d6470..8044b6ea1 100644 --- a/include/event_data.h +++ b/include/event_data.h @@ -41,6 +41,7 @@ void EnableResetRTC(void); bool32 CanResetRTC(void); u16 *GetVarPointer(u16 id); u16 VarGet(u16 id); +u16 VarGetIfExist(u16 id); bool8 VarSet(u16 id, u16 value); u8 VarGetObjectEventGraphicsId(u8 id); u8 *GetFlagPointer(u16 id); diff --git a/include/list_menu.h b/include/list_menu.h index eded1074c..de271708c 100644 --- a/include/list_menu.h +++ b/include/list_menu.h @@ -100,6 +100,7 @@ u8 ListMenuInitInRect(const struct ListMenuTemplate *listMenuTemplate, const str s32 ListMenu_ProcessInput(u8 listTaskId); void DestroyListMenuTask(u8 listTaskId, u16 *cursorPos, u16 *itemsAbove); void RedrawListMenu(u8 listTaskId); +void ListMenuGetCurrentItemArrayId(u8 listTaskId, u16 *arrayId); void ListMenuGetScrollAndRow(u8 listTaskId, u16 *cursorPos, u16 *itemsAbove); u16 ListMenuGetYCoordForPrintingArrowCursor(u8 listTaskId); void ListMenuOverrideSetColors(u8 cursorPal, u8 fillValue, u8 cursorShadowPal); diff --git a/include/menu_helpers.h b/include/menu_helpers.h index f4a61cf93..e8bfc8de3 100644 --- a/include/menu_helpers.h +++ b/include/menu_helpers.h @@ -14,6 +14,7 @@ struct YesNoFuncTable TaskFunc noFunc; }; +void ResetAllBgsCoordinates(void); bool16 RunTextPrinters_CheckActive(u8 textPrinterId); bool8 IsActiveOverworldLinkBusy(void); bool8 MenuHelpers_ShouldWaitForLinkRecv(void); diff --git a/include/money.h b/include/money.h index 31e925c0b..3a582ab0e 100644 --- a/include/money.h +++ b/include/money.h @@ -3,6 +3,8 @@ #include "global.h" +#define MAX_MONEY 999999 + u32 GetMoney(u32 *moneyPtr); void SetMoney(u32 *moneyPtr, u32 newValue); bool8 IsEnoughMoney(u32 *moneyPtr, u32 cost); diff --git a/include/party_menu.h b/include/party_menu.h index ef5709439..894305391 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -27,6 +27,7 @@ extern u8 gSelectedOrderFromParty[3]; extern u8 gBattlePartyCurrentOrder[PARTY_SIZE / 2]; extern void (*gItemUseCB)(u8, TaskFunc); +extern const struct SpriteTemplate gSpriteTemplate_StatusIcons; void InitPartyMenu(u8 menuType, u8 layout, u8 partyAction, bool8 keepCursorPos, u8 messageId, TaskFunc task, MainCallback callback); void AnimatePartySlot(u8 slot, u8 animNum); @@ -43,6 +44,7 @@ u8 GetMonAilment(struct Pokemon *mon); void DisplayPartyMenuStdMessage(u32 stringId); void LoadHeldItemIcons(void); void DrawHeldItemIconsForTrade(u8 *partyCounts, u8 *partySpriteIds, u8 whichParty); +void LoadPartyMenuAilmentGfx(void); void SpriteCB_BounceConfirmCancelButton(u8 spriteId, u8 spriteId2, u8 animNum); void CB2_SelectBagItemToGive(void); void CB2_GiveHoldItem(void); diff --git a/include/pokemon.h b/include/pokemon.h index 2511d95b2..7c7c2cd80 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -804,6 +804,7 @@ void PlayBattleBGM(void); void PlayMapChosenOrBattleBGM(u16 songId); const u32 *GetMonFrontSpritePal(struct Pokemon *mon); const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, bool32 isShiny, u32 personality); +const u32 *GetMonSpritePalFromSpecies(u16 species, bool32 isShiny, bool32 isFemale); bool32 IsMoveHM(u16 move); bool8 IsMonSpriteNotFlipped(u16 species); s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor); @@ -834,6 +835,7 @@ bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method); void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method); bool8 IsMonPastEvolutionLevel(struct Pokemon *mon); bool32 IsPersonalityFemale(u16 species, u32 personality); +bool32 SpeciesHasGenderDifferences(u16 species); bool32 TryFormChange(u32 monId, u32 side, u16 method); u16 ModifyStatByNature(u8 nature, u16 stat, u8 statIndex); bool8 HealStatusConditions(struct Pokemon *mon, u32 healMask, u8 battleId); diff --git a/include/pokemon_icon.h b/include/pokemon_icon.h index d46698d70..6275aaaec 100644 --- a/include/pokemon_icon.h +++ b/include/pokemon_icon.h @@ -21,6 +21,7 @@ void SpriteCB_MonIcon(struct Sprite *); u8 CreateMonIcon(u16 species, SpriteCallback callback, s16 x, s16 y, u8 subpriority, u32 personality); u8 UpdateMonIconFrame(struct Sprite *sprite); void LoadMonIconPalette(u16 iconId); +void LoadMonIconPalettePersonality(u16 species, u32 personality); void FreeMonIconPalette(u16 iconId); void SetPartyHPBarSprite(struct Sprite *sprite, u8 animNum); u8 GetMonIconPaletteIndexFromSpecies(u16 species); diff --git a/include/pokemon_sprite_visualizer.h b/include/pokemon_sprite_visualizer.h new file mode 100644 index 000000000..946c2f37f --- /dev/null +++ b/include/pokemon_sprite_visualizer.h @@ -0,0 +1,74 @@ +#ifndef GUARD_POKEMON_SPRITE_VISUALIZER_H +#define GUARD_POKEMON_SPRITE_VISUALIZER_H + +#include "constants/pokemon_sprite_visualizer.h" + +//Structs +struct PokemonSpriteVisualizerModifyArrows +{ + u8 arrowSpriteId[2]; + u16 minValue; + u16 maxValue; + int currValue; + u8 currentDigit; + u8 maxDigits; + u8 charDigits[MODIFY_DIGITS_MAX]; + void *modifiedValPtr; + u8 typeOfVal; +}; + +struct PokemonSpriteVisualizerOptionArrows +{ + u8 arrowSpriteId[1]; + u8 currentDigit; +}; + +struct PokemonSpriteVisualizerYPosModifiyArrows +{ + u8 arrowSpriteId[1]; + u8 currentDigit; +}; + +struct PokemonSpriteConstValues +{ + u8 backPicCoords; + u8 frontPicCoords; + u8 frontElevation; +}; + +struct PokemonSpriteOffsets +{ + s8 offset_back_picCoords; + s8 offset_front_picCoords; + s8 offset_front_elevation; +}; + +struct PokemonSpriteVisualizer +{ + u16 currentmonId; + u8 currentmonWindowId; + u8 InstructionsWindowId; + u8 frontspriteId; + u8 backspriteId; + u8 iconspriteId; + u8 followerspriteId; + u8 frontShadowSpriteId; + bool8 isShiny; + bool8 isFemale; + struct PokemonSpriteVisualizerModifyArrows modifyArrows; + struct PokemonSpriteVisualizerOptionArrows optionArrows; + struct PokemonSpriteVisualizerYPosModifiyArrows yPosModifyArrows; + struct PokemonSpriteConstValues constSpriteValues; + struct PokemonSpriteOffsets offsetsSpriteValues; + u8 animIdBack; + u8 animIdFront; + u8 battleBgType; + u8 battleTerrain; + u8 currentSubmenu; + u8 submenuYpos[3]; +}; + +void CB2_Pokemon_Sprite_Visualizer(void); + + +#endif // GUARD_POKEMON_SPRITE_VISUALIZER_H diff --git a/include/reset_rtc_screen.h b/include/reset_rtc_screen.h index 5807dec99..589616400 100644 --- a/include/reset_rtc_screen.h +++ b/include/reset_rtc_screen.h @@ -1,6 +1,9 @@ #ifndef GUARD_RESET_RTC_SCREEN_H #define GUARD_RESET_RTC_SCREEN_H +extern const struct SpritePalette gSpritePalette_Arrow; +extern const struct SpriteTemplate gSpriteTemplate_Arrow; + void CB2_InitResetRtcScreen(void); #endif // GUARD_RESET_RTC_SCREEN_H diff --git a/include/strings.h b/include/strings.h index f32fd3e20..39cfda134 100644 --- a/include/strings.h +++ b/include/strings.h @@ -659,6 +659,7 @@ extern const u8 gStartMenuDesc_Option[]; extern const u8 gStartMenuDesc_Exit[]; extern const u8 gStartMenuDesc_Retire[]; extern const u8 gStartMenuDesc_Player[]; +extern const u8 gStartMenuDesc_Debug[]; extern const u8 gText_SaveError_PleaseExchangeBackupMemory[]; extern const u8 gText_SavingDontTurnOffThePower2[]; extern const u8 gSaveStatName_Player[]; @@ -1603,4 +1604,11 @@ extern const u8 gText_NextFusionMon[]; extern const u8 gText_ExpShareOn[]; extern const u8 gText_ExpShareOff[]; +// stats +extern const u8 gText_Attack[]; +extern const u8 gText_Defense[]; +extern const u8 gText_SpAtk[]; +extern const u8 gText_SpDef[]; +extern const u8 gText_Speed[]; + #endif //GUARD_STRINGS_H diff --git a/include/trainer_see.h b/include/trainer_see.h index 65d4a9efe..ced4ff550 100644 --- a/include/trainer_see.h +++ b/include/trainer_see.h @@ -3,6 +3,9 @@ #include "global.h" +extern u16 gWhichTrainerToFaceAfterBattle; +extern u8 gNoOfApproachingTrainers; + bool8 CheckForTrainersWantingBattle(void); void MovementAction_RevealTrainer_RunTrainerSeeFuncList(struct ObjectEvent *var); u8 FldEff_ExclamationMarkIcon1(void); diff --git a/map_data_rules.mk b/map_data_rules.mk index 7ba6bceb5..507dc18e2 100644 --- a/map_data_rules.mk +++ b/map_data_rules.mk @@ -18,6 +18,7 @@ $(MAPS_DIR)/groups.inc: $(MAPS_DIR)/map_groups.json $(MAPS_DIR)/connections.inc: $(MAPS_DIR)/groups.inc ; $(MAPS_DIR)/events.inc: $(MAPS_DIR)/connections.inc ; $(MAPS_DIR)/headers.inc: $(MAPS_DIR)/events.inc ; +$(DATA_SRC_SUBDIR)/map_group_count.h: $(MAPS_DIR)/headers.inc ; include/constants/map_groups.h: $(MAPS_DIR)/headers.inc ; $(LAYOUTS_DIR)/layouts.inc: $(LAYOUTS_DIR)/layouts.json diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d0d39bfb0..cbb238dcb 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -10,7 +10,7 @@ #include "battle_z_move.h" #include "battle_terastal.h" #include "data.h" -// #include "debug.h" +#include "debug.h" #include "event_data.h" #include "item.h" #include "pokemon.h" diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index b69093992..d7d5e82d9 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -28,7 +28,7 @@ static void AnimWeatherBallUp_Step(struct Sprite *sprite); static EWRAM_DATA union AffineAnimCmd *sAnimTaskAffineAnim = NULL; -static const struct UCoords8 sBattlerCoords[][MAX_BATTLERS_COUNT] = +const struct UCoords8 sBattlerCoords[][MAX_BATTLERS_COUNT] = { { // Single battle { 72, 80 }, diff --git a/src/battle_bg.c b/src/battle_bg.c index 5adc23217..9630e083a 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -17,15 +17,6 @@ #define TAG_VS_LETTERS 10000 -struct BattleBackground -{ - const void *tileset; - const void *tilemap; - const void *entryTileset; - const void *entryTilemap; - const void *palette; -}; - static u8 GetBattleTerrainOverride(void); static const struct OamData sVsLetter_V_OamData = { @@ -434,7 +425,8 @@ static const u32 sBattleTerrainPalette_Plain[] = INCBIN_U32("graphics/battle_ter static const u32 sBattleTerrainTiles_Indoor[] = INCBIN_U32("graphics/battle_terrain/indoor/terrain.4bpp.lz"); static const u32 sBattleTerrainTilemap_Indoor[] = INCBIN_U32("graphics/battle_terrain/indoor/terrain.bin.lz"); -static const struct BattleBackground sBattleTerrainTable[] = { +const struct BattleBackground sBattleTerrainTable[] = +{ [BATTLE_TERRAIN_GRASS] = { .tileset = sBattleTerrainTiles_Grass, diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index a715b1ee4..f3dc2225a 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -88,6 +88,7 @@ static void (*const sLinkOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 batt [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, // done [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done [CONTROLLER_ENDLINKBATTLE] = LinkOpponentHandleEndLinkBattle, // done + [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop // done }; diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index 3019813d2..b9d5929aa 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -86,6 +86,7 @@ static void (*const sLinkPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battl [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, // done [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done [CONTROLLER_ENDLINKBATTLE] = LinkPartnerHandleEndLinkBattle, // done + [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop // done }; diff --git a/src/battle_controller_oak_old_man.c b/src/battle_controller_oak_old_man.c index bf4fea887..1186e9789 100644 --- a/src/battle_controller_oak_old_man.c +++ b/src/battle_controller_oak_old_man.c @@ -106,6 +106,7 @@ static void (*const sOakOldManBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler [CONTROLLER_LINKSTANDBYMSG] = OakOldManHandleLinkStandbyMsg, // done [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done [CONTROLLER_ENDLINKBATTLE] = OakOldManHandleEndLinkBattle, // done + [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, // done }; diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index e46f7c65b..5fd0b23af 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -103,6 +103,7 @@ static void (*const sOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, // done [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done [CONTROLLER_ENDLINKBATTLE] = OpponentHandleEndLinkBattle, // done + [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop // done }; diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 1f5c15085..e1c5de538 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -59,6 +59,7 @@ static void PlayerHandleBattleAnimation(u32 battler); static void PlayerHandleLinkStandbyMsg(u32 battler); static void PlayerHandleResetActionMoveSelection(u32 battler); static void PlayerHandleEndLinkBattle(u32 battler); +static void PlayerHandleBattleDebug(u32 battler); static void PlayerBufferRunCommand(u32 battler); static void HandleInputChooseTarget(u32 battler); @@ -138,6 +139,7 @@ static void (*const sPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = [CONTROLLER_LINKSTANDBYMSG] = PlayerHandleLinkStandbyMsg, // done [CONTROLLER_RESETACTIONMOVESELECTION] = PlayerHandleResetActionMoveSelection, // done [CONTROLLER_ENDLINKBATTLE] = PlayerHandleEndLinkBattle, // done + [CONTROLLER_DEBUGMENU] = PlayerHandleBattleDebug, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, // done }; @@ -270,6 +272,13 @@ static void HandleInputChooseAction(u32 battler) { SwapHpBarsWithHpText(); } +#if DEBUG_BATTLE_MENU == TRUE + else if (JOY_NEW(SELECT_BUTTON)) + { + BtlController_EmitTwoReturnValues(battler, BUFFER_B, B_ACTION_DEBUG, 0); + PlayerBufferExecCompleted(battler); + } +#endif } static void HandleInputChooseTarget(u32 battler) @@ -2066,3 +2075,18 @@ static void PlayerHandleEndLinkBattle(u32 battler) PlayerBufferExecCompleted(battler); gBattlerControllerFuncs[battler] = SetBattleEndCallbacks; } + +static void Controller_WaitForDebug(u32 battler) +{ + if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) + { + PlayerBufferExecCompleted(battler); + } +} + +static void PlayerHandleBattleDebug(u32 battler) +{ + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + SetMainCallback2(CB2_BattleDebugMenu); + gBattlerControllerFuncs[battler] = Controller_WaitForDebug; +} diff --git a/src/battle_controller_pokedude.c b/src/battle_controller_pokedude.c index cba70c9d9..997d017d9 100644 --- a/src/battle_controller_pokedude.c +++ b/src/battle_controller_pokedude.c @@ -130,6 +130,7 @@ static void (*const sPokedudeBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) [CONTROLLER_LINKSTANDBYMSG] = PokedudeHandleLinkStandbyMsg, // done [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done [CONTROLLER_ENDLINKBATTLE] = PokedudeHandleEndLinkBattle, // done + [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, // done }; diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index d964609e6..14cf4def1 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -111,6 +111,7 @@ static void (*const sRecordedOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, [CONTROLLER_ENDLINKBATTLE] = RecordedOpponentHandleEndLinkBattle, + [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop }; diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 64bbdb18f..7c3b4ee41 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -109,6 +109,7 @@ static void (*const sRecordedPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 ba [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, [CONTROLLER_ENDLINKBATTLE] = RecordedPlayerHandleEndLinkBattle, + [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop }; diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index 062a8d651..08ff94b03 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -89,6 +89,7 @@ static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = [CONTROLLER_LINKSTANDBYMSG] = BtlController_Empty, // done [CONTROLLER_RESETACTIONMOVESELECTION] = BtlController_Empty, // done [CONTROLLER_ENDLINKBATTLE] = SafariHandleEndLinkBattle, // done + [CONTROLLER_DEBUGMENU] = BtlController_Empty, [CONTROLLER_TERMINATOR_NOP] = BtlController_TerminatorNop, // done }; diff --git a/src/battle_controllers.c b/src/battle_controllers.c index cb4e578ca..4efdd4edc 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1295,6 +1295,12 @@ void BtlController_EmitEndLinkBattle(u32 battler, u32 bufferId, u8 battleOutcome PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 2); } +void BtlController_EmitDebugMenu(u32 battler, u32 bufferId) +{ + gBattleResources->transferBuffer[0] = CONTROLLER_DEBUGMENU; + PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 1); +} + // Standardized Controller functions // Can be used for all the controllers. diff --git a/src/battle_debug.c b/src/battle_debug.c new file mode 100644 index 000000000..ae1dff3fc --- /dev/null +++ b/src/battle_debug.c @@ -0,0 +1,2348 @@ +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_message.h" +#include "main.h" +#include "menu.h" +#include "menu_helpers.h" +#include "scanline_effect.h" +#include "palette.h" +#include "party_menu.h" +#include "pokemon_icon.h" +#include "sprite.h" +#include "item.h" +#include "task.h" +#include "bg.h" +#include "gpu_regs.h" +#include "window.h" +#include "text.h" +#include "text_window.h" +// #include "international_string_util.h" +#include "strings.h" +#include "battle_ai_main.h" +#include "battle_ai_util.h" +#include "list_menu.h" +#include "decompress.h" +#include "trainer_pokemon_sprites.h" +#include "malloc.h" +#include "string_util.h" +#include "util.h" +#include "data.h" +#include "reset_rtc_screen.h" +#include "reshow_battle_screen.h" +#include "constants/abilities.h" +#include "constants/party_menu.h" +#include "constants/moves.h" +#include "constants/items.h" +#include "constants/rgb.h" +#include "constants/hold_effects.h" + +#define MAX_MODIFY_DIGITS 4 + +struct BattleDebugModifyArrows +{ + u8 arrowSpriteId[2]; + u16 minValue; + u16 maxValue; + int currValue; + u8 currentDigit:4; + u8 maxDigits:4; + u8 charDigits[MAX_MODIFY_DIGITS]; + void *modifiedValPtr; + u8 typeOfVal; +}; + +struct BattleDebugMenu +{ + u8 battlerId:2; + u8 aiBattlerId:2; + + u8 battlerWindowId; + + u8 mainListWindowId; + u8 mainListTaskId; + u8 currentMainListItemId; + + u8 secondaryListWindowId; + u8 secondaryListTaskId; + u8 currentSecondaryListItemId; + u8 secondaryListItemCount; + + u8 modifyWindowId; + + u8 activeWindow; + + struct BattleDebugModifyArrows modifyArrows; + const struct BitfieldInfo *bitfield; + bool8 battlerWasChanged[MAX_BATTLERS_COUNT]; + + u8 aiViewState; + + u8 aiMonSpriteId; + u8 aiMovesWindowId; + + union + { + u8 aiIconSpriteIds[MAX_BATTLERS_COUNT]; + u8 aiPartyIcons[PARTY_SIZE]; + } spriteIds; +}; + +struct __attribute__((__packed__)) BitfieldInfo +{ + u8 bitsCount; + u8 currBit; +}; + +enum +{ + LIST_ITEM_MOVES, + LIST_ITEM_ABILITY, + LIST_ITEM_HELD_ITEM, + LIST_ITEM_PP, + LIST_ITEM_TYPES, + LIST_ITEM_STATS, + LIST_ITEM_STAT_STAGES, + LIST_ITEM_STATUS1, + LIST_ITEM_STATUS2, + LIST_ITEM_STATUS3, + LIST_ITEM_STATUS4, + LIST_ITEM_SIDE_STATUS, + LIST_ITEM_AI, + LIST_ITEM_AI_MOVES_PTS, + LIST_ITEM_AI_INFO, + LIST_ITEM_AI_PARTY, + LIST_ITEM_VARIOUS, + LIST_ITEM_COUNT +}; + +enum +{ + ACTIVE_WIN_MAIN, + ACTIVE_WIN_SECONDARY, + ACTIVE_WIN_MODIFY +}; + +enum +{ + VAL_U8, + VAL_U16, + VAL_U32, + VAL_BITFIELD_8, + VAL_BITFIELD_16, + VAL_BITFIELD_32, + VAR_SIDE_STATUS, + VAR_SHOW_HP, + VAR_SUBSTITUTE, + VAR_IN_LOVE, + VAR_U16_4_ENTRIES, + VAL_S8, + VAL_ALL_STAT_STAGES, +}; + +enum +{ + LIST_SIDE_REFLECT, + LIST_SIDE_LIGHTSCREEN, + LIST_SIDE_SPIKES, + LIST_SIDE_SAFEGUARD, + LIST_SIDE_MIST, + LIST_SIDE_AURORA_VEIL, + LIST_SIDE_LUCKY_CHANT, + LIST_SIDE_TAILWIND, + LIST_SIDE_STEALTH_ROCK, + LIST_SIDE_TOXIC_SPIKES, + LIST_SIDE_STICKY_WEB, + LIST_SIDE_STEELSURGE, +}; + +enum +{ + VARIOUS_SHOW_HP, + VARIOUS_SUBSTITUTE_HP, + VARIOUS_IN_LOVE, +}; + +// Static Declarations +static const u8 *GetHoldEffectName(u16 holdEffect); + +// const rom data +static const u8 sText_HoldEffect[] = _("Hold Effect"); +static const u8 sText_Ability[] = _("Ability"); +static const u8 sText_Moves[] = _("Moves"); +static const u8 sText_Stats[] = _("Stats"); +static const u8 sText_StatStages[] = _("Stat Stages"); +static const u8 sText_Status1[] = _("Status1"); +static const u8 sText_Status2[] = _("Status2"); +static const u8 sText_Status3[] = _("Status3"); +static const u8 sText_Status4[] = _("Status4"); +static const u8 sText_HeldItem[] = _("Held Item"); +static const u8 sText_SideStatus[] = _("Side Status"); +static const u8 sText_MaxHp[] = _("HP Max"); +static const u8 sText_CurrHp[] = _("HP Current"); +static const u8 sText_Freeze[] = _("Freeze"); +static const u8 sText_Frostbite[] = _("Frostbite"); +static const u8 sText_ToxicPoison[] = _("Toxic Poison"); +static const u8 sText_ToxicCounter[] = _("Toxic Counter"); +static const u8 sText_Flinch[] = _("Flinch"); +static const u8 sText_Uproar[] = _("Uproar"); +static const u8 sText_Bide[] = _("Bide"); +static const u8 sText_LockConfuse[] = _("Lock Confuse"); +static const u8 sText_MultipleTurns[] = _("MultipleTurns"); +static const u8 sText_FocusEnergy[] = _("Focus Energy"); +static const u8 sText_Transformed[] = _("Transformed"); +static const u8 sText_Recharge[] = _("Recharge"); +static const u8 sText_Rage[] = _("Rage"); +static const u8 sText_Substitute[] = _("Substitute"); +static const u8 sText_SubstituteHp[] = _("Substitute HP"); +static const u8 sText_DestinyBond[] = _("Destiny Bond"); +static const u8 sText_CantEscape[] = _("Cant Escape"); +static const u8 sText_Nightmare[] = _("Nightmare"); +static const u8 sText_Cursed[] = _("Cursed"); +static const u8 sText_Foresight[] = _("Foresighted"); +static const u8 sText_DefenseCurl[] = _("Def Curled"); +static const u8 sText_Tormented[] = _("Tormented"); +static const u8 sText_AlwaysHits[] = _("Sure Hit"); +static const u8 sText_ChargedUp[] = _("Charged Up"); +static const u8 sText_Rooted[] = _("Rooted"); +static const u8 sText_Yawned[] = _("Yawned"); +static const u8 sText_Minimized[] = _("Minimized"); +static const u8 sText_NoCrit[] = _("No Crit"); +static const u8 sText_Imprisoned[] = _("Imprison"); +static const u8 sText_Reflect[] = _("Reflect"); +static const u8 sText_LightScreen[] = _("Light Screen"); +static const u8 sText_Spikes[] = _("Spikes"); +static const u8 sText_Safeguard[] = _("Safeguard"); +static const u8 sText_Mist[] = _("Mist"); +static const u8 sText_ShowOpponentHP[] = _("Opponent Hp"); +static const u8 sText_Types[] = _("Types"); +static const u8 sText_GastroAcid[] = _("Gastro Acid"); +static const u8 sText_SmackDown[] = _("Smacked Down"); +static const u8 sText_MiracleEye[] = _("Miracle Eye"); +static const u8 sText_AquaRing[] = _("Aqua Ring"); +static const u8 sText_LaserFocus[] = _("Laser Focused"); +static const u8 sText_Electrified[] = _("Electrified"); +static const u8 sText_AuroraVeil[] = _("Aurora Veil"); +static const u8 sText_LuckyChant[] = _("Lucky Chant"); +static const u8 sText_Tailwind[] = _("Tailwind"); +static const u8 sText_PP[] = _("PP"); +static const u8 sText_StealthRock[] = _("Stealth Rock"); +static const u8 sText_ToxicSpikes[] = _("Toxic Spikes"); +static const u8 sText_StickyWeb[] = _("Sticky Web"); +static const u8 sText_Steelsurge[] = _("Steelsurge"); +static const u8 sText_AI[] = _("AI"); +static const u8 sText_NoBadMoves[] = _("No Bad Moves"); +static const u8 sText_Viability[] = _("Viability"); +static const u8 sText_TryFaint[] = _("Try Faint"); +static const u8 sText_SetUpFirstTurn[] = _("Setup 1 turn"); +static const u8 sText_Risky[] = _("Risky"); +static const u8 sText_StrongestMove[] = _("Most dmg move"); +static const u8 sText_Various[] = _("Various"); +static const u8 sText_ShowHP[] = _("Show HP"); +static const u8 sText_PreferBatonPass[] = _("Baton Pass"); +static const u8 sText_InDoubles[] = _("In Doubles"); +static const u8 sText_HpAware[] = _("HP aware"); +static const u8 sText_Unknown[] = _("Unknown"); +static const u8 sText_InLove[] = _("In Love"); +static const u8 sText_AIMovePts[] = _("AI Pts/Dmg"); +static const u8 sText_AiKnowledge[] = _("AI Info"); +static const u8 sText_AiParty[] = _("AI Party"); + +static const u8 sText_EmptyString[] = _(""); + +static const struct BitfieldInfo sStatus1Bitfield[] = +{ + {/*Sleep*/ 3, 0}, + {/*Poison*/ 1, 3}, + {/*Burn*/ 1, 4}, + {/*Freeze*/ 1, 5}, + {/*Paralysis*/1, 6}, + {/*Toxic Poison*/ 1, 7}, + {/*Toxic Counter*/ 4, 8}, + {/*Frostbite*/ 1, 12}, +}; + +static const struct BitfieldInfo sStatus2Bitfield[] = +{ + {/*Confusion*/ 3, 0}, + {/*Flinch*/ 1, 3}, + {/*Uproar*/ 3, 4}, + // Bit 7 is unused. + {/*Bide*/ 2, 8}, + {/*Lock Confuse*/ 2, 10}, + {/*Multiple Turns*/ 1, 12}, + // Wrap bits are omitted. Done in various. + // In Love bits are omitted. Done in various. + {/*(Focus Energy*/ 1, 20}, + {/*Transformed*/ 1, 21}, + {/*Recharge*/ 1, 22}, + {/*Rage*/ 1, 23}, + {/*Substitute*/ 1, 24}, + {/*Destiny bond*/ 1, 25}, + {/*Can't escape*/ 1, 26}, + {/*Nightmares*/ 1, 27}, + {/*Cursed*/ 1, 28}, + {/*Foresighted*/ 1, 29}, + {/*Defense Curled*/ 1, 30}, + {/*Tormented*/ 1, 31}, +}; + +static const struct BitfieldInfo sStatus3Bitfield[] = +{ + {/*Always hits*/ 2, 4}, + //*Perish Song*/ 1, 5}, + // On Air 1, 6, + // Underground 1, 7, + {/*Minimized*/ 1, 8}, + {/*Charged Up*/ 1, 9}, + {/*Rooted*/ 1, 10}, + {/*Yawn*/ 2, 11}, + {/*Imprison*/ 1, 13}, + // Grudge 1, 14, + {/*No Crit*/ 1, 15}, + {/*Gastro Acid*/ 1, 16}, + // Embargo 1, 17, + // Underwater 1, 18, + // Intimidated Mons 1, 19, + // Traced 1, 20, + {/*Smacked Down*/ 1, 21}, + // Me First 1, 22, + // Telekinesis 1, 23, + // Phantom Force 1, 24}, + {/*Miracle Eyed*/ 1, 25}, + // Magnet Rise 1, 26, + // Heal Block 1, 27, + {/*Aqua Ring*/ 1, 28}, + {/*Laser Focus*/ 1, 29}, + // Power Trick 1, 30, +}; + +static const struct BitfieldInfo sStatus4Bitfield[] = +{ + {/*Electrified*/ 1, 0,} +}; + +static const struct BitfieldInfo sAIBitfield[] = +{ + {/*Check bad move*/ 1, 0}, + {/*Try To Faint*/ 1, 1}, + {/*Viability*/ 1, 2}, + {/*Set up first turn*/ 1, 3}, + {/*Risky*/ 1, 4}, + {/*Prefer Strongest Move*/ 1, 5}, + {/*Prefer Baton Pass*/ 1, 6}, + {/*In Doubles*/ 1, 7}, + {/*Hp aware*/ 1, 8}, + {/*Unknown*/ 1, 9}, +}; + + +static const struct ListMenuItem sMainListItems[] = +{ + {sText_Moves, LIST_ITEM_MOVES}, + {sText_Ability, LIST_ITEM_ABILITY}, + {sText_HeldItem, LIST_ITEM_HELD_ITEM}, + {sText_PP, LIST_ITEM_PP}, + {sText_Types, LIST_ITEM_TYPES}, + {sText_Stats, LIST_ITEM_STATS}, + {sText_StatStages, LIST_ITEM_STAT_STAGES}, + {sText_Status1, LIST_ITEM_STATUS1}, + {sText_Status2, LIST_ITEM_STATUS2}, + {sText_Status3, LIST_ITEM_STATUS3}, + {sText_Status4, LIST_ITEM_STATUS4}, + {sText_SideStatus, LIST_ITEM_SIDE_STATUS}, + {sText_AI, LIST_ITEM_AI}, + {sText_AIMovePts, LIST_ITEM_AI_MOVES_PTS}, + {sText_AiKnowledge, LIST_ITEM_AI_INFO}, + {sText_AiParty, LIST_ITEM_AI_PARTY}, + {sText_Various, LIST_ITEM_VARIOUS}, +}; + +static const struct ListMenuItem sVariousListItems[] = +{ + {sText_ShowHP, VARIOUS_SHOW_HP}, + {sText_SubstituteHp, VARIOUS_SUBSTITUTE_HP}, + {sText_InLove, VARIOUS_IN_LOVE}, +}; + +static const struct ListMenuItem sAIListItems[] = +{ + {sText_NoBadMoves, 0}, + {sText_TryFaint, 1}, + {sText_Viability, 2}, + {sText_SetUpFirstTurn, 3}, + {sText_Risky, 4}, + {sText_StrongestMove, 5}, + {sText_PreferBatonPass, 6}, + {sText_InDoubles, 7}, + {sText_HpAware, 8}, + // {sText_Unknown, 9}, +}; + +static const struct ListMenuItem sStatsListItems[] = +{ + {sText_CurrHp, 0}, + {sText_MaxHp, 1}, + {gText_Attack, 2}, + {gText_Defense, 3}, + {gText_Speed, 4}, + {gText_SpAtk, 5}, + {gText_SpDef, 6}, +}; + +static const struct ListMenuItem sStatus1ListItems[] = +{ + {gText_Sleep, 0}, + {gText_Poison, 1}, + {gText_Burn, 2}, + {sText_Freeze, 3}, + {gText_Paralysis, 4}, + {sText_ToxicPoison, 5}, + {sText_ToxicCounter, 6}, + {sText_Frostbite, 7}, +}; + +static const struct ListMenuItem sStatus2ListItems[] = +{ + {gText_Confusion, 0}, + {sText_Flinch, 1}, + {sText_Uproar, 2}, + {sText_Bide, 3}, + {sText_LockConfuse, 4}, + {sText_MultipleTurns, 5}, + {sText_FocusEnergy, 6}, + {sText_Recharge, 7}, + {sText_Rage, 8}, + {sText_Substitute, 9}, + {sText_DestinyBond, 10}, + {sText_CantEscape, 11}, + {sText_Nightmare, 12}, + {sText_Cursed, 13}, + {sText_Foresight, 14}, + {sText_DefenseCurl, 15}, + {sText_Tormented, 16}, +}; + +static const struct ListMenuItem sStatus3ListItems[] = +{ + {sText_AlwaysHits, 0}, + {sText_Minimized, 1}, + {sText_ChargedUp, 2}, + {sText_Rooted, 3}, + {sText_Yawned, 4}, + {sText_Imprisoned, 5}, + {sText_NoCrit, 6}, + {sText_GastroAcid, 7}, + {sText_SmackDown, 8}, + {sText_MiracleEye, 9}, + {sText_AquaRing, 10}, + {sText_LaserFocus, 11}, +}; + +static const struct ListMenuItem sStatus4ListItems[] = +{ + {sText_Electrified, 0}, +}; + +static const struct ListMenuItem sSideStatusListItems[] = +{ + {sText_Reflect, LIST_SIDE_REFLECT}, + {sText_LightScreen, LIST_SIDE_LIGHTSCREEN}, + {sText_Spikes, LIST_SIDE_SPIKES}, + {sText_Safeguard, LIST_SIDE_SAFEGUARD}, + {sText_Mist, LIST_SIDE_MIST}, + {sText_AuroraVeil, LIST_SIDE_AURORA_VEIL}, + {sText_LuckyChant, LIST_SIDE_LUCKY_CHANT}, + {sText_Tailwind, LIST_SIDE_TAILWIND}, + {sText_StealthRock, LIST_SIDE_STEALTH_ROCK}, + {sText_ToxicSpikes, LIST_SIDE_TOXIC_SPIKES}, + {sText_StickyWeb, LIST_SIDE_STICKY_WEB}, + {sText_Steelsurge, LIST_SIDE_STEELSURGE}, +}; + +static const struct ListMenuItem sSecondaryListItems[] = +{ + {sText_EmptyString, 0}, + {sText_EmptyString, 1}, + {sText_EmptyString, 2}, + {sText_EmptyString, 3}, + {sText_EmptyString, 4}, + {sText_EmptyString, 5}, + {sText_EmptyString, 6}, + {sText_EmptyString, 7}, + {sText_EmptyString, 8}, +}; + + +static const struct ListMenuTemplate sMainListTemplate = +{ + .items = sMainListItems, + .moveCursorFunc = NULL, + .itemPrintFunc = NULL, + .totalItems = ARRAY_COUNT(sMainListItems), + .maxShowed = 6, + .windowId = 0, + .header_X = 0, + .item_X = 8, + .cursor_X = 0, + .upText_Y = 1, + .cursorPal = 2, + .fillValue = 1, + .cursorShadowPal = 3, + .lettersSpacing = 1, + .itemVerticalPadding = 0, + .scrollMultiple = LIST_NO_MULTIPLE_SCROLL, + .fontId = 1, + .cursorKind = 0 +}; + +static const struct ListMenuTemplate sSecondaryListTemplate = +{ + .items = sSecondaryListItems, + .moveCursorFunc = NULL, + .itemPrintFunc = NULL, + .totalItems = 0, + .maxShowed = 0, + .windowId = 0, + .header_X = 0, + .item_X = 8, + .cursor_X = 0, + .upText_Y = 1, + .cursorPal = 2, + .fillValue = 1, + .cursorShadowPal = 3, + .lettersSpacing = 1, + .itemVerticalPadding = 0, + .scrollMultiple = LIST_NO_MULTIPLE_SCROLL, + .fontId = 1, + .cursorKind = 0 +}; + + +static const struct WindowTemplate sMainListWindowTemplate = +{ + .bg = 0, + .tilemapLeft = 1, + .tilemapTop = 3, + .width = 9, + .height = 12, + .paletteNum = 0xF, + .baseBlock = 0x2 +}; + +static const struct WindowTemplate sSecondaryListWindowTemplate = +{ + .bg = 0, + .tilemapLeft = 12, + .tilemapTop = 3, + .width = 10, + .height = 2, + .paletteNum = 0xF, + .baseBlock = 0xA0 +}; + +static const struct WindowTemplate sModifyWindowTemplate = +{ + .bg = 0, + .tilemapLeft = 25, + .tilemapTop = 2, + .width = 4, + .height = 2, + .paletteNum = 0xF, + .baseBlock = 0x200 +}; + +static const struct WindowTemplate sBattlerWindowTemplate = +{ + .bg = 0, + .tilemapLeft = 10, + .tilemapTop = 0, + .width = 14, + .height = 2, + .paletteNum = 0xF, + .baseBlock = 0x300 +}; + +static const struct BgTemplate sBgTemplates[] = +{ + { + .bg = 0, + .charBaseIndex = 0, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 1, + .baseTile = 0 + }, + { + .bg = 1, + .charBaseIndex = 2, + .mapBaseIndex = 20, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + } +}; + +static const u8 sBitsToMaxDigit[] = +{ + [0] = 0, + [1] = 1, // max 1 + [2] = 1, // max 3 + [3] = 1, // max 7 + [4] = 2, // max 15 + [5] = 2, // max 31 + [6] = 2, // max 63 + [7] = 3, // max 127 + [8] = 3, // max 255 +}; + +static const bool8 sHasChangeableEntries[LIST_ITEM_COUNT] = +{ + [LIST_ITEM_MOVES] = TRUE, + [LIST_ITEM_AI_MOVES_PTS] = TRUE, + [LIST_ITEM_PP] = TRUE, + [LIST_ITEM_ABILITY] = TRUE, + [LIST_ITEM_TYPES] = TRUE, + [LIST_ITEM_HELD_ITEM] = TRUE, + [LIST_ITEM_STAT_STAGES] = TRUE, +}; + +static const u16 sBgColor[] = {RGB_WHITE}; + +// this file's functions +static void Task_DebugMenuFadeOut(u8 taskId); +static void Task_DebugMenuProcessInput(u8 taskId); +static void Task_DebugMenuFadeIn(u8 taskId); +static void PrintOnBattlerWindow(u8 windowId, u8 battlerId); +static void UpdateWindowsOnChangedBattler(struct BattleDebugMenu *data); +static void CreateSecondaryListMenu(struct BattleDebugMenu *data); +static void PrintSecondaryEntries(struct BattleDebugMenu *data); +static void DestroyModifyArrows(struct BattleDebugMenu *data); +static void PrintDigitChars(struct BattleDebugMenu *data); +static void SetUpModifyArrows(struct BattleDebugMenu *data); +static void UpdateBattlerValue(struct BattleDebugMenu *data); +static void UpdateMonData(struct BattleDebugMenu *data); +static u8 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue); +static bool32 TryMoveDigit(struct BattleDebugModifyArrows *modArrows, bool32 moveUp); +static void SwitchToDebugView(u8 taskId); +static void SwitchToDebugViewFromAiParty(u8 taskId); + +// code +static struct BattleDebugMenu *GetStructPtr(u8 taskId) +{ + u8 *taskDataPtr = (u8 *)(&gTasks[taskId].data[0]); + + return (struct BattleDebugMenu*)(T1_READ_PTR(taskDataPtr)); +} + +static void SetStructPtr(u8 taskId, void *ptr) +{ + u32 structPtr = (u32)(ptr); + u8 *taskDataPtr = (u8 *)(&gTasks[taskId].data[0]); + + taskDataPtr[0] = structPtr >> 0; + taskDataPtr[1] = structPtr >> 8; + taskDataPtr[2] = structPtr >> 16; + taskDataPtr[3] = structPtr >> 24; +} + +static void MainCB2(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void VBlankCB(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void CB2_BattleDebugMenu(void) +{ + u8 taskId; + struct BattleDebugMenu *data; + + switch (gMain.state) + { + default: + case 0: + SetVBlankCallback(NULL); + gMain.state++; + break; + case 1: + ResetVramOamAndBgCntRegs(); + SetGpuReg(REG_OFFSET_DISPCNT, 0); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); + ResetAllBgsCoordinates(); + FreeAllWindowBuffers(); + DeactivateAllTextPrinters(); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); + ShowBg(0); + ShowBg(1); + gMain.state++; + break; + case 2: + ResetPaletteFade(); + ScanlineEffect_Stop(); + ResetTasks(); + ResetSpriteData(); + gMain.state++; + break; + case 3: + LoadPalette(sBgColor, 0, 2); + // LoadPalette(GetOverworldTextboxPalettePtr(), 0xf0, 16); // TODO: debug + LoadPalette(GetTextWindowPalette(2), 0xC0, 0x20); + gMain.state++; + break; + case 4: + taskId = CreateTask(Task_DebugMenuFadeIn, 0); + data = AllocZeroed(sizeof(struct BattleDebugMenu)); + SetStructPtr(taskId, data); + + data->battlerId = gBattleStruct->debugBattler; + data->battlerWindowId = AddWindow(&sBattlerWindowTemplate); + PutWindowTilemap(data->battlerWindowId); + PrintOnBattlerWindow(data->battlerWindowId, data->battlerId); + + data->mainListWindowId = AddWindow(&sMainListWindowTemplate); + + gMultiuseListMenuTemplate = sMainListTemplate; + gMultiuseListMenuTemplate.windowId = data->mainListWindowId; + data->mainListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, 0, 0); + + data->currentMainListItemId = 0; + data->activeWindow = ACTIVE_WIN_MAIN; + data->secondaryListTaskId = 0xFF; + CopyWindowToVram(data->mainListWindowId, COPYWIN_FULL); + gMain.state++; + break; + case 5: + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + SetVBlankCallback(VBlankCB); + SetMainCallback2(MainCB2); + return; + } +} + +static void PutMovesPointsText(struct BattleDebugMenu *data) +{ + u32 i, j, count, battlerDef; + u8 *text = Alloc(0x50); + + FillWindowPixelBuffer(data->aiMovesWindowId, 0x11); + for (i = 0; i < MAX_MON_MOVES; i++) + { + text[0] = CHAR_SPACE; + StringCopy(text + 1, GetMoveName(gBattleMons[data->aiBattlerId].moves[i])); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 0, i * 15, 0, NULL); + for (count = 0, j = 0; j < MAX_BATTLERS_COUNT; j++) + { + if (data->spriteIds.aiIconSpriteIds[j] == 0xFF) + continue; + battlerDef = gSprites[data->spriteIds.aiIconSpriteIds[j]].data[0]; + ConvertIntToDecimalStringN(text, + gBattleStruct->aiFinalScore[data->aiBattlerId][battlerDef][i], + STR_CONV_MODE_RIGHT_ALIGN, 3); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 83 + count * 54, i * 15, 0, NULL); + + ConvertIntToDecimalStringN(text, + AI_DATA->simulatedDmg[data->aiBattlerId][battlerDef][i].expected, + STR_CONV_MODE_RIGHT_ALIGN, 3); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 110 + count * 54, i * 15, 0, NULL); + + count++; + } + } + + CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL); + Free(text); +} + +static void CleanUpAiInfoWindow(u8 taskId) +{ + u32 i; + struct BattleDebugMenu *data = GetStructPtr(taskId); + + FreeMonIconPalettes(); + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (data->spriteIds.aiIconSpriteIds[i] != 0xFF) + DestroyMonIcon(&gSprites[data->spriteIds.aiIconSpriteIds[i]]); + } + FreeAndDestroyMonPicSprite(data->aiMonSpriteId); + ClearWindowTilemap(data->aiMovesWindowId); + RemoveWindow(data->aiMovesWindowId); +} + +static void Task_ShowAiPoints(u8 taskId) +{ + u32 i, count; + struct WindowTemplate winTemplate; + struct BattleDebugMenu *data = GetStructPtr(taskId); + struct Pokemon *mon; + + switch (data->aiViewState) + { + case 0: + HideBg(0); + ShowBg(1); + + // Swap battler if it's player mon + data->aiBattlerId = data->battlerId; + while (!BattlerHasAi(data->aiBattlerId)) + { + if (++data->aiBattlerId >= gBattlersCount) + data->aiBattlerId = 0; + } + data->battlerId = data->aiBattlerId; + + LoadMonIconPalettes(); + for (count = 0, i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (i != data->aiBattlerId && IsBattlerAlive(i)) + { + data->spriteIds.aiIconSpriteIds[i] = CreateMonIcon(gBattleMons[i].species, + SpriteCallbackDummy, + 95 + (count * 60), 17, 0, 0); + gSprites[data->spriteIds.aiIconSpriteIds[i]].data[0] = i; // battler id + count++; + } + else + { + data->spriteIds.aiIconSpriteIds[i] = 0xFF; + } + } + + mon = &GetBattlerParty(data->aiBattlerId)[gBattlerPartyIndexes[data->aiBattlerId]]; + + data->aiMonSpriteId = CreateMonPicSprite(gBattleMons[data->aiBattlerId].species, + GetMonData(mon, MON_DATA_IS_SHINY), + gBattleMons[data->aiBattlerId].personality, + TRUE, + 39, 130, 15, TAG_NONE); + data->aiViewState++; + break; + // Put text + case 1: + winTemplate = SetWindowTemplateFields(1, 0, 4, 30, 14, 15, 0x200); + data->aiMovesWindowId = AddWindow(&winTemplate); + PutWindowTilemap(data->aiMovesWindowId); + PutMovesPointsText(data); + + data->aiViewState++; + break; + // Input + case 2: + if (JOY_NEW(R_BUTTON) && IsDoubleBattle()) + { + CleanUpAiInfoWindow(taskId); + do { + data->battlerId++; + data->battlerId %= gBattlersCount; + } while (!IsBattlerAlive(data->battlerId)); + data->aiViewState = 0; + } + else if (JOY_NEW(L_BUTTON) && IsDoubleBattle()) + { + CleanUpAiInfoWindow(taskId); + do { + if (data->battlerId == 0) + data->battlerId = gBattlersCount - 1; + else + data->battlerId--; + } while (!IsBattlerAlive(data->battlerId) || !BattlerHasAi(data->battlerId)); + data->aiViewState = 0; + } + else if (JOY_NEW(SELECT_BUTTON | B_BUTTON)) + { + SwitchToDebugView(taskId); + HideBg(1); + ShowBg(0); + return; + } + break; + } +} + +static void SwitchToAiPointsView(u8 taskId) +{ + gTasks[taskId].func = Task_ShowAiPoints; + GetStructPtr(taskId)->aiViewState = 0; +} + +static const u8 *const sAiInfoItemNames[] = +{ + sText_Ability, + sText_HeldItem, + sText_HoldEffect, +}; + +static void PutAiInfoText(struct BattleDebugMenu *data) +{ + u32 i; + u8 *text = Alloc(0x50); + + FillWindowPixelBuffer(data->aiMovesWindowId, 0x11); + + // item names + for (i = 0; i < ARRAY_COUNT(sAiInfoItemNames); i++) + { + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, sAiInfoItemNames[i], 3, i * 15, 0, NULL); + } + + // items info + for (i = 0; i < gBattlersCount; i++) + { + if (GetBattlerSide(i) == B_SIDE_PLAYER && IsBattlerAlive(i)) + { + u16 ability = AI_DATA->abilities[i]; + u16 holdEffect = AI_DATA->holdEffects[i]; + u16 item = AI_DATA->items[i]; + u8 x = (i == B_POSITION_PLAYER_LEFT) ? 83 + (i) * 75 : 83 + (i-1) * 75; + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, gAbilitiesInfo[ability].name, x, 0, 0, NULL); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, ItemId_GetName(item), x, 15, 0, NULL); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, GetHoldEffectName(holdEffect), x, 30, 0, NULL); + } + } + + CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL); + Free(text); +} + +static void PutAiPartyText(struct BattleDebugMenu *data) +{ + u32 i, j, count; + u8 *text = Alloc(0x50), *txtPtr; + struct AiPartyMon *aiMons = AI_PARTY->mons[GetBattlerSide(data->aiBattlerId)]; + + FillWindowPixelBuffer(data->aiMovesWindowId, 0x11); + count = AI_PARTY->count[GetBattlerSide(data->aiBattlerId)]; + for (i = 0; i < count; i++) + { + if (aiMons[i].wasSentInBattle) + { + text[0] = CHAR_LV; + txtPtr = ConvertIntToDecimalStringN(text + 1, aiMons[i].level, STR_CONV_MODE_LEFT_ALIGN, 3); + *txtPtr++ = CHAR_SPACE; + if (aiMons[i].gender == MON_MALE) + *txtPtr++ = CHAR_MALE; + else if (aiMons[i].gender == MON_FEMALE) + *txtPtr++ = CHAR_FEMALE; + *txtPtr = EOS; + AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL, text, i * 41, 0, 0, NULL, 0, 0); // TODO: font FONT_SMALL_NARROW + } + + txtPtr = StringCopyN(text, gAbilitiesInfo[aiMons[i].ability].name, 7); // The screen is too small to fit the whole string, so we need to drop the last letters. + *txtPtr = EOS; + AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL, text, i * 41, 15, 0, NULL, 0, 0); // TODO: font FONT_SMALL_NARROW + + for (j = 0; j < MAX_MON_MOVES; j++) + { + txtPtr = StringCopyN(text, GetMoveName(aiMons[i].moves[j]), 8); + *txtPtr = EOS; + AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL, text, i * 41, 35 + j * 15, 0, NULL, 0, 0); // TODO: font FONT_SMALL_NARROW + } + + txtPtr = StringCopyN(text, GetHoldEffectName(aiMons[i].heldEffect), 7); + *txtPtr = EOS; + AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL, text, i * 41, 35 + j * 15, 0, NULL, 0, 0); // TODO: font FONT_SMALL_NARROW + + txtPtr = ConvertIntToDecimalStringN(text, aiMons[i].switchInCount, STR_CONV_MODE_LEFT_ALIGN, 2); + *txtPtr = EOS; + AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL, text, i * 41, 35 + (j + 1) * 15, 0, NULL, 0, 0); // TODO: font FONT_SMALL_NARROW + } + + CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL); + Free(text); +} + +static void Task_ShowAiKnowledge(u8 taskId) +{ + u32 i, count; + struct WindowTemplate winTemplate; + struct BattleDebugMenu *data = GetStructPtr(taskId); + struct Pokemon *mon; + + switch (data->aiViewState) + { + case 0: + HideBg(0); + ShowBg(1); + + // Swap battler if it's player mon + data->aiBattlerId = data->battlerId; + while (!BattlerHasAi(data->aiBattlerId)) + { + if (++data->aiBattlerId >= gBattlersCount) + data->aiBattlerId = 0; + } + + LoadMonIconPalettes(); + for (count = 0, i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (GetBattlerSide(i) == B_SIDE_PLAYER && IsBattlerAlive(i)) + { + data->spriteIds.aiIconSpriteIds[i] = CreateMonIcon(gBattleMons[i].species, + SpriteCallbackDummy, + 95 + (count * 80), 17, 0, 0); + gSprites[data->spriteIds.aiIconSpriteIds[i]].data[0] = i; // battler id + count++; + } + else + { + data->spriteIds.aiIconSpriteIds[i] = 0xFF; + } + } + + mon = &GetBattlerParty(data->aiBattlerId)[gBattlerPartyIndexes[data->aiBattlerId]]; + + data->aiMonSpriteId = CreateMonPicSprite(gBattleMons[data->aiBattlerId].species, + GetMonData(mon, MON_DATA_IS_SHINY), + gBattleMons[data->aiBattlerId].personality, + TRUE, + 39, 130, 15, TAG_NONE); + data->aiViewState++; + break; + // Put text + case 1: + winTemplate = SetWindowTemplateFields(1, 0, 4, 27, 14, 15, 0x200); + data->aiMovesWindowId = AddWindow(&winTemplate); + PutWindowTilemap(data->aiMovesWindowId); + PutAiInfoText(data); + data->aiViewState++; + break; + // Input + case 2: + if (JOY_NEW(SELECT_BUTTON | B_BUTTON)) + { + SwitchToDebugView(taskId); + HideBg(1); + ShowBg(0); + return; + } + break; + } +} + +#define sConditionSpriteId data[1] + +static void Task_ShowAiParty(u8 taskId) +{ + u32 i, ailment; + struct WindowTemplate winTemplate; + struct AiPartyMon *aiMons; + struct BattleDebugMenu *data = GetStructPtr(taskId); + + switch (data->aiViewState) + { + case 0: + HideBg(0); + ShowBg(1); + + LoadMonIconPalettes(); + LoadPartyMenuAilmentGfx(); + data->aiBattlerId = data->battlerId; + aiMons = AI_PARTY->mons[GetBattlerSide(data->aiBattlerId)]; + for (i = 0; i < AI_PARTY->count[GetBattlerSide(data->aiBattlerId)]; i++) + { + u16 species = SPECIES_NONE; // Question mark + if (aiMons[i].wasSentInBattle && aiMons[i].species) + species = aiMons[i].species; + data->spriteIds.aiPartyIcons[i] = CreateMonIcon(species, SpriteCallbackDummy, (i * 41) + 15, 7, 1, 0); + gSprites[data->spriteIds.aiPartyIcons[i]].oam.priority = 0; + + gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId = CreateSprite(&gSpriteTemplate_StatusIcons, (i * 41) + 15, 7, 0); + gSprites[gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId].oam.priority = 0; + if (aiMons[i].isFainted) + ailment = AILMENT_FNT; + else + ailment = GetAilmentFromStatus(aiMons[i].status); + + if (ailment != AILMENT_NONE) + StartSpriteAnim(&gSprites[gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId], ailment - 1); + else + gSprites[gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId].invisible = TRUE; + } + for (; i < PARTY_SIZE; i++) + data->spriteIds.aiPartyIcons[i] = 0xFF; + data->aiViewState++; + break; + // Put text + case 1: + winTemplate = SetWindowTemplateFields(1, 0, 3, 29, 16, 15, 0x150); + data->aiMovesWindowId = AddWindow(&winTemplate); + PutWindowTilemap(data->aiMovesWindowId); + PutAiPartyText(data); + data->aiViewState++; + break; + // Input + case 2: + if (JOY_NEW(SELECT_BUTTON | B_BUTTON)) + { + SwitchToDebugViewFromAiParty(taskId); + HideBg(1); + ShowBg(0); + return; + } + break; + } +} + +static void SwitchToAiInfoView(u8 taskId) +{ + gTasks[taskId].func = Task_ShowAiKnowledge; + GetStructPtr(taskId)->aiViewState = 0; +} + +static void SwitchToAiPartyView(u8 taskId) +{ + gTasks[taskId].func = Task_ShowAiParty; + GetStructPtr(taskId)->aiViewState = 0; +} + +static void SwitchToDebugViewFromAiParty(u8 taskId) +{ + u32 i; + struct BattleDebugMenu *data = GetStructPtr(taskId); + + FreeMonIconPalettes(); + for (i = 0; i < PARTY_SIZE; i++) + { + if (data->spriteIds.aiPartyIcons[i] != 0xFF) + { + DestroySpriteAndFreeResources(&gSprites[gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId]); + DestroyMonIcon(&gSprites[data->spriteIds.aiPartyIcons[i]]); + } + } + ClearWindowTilemap(data->aiMovesWindowId); + RemoveWindow(data->aiMovesWindowId); + + gTasks[taskId].func = Task_DebugMenuProcessInput; +} + +#undef sConditionSpriteId + +static void SwitchToDebugView(u8 taskId) +{ + CleanUpAiInfoWindow(taskId); + gTasks[taskId].func = Task_DebugMenuProcessInput; +} + +static void Task_DebugMenuFadeIn(u8 taskId) +{ + if (!gPaletteFade.active) + gTasks[taskId].func = Task_DebugMenuProcessInput; +} + +static void Task_DebugMenuProcessInput(u8 taskId) +{ + s32 listItemId = 0; + struct BattleDebugMenu *data = GetStructPtr(taskId); + + // Exit the menu. + if (JOY_NEW(SELECT_BUTTON) || ((JOY_NEW(B_BUTTON)) && data->activeWindow == ACTIVE_WIN_MAIN)) + { + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gTasks[taskId].func = Task_DebugMenuFadeOut; + return; + } + + // Try changing active battler. + if (JOY_NEW(R_BUTTON)) + { + if (data->battlerId++ == gBattlersCount - 1) + data->battlerId = 0; + UpdateWindowsOnChangedBattler(data); + } + else if (JOY_NEW(L_BUTTON)) + { + if (data->battlerId-- == 0) + data->battlerId = gBattlersCount - 1; + UpdateWindowsOnChangedBattler(data); + } + + // A main list item is active, handle input. + if (data->activeWindow == ACTIVE_WIN_MAIN) + { + listItemId = ListMenu_ProcessInput(data->mainListTaskId); + if (listItemId != LIST_CANCEL && listItemId != LIST_NOTHING_CHOSEN && listItemId < LIST_ITEM_COUNT) + { + if (listItemId == LIST_ITEM_AI_MOVES_PTS && JOY_NEW(A_BUTTON)) + { + SwitchToAiPointsView(taskId); + return; + } + else if (listItemId == LIST_ITEM_AI_INFO && JOY_NEW(A_BUTTON)) + { + SwitchToAiInfoView(taskId); + return; + } + else if (listItemId == LIST_ITEM_AI_PARTY && JOY_NEW(A_BUTTON)) + { + SwitchToAiPartyView(taskId); + return; + } + data->currentMainListItemId = listItemId; + + // Create the secondary menu list. + CreateSecondaryListMenu(data); + PrintSecondaryEntries(data); + data->activeWindow = ACTIVE_WIN_SECONDARY; + } + } + // Secondary list is active, handle input. + else if (data->activeWindow == ACTIVE_WIN_SECONDARY) + { + listItemId = ListMenu_ProcessInput(data->secondaryListTaskId); + if (listItemId == LIST_CANCEL) + { + DestroyListMenuTask(data->secondaryListTaskId, NULL, NULL); + ClearStdWindowAndFrameToTransparent(data->secondaryListWindowId, TRUE); + RemoveWindow(data->secondaryListWindowId); + data->activeWindow = ACTIVE_WIN_MAIN; + data->secondaryListTaskId = 0xFF; + } + else if (listItemId != LIST_NOTHING_CHOSEN) + { + data->currentSecondaryListItemId = listItemId; + data->modifyWindowId = AddWindow(&sModifyWindowTemplate); + PutWindowTilemap(data->modifyWindowId); + CopyWindowToVram(data->modifyWindowId, COPYWIN_FULL); + SetUpModifyArrows(data); + PrintDigitChars(data); + data->activeWindow = ACTIVE_WIN_MODIFY; + } + } + // Handle value modifying. + else if (data->activeWindow == ACTIVE_WIN_MODIFY) + { + if (JOY_NEW(B_BUTTON | A_BUTTON)) + { + ClearStdWindowAndFrameToTransparent(data->modifyWindowId, TRUE); + RemoveWindow(data->modifyWindowId); + DestroyModifyArrows(data); + data->activeWindow = ACTIVE_WIN_SECONDARY; + } + else if (JOY_NEW(DPAD_RIGHT)) + { + if (data->modifyArrows.currentDigit != (data->modifyArrows.maxDigits - 1)) + { + data->modifyArrows.currentDigit++; + gSprites[data->modifyArrows.arrowSpriteId[0]].x2 += 6; + gSprites[data->modifyArrows.arrowSpriteId[1]].x2 += 6; + } + } + else if (JOY_NEW(DPAD_LEFT)) + { + if (data->modifyArrows.currentDigit != 0) + { + data->modifyArrows.currentDigit--; + gSprites[data->modifyArrows.arrowSpriteId[0]].x2 -= 6; + gSprites[data->modifyArrows.arrowSpriteId[1]].x2 -= 6; + } + } + else if (JOY_NEW(DPAD_UP)) + { + if (TryMoveDigit(&data->modifyArrows, TRUE)) + { + PrintDigitChars(data); + UpdateBattlerValue(data); + PrintSecondaryEntries(data); + } + } + else if (JOY_NEW(DPAD_DOWN)) + { + if (TryMoveDigit(&data->modifyArrows, FALSE)) + { + PrintDigitChars(data); + UpdateBattlerValue(data); + PrintSecondaryEntries(data); + } + } + } +} + +static void Task_DebugMenuFadeOut(u8 taskId) +{ + if (!gPaletteFade.active) + { + struct BattleDebugMenu *data = GetStructPtr(taskId); + DestroyListMenuTask(data->mainListTaskId, 0, 0); + if (data->secondaryListTaskId != 0xFF) + DestroyListMenuTask(data->secondaryListTaskId, 0, 0); + + FreeAllWindowBuffers(); + UpdateMonData(data); + gBattleStruct->debugBattler = data->battlerId; + Free(data); + DestroyTask(taskId); + SetMainCallback2(ReshowBattleScreenAfterMenu); + } +} + +static void PrintOnBattlerWindow(u8 windowId, u8 battlerId) +{ + u8 text[POKEMON_NAME_LENGTH + 10]; + + text[0] = CHAR_0 + battlerId; + text[1] = CHAR_SPACE; + text[2] = CHAR_HYPHEN; + text[3] = CHAR_SPACE; + StringCopy(&text[4], gBattleMons[battlerId].nickname); + + FillWindowPixelBuffer(windowId, 0x11); + AddTextPrinterParameterized(windowId, FONT_NORMAL, text, 0, 0, 0, NULL); + CopyWindowToVram(windowId, COPYWIN_FULL); +} + +static void UpdateWindowsOnChangedBattler(struct BattleDebugMenu *data) +{ + PrintOnBattlerWindow(data->battlerWindowId, data->battlerId); + if (data->secondaryListTaskId != 0xFF) + { + DestroyListMenuTask(data->secondaryListTaskId, 0, 0); + RemoveWindow(data->secondaryListWindowId); + CreateSecondaryListMenu(data); + data->currentSecondaryListItemId = 0; + PrintSecondaryEntries(data); + } + if (data->activeWindow == ACTIVE_WIN_MODIFY) + { + DestroyModifyArrows(data); + SetUpModifyArrows(data); + PrintDigitChars(data); + } +} + + +static void CreateSecondaryListMenu(struct BattleDebugMenu *data) +{ + struct WindowTemplate winTemplate; + struct ListMenuTemplate listTemplate; + u8 itemsCount = 1; + + winTemplate = sSecondaryListWindowTemplate; + listTemplate = sSecondaryListTemplate; + + switch (data->currentMainListItemId) + { + case LIST_ITEM_ABILITY: + itemsCount = 1; + break; + case LIST_ITEM_HELD_ITEM: + itemsCount = 1; + break; + case LIST_ITEM_TYPES: + itemsCount = 3; + break; + case LIST_ITEM_MOVES: + itemsCount = 5; + break; + case LIST_ITEM_PP: + itemsCount = 4; + break; + case LIST_ITEM_STATS: + listTemplate.items = sStatsListItems; + itemsCount = ARRAY_COUNT(sStatsListItems); + break; + case LIST_ITEM_STAT_STAGES: + itemsCount = 8; + break; + case LIST_ITEM_STATUS1: + listTemplate.items = sStatus1ListItems; + itemsCount = ARRAY_COUNT(sStatus1ListItems); + data->bitfield = sStatus1Bitfield; + break; + case LIST_ITEM_STATUS2: + listTemplate.items = sStatus2ListItems; + itemsCount = ARRAY_COUNT(sStatus2ListItems); + data->bitfield = sStatus2Bitfield; + winTemplate.height = 1; + break; + case LIST_ITEM_STATUS3: + listTemplate.items = sStatus3ListItems; + itemsCount = ARRAY_COUNT(sStatus3ListItems); + data->bitfield = sStatus3Bitfield; + break; + case LIST_ITEM_STATUS4: + listTemplate.items = sStatus4ListItems; + itemsCount = ARRAY_COUNT(sStatus4ListItems); + data->bitfield = sStatus4Bitfield; + break; + case LIST_ITEM_AI: + listTemplate.items = sAIListItems; + itemsCount = ARRAY_COUNT(sAIListItems); + data->bitfield = sAIBitfield; + break; + case LIST_ITEM_VARIOUS: + listTemplate.items = sVariousListItems; + itemsCount = ARRAY_COUNT(sVariousListItems); + break; + case LIST_ITEM_SIDE_STATUS: + listTemplate.items = sSideStatusListItems; + itemsCount = ARRAY_COUNT(sSideStatusListItems); + break; + case LIST_ITEM_AI_MOVES_PTS: + case LIST_ITEM_AI_INFO: + return; + } + + data->secondaryListItemCount = itemsCount; + winTemplate.height *= itemsCount; + data->secondaryListWindowId = AddWindow(&winTemplate); + + listTemplate.totalItems = itemsCount; + listTemplate.maxShowed = itemsCount; + if (listTemplate.maxShowed > 7 && !sHasChangeableEntries[data->currentMainListItemId]) + listTemplate.maxShowed = 7; + listTemplate.windowId = data->secondaryListWindowId; + + data->secondaryListTaskId = ListMenuInit(&listTemplate, 0, 0); + CopyWindowToVram(data->secondaryListWindowId, COPYWIN_FULL); +} + +static void PadString(const u8 *src, u8 *dst) +{ + u32 i; + + for (i = 0; i < 17 && src[i] != EOS; i++) + dst[i] = src[i]; + + for (; i < 17; i++) + dst[i] = CHAR_SPACE; + + dst[i] = EOS; +} + +static const u8 sTextAll[] = _("All"); + +static void PrintSecondaryEntries(struct BattleDebugMenu *data) +{ + u8 text[20]; + s32 i; + struct TextPrinterTemplate printer; + u8 yMultiplier; + + // Do not print entries if they are not changing. + if (!sHasChangeableEntries[data->currentMainListItemId]) + return; + + yMultiplier = (GetFontAttribute(sSecondaryListTemplate.fontId, 1) + sSecondaryListTemplate.itemVerticalPadding); + + printer.windowId = data->secondaryListWindowId; + printer.fontId = 1; + printer.unk = 0; + printer.letterSpacing = 0; + printer.lineSpacing = 1; + printer.fgColor = 2; + printer.bgColor = 1; + printer.shadowColor = 3; + printer.x = sSecondaryListTemplate.item_X; + printer.currentX = sSecondaryListTemplate.item_X; + printer.currentChar = text; + + switch (data->currentMainListItemId) + { + case LIST_ITEM_MOVES: + case LIST_ITEM_PP: + for (i = 0; i < 4; i++) + { + PadString(GetMoveName(gBattleMons[data->battlerId].moves[i]), text); + printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y; + AddTextPrinter(&printer, 0, NULL); + } + // Allow changing all moves at once. Useful for testing in wild doubles. + if (data->currentMainListItemId == LIST_ITEM_MOVES) + { + PadString(sTextAll, text); + printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y; + AddTextPrinter(&printer, 0, NULL); + } + break; + case LIST_ITEM_ABILITY: + PadString(gAbilitiesInfo[gBattleMons[data->battlerId].ability].name, text); + printer.currentY = printer.y = sSecondaryListTemplate.upText_Y; + AddTextPrinter(&printer, 0, NULL); + break; + case LIST_ITEM_HELD_ITEM: + PadString(ItemId_GetName(gBattleMons[data->battlerId].item), text); + printer.currentY = printer.y = sSecondaryListTemplate.upText_Y; + AddTextPrinter(&printer, 0, NULL); + break; + case LIST_ITEM_TYPES: + for (i = 0; i < 3; i++) + { + u8 *types = &gBattleMons[data->battlerId].type1; + + PadString(gTypesInfo[types[i]].name, text); + printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y; + AddTextPrinter(&printer, 0, NULL); + } + break; + case LIST_ITEM_STAT_STAGES: + for (i = 0; i < NUM_BATTLE_STATS - 1; i++) + { + u8 *txtPtr = StringCopy(text, gStatNamesTable[STAT_ATK + i]); + txtPtr[0] = CHAR_SPACE; + if (gBattleMons[data->battlerId].statStages[STAT_ATK + i] >= DEFAULT_STAT_STAGE) + { + txtPtr[1] = CHAR_PLUS; + txtPtr[2] = CHAR_0 + (gBattleMons[data->battlerId].statStages[STAT_ATK + i] - DEFAULT_STAT_STAGE); + } + else + { + txtPtr[1] = CHAR_HYPHEN; + txtPtr[2] = CHAR_6 - (gBattleMons[data->battlerId].statStages[STAT_ATK + i]); + } + txtPtr[3] = EOS; + + PadString(text, text); + printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y; + AddTextPrinter(&printer, 0, NULL); + } + // Allow changing all stat stages at once. + PadString(sTextAll, text); + printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y; + AddTextPrinter(&printer, 0, NULL); + break; + } +} + +static void DestroyModifyArrows(struct BattleDebugMenu *data) +{ + FreeSpritePaletteByTag(gSpritePalette_Arrow.tag); + if (data->modifyArrows.arrowSpriteId[0] != 0xFF) + DestroySprite(&gSprites[data->modifyArrows.arrowSpriteId[0]]); + if (data->modifyArrows.arrowSpriteId[1] != 0xFF) + DestroySprite(&gSprites[data->modifyArrows.arrowSpriteId[1]]); +} + +static void PrintDigitChars(struct BattleDebugMenu *data) +{ + s32 i; + u8 text[MAX_MODIFY_DIGITS + 1]; + + for (i = 0; i < data->modifyArrows.maxDigits; i++) + text[i] = data->modifyArrows.charDigits[i]; + + text[i] = EOS; + + AddTextPrinterParameterized(data->modifyWindowId, FONT_NORMAL, text, 3, 0, 0, NULL); +} + +static const u32 GetBitfieldToAndValue(u32 currBit, u32 bitsCount) +{ + u32 i; + u32 toAnd = 0; + + for (i = 0; i < bitsCount; i++) + toAnd |= (1 << (currBit + i)); + + return toAnd; +} + +static const u32 GetBitfieldValue(u32 value, u32 currBit, u32 bitsCount) +{ + return (value & (GetBitfieldToAndValue(currBit, bitsCount))) >> currBit; +} + +static void UpdateBattlerValue(struct BattleDebugMenu *data) +{ + u32 i; + switch (data->modifyArrows.typeOfVal) + { + case VAL_U8: + *(u8 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue; + break; + case VAL_S8: + *(s8 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue; + break; + case VAL_U16: + *(u16 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue; + break; + case VAR_U16_4_ENTRIES: + ((u16 *)(data->modifyArrows.modifiedValPtr))[0] = data->modifyArrows.currValue; + ((u16 *)(data->modifyArrows.modifiedValPtr))[1] = data->modifyArrows.currValue; + ((u16 *)(data->modifyArrows.modifiedValPtr))[2] = data->modifyArrows.currValue; + ((u16 *)(data->modifyArrows.modifiedValPtr))[3] = data->modifyArrows.currValue; + break; + case VAL_ALL_STAT_STAGES: + for (i = 0; i < NUM_BATTLE_STATS; i++) + gBattleMons[data->battlerId].statStages[i] = data->modifyArrows.currValue; + break; + case VAL_U32: + *(u32 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue; + break; + case VAL_BITFIELD_32: + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~(GetBitfieldToAndValue(data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount)); + *(u32 *)(data->modifyArrows.modifiedValPtr) |= (data->modifyArrows.currValue << data->bitfield[data->currentSecondaryListItemId].currBit); + break; + case VAR_SIDE_STATUS: + *GetSideStatusValue(data, TRUE, data->modifyArrows.currValue != 0) = data->modifyArrows.currValue; + break; + case VAR_SHOW_HP: + (*(struct BattleSpriteInfo*)(data->modifyArrows.modifiedValPtr)).hpNumbersNoBars = data->modifyArrows.currValue; + break; + case VAR_SUBSTITUTE: + *(u8 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue; + if (*(u8 *)(data->modifyArrows.modifiedValPtr) == 0) + { + gBattleMons[data->battlerId].status2 &= ~STATUS2_SUBSTITUTE; + gBattleSpritesDataPtr->battlerData[data->battlerId].behindSubstitute = 0; + } + else + { + gBattleMons[data->battlerId].status2 |= STATUS2_SUBSTITUTE; + gBattleSpritesDataPtr->battlerData[data->battlerId].behindSubstitute = 1; + } + break; + case VAR_IN_LOVE: + if (data->modifyArrows.currValue) + { + if (IsBattlerAlive(BATTLE_OPPOSITE(data->battlerId))) + gBattleMons[data->battlerId].status2 |= STATUS2_INFATUATED_WITH(BATTLE_OPPOSITE(data->battlerId)); + else + gBattleMons[data->battlerId].status2 |= STATUS2_INFATUATED_WITH(BATTLE_PARTNER(BATTLE_OPPOSITE(data->battlerId))); + } + else + { + gBattleMons[data->battlerId].status2 &= ~STATUS2_INFATUATION; + } + break; + } + data->battlerWasChanged[data->battlerId] = TRUE; +} + +static u32 CharDigitsToValue(u8 *charDigits, u8 maxDigits) +{ + s32 i; + u8 id = 0; + u32 newValue = 0; + u8 valueDigits[MAX_MODIFY_DIGITS]; + + for (i = 0; i < MAX_MODIFY_DIGITS; i++) + valueDigits[i] = charDigits[i] - CHAR_0; + + if (maxDigits >= MAX_MODIFY_DIGITS) + newValue += valueDigits[id++] * 1000; + if (maxDigits >= MAX_MODIFY_DIGITS - 1) + newValue += valueDigits[id++] * 100; + if (maxDigits >= MAX_MODIFY_DIGITS - 2) + newValue += valueDigits[id++] * 10; + if (maxDigits >= MAX_MODIFY_DIGITS - 3) + newValue += valueDigits[id++]; + + return newValue; +} + +static void ValueToCharDigits(u8 *charDigits, u32 newValue, u8 maxDigits) +{ + s32 i; + u8 valueDigits[MAX_MODIFY_DIGITS]; + u8 id = 0; + + if (maxDigits >= MAX_MODIFY_DIGITS) + valueDigits[id++] = newValue / 1000; + if (maxDigits >= MAX_MODIFY_DIGITS - 1) + valueDigits[id++] = (newValue % 1000) / 100; + if (maxDigits >= MAX_MODIFY_DIGITS - 2) + valueDigits[id++] = (newValue % 100) / 10; + if (maxDigits >= MAX_MODIFY_DIGITS - 3) + valueDigits[id++] = newValue % 10; + + for (i = 0; i < MAX_MODIFY_DIGITS; i++) + charDigits[i] = valueDigits[i] + CHAR_0; +} + +static u8 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue) +{ + struct SideTimer *sideTimer = &gSideTimers[GetBattlerSide(data->battlerId)]; + + switch (data->currentSecondaryListItemId) + { + case LIST_SIDE_REFLECT: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_REFLECT; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_REFLECT; + sideTimer->reflectBattlerId = data->battlerId; + } + return &sideTimer->reflectTimer; + case LIST_SIDE_LIGHTSCREEN: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_LIGHTSCREEN; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_LIGHTSCREEN; + sideTimer->lightscreenBattlerId = data->battlerId; + } + return &sideTimer->lightscreenTimer; + case LIST_SIDE_SPIKES: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_SPIKES; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_SPIKES; + } + return &sideTimer->spikesAmount; + case LIST_SIDE_SAFEGUARD: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_SAFEGUARD; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_SAFEGUARD; + sideTimer->safeguardBattlerId = data->battlerId; + } + return &sideTimer->safeguardTimer; + case LIST_SIDE_MIST: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_MIST; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_MIST; + sideTimer->mistBattlerId = data->battlerId; + } + return &sideTimer->mistTimer; + case LIST_SIDE_AURORA_VEIL: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_AURORA_VEIL; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_AURORA_VEIL; + sideTimer->auroraVeilBattlerId = data->battlerId; + } + return &sideTimer->auroraVeilTimer; + case LIST_SIDE_LUCKY_CHANT: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_LUCKY_CHANT; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_LUCKY_CHANT; + sideTimer->luckyChantBattlerId = data->battlerId; + } + return &sideTimer->luckyChantTimer; + case LIST_SIDE_TAILWIND: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_TAILWIND; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_TAILWIND; + sideTimer->tailwindBattlerId = data->battlerId; + } + return &sideTimer->tailwindTimer; + case LIST_SIDE_STEALTH_ROCK: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEALTH_ROCK; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STEALTH_ROCK; + } + return &sideTimer->stealthRockAmount; + case LIST_SIDE_TOXIC_SPIKES: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_TOXIC_SPIKES; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_TOXIC_SPIKES; + } + return &sideTimer->toxicSpikesAmount; + case LIST_SIDE_STICKY_WEB: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STICKY_WEB; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STICKY_WEB; + } + return &sideTimer->stickyWebAmount; + case LIST_SIDE_STEELSURGE: + if (changeStatus) + { + if (statusTrue) + *(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEELSURGE; + else + *(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STEELSURGE; + } + return &sideTimer->steelsurgeAmount; + default: + return NULL; + } +} + +static void SetUpModifyArrows(struct BattleDebugMenu *data) +{ + LoadSpritePalette(&gSpritePalette_Arrow); + data->modifyArrows.arrowSpriteId[0] = CreateSprite(&gSpriteTemplate_Arrow, 207, 12, 0); + data->modifyArrows.arrowSpriteId[1] = CreateSprite(&gSpriteTemplate_Arrow, 207, 36, 0); + gSprites[data->modifyArrows.arrowSpriteId[1]].animNum = 1; + switch (data->currentMainListItemId) + { + case LIST_ITEM_ABILITY: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = ABILITIES_COUNT - 1; + data->modifyArrows.maxDigits = 3; + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].ability; + data->modifyArrows.typeOfVal = VAL_U16; + data->modifyArrows.currValue = gBattleMons[data->battlerId].ability; + break; + case LIST_ITEM_MOVES: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = MOVES_COUNT - 1; + data->modifyArrows.maxDigits = 3; + if (data->currentSecondaryListItemId == 4) + { + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].moves[0]; + data->modifyArrows.currValue = gBattleMons[data->battlerId].moves[0]; + data->modifyArrows.typeOfVal = VAR_U16_4_ENTRIES; + } + else + { + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].moves[data->currentSecondaryListItemId]; + data->modifyArrows.currValue = gBattleMons[data->battlerId].moves[data->currentSecondaryListItemId]; + data->modifyArrows.typeOfVal = VAL_U16; + } + break; + case LIST_ITEM_PP: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = CalculatePPWithBonus(gBattleMons[data->battlerId].moves[data->currentSecondaryListItemId], gBattleMons[data->battlerId].ppBonuses, data->currentSecondaryListItemId); + data->modifyArrows.maxDigits = 2; + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].pp[data->currentSecondaryListItemId]; + data->modifyArrows.typeOfVal = VAL_U8; + data->modifyArrows.currValue = gBattleMons[data->battlerId].pp[data->currentSecondaryListItemId]; + break; + case LIST_ITEM_HELD_ITEM: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = ITEMS_COUNT - 1; + data->modifyArrows.maxDigits = 3; + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].item; + data->modifyArrows.typeOfVal = VAL_U16; + data->modifyArrows.currValue = gBattleMons[data->battlerId].item; + break; + case LIST_ITEM_TYPES: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = NUMBER_OF_MON_TYPES - 1; + data->modifyArrows.maxDigits = 2; + data->modifyArrows.modifiedValPtr = (u8 *)((&gBattleMons[data->battlerId].type1) + data->currentSecondaryListItemId); + data->modifyArrows.typeOfVal = VAL_U8; + data->modifyArrows.currValue = *(u8 *)((&gBattleMons[data->battlerId].type1) + data->currentSecondaryListItemId); + break; + case LIST_ITEM_STATS: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = 9999; + data->modifyArrows.maxDigits = 4; + if (data->currentSecondaryListItemId == 0) + { + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].hp; + data->modifyArrows.currValue = gBattleMons[data->battlerId].hp; + data->modifyArrows.minValue = 1; + data->modifyArrows.maxValue = gBattleMons[data->battlerId].maxHP; + } + else if (data->currentSecondaryListItemId == 1) + { + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].maxHP; + data->modifyArrows.minValue = gBattleMons[data->battlerId].hp; + data->modifyArrows.currValue = gBattleMons[data->battlerId].maxHP; + } + else + { + data->modifyArrows.modifiedValPtr = (u16 *)((&gBattleMons[data->battlerId].attack) + (data->currentSecondaryListItemId - 2)); + data->modifyArrows.currValue = *(u16 *)((&gBattleMons[data->battlerId].attack) + (data->currentSecondaryListItemId - 2)); + } + data->modifyArrows.typeOfVal = VAL_U16; + break; + case LIST_ITEM_STAT_STAGES: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = 12; + data->modifyArrows.maxDigits = 2; + if (data->currentSecondaryListItemId == NUM_BATTLE_STATS - 1) // Change all stats + { + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].statStages[STAT_ATK]; + data->modifyArrows.currValue = gBattleMons[data->battlerId].statStages[STAT_ATK]; + data->modifyArrows.typeOfVal = VAL_ALL_STAT_STAGES; + } + else + { + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].statStages[data->currentSecondaryListItemId + STAT_ATK]; + data->modifyArrows.typeOfVal = VAL_U8; + data->modifyArrows.currValue = gBattleMons[data->battlerId].statStages[data->currentSecondaryListItemId + STAT_ATK]; + } + break; + case LIST_ITEM_VARIOUS: + if (data->currentSecondaryListItemId == VARIOUS_SHOW_HP) + { + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = 1; + data->modifyArrows.maxDigits = 1; + data->modifyArrows.modifiedValPtr = &gBattleSpritesDataPtr->battlerData[data->battlerId]; + data->modifyArrows.typeOfVal = VAR_SHOW_HP; + data->modifyArrows.currValue = gBattleSpritesDataPtr->battlerData[data->battlerId].hpNumbersNoBars; + } + else if (data->currentSecondaryListItemId == VARIOUS_SUBSTITUTE_HP) + { + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = 255; + data->modifyArrows.maxDigits = 3; + data->modifyArrows.modifiedValPtr = &gDisableStructs[data->battlerId].substituteHP; + data->modifyArrows.typeOfVal = VAR_SUBSTITUTE; + data->modifyArrows.currValue = gDisableStructs[data->battlerId].substituteHP; + } + else if (data->currentSecondaryListItemId == VARIOUS_IN_LOVE) + { + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = 1; + data->modifyArrows.maxDigits = 1; + data->modifyArrows.modifiedValPtr = NULL; + data->modifyArrows.typeOfVal = VAR_IN_LOVE; + data->modifyArrows.currValue = (gBattleMons[data->battlerId].status2 & STATUS2_INFATUATION) != 0; + } + break; + case LIST_ITEM_STATUS1: + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].status1; + data->modifyArrows.currValue = GetBitfieldValue(gBattleMons[data->battlerId].status1, data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); + data->modifyArrows.typeOfVal = VAL_BITFIELD_32; + goto CASE_ITEM_STATUS; + case LIST_ITEM_STATUS2: + data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].status2; + data->modifyArrows.currValue = GetBitfieldValue(gBattleMons[data->battlerId].status2, data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); + data->modifyArrows.typeOfVal = VAL_BITFIELD_32; + goto CASE_ITEM_STATUS; + case LIST_ITEM_STATUS3: + data->modifyArrows.modifiedValPtr = &gStatuses3[data->battlerId]; + data->modifyArrows.currValue = GetBitfieldValue(gStatuses3[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); + data->modifyArrows.typeOfVal = VAL_BITFIELD_32; + goto CASE_ITEM_STATUS; + case LIST_ITEM_STATUS4: + data->modifyArrows.modifiedValPtr = &gStatuses4[data->battlerId]; + data->modifyArrows.currValue = GetBitfieldValue(gStatuses4[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); + data->modifyArrows.typeOfVal = VAL_BITFIELD_32; + goto CASE_ITEM_STATUS; + case LIST_ITEM_AI: + data->modifyArrows.modifiedValPtr = &gBattleResources->ai->aiFlags[data->battlerId]; + data->modifyArrows.currValue = GetBitfieldValue(gBattleResources->ai->aiFlags[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount); + data->modifyArrows.typeOfVal = VAL_BITFIELD_32; + goto CASE_ITEM_STATUS; + CASE_ITEM_STATUS: + data->modifyArrows.minValue = 0; + data->modifyArrows.maxValue = (1 << data->bitfield[data->currentSecondaryListItemId].bitsCount) - 1; + data->modifyArrows.maxDigits = sBitsToMaxDigit[data->bitfield[data->currentSecondaryListItemId].bitsCount]; + break; + case LIST_ITEM_SIDE_STATUS: + data->modifyArrows.minValue = 0; + + if (data->currentSecondaryListItemId == LIST_SIDE_SPIKES) + data->modifyArrows.maxValue = 3; + else if (data->currentSecondaryListItemId == LIST_SIDE_STEALTH_ROCK || data->currentSecondaryListItemId == LIST_SIDE_STICKY_WEB) + data->modifyArrows.maxValue = 1; + else + data->modifyArrows.maxValue = 9; + + data->modifyArrows.maxDigits = 2; + data->modifyArrows.modifiedValPtr = &gSideStatuses[GetBattlerSide(data->battlerId)]; + data->modifyArrows.typeOfVal = VAR_SIDE_STATUS; + data->modifyArrows.currValue = *GetSideStatusValue(data, FALSE, FALSE); + break; + } + + data->modifyArrows.currentDigit = 0; + ValueToCharDigits(data->modifyArrows.charDigits, data->modifyArrows.currValue, data->modifyArrows.maxDigits); +} + +static bool32 TryMoveDigit(struct BattleDebugModifyArrows *modArrows, bool32 moveUp) +{ + s32 i; + u8 charDigits[MAX_MODIFY_DIGITS]; + u32 newValue; + + for (i = 0; i < MAX_MODIFY_DIGITS; i++) + charDigits[i] = modArrows->charDigits[i]; + + if (moveUp) + { + if (charDigits[modArrows->currentDigit] == CHAR_9) + { + charDigits[modArrows->currentDigit] = CHAR_0; + for (i = modArrows->currentDigit - 1; i >= 0; i--) + { + if (charDigits[i] == CHAR_9) + { + charDigits[i] = CHAR_0; + } + else + { + charDigits[i]++; + break; + } + } + } + else + charDigits[modArrows->currentDigit]++; + } + else + { + if (charDigits[modArrows->currentDigit] == CHAR_0) + { + charDigits[modArrows->currentDigit] = CHAR_9; + for (i = modArrows->currentDigit - 1; i >= 0; i--) + { + if (charDigits[i] == CHAR_0) + { + charDigits[i] = CHAR_9; + } + else + { + charDigits[i]--; + break; + } + } + } + else + charDigits[modArrows->currentDigit]--; + } + + newValue = CharDigitsToValue(charDigits, modArrows->maxDigits); + if (newValue > modArrows->maxValue || newValue < modArrows->minValue) + { + return FALSE; + } + else + { + modArrows->currValue = newValue; + for (i = 0; i < MAX_MODIFY_DIGITS; i++) + modArrows->charDigits[i] = charDigits[i]; + return TRUE; + } +} + +static void UpdateMonData(struct BattleDebugMenu *data) +{ + s32 i, j; + + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (data->battlerWasChanged[i]) + { + struct Pokemon *mon; + struct BattlePokemon *battleMon = &gBattleMons[i]; + + if (GetBattlerSide(i) == B_SIDE_PLAYER) + mon = &gPlayerParty[gBattlerPartyIndexes[i]]; + else + mon = &gEnemyParty[gBattlerPartyIndexes[i]]; + + SetMonData(mon, MON_DATA_HELD_ITEM, &battleMon->item); + SetMonData(mon, MON_DATA_STATUS, &battleMon->status1); + SetMonData(mon, MON_DATA_HP, &battleMon->hp); + SetMonData(mon, MON_DATA_MAX_HP, &battleMon->maxHP); + for (j = 0; j < 4; j++) + SetMonData(mon, MON_DATA_MOVE1 + j, &battleMon->moves[j]); + } + } +} + +static const u8 sText_HoldEffectNone[] = _("????????"); +static const u8 sText_HoldEffectRestoreHp[] = _("Restore Hp"); +static const u8 sText_HoldEffectCurePar[] = _("Cure Par"); +static const u8 sText_HoldEffectCureSlp[] = _("Cure Slp"); +static const u8 sText_HoldEffectCurePsn[] = _("Cure Psn"); +static const u8 sText_HoldEffectCureBrn[] = _("Cure Brn"); +static const u8 sText_HoldEffectCureFrz[] = _("Cure Frz"); +static const u8 sText_HoldEffectRestorePp[] = _("Restore Pp"); +static const u8 sText_HoldEffectCureConfusion[] = _("Cure Confusion"); +static const u8 sText_HoldEffectCureStatus[] = _("Cure Status"); +static const u8 sText_HoldEffectConfuseSpicy[] = _("Confuse Spicy"); +static const u8 sText_HoldEffectConfuseDry[] = _("Confuse Dry"); +static const u8 sText_HoldEffectConfuseSweet[] = _("Confuse Sweet"); +static const u8 sText_HoldEffectConfuseBitter[] = _("Confuse Bitter"); +static const u8 sText_HoldEffectConfuseSour[] = _("Confuse Sour"); +static const u8 sText_HoldEffectAttackUp[] = _("Attack Up"); +static const u8 sText_HoldEffectDefenseUp[] = _("Defense Up"); +static const u8 sText_HoldEffectSpeedUp[] = _("Speed Up"); +static const u8 sText_HoldEffectSpAttackUp[] = _("Sp Attack Up"); +static const u8 sText_HoldEffectSpDefenseUp[] = _("Sp Defense Up"); +static const u8 sText_HoldEffectCriticalUp[] = _("Critical Up"); +static const u8 sText_HoldEffectRandomStatUp[] = _("Random Stat Up"); +static const u8 sText_HoldEffectEvasionUp[] = _("Evasion Up"); +static const u8 sText_HoldEffectRestoreStats[] = _("Restore Stats"); +static const u8 sText_HoldEffectMachoBrace[] = _("Macho Brace"); +static const u8 sText_HoldEffectExpShare[] = _("Exp Share"); +static const u8 sText_HoldEffectQuickClaw[] = _("Quick Claw"); +static const u8 sText_HoldEffectFriendshipUp[] = _("Friendship Up"); +static const u8 sText_HoldEffectMentalHerb[] = _("Mental Herb"); +static const u8 sText_HoldEffectChoiceBand[] = _("Choice Band"); +static const u8 sText_HoldEffectFlinch[] = _("Flinch"); +static const u8 sText_HoldEffectBugPower[] = _("Bug Power"); +static const u8 sText_HoldEffectDoublePrize[] = _("Double Prize"); +static const u8 sText_HoldEffectRepel[] = _("Repel"); +static const u8 sText_HoldEffectSoulDew[] = _("Soul Dew"); +static const u8 sText_HoldEffectDeepSeaTooth[] = _("Deep Sea Tooth"); +static const u8 sText_HoldEffectDeepSeaScale[] = _("Deep Sea Scale"); +static const u8 sText_HoldEffectCanAlwaysRun[] = _("Can Always Run"); +static const u8 sText_HoldEffectPreventEvolve[] = _("Prevent Evolve"); +static const u8 sText_HoldEffectFocusBand[] = _("Focus Band"); +static const u8 sText_HoldEffectLuckyEgg[] = _("Lucky Egg"); +static const u8 sText_HoldEffectScopeLens[] = _("Scope Lens"); +static const u8 sText_HoldEffectSteelPower[] = _("Steel Power"); +static const u8 sText_HoldEffectLeftovers[] = _("Leftovers"); +static const u8 sText_HoldEffectDragonScale[] = _("Dragon Scale"); +static const u8 sText_HoldEffectLightBall[] = _("Light Ball"); +static const u8 sText_HoldEffectGroundPower[] = _("Ground Power"); +static const u8 sText_HoldEffectRockPower[] = _("Rock Power"); +static const u8 sText_HoldEffectGrassPower[] = _("Grass Power"); +static const u8 sText_HoldEffectDarkPower[] = _("Dark Power"); +static const u8 sText_HoldEffectFightingPower[] = _("Fighting Power"); +static const u8 sText_HoldEffectElectricPower[] = _("Electric Power"); +static const u8 sText_HoldEffectWaterPower[] = _("Water Power"); +static const u8 sText_HoldEffectFlyingPower[] = _("Flying Power"); +static const u8 sText_HoldEffectPoisonPower[] = _("Poison Power"); +static const u8 sText_HoldEffectIcePower[] = _("Ice Power"); +static const u8 sText_HoldEffectGhostPower[] = _("Ghost Power"); +static const u8 sText_HoldEffectPsychicPower[] = _("Psychic Power"); +static const u8 sText_HoldEffectFirePower[] = _("Fire Power"); +static const u8 sText_HoldEffectDragonPower[] = _("Dragon Power"); +static const u8 sText_HoldEffectNormalPower[] = _("Normal Power"); +static const u8 sText_HoldEffectUpgrade[] = _("Upgrade"); +static const u8 sText_HoldEffectShellBell[] = _("Shell Bell"); +static const u8 sText_HoldEffectLuckyPunch[] = _("Lucky Punch"); +static const u8 sText_HoldEffectMetalPowder[] = _("Metal Powder"); +static const u8 sText_HoldEffectThickClub[] = _("Thick Club"); +static const u8 sText_HoldEffectLeek[] = _("Leek"); +static const u8 sText_HoldEffectChoiceScarf[] = _("Choice Scarf"); +static const u8 sText_HoldEffectChoiceSpecs[] = _("Choice Specs"); +static const u8 sText_HoldEffectDampRock[] = _("Damp Rock"); +static const u8 sText_HoldEffectGripClaw[] = _("Grip Claw"); +static const u8 sText_HoldEffectHeatRock[] = _("Heat Rock"); +static const u8 sText_HoldEffectIcyRock[] = _("Icy Rock"); +static const u8 sText_HoldEffectLightClay[] = _("Light Clay"); +static const u8 sText_HoldEffectSmoothRock[] = _("Smooth Rock"); +static const u8 sText_HoldEffectPowerHerb[] = _("Power Herb"); +static const u8 sText_HoldEffectBigRoot[] = _("Big Root"); +static const u8 sText_HoldEffectExpertBelt[] = _("Expert Belt"); +static const u8 sText_HoldEffectLifeOrb[] = _("Life Orb"); +static const u8 sText_HoldEffectMetronome[] = _("Metronome"); +static const u8 sText_HoldEffectMuscleBand[] = _("Muscle Band"); +static const u8 sText_HoldEffectWideLens[] = _("Wide Lens"); +static const u8 sText_HoldEffectWiseGlasses[] = _("Wise Glasses"); +static const u8 sText_HoldEffectZoomLens[] = _("Zoom Lens"); +static const u8 sText_HoldEffectLaggingTail[] = _("Lagging Tail"); +static const u8 sText_HoldEffectFocusSash[] = _("Focus Sash"); +static const u8 sText_HoldEffectFlameOrb[] = _("Flame Orb"); +static const u8 sText_HoldEffectToxicOrb[] = _("Toxic Orb"); +static const u8 sText_HoldEffectStickyBarb[] = _("Sticky Barb"); +static const u8 sText_HoldEffectIronBall[] = _("Iron Ball"); +static const u8 sText_HoldEffectBlackSludge[] = _("Black Sludge"); +static const u8 sText_HoldEffectDestinyKnot[] = _("Destiny Knot"); +static const u8 sText_HoldEffectShedShell[] = _("Shed Shell"); +static const u8 sText_HoldEffectQuickPowder[] = _("Quick Powder"); +static const u8 sText_HoldEffectAdamantOrb[] = _("Adamant Orb"); +static const u8 sText_HoldEffectLustrousOrb[] = _("Lustrous Orb"); +static const u8 sText_HoldEffectGriseousOrb[] = _("Griseous Orb"); +static const u8 sText_HoldEffectEnigmaBerry[] = _("Enigma Berry"); +static const u8 sText_HoldEffectResistBerry[] = _("Resist Berry"); +static const u8 sText_HoldEffectPowerItem[] = _("Power Item"); +static const u8 sText_HoldEffectRestorePctHp[] = _("Restore Pct Hp"); +static const u8 sText_HoldEffectMicleBerry[] = _("Micle Berry"); +static const u8 sText_HoldEffectCustapBerry[] = _("Custap Berry"); +static const u8 sText_HoldEffectJabocaBerry[] = _("Jaboca Berry"); +static const u8 sText_HoldEffectRowapBerry[] = _("Rowap Berry"); +static const u8 sText_HoldEffectKeeBerry[] = _("Kee Berry"); +static const u8 sText_HoldEffectMarangaBerry[] = _("Maranga Berry"); +static const u8 sText_HoldEffectFloatStone[] = _("Float Stone"); +static const u8 sText_HoldEffectEviolite[] = _("Eviolite"); +static const u8 sText_HoldEffectAssaultVest[] = _("Assault Vest"); +static const u8 sText_HoldEffectDrive[] = _("Drive"); +static const u8 sText_HoldEffectGems[] = _("Gems"); +static const u8 sText_HoldEffectRockyHelmet[] = _("Rocky Helmet"); +static const u8 sText_HoldEffectAirBalloon[] = _("Air Balloon"); +static const u8 sText_HoldEffectRedCard[] = _("Red Card"); +static const u8 sText_HoldEffectRingTarget[] = _("Ring Target"); +static const u8 sText_HoldEffectBindingBand[] = _("Binding Band"); +static const u8 sText_HoldEffectEjectButton[] = _("Eject Button"); +static const u8 sText_HoldEffectAbsorbBulb[] = _("Absorb Bulb"); +static const u8 sText_HoldEffectCellBattery[] = _("Cell Battery"); +static const u8 sText_HoldEffectFairyPower[] = _("Fairy Power"); +static const u8 sText_HoldEffectMegaStone[] = _("Mega Stone"); +static const u8 sText_HoldEffectSafetyGoggles[] = _("Safety Goggles"); +static const u8 sText_HoldEffectLuminousMoss[] = _("Luminous Moss"); +static const u8 sText_HoldEffectSnowball[] = _("Snowball"); +static const u8 sText_HoldEffectWeaknessPolicy[] = _("Weakness Policy"); +static const u8 sText_HoldEffectPrimalOrb[] = _("Primal Orb"); +static const u8 sText_HoldEffectProtectivePads[] = _("Protective Pads"); +static const u8 sText_HoldEffectTerrainExtender[] = _("Terrain Extender"); +static const u8 sText_HoldEffectSeeds[] = _("Seeds"); +static const u8 sText_HoldEffectAdrenalineOrb[] = _("Adrenaline Orb"); +static const u8 sText_HoldEffectMemory[] = _("Memory"); +static const u8 sText_HoldEffectZCrystal[] = _("Z-Crystal"); +static const u8 sText_HoldEffectPlate[] = _("Plate"); +static const u8 sText_HoldEffectUtilityUmbrella[] = _("Utility Umbrella"); +static const u8 sText_HoldEffectEjectPack[] = _("Eject Pack"); +static const u8 sText_HoldEffectRoomService[] = _("Room Service"); +static const u8 sText_HoldEffectBlunderPolicy[] = _("Blunder Policy"); +static const u8 sText_HoldEffectHeavyDutyBoots[] = _("Heavy Duty Boots"); +static const u8 sText_HoldEffectThroatSpray[] = _("Throat Spray"); +static const u8 *const sHoldEffectNames[] = +{ + [HOLD_EFFECT_NONE] = sText_HoldEffectNone, + [HOLD_EFFECT_RESTORE_HP] = sText_HoldEffectRestoreHp, + [HOLD_EFFECT_CURE_PAR] = sText_HoldEffectCurePar, + [HOLD_EFFECT_CURE_SLP] = sText_HoldEffectCureSlp, + [HOLD_EFFECT_CURE_PSN] = sText_HoldEffectCurePsn, + [HOLD_EFFECT_CURE_BRN] = sText_HoldEffectCureBrn, + [HOLD_EFFECT_CURE_FRZ] = sText_HoldEffectCureFrz, + [HOLD_EFFECT_RESTORE_PP] = sText_HoldEffectRestorePp, + [HOLD_EFFECT_CURE_CONFUSION] = sText_HoldEffectCureConfusion, + [HOLD_EFFECT_CURE_STATUS] = sText_HoldEffectCureStatus, + [HOLD_EFFECT_CONFUSE_SPICY] = sText_HoldEffectConfuseSpicy, + [HOLD_EFFECT_CONFUSE_DRY] = sText_HoldEffectConfuseDry, + [HOLD_EFFECT_CONFUSE_SWEET] = sText_HoldEffectConfuseSweet, + [HOLD_EFFECT_CONFUSE_BITTER] = sText_HoldEffectConfuseBitter, + [HOLD_EFFECT_CONFUSE_SOUR] = sText_HoldEffectConfuseSour, + [HOLD_EFFECT_ATTACK_UP] = sText_HoldEffectAttackUp, + [HOLD_EFFECT_DEFENSE_UP] = sText_HoldEffectDefenseUp, + [HOLD_EFFECT_SPEED_UP] = sText_HoldEffectSpeedUp, + [HOLD_EFFECT_SP_ATTACK_UP] = sText_HoldEffectSpAttackUp, + [HOLD_EFFECT_SP_DEFENSE_UP] = sText_HoldEffectSpDefenseUp, + [HOLD_EFFECT_CRITICAL_UP] = sText_HoldEffectCriticalUp, + [HOLD_EFFECT_RANDOM_STAT_UP] = sText_HoldEffectRandomStatUp, + [HOLD_EFFECT_EVASION_UP] = sText_HoldEffectEvasionUp, + [HOLD_EFFECT_RESTORE_STATS] = sText_HoldEffectRestoreStats, + [HOLD_EFFECT_MACHO_BRACE] = sText_HoldEffectMachoBrace, + [HOLD_EFFECT_EXP_SHARE] = sText_HoldEffectExpShare, + [HOLD_EFFECT_QUICK_CLAW] = sText_HoldEffectQuickClaw, + [HOLD_EFFECT_FRIENDSHIP_UP] = sText_HoldEffectFriendshipUp, + [HOLD_EFFECT_MENTAL_HERB] = sText_HoldEffectMentalHerb, + [HOLD_EFFECT_CHOICE_BAND] = sText_HoldEffectChoiceBand, + [HOLD_EFFECT_FLINCH] = sText_HoldEffectFlinch, + [HOLD_EFFECT_BUG_POWER] = sText_HoldEffectBugPower, + [HOLD_EFFECT_DOUBLE_PRIZE] = sText_HoldEffectDoublePrize, + [HOLD_EFFECT_REPEL] = sText_HoldEffectRepel, + [HOLD_EFFECT_SOUL_DEW] = sText_HoldEffectSoulDew, + [HOLD_EFFECT_DEEP_SEA_TOOTH] = sText_HoldEffectDeepSeaTooth, + [HOLD_EFFECT_DEEP_SEA_SCALE] = sText_HoldEffectDeepSeaScale, + [HOLD_EFFECT_CAN_ALWAYS_RUN] = sText_HoldEffectCanAlwaysRun, + [HOLD_EFFECT_PREVENT_EVOLVE] = sText_HoldEffectPreventEvolve, + [HOLD_EFFECT_FOCUS_BAND] = sText_HoldEffectFocusBand, + [HOLD_EFFECT_LUCKY_EGG] = sText_HoldEffectLuckyEgg, + [HOLD_EFFECT_SCOPE_LENS] = sText_HoldEffectScopeLens, + [HOLD_EFFECT_STEEL_POWER] = sText_HoldEffectSteelPower, + [HOLD_EFFECT_LEFTOVERS] = sText_HoldEffectLeftovers, + [HOLD_EFFECT_DRAGON_SCALE] = sText_HoldEffectDragonScale, + [HOLD_EFFECT_LIGHT_BALL] = sText_HoldEffectLightBall, + [HOLD_EFFECT_GROUND_POWER] = sText_HoldEffectGroundPower, + [HOLD_EFFECT_ROCK_POWER] = sText_HoldEffectRockPower, + [HOLD_EFFECT_GRASS_POWER] = sText_HoldEffectGrassPower, + [HOLD_EFFECT_DARK_POWER] = sText_HoldEffectDarkPower, + [HOLD_EFFECT_FIGHTING_POWER] = sText_HoldEffectFightingPower, + [HOLD_EFFECT_ELECTRIC_POWER] = sText_HoldEffectElectricPower, + [HOLD_EFFECT_WATER_POWER] = sText_HoldEffectWaterPower, + [HOLD_EFFECT_FLYING_POWER] = sText_HoldEffectFlyingPower, + [HOLD_EFFECT_POISON_POWER] = sText_HoldEffectPoisonPower, + [HOLD_EFFECT_ICE_POWER] = sText_HoldEffectIcePower, + [HOLD_EFFECT_GHOST_POWER] = sText_HoldEffectGhostPower, + [HOLD_EFFECT_PSYCHIC_POWER] = sText_HoldEffectPsychicPower, + [HOLD_EFFECT_FIRE_POWER] = sText_HoldEffectFirePower, + [HOLD_EFFECT_DRAGON_POWER] = sText_HoldEffectDragonPower, + [HOLD_EFFECT_NORMAL_POWER] = sText_HoldEffectNormalPower, + [HOLD_EFFECT_UPGRADE] = sText_HoldEffectUpgrade, + [HOLD_EFFECT_SHELL_BELL] = sText_HoldEffectShellBell, + [HOLD_EFFECT_LUCKY_PUNCH] = sText_HoldEffectLuckyPunch, + [HOLD_EFFECT_METAL_POWDER] = sText_HoldEffectMetalPowder, + [HOLD_EFFECT_THICK_CLUB] = sText_HoldEffectThickClub, + [HOLD_EFFECT_LEEK] = sText_HoldEffectLeek, + [HOLD_EFFECT_CHOICE_SCARF] = sText_HoldEffectChoiceScarf, + [HOLD_EFFECT_CHOICE_SPECS] = sText_HoldEffectChoiceSpecs, + [HOLD_EFFECT_DAMP_ROCK] = sText_HoldEffectDampRock, + [HOLD_EFFECT_GRIP_CLAW] = sText_HoldEffectGripClaw, + [HOLD_EFFECT_HEAT_ROCK] = sText_HoldEffectHeatRock, + [HOLD_EFFECT_ICY_ROCK] = sText_HoldEffectIcyRock, + [HOLD_EFFECT_LIGHT_CLAY] = sText_HoldEffectLightClay, + [HOLD_EFFECT_SMOOTH_ROCK] = sText_HoldEffectSmoothRock, + [HOLD_EFFECT_POWER_HERB] = sText_HoldEffectPowerHerb, + [HOLD_EFFECT_BIG_ROOT] = sText_HoldEffectBigRoot, + [HOLD_EFFECT_EXPERT_BELT] = sText_HoldEffectExpertBelt, + [HOLD_EFFECT_LIFE_ORB] = sText_HoldEffectLifeOrb, + [HOLD_EFFECT_METRONOME] = sText_HoldEffectMetronome, + [HOLD_EFFECT_MUSCLE_BAND] = sText_HoldEffectMuscleBand, + [HOLD_EFFECT_WIDE_LENS] = sText_HoldEffectWideLens, + [HOLD_EFFECT_WISE_GLASSES] = sText_HoldEffectWiseGlasses, + [HOLD_EFFECT_ZOOM_LENS] = sText_HoldEffectZoomLens, + [HOLD_EFFECT_LAGGING_TAIL] = sText_HoldEffectLaggingTail, + [HOLD_EFFECT_FOCUS_SASH] = sText_HoldEffectFocusSash, + [HOLD_EFFECT_FLAME_ORB] = sText_HoldEffectFlameOrb, + [HOLD_EFFECT_TOXIC_ORB] = sText_HoldEffectToxicOrb, + [HOLD_EFFECT_STICKY_BARB] = sText_HoldEffectStickyBarb, + [HOLD_EFFECT_IRON_BALL] = sText_HoldEffectIronBall, + [HOLD_EFFECT_BLACK_SLUDGE] = sText_HoldEffectBlackSludge, + [HOLD_EFFECT_DESTINY_KNOT] = sText_HoldEffectDestinyKnot, + [HOLD_EFFECT_SHED_SHELL] = sText_HoldEffectShedShell, + [HOLD_EFFECT_QUICK_POWDER] = sText_HoldEffectQuickPowder, + [HOLD_EFFECT_ADAMANT_ORB] = sText_HoldEffectAdamantOrb, + [HOLD_EFFECT_LUSTROUS_ORB] = sText_HoldEffectLustrousOrb, + [HOLD_EFFECT_GRISEOUS_ORB] = sText_HoldEffectGriseousOrb, + [HOLD_EFFECT_ENIGMA_BERRY] = sText_HoldEffectEnigmaBerry, + [HOLD_EFFECT_RESIST_BERRY] = sText_HoldEffectResistBerry, + [HOLD_EFFECT_POWER_ITEM] = sText_HoldEffectPowerItem, + [HOLD_EFFECT_RESTORE_PCT_HP] = sText_HoldEffectRestorePctHp, + [HOLD_EFFECT_MICLE_BERRY] = sText_HoldEffectMicleBerry, + [HOLD_EFFECT_CUSTAP_BERRY] = sText_HoldEffectCustapBerry, + [HOLD_EFFECT_JABOCA_BERRY] = sText_HoldEffectJabocaBerry, + [HOLD_EFFECT_ROWAP_BERRY] = sText_HoldEffectRowapBerry, + [HOLD_EFFECT_KEE_BERRY] = sText_HoldEffectKeeBerry, + [HOLD_EFFECT_MARANGA_BERRY] = sText_HoldEffectMarangaBerry, + [HOLD_EFFECT_PLATE] = sText_HoldEffectPlate, + [HOLD_EFFECT_FLOAT_STONE] = sText_HoldEffectFloatStone, + [HOLD_EFFECT_EVIOLITE] = sText_HoldEffectEviolite, + [HOLD_EFFECT_ASSAULT_VEST] = sText_HoldEffectAssaultVest, + [HOLD_EFFECT_DRIVE] = sText_HoldEffectDrive, + [HOLD_EFFECT_GEMS] = sText_HoldEffectGems, + [HOLD_EFFECT_ROCKY_HELMET] = sText_HoldEffectRockyHelmet, + [HOLD_EFFECT_AIR_BALLOON] = sText_HoldEffectAirBalloon, + [HOLD_EFFECT_RED_CARD] = sText_HoldEffectRedCard, + [HOLD_EFFECT_RING_TARGET] = sText_HoldEffectRingTarget, + [HOLD_EFFECT_BINDING_BAND] = sText_HoldEffectBindingBand, + [HOLD_EFFECT_EJECT_BUTTON] = sText_HoldEffectEjectButton, + [HOLD_EFFECT_ABSORB_BULB] = sText_HoldEffectAbsorbBulb, + [HOLD_EFFECT_CELL_BATTERY] = sText_HoldEffectCellBattery, + [HOLD_EFFECT_FAIRY_POWER] = sText_HoldEffectFairyPower, + [HOLD_EFFECT_MEGA_STONE] = sText_HoldEffectMegaStone, + [HOLD_EFFECT_SAFETY_GOGGLES] = sText_HoldEffectSafetyGoggles, + [HOLD_EFFECT_LUMINOUS_MOSS] = sText_HoldEffectLuminousMoss, + [HOLD_EFFECT_SNOWBALL] = sText_HoldEffectSnowball, + [HOLD_EFFECT_WEAKNESS_POLICY] = sText_HoldEffectWeaknessPolicy, + [HOLD_EFFECT_PRIMAL_ORB] = sText_HoldEffectPrimalOrb, + [HOLD_EFFECT_PROTECTIVE_PADS] = sText_HoldEffectProtectivePads, + [HOLD_EFFECT_TERRAIN_EXTENDER] = sText_HoldEffectTerrainExtender, + [HOLD_EFFECT_SEEDS] = sText_HoldEffectSeeds, + [HOLD_EFFECT_ADRENALINE_ORB] = sText_HoldEffectAdrenalineOrb, + [HOLD_EFFECT_MEMORY] = sText_HoldEffectMemory, + [HOLD_EFFECT_Z_CRYSTAL] = sText_HoldEffectZCrystal, + [HOLD_EFFECT_UTILITY_UMBRELLA] = sText_HoldEffectUtilityUmbrella, + [HOLD_EFFECT_EJECT_PACK] = sText_HoldEffectEjectPack, + [HOLD_EFFECT_ROOM_SERVICE] = sText_HoldEffectRoomService, + [HOLD_EFFECT_BLUNDER_POLICY] = sText_HoldEffectBlunderPolicy, + [HOLD_EFFECT_HEAVY_DUTY_BOOTS] = sText_HoldEffectHeavyDutyBoots, + [HOLD_EFFECT_THROAT_SPRAY] = sText_HoldEffectThroatSpray, +}; +static const u8 *GetHoldEffectName(u16 holdEffect) +{ + if (holdEffect > ARRAY_COUNT(sHoldEffectNames)) + return sHoldEffectNames[0]; + return sHoldEffectNames[holdEffect]; +} diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 7a32ec786..ec8065a1d 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -95,7 +95,7 @@ static const struct CompressedSpriteSheet sSpriteSheets_HealthBar[MAX_BATTLERS_C }, }; -static const struct SpritePalette sSpritePalettes_HealthBoxHealthBar[2] = +const struct SpritePalette sSpritePalettes_HealthBoxHealthBar[2] = { { .data = gBattleInterface_Healthbox_Pal, diff --git a/src/battle_interface.c b/src/battle_interface.c index d49722632..22bafe3e8 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1,6 +1,7 @@ #include "global.h" #include "gflib.h" #include "battle_anim.h" +#include "battle_debug.h" #include "battle_interface.h" #include "battle_message.h" #include "battle_z_move.h" diff --git a/src/battle_main.c b/src/battle_main.c index 1a1ad0ad8..e4fbf8a33 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5,6 +5,7 @@ #include "battle_ai_util.h" #include "battle_anim.h" #include "battle_controllers.h" +#include "debug.h" #include "battle_interface.h" #include "battle_main.h" #include "battle_message.h" @@ -3469,6 +3470,10 @@ static void HandleTurnActionSelectionState(void) BtlController_EmitEndBounceEffect(battler, BUFFER_A); MarkBattlerForControllerExec(battler); return; + case B_ACTION_DEBUG: + BtlController_EmitDebugMenu(battler, BUFFER_A); + MarkBattlerForControllerExec(battler); + break; } if (gBattleTypeFlags & BATTLE_TYPE_TRAINER @@ -3611,6 +3616,9 @@ static void HandleTurnActionSelectionState(void) case B_ACTION_OLDMAN_THROW: gBattleCommunication[battler]++; break; + case B_ACTION_DEBUG: + gBattleCommunication[battler] = STATE_BEFORE_ACTION_CHOSEN; + break; } } break; diff --git a/src/battle_setup.c b/src/battle_setup.c index 1ff640408..06d886504 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -22,6 +22,7 @@ #include "field_player_avatar.h" #include "field_screen_effect.h" #include "field_message_box.h" +#include "trainer_see.h" #include "vs_seeker.h" #include "battle.h" #include "battle_transition.h" @@ -82,6 +83,8 @@ static EWRAM_DATA u8 *sTrainerCannotBattleSpeech = NULL; static EWRAM_DATA u8 *sTrainerBattleEndScript = NULL; static EWRAM_DATA u8 *sTrainerABattleScriptRetAddr = NULL; static EWRAM_DATA u16 sRivalBattleFlags = 0; +EWRAM_DATA static bool8 sShouldCheckTrainerBScript = FALSE; +EWRAM_DATA static u8 sNoOfPossibleTrainerRetScripts = 0; // The first transition is used if the enemy pokemon are lower level than our pokemon. // Otherwise, the second transition is used. @@ -219,6 +222,46 @@ static void CreateBattleStartTask(u8 transition, u16 song) // song == 0 means de PlayMapChosenOrBattleBGM(song); } +static void Task_BattleStart_Debug(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (tState) + { + case 0: + if (!FldEffPoison_IsActive()) // is poison not active? + { + HelpSystem_Disable(); + BattleTransition_StartOnField(tTransition); + // ClearMirageTowerPulseBlendEffect(); + tState++; // go to case 1. + } + break; + case 1: + if (IsBattleTransitionDone() == TRUE) + { + HelpSystem_Enable(); + CleanupOverworldWindowsAndTilemaps(); + SetMainCallback2(CB2_InitBattle); + RestartWildEncounterImmunitySteps(); + ClearPoisonStepCounter(); + DestroyTask(taskId); + } + break; + } +} + +static void CreateBattleStartTask_Debug(u8 transition, u16 song) +{ + u8 taskId = CreateTask(Task_BattleStart_Debug, 1); + + gTasks[taskId].tTransition = transition; + PlayMapChosenOrBattleBGM(song); +} + +#undef tState +#undef tTransition + static bool8 CheckSilphScopeInPokemonTower(u16 mapGroup, u16 mapNum) { if (mapGroup == MAP_GROUP(POKEMON_TOWER_1F) @@ -845,6 +888,37 @@ void ClearTrainerFlag(u16 trainerId) FlagClear(TRAINER_FLAGS_START + trainerId); } +void BattleSetup_StartTrainerBattle(void) +{ + if (gNoOfApproachingTrainers == 2) + gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER); + else + gBattleTypeFlags = (BATTLE_TYPE_TRAINER); + + sNoOfPossibleTrainerRetScripts = gNoOfApproachingTrainers; + gNoOfApproachingTrainers = 0; + sShouldCheckTrainerBScript = FALSE; + gWhichTrainerToFaceAfterBattle = 0; + gMain.savedCallback = CB2_EndTrainerBattle; + + DoTrainerBattle(); + + ScriptContext_Stop(); +} + +void BattleSetup_StartTrainerBattle_Debug(void) +{ + sNoOfPossibleTrainerRetScripts = gNoOfApproachingTrainers; + gNoOfApproachingTrainers = 0; + sShouldCheckTrainerBScript = FALSE; + gWhichTrainerToFaceAfterBattle = 0; + gMain.savedCallback = CB2_EndTrainerBattle; + + CreateBattleStartTask_Debug(GetWildBattleTransition(), 0); + + ScriptContext_Stop(); +} + void StartTrainerBattle(void) { gBattleTypeFlags = BATTLE_TYPE_TRAINER; diff --git a/src/battle_z_move.c b/src/battle_z_move.c index 6ea91b8f3..f997f1c41 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -30,7 +30,7 @@ #include "battle_anim.h" #include "constants/battle_anim.h" #include "constants/rgb.h" -// #include "battle_debug.h" +#include "battle_debug.h" #include "data.h" #include "pokemon_summary_screen.h" #include "constants/songs.h" diff --git a/src/crt0.s b/src/crt0.s index a0d8a4b55..9b492486a 100644 --- a/src/crt0.s +++ b/src/crt0.s @@ -1,6 +1,5 @@ .include "constants/gba_constants.inc" .include "constants/misc_constants.inc" - .include "constants/version.inc" .syntax unified diff --git a/src/data/party_menu.h b/src/data/party_menu.h index 38d703c20..484bbdf4e 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -980,7 +980,7 @@ static const struct CompressedSpritePalette sSpritePalette_StatusIcons = gStatusPal_Icons, 1202 }; -static const struct SpriteTemplate sSpriteTemplate_StatusIcons = +const struct SpriteTemplate gSpriteTemplate_StatusIcons = { .tileTag = 1202, .paletteTag = 1202, diff --git a/src/daycare.c b/src/daycare.c index d9fd1ed6e..9331bd215 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -59,7 +59,6 @@ struct EggHatchData // this file's functions static void ClearDaycareMonMail(struct DayCareMail *mail); static void SetInitialEggData(struct Pokemon *mon, u16 species, struct DayCare *daycare); -static u8 GetDaycareCompatibilityScore(struct DayCare *daycare); static void DaycarePrintMonInfo(u8 windowId, u32 daycareSlotId, u8 y); static u8 ModifyBreedingScoreForOvalCharm(u8 score); static u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves); @@ -433,13 +432,13 @@ void InitDaycareMailRecordMixing(struct DayCare *daycare, struct RecordMixingDay daycareMail->numDaycareMons = numDaycareMons; } -static s8 Daycare_FindEmptySpot(struct DayCare *daycare) +s8 Daycare_FindEmptySpot(struct DayCare *daycare) { u8 i; for (i = 0; i < DAYCARE_MON_COUNT; i++) { - if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES) == 0) + if (GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES) == SPECIES_NONE) return i; } @@ -1524,7 +1523,7 @@ static bool8 EggGroupsOverlap(u16 *eggGroups1, u16 *eggGroups2) return FALSE; } -static u8 GetDaycareCompatibilityScore(struct DayCare *daycare) +u8 GetDaycareCompatibilityScore(struct DayCare *daycare) { u32 i; u16 eggGroups[DAYCARE_MON_COUNT][EGG_GROUPS_PER_MON]; diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 000000000..0e7efe539 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,4450 @@ +//CREDITS +//TheXaman: https://github.com/TheXaman/pokeemerald/tree/tx_debug_system +//CODE USED FROM: +//ketsuban: https://github.com/pret/pokeemerald/wiki/Add-a-debug-menu +//Pyredrid: https://github.com/Pyredrid/pokeemerald/tree/debugmenu +//AsparagusEduardo: https://github.com/AsparagusEduardo/pokeemerald/tree/InfusedEmerald_v2 +//Ghoulslash: https://github.com/ghoulslash/pokeemerald +//Jaizu: https://jaizu.moe/ +//AND OTHER RHH POKEEMERALD-EXPANSION CONTRIBUTORS +#include "global.h" +#include "battle.h" +#include "battle_setup.h" +#include "berry.h" +#include "clock.h" +#include "coins.h" +#include "credits.h" +#include "data.h" +#include "daycare.h" +#include "debug.h" +#include "event_data.h" +#include "event_object_movement.h" +#include "event_scripts.h" +#include "field_fadetransition.h" +#include "field_message_box.h" +#include "field_screen_effect.h" +#include "field_weather.h" +#include "field_weather_util.h" +// #include "international_string_util.h" +#include "item.h" +// #include "item_icon.h" +#include "item_menu_icons.h" +#include "list_menu.h" +#include "m4a.h" +#include "main.h" +#include "main_menu.h" +#include "malloc.h" +#include "map_name_popup.h" +#include "menu.h" +#include "money.h" +#include "naming_screen.h" +#include "new_game.h" +#include "new_menu_helpers.h" +#include "overworld.h" +#include "palette.h" +#include "party_menu.h" +#include "pokedex.h" +#include "pokemon.h" +#include "pokemon_icon.h" +#include "pokemon_storage_system.h" +#include "random.h" +#include "region_map.h" +#include "rtc.h" +#include "script.h" +#include "script_pokemon_util.h" +#include "sound.h" +#include "strings.h" +#include "string_util.h" +#include "task.h" +#include "pokemon_summary_screen.h" +#include "wild_encounter.h" +#include "constants/abilities.h" +#include "constants/battle_ai.h" +// #include "constants/battle_frontier.h" +#include "constants/coins.h" +// #include "constants/expansion.h" +#include "constants/flags.h" +#include "constants/items.h" +#include "constants/map_groups.h" +#include "constants/rgb.h" +#include "constants/songs.h" +#include "constants/species.h" +#include "constants/weather.h" +#include "save.h" + +#if DEBUG_OVERWORLD_MENU == TRUE +// ******************************* +enum DebugMenu +{ + DEBUG_MENU_ITEM_UTILITIES, + DEBUG_MENU_ITEM_PCBAG, + DEBUG_MENU_ITEM_PARTY, + DEBUG_MENU_ITEM_GIVE, + DEBUG_MENU_ITEM_SCRIPTS, + DEBUG_MENU_ITEM_FLAGVAR, + //DEBUG_MENU_ITEM_BATTLE, + DEBUG_MENU_ITEM_SOUND, + DEBUG_MENU_ITEM_CANCEL, +}; + +enum UtilDebugMenu +{ + DEBUG_UTIL_MENU_ITEM_FLY, + DEBUG_UTIL_MENU_ITEM_WARP, + DEBUG_UTIL_MENU_ITEM_SAVEBLOCK, + DEBUG_UTIL_MENU_ITEM_ROM_SPACE, + DEBUG_UTIL_MENU_ITEM_WEATHER, + DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK, + DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK, + DEBUG_UTIL_MENU_ITEM_WATCHCREDITS, + DEBUG_UTIL_MENU_ITEM_PLAYER_NAME, + DEBUG_UTIL_MENU_ITEM_PLAYER_GENDER, + DEBUG_UTIL_MENU_ITEM_PLAYER_ID, + DEBUG_UTIL_MENU_ITEM_CHEAT, + DEBUG_UTIL_MENU_ITEM_EXPANSION_VER, + DEBUG_UTIL_MENU_ITEM_BERRY_FUNCTIONS, +}; + +enum GivePCBagDebugMenu +{ + DEBUG_PCBAG_MENU_ITEM_ACCESS_PC, + DEBUG_PCBAG_MENU_ITEM_FILL, + DEBUG_PCBAG_MENU_ITEM_CLEAR_BAG, + DEBUG_PCBAG_MENU_ITEM_CLEAR_BOXES, +}; + +enum GivePCBagFillDebugMenu +{ + DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_FAST, + DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_SLOW, + DEBUG_PCBAG_MENU_ITEM_FILL_PC_ITEMS, + DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_ITEMS, + DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BALLS, + DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_TMHM, + DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BERRIES, + DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_KEY_ITEMS, +}; + +enum PartyDebugMenu +{ + DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER, + DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG, + DEBUG_PARTY_MENU_ITEM_HEAL_PARTY, + DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1, + DEBUG_PARTY_MENU_ITEM_CHECK_EVS, + DEBUG_PARTY_MENU_ITEM_CHECK_IVS, + DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY, +}; + +enum ScriptDebugMenu +{ + DEBUG_UTIL_MENU_ITEM_SCRIPT_1, + DEBUG_UTIL_MENU_ITEM_SCRIPT_2, + DEBUG_UTIL_MENU_ITEM_SCRIPT_3, + DEBUG_UTIL_MENU_ITEM_SCRIPT_4, + DEBUG_UTIL_MENU_ITEM_SCRIPT_5, + DEBUG_UTIL_MENU_ITEM_SCRIPT_6, + DEBUG_UTIL_MENU_ITEM_SCRIPT_7, + DEBUG_UTIL_MENU_ITEM_SCRIPT_8, +}; + +enum FlagsVarsDebugMenu +{ + DEBUG_FLAGVAR_MENU_ITEM_FLAGS, + DEBUG_FLAGVAR_MENU_ITEM_VARS, + DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL, + DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE, + DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING, +}; + +enum BattleType +{ + DEBUG_BATTLE_0_MENU_ITEM_WILD, + DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE, + DEBUG_BATTLE_0_MENU_ITEM_SINGLE, + DEBUG_BATTLE_0_MENU_ITEM_DOUBLE, + DEBUG_BATTLE_0_MENU_ITEM_MULTI, +}; + +enum BattleAIFlags +{ + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_00, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_01, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_02, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_03, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_04, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_05, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_06, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_07, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_08, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_09, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_10, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_11, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_12, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_13, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_14, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_15, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_16, + DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_17, + DEBUG_BATTLE_1_MENU_ITEM_CONTINUE, +}; + +enum BattleTerrain +{ + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_9, +}; + +enum GiveDebugMenu +{ + DEBUG_GIVE_MENU_ITEM_ITEM_X, + DEBUG_GIVE_MENU_ITEM_POKEMON_SIMPLE, + DEBUG_GIVE_MENU_ITEM_POKEMON_COMPLEX, + DEBUG_GIVE_MENU_ITEM_MAX_MONEY, + DEBUG_GIVE_MENU_ITEM_MAX_COINS, + DEBUG_GIVE_MENU_ITEM_MAX_BATTLE_POINTS, + DEBUG_GIVE_MENU_ITEM_DAYCARE_EGG, +}; + +enum SoundDebugMenu +{ + DEBUG_SOUND_MENU_ITEM_SE, + DEBUG_SOUND_MENU_ITEM_MUS, +}; + +enum BerryFunctionsMenu +{ + DEBUG_BERRY_FUNCTIONS_MENU_CLEAR_ALL, + DEBUG_BERRY_FUNCTIONS_MENU_READY, + DEBUG_BERRY_FUNCTIONS_MENU_NEXT_STAGE, + DEBUG_BERRY_FUNCTIONS_MENU_WEEDS, + DEBUG_BERRY_FUNCTIONS_MENU_PESTS, +}; + +// ******************************* +// Constants +#define DEBUG_MENU_FONT FONT_NORMAL + +#define DEBUG_MENU_WIDTH_MAIN 17 +#define DEBUG_MENU_HEIGHT_MAIN 9 + +#define DEBUG_MENU_WIDTH_EXTRA 10 +#define DEBUG_MENU_HEIGHT_EXTRA 4 + +#define DEBUG_MENU_WIDTH_WEATHER 15 +#define DEBUG_MENU_HEIGHT_WEATHER 3 + +#define DEBUG_MENU_WIDTH_SOUND 20 +#define DEBUG_MENU_HEIGHT_SOUND 6 + +#define DEBUG_MENU_WIDTH_FLAGVAR 4 +#define DEBUG_MENU_HEIGHT_FLAGVAR 2 + +#define DEBUG_NUMBER_DIGITS_FLAGS 4 +#define DEBUG_NUMBER_DIGITS_VARIABLES 5 +#define DEBUG_NUMBER_DIGITS_VARIABLE_VALUE 5 +#define DEBUG_NUMBER_DIGITS_ITEMS 4 +#define DEBUG_NUMBER_DIGITS_ITEM_QUANTITY 3 + +#define DEBUG_NUMBER_ICON_X 210 +#define DEBUG_NUMBER_ICON_Y 50 + +#define DEBUG_MAX_MENU_ITEMS 50 + +// ******************************* +struct DebugMonData +{ + u16 species; + u8 level; + bool8 isShiny:1; + u8 nature:5; + u8 abilityNum:2; + u8 mon_iv_hp; + u8 mon_iv_atk; + u8 mon_iv_def; + u8 mon_iv_speed; + u8 mon_iv_satk; + u8 mon_iv_sdef; + u16 mon_move_0; + u16 mon_move_1; + u16 mon_move_2; + u16 mon_move_3; + u8 mon_ev_hp; + u8 mon_ev_atk; + u8 mon_ev_def; + u8 mon_ev_speed; + u8 mon_ev_satk; + u8 mon_ev_sdef; +}; + +struct DebugMenuListData +{ + struct ListMenuItem listItems[20 + 1]; + u8 itemNames[DEBUG_MAX_MENU_ITEMS + 1][26]; + u8 listId; +}; + +struct DebugBattleData +{ + u8 submenu; + u8 battleType; + u8 battleTerrain; + bool8 aiFlags[AI_FLAG_COUNT]; +}; + +// EWRAM +static EWRAM_DATA struct DebugMonData *sDebugMonData = NULL; +static EWRAM_DATA struct DebugMenuListData *sDebugMenuListData = NULL; +static EWRAM_DATA struct DebugBattleData *sDebugBattleData = NULL; +EWRAM_DATA bool8 gIsDebugBattle = FALSE; +EWRAM_DATA u32 gDebugAIFlags = 0; + +// ******************************* +// Define functions +static void Debug_ReShowMainMenu(void); +static void Debug_ShowMenu(void (*HandleInput)(u8), struct ListMenuTemplate LMtemplate); +static void Debug_DestroyMenu(u8 taskId); +static void Debug_DestroyMenu_Full(u8 taskId); +static void DebugAction_Cancel(u8 taskId); +static void DebugAction_DestroyExtraWindow(u8 taskId); +static void Debug_InitDebugBattleData(void); +static void Debug_RefreshListMenu(u8 taskId); +static void Debug_RedrawListMenu(u8 taskId); + +static void DebugAction_Util_Script_1(u8 taskId); +static void DebugAction_Util_Script_2(u8 taskId); +static void DebugAction_Util_Script_3(u8 taskId); +static void DebugAction_Util_Script_4(u8 taskId); +static void DebugAction_Util_Script_5(u8 taskId); +static void DebugAction_Util_Script_6(u8 taskId); +static void DebugAction_Util_Script_7(u8 taskId); +static void DebugAction_Util_Script_8(u8 taskId); + +static void DebugAction_OpenUtilitiesMenu(u8 taskId); +static void DebugAction_OpenPCBagMenu(u8 taskId); +static void DebugAction_OpenPartyMenu(u8 taskId); +static void DebugAction_OpenScriptsMenu(u8 taskId); +static void DebugAction_OpenFlagsVarsMenu(u8 taskId); +static void DebugAction_OpenGiveMenu(u8 taskId); +static void DebugAction_OpenSoundMenu(u8 taskId); + +static void DebugTask_HandleMenuInput_Main(u8 taskId); +static void DebugTask_HandleMenuInput_Utilities(u8 taskId); +static void DebugTask_HandleMenuInput_PCBag(u8 taskId); +static void DebugTask_HandleMenuInput_PCBag_Fill(u8 taskId); +static void DebugTask_HandleMenuInput_Party(u8 taskId); +static void DebugTask_HandleMenuInput_Scripts(u8 taskId); +static void DebugTask_HandleMenuInput_FlagsVars(u8 taskId); +static void DebugTask_HandleMenuInput_Battle(u8 taskId); +static void DebugTask_HandleMenuInput_Give(u8 taskId); +static void DebugTask_HandleMenuInput_Sound(u8 taskId); + +static void DebugAction_Util_Fly(u8 taskId); +static void DebugAction_Util_Warp_Warp(u8 taskId); +static void DebugAction_Util_Warp_SelectMapGroup(u8 taskId); +static void DebugAction_Util_Warp_SelectMap(u8 taskId); +static void DebugAction_Util_Warp_SelectWarp(u8 taskId); +static void DebugAction_Util_CheckSaveBlock(u8 taskId); +static void DebugAction_Util_CheckROMSpace(u8 taskId); +static void DebugAction_Util_Weather(u8 taskId); +static void DebugAction_Util_Weather_SelectId(u8 taskId); +static void DebugAction_Util_CheckWallClock(u8 taskId); +static void DebugAction_Util_SetWallClock(u8 taskId); +static void DebugAction_Util_WatchCredits(u8 taskId); +static void DebugAction_Util_Player_Name(u8 taskId); +static void DebugAction_Util_Player_Gender(u8 taskId); +static void DebugAction_Util_Player_Id(u8 taskId); +static void DebugAction_Util_CheatStart(u8 taskId); +static void DebugAction_Util_ExpansionVersion(u8 taskId); +static void DebugAction_Util_BerryFunctions(u8 taskId); + +static void DebugAction_OpenPCBagFillMenu(u8 taskId); +static void DebugAction_PCBag_Fill_PCBoxes_Fast(u8 taskId); +static void DebugAction_PCBag_Fill_PCBoxes_Slow(u8 taskId); +static void DebugAction_PCBag_Fill_PCItemStorage(u8 taskId); +static void DebugAction_PCBag_Fill_PocketItems(u8 taskId); +static void DebugAction_PCBag_Fill_PocketPokeBalls(u8 taskId); +static void DebugAction_PCBag_Fill_PocketTMHM(u8 taskId); +static void DebugAction_PCBag_Fill_PocketBerries(u8 taskId); +static void DebugAction_PCBag_Fill_PocketKeyItems(u8 taskId); +static void DebugAction_PCBag_AccessPC(u8 taskId); +static void DebugAction_PCBag_ClearBag(u8 taskId); +static void DebugAction_PCBag_ClearBoxes(u8 taskId); + +static void DebugAction_Party_MoveReminder(u8 taskId); +static void DebugAction_Party_HatchAnEgg(u8 taskId); +static void DebugAction_Party_HealParty(u8 taskId); +static void DebugAction_Party_InflictStatus1(u8 taskId); +static void DebugAction_Party_CheckEVs(u8 taskId); +static void DebugAction_Party_CheckIVs(u8 taskId); +static void DebugAction_Party_ClearParty(u8 taskId); + +static void DebugAction_FlagsVars_Flags(u8 taskId); +static void DebugAction_FlagsVars_FlagsSelect(u8 taskId); +static void DebugAction_FlagsVars_Vars(u8 taskId); +static void DebugAction_FlagsVars_Select(u8 taskId); +static void DebugAction_FlagsVars_SetValue(u8 taskId); +static void DebugAction_FlagsVars_PokedexFlags_All(u8 taskId); +static void DebugAction_FlagsVars_PokedexFlags_Reset(u8 taskId); +static void DebugAction_FlagsVars_SwitchDex(u8 taskId); +static void DebugAction_FlagsVars_SwitchNatDex(u8 taskId); +static void DebugAction_FlagsVars_SwitchPokeNav(u8 taskId); +static void DebugAction_FlagsVars_SwitchMatchCall(u8 taskId); +static void DebugAction_FlagsVars_ToggleFlyFlags(u8 taskId); +static void DebugAction_FlagsVars_ToggleBadgeFlags(u8 taskId); +static void DebugAction_FlagsVars_ToggleFrontierPass(u8 taskId); +static void DebugAction_FlagsVars_CollisionOnOff(u8 taskId); +static void DebugAction_FlagsVars_EncounterOnOff(u8 taskId); +static void DebugAction_FlagsVars_TrainerSeeOnOff(u8 taskId); +static void DebugAction_FlagsVars_BagUseOnOff(u8 taskId); +static void DebugAction_FlagsVars_CatchingOnOff(u8 taskId); +static void DebugAction_FlagsVars_RunningShoes(u8 taskId); + +static void Debug_InitializeBattle(u8 taskId); + +static void DebugAction_Give_Item(u8 taskId); +static void DebugAction_Give_Item_SelectId(u8 taskId); +static void DebugAction_Give_Item_SelectQuantity(u8 taskId); +static void DebugAction_Give_PokemonSimple(u8 taskId); +static void DebugAction_Give_PokemonComplex(u8 taskId); +static void DebugAction_Give_Pokemon_SelectId(u8 taskId); +static void DebugAction_Give_Pokemon_SelectLevel(u8 taskId); +static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId); +static void DebugAction_Give_Pokemon_SelectNature(u8 taskId); +static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId); +static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId); +static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId); +static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId); +static void DebugAction_Give_Pokemon_Move(u8 taskId); +static void DebugAction_Give_MaxMoney(u8 taskId); +static void DebugAction_Give_MaxCoins(u8 taskId); +static void DebugAction_Give_MaxBattlePoints(u8 taskId); +static void DebugAction_Give_DayCareEgg(u8 taskId); + +static void DebugAction_Sound_SE(u8 taskId); +static void DebugAction_Sound_SE_SelectId(u8 taskId); +static void DebugAction_Sound_MUS(u8 taskId); +static void DebugAction_Sound_MUS_SelectId(u8 taskId); + +extern const u8 Debug_FlagsNotSetOverworldConfigMessage[]; +extern const u8 Debug_FlagsNotSetBattleConfigMessage[]; +extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[]; +extern const u8 Debug_EventScript_CheckEVs[]; +extern const u8 Debug_EventScript_CheckIVs[]; +extern const u8 Debug_EventScript_InflictStatus1[]; +extern const u8 Debug_EventScript_Script_1[]; +extern const u8 Debug_EventScript_Script_2[]; +extern const u8 Debug_EventScript_Script_3[]; +extern const u8 Debug_EventScript_Script_4[]; +extern const u8 Debug_EventScript_Script_5[]; +extern const u8 Debug_EventScript_Script_6[]; +extern const u8 Debug_EventScript_Script_7[]; +extern const u8 Debug_EventScript_Script_8[]; +extern const u8 DebugScript_DaycareMonsNotCompatible[]; +extern const u8 DebugScript_OneDaycareMons[]; +extern const u8 DebugScript_ZeroDaycareMons[]; + +extern const u8 Debug_ShowFieldMessageStringVar4[]; +extern const u8 Debug_CheatStart[]; +extern const u8 Debug_HatchAnEgg[]; +extern const u8 PlayersHouse_2F_EventScript_SetWallClock[]; +extern const u8 PlayersHouse_2F_EventScript_CheckWallClock[]; +extern const u8 Debug_CheckSaveBlock[]; +extern const u8 Debug_CheckROMSpace[]; +extern const u8 Debug_BoxFilledMessage[]; +extern const u8 Debug_ShowExpansionVersion[]; + +extern const u8 FallarborTown_MoveRelearnersHouse_EventScript_ChooseMon[]; + +#include "data/map_group_count.h" + +// Text +// General +static const u8 sDebugText_True[] = _("TRUE"); +static const u8 sDebugText_False[] = _("FALSE"); +static const u8 sDebugText_Colored_True[] = _("{COLOR GREEN}TRUE"); +static const u8 sDebugText_Colored_False[] = _("{COLOR RED}FALSE"); +static const u8 sDebugText_Dashes[] = _("---"); +static const u8 sDebugText_Empty[] = _(""); +static const u8 sDebugText_Continue[] = _("Continue…{CLEAR_TO 110}{RIGHT_ARROW}"); +// Main Menu +static const u8 sDebugText_Utilities[] = _("Utilities…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_PCBag[] = _("PC/Bag…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Party[] = _("Party…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Scripts[] = _("Scripts…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_FlagsVars[] = _("Flags & Vars…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle[] = _("Battle Test{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Give[] = _("Give X…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Sound[] = _("Sound…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Cancel[] = _("Cancel"); +// Script menu +static const u8 sDebugText_Util_Script_1[] = _("Script 1"); +static const u8 sDebugText_Util_Script_2[] = _("Script 2"); +static const u8 sDebugText_Util_Script_3[] = _("Script 3"); +static const u8 sDebugText_Util_Script_4[] = _("Script 4"); +static const u8 sDebugText_Util_Script_5[] = _("Script 5"); +static const u8 sDebugText_Util_Script_6[] = _("Script 6"); +static const u8 sDebugText_Util_Script_7[] = _("Script 7"); +static const u8 sDebugText_Util_Script_8[] = _("Script 8"); +// Util Menu +static const u8 sDebugText_Util_FlyToMap[] = _("Fly to map…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_WarpToMap[] = _("Warp to map warp…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_WarpToMap_SelectMapGroup[] = _("Group: {STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n\n{STR_VAR_3}{CLEAR_TO 90}"); +static const u8 sDebugText_Util_WarpToMap_SelectMap[] = _("Map: {STR_VAR_1}{CLEAR_TO 90}\nMapSec:{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}\n{STR_VAR_3}{CLEAR_TO 90}"); +static const u8 sDebugText_Util_WarpToMap_SelectWarp[] = _("Warp:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_3}{CLEAR_TO 90}"); +static const u8 sDebugText_Util_WarpToMap_SelMax[] = _("{STR_VAR_1} / {STR_VAR_2}"); +static const u8 sDebugText_Util_SaveBlockSpace[] = _("Save Block space…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_ROMSpace[] = _("ROM space…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_Weather[] = _("Set weather…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_Weather_ID[] = _("Weather ID: {STR_VAR_3}\n{STR_VAR_1}\n{STR_VAR_2}"); +static const u8 sDebugText_Util_CheckWallClock[] = _("Check wall clock…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_SetWallClock[] = _("Set wall clock…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_WatchCredits[] = _("Watch credits…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Util_Player_Name[] = _("Player name"); +static const u8 sDebugText_Util_Player_Gender[] = _("Toggle gender"); +static const u8 sDebugText_Util_Player_Id[] = _("New Trainer ID"); +static const u8 sDebugText_Util_CheatStart[] = _("Cheat start"); +static const u8 sDebugText_Util_ExpansionVersion[] = _("Expansion Version"); +static const u8 sDebugText_Util_BerryFunctions[] = _("Berry Functions…{CLEAR_TO 110}{RIGHT_ARROW}"); +// PC/Bag Menu +static const u8 sDebugText_PCBag_Fill[] = _("Fill…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_PCBag_Fill_Pc_Fast[] = _("Fill PC Boxes Fast"); +static const u8 sDebugText_PCBag_Fill_Pc_Slow[] = _("Fill PC Boxes Slow (LAG!)"); +static const u8 sDebugText_PCBag_Fill_Pc_Items[] = _("Fill PC Items"); +static const u8 sDebugText_PCBag_Fill_PocketItems[] = _("Fill Pocket Items"); +static const u8 sDebugText_PCBag_Fill_PocketPokeBalls[] = _("Fill Pocket Poké Balls"); +static const u8 sDebugText_PCBag_Fill_PocketTMHM[] = _("Fill Pocket TMHM"); +static const u8 sDebugText_PCBag_Fill_PocketBerries[] = _("Fill Pocket Berries"); +static const u8 sDebugText_PCBag_Fill_PocketKeyItems[] = _("Fill Pocket Key Items"); +static const u8 sDebugText_PCBag_AccessPC[] = _("Access PC"); +static const u8 sDebugText_PCBag_ClearBag[] = _("Clear Bag"); +static const u8 sDebugText_PCBag_ClearBoxes[] = _("Clear Storage Boxes"); +// Party/Boxes Menu +static const u8 sDebugText_Party_MoveReminder[] = _("Move Reminder"); +static const u8 sDebugText_Party_HatchAnEgg[] = _("Hatch an Egg"); +static const u8 sDebugText_Party_HealParty[] = _("Heal party"); +static const u8 sDebugText_Party_InflictStatus1[] = _("Inflict Status1"); +static const u8 sDebugText_Party_CheckEVs[] = _("Check EVs"); +static const u8 sDebugText_Party_CheckIVs[] = _("Check IVs"); +static const u8 sDebugText_Party_ClearParty[] = _("Clear Party"); +// Flags/Vars Menu +static const u8 sDebugText_FlagsVars_Flags[] = _("Set Flag XYZ…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_FlagsVars_Flag[] = _("Flag: {STR_VAR_1}{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}\n{STR_VAR_3}"); +static const u8 sDebugText_FlagsVars_FlagHex[] = _("{STR_VAR_1}{CLEAR_TO 90}\n0x{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_FlagsVars_Vars[] = _("Set Var XYZ…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_FlagsVars_VariableHex[] = _("{STR_VAR_1}{CLEAR_TO 90}\n0x{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_FlagsVars_Variable[] = _("Var: {STR_VAR_1}{CLEAR_TO 90}\nVal: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_2}"); +static const u8 sDebugText_FlagsVars_VariableValueSet[] = _("Var: {STR_VAR_1}{CLEAR_TO 90}\nVal: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_2}"); +static const u8 sDebugText_FlagsVars_PokedexFlags_All[] = _("Pokédex Flags All"); +static const u8 sDebugText_FlagsVars_PokedexFlags_Reset[] = _("Pokédex Flags Reset"); +static const u8 sDebugText_FlagsVars_SwitchDex[] = _("Toggle {STR_VAR_1}Pokédex"); +static const u8 sDebugText_FlagsVars_SwitchNationalDex[] = _("Toggle {STR_VAR_1}National Dex"); +static const u8 sDebugText_FlagsVars_SwitchPokeNav[] = _("Toggle {STR_VAR_1}PokéNav"); +static const u8 sDebugText_FlagsVars_SwitchMatchCall[] = _("Toggle {STR_VAR_1}Match Call"); +static const u8 sDebugText_FlagsVars_RunningShoes[] = _("Toggle {STR_VAR_1}Running Shoes"); +static const u8 sDebugText_FlagsVars_ToggleFlyFlags[] = _("Toggle {STR_VAR_1}Fly Flags"); +static const u8 sDebugText_FlagsVars_ToggleAllBadges[] = _("Toggle {STR_VAR_1}All badges"); +static const u8 sDebugText_FlagsVars_ToggleFrontierPass[] = _("Toggle {STR_VAR_1}Frontier Pass"); +static const u8 sDebugText_FlagsVars_SwitchCollision[] = _("Toggle {STR_VAR_1}Collision OFF"); +static const u8 sDebugText_FlagsVars_SwitchEncounter[] = _("Toggle {STR_VAR_1}Encounter OFF"); +static const u8 sDebugText_FlagsVars_SwitchTrainerSee[] = _("Toggle {STR_VAR_1}Trainer See OFF"); +static const u8 sDebugText_FlagsVars_SwitchBagUse[] = _("Toggle {STR_VAR_1}Bag Use OFF"); +static const u8 sDebugText_FlagsVars_SwitchCatching[] = _("Toggle {STR_VAR_1}Catching OFF"); +// Battle +static const u8 sDebugText_Battle_0_Wild[] = _("Wild…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_0_WildDouble[] = _("Wild Double…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_0_Single[] = _("Single…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_0_Double[] = _("Double…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_0_Mulit[] = _("Multi…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_1_AIFlag_00[] = _("{STR_VAR_1}Check bad move"); +static const u8 sDebugText_Battle_1_AIFlag_01[] = _("{STR_VAR_1}Try to faint"); +static const u8 sDebugText_Battle_1_AIFlag_02[] = _("{STR_VAR_1}Check viability"); +static const u8 sDebugText_Battle_1_AIFlag_03[] = _("{STR_VAR_1}Setup first turn"); +static const u8 sDebugText_Battle_1_AIFlag_04[] = _("{STR_VAR_1}Risky"); +static const u8 sDebugText_Battle_1_AIFlag_05[] = _("{STR_VAR_1}Prefer strongest move"); +static const u8 sDebugText_Battle_1_AIFlag_06[] = _("{STR_VAR_1}Prefer Baton Pass"); +static const u8 sDebugText_Battle_1_AIFlag_07[] = _("{STR_VAR_1}Double battle"); +static const u8 sDebugText_Battle_1_AIFlag_08[] = _("{STR_VAR_1}HP aware"); +static const u8 sDebugText_Battle_1_AIFlag_09[] = _("{STR_VAR_1}Negate Unaware"); +static const u8 sDebugText_Battle_1_AIFlag_10[] = _("{STR_VAR_1}Will suicide"); +static const u8 sDebugText_Battle_1_AIFlag_11[] = _("{STR_VAR_1}Help partner"); +static const u8 sDebugText_Battle_1_AIFlag_12[] = _("{STR_VAR_1}Prefer status moves"); +static const u8 sDebugText_Battle_1_AIFlag_13[] = _("{STR_VAR_1}Stall"); +static const u8 sDebugText_Battle_1_AIFlag_14[] = _("{STR_VAR_1}Screener"); +static const u8 sDebugText_Battle_1_AIFlag_15[] = _("{STR_VAR_1}Smart switching"); +static const u8 sDebugText_Battle_1_AIFlag_16[] = _("{STR_VAR_1}Ace pokemon"); +static const u8 sDebugText_Battle_1_AIFlag_17[] = _("{STR_VAR_1}Omniscient"); +static const u8 sDebugText_Battle_2_Terrain_0[] = _("Grass…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_1[] = _("Long grass…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_2[] = _("Sand…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_3[] = _("Underwater…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_4[] = _("Water…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_5[] = _("Pond…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_6[] = _("Mountain…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_7[] = _("Cave…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_8[] = _("Building…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Battle_2_Terrain_9[] = _("Plain…{CLEAR_TO 110}{RIGHT_ARROW}"); +// Give Menu +static const u8 sDebugText_Give_GiveItem[] = _("Give item XYZ…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_ItemQuantity[] = _("Quantity:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}"); +static const u8 sDebugText_ItemID[] = _("Item ID: {STR_VAR_3}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}"); +static const u8 sDebugText_Give_GivePokemonSimple[] = _("Pokémon (Basic){CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Give_GivePokemonComplex[] = _("Pokémon (Complex){CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_PokemonID[] = _("Species: {STR_VAR_3}\n{STR_VAR_1}{CLEAR_TO 90}\n\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonLevel[] = _("Level:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonShiny[] = _("Shiny:{CLEAR_TO 90}\n {STR_VAR_2}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonNature[] = _("Nature ID: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonAbility[] = _("Ability Num: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonIVs[] = _("All IVs:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonEVs[] = _("All EVs:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_IV_HP[] = _("IV HP:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_IV_Attack[] = _("IV Attack:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_IV_Defense[] = _("IV Defense:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_IV_Speed[] = _("IV Speed:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_IV_SpAttack[] = _("IV Sp. Attack:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_IV_SpDefense[] = _("IV Sp. Defense:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_EV_HP[] = _("EV HP:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_EV_Attack[] = _("EV Attack:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_EV_Defense[] = _("EV Defense:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_EV_Speed[] = _("EV Speed:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_EV_SpAttack[] = _("EV Sp. Attack:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_EV_SpDefense[] = _("EV Sp. Defense:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonMove_0[] = _("Move 0: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonMove_1[] = _("Move 1: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonMove_2[] = _("Move 2: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonMove_3[] = _("Move 3: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_Give_MaxMoney[] = _("Max Money"); +static const u8 sDebugText_Give_MaxCoins[] = _("Max Coins"); +static const u8 sDebugText_Give_BattlePoints[] = _("Max Battle Points"); +static const u8 sDebugText_Give_DaycareEgg[] = _("Daycare Egg"); +// Sound Menu +static const u8 sDebugText_Sound_SFX[] = _("SFX…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Sound_SFX_ID[] = _("SFX ID: {STR_VAR_3} {START_BUTTON} Stop\n{STR_VAR_1} \n{STR_VAR_2}"); +static const u8 sDebugText_Sound_Music[] = _("Music…{CLEAR_TO 110}{RIGHT_ARROW}"); +static const u8 sDebugText_Sound_Music_ID[] = _("Music ID: {STR_VAR_3} {START_BUTTON} Stop\n{STR_VAR_1} \n{STR_VAR_2}"); +// Berry Function Menu +static const u8 sDebugText_BerryFunctions_ClearAll[] = _("Clear map trees"); +static const u8 sDebugText_BerryFunctions_Ready[] = _("Ready map trees"); +static const u8 sDebugText_BerryFunctions_NextStage[] = _("Grow map trees"); +static const u8 sDebugText_BerryFunctions_Pests[] = _("Give map trees pests"); +static const u8 sDebugText_BerryFunctions_Weeds[] = _("Give map trees weeds"); + +static const u8 sDebugText_Digit_1[] = _("{LEFT_ARROW}+1{RIGHT_ARROW} "); +static const u8 sDebugText_Digit_10[] = _("{LEFT_ARROW}+10{RIGHT_ARROW} "); +static const u8 sDebugText_Digit_100[] = _("{LEFT_ARROW}+100{RIGHT_ARROW} "); +static const u8 sDebugText_Digit_1000[] = _("{LEFT_ARROW}+1000{RIGHT_ARROW} "); +static const u8 sDebugText_Digit_10000[] = _("{LEFT_ARROW}+10000{RIGHT_ARROW} "); +static const u8 sDebugText_Digit_100000[] = _("{LEFT_ARROW}+100000{RIGHT_ARROW} "); +static const u8 sDebugText_Digit_1000000[] = _("{LEFT_ARROW}+1000000{RIGHT_ARROW} "); +static const u8 sDebugText_Digit_10000000[] = _("{LEFT_ARROW}+10000000{RIGHT_ARROW} "); +const u8 *const gText_DigitIndicator[] = +{ + sDebugText_Digit_1, + sDebugText_Digit_10, + sDebugText_Digit_100, + sDebugText_Digit_1000, + sDebugText_Digit_10000, + sDebugText_Digit_100000, + sDebugText_Digit_1000000, + sDebugText_Digit_10000000 +}; + +static const s32 sPowersOfTen[] = +{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, +}; + +// ******************************* +// List Menu Items +static const struct ListMenuItem sDebugMenu_Items_Main[] = +{ + [DEBUG_MENU_ITEM_UTILITIES] = {sDebugText_Utilities, DEBUG_MENU_ITEM_UTILITIES}, + [DEBUG_MENU_ITEM_PCBAG] = {sDebugText_PCBag, DEBUG_MENU_ITEM_PCBAG}, + [DEBUG_MENU_ITEM_PARTY] = {sDebugText_Party, DEBUG_MENU_ITEM_PARTY}, + [DEBUG_MENU_ITEM_GIVE] = {sDebugText_Give, DEBUG_MENU_ITEM_GIVE}, + [DEBUG_MENU_ITEM_SCRIPTS] = {sDebugText_Scripts, DEBUG_MENU_ITEM_SCRIPTS}, + [DEBUG_MENU_ITEM_FLAGVAR] = {sDebugText_FlagsVars, DEBUG_MENU_ITEM_FLAGVAR}, + //[DEBUG_MENU_ITEM_BATTLE] = {sDebugText_Battle, DEBUG_MENU_ITEM_BATTLE}, + [DEBUG_MENU_ITEM_SOUND] = {sDebugText_Sound, DEBUG_MENU_ITEM_SOUND}, + [DEBUG_MENU_ITEM_CANCEL] = {sDebugText_Cancel, DEBUG_MENU_ITEM_CANCEL}, +}; + +static const struct ListMenuItem sDebugMenu_Items_Utilities[] = +{ + [DEBUG_UTIL_MENU_ITEM_FLY] = {sDebugText_Util_FlyToMap, DEBUG_UTIL_MENU_ITEM_FLY}, + [DEBUG_UTIL_MENU_ITEM_WARP] = {sDebugText_Util_WarpToMap, DEBUG_UTIL_MENU_ITEM_WARP}, + [DEBUG_UTIL_MENU_ITEM_SAVEBLOCK] = {sDebugText_Util_SaveBlockSpace, DEBUG_UTIL_MENU_ITEM_SAVEBLOCK}, + [DEBUG_UTIL_MENU_ITEM_ROM_SPACE] = {sDebugText_Util_ROMSpace, DEBUG_UTIL_MENU_ITEM_ROM_SPACE}, + [DEBUG_UTIL_MENU_ITEM_WEATHER] = {sDebugText_Util_Weather, DEBUG_UTIL_MENU_ITEM_WEATHER}, + [DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK] = {sDebugText_Util_CheckWallClock, DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK}, + [DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK] = {sDebugText_Util_SetWallClock, DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK}, + [DEBUG_UTIL_MENU_ITEM_WATCHCREDITS] = {sDebugText_Util_WatchCredits, DEBUG_UTIL_MENU_ITEM_WATCHCREDITS}, + [DEBUG_UTIL_MENU_ITEM_PLAYER_NAME] = {sDebugText_Util_Player_Name, DEBUG_UTIL_MENU_ITEM_PLAYER_NAME}, + [DEBUG_UTIL_MENU_ITEM_PLAYER_GENDER] = {sDebugText_Util_Player_Gender, DEBUG_UTIL_MENU_ITEM_PLAYER_GENDER}, + [DEBUG_UTIL_MENU_ITEM_PLAYER_ID] = {sDebugText_Util_Player_Id, DEBUG_UTIL_MENU_ITEM_PLAYER_ID}, + [DEBUG_UTIL_MENU_ITEM_CHEAT] = {sDebugText_Util_CheatStart, DEBUG_UTIL_MENU_ITEM_CHEAT}, + [DEBUG_UTIL_MENU_ITEM_EXPANSION_VER] = {sDebugText_Util_ExpansionVersion, DEBUG_UTIL_MENU_ITEM_EXPANSION_VER}, + [DEBUG_UTIL_MENU_ITEM_BERRY_FUNCTIONS] = {sDebugText_Util_BerryFunctions, DEBUG_UTIL_MENU_ITEM_BERRY_FUNCTIONS}, +}; + +static const struct ListMenuItem sDebugMenu_Items_PCBag[] = +{ + [DEBUG_PCBAG_MENU_ITEM_ACCESS_PC] = {sDebugText_PCBag_AccessPC, DEBUG_PCBAG_MENU_ITEM_ACCESS_PC}, + [DEBUG_PCBAG_MENU_ITEM_FILL] = {sDebugText_PCBag_Fill, DEBUG_PCBAG_MENU_ITEM_FILL}, + [DEBUG_PCBAG_MENU_ITEM_CLEAR_BAG] = {sDebugText_PCBag_ClearBag, DEBUG_PCBAG_MENU_ITEM_CLEAR_BAG}, + [DEBUG_PCBAG_MENU_ITEM_CLEAR_BOXES] = {sDebugText_PCBag_ClearBoxes, DEBUG_PCBAG_MENU_ITEM_CLEAR_BOXES}, +}; + +static const struct ListMenuItem sDebugMenu_Items_PCBag_Fill[] = +{ + [DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_FAST] = {sDebugText_PCBag_Fill_Pc_Fast, DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_FAST}, + [DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_SLOW] = {sDebugText_PCBag_Fill_Pc_Slow, DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_SLOW}, + [DEBUG_PCBAG_MENU_ITEM_FILL_PC_ITEMS] = {sDebugText_PCBag_Fill_Pc_Items , DEBUG_PCBAG_MENU_ITEM_FILL_PC_ITEMS}, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_ITEMS] = {sDebugText_PCBag_Fill_PocketItems, DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_ITEMS}, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BALLS] = {sDebugText_PCBag_Fill_PocketPokeBalls, DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BALLS}, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_TMHM] = {sDebugText_PCBag_Fill_PocketTMHM, DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_TMHM}, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BERRIES] = {sDebugText_PCBag_Fill_PocketBerries, DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BERRIES}, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_KEY_ITEMS] = {sDebugText_PCBag_Fill_PocketKeyItems, DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_KEY_ITEMS}, +}; + +static const struct ListMenuItem sDebugMenu_Items_Party[] = +{ + [DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER] = {sDebugText_Party_MoveReminder, DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER}, + [DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG] = {sDebugText_Party_HatchAnEgg, DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG}, + [DEBUG_PARTY_MENU_ITEM_HEAL_PARTY] = {sDebugText_Party_HealParty, DEBUG_PARTY_MENU_ITEM_HEAL_PARTY}, + [DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1] = {sDebugText_Party_InflictStatus1, DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1}, + [DEBUG_PARTY_MENU_ITEM_CHECK_EVS] = {sDebugText_Party_CheckEVs, DEBUG_PARTY_MENU_ITEM_CHECK_EVS}, + [DEBUG_PARTY_MENU_ITEM_CHECK_IVS] = {sDebugText_Party_CheckIVs, DEBUG_PARTY_MENU_ITEM_CHECK_IVS}, + [DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY] = {sDebugText_Party_ClearParty, DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY}, +}; + +static const struct ListMenuItem sDebugMenu_Items_Scripts[] = +{ + [DEBUG_UTIL_MENU_ITEM_SCRIPT_1] = {sDebugText_Util_Script_1, DEBUG_UTIL_MENU_ITEM_SCRIPT_1}, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_2] = {sDebugText_Util_Script_2, DEBUG_UTIL_MENU_ITEM_SCRIPT_2}, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_3] = {sDebugText_Util_Script_3, DEBUG_UTIL_MENU_ITEM_SCRIPT_3}, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_4] = {sDebugText_Util_Script_4, DEBUG_UTIL_MENU_ITEM_SCRIPT_4}, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_5] = {sDebugText_Util_Script_5, DEBUG_UTIL_MENU_ITEM_SCRIPT_5}, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_6] = {sDebugText_Util_Script_6, DEBUG_UTIL_MENU_ITEM_SCRIPT_6}, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_7] = {sDebugText_Util_Script_7, DEBUG_UTIL_MENU_ITEM_SCRIPT_7}, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_8] = {sDebugText_Util_Script_8, DEBUG_UTIL_MENU_ITEM_SCRIPT_8}, +}; + +static const struct ListMenuItem sDebugMenu_Items_FlagsVars[] = +{ + [DEBUG_FLAGVAR_MENU_ITEM_FLAGS] = {sDebugText_FlagsVars_Flags, DEBUG_FLAGVAR_MENU_ITEM_FLAGS}, + [DEBUG_FLAGVAR_MENU_ITEM_VARS] = {sDebugText_FlagsVars_Vars, DEBUG_FLAGVAR_MENU_ITEM_VARS}, + [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL] = {sDebugText_FlagsVars_PokedexFlags_All, DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL}, + [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET] = {sDebugText_FlagsVars_PokedexFlags_Reset, DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = {sDebugText_FlagsVars_SwitchDex, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = {sDebugText_FlagsVars_SwitchNationalDex, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = {sDebugText_FlagsVars_SwitchPokeNav, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = {sDebugText_FlagsVars_SwitchMatchCall, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = {sDebugText_FlagsVars_RunningShoes, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = {sDebugText_FlagsVars_ToggleFlyFlags, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = {sDebugText_FlagsVars_ToggleAllBadges, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = {sDebugText_FlagsVars_ToggleFrontierPass, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION] = {sDebugText_FlagsVars_SwitchCollision, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = {sDebugText_FlagsVars_SwitchEncounter, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = {sDebugText_FlagsVars_SwitchTrainerSee, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = {sDebugText_FlagsVars_SwitchBagUse, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE}, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = {sDebugText_FlagsVars_SwitchCatching, DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING}, +}; + +static const struct ListMenuItem sDebugMenu_Items_Battle_0[] = +{ + [DEBUG_BATTLE_0_MENU_ITEM_WILD] = {sDebugText_Battle_0_Wild, DEBUG_BATTLE_0_MENU_ITEM_WILD}, + [DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE] = {sDebugText_Battle_0_WildDouble, DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE}, + [DEBUG_BATTLE_0_MENU_ITEM_SINGLE] = {sDebugText_Battle_0_Single, DEBUG_BATTLE_0_MENU_ITEM_SINGLE}, + [DEBUG_BATTLE_0_MENU_ITEM_DOUBLE] = {sDebugText_Battle_0_Double, DEBUG_BATTLE_0_MENU_ITEM_DOUBLE}, + [DEBUG_BATTLE_0_MENU_ITEM_MULTI] = {sDebugText_Battle_0_Mulit, DEBUG_BATTLE_0_MENU_ITEM_MULTI}, +}; + +static const struct ListMenuItem sDebugMenu_Items_Battle_1[] = +{ + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_00] = {sDebugText_Battle_1_AIFlag_00, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_00}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_01] = {sDebugText_Battle_1_AIFlag_01, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_01}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_02] = {sDebugText_Battle_1_AIFlag_02, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_02}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_03] = {sDebugText_Battle_1_AIFlag_03, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_03}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_04] = {sDebugText_Battle_1_AIFlag_04, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_04}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_05] = {sDebugText_Battle_1_AIFlag_05, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_05}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_06] = {sDebugText_Battle_1_AIFlag_06, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_06}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_07] = {sDebugText_Battle_1_AIFlag_07, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_07}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_08] = {sDebugText_Battle_1_AIFlag_08, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_08}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_09] = {sDebugText_Battle_1_AIFlag_09, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_09}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_10] = {sDebugText_Battle_1_AIFlag_10, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_10}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_11] = {sDebugText_Battle_1_AIFlag_11, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_11}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_12] = {sDebugText_Battle_1_AIFlag_12, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_12}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_13] = {sDebugText_Battle_1_AIFlag_13, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_13}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_14] = {sDebugText_Battle_1_AIFlag_14, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_14}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_15] = {sDebugText_Battle_1_AIFlag_15, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_15}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_16] = {sDebugText_Battle_1_AIFlag_16, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_16}, + [DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_17] = {sDebugText_Battle_1_AIFlag_17, DEBUG_BATTLE_1_MENU_ITEM_AI_FLAG_17}, + [DEBUG_BATTLE_1_MENU_ITEM_CONTINUE] = {sDebugText_Continue, DEBUG_BATTLE_1_MENU_ITEM_CONTINUE}, +}; + +static const struct ListMenuItem sDebugMenu_Items_Battle_2[] = +{ + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0] = {sDebugText_Battle_2_Terrain_0, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1] = {sDebugText_Battle_2_Terrain_1, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2] = {sDebugText_Battle_2_Terrain_2, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3] = {sDebugText_Battle_2_Terrain_3, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4] = {sDebugText_Battle_2_Terrain_4, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5] = {sDebugText_Battle_2_Terrain_5, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6] = {sDebugText_Battle_2_Terrain_6, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7] = {sDebugText_Battle_2_Terrain_7, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8] = {sDebugText_Battle_2_Terrain_8, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8}, + [DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_9] = {sDebugText_Battle_2_Terrain_9, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_9}, +}; + +static const struct ListMenuItem sDebugMenu_Items_Give[] = +{ + [DEBUG_GIVE_MENU_ITEM_ITEM_X] = {sDebugText_Give_GiveItem, DEBUG_GIVE_MENU_ITEM_ITEM_X}, + [DEBUG_GIVE_MENU_ITEM_POKEMON_SIMPLE] = {sDebugText_Give_GivePokemonSimple, DEBUG_GIVE_MENU_ITEM_POKEMON_SIMPLE}, + [DEBUG_GIVE_MENU_ITEM_POKEMON_COMPLEX] = {sDebugText_Give_GivePokemonComplex, DEBUG_GIVE_MENU_ITEM_POKEMON_COMPLEX}, + [DEBUG_GIVE_MENU_ITEM_MAX_MONEY] = {sDebugText_Give_MaxMoney, DEBUG_GIVE_MENU_ITEM_MAX_MONEY}, + [DEBUG_GIVE_MENU_ITEM_MAX_COINS] = {sDebugText_Give_MaxCoins, DEBUG_GIVE_MENU_ITEM_MAX_COINS}, + [DEBUG_GIVE_MENU_ITEM_MAX_BATTLE_POINTS] = {sDebugText_Give_BattlePoints, DEBUG_GIVE_MENU_ITEM_MAX_BATTLE_POINTS}, + [DEBUG_GIVE_MENU_ITEM_DAYCARE_EGG] = {sDebugText_Give_DaycareEgg, DEBUG_GIVE_MENU_ITEM_DAYCARE_EGG}, +}; + +static const struct ListMenuItem sDebugMenu_Items_Sound[] = +{ + [DEBUG_SOUND_MENU_ITEM_SE] = {sDebugText_Sound_SFX, DEBUG_SOUND_MENU_ITEM_SE}, + [DEBUG_SOUND_MENU_ITEM_MUS] = {sDebugText_Sound_Music, DEBUG_SOUND_MENU_ITEM_MUS}, +}; + +static const struct ListMenuItem sDebugMenu_Items_BerryFunctions[] = +{ + [DEBUG_BERRY_FUNCTIONS_MENU_CLEAR_ALL] = {sDebugText_BerryFunctions_ClearAll, DEBUG_BERRY_FUNCTIONS_MENU_CLEAR_ALL}, + [DEBUG_BERRY_FUNCTIONS_MENU_READY] = {sDebugText_BerryFunctions_Ready, DEBUG_BERRY_FUNCTIONS_MENU_READY}, + [DEBUG_BERRY_FUNCTIONS_MENU_NEXT_STAGE] = {sDebugText_BerryFunctions_NextStage, DEBUG_BERRY_FUNCTIONS_MENU_NEXT_STAGE}, + [DEBUG_BERRY_FUNCTIONS_MENU_PESTS] = {sDebugText_BerryFunctions_Pests, DEBUG_BERRY_FUNCTIONS_MENU_PESTS}, + [DEBUG_BERRY_FUNCTIONS_MENU_WEEDS] = {sDebugText_BerryFunctions_Weeds, DEBUG_BERRY_FUNCTIONS_MENU_WEEDS}, +}; + +// ******************************* +// Menu Actions +static void (*const sDebugMenu_Actions_Main[])(u8) = +{ + [DEBUG_MENU_ITEM_UTILITIES] = DebugAction_OpenUtilitiesMenu, + [DEBUG_MENU_ITEM_PCBAG] = DebugAction_OpenPCBagMenu, + [DEBUG_MENU_ITEM_PARTY] = DebugAction_OpenPartyMenu, + [DEBUG_MENU_ITEM_GIVE] = DebugAction_OpenGiveMenu, + [DEBUG_MENU_ITEM_SCRIPTS] = DebugAction_OpenScriptsMenu, + [DEBUG_MENU_ITEM_FLAGVAR] = DebugAction_OpenFlagsVarsMenu, + //[DEBUG_MENU_ITEM_BATTLE] = DebugAction_OpenBattleMenu, + [DEBUG_MENU_ITEM_SOUND] = DebugAction_OpenSoundMenu, + [DEBUG_MENU_ITEM_CANCEL] = DebugAction_Cancel +}; + +static void (*const sDebugMenu_Actions_Utilities[])(u8) = +{ + [DEBUG_UTIL_MENU_ITEM_FLY] = DebugAction_Util_Fly, + [DEBUG_UTIL_MENU_ITEM_WARP] = DebugAction_Util_Warp_Warp, + [DEBUG_UTIL_MENU_ITEM_SAVEBLOCK] = DebugAction_Util_CheckSaveBlock, + [DEBUG_UTIL_MENU_ITEM_ROM_SPACE] = DebugAction_Util_CheckROMSpace, + [DEBUG_UTIL_MENU_ITEM_WEATHER] = DebugAction_Util_Weather, + [DEBUG_UTIL_MENU_ITEM_CHECKWALLCLOCK] = DebugAction_Util_CheckWallClock, + [DEBUG_UTIL_MENU_ITEM_SETWALLCLOCK] = DebugAction_Util_SetWallClock, + [DEBUG_UTIL_MENU_ITEM_WATCHCREDITS] = DebugAction_Util_WatchCredits, + [DEBUG_UTIL_MENU_ITEM_PLAYER_NAME] = DebugAction_Util_Player_Name, + [DEBUG_UTIL_MENU_ITEM_PLAYER_GENDER] = DebugAction_Util_Player_Gender, + [DEBUG_UTIL_MENU_ITEM_PLAYER_ID] = DebugAction_Util_Player_Id, + [DEBUG_UTIL_MENU_ITEM_CHEAT] = DebugAction_Util_CheatStart, + [DEBUG_UTIL_MENU_ITEM_EXPANSION_VER] = DebugAction_Util_ExpansionVersion, + [DEBUG_UTIL_MENU_ITEM_BERRY_FUNCTIONS] = DebugAction_Util_BerryFunctions, +}; + +static void (*const sDebugMenu_Actions_PCBag[])(u8) = +{ + [DEBUG_PCBAG_MENU_ITEM_ACCESS_PC] = DebugAction_PCBag_AccessPC, + [DEBUG_PCBAG_MENU_ITEM_FILL] = DebugAction_OpenPCBagFillMenu, + [DEBUG_PCBAG_MENU_ITEM_CLEAR_BAG] = DebugAction_PCBag_ClearBag, + [DEBUG_PCBAG_MENU_ITEM_CLEAR_BOXES] = DebugAction_PCBag_ClearBoxes, +}; + +static void (*const sDebugMenu_Actions_PCBag_Fill[])(u8) = +{ + [DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_FAST] = DebugAction_PCBag_Fill_PCBoxes_Fast, + [DEBUG_PCBAG_MENU_ITEM_FILL_PC_BOXES_SLOW] = DebugAction_PCBag_Fill_PCBoxes_Slow, + [DEBUG_PCBAG_MENU_ITEM_FILL_PC_ITEMS] = DebugAction_PCBag_Fill_PCItemStorage, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_ITEMS] = DebugAction_PCBag_Fill_PocketItems, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BALLS] = DebugAction_PCBag_Fill_PocketPokeBalls, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_TMHM] = DebugAction_PCBag_Fill_PocketTMHM, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_BERRIES] = DebugAction_PCBag_Fill_PocketBerries, + [DEBUG_PCBAG_MENU_ITEM_FILL_POCKET_KEY_ITEMS] = DebugAction_PCBag_Fill_PocketKeyItems, +}; + +static void (*const sDebugMenu_Actions_Party[])(u8) = +{ + [DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER] = DebugAction_Party_MoveReminder, + [DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG] = DebugAction_Party_HatchAnEgg, + [DEBUG_PARTY_MENU_ITEM_HEAL_PARTY] = DebugAction_Party_HealParty, + [DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1] = DebugAction_Party_InflictStatus1, + [DEBUG_PARTY_MENU_ITEM_CHECK_EVS] = DebugAction_Party_CheckEVs, + [DEBUG_PARTY_MENU_ITEM_CHECK_IVS] = DebugAction_Party_CheckIVs, + [DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY] = DebugAction_Party_ClearParty, +}; + +static void (*const sDebugMenu_Actions_Scripts[])(u8) = +{ + [DEBUG_UTIL_MENU_ITEM_SCRIPT_1] = DebugAction_Util_Script_1, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_2] = DebugAction_Util_Script_2, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_3] = DebugAction_Util_Script_3, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_4] = DebugAction_Util_Script_4, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_5] = DebugAction_Util_Script_5, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_6] = DebugAction_Util_Script_6, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_7] = DebugAction_Util_Script_7, + [DEBUG_UTIL_MENU_ITEM_SCRIPT_8] = DebugAction_Util_Script_8, +}; + +static void (*const sDebugMenu_Actions_Flags[])(u8) = +{ + [DEBUG_FLAGVAR_MENU_ITEM_FLAGS] = DebugAction_FlagsVars_Flags, + [DEBUG_FLAGVAR_MENU_ITEM_VARS] = DebugAction_FlagsVars_Vars, + [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_ALL] = DebugAction_FlagsVars_PokedexFlags_All, + [DEBUG_FLAGVAR_MENU_ITEM_DEXFLAGS_RESET] = DebugAction_FlagsVars_PokedexFlags_Reset, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX] = DebugAction_FlagsVars_SwitchDex, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX] = DebugAction_FlagsVars_SwitchNatDex, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV] = DebugAction_FlagsVars_SwitchPokeNav, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL] = DebugAction_FlagsVars_SwitchMatchCall, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES] = DebugAction_FlagsVars_RunningShoes, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS] = DebugAction_FlagsVars_ToggleFlyFlags, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL] = DebugAction_FlagsVars_ToggleBadgeFlags, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS] = DebugAction_FlagsVars_ToggleFrontierPass, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION] = DebugAction_FlagsVars_CollisionOnOff, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER] = DebugAction_FlagsVars_EncounterOnOff, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE] = DebugAction_FlagsVars_TrainerSeeOnOff, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE] = DebugAction_FlagsVars_BagUseOnOff, + [DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING] = DebugAction_FlagsVars_CatchingOnOff, +}; +static void (*const sDebugMenu_Actions_Give[])(u8) = +{ + [DEBUG_GIVE_MENU_ITEM_ITEM_X] = DebugAction_Give_Item, + [DEBUG_GIVE_MENU_ITEM_POKEMON_SIMPLE] = DebugAction_Give_PokemonSimple, + [DEBUG_GIVE_MENU_ITEM_POKEMON_COMPLEX] = DebugAction_Give_PokemonComplex, + [DEBUG_GIVE_MENU_ITEM_MAX_MONEY] = DebugAction_Give_MaxMoney, + [DEBUG_GIVE_MENU_ITEM_MAX_COINS] = DebugAction_Give_MaxCoins, + [DEBUG_GIVE_MENU_ITEM_MAX_BATTLE_POINTS] = DebugAction_Give_MaxBattlePoints, + [DEBUG_GIVE_MENU_ITEM_DAYCARE_EGG] = DebugAction_Give_DayCareEgg, +}; + +static void (*const sDebugMenu_Actions_Sound[])(u8) = +{ + [DEBUG_SOUND_MENU_ITEM_SE] = DebugAction_Sound_SE, + [DEBUG_SOUND_MENU_ITEM_MUS] = DebugAction_Sound_MUS, +}; + +// ******************************* +// Windows +static const struct WindowTemplate sDebugMenuWindowTemplateMain = +{ + .bg = 0, + .tilemapLeft = 1, + .tilemapTop = 1, + .width = DEBUG_MENU_WIDTH_MAIN, + .height = 2 * DEBUG_MENU_HEIGHT_MAIN, + .paletteNum = 15, + .baseBlock = 1, +}; + +static const struct WindowTemplate sDebugMenuWindowTemplateExtra = +{ + .bg = 0, + .tilemapLeft = 30 - DEBUG_MENU_WIDTH_EXTRA - 1, + .tilemapTop = 1, + .width = DEBUG_MENU_WIDTH_EXTRA, + .height = 2 * DEBUG_MENU_HEIGHT_EXTRA, + .paletteNum = 15, + .baseBlock = 1, +}; + +static const struct WindowTemplate sDebugMenuWindowTemplateWeather = +{ + .bg = 0, + .tilemapLeft = 30 - DEBUG_MENU_WIDTH_WEATHER - 1, + .tilemapTop = 1, + .width = DEBUG_MENU_WIDTH_WEATHER, + .height = 2 * DEBUG_MENU_HEIGHT_WEATHER, + .paletteNum = 15, + .baseBlock = 1, +}; + +static const struct WindowTemplate sDebugMenuWindowTemplateSound = +{ + .bg = 0, + .tilemapLeft = 30 - DEBUG_MENU_WIDTH_SOUND - 1, + .tilemapTop = 1, + .width = DEBUG_MENU_WIDTH_SOUND, + .height = DEBUG_MENU_HEIGHT_SOUND, + .paletteNum = 15, + .baseBlock = 1, +}; + +static const struct WindowTemplate sDebugMenuWindowTemplateFlagsVars = +{ + .bg = 0, + .tilemapLeft = 30 - DEBUG_MENU_WIDTH_FLAGVAR - 1, + .tilemapTop = 1, + .width = DEBUG_MENU_WIDTH_FLAGVAR, + .height = DEBUG_MENU_HEIGHT_FLAGVAR, + .paletteNum = 15, + .baseBlock = 1 + DEBUG_MENU_WIDTH_MAIN * DEBUG_MENU_HEIGHT_MAIN * 2, +}; + +// ******************************* +// List Menu Templates +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Main = +{ + .items = sDebugMenu_Items_Main, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Main), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Utilities = +{ + .items = sDebugMenu_Items_Utilities, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Utilities), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_PCBag = +{ + .items = sDebugMenu_Items_PCBag, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_PCBag), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_PCBag_Fill = +{ + .items = sDebugMenu_Items_PCBag_Fill, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_PCBag_Fill), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Party = +{ + .items = sDebugMenu_Items_Party, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Party), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Scripts = +{ + .items = sDebugMenu_Items_Scripts, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Scripts), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_FlagsVars = +{ + .items = sDebugMenu_Items_FlagsVars, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_FlagsVars), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Battle_0 = +{ + .items = sDebugMenu_Items_Battle_0, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Battle_0), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Battle_1 = +{ + .items = sDebugMenu_Items_Battle_1, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Battle_1), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Battle_2 = +{ + .items = sDebugMenu_Items_Battle_2, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Battle_2), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Give = +{ + .items = sDebugMenu_Items_Give, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Give), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_Sound = +{ + .items = sDebugMenu_Items_Sound, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_Sound), +}; + +static const struct ListMenuTemplate sDebugMenu_ListTemplate_BerryFunctions = +{ + .items = sDebugMenu_Items_BerryFunctions, + .moveCursorFunc = ListMenuDefaultCursorMoveFunc, + .totalItems = ARRAY_COUNT(sDebugMenu_Items_BerryFunctions), +}; + +// ******************************* +// Functions universal +void Debug_ShowMainMenu(void) +{ + sDebugBattleData = AllocZeroed(sizeof(*sDebugBattleData)); + sDebugMenuListData = AllocZeroed(sizeof(*sDebugMenuListData)); + Debug_InitDebugBattleData(); + + Debug_ShowMenu(DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); +} + +static void Debug_ReShowMainMenu(void) +{ + Debug_ShowMenu(DebugTask_HandleMenuInput_Main, sDebugMenu_ListTemplate_Main); +} + +#define tMenuTaskId data[0] +#define tWindowId data[1] +#define tSubWindowId data[2] +#define tInput data[3] +#define tDigit data[4] + +static void Debug_ShowMenu(void (*HandleInput)(u8), struct ListMenuTemplate LMtemplate) +{ + struct ListMenuTemplate menuTemplate; + u8 windowId; + u8 menuTaskId; + u8 inputTaskId; + + // create window + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateMain); + DrawStdWindowFrame(windowId, FALSE); + + // create list menu + menuTemplate = LMtemplate; + menuTemplate.maxShowed = DEBUG_MENU_HEIGHT_MAIN; + menuTemplate.windowId = windowId; + menuTemplate.header_X = 0; + menuTemplate.item_X = 8; + menuTemplate.cursor_X = 0; + menuTemplate.upText_Y = 1; + menuTemplate.cursorPal = 2; + menuTemplate.fillValue = 1; + menuTemplate.cursorShadowPal = 3; + menuTemplate.lettersSpacing = 1; + menuTemplate.itemVerticalPadding = 0; + menuTemplate.scrollMultiple = LIST_NO_MULTIPLE_SCROLL; + menuTemplate.fontId = DEBUG_MENU_FONT; + menuTemplate.cursorKind = 0; + menuTaskId = ListMenuInit(&menuTemplate, 0, 0); + + // create input handler task + inputTaskId = CreateTask(HandleInput, 3); + gTasks[inputTaskId].tMenuTaskId = menuTaskId; + gTasks[inputTaskId].tWindowId = windowId; + gTasks[inputTaskId].tSubWindowId = 0; + + Debug_RefreshListMenu(inputTaskId); + + // draw everything + CopyWindowToVram(windowId, COPYWIN_FULL); +} + +static void Debug_DestroyMenu(u8 taskId) +{ + DestroyListMenuTask(gTasks[taskId].tMenuTaskId, NULL, NULL); + RemoveWindow(gTasks[taskId].tWindowId); + DestroyTask(taskId); +} + +static void Debug_DestroyMenu_Full(u8 taskId) +{ + if (gTasks[taskId].tSubWindowId != 0) + { + ClearStdWindowAndFrame(gTasks[taskId].tSubWindowId, FALSE); + DebugAction_DestroyExtraWindow(taskId); + } + DestroyListMenuTask(gTasks[taskId].tMenuTaskId, NULL, NULL); + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + DestroyTask(taskId); + UnfreezeObjectEvents(); + Free(sDebugMenuListData); + Free(sDebugBattleData); +} + +static void Debug_DestroyMenu_Full_Script(u8 taskId, const u8 *script) +{ + Debug_DestroyMenu_Full(taskId); + LockPlayerFieldControls(); + FreezeObjectEvents(); + ScriptContext_SetupScript(script); +} + +static void DebugAction_Cancel(u8 taskId) +{ + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); +} + +static void DebugAction_DestroyExtraWindow(u8 taskId) +{ + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + ClearStdWindowAndFrame(gTasks[taskId].tSubWindowId, TRUE); + RemoveWindow(gTasks[taskId].tSubWindowId); + + DestroyListMenuTask(gTasks[taskId].tMenuTaskId, NULL, NULL); + DestroyTask(taskId); + ScriptContext_Enable(); + UnfreezeObjectEvents(); +} + +static u8 Debug_CheckToggleFlags(u8 id) +{ + u8 result = FALSE; + + switch (id) + { + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKEDEX: + result = FlagGet(FLAG_SYS_POKEDEX_GET); + break; + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_NATDEX: + result = IsNationalPokedexEnabled(); + break; + // case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_POKENAV: + // result = FlagGet(FLAG_SYS_POKENAV_GET); + // break; + // case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_MATCH_CALL: + // result = FlagGet(FLAG_ADDED_MATCH_CALL_TO_POKENAV) && FlagGet(FLAG_HAS_MATCH_CALL); + // break; + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_RUN_SHOES: + result = FlagGet(FLAG_SYS_B_DASH); + break; + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_LOCATIONS: + result = FlagGet(FLAG_WORLD_MAP_PALLET_TOWN)/* && // TODO: debug + FlagGet(FLAG_VISITED_OLDALE_TOWN) && + FlagGet(FLAG_VISITED_DEWFORD_TOWN) && + FlagGet(FLAG_VISITED_LAVARIDGE_TOWN) && + FlagGet(FLAG_VISITED_FALLARBOR_TOWN) && + FlagGet(FLAG_VISITED_VERDANTURF_TOWN) && + FlagGet(FLAG_VISITED_PACIFIDLOG_TOWN) && + FlagGet(FLAG_VISITED_PETALBURG_CITY) && + FlagGet(FLAG_VISITED_SLATEPORT_CITY) && + FlagGet(FLAG_VISITED_MAUVILLE_CITY) && + FlagGet(FLAG_VISITED_RUSTBORO_CITY) && + FlagGet(FLAG_VISITED_FORTREE_CITY) && + FlagGet(FLAG_VISITED_LILYCOVE_CITY) && + FlagGet(FLAG_VISITED_MOSSDEEP_CITY) && + FlagGet(FLAG_VISITED_SOOTOPOLIS_CITY) && + FlagGet(FLAG_VISITED_EVER_GRANDE_CITY) && + FlagGet(FLAG_LANDMARK_POKEMON_LEAGUE) && + FlagGet(FLAG_LANDMARK_BATTLE_FRONTIER) */; + break; + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BADGES_ALL: + result = FlagGet(FLAG_BADGE01_GET) && + FlagGet(FLAG_BADGE02_GET) && + FlagGet(FLAG_BADGE03_GET) && + FlagGet(FLAG_BADGE04_GET) && + FlagGet(FLAG_BADGE05_GET) && + FlagGet(FLAG_BADGE06_GET) && + FlagGet(FLAG_BADGE07_GET) && + FlagGet(FLAG_BADGE08_GET); + break; + // case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_FRONTIER_PASS: + // result = FlagGet(FLAG_SYS_FRONTIER_PASS); + // break; + #if OW_FLAG_NO_COLLISION != 0 + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_COLISSION: + result = FlagGet(OW_FLAG_NO_COLLISION); + break; + #endif + #if OW_FLAG_NO_ENCOUNTER != 0 + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_ENCOUNTER: + result = FlagGet(OW_FLAG_NO_ENCOUNTER); + break; + #endif + #if OW_FLAG_NO_TRAINER_SEE != 0 + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_TRAINER_SEE: + result = FlagGet(OW_FLAG_NO_TRAINER_SEE); + break; + #endif + #if B_FLAG_NO_BAG_USE != 0 + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_BAG_USE: + result = FlagGet(B_FLAG_NO_BAG_USE); + break; + #endif + #if B_FLAG_NO_CATCHING != 0 + case DEBUG_FLAGVAR_MENU_ITEM_TOGGLE_CATCHING: + result = FlagGet(B_FLAG_NO_CATCHING); + break; + #endif + default: + result = 0xFF; + break; + } + + return result; +} + +static void Debug_InitDebugBattleData(void) +{ + u32 i; + sDebugBattleData->submenu = 0; + sDebugBattleData->battleType = 0xFF; + sDebugBattleData->battleTerrain = 0xFF; + + for (i = 0; i < AI_FLAG_COUNT; i++) + sDebugBattleData->aiFlags[i] = FALSE; +} + +static void Debug_GenerateListMenuNames(u32 totalItems) +{ + const u8 sColor_Red[] = _("{COLOR RED}"); + const u8 sColor_Green[] = _("{COLOR GREEN}"); + u32 i, flagResult = 0; + u8 const *name = NULL; + + // Copy item names for all entries but the last (which is Cancel) + for (i = 0; i < totalItems; i++) + { + if (sDebugMenuListData->listId == 1 && sDebugBattleData->submenu > 1) + { + u16 species; + if (i == 6) + { + name = sDebugText_Continue; + StringCopy(&sDebugMenuListData->itemNames[i][0], name); + } + else if (GetMonData(&gEnemyParty[i], MON_DATA_SANITY_HAS_SPECIES)) + { + species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES); + StringCopy(gStringVar1, GetSpeciesName(species)); + StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar1); + } + else + { + StringCopy(&sDebugMenuListData->itemNames[i][0], sDebugText_Dashes); + } + } + else + { + if (sDebugMenuListData->listId == 0) + { + flagResult = Debug_CheckToggleFlags(i); + name = sDebugMenu_Items_FlagsVars[i].label; + } + else if (sDebugMenuListData->listId == 1) + { + flagResult = sDebugBattleData->aiFlags[i]; + if (i == totalItems - 1) + flagResult = 0xFF; + name = sDebugMenu_Items_Battle_1[i].label; + } + + if (flagResult == 0xFF) + { + StringCopy(&sDebugMenuListData->itemNames[i][0], name); + } + else if (flagResult) + { + StringCopy(gStringVar1, sColor_Green); + StringExpandPlaceholders(gStringVar4, name); + StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); + } + else + { + StringCopy(gStringVar1, sColor_Red); + StringExpandPlaceholders(gStringVar4, name); + StringCopy(&sDebugMenuListData->itemNames[i][0], gStringVar4); + } + } + + sDebugMenuListData->listItems[i].label = &sDebugMenuListData->itemNames[i][0]; + sDebugMenuListData->listItems[i].index = i; + } +} + +static void Debug_RefreshListMenu(u8 taskId) +{ + u8 totalItems = 0; + + if (sDebugMenuListData->listId == 0) + { + gMultiuseListMenuTemplate = sDebugMenu_ListTemplate_FlagsVars; + totalItems = gMultiuseListMenuTemplate.totalItems; + } + else if (sDebugMenuListData->listId == 1 && sDebugBattleData->submenu <= 1) + { + gMultiuseListMenuTemplate = sDebugMenu_ListTemplate_Battle_1; + totalItems = gMultiuseListMenuTemplate.totalItems; + } + else if (sDebugMenuListData->listId == 1 && sDebugBattleData->submenu > 1) + { + gMultiuseListMenuTemplate = sDebugMenu_ListTemplate_Battle_2; + totalItems = 7; + } + + // Failsafe to prevent memory corruption + totalItems = min(totalItems, DEBUG_MAX_MENU_ITEMS); + Debug_GenerateListMenuNames(totalItems); + + // Set list menu data + gMultiuseListMenuTemplate.items = sDebugMenuListData->listItems; + gMultiuseListMenuTemplate.totalItems = totalItems; + gMultiuseListMenuTemplate.maxShowed = DEBUG_MENU_HEIGHT_MAIN; + gMultiuseListMenuTemplate.windowId = gTasks[taskId].tWindowId; + gMultiuseListMenuTemplate.header_X = 0; + gMultiuseListMenuTemplate.item_X = 8; + gMultiuseListMenuTemplate.cursor_X = 0; + gMultiuseListMenuTemplate.upText_Y = 1; + gMultiuseListMenuTemplate.cursorPal = 2; + gMultiuseListMenuTemplate.fillValue = 1; + gMultiuseListMenuTemplate.cursorShadowPal = 3; + gMultiuseListMenuTemplate.lettersSpacing = 1; + gMultiuseListMenuTemplate.itemVerticalPadding = 0; + gMultiuseListMenuTemplate.scrollMultiple = LIST_NO_MULTIPLE_SCROLL; + gMultiuseListMenuTemplate.fontId = 1; + gMultiuseListMenuTemplate.cursorKind = 0; +} + +static void Debug_RedrawListMenu(u8 taskId) +{ + u8 listTaskId = gTasks[taskId].tMenuTaskId; + u16 scrollOffset, selectedRow; + ListMenuGetScrollAndRow(listTaskId, &scrollOffset, &selectedRow); + + DestroyListMenuTask(gTasks[taskId].tMenuTaskId, &scrollOffset, &selectedRow); + Debug_RefreshListMenu(taskId); + gTasks[taskId].tMenuTaskId = ListMenuInit(&gMultiuseListMenuTemplate, scrollOffset, selectedRow); +} + + +// ******************************* +// Handle Inputs +static void DebugTask_HandleMenuInput_Main(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_Main[input]) != NULL) + func(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); + } +} + +static void DebugTask_HandleMenuInput_Utilities(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_Utilities[input]) != NULL) + func(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ReShowMainMenu(); + } +} + +static void DebugTask_HandleMenuInput_PCBag(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_PCBag[input]) != NULL) + func(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ReShowMainMenu(); + } +} + +static void DebugTask_HandleMenuInput_PCBag_Fill(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_PCBag_Fill[input]) != NULL) + func(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_PCBag, sDebugMenu_ListTemplate_PCBag); + } +} + +static void DebugTask_HandleMenuInput_Party(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_Party[input]) != NULL) + func(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ReShowMainMenu(); + } +} + +static void DebugTask_HandleMenuInput_Scripts(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_Scripts[input]) != NULL) + func(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ReShowMainMenu(); + } +} + +static void DebugTask_HandleMenuInput_FlagsVars(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_Flags[input]) != NULL) + { + if (input == DEBUG_FLAGVAR_MENU_ITEM_FLAGS || input == DEBUG_FLAGVAR_MENU_ITEM_VARS) + { + Debug_RedrawListMenu(taskId); + func(taskId); + } + else + { + func(taskId); + Debug_GenerateListMenuNames(gMultiuseListMenuTemplate.totalItems); + RedrawListMenu(gTasks[taskId].tMenuTaskId); + } + + // Remove TRUE/FALSE window for functions that haven't been assigned flags + if (gTasks[taskId].tInput == 0xFF) + { + ClearStdWindowAndFrame(gTasks[taskId].tSubWindowId, TRUE); + RemoveWindow(gTasks[taskId].tSubWindowId); + Free(sDebugMenuListData); + } + } + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ReShowMainMenu(); + } +} + +static void DebugTask_HandleBattleMenuReDraw(u8 taskId) +{ + Debug_RefreshListMenu(taskId); + switch (sDebugBattleData->submenu) + { + case 0: + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_0); + break; + case 1: + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, gMultiuseListMenuTemplate); + break; + case 2: + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_2); + break; + case 3: + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, gMultiuseListMenuTemplate); + break; + } +} + +static void DebugTask_HandleMenuInput_Battle(u8 taskId) +{ + u16 idx; + u8 listTaskId = gTasks[taskId].tMenuTaskId; + ListMenu_ProcessInput(listTaskId); + + ListMenuGetCurrentItemArrayId(listTaskId, &idx); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + + switch (sDebugBattleData->submenu) + { + case 0: // Battle type + sDebugBattleData->battleType = idx; + sDebugBattleData->submenu++; + Debug_DestroyMenu(taskId); + + if (sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD // Skip AI Flag selection if wild battle + || sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE) + { + sDebugBattleData->submenu++; + Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_2); + } + else + { + Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, gMultiuseListMenuTemplate); + } + break; + case 1: // AI Flags + if (idx == sDebugMenu_ListTemplate_Battle_1.totalItems - 1) + { + sDebugBattleData->submenu++; + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, sDebugMenu_ListTemplate_Battle_2); + } + else + { + sDebugBattleData->aiFlags[idx] = !sDebugBattleData->aiFlags[idx]; + Debug_RedrawListMenu(taskId); + } + + break; + case 2: // Terrain + sDebugBattleData->submenu++; + sDebugBattleData->battleTerrain = idx; + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Battle, gMultiuseListMenuTemplate); + break; + case 3: // Enemy pokemon + if (idx == 6) + Debug_InitializeBattle(taskId); + break; + } + } + else if (JOY_NEW(B_BUTTON)) + { + switch (sDebugBattleData->submenu) + { + case 0: // Return to Main menu + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ReShowMainMenu(); + break; + case 2: // Skip AI Flag selection if wild battle + if (sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD + || sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE) + { + sDebugBattleData->submenu = 0; + } + else + sDebugBattleData->submenu--; + DebugTask_HandleBattleMenuReDraw(taskId); + break; + default: + sDebugBattleData->submenu--; + DebugTask_HandleBattleMenuReDraw(taskId); + break; + } + } +} + +static void Debug_InitializeBattle(u8 taskId) +{ + u32 i; + gBattleTypeFlags = 0; + + // Set main battle flags + switch (sDebugBattleData->battleType) + { + case DEBUG_BATTLE_0_MENU_ITEM_WILD: + break; + case DEBUG_BATTLE_0_MENU_ITEM_SINGLE: + gBattleTypeFlags = (BATTLE_TYPE_TRAINER); + break; + case DEBUG_BATTLE_0_MENU_ITEM_DOUBLE: + gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER); + break; + case DEBUG_BATTLE_0_MENU_ITEM_MULTI: + gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER); + break; + } + + // Set terrain + gBattleTerrain = sDebugBattleData->battleTerrain; + + // Populate enemy party + for (i = 0; i < PARTY_SIZE; i++) + { + ZeroMonData(&gEnemyParty[i]); + if (GetMonData(&gPlayerParty[i], MON_DATA_SANITY_HAS_SPECIES)) + gEnemyParty[i] = gPlayerParty[i]; + } + + // Set AI flags + for (i = 0; i < ARRAY_COUNT(sDebugBattleData->aiFlags); i++) + { + if (sDebugBattleData->aiFlags[i]) + gDebugAIFlags |= (1 << i); + } + + gIsDebugBattle = TRUE; + BattleSetup_StartTrainerBattle_Debug(); + + + Debug_DestroyMenu_Full(taskId); +} + +static void DebugTask_HandleMenuInput_Give(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_Give[input]) != NULL) + func(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ReShowMainMenu(); + } +} + +static void DebugTask_HandleMenuInput_Sound(u8 taskId) +{ + void (*func)(u8); + u32 input = ListMenu_ProcessInput(gTasks[taskId].tMenuTaskId); + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + if ((func = sDebugMenu_Actions_Sound[input]) != NULL) + func(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Debug_DestroyMenu(taskId); + Debug_ReShowMainMenu(); + } +} + +// ******************************* +// Open sub-menus +static void DebugAction_OpenUtilitiesMenu(u8 taskId) +{ + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Utilities, sDebugMenu_ListTemplate_Utilities); +} + +static void DebugAction_OpenPCBagMenu(u8 taskId) +{ + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_PCBag, sDebugMenu_ListTemplate_PCBag); +} + +static void DebugAction_OpenPartyMenu(u8 taskId) +{ + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Party, sDebugMenu_ListTemplate_Party); +} + +static void DebugAction_OpenScriptsMenu(u8 taskId) +{ + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Scripts, sDebugMenu_ListTemplate_Scripts); +} + +static void DebugAction_OpenFlagsVarsMenu(u8 taskId) +{ + Debug_DestroyMenu(taskId); + sDebugMenuListData->listId = 0; + Debug_ShowMenu(DebugTask_HandleMenuInput_FlagsVars, gMultiuseListMenuTemplate); +} + +static void DebugAction_OpenGiveMenu(u8 taskId) +{ + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Give, sDebugMenu_ListTemplate_Give); +} + +static void DebugAction_OpenSoundMenu(u8 taskId) +{ + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_Sound, sDebugMenu_ListTemplate_Sound); +} + +static void DebugAction_Util_BerryFunctions(u8 taskId) +{ + Debug_DestroyMenu(taskId); +} + +// ******************************* +// Actions Utilities + +static void DebugAction_Util_Fly(u8 taskId) +{ + Debug_DestroyMenu_Full(taskId); + SetMainCallback2(CB2_OpenFlyMap); +} + +#define tMapGroup data[5] +#define tMapNum data[6] +#define tWarp data[7] + +#define LAST_MAP_GROUP (MAP_GROUPS_COUNT - 1) + +static void DebugAction_Util_Warp_Warp(u8 taskId) +{ + u8 windowId; + + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateExtra); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + ConvertIntToDecimalStringN(gStringVar2, LAST_MAP_GROUP, STR_CONV_MODE_LEADING_ZEROS, 3); + StringExpandPlaceholders(gStringVar1, sDebugText_Util_WarpToMap_SelMax); + StringCopy(gStringVar3, gText_DigitIndicator[0]); + StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMapGroup); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Util_Warp_SelectMapGroup; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tMapGroup = 0; + gTasks[taskId].tMapNum = 0; + gTasks[taskId].tWarp = 0; +} + +static void DebugAction_Util_Warp_SelectMapGroup(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > LAST_MAP_GROUP) + gTasks[taskId].tInput = LAST_MAP_GROUP; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < 2) + gTasks[taskId].tDigit += 1; + } + + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + ConvertIntToDecimalStringN(gStringVar2, LAST_MAP_GROUP, STR_CONV_MODE_LEADING_ZEROS, 3); + StringExpandPlaceholders(gStringVar1, sDebugText_Util_WarpToMap_SelMax); + StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMapGroup); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + gTasks[taskId].tMapGroup = gTasks[taskId].tInput; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, (MAP_GROUP_COUNT[gTasks[taskId].tMapGroup] - 1 >= 100) ? 3 : 2); + ConvertIntToDecimalStringN(gStringVar2, MAP_GROUP_COUNT[gTasks[taskId].tMapGroup] - 1, STR_CONV_MODE_LEADING_ZEROS, (MAP_GROUP_COUNT[gTasks[taskId].tMapGroup] - 1 >= 100) ? 3 : 2); + StringExpandPlaceholders(gStringVar1, sDebugText_Util_WarpToMap_SelMax); + GetMapName(gStringVar2, Overworld_GetMapHeaderByGroupAndId(gTasks[taskId].tMapGroup, gTasks[taskId].tInput)->regionMapSectionId, 0); + StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMap); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Util_Warp_SelectMap; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Util_Warp_SelectMap(u8 taskId) +{ + u8 max_value = MAP_GROUP_COUNT[gTasks[taskId].tMapGroup]; //maps in the selected map group + + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > max_value - 1) + gTasks[taskId].tInput = max_value - 1; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < 2) + gTasks[taskId].tDigit += 1; + } + + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, (max_value >= 100) ? 3 : 2); + ConvertIntToDecimalStringN(gStringVar2, MAP_GROUP_COUNT[gTasks[taskId].tMapGroup] - 1, STR_CONV_MODE_LEADING_ZEROS, (max_value >= 100) ? 3 : 2); + StringExpandPlaceholders(gStringVar1, sDebugText_Util_WarpToMap_SelMax); + GetMapName(gStringVar2, Overworld_GetMapHeaderByGroupAndId(gTasks[taskId].tMapGroup, gTasks[taskId].tInput)->regionMapSectionId, 0); + StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMap); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + gTasks[taskId].tMapNum = gTasks[taskId].tInput; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectWarp); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + gTasks[taskId].func = DebugAction_Util_Warp_SelectWarp; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Util_Warp_SelectWarp(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > 10) + gTasks[taskId].tInput = 10; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + + StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectWarp); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + gTasks[taskId].tWarp = gTasks[taskId].tInput; + //If there's no warp with the number available, warp to the center of the map. + SetWarpDestinationToMapWarp(gTasks[taskId].tMapGroup, gTasks[taskId].tMapNum, gTasks[taskId].tWarp); + DoWarp(); + ResetInitialPlayerAvatarState(); + DebugAction_DestroyExtraWindow(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + } +} + +#undef tMapGroup +#undef tMapNum +#undef tWarp + +void CheckSaveBlock1Size(struct ScriptContext *ctx) +{ + u32 currSb1Size = sizeof(struct SaveBlock1); + u32 maxSb1Size = SECTOR_DATA_SIZE * (SECTOR_ID_SAVEBLOCK1_END - SECTOR_ID_SAVEBLOCK1_START + 1); + ConvertIntToDecimalStringN(gStringVar1, currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar2, maxSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar3, maxSb1Size - currSb1Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar4, 1, STR_CONV_MODE_LEFT_ALIGN, 6); +} + +void CheckSaveBlock2Size(struct ScriptContext *ctx) +{ + u32 currSb2Size = (sizeof(struct SaveBlock2)); + u32 maxSb2Size = SECTOR_DATA_SIZE; + ConvertIntToDecimalStringN(gStringVar1, currSb2Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar2, maxSb2Size, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar3, maxSb2Size - currSb2Size, STR_CONV_MODE_LEFT_ALIGN, 6); +} + +// void CheckSaveBlock3Size(struct ScriptContext *ctx) +// { +// u32 currSb3Size = (sizeof(struct SaveBlock3)); +// u32 maxSb3Size = SAVE_BLOCK_3_CHUNK_SIZE * NUM_SECTORS_PER_SLOT; +// ConvertIntToDecimalStringN(gStringVar1, currSb3Size, STR_CONV_MODE_LEFT_ALIGN, 6); +// ConvertIntToDecimalStringN(gStringVar2, maxSb3Size, STR_CONV_MODE_LEFT_ALIGN, 6); +// ConvertIntToDecimalStringN(gStringVar3, maxSb3Size - currSb3Size, STR_CONV_MODE_LEFT_ALIGN, 6); +// } + +void CheckPokemonStorageSize(struct ScriptContext *ctx) +{ + u32 currPkmnStorageSize = sizeof(struct PokemonStorage); + u32 maxPkmnStorageSize = SECTOR_DATA_SIZE * (SECTOR_ID_PKMN_STORAGE_END - SECTOR_ID_PKMN_STORAGE_START + 1); + ConvertIntToDecimalStringN(gStringVar1, currPkmnStorageSize, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar2, maxPkmnStorageSize, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar3, maxPkmnStorageSize - currPkmnStorageSize, STR_CONV_MODE_LEFT_ALIGN, 6); +} + +static void DebugAction_Util_CheckSaveBlock(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_CheckSaveBlock); +} + +enum RoundMode +{ + ROUND_CEILING, + ROUND_NEAREST, + ROUND_FLOOR, +}; + +static u8 *ConvertQ22_10ToDecimalString(u8 *string, u32 q22_10, u32 decimalDigits, enum RoundMode roundMode) +{ + string = ConvertIntToDecimalStringN(string, q22_10 >> 10, STR_CONV_MODE_LEFT_ALIGN, 10); + + if (decimalDigits == 0) + return string; + + *string++ = CHAR_PERIOD; + + q22_10 &= (1 << 10) - 1; + while (decimalDigits-- > 1) + { + q22_10 *= 10; + *string++ = CHAR_0 + (q22_10 >> 10); + q22_10 &= (1 << 10) - 1; + } + + q22_10 *= 10; + switch (roundMode) + { + case ROUND_CEILING: q22_10 += (1 << 10) - 1; break; + case ROUND_NEAREST: q22_10 += 1 << (10 - 1); break; + case ROUND_FLOOR: break; + } + *string++ = CHAR_0 + (q22_10 >> 10); + + *string++ = EOS; + + return string; +} + +void CheckROMSize(struct ScriptContext *ctx) +{ + extern u8 __rom_end[]; + u32 currROMSizeB = __rom_end - (const u8 *)ROM_START; + u32 currROMSizeKB = (currROMSizeB + 1023) / 1024; + u32 currROMFreeKB = ((const u8 *)ROM_END - __rom_end) / 1024; + ConvertQ22_10ToDecimalString(gStringVar1, currROMSizeKB, 2, ROUND_CEILING); + ConvertQ22_10ToDecimalString(gStringVar2, currROMFreeKB, 2, ROUND_FLOOR); +} + +static void DebugAction_Util_CheckROMSpace(u8 taskId) +{ + Debug_DestroyMenu_Full(taskId); + LockPlayerFieldControls(); + ScriptContext_SetupScript(Debug_CheckROMSpace); +} + +static const u8 sWeatherNames[22][24] = { + [WEATHER_NONE] = _("NONE"), + [WEATHER_SUNNY_CLOUDS] = _("SUNNY CLOUDS"), + [WEATHER_SUNNY] = _("SUNNY"), + [WEATHER_RAIN] = _("RAIN"), + [WEATHER_SNOW] = _("SNOW"), + [WEATHER_RAIN_THUNDERSTORM] = _("RAIN THUNDERSTORM"), + [WEATHER_FOG_HORIZONTAL] = _("FOG HORIZONTAL"), + [WEATHER_VOLCANIC_ASH] = _("VOLCANIC ASH"), + [WEATHER_SANDSTORM] = _("SANDSTORM"), + [WEATHER_FOG_DIAGONAL] = _("FOG DIAGONAL"), + [WEATHER_UNDERWATER] = _("UNDERWATER"), + [WEATHER_SHADE] = _("SHADE"), + [WEATHER_DROUGHT] = _("DROUGHT"), + [WEATHER_DOWNPOUR] = _("DOWNPOUR"), + [WEATHER_UNDERWATER_BUBBLES] = _("UNDERWATER BUBBLES"), + [WEATHER_ABNORMAL] = _("ABNORMAL(NOT WORKING)"), + [WEATHER_ROUTE119_CYCLE] = _("ROUTE119 CYCLE"), + [WEATHER_ROUTE123_CYCLE] = _("ROUTE123 CYCLE"), +}; +static const u8 sDebugText_WeatherNotDefined[] = _("NOT DEFINED!!!"); +static void DebugAction_Util_Weather(u8 taskId) +{ + u8 windowId; + + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateWeather); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + //Display initial ID + StringCopy(gStringVar2, gText_DigitIndicator[0]); + ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar1, sWeatherNames[0], CHAR_SPACE, 30); + StringExpandPlaceholders(gStringVar4, sDebugText_Util_Weather_ID); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Util_Weather_SelectId; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; +} + +static void DebugAction_Util_Weather_SelectId(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > WEATHER_ROUTE123_CYCLE) + gTasks[taskId].tInput = WEATHER_ROUTE123_CYCLE; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < WEATHER_NONE) + gTasks[taskId].tInput = WEATHER_NONE; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < 2) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + + if (gTasks[taskId].tInput <= 15 || gTasks[taskId].tInput >= 20) + StringCopyPadded(gStringVar1, sWeatherNames[gTasks[taskId].tInput], CHAR_SPACE, 30); + else + StringCopyPadded(gStringVar1, sDebugText_WeatherNotDefined, CHAR_SPACE, 30); + + StringExpandPlaceholders(gStringVar4, sDebugText_Util_Weather_ID); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + if (gTasks[taskId].tInput <= 14 || gTasks[taskId].tInput >= 20) + { + gTasks[taskId].data[5] = gTasks[taskId].tInput; + SetWeather(gTasks[taskId].data[5]); + } + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Util_CheckWallClock(u8 taskId) +{ + // Debug_DestroyMenu_Full_Script(taskId, PlayersHouse_2F_EventScript_CheckWallClock); +} + +static void DebugAction_Util_SetWallClock(u8 taskId) +{ + // Debug_DestroyMenu_Full_Script(taskId, PlayersHouse_2F_EventScript_SetWallClock); +} + +static void DebugAction_Util_WatchCredits(u8 taskId) +{ + Debug_DestroyMenu_Full(taskId); + SetMainCallback2(DoCredits); +} + +static void DebugAction_Util_Player_Name(u8 taskId) +{ + DoNamingScreen(NAMING_SCREEN_PLAYER, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldContinueScript); +} + +static void DebugAction_Util_Player_Gender(u8 taskId) +{ + if (gSaveBlock2Ptr->playerGender == MALE) + gSaveBlock2Ptr->playerGender = FEMALE; + else + gSaveBlock2Ptr->playerGender = MALE; + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); +} + +static void DebugAction_Util_Player_Id(u8 taskId) +{ + u32 trainerId = Random32(); + SetTrainerId(trainerId, gSaveBlock2Ptr->playerTrainerId); + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); +} + +static void DebugAction_Util_CheatStart(u8 taskId) +{ + if (!FlagGet(FLAG_SYS_CLOCK_SET)) + RtcInitLocalTimeOffset(0, 0); + + InitTimeBasedEvents(); + Debug_DestroyMenu_Full_Script(taskId, Debug_CheatStart); +} + +static void DebugAction_Util_ExpansionVersion(u8 taskId) +{ + Debug_DestroyMenu_Full(taskId); + // LockPlayerFieldControls(); + // ScriptContext_SetupScript(Debug_ShowExpansionVersion); +} + +// void BufferExpansionVersion(struct ScriptContext *ctx) +// { +// static const u8 sText_Released[] = _("\nRelease Build"); +// static const u8 sText_Unreleased[] = _("\nDevelopment Build"); +// u8 *string = gStringVar1; +// *string++ = CHAR_v; +// string = ConvertIntToDecimalStringN(string, EXPANSION_VERSION_MAJOR, STR_CONV_MODE_LEFT_ALIGN, 3); +// *string++ = CHAR_PERIOD; +// string = ConvertIntToDecimalStringN(string, EXPANSION_VERSION_MINOR, STR_CONV_MODE_LEFT_ALIGN, 3); +// *string++ = CHAR_PERIOD; +// string = ConvertIntToDecimalStringN(string, EXPANSION_VERSION_PATCH, STR_CONV_MODE_LEFT_ALIGN, 3); +// if (EXPANSION_TAGGED_RELEASE) +// string = StringCopy(string, sText_Released); +// else +// string = StringCopy(string, sText_Unreleased); +// } + +// ******************************* +// Actions Scripts +static void DebugAction_Util_Script_1(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_1); +} + +static void DebugAction_Util_Script_2(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_2); +} + +static void DebugAction_Util_Script_3(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_3); +} + +static void DebugAction_Util_Script_4(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_4); +} + +static void DebugAction_Util_Script_5(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_5); +} + +static void DebugAction_Util_Script_6(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_6); +} + +static void DebugAction_Util_Script_7(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_7); +} + +static void DebugAction_Util_Script_8(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_Script_8); +} + +// ******************************* +// Actions Flags and Vars +static void DebugAction_FlagsVars_Flags(u8 taskId) +{ + u8 windowId; + + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateExtra); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + // Display initial flag + ConvertIntToDecimalStringN(gStringVar1, 1, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_FLAGS); + ConvertIntToHexStringN(gStringVar2, 1, STR_CONV_MODE_LEFT_ALIGN, 3); + StringExpandPlaceholders(gStringVar1, sDebugText_FlagsVars_FlagHex); + if (FlagGet(FLAG_TEMP_1)) + StringCopyPadded(gStringVar2, sDebugText_True, CHAR_SPACE, 15); + else + StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15); + StringCopy(gStringVar3, gText_DigitIndicator[0]); + StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Flag); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_FlagsVars_FlagsSelect; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = FLAG_TEMP_1; + gTasks[taskId].tDigit = 0; +} + +static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) +{ + if (JOY_NEW(A_BUTTON)) + { + FlagToggle(gTasks[taskId].tInput); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + return; + } + + if (JOY_NEW(DPAD_UP)) + { + PlaySE(SE_SELECT); + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput >= FLAGS_COUNT) + gTasks[taskId].tInput = FLAGS_COUNT - 1; + } + if (JOY_NEW(DPAD_DOWN)) + { + PlaySE(SE_SELECT); + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 1) + gTasks[taskId].tInput = 1; + } + if (JOY_NEW(DPAD_LEFT)) + { + PlaySE(SE_SELECT); + gTasks[taskId].tDigit -= 1; + if (gTasks[taskId].tDigit < 0) + gTasks[taskId].tDigit = 0; + } + if (JOY_NEW(DPAD_RIGHT)) + { + PlaySE(SE_SELECT); + gTasks[taskId].tDigit += 1; + if (gTasks[taskId].tDigit > DEBUG_NUMBER_DIGITS_FLAGS - 1) + gTasks[taskId].tDigit = DEBUG_NUMBER_DIGITS_FLAGS - 1; + } + + if (JOY_NEW(DPAD_ANY) || JOY_NEW(A_BUTTON)) + { + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_FLAGS); + ConvertIntToHexStringN(gStringVar2, gTasks[taskId].tInput, STR_CONV_MODE_LEFT_ALIGN, 3); + StringExpandPlaceholders(gStringVar1, sDebugText_FlagsVars_FlagHex); + if (FlagGet(gTasks[taskId].tInput) == TRUE) + StringCopyPadded(gStringVar2, sDebugText_True, CHAR_SPACE, 15); + else + StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15); + StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Flag); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } +} + +#define tVarValue data[5] + +static void DebugAction_FlagsVars_Vars(u8 taskId) +{ + u8 windowId; + + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateExtra); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + // Display initial var + ConvertIntToDecimalStringN(gStringVar1, VARS_START, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_VARIABLES); + ConvertIntToHexStringN(gStringVar2, VARS_START, STR_CONV_MODE_LEFT_ALIGN, 4); + StringExpandPlaceholders(gStringVar1, sDebugText_FlagsVars_VariableHex); + ConvertIntToDecimalStringN(gStringVar3, 0, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_VARIABLES); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopy(gStringVar2, gText_DigitIndicator[0]); + StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Variable); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_FlagsVars_Select; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = VARS_START; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tVarValue = 0; +} + +static void DebugAction_FlagsVars_Select(u8 taskId) +{ + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > VARS_END) + gTasks[taskId].tInput = VARS_END; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < VARS_START) + gTasks[taskId].tInput = VARS_START; + } + if (JOY_NEW(DPAD_LEFT)) + { + gTasks[taskId].tDigit -= 1; + if (gTasks[taskId].tDigit < 0) + gTasks[taskId].tDigit = 0; + } + if (JOY_NEW(DPAD_RIGHT)) + { + gTasks[taskId].tDigit += 1; + if (gTasks[taskId].tDigit > DEBUG_NUMBER_DIGITS_VARIABLES - 1) + gTasks[taskId].tDigit = DEBUG_NUMBER_DIGITS_VARIABLES - 1; + } + + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_VARIABLES); + ConvertIntToHexStringN(gStringVar2, gTasks[taskId].tInput, STR_CONV_MODE_LEFT_ALIGN, 4); + StringExpandPlaceholders(gStringVar1, sDebugText_FlagsVars_VariableHex); + if (VarGetIfExist(gTasks[taskId].tInput) == 0xFFFF) + gTasks[taskId].tVarValue = 0; + else + gTasks[taskId].tVarValue = VarGet(gTasks[taskId].tInput); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tVarValue, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_VARIABLES); + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + + //Combine str's to full window string + StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Variable); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + gTasks[taskId].tDigit = 0; + + PlaySE(SE_SELECT); + + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_VARIABLES); + ConvertIntToHexStringN(gStringVar2, gTasks[taskId].tInput, STR_CONV_MODE_LEFT_ALIGN, 4); + StringExpandPlaceholders(gStringVar1, sDebugText_FlagsVars_VariableHex); + if (VarGetIfExist(gTasks[taskId].tInput) == 0xFFFF) + gTasks[taskId].tVarValue = 0; + else + gTasks[taskId].tVarValue = VarGet(gTasks[taskId].tInput); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tVarValue, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_VARIABLES); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_VariableValueSet); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].data[6] = gTasks[taskId].data[5]; //New value selector + gTasks[taskId].func = DebugAction_FlagsVars_SetValue; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + return; + } +} + +static void DebugAction_FlagsVars_SetValue(u8 taskId) +{ + if (JOY_NEW(DPAD_UP)) + { + if (gTasks[taskId].data[6] + sPowersOfTen[gTasks[taskId].tDigit] <= 32000) + gTasks[taskId].data[6] += sPowersOfTen[gTasks[taskId].tDigit]; + else + gTasks[taskId].data[6] = 32000 - 1; + + if (gTasks[taskId].data[6] >= 32000) + gTasks[taskId].data[6] = 32000 - 1; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].data[6] -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].data[6] < 0) + gTasks[taskId].data[6] = 0; + } + if (JOY_NEW(DPAD_LEFT)) + { + gTasks[taskId].tDigit -= 1; + if (gTasks[taskId].tDigit < 0) + gTasks[taskId].tDigit = 0; + } + if (JOY_NEW(DPAD_RIGHT)) + { + gTasks[taskId].tDigit += 1; + if (gTasks[taskId].tDigit > 4) + gTasks[taskId].tDigit = 4; + } + + if (JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + VarSet(gTasks[taskId].tInput, gTasks[taskId].data[6]); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + return; + } + + if (JOY_NEW(DPAD_ANY) || JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_VARIABLES); + ConvertIntToHexStringN(gStringVar2, gTasks[taskId].tInput, STR_CONV_MODE_LEFT_ALIGN, 4); + StringExpandPlaceholders(gStringVar1, sDebugText_FlagsVars_VariableHex); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].data[6], STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_VARIABLES); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_VariableValueSet); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } +} + +#undef tVarValue + +static void DebugAction_FlagsVars_PokedexFlags_All(u8 taskId) +{ + u16 i; + for (i = 0; i < NATIONAL_DEX_COUNT; i++) + { + GetSetPokedexFlag(i + 1, FLAG_SET_CAUGHT); + GetSetPokedexFlag(i + 1, FLAG_SET_SEEN); + } + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); +} + +static void DebugAction_FlagsVars_PokedexFlags_Reset(u8 taskId) +{ + int boxId, boxPosition, partyId; + u16 species; + + // Reset Pokedex to emtpy + memset(&gSaveBlock2Ptr->pokedex.owned, 0, sizeof(gSaveBlock2Ptr->pokedex.owned)); + memset(&gSaveBlock2Ptr->pokedex.seen, 0, sizeof(gSaveBlock2Ptr->pokedex.seen)); + + // Add party Pokemon to Pokedex + for (partyId = 0; partyId < PARTY_SIZE; partyId++) + { + if (GetMonData(&gPlayerParty[partyId], MON_DATA_SANITY_HAS_SPECIES)) + { + species = GetMonData(&gPlayerParty[partyId], MON_DATA_SPECIES); + GetSetPokedexFlag(SpeciesToNationalDexNum(species), FLAG_SET_CAUGHT); + GetSetPokedexFlag(SpeciesToNationalDexNum(species), FLAG_SET_SEEN); + } + } + + // Add box Pokemon to Pokedex + for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++) + { + for (boxPosition = 0; boxPosition < IN_BOX_COUNT; boxPosition++) + { + if (GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], MON_DATA_SANITY_HAS_SPECIES)) + { + species = GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], MON_DATA_SPECIES); + GetSetPokedexFlag(SpeciesToNationalDexNum(species), FLAG_SET_CAUGHT); + GetSetPokedexFlag(SpeciesToNationalDexNum(species), FLAG_SET_SEEN); + } + } + } + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); +} + +static void DebugAction_FlagsVars_SwitchDex(u8 taskId) +{ + if (FlagGet(FLAG_SYS_POKEDEX_GET)) + PlaySE(SE_PC_OFF); + else + PlaySE(SE_PC_LOGIN); + FlagToggle(FLAG_SYS_POKEDEX_GET); +} + +static void DebugAction_FlagsVars_SwitchNatDex(u8 taskId) +{ + if (IsNationalPokedexEnabled()) + { + DisableNationalPokedex(); + PlaySE(SE_PC_OFF); + } + else + { + EnableNationalPokedex(); + PlaySE(SE_PC_LOGIN); + } +} + +static void DebugAction_FlagsVars_SwitchPokeNav(u8 taskId) +{ + // if (FlagGet(FLAG_SYS_POKENAV_GET)) + // PlaySE(SE_PC_OFF); + // else + // PlaySE(SE_PC_LOGIN); + // FlagToggle(FLAG_SYS_POKENAV_GET); +} + +static void DebugAction_FlagsVars_SwitchMatchCall(u8 taskId) +{ + // if (FlagGet(FLAG_ADDED_MATCH_CALL_TO_POKENAV)) + // { + // PlaySE(SE_PC_OFF); + // FlagClear(FLAG_ADDED_MATCH_CALL_TO_POKENAV); + // FlagClear(FLAG_HAS_MATCH_CALL); + // } + // else + // { + // PlaySE(SE_PC_LOGIN); + // FlagSet(FLAG_ADDED_MATCH_CALL_TO_POKENAV); + // FlagSet(FLAG_HAS_MATCH_CALL); + // } +} + +static void DebugAction_FlagsVars_RunningShoes(u8 taskId) +{ + if (FlagGet(FLAG_SYS_B_DASH)) + PlaySE(SE_PC_OFF); + else + PlaySE(SE_PC_LOGIN); + FlagToggle(FLAG_SYS_B_DASH); +} + +static void DebugAction_FlagsVars_ToggleFlyFlags(u8 taskId) +{ + // TODO: debug + // if (FlagGet(FLAG_LANDMARK_BATTLE_FRONTIER)) + // { + // PlaySE(SE_PC_OFF); + // FlagClear(FLAG_VISITED_LITTLEROOT_TOWN); + // FlagClear(FLAG_VISITED_OLDALE_TOWN); + // FlagClear(FLAG_VISITED_DEWFORD_TOWN); + // FlagClear(FLAG_VISITED_LAVARIDGE_TOWN); + // FlagClear(FLAG_VISITED_FALLARBOR_TOWN); + // FlagClear(FLAG_VISITED_VERDANTURF_TOWN); + // FlagClear(FLAG_VISITED_PACIFIDLOG_TOWN); + // FlagClear(FLAG_VISITED_PETALBURG_CITY); + // FlagClear(FLAG_VISITED_SLATEPORT_CITY); + // FlagClear(FLAG_VISITED_MAUVILLE_CITY); + // FlagClear(FLAG_VISITED_RUSTBORO_CITY); + // FlagClear(FLAG_VISITED_FORTREE_CITY); + // FlagClear(FLAG_VISITED_LILYCOVE_CITY); + // FlagClear(FLAG_VISITED_MOSSDEEP_CITY); + // FlagClear(FLAG_VISITED_SOOTOPOLIS_CITY); + // FlagClear(FLAG_VISITED_EVER_GRANDE_CITY); + // FlagClear(FLAG_LANDMARK_POKEMON_LEAGUE); + // FlagClear(FLAG_LANDMARK_BATTLE_FRONTIER); + // } + // else + // { + // PlaySE(SE_PC_LOGIN); + // FlagSet(FLAG_VISITED_LITTLEROOT_TOWN); + // FlagSet(FLAG_VISITED_OLDALE_TOWN); + // FlagSet(FLAG_VISITED_DEWFORD_TOWN); + // FlagSet(FLAG_VISITED_LAVARIDGE_TOWN); + // FlagSet(FLAG_VISITED_FALLARBOR_TOWN); + // FlagSet(FLAG_VISITED_VERDANTURF_TOWN); + // FlagSet(FLAG_VISITED_PACIFIDLOG_TOWN); + // FlagSet(FLAG_VISITED_PETALBURG_CITY); + // FlagSet(FLAG_VISITED_SLATEPORT_CITY); + // FlagSet(FLAG_VISITED_MAUVILLE_CITY); + // FlagSet(FLAG_VISITED_RUSTBORO_CITY); + // FlagSet(FLAG_VISITED_FORTREE_CITY); + // FlagSet(FLAG_VISITED_LILYCOVE_CITY); + // FlagSet(FLAG_VISITED_MOSSDEEP_CITY); + // FlagSet(FLAG_VISITED_SOOTOPOLIS_CITY); + // FlagSet(FLAG_VISITED_EVER_GRANDE_CITY); + // FlagSet(FLAG_LANDMARK_POKEMON_LEAGUE); + // FlagSet(FLAG_LANDMARK_BATTLE_FRONTIER); + // } +} + +static void DebugAction_FlagsVars_ToggleBadgeFlags(u8 taskId) +{ + if (FlagGet(FLAG_BADGE08_GET)) + { + PlaySE(SE_PC_OFF); + FlagClear(FLAG_BADGE01_GET); + FlagClear(FLAG_BADGE02_GET); + FlagClear(FLAG_BADGE03_GET); + FlagClear(FLAG_BADGE04_GET); + FlagClear(FLAG_BADGE05_GET); + FlagClear(FLAG_BADGE06_GET); + FlagClear(FLAG_BADGE07_GET); + FlagClear(FLAG_BADGE08_GET); + } + else + { + PlaySE(SE_PC_LOGIN); + FlagSet(FLAG_BADGE01_GET); + FlagSet(FLAG_BADGE02_GET); + FlagSet(FLAG_BADGE03_GET); + FlagSet(FLAG_BADGE04_GET); + FlagSet(FLAG_BADGE05_GET); + FlagSet(FLAG_BADGE06_GET); + FlagSet(FLAG_BADGE07_GET); + FlagSet(FLAG_BADGE08_GET); + } +} + +static void DebugAction_FlagsVars_ToggleFrontierPass(u8 taskId) +{ + // // Sound effect + // if (FlagGet(FLAG_SYS_FRONTIER_PASS)) + // PlaySE(SE_PC_OFF); + // else + // PlaySE(SE_PC_LOGIN); + // FlagToggle(FLAG_SYS_FRONTIER_PASS); +} + +static void DebugAction_FlagsVars_CollisionOnOff(u8 taskId) +{ +#if OW_FLAG_NO_COLLISION == 0 + Debug_DestroyMenu_Full_Script(taskId, Debug_FlagsNotSetOverworldConfigMessage); +#else + if (FlagGet(OW_FLAG_NO_COLLISION)) + PlaySE(SE_PC_OFF); + else + PlaySE(SE_PC_LOGIN); + FlagToggle(OW_FLAG_NO_COLLISION); +#endif +} + +static void DebugAction_FlagsVars_EncounterOnOff(u8 taskId) +{ +#if OW_FLAG_NO_ENCOUNTER == 0 + Debug_DestroyMenu_Full_Script(taskId, Debug_FlagsNotSetOverworldConfigMessage); +#else + if (FlagGet(OW_FLAG_NO_ENCOUNTER)) + PlaySE(SE_PC_OFF); + else + PlaySE(SE_PC_LOGIN); + FlagToggle(OW_FLAG_NO_ENCOUNTER); +#endif +} + +static void DebugAction_FlagsVars_TrainerSeeOnOff(u8 taskId) +{ +#if OW_FLAG_NO_TRAINER_SEE == 0 + Debug_DestroyMenu_Full_Script(taskId, Debug_FlagsNotSetOverworldConfigMessage); +#else + if (FlagGet(OW_FLAG_NO_TRAINER_SEE)) + PlaySE(SE_PC_OFF); + else + PlaySE(SE_PC_LOGIN); + FlagToggle(OW_FLAG_NO_TRAINER_SEE); +#endif +} + +static void DebugAction_FlagsVars_BagUseOnOff(u8 taskId) +{ +#if B_FLAG_NO_BAG_USE == 0 + Debug_DestroyMenu_Full_Script(taskId, Debug_FlagsNotSetBattleConfigMessage); +#else + if (FlagGet(B_FLAG_NO_BAG_USE)) + PlaySE(SE_PC_OFF); + else + PlaySE(SE_PC_LOGIN); + FlagToggle(B_FLAG_NO_BAG_USE); +#endif +} + +static void DebugAction_FlagsVars_CatchingOnOff(u8 taskId) +{ +#if B_FLAG_NO_CATCHING == 0 + Debug_DestroyMenu_Full_Script(taskId, Debug_FlagsNotSetBattleConfigMessage); +#else + if (FlagGet(B_FLAG_NO_CATCHING)) + PlaySE(SE_PC_OFF); + else + PlaySE(SE_PC_LOGIN); + FlagToggle(B_FLAG_NO_CATCHING); +#endif +} + +// ******************************* +// Actions Give +#define ITEM_TAG 0xFDF3 +#define tItemId data[5] +#define tSpriteId data[6] + +static void DebugAction_Give_Item(u8 taskId) +{ + u8 windowId; + + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateExtra); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + // Display initial item + StringCopy(gStringVar2, gText_DigitIndicator[0]); + ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + CopyItemName(1, gStringVar1); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_ItemID); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Item_SelectId; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = 1; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tSpriteId = AddItemIconObject(ITEM_TAG, ITEM_TAG, gTasks[taskId].tInput); + gSprites[gTasks[taskId].tSpriteId].x2 = DEBUG_NUMBER_ICON_X+10; + gSprites[gTasks[taskId].tSpriteId].y2 = DEBUG_NUMBER_ICON_Y+10; + gSprites[gTasks[taskId].tSpriteId].oam.priority = 0; +} + +static void DebugAction_Give_Item_SelectId(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput >= ITEMS_COUNT) + gTasks[taskId].tInput = ITEMS_COUNT - 1; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 1) + gTasks[taskId].tInput = 1; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < DEBUG_NUMBER_DIGITS_ITEMS - 1) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + CopyItemName(gTasks[taskId].tInput, gStringVar1); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + StringExpandPlaceholders(gStringVar4, sDebugText_ItemID); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + FreeSpriteTilesByTag(ITEM_TAG); //Destroy item icon + FreeSpritePaletteByTag(ITEM_TAG); //Destroy item icon + FreeSpriteOamMatrix(&gSprites[gTasks[taskId].tSpriteId]); //Destroy item icon + DestroySprite(&gSprites[gTasks[taskId].tSpriteId]); //Destroy item icon + gTasks[taskId].tSpriteId = AddItemIconObject(ITEM_TAG, ITEM_TAG, gTasks[taskId].tInput); + gSprites[gTasks[taskId].tSpriteId].x2 = DEBUG_NUMBER_ICON_X+10; + gSprites[gTasks[taskId].tSpriteId].y2 = DEBUG_NUMBER_ICON_Y+10; + gSprites[gTasks[taskId].tSpriteId].oam.priority = 0; + } + + if (JOY_NEW(A_BUTTON)) + { + gTasks[taskId].tItemId = gTasks[taskId].tInput; + gTasks[taskId].tInput = 1; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEM_QUANTITY); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_ItemQuantity); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Item_SelectQuantity; + } + else if (JOY_NEW(B_BUTTON)) + { + FreeSpriteTilesByTag(ITEM_TAG); //Destroy item icon + FreeSpritePaletteByTag(ITEM_TAG); //Destroy item icon + FreeSpriteOamMatrix(&gSprites[gTasks[taskId].tSpriteId]); //Destroy item icon + DestroySprite(&gSprites[gTasks[taskId].tSpriteId]); //Destroy item icon + + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Item_SelectQuantity(u8 taskId) +{ + u32 itemId = gTasks[taskId].tItemId; + + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > MAX_BAG_ITEM_CAPACITY) + gTasks[taskId].tInput = MAX_BAG_ITEM_CAPACITY; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 1) + gTasks[taskId].tInput = 1; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < MAX_ITEM_DIGITS) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEM_QUANTITY); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_ItemQuantity); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + FreeSpriteTilesByTag(ITEM_TAG); //Destroy item icon + FreeSpritePaletteByTag(ITEM_TAG); //Destroy item icon + FreeSpriteOamMatrix(&gSprites[gTasks[taskId].tSpriteId]); //Destroy item icon + DestroySprite(&gSprites[gTasks[taskId].tSpriteId]); //Destroy item icon + + PlaySE(MUS_LEVEL_UP); + AddBagItem(itemId, gTasks[taskId].tInput); + DebugAction_DestroyExtraWindow(taskId); + } + else if (JOY_NEW(B_BUTTON)) + { + FreeSpriteTilesByTag(ITEM_TAG); //Destroy item icon + FreeSpritePaletteByTag(ITEM_TAG); //Destroy item icon + FreeSpriteOamMatrix(&gSprites[gTasks[taskId].tSpriteId]); //Destroy item icon + DestroySprite(&gSprites[gTasks[taskId].tSpriteId]); //Destroy item icon + + PlaySE(SE_SELECT); + DebugAction_DestroyExtraWindow(taskId); + } +} + +#undef tItemId +#undef tSpriteId + +//Pokemon +static void ResetMonDataStruct(struct DebugMonData *sDebugMonData) +{ + sDebugMonData->species = 1; + sDebugMonData->level = MIN_LEVEL; + sDebugMonData->isShiny = FALSE; + sDebugMonData->nature = 0; + sDebugMonData->abilityNum = 0; + sDebugMonData->mon_iv_hp = 0; + sDebugMonData->mon_iv_atk = 0; + sDebugMonData->mon_iv_def = 0; + sDebugMonData->mon_iv_speed = 0; + sDebugMonData->mon_iv_satk = 0; + sDebugMonData->mon_iv_sdef = 0; + sDebugMonData->mon_ev_hp = 0; + sDebugMonData->mon_ev_atk = 0; + sDebugMonData->mon_ev_def = 0; + sDebugMonData->mon_ev_speed = 0; + sDebugMonData->mon_ev_satk = 0; + sDebugMonData->mon_ev_sdef = 0; +} + +#define tIsComplex data[5] +#define tSpriteId data[6] +#define tIterator data[7] + +static void DebugAction_Give_PokemonSimple(u8 taskId) +{ + u8 windowId; + + //Mon data struct + sDebugMonData = AllocZeroed(sizeof(struct DebugMonData)); + ResetMonDataStruct(sDebugMonData); + + //Window initialization + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateExtra); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + // Display initial Pokémon + StringCopy(gStringVar2, gText_DigitIndicator[0]); + ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, 3); + StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species)); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + //Set task data + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectId; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = sDebugMonData->species; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tIsComplex = FALSE; + + FreeMonIconPalettes(); + LoadMonIconPalette(gTasks[taskId].tInput); + gTasks[taskId].tSpriteId = CreateMonIcon(gTasks[taskId].tInput, SpriteCB_MonIcon, DEBUG_NUMBER_ICON_X, DEBUG_NUMBER_ICON_Y, 4, 0); + gSprites[gTasks[taskId].tSpriteId].oam.priority = 0; +} + +static void DebugAction_Give_PokemonComplex(u8 taskId) +{ + u8 windowId; + + //Mon data struct + sDebugMonData = AllocZeroed(sizeof(struct DebugMonData)); + ResetMonDataStruct(sDebugMonData); + + //Window initialization + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateExtra); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + // Display initial Pokémon + StringCopy(gStringVar2, gText_DigitIndicator[0]); + ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, 4); + StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species)); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectId; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = 1; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tIsComplex = TRUE; + + FreeMonIconPalettes(); + LoadMonIconPalette(gTasks[taskId].tInput); + gTasks[taskId].tSpriteId = CreateMonIcon(gTasks[taskId].tInput, SpriteCB_MonIcon, DEBUG_NUMBER_ICON_X, DEBUG_NUMBER_ICON_Y, 4, 0); + gSprites[gTasks[taskId].tSpriteId].oam.priority = 0; + gTasks[taskId].tIterator = 0; +} + +static void DebugAction_Give_Pokemon_SelectId(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput >= NUM_SPECIES) + gTasks[taskId].tInput = NUM_SPECIES - 1; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 1) + gTasks[taskId].tInput = 1; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < DEBUG_NUMBER_DIGITS_ITEMS - 1) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringCopy(gStringVar1, GetSpeciesName(gTasks[taskId].tInput)); //CopyItemName(gTasks[taskId].tInput, gStringVar1); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 4); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + DestroyMonIcon(&gSprites[gTasks[taskId].tSpriteId]); + FreeMonIconPalettes(); + LoadMonIconPalette(gTasks[taskId].tInput); + gTasks[taskId].tSpriteId = CreateMonIcon(gTasks[taskId].tInput, SpriteCB_MonIcon, DEBUG_NUMBER_ICON_X, DEBUG_NUMBER_ICON_Y, 4, 0); + gSprites[gTasks[taskId].tSpriteId].oam.priority = 0; + } + + if (JOY_NEW(A_BUTTON)) + { + sDebugMonData->species = gTasks[taskId].tInput; + gTasks[taskId].tInput = 1; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonLevel); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectLevel; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + FreeMonIconPalettes(); + DestroyMonIcon(&gSprites[gTasks[taskId].tSpriteId]); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_SelectLevel(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > MAX_LEVEL) + gTasks[taskId].tInput = MAX_LEVEL; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 1) + gTasks[taskId].tInput = 1; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < 2) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonLevel); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + FreeMonIconPalettes(); + DestroyMonIcon(&gSprites[gTasks[taskId].tSpriteId]); + if (gTasks[taskId].tIsComplex == FALSE) + { + PlaySE(MUS_LEVEL_UP); + ScriptGiveMon(sDebugMonData->species, gTasks[taskId].tInput, ITEM_NONE); + // Set flag for user convenience + FlagSet(FLAG_SYS_POKEMON_GET); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } + else + { + sDebugMonData->level = gTasks[taskId].tInput; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 0); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonShiny); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectShiny; + } + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + FreeMonIconPalettes(); + DestroyMonIcon(&gSprites[gTasks[taskId].tSpriteId]); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId) +{ + static const u8 *txtStr; + + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + gTasks[taskId].tInput ^= JOY_NEW(DPAD_UP | DPAD_DOWN) > 0; + txtStr = (gTasks[taskId].tInput == TRUE) ? sDebugText_True : sDebugText_False; + StringCopyPadded(gStringVar2, txtStr, CHAR_SPACE, 15); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 0); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonShiny); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + sDebugMonData->isShiny = gTasks[taskId].tInput; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopy(gStringVar1, gNaturesInfo[0].name); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonNature); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectNature; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_SelectNature(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > NUM_NATURES-1) + gTasks[taskId].tInput = NUM_NATURES-1; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopy(gStringVar1, gNaturesInfo[gTasks[taskId].tInput].name); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonNature); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + u16 abilityId; + sDebugMonData->nature = gTasks[taskId].tInput; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + abilityId = GetAbilityBySpecies(sDebugMonData->species, 0); + StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectAbility; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) +{ + u16 abilityId; + u8 abilityCount = NUM_ABILITY_SLOTS - 1; //-1 for proper iteration + u8 i = 0; + + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > abilityCount) + gTasks[taskId].tInput = abilityCount; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + + while (GetAbilityBySpecies(sDebugMonData->species, gTasks[taskId].tInput - i) == ABILITY_NONE && gTasks[taskId].tInput - i < NUM_ABILITY_SLOTS) + { + i++; + } + abilityId = GetAbilityBySpecies(sDebugMonData->species, gTasks[taskId].tInput - i); + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + sDebugMonData->abilityNum = gTasks[taskId].tInput - i; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_IV_HP); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectIVs; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > MAX_PER_STAT_IVS) + gTasks[taskId].tInput = MAX_PER_STAT_IVS; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < 2) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + switch (gTasks[taskId].tIterator) + { + case STAT_HP: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_HP); + break; + case STAT_ATK: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_Attack); + break; + case STAT_DEF: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_Defense); + break; + case STAT_SPEED: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_Speed); + break; + case STAT_SPATK: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_SpAttack); + break; + case STAT_SPDEF: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_SpDefense); + break; + } + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + //If A or B button + if (JOY_NEW(A_BUTTON)) + { + switch (gTasks[taskId].tIterator) + { + case STAT_HP: + sDebugMonData->mon_iv_hp = gTasks[taskId].tInput; + break; + case STAT_ATK: + sDebugMonData->mon_iv_atk = gTasks[taskId].tInput; + break; + case STAT_DEF: + sDebugMonData->mon_iv_def = gTasks[taskId].tInput; + break; + case STAT_SPEED: + sDebugMonData->mon_iv_speed = gTasks[taskId].tInput; + break; + case STAT_SPATK: + sDebugMonData->mon_iv_satk = gTasks[taskId].tInput; + break; + case STAT_SPDEF: + sDebugMonData->mon_iv_sdef = gTasks[taskId].tInput; + break; + } + + //Check if all IVs set + if (gTasks[taskId].tIterator != NUM_STATS - 1) + { + gTasks[taskId].tIterator++; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + switch (gTasks[taskId].tIterator) + { + case STAT_HP: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_HP); + break; + case STAT_ATK: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_Attack); + break; + case STAT_DEF: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_Defense); + break; + case STAT_SPEED: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_Speed); + break; + case STAT_SPATK: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_SpAttack); + break; + case STAT_SPDEF: + StringExpandPlaceholders(gStringVar4, sDebugText_IV_SpDefense); + break; + } + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectIVs; + } + else + { + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tIterator = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_EV_HP); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs; + } + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static u32 GetDebugPokemonTotalEV(void) +{ + return (sDebugMonData->mon_ev_hp + + sDebugMonData->mon_ev_atk + + sDebugMonData->mon_ev_def + + sDebugMonData->mon_ev_speed + + sDebugMonData->mon_ev_satk + + sDebugMonData->mon_ev_sdef); +} + +static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId) +{ + u16 totalEV = GetDebugPokemonTotalEV(); + + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > MAX_PER_STAT_EVS) + gTasks[taskId].tInput = MAX_PER_STAT_EVS; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < 3) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + switch (gTasks[taskId].tIterator) + { + case STAT_HP: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_HP); + break; + case STAT_ATK: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_Attack); + break; + case STAT_DEF: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_Defense); + break; + case STAT_SPEED: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_Speed); + break; + case STAT_SPATK: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_SpAttack); + break; + case STAT_SPDEF: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_SpDefense); + break; + } + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + //If A or B button + if (JOY_NEW(A_BUTTON)) + { + switch (gTasks[taskId].tIterator) + { + case STAT_HP: + sDebugMonData->mon_ev_hp = gTasks[taskId].tInput; + break; + case STAT_ATK: + sDebugMonData->mon_ev_atk = gTasks[taskId].tInput; + break; + case STAT_DEF: + sDebugMonData->mon_ev_def = gTasks[taskId].tInput; + break; + case STAT_SPEED: + sDebugMonData->mon_ev_speed = gTasks[taskId].tInput; + break; + case STAT_SPATK: + sDebugMonData->mon_ev_satk = gTasks[taskId].tInput; + break; + case STAT_SPDEF: + sDebugMonData->mon_ev_sdef = gTasks[taskId].tInput; + break; + } + + //Check if all EVs set + if (gTasks[taskId].tIterator != NUM_STATS - 1) + { + gTasks[taskId].tIterator++; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + switch (gTasks[taskId].tIterator) + { + case STAT_HP: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_HP); + break; + case STAT_ATK: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_Attack); + break; + case STAT_DEF: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_Defense); + break; + case STAT_SPEED: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_Speed); + break; + case STAT_SPATK: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_SpAttack); + break; + case STAT_SPDEF: + StringExpandPlaceholders(gStringVar4, sDebugText_EV_SpDefense); + break; + } + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs; + } + else + { + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tIterator = 0; + + if (totalEV > MAX_TOTAL_EVS) + { + sDebugMonData->mon_ev_hp = 0; + sDebugMonData->mon_ev_atk = 0; + sDebugMonData->mon_ev_def = 0; + sDebugMonData->mon_ev_speed = 0; + sDebugMonData->mon_ev_satk = 0; + sDebugMonData->mon_ev_sdef = 0; + + PlaySE(SE_FAILURE); + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_EV_HP); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs; + } + else + { + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_0); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_Move; + } + } + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_Move(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput >= MOVES_COUNT) + gTasks[taskId].tInput = MOVES_COUNT - 1; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < 3) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + switch (gTasks[taskId].tIterator) + { + case 0: + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_0); + break; + case 1: + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_1); + break; + case 2: + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_2); + break; + case 3: + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_3); + break; + } + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + // If MOVE_NONE selected, stop asking for additional moves + if (gTasks[taskId].tInput == MOVE_NONE) + gTasks[taskId].tIterator = 4; + + //Set current value + switch (gTasks[taskId].tIterator) + { + case 0: + sDebugMonData->mon_move_0 = gTasks[taskId].tInput; + break; + case 1: + sDebugMonData->mon_move_1 = gTasks[taskId].tInput; + break; + case 2: + sDebugMonData->mon_move_2 = gTasks[taskId].tInput; + break; + case 3: + sDebugMonData->mon_move_3 = gTasks[taskId].tInput; + break; + } + + //If NOT last move or selected MOVE_NONE ask for next move, else make mon + if (gTasks[taskId].tIterator < MAX_MON_MOVES - 1) + { + gTasks[taskId].tIterator++; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); + switch (gTasks[taskId].tIterator) + { + case 0: + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_0); + break; + case 1: + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_1); + break; + case 2: + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_2); + break; + case 3: + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_3); + break; + } + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_Move; + } + else + { + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + PlaySE(MUS_LEVEL_UP); + gTasks[taskId].func = DebugAction_Give_Pokemon_ComplexCreateMon; + } + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://github.com/ghoulslash/pokeemerald/tree/custom-givemon +{ + u16 nationalDexNum; + int sentToPc; + struct Pokemon mon; + u8 i; + u16 moves[4]; + u8 IVs[6]; + u8 iv_val; + u8 EVs[6]; + u8 ev_val; + u16 species = sDebugMonData->species; + u8 level = sDebugMonData->level; + bool8 isShiny = sDebugMonData->isShiny; + u8 nature = sDebugMonData->nature; + u8 abilityNum = sDebugMonData->abilityNum; + moves[0] = sDebugMonData->mon_move_0; + moves[1] = sDebugMonData->mon_move_1; + moves[2] = sDebugMonData->mon_move_2; + moves[3] = sDebugMonData->mon_move_3; + IVs[0] = sDebugMonData->mon_iv_hp; + IVs[1] = sDebugMonData->mon_iv_atk; + IVs[2] = sDebugMonData->mon_iv_def; + IVs[3] = sDebugMonData->mon_iv_speed; + IVs[4] = sDebugMonData->mon_iv_satk; + IVs[5] = sDebugMonData->mon_iv_sdef; + EVs[0] = sDebugMonData->mon_ev_hp; + EVs[1] = sDebugMonData->mon_ev_atk; + EVs[2] = sDebugMonData->mon_ev_def; + EVs[3] = sDebugMonData->mon_ev_speed; + EVs[4] = sDebugMonData->mon_ev_satk; + EVs[5] = sDebugMonData->mon_ev_sdef; + + //Nature + if (nature == NUM_NATURES || nature == 0xFF) + nature = Random() % NUM_NATURES; + CreateMonWithNature(&mon, species, level, 32, nature); + + //Shininess + SetMonData(&mon, MON_DATA_IS_SHINY, &isShiny); + + //IVs + for (i = 0; i < NUM_STATS; i++) + { + iv_val = IVs[i]; + if (iv_val != 32 && iv_val != 0xFF) + SetMonData(&mon, MON_DATA_HP_IV + i, &iv_val); + } + + //EVs + for (i = 0; i < NUM_STATS; i++) + { + ev_val = EVs[i]; + if (ev_val) + SetMonData(&mon, MON_DATA_HP_EV + i, &ev_val); + } + + //Moves + for (i = 0; i < MAX_MON_MOVES; i++) + { + if (moves[i] == 0 || moves[i] == 0xFF || moves[i] >= MOVES_COUNT) + continue; + + SetMonMoveSlot(&mon, moves[i], i); + } + + //Ability + if (abilityNum == 0xFF || GetAbilityBySpecies(species, abilityNum) == 0) + { + do { + abilityNum = Random() % 3; // includes hidden abilities + } while (GetAbilityBySpecies(species, abilityNum) == 0); + } + + SetMonData(&mon, MON_DATA_ABILITY_NUM, &abilityNum); + + //Update mon stats before giving it to the player + CalculateMonStats(&mon); + + // give player the mon + SetMonData(&mon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName); + SetMonData(&mon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender); + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) == SPECIES_NONE) + break; + } + + if (i >= PARTY_SIZE) + sentToPc = CopyMonToPC(&mon); + else + { + sentToPc = MON_GIVEN_TO_PARTY; + CopyMon(&gPlayerParty[i], &mon, sizeof(mon)); + gPlayerPartyCount = i + 1; + } + + //Pokedex entry + nationalDexNum = SpeciesToNationalDexNum(species); + switch(sentToPc) + { + case MON_GIVEN_TO_PARTY: + case MON_GIVEN_TO_PC: + GetSetPokedexFlag(nationalDexNum, FLAG_SET_SEEN); + GetSetPokedexFlag(nationalDexNum, FLAG_SET_CAUGHT); + break; + case MON_CANT_GIVE: + break; + } + + // Set flag for user convenience + FlagSet(FLAG_SYS_POKEMON_GET); + + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); //return sentToPc; +} + +#undef tIsComplex +#undef tSpriteId +#undef tIterator + +static void DebugAction_Give_MaxMoney(u8 taskId) +{ + SetMoney(&gSaveBlock1Ptr->money, MAX_MONEY); +} + +static void DebugAction_Give_MaxCoins(u8 taskId) +{ + SetCoins(MAX_COINS); +} + +static void DebugAction_Give_MaxBattlePoints(u8 taskId) +{ + // gSaveBlock2Ptr->frontier.battlePoints = MAX_BATTLE_FRONTIER_POINTS; +} + +static void DebugAction_Give_DayCareEgg(u8 taskId) +{ + s32 emptySlot = Daycare_FindEmptySpot(&gSaveBlock1Ptr->daycare); + if (emptySlot == 0) // no daycare mons + Debug_DestroyMenu_Full_Script(taskId, DebugScript_ZeroDaycareMons); + else if (emptySlot == 1) // 1 daycare mon + Debug_DestroyMenu_Full_Script(taskId, DebugScript_OneDaycareMons); + else if (GetDaycareCompatibilityScore(&gSaveBlock1Ptr->daycare) == PARENTS_INCOMPATIBLE) // not compatible parents + Debug_DestroyMenu_Full_Script(taskId, DebugScript_DaycareMonsNotCompatible); + else // 2 pokemon which can have a pokemon baby together + TriggerPendingDaycareEgg(); +} + +// ******************************* +// Actions PCBag + +static void DebugAction_OpenPCBagFillMenu(u8 taskId) +{ + Debug_DestroyMenu(taskId); + Debug_ShowMenu(DebugTask_HandleMenuInput_PCBag_Fill, sDebugMenu_ListTemplate_PCBag_Fill); +} + +static void DebugAction_PCBag_Fill_PCBoxes_Fast(u8 taskId) //Credit: Sierraffinity +{ + int boxId, boxPosition; + u32 personality; + struct BoxPokemon boxMon; + u16 species = SPECIES_BULBASAUR; + u8 speciesName[POKEMON_NAME_LENGTH + 1]; + + personality = Random32(); + + CreateBoxMon(&boxMon, species, 100, USE_RANDOM_IVS, FALSE, personality, OT_ID_PLAYER_ID, 0); + + for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++) + { + for (boxPosition = 0; boxPosition < IN_BOX_COUNT; boxPosition++, species++) + { + if (!GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], MON_DATA_SANITY_HAS_SPECIES)) + { + StringCopy(speciesName, GetSpeciesName(species)); + SetBoxMonData(&boxMon, MON_DATA_NICKNAME, &speciesName); + SetBoxMonData(&boxMon, MON_DATA_SPECIES, &species); + GiveBoxMonInitialMoveset(&boxMon); + gPokemonStoragePtr->boxes[boxId][boxPosition] = boxMon; + } + } + } + + // Set flag for user convenience + FlagSet(FLAG_SYS_POKEMON_GET); + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); +} + +static void DebugAction_PCBag_Fill_PCBoxes_Slow(u8 taskId) +{ + int boxId, boxPosition; + struct BoxPokemon boxMon; + u32 species = SPECIES_BULBASAUR; + bool8 spaceAvailable = FALSE; + + for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++) + { + for (boxPosition = 0; boxPosition < IN_BOX_COUNT; boxPosition++) + { + if (!GetBoxMonData(&gPokemonStoragePtr->boxes[boxId][boxPosition], MON_DATA_SANITY_HAS_SPECIES)) + { + if (!spaceAvailable) + PlayBGM(MUS_MYSTERY_GIFT); + CreateBoxMon(&boxMon, species, 100, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0); + gPokemonStoragePtr->boxes[boxId][boxPosition] = boxMon; + species = (species < NUM_SPECIES - 1) ? species + 1 : 1; + spaceAvailable = TRUE; + } + } + } + + // Set flag for user convenience + FlagSet(FLAG_SYS_POKEMON_GET); + if (spaceAvailable) + PlayBGM(GetCurrentMapMusic()); + + Debug_DestroyMenu_Full_Script(taskId, Debug_BoxFilledMessage); +} + +static void DebugAction_PCBag_Fill_PCItemStorage(u8 taskId) +{ + u16 itemId; + + for (itemId = 1; itemId < ITEMS_COUNT; itemId++) + { + if (!CheckPCHasItem(itemId, MAX_PC_ITEM_CAPACITY)) + AddPCItem(itemId, MAX_PC_ITEM_CAPACITY); + } +} + +static void DebugAction_PCBag_Fill_PocketItems(u8 taskId) +{ + u16 itemId; + + for (itemId = 1; itemId < ITEMS_COUNT; itemId++) + { + if (ItemId_GetPocket(itemId) == POCKET_ITEMS && CheckBagHasSpace(itemId, MAX_BAG_ITEM_CAPACITY)) + AddBagItem(itemId, MAX_BAG_ITEM_CAPACITY); + } +} + +static void DebugAction_PCBag_Fill_PocketPokeBalls(u8 taskId) +{ + u16 itemId; + + for (itemId = FIRST_BALL; itemId < LAST_BALL; itemId++) + { + if (CheckBagHasSpace(itemId, MAX_BAG_ITEM_CAPACITY)) + AddBagItem(itemId, MAX_BAG_ITEM_CAPACITY); + } +} + +static void DebugAction_PCBag_Fill_PocketTMHM(u8 taskId) +{ + u16 itemId; + + for (itemId = ITEM_TM01; itemId <= ITEM_HM08; itemId++) + { + if (CheckBagHasSpace(itemId, 1) && ItemIdToBattleMoveId(itemId) != MOVE_NONE) + AddBagItem(itemId, 1); + } +} + +static void DebugAction_PCBag_Fill_PocketBerries(u8 taskId) +{ + u16 itemId; + + for (itemId = FIRST_BERRY_INDEX; itemId < LAST_BERRY_INDEX; itemId++) + { + if (CheckBagHasSpace(itemId, MAX_BAG_ITEM_CAPACITY)) + AddBagItem(itemId, MAX_BAG_ITEM_CAPACITY); + } +} + +static void DebugAction_PCBag_Fill_PocketKeyItems(u8 taskId) +{ + u16 itemId; + + for (itemId = 1; itemId < ITEMS_COUNT; itemId++) + { + if (ItemId_GetPocket(itemId) == POCKET_KEY_ITEMS && CheckBagHasSpace(itemId, 1)) + AddBagItem(itemId, 1); + } +} + +static void DebugAction_PCBag_AccessPC(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, EventScript_PC); +} + +static void DebugAction_PCBag_ClearBag(u8 taskId) +{ + PlaySE(MUS_LEVEL_UP); + ClearBag(); +} + +static void DebugAction_PCBag_ClearBoxes(u8 taskId) +{ + ResetPokemonStorageSystem(); + Debug_DestroyMenu_Full(taskId); + ScriptContext_Enable(); +} + +// ******************************* +// Actions Sound +static const u8 *const sBGMNames[]; +static const u8 *const sSENames[]; + +#define tCurrentSong data[5] + +static void DebugAction_Sound_SE(u8 taskId) +{ + u8 windowId; + + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateSound); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + // Display initial sound effect + StringCopy(gStringVar2, gText_DigitIndicator[0]); + ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + StringCopyPadded(gStringVar1, sSENames[0], CHAR_SPACE, 35); + StringExpandPlaceholders(gStringVar4, sDebugText_Sound_SFX_ID); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + StopMapMusic(); //Stop map music to better hear sounds + + gTasks[taskId].func = DebugAction_Sound_SE_SelectId; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = 1; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tCurrentSong = gTasks[taskId].tInput; +} + +static void DebugAction_Sound_SE_SelectId(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > END_SE) + gTasks[taskId].tInput = END_SE; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 1) + gTasks[taskId].tInput = 1; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < DEBUG_NUMBER_DIGITS_ITEMS - 1) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringCopyPadded(gStringVar1, sSENames[gTasks[taskId].tInput-1], CHAR_SPACE, 35); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + StringExpandPlaceholders(gStringVar4, sDebugText_Sound_SFX_ID); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + m4aSongNumStop(gTasks[taskId].tCurrentSong); + gTasks[taskId].tCurrentSong = gTasks[taskId].tInput; + m4aSongNumStart(gTasks[taskId].tInput); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + m4aSongNumStop(gTasks[taskId].tCurrentSong); + DebugAction_DestroyExtraWindow(taskId); + } + else if (JOY_NEW(START_BUTTON)) + { + m4aSongNumStop(gTasks[taskId].tCurrentSong); + } +} + +static void DebugAction_Sound_MUS(u8 taskId) +{ + u8 windowId; + + ClearStdWindowAndFrame(gTasks[taskId].tWindowId, TRUE); + RemoveWindow(gTasks[taskId].tWindowId); + + DismissMapNamePopup(); + LoadStdWindowFrameGfx(); + windowId = AddWindow(&sDebugMenuWindowTemplateSound); + DrawStdWindowFrame(windowId, FALSE); + + CopyWindowToVram(windowId, COPYWIN_FULL); + + // Display initial song + StringCopy(gStringVar2, gText_DigitIndicator[0]); + ConvertIntToDecimalStringN(gStringVar3, START_MUS, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + StringCopyPadded(gStringVar1, sBGMNames[0], CHAR_SPACE, 35); + StringExpandPlaceholders(gStringVar4, sDebugText_Sound_Music_ID); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + + StopMapMusic(); //Stop map music to better hear new music + + gTasks[taskId].func = DebugAction_Sound_MUS_SelectId; + gTasks[taskId].tSubWindowId = windowId; + gTasks[taskId].tInput = START_MUS; + gTasks[taskId].tDigit = 0; + gTasks[taskId].tCurrentSong = gTasks[taskId].tInput; +} + +static void DebugAction_Sound_MUS_SelectId(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > END_MUS) + gTasks[taskId].tInput = END_MUS; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < START_MUS) + gTasks[taskId].tInput = START_MUS; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < DEBUG_NUMBER_DIGITS_ITEMS - 1) + gTasks[taskId].tDigit += 1; + } + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + StringCopyPadded(gStringVar1, sBGMNames[gTasks[taskId].tInput-START_MUS], CHAR_SPACE, 35); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + StringExpandPlaceholders(gStringVar4, sDebugText_Sound_Music_ID); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + m4aSongNumStop(gTasks[taskId].tCurrentSong); + gTasks[taskId].tCurrentSong = gTasks[taskId].tInput; + m4aSongNumStart(gTasks[taskId].tInput); + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + // m4aSongNumStop(gTasks[taskId].tCurrentSong); //Uncomment if music should stop after leaving menu + DebugAction_DestroyExtraWindow(taskId); + } + else if (JOY_NEW(START_BUTTON)) + { + m4aSongNumStop(gTasks[taskId].tCurrentSong); + } +} + +#undef tCurrentSong + +#undef tMenuTaskId +#undef tWindowId +#undef tSubWindowId +#undef tInput +#undef tDigit + +#define SOUND_LIST_BGM \ + X(MUS_CAUGHT) \ + +#define SOUND_LIST_SE \ + X(SE_USE_ITEM) \ + +// Create BGM list +#define X(songId) static const u8 sBGMName_##songId[] = _(#songId); +SOUND_LIST_BGM +#undef X + +#define X(songId) sBGMName_##songId, +static const u8 *const sBGMNames[] = +{ +SOUND_LIST_BGM +}; +#undef X + +// Create SE list +#define X(songId) static const u8 sSEName_##songId[] = _(#songId); +SOUND_LIST_SE +#undef X + +#define X(songId) sSEName_##songId, +static const u8 *const sSENames[] = +{ +SOUND_LIST_SE +}; +#undef X + +// ******************************* +// Actions Party/Boxes + +static void DebugAction_Party_MoveReminder(u8 taskId) +{ + // Debug_DestroyMenu_Full_Script(taskId, FallarborTown_MoveRelearnersHouse_EventScript_ChooseMon); +} + +static void DebugAction_Party_HatchAnEgg(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_HatchAnEgg); +} + +static void DebugAction_Party_HealParty(u8 taskId) +{ + PlaySE(SE_USE_ITEM); + HealPlayerParty(); + ScriptContext_Enable(); + Debug_DestroyMenu_Full(taskId); +} + +static void DebugAction_Party_InflictStatus1(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_InflictStatus1); +} + +static void DebugAction_Party_CheckEVs(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_CheckEVs); +} + +static void DebugAction_Party_CheckIVs(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_EventScript_CheckIVs); +} + +static void DebugAction_Party_ClearParty(u8 taskId) +{ + ZeroPlayerPartyMons(); + ScriptContext_Enable(); + Debug_DestroyMenu_Full(taskId); +} + +#endif //DEBUG_OVERWORLD_MENU == TRUE diff --git a/src/event_data.c b/src/event_data.c index 9ec19e230..5f20978b4 100644 --- a/src/event_data.c +++ b/src/event_data.c @@ -230,6 +230,14 @@ u16 VarGet(u16 idx) return *ptr; } +u16 VarGetIfExist(u16 id) +{ + u16 *ptr = GetVarPointer(id); + if (!ptr) + return 65535; + return *ptr; +} + bool8 VarSet(u16 idx, u16 val) { u16 *ptr = GetVarPointer(idx); diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 488bd66d9..565c0f097 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -1,5 +1,6 @@ #include "global.h" #include "gflib.h" +#include "debug.h" #include "event_data.h" #include "event_object_movement.h" #include "field_camera.h" diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index 3310442a8..3e2fc216c 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -3,6 +3,7 @@ #include "bike.h" #include "coord_event_weather.h" #include "daycare.h" +#include "debug.h" #include "event_data.h" #include "event_object_movement.h" #include "event_scripts.h" @@ -295,6 +296,16 @@ int ProcessPlayerFieldInput(struct FieldInput *input) return TRUE; } +#if DEBUG_OVERWORLD_MENU == TRUE && DEBUG_OVERWORLD_IN_MENU == FALSE + if (input->input_field_1_2) + { + PlaySE(SE_WIN_OPEN); + FreezeObjectEvents(); + Debug_ShowMainMenu(); + return TRUE; + } +#endif + return FALSE; } diff --git a/src/field_specials.c b/src/field_specials.c index a711b343d..3d3b9feca 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -2,6 +2,7 @@ #include "gflib.h" #include "quest_log.h" #include "list_menu.h" +#include "debug.h" #include "diploma.h" #include "script.h" #include "field_player_avatar.h" diff --git a/src/list_menu.c b/src/list_menu.c index e343687b8..02fcda3d3 100644 --- a/src/list_menu.c +++ b/src/list_menu.c @@ -247,6 +247,14 @@ void RedrawListMenu(u8 listTaskId) CopyWindowToVram(list->template.windowId, COPYWIN_GFX); } +void ListMenuGetCurrentItemArrayId(u8 listTaskId, u16 *arrayId) +{ + struct ListMenu *list = (void *) gTasks[listTaskId].data; + + if (arrayId != NULL) + *arrayId = list->cursorPos + list->itemsAbove; +} + void ListMenuGetScrollAndRow(u8 listTaskId, u16 *cursorPos, u16 *itemsAbove) { struct ListMenu *list = (struct ListMenu *)gTasks[listTaskId].data; diff --git a/src/main.c b/src/main.c index 4c96317bd..5e376ffb0 100644 --- a/src/main.c +++ b/src/main.c @@ -223,7 +223,7 @@ static void InitMainCallbacks(void) static void CallCallbacks(void) { -#if TESTING // test framework not working with help system +#if TESTING || DEBUG_BATTLE_MENU == TRUE // test framework not working with help system if (!RunSaveFailedScreen()) #else if (!RunSaveFailedScreen() && !RunHelpSystemCallback()) diff --git a/src/menu_helpers.c b/src/menu_helpers.c index afa850af6..d50a2d722 100644 --- a/src/menu_helpers.c +++ b/src/menu_helpers.c @@ -149,13 +149,8 @@ void ResetVramOamAndBgCntRegs(void) CpuFill16(0, (void *) PLTT, PLTT_SIZE); } -void ResetAllBgsCoordinatesAndBgCntRegs(void) +void ResetAllBgsCoordinates(void) { - SetGpuReg(REG_OFFSET_DISPCNT, 0); - SetGpuReg(REG_OFFSET_BG3CNT, 0); - SetGpuReg(REG_OFFSET_BG2CNT, 0); - SetGpuReg(REG_OFFSET_BG1CNT, 0); - SetGpuReg(REG_OFFSET_BG0CNT, 0); ChangeBgX(0, 0, 0); ChangeBgY(0, 0, 0); ChangeBgX(1, 0, 0); @@ -166,6 +161,16 @@ void ResetAllBgsCoordinatesAndBgCntRegs(void) ChangeBgY(3, 0, 0); } +void ResetAllBgsCoordinatesAndBgCntRegs(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG3CNT, 0); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + ResetAllBgsCoordinates(); +} + bool8 AdjustQuantityAccordingToDPadInput(s16 *quantity_p, u16 qmax) { s16 valBefore = (*quantity_p); diff --git a/src/money.c b/src/money.c index 4a9a4f464..f1dc3f6ba 100644 --- a/src/money.c +++ b/src/money.c @@ -2,11 +2,10 @@ #include "gflib.h" #include "event_data.h" #include "menu.h" +#include "money.h" #include "text_window.h" #include "strings.h" -#define MAX_MONEY 999999 - EWRAM_DATA static u8 sMoneyBoxWindowId = 0; u32 GetMoney(u32 *moneyPtr) diff --git a/src/party_menu.c b/src/party_menu.c index 737757dca..0e9f7de43 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -194,7 +194,6 @@ static void LoadPartyMenuWindows(void); static void InitPartyMenuBoxes(u8 layout); static void LoadPartyMenuBoxes(u8 layout); static void LoadPartyMenuPokeballGfx(void); -static void LoadPartyMenuAilmentGfx(void); static bool8 RenderPartyMenuBoxes(void); static void CreateCancelConfirmPokeballSprites(void); static void CreateCancelConfirmWindows(bool8 chooseMultiple); @@ -3040,7 +3039,7 @@ static void CreatePartyMonStatusSprite(struct Pokemon *mon, struct PartyMenuBox { if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE) { - menuBox->statusSpriteId = CreateSprite(&sSpriteTemplate_StatusIcons, menuBox->spriteCoords[4], menuBox->spriteCoords[5], 0); + menuBox->statusSpriteId = CreateSprite(&gSpriteTemplate_StatusIcons, menuBox->spriteCoords[4], menuBox->spriteCoords[5], 0); SetPartyMonAilmentGfx(mon, menuBox); } } @@ -3049,7 +3048,7 @@ static void CreatePartyMonStatusSpriteParameterized(u16 species, u8 status, stru { if (species != SPECIES_NONE) { - menuBox->statusSpriteId = CreateSprite(&sSpriteTemplate_StatusIcons, menuBox->spriteCoords[4], menuBox->spriteCoords[5], 0); + menuBox->statusSpriteId = CreateSprite(&gSpriteTemplate_StatusIcons, menuBox->spriteCoords[4], menuBox->spriteCoords[5], 0); UpdatePartyMonAilmentGfx(status, menuBox); gSprites[menuBox->statusSpriteId].oam.priority = 0; } @@ -3075,7 +3074,7 @@ static void UpdatePartyMonAilmentGfx(u8 status, struct PartyMenuBox *menuBox) } } -static void LoadPartyMenuAilmentGfx(void) +void LoadPartyMenuAilmentGfx(void) { LoadCompressedSpriteSheet(&sSpriteSheet_StatusIcons); LoadCompressedSpritePalette(&sSpritePalette_StatusIcons); diff --git a/src/pokemon.c b/src/pokemon.c index 6c21bd495..2112ddf1f 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5400,12 +5400,17 @@ const u32 *GetMonFrontSpritePal(struct Pokemon *mon) } const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, bool32 isShiny, u32 personality) +{ + return GetMonSpritePalFromSpecies(species, isShiny, IsPersonalityFemale(species, personality)); +} + +const u32 *GetMonSpritePalFromSpecies(u16 species, bool32 isShiny, bool32 isFemale) { species = SanitizeSpeciesId(species); if (isShiny) { - if (gSpeciesInfo[species].shinyPaletteFemale != NULL && IsPersonalityFemale(species, personality)) + if (gSpeciesInfo[species].shinyPaletteFemale != NULL && isFemale) return gSpeciesInfo[species].shinyPaletteFemale; else if (gSpeciesInfo[species].shinyPalette != NULL) return gSpeciesInfo[species].shinyPalette; @@ -5414,7 +5419,7 @@ const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, bool32 isShiny, } else { - if (gSpeciesInfo[species].paletteFemale != NULL && IsPersonalityFemale(species, personality)) + if (gSpeciesInfo[species].paletteFemale != NULL && isFemale) return gSpeciesInfo[species].paletteFemale; else if (gSpeciesInfo[species].palette != NULL) return gSpeciesInfo[species].palette; @@ -6214,6 +6219,18 @@ bool32 IsPersonalityFemale(u16 species, u32 personality) return GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE; } +bool32 SpeciesHasGenderDifferences(u16 species) +{ + if (gSpeciesInfo[species].frontPicFemale != NULL + || gSpeciesInfo[species].paletteFemale != NULL + || gSpeciesInfo[species].backPicFemale != NULL + || gSpeciesInfo[species].shinyPaletteFemale != NULL + || gSpeciesInfo[species].iconSpriteFemale != NULL) + return TRUE; + + return FALSE; +} + bool32 TryFormChange(u32 monId, u32 side, u16 method) { struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; diff --git a/src/pokemon_icon.c b/src/pokemon_icon.c index 2022ab50e..8cff27488 100644 --- a/src/pokemon_icon.c +++ b/src/pokemon_icon.c @@ -274,6 +274,18 @@ void LoadMonIconPalette(u16 species) LoadSpritePalette(&gMonIconPaletteTable[palIndex]); } +void LoadMonIconPalettePersonality(u16 species, u32 personality) +{ + u8 palIndex; + species = SanitizeSpeciesId(species); + if (gSpeciesInfo[species].iconSpriteFemale != NULL && IsPersonalityFemale(species, personality)) + palIndex = gSpeciesInfo[species].iconPalIndexFemale; + else + palIndex = gSpeciesInfo[species].iconPalIndex; + if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF) + LoadSpritePalette(&gMonIconPaletteTable[palIndex]); +} + void FreeMonIconPalettes(void) { u8 i; diff --git a/src/pokemon_sprite_visualizer.c b/src/pokemon_sprite_visualizer.c new file mode 100644 index 000000000..90f6b4f78 --- /dev/null +++ b/src/pokemon_sprite_visualizer.c @@ -0,0 +1,1768 @@ +//Credits: Gamer2020, AsparagusEduardo, TheXaman, ShinyDragonHunter +#include "global.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_gfx_sfx_util.h" +#include "bg.h" +#include "constants/rgb.h" +#include "constants/songs.h" +#include "data.h" +#include "decompress.h" +#include "event_object_movement.h" +#include "field_weather.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "item.h" +#include "item_menu_icons.h" +#include "list_menu.h" +#include "m4a.h" +#include "main.h" +#include "malloc.h" +#include "menu.h" +#include "overworld.h" +#include "palette.h" +#include "palette_util.h" +#include "pokedex.h" +#include "pokemon.h" +#include "pokemon_animation.h" +#include "pokemon_sprite_visualizer.h" +#include "pokemon_icon.h" +#include "reset_rtc_screen.h" +#include "scanline_effect.h" +#include "script.h" +#include "script_pokemon_util.h" +#include "sound.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "text_window.h" +#include "trainer_pokemon_sprites.h" + +#include "constants/items.h" +#include "constants/event_objects.h" + +#if DEBUG_POKEMON_SPRITE_VISUALIZER == TRUE +extern const struct BattleBackground sBattleTerrainTable[]; +extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow; +extern const struct SpriteTemplate gSpriteTemplate_EnemyShadow; +extern const struct SpritePalette sSpritePalettes_HealthBoxHealthBar[2]; +extern const struct UCoords8 sBattlerCoords[][MAX_BATTLERS_COUNT] ; +static const u16 sBgColor[] = {RGB_WHITE}; + +static struct PokemonSpriteVisualizer *GetStructPtr(u8 taskId) +{ + u8 *taskDataPtr = (u8 *)(&gTasks[taskId].data[0]); + + return (struct PokemonSpriteVisualizer*)(T1_READ_PTR(taskDataPtr)); +} + +static const union AnimCmd sAnim_Follower_1[] = +{ + ANIMCMD_FRAME(0, 30), + ANIMCMD_FRAME(1, 30), + ANIMCMD_FRAME(0, 30), + ANIMCMD_FRAME(1, 30), + ANIMCMD_FRAME(0, 10), + ANIMCMD_FRAME(2, 30), + ANIMCMD_FRAME(3, 30), + ANIMCMD_FRAME(2, 30), + ANIMCMD_FRAME(3, 30), + ANIMCMD_FRAME(2, 10), + ANIMCMD_FRAME(4, 30), + ANIMCMD_FRAME(5, 30), + ANIMCMD_FRAME(4, 30), + ANIMCMD_FRAME(5, 30), + ANIMCMD_FRAME(4, 10), + ANIMCMD_FRAME(4, 30, .hFlip = TRUE), + ANIMCMD_FRAME(5, 30, .hFlip = TRUE), + ANIMCMD_FRAME(4, 30, .hFlip = TRUE), + ANIMCMD_FRAME(5, 30, .hFlip = TRUE), + ANIMCMD_FRAME(4, 10, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_Follower[] = +{ + sAnim_GeneralFrame0, + sAnim_Follower_1, +}; + +//BgTemplates +static const struct BgTemplate sBgTemplates[] = +{ + { + .bg = 0, + .charBaseIndex = 0, + .mapBaseIndex = 24, + .screenSize = 2, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, + { + .bg = 1, + .charBaseIndex = 1, + .mapBaseIndex = 28, + .screenSize = 2, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, + { + .bg = 2, + .charBaseIndex = 1, + .mapBaseIndex = 30, + .screenSize = 1, + .paletteMode = 0, + .priority = 1, + .baseTile = 0 + }, + { + .bg = 3, + .charBaseIndex = 2, + .mapBaseIndex = 26, + .screenSize = 1, + .paletteMode = 0, + .priority = 3, + .baseTile = 0 + }, +}; + +//WindowTemplates +static const struct WindowTemplate sPokemonSpriteVisualizerWindowTemplate[] = +{ + [WIN_NAME_NUMBERS] = { + .bg = 0, + .tilemapLeft = 15, + .tilemapTop = 12, + .width = 15, + .height = 2, + .paletteNum = 0xF, + .baseBlock = 1 + }, + [WIN_INSTRUCTIONS] = { + .bg = 0, + .tilemapLeft = 0, + .tilemapTop = 0, + .width = 15, + .height = 4, + .paletteNum = 0xF, + .baseBlock = 1 + 30 + }, + [WIN_BOTTOM_LEFT] = { + .bg = 0, + .tilemapLeft = 1, + .tilemapTop = 14, + .width = 6, + .height = 6, + .paletteNum = 0xF, + .baseBlock = 1 + 30 + 60 + }, + [WIN_BOTTOM_RIGHT] = { + .bg = 0, + .tilemapLeft = 7, + .tilemapTop = 14, + .width = 24, + .height = 6, + .paletteNum = 0xF, + .baseBlock = 1 + 30 + 60 + 36 + }, + [WIN_FOOTPRINT] = + { + .bg = 0, + .tilemapLeft = 27, + .tilemapTop = 14, + .width = 2, + .height = 2, + .paletteNum = 0xF, + .baseBlock = 1 + 30 + 60 + 36 + 144, + }, + DUMMY_WIN_TEMPLATE, +}; + +//Lookup tables +const u8 gBackAnimNames[][23 + 1] = +{ + [BACK_ANIM_NONE] = _("NONE"), + [BACK_ANIM_H_VIBRATE] = _("H VIBRATE"), + [BACK_ANIM_H_SLIDE] = _("H SLIDE"), + [BACK_ANIM_H_SPRING] = _("H SPRING"), + [BACK_ANIM_H_SPRING_REPEATED] = _("H SPRING REPEATED"), + [BACK_ANIM_SHRINK_GROW] = _("SHRINK GROW"), + [BACK_ANIM_GROW] = _("GROW"), + [BACK_ANIM_CIRCLE_COUNTERCLOCKWISE] = _("CIRCLE COUNTERCLOCKWISE"), + [BACK_ANIM_H_SHAKE] = _("H SHAKE"), + [BACK_ANIM_V_SHAKE] = _("V SHAKE"), + [BACK_ANIM_V_SHAKE_H_SLIDE] = _("V SHAKE H SLIDE"), + [BACK_ANIM_V_STRETCH] = _("V STRETCH"), + [BACK_ANIM_H_STRETCH] = _("H STRETCH"), + [BACK_ANIM_GROW_STUTTER] = _("GROW STUTTER"), + [BACK_ANIM_V_SHAKE_LOW] = _("V SHAKE LOW"), + [BACK_ANIM_TRIANGLE_DOWN] = _("TRIANGLE DOWN"), + [BACK_ANIM_CONCAVE_ARC_LARGE] = _("CONCAVE ARC LARGE"), + [BACK_ANIM_CONVEX_DOUBLE_ARC] = _("CONVEX DOUBLE ARC"), + [BACK_ANIM_CONCAVE_ARC_SMALL] = _("CONCAVE ARC SMALL"), + [BACK_ANIM_DIP_RIGHT_SIDE] = _("DIP RIGHT SIDE"), + [BACK_ANIM_SHRINK_GROW_VIBRATE] = _("SHRINK GROW VIBRATE"), + [BACK_ANIM_JOLT_RIGHT] = _("JOLT RIGHT"), + [BACK_ANIM_SHAKE_FLASH_YELLOW] = _("SHAKE FLASH YELLOW"), + [BACK_ANIM_SHAKE_GLOW_RED] = _("SHAKE GLOW RED"), + [BACK_ANIM_SHAKE_GLOW_GREEN] = _("SHAKE GLOW GREEN"), + [BACK_ANIM_SHAKE_GLOW_BLUE] = _("SHAKE GLOW BLUE"), +}; +const u8 gFrontAnimNames[][34] = +{ + [ANIM_V_SQUISH_AND_BOUNCE] = _("V SQUISH AND BOUNCE"), + [ANIM_CIRCULAR_STRETCH_TWICE] = _("CIRCULAR STRETCH TWICE"), + [ANIM_H_VIBRATE] = _("H VIBRATE"), + [ANIM_H_SLIDE] = _("H SLIDE"), + [ANIM_V_SLIDE] = _("V SLIDE"), + [ANIM_BOUNCE_ROTATE_TO_SIDES] = _("BOUNCE ROTATE TO SIDES"), + [ANIM_V_JUMPS_H_JUMPS] = _("V JUMPS H JUMPS"), + [ANIM_ROTATE_TO_SIDES] = _("ROTATE TO SIDES"), + [ANIM_ROTATE_TO_SIDES_TWICE] = _("ROTATE TO SIDES TWICE"), + [ANIM_GROW_VIBRATE] = _("GROW VIBRATE"), + [ANIM_ZIGZAG_FAST] = _("ZIGZAG FAST"), + [ANIM_SWING_CONCAVE] = _("SWING CONCAVE"), + [ANIM_SWING_CONCAVE_FAST] = _("SWING CONCAVE FAST"), + [ANIM_SWING_CONVEX] = _("SWING CONVEX"), + [ANIM_SWING_CONVEX_FAST] = _("SWING CONVEX FAST"), + [ANIM_H_SHAKE] = _("H SHAKE"), + [ANIM_V_SHAKE] = _("V SHAKE"), + [ANIM_CIRCULAR_VIBRATE] = _("CIRCULAR VIBRATE"), + [ANIM_TWIST] = _("TWIST"), + [ANIM_SHRINK_GROW] = _("SHRINK GROW"), + [ANIM_CIRCLE_C_CLOCKWISE] = _("CIRCLE C CLOCKWISE"), + [ANIM_GLOW_BLACK] = _("GLOW BLACK"), + [ANIM_H_STRETCH] = _("H STRETCH"), + [ANIM_V_STRETCH] = _("V STRETCH"), + [ANIM_RISING_WOBBLE] = _("RISING WOBBLE"), + [ANIM_V_SHAKE_TWICE] = _("V SHAKE TWICE"), + [ANIM_TIP_MOVE_FORWARD] = _("TIP MOVE FORWARD"), + [ANIM_H_PIVOT] = _("H PIVOT"), + [ANIM_V_SLIDE_WOBBLE] = _("V SLIDE WOBBLE"), + [ANIM_H_SLIDE_WOBBLE] = _("H SLIDE WOBBLE"), + [ANIM_V_JUMPS_BIG] = _("V JUMPS BIG"), + [ANIM_SPIN_LONG] = _("SPIN LONG"), + [ANIM_GLOW_ORANGE] = _("GLOW ORANGE"), + [ANIM_GLOW_RED] = _("GLOW RED"), + [ANIM_GLOW_BLUE] = _("GLOW BLUE"), + [ANIM_GLOW_YELLOW] = _("GLOW YELLOW"), + [ANIM_GLOW_PURPLE] = _("GLOW PURPLE"), + [ANIM_BACK_AND_LUNGE] = _("BACK AND LUNGE"), + [ANIM_BACK_FLIP] = _("BACK FLIP"), + [ANIM_FLICKER] = _("FLICKER"), + [ANIM_BACK_FLIP_BIG] = _("BACK FLIP BIG"), + [ANIM_FRONT_FLIP] = _("FRONT FLIP"), + [ANIM_TUMBLING_FRONT_FLIP] = _("TUMBLING FRONT FLIP"), + [ANIM_FIGURE_8] = _("FIGURE 8"), + [ANIM_FLASH_YELLOW] = _("FLASH YELLOW"), + [ANIM_SWING_CONCAVE_FAST_SHORT] = _("SWING CONCAVE FAST SHORT"), + [ANIM_SWING_CONVEX_FAST_SHORT] = _("SWING CONVEX FAST SHORT"), + [ANIM_ROTATE_UP_SLAM_DOWN] = _("ROTATE UP SLAM DOWN"), + [ANIM_DEEP_V_SQUISH_AND_BOUNCE] = _("DEEP V SQUISH AND BOUNCE"), + [ANIM_H_JUMPS] = _("H JUMPS"), + [ANIM_H_JUMPS_V_STRETCH] = _("H JUMPS V STRETCH"), + [ANIM_ROTATE_TO_SIDES_FAST] = _("ROTATE TO SIDES FAST"), + [ANIM_ROTATE_UP_TO_SIDES] = _("ROTATE UP TO SIDES"), + [ANIM_FLICKER_INCREASING] = _("FLICKER INCREASING"), + [ANIM_TIP_HOP_FORWARD] = _("TIP HOP FORWARD"), + [ANIM_PIVOT_SHAKE] = _("PIVOT SHAKE"), + [ANIM_TIP_AND_SHAKE] = _("TIP AND SHAKE"), + [ANIM_VIBRATE_TO_CORNERS] = _("VIBRATE TO CORNERS"), + [ANIM_GROW_IN_STAGES] = _("GROW IN STAGES"), + [ANIM_V_SPRING] = _("V SPRING"), + [ANIM_V_REPEATED_SPRING] = _("V REPEATED SPRING"), + [ANIM_SPRING_RISING] = _("SPRING RISING"), + [ANIM_H_SPRING] = _("H SPRING"), + [ANIM_H_REPEATED_SPRING_SLOW] = _("H REPEATED SPRING SLOW"), + [ANIM_H_SLIDE_SHRINK] = _("H SLIDE SHRINK"), + [ANIM_LUNGE_GROW] = _("LUNGE GROW"), + [ANIM_CIRCLE_INTO_BG] = _("CIRCLE INTO BG"), + [ANIM_RAPID_H_HOPS] = _("RAPID H HOPS"), + [ANIM_FOUR_PETAL] = _("FOUR PETAL"), + [ANIM_V_SQUISH_AND_BOUNCE_SLOW] = _("V SQUISH AND BOUNCE SLOW"), + [ANIM_H_SLIDE_SLOW] = _("H SLIDE SLOW"), + [ANIM_V_SLIDE_SLOW] = _("V SLIDE SLOW"), + [ANIM_BOUNCE_ROTATE_TO_SIDES_SMALL] = _("BOUNCE ROTATE TO SIDES SMALL"), + [ANIM_BOUNCE_ROTATE_TO_SIDES_SLOW] = _("BOUNCE ROTATE TO SIDES SLOW"), + [ANIM_BOUNCE_ROTATE_TO_SIDES_SMALL_SLOW] = _("BOUNCE ROTATE TO SIDES SMALL SLOW"), + [ANIM_ZIGZAG_SLOW] = _("ZIGZAG SLOW"), + [ANIM_H_SHAKE_SLOW] = _("H SHAKE SLOW"), + [ANIM_V_SHAKE_SLOW] = _("V SHAKE SLOW"), + [ANIM_TWIST_TWICE] = _("TWIST TWICE"), + [ANIM_CIRCLE_C_CLOCKWISE_SLOW] = _("CIRCLE C CLOCKWISE SLOW"), + [ANIM_V_SHAKE_TWICE_SLOW] = _("V SHAKE TWICE SLOW"), + [ANIM_V_SLIDE_WOBBLE_SMALL] = _("V SLIDE WOBBLE SMALL"), + [ANIM_V_JUMPS_SMALL] = _("V JUMPS SMALL"), + [ANIM_SPIN] = _("SPIN"), + [ANIM_TUMBLING_FRONT_FLIP_TWICE] = _("TUMBLING FRONT FLIP TWICE"), + [ANIM_DEEP_V_SQUISH_AND_BOUNCE_TWICE] = _("DEEP V SQUISH AND BOUNCE TWICE"), + [ANIM_H_JUMPS_V_STRETCH_TWICE] = _("H JUMPS V STRETCH TWICE"), + [ANIM_V_SHAKE_BACK] = _("V SHAKE BACK"), + [ANIM_V_SHAKE_BACK_SLOW] = _("V SHAKE BACK SLOW"), + [ANIM_V_SHAKE_H_SLIDE_SLOW] = _("V SHAKE H SLIDE SLOW"), + [ANIM_V_STRETCH_BOTH_ENDS_SLOW] = _("V STRETCH BOTH ENDS SLOW"), + [ANIM_H_STRETCH_FAR_SLOW] = _("H STRETCH FAR SLOW"), + [ANIM_V_SHAKE_LOW_TWICE] = _("V SHAKE LOW TWICE"), + [ANIM_H_SHAKE_FAST] = _("H SHAKE FAST"), + [ANIM_H_SLIDE_FAST] = _("H SLIDE FAST"), + [ANIM_H_VIBRATE_FAST] = _("H VIBRATE FAST"), + [ANIM_H_VIBRATE_FASTEST] = _("H VIBRATE FASTEST"), + [ANIM_V_SHAKE_BACK_FAST] = _("V SHAKE BACK FAST"), + [ANIM_V_SHAKE_LOW_TWICE_SLOW] = _("V SHAKE LOW TWICE SLOW"), + [ANIM_V_SHAKE_LOW_TWICE_FAST] = _("V SHAKE LOW TWICE FAST"), + [ANIM_CIRCLE_C_CLOCKWISE_LONG] = _("CIRCLE C CLOCKWISE LONG"), + [ANIM_GROW_STUTTER_SLOW] = _("GROW STUTTER SLOW"), + [ANIM_V_SHAKE_H_SLIDE] = _("V SHAKE H SLIDE"), + [ANIM_V_SHAKE_H_SLIDE_FAST] = _("V SHAKE H SLIDE FAST"), + [ANIM_TRIANGLE_DOWN_SLOW] = _("TRIANGLE DOWN SLOW"), + [ANIM_TRIANGLE_DOWN] = _("TRIANGLE DOWN"), + [ANIM_TRIANGLE_DOWN_TWICE] = _("TRIANGLE DOWN TWICE"), + [ANIM_GROW] = _("GROW"), + [ANIM_GROW_TWICE] = _("GROW TWICE"), + [ANIM_H_SPRING_FAST] = _("H SPRING FAST"), + [ANIM_H_SPRING_SLOW] = _("H SPRING SLOW"), + [ANIM_H_REPEATED_SPRING_FAST] = _("H REPEATED SPRING FAST"), + [ANIM_H_REPEATED_SPRING] = _("H REPEATED SPRING"), + [ANIM_SHRINK_GROW_FAST] = _("SHRINK GROW FAST"), + [ANIM_SHRINK_GROW_SLOW] = _("SHRINK GROW SLOW"), + [ANIM_V_STRETCH_BOTH_ENDS] = _("V STRETCH BOTH ENDS"), + [ANIM_V_STRETCH_BOTH_ENDS_TWICE] = _("V STRETCH BOTH ENDS TWICE"), + [ANIM_H_STRETCH_FAR_TWICE] = _("H STRETCH FAR TWICE"), + [ANIM_H_STRETCH_FAR] = _("H STRETCH FAR"), + [ANIM_GROW_STUTTER_TWICE] = _("GROW STUTTER TWICE"), + [ANIM_GROW_STUTTER] = _("GROW STUTTER"), + [ANIM_CONCAVE_ARC_LARGE_SLOW] = _("CONCAVE ARC LARGE SLOW"), + [ANIM_CONCAVE_ARC_LARGE] = _("CONCAVE ARC LARGE"), + [ANIM_CONCAVE_ARC_LARGE_TWICE] = _("CONCAVE ARC LARGE TWICE"), + [ANIM_CONVEX_DOUBLE_ARC_SLOW] = _("CONVEX DOUBLE ARC SLOW"), + [ANIM_CONVEX_DOUBLE_ARC] = _("CONVEX DOUBLE ARC"), + [ANIM_CONVEX_DOUBLE_ARC_TWICE] = _("CONVEX DOUBLE ARC TWICE"), + [ANIM_CONCAVE_ARC_SMALL_SLOW] = _("CONCAVE ARC SMALL SLOW"), + [ANIM_CONCAVE_ARC_SMALL] = _("CONCAVE ARC SMALL"), + [ANIM_CONCAVE_ARC_SMALL_TWICE] = _("CONCAVE ARC SMALL TWICE"), + [ANIM_H_DIP] = _("H DIP"), + [ANIM_H_DIP_FAST] = _("H DIP FAST"), + [ANIM_H_DIP_TWICE] = _("H DIP TWICE"), + [ANIM_SHRINK_GROW_VIBRATE_FAST] = _("SHRINK GROW VIBRATE FAST"), + [ANIM_SHRINK_GROW_VIBRATE] = _("SHRINK GROW VIBRATE"), + [ANIM_SHRINK_GROW_VIBRATE_SLOW] = _("SHRINK GROW VIBRATE SLOW"), + [ANIM_JOLT_RIGHT_FAST] = _("JOLT RIGHT FAST"), + [ANIM_JOLT_RIGHT] = _("JOLT RIGHT"), + [ANIM_JOLT_RIGHT_SLOW] = _("JOLT RIGHT SLOW"), + [ANIM_SHAKE_FLASH_YELLOW_FAST] = _("SHAKE FLASH YELLOW FAST"), + [ANIM_SHAKE_FLASH_YELLOW] = _("SHAKE FLASH YELLOW"), + [ANIM_SHAKE_FLASH_YELLOW_SLOW] = _("SHAKE FLASH YELLOW SLOW"), + [ANIM_SHAKE_GLOW_RED_FAST] = _("SHAKE GLOW RED FAST"), + [ANIM_SHAKE_GLOW_RED] = _("SHAKE GLOW RED"), + [ANIM_SHAKE_GLOW_RED_SLOW] = _("SHAKE GLOW RED SLOW"), + [ANIM_SHAKE_GLOW_GREEN_FAST] = _("SHAKE GLOW GREEN FAST"), + [ANIM_SHAKE_GLOW_GREEN] = _("SHAKE GLOW GREEN"), + [ANIM_SHAKE_GLOW_GREEN_SLOW] = _("SHAKE GLOW GREEN SLOW"), + [ANIM_SHAKE_GLOW_BLUE_FAST] = _("SHAKE GLOW BLUE FAST"), + [ANIM_SHAKE_GLOW_BLUE] = _("SHAKE GLOW BLUE"), + [ANIM_SHAKE_GLOW_BLUE_SLOW] = _("SHAKE GLOW BLUE SLOW"), + [ANIM_SHAKE_GLOW_BLACK_SLOW] = _("SHAKE GLOW BLACK SLOW"), + [ANIM_SHAKE_GLOW_WHITE_SLOW] = _("SHAKE GLOW WHITE SLOW"), + [ANIM_SHAKE_GLOW_PURPLE_SLOW] = _("SHAKE GLOW PURPLE SLOW"), +}; +const u8 gBattleBackgroundNames[][30] = +{ + [MAP_BATTLE_SCENE_NORMAL] = _("NORMAL "), + [MAP_BATTLE_SCENE_GYM] = _("GYM "), + [MAP_BATTLE_SCENE_MAGMA] = _("MAGMA "), + [MAP_BATTLE_SCENE_AQUA] = _("AQUA "), + [MAP_BATTLE_SCENE_SIDNEY] = _("SIDNEY "), + [MAP_BATTLE_SCENE_PHOEBE] = _("PHOEBE "), + [MAP_BATTLE_SCENE_GLACIA] = _("GLACIA "), + [MAP_BATTLE_SCENE_DRAKE] = _("DRAKE "), + [MAP_BATTLE_SCENE_FRONTIER] = _("FRONTIER "), + [MAP_BATTLE_SCENE_LEADER] = _("LEADER "), + [MAP_BATTLE_SCENE_WALLACE] = _("WALLACE "), + [MAP_BATTLE_SCENE_GROUDON] = _("GROUDON "), + [MAP_BATTLE_SCENE_KYOGRE] = _("KYOGRE "), + [MAP_BATTLE_SCENE_RAYQUAZA] = _("RAYQUAZA "), +}; +const u8 gBattleBackgroundTerrainNames[][26] = +{ + [BATTLE_TERRAIN_GRASS] = _("NORMAL - GRASS "), + [BATTLE_TERRAIN_LONG_GRASS] = _("NORMAL - LONG GRASS "), + [BATTLE_TERRAIN_SAND] = _("NORMAL - SAND "), + [BATTLE_TERRAIN_UNDERWATER] = _("NORMAL - UNDERWATER "), + [BATTLE_TERRAIN_WATER] = _("NORMAL - WATER "), + [BATTLE_TERRAIN_POND] = _("NORMAL - POND "), + [BATTLE_TERRAIN_MOUNTAIN] = _("NORMAL - MOUNTAIN "), + [BATTLE_TERRAIN_CAVE] = _("NORMAL - CAVE "), + [BATTLE_TERRAIN_BUILDING] = _("NORMAL - BUILDING "), + [BATTLE_TERRAIN_PLAIN] = _("NORMAL - PLAIN "), +}; +//Function declarations +static void PrintDigitChars(struct PokemonSpriteVisualizer *data); +static void SetUpModifyArrows(struct PokemonSpriteVisualizer *data); +static void UpdateBattlerValue(struct PokemonSpriteVisualizer *data); +static void ValueToCharDigits(u8 *charDigits, u32 newValue, u8 maxDigits); +static bool32 TryMoveDigit(struct PokemonSpriteVisualizerModifyArrows *modArrows, bool32 moveUp); +static void CB2_PokemonSpriteVisualizerRunner(void); +static void ResetBGs_PokemonSpriteVisualizer(u16); +static void HandleInput_PokemonSpriteVisualizer(u8); +static void ReloadPokemonSprites(struct PokemonSpriteVisualizer *data); +static void Exit_PokemonSpriteVisualizer(u8); + +//Text handling functions +static void UNUSED PadString(const u8 *src, u8 *dst) +{ + u32 i; + + for (i = 0; i < 17 && src[i] != EOS; i++) + dst[i] = src[i]; + + for (; i < 17; i++) + dst[i] = CHAR_SPACE; + + dst[i] = EOS; +} + +static void PrintInstructionsOnWindow(struct PokemonSpriteVisualizer *data) +{ + u8 fontId = 0; + u8 x = 2; + u8 textInstructions[] = _("{START_BUTTON} Shiny\n{B_BUTTON} Exit {A_BUTTON} Submenu 1$"); + u8 textInstructionsGender[] = _("{START_BUTTON} Shiny {SELECT_BUTTON} Gender\n{B_BUTTON} Exit {A_BUTTON} Submenu 1$"); + u8 textInstructionsSubmenuOne[] = _("{START_BUTTON} Shiny\n{B_BUTTON} Back {A_BUTTON} Submenu 2$"); + u8 textInstructionsSubmenuOneGender[] = _("{START_BUTTON} Shiny {SELECT_BUTTON} Gender\n{B_BUTTON} Back {A_BUTTON} Submenu 2$"); + u8 textInstructionsSubmenuTwo[] = _("{START_BUTTON} Shiny\n{B_BUTTON} Back$"); + u8 textInstructionsSubmenuTwoGender[] = _("{START_BUTTON} Shiny {SELECT_BUTTON} Gender\n{B_BUTTON} Back$"); + + + u8 textBottom[] = _("BACK:\nFRONT:\nBG:$"); + u8 textBottomForms[] = _("BACK:\nFRONT:\nBG:\nFORMS:$"); + u8 textBottomSubmenuTwo[] = _("B coords:\nF coords:\nF elev:"); + u16 species = data->modifyArrows.currValue; + + u8 textL[] = _("{L_BUTTON}"); + u8 textR[] = _("{R_BUTTON}"); + + //Instruction window + FillWindowPixelBuffer(WIN_INSTRUCTIONS, 0x11); + if (data->currentSubmenu == 0) + { + if (SpeciesHasGenderDifferences(species)) + AddTextPrinterParameterized(WIN_INSTRUCTIONS, fontId, textInstructionsGender, x, 0, 0, NULL); + else + AddTextPrinterParameterized(WIN_INSTRUCTIONS, fontId, textInstructions, x, 0, 0, NULL); + } + else if (data->currentSubmenu == 1) + { + if (SpeciesHasGenderDifferences(species)) + AddTextPrinterParameterized(WIN_INSTRUCTIONS, fontId, textInstructionsSubmenuOneGender, x, 0, 0, NULL); + else + AddTextPrinterParameterized(WIN_INSTRUCTIONS, fontId, textInstructionsSubmenuOne, x, 0, 0, NULL); + } + else if (data->currentSubmenu == 2) + { + if (SpeciesHasGenderDifferences(species)) + AddTextPrinterParameterized(WIN_INSTRUCTIONS, fontId, textInstructionsSubmenuTwoGender, x, 0, 0, NULL); + else + AddTextPrinterParameterized(WIN_INSTRUCTIONS, fontId, textInstructionsSubmenuTwo, x, 0, 0, NULL); + } + CopyWindowToVram(WIN_INSTRUCTIONS, COPYWIN_FULL); + + //Bottom left text + FillWindowPixelBuffer(WIN_BOTTOM_LEFT, PIXEL_FILL(0)); + if (data->currentSubmenu != 2) + { + AddTextPrinterParameterized(WIN_BOTTOM_LEFT, fontId, textL, 30, 0, 0, NULL); + AddTextPrinterParameterized(WIN_BOTTOM_LEFT, fontId, textR, 30, 12, 0, NULL); + if (GetSpeciesFormTable(data->currentmonId) != NULL) + AddTextPrinterParameterized(WIN_BOTTOM_LEFT, fontId, textBottomForms, 0, 0, 0, NULL); + else + AddTextPrinterParameterized(WIN_BOTTOM_LEFT, fontId, textBottom, 0, 0, 0, NULL); + } + else + AddTextPrinterParameterized(WIN_BOTTOM_LEFT, fontId, textBottomSubmenuTwo, 0, 0, 0, NULL); +} + +static void VBlankCB(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void SetStructPtr(u8 taskId, void *ptr) +{ + u32 structPtr = (u32)(ptr); + u8 *taskDataPtr = (u8 *)(&gTasks[taskId].data[0]); + + taskDataPtr[0] = structPtr >> 0; + taskDataPtr[1] = structPtr >> 8; + taskDataPtr[2] = structPtr >> 16; + taskDataPtr[3] = structPtr >> 24; +} + +//Digit and arrow functions +#define VAL_U16 0 +static void PrintDigitChars(struct PokemonSpriteVisualizer *data) +{ + s32 i; + u16 species = data->modifyArrows.currValue; + u8 text[MODIFY_DIGITS_MAX + POKEMON_NAME_LENGTH + 8]; + + for (i = 0; i < data->modifyArrows.maxDigits; i++) + text[i] = data->modifyArrows.charDigits[i]; + + text[i++] = CHAR_SPACE; + text[i++] = CHAR_HYPHEN; + + if (SpeciesHasGenderDifferences(species)) + { + if (data->isFemale) + text[i++] = CHAR_FEMALE; + else + text[i++] = CHAR_MALE; + text[i++] = CHAR_HYPHEN; + } + + text[i++] = CHAR_SPACE; + StringCopy(&text[i], GetSpeciesName(species)); + + FillWindowPixelBuffer(WIN_NAME_NUMBERS, 0x11); + AddTextPrinterParameterized(WIN_NAME_NUMBERS, FONT_NORMAL, text, 6, 0, 0, NULL); +} + +static u32 CharDigitsToValue(u8 *charDigits, u8 maxDigits) +{ + s32 i; + u8 id = 0; + u32 newValue = 0; + u8 valueDigits[MODIFY_DIGITS_MAX]; + + for (i = 0; i < MODIFY_DIGITS_MAX; i++) + valueDigits[i] = charDigits[i] - CHAR_0; + + if (maxDigits >= MODIFY_DIGITS_MAX) + newValue += valueDigits[id++] * 1000; + if (maxDigits >= MODIFY_DIGITS_MAX - 1) + newValue += valueDigits[id++] * 100; + if (maxDigits >= MODIFY_DIGITS_MAX - 2) + newValue += valueDigits[id++] * 10; + if (maxDigits >= MODIFY_DIGITS_MAX - 3) + newValue += valueDigits[id++]; + + return newValue; +} + +static void ValueToCharDigits(u8 *charDigits, u32 newValue, u8 maxDigits) +{ + s32 i; + u8 valueDigits[MODIFY_DIGITS_MAX]; + u8 id = 0; + + if (maxDigits >= MODIFY_DIGITS_MAX) + valueDigits[id++] = newValue / 1000; + if (maxDigits >= MODIFY_DIGITS_MAX - 1) + valueDigits[id++] = (newValue % 1000) / 100; + if (maxDigits >= MODIFY_DIGITS_MAX - 2) + valueDigits[id++] = (newValue % 100) / 10; + if (maxDigits >= MODIFY_DIGITS_MAX - 3) + valueDigits[id++] = newValue % 10; + + for (i = 0; i < MODIFY_DIGITS_MAX; i++) + charDigits[i] = valueDigits[i] + CHAR_0; +} + +static void SetArrowInvisibility(struct PokemonSpriteVisualizer *data) +{ + switch (data->currentSubmenu) + { + case 0: + gSprites[data->modifyArrows.arrowSpriteId[0]].invisible = FALSE; + gSprites[data->modifyArrows.arrowSpriteId[1]].invisible = FALSE; + gSprites[data->optionArrows.arrowSpriteId[0]].invisible = TRUE; + gSprites[data->yPosModifyArrows.arrowSpriteId[0]].invisible = TRUE; + break; + case 1: + gSprites[data->modifyArrows.arrowSpriteId[0]].invisible = TRUE; + gSprites[data->modifyArrows.arrowSpriteId[1]].invisible = TRUE; + gSprites[data->optionArrows.arrowSpriteId[0]].invisible = FALSE; + gSprites[data->yPosModifyArrows.arrowSpriteId[0]].invisible = TRUE; + break; + case 2: + gSprites[data->modifyArrows.arrowSpriteId[0]].invisible = TRUE; + gSprites[data->modifyArrows.arrowSpriteId[1]].invisible = TRUE; + gSprites[data->optionArrows.arrowSpriteId[0]].invisible = TRUE; + gSprites[data->yPosModifyArrows.arrowSpriteId[0]].invisible = FALSE; + break; + } +} + +static void SetUpModifyArrows(struct PokemonSpriteVisualizer *data) +{ + LoadSpritePalette(&gSpritePalette_Arrow); + data->modifyArrows.arrowSpriteId[0] = CreateSprite(&gSpriteTemplate_Arrow, MODIFY_DIGITS_ARROW_X, MODIFY_DIGITS_ARROW1_Y, 0); + data->modifyArrows.arrowSpriteId[1] = CreateSprite(&gSpriteTemplate_Arrow, MODIFY_DIGITS_ARROW_X, MODIFY_DIGITS_ARROW2_Y, 0); + gSprites[data->modifyArrows.arrowSpriteId[1]].animNum = 1; + + data->modifyArrows.minValue = 1; + data->modifyArrows.maxValue = NUM_SPECIES - 1; + data->modifyArrows.maxDigits = 4; + data->modifyArrows.modifiedValPtr = &data->currentmonId; + data->modifyArrows.typeOfVal = VAL_U16; + data->modifyArrows.currValue = data->currentmonId; + + data->modifyArrows.currentDigit = 0; + ValueToCharDigits(data->modifyArrows.charDigits, data->modifyArrows.currValue, data->modifyArrows.maxDigits); +} + +static void SetUpOptionArrows(struct PokemonSpriteVisualizer *data) +{ + LoadSpritePalette(&gSpritePalette_Arrow); + data->optionArrows.arrowSpriteId[0] = CreateSprite(&gSpriteTemplate_Arrow, OPTIONS_ARROW_1_X, OPTIONS_ARROW_Y, 0); + gSprites[data->optionArrows.arrowSpriteId[0]].animNum = 2; + + data->optionArrows.currentDigit = 0; + + gSprites[data->optionArrows.arrowSpriteId[0]].invisible = TRUE; +} + +static void SetUpYPosModifyArrows(struct PokemonSpriteVisualizer *data) +{ + LoadSpritePalette(&gSpritePalette_Arrow); + data->yPosModifyArrows.arrowSpriteId[0] = CreateSprite(&gSpriteTemplate_Arrow, OPTIONS_ARROW_1_X, OPTIONS_ARROW_Y, 0); + gSprites[data->yPosModifyArrows.arrowSpriteId[0]].animNum = 2; + + data->yPosModifyArrows.currentDigit = 0; + + gSprites[data->yPosModifyArrows.arrowSpriteId[0]].invisible = TRUE; +} + +static bool32 TryMoveDigit(struct PokemonSpriteVisualizerModifyArrows *modArrows, bool32 moveUp) +{ + s32 i; + u8 charDigits[MODIFY_DIGITS_MAX]; + u32 newValue; + + for (i = 0; i < MODIFY_DIGITS_MAX; i++) + charDigits[i] = modArrows->charDigits[i]; + + if (moveUp) + { + if (charDigits[modArrows->currentDigit] == CHAR_9) + { + charDigits[modArrows->currentDigit] = CHAR_0; + for (i = modArrows->currentDigit - 1; i >= 0; i--) + { + if (charDigits[i] == CHAR_9) + charDigits[i] = CHAR_0; + else + { + charDigits[i]++; + break; + } + } + } + else + charDigits[modArrows->currentDigit]++; + } + else + { + if (charDigits[modArrows->currentDigit] == CHAR_0) + { + charDigits[modArrows->currentDigit] = CHAR_9; + + for (i = modArrows->currentDigit - 1; i >= 0; i--) + { + if (charDigits[i] == CHAR_0) + charDigits[i] = CHAR_9; + else + { + charDigits[i]--; + break; + } + } + } + + else + charDigits[modArrows->currentDigit]--; + } + + newValue = CharDigitsToValue(charDigits, modArrows->maxDigits); + if (newValue > modArrows->maxValue || newValue < modArrows->minValue) + { + return FALSE; + } + else + { + modArrows->currValue = newValue; + for (i = 0; i < MODIFY_DIGITS_MAX; i++) + modArrows->charDigits[i] = charDigits[i]; + return TRUE; + } +} + +static void UpdateBattlerValue(struct PokemonSpriteVisualizer *data) +{ + switch (data->modifyArrows.typeOfVal) + { + case VAL_U16: + *(u16*)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue; + break; + } +} + +static void BattleLoadOpponentMonSpriteGfxCustom(u16 species, bool8 isFemale, bool8 isShiny, u8 battlerId) +{ + const u32 *lzPaletteData = GetMonSpritePalFromSpecies(species, isShiny, isFemale); + u16 paletteOffset = OBJ_PLTT_ID(battlerId); + + LZDecompressWram(lzPaletteData, gDecompressionBuffer); + LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); + LoadPalette(gDecompressionBuffer, BG_PLTT_ID(8) + BG_PLTT_ID(battlerId), PLTT_SIZE_4BPP); +} + +static void SetConstSpriteValues(struct PokemonSpriteVisualizer *data) +{ + u16 species = data->currentmonId; + data->constSpriteValues.frontPicCoords = gSpeciesInfo[species].frontPicYOffset; + data->constSpriteValues.frontElevation = gSpeciesInfo[species].enemyMonElevation; + data->constSpriteValues.backPicCoords = gSpeciesInfo[species].backPicYOffset; +} + +static void ResetOffsetSpriteValues(struct PokemonSpriteVisualizer *data) +{ + data->offsetsSpriteValues.offset_back_picCoords = 0; + data->offsetsSpriteValues.offset_front_picCoords = 0; + data->offsetsSpriteValues.offset_front_elevation = 0; +} + +static u8 GetBattlerSpriteFinal_YCustom(u16 species, s8 offset_picCoords, s8 offset_elevation) +{ + u16 offset; + u8 y; + species = SanitizeSpeciesId(species); + + //FrontPicCoords + offset = gSpeciesInfo[species].frontPicYOffset + offset_picCoords; + + //Elevation + offset -= gSpeciesInfo[species].enemyMonElevation + offset_elevation; + + //Main position + y = offset + sBattlerCoords[0][1].y; + + if (y > DISPLAY_HEIGHT - MON_PIC_HEIGHT + 8) + y = DISPLAY_HEIGHT - MON_PIC_HEIGHT + 8; + + return y; +} + +static void UpdateShadowSpriteInvisible(struct PokemonSpriteVisualizer *data) +{ + if (data->constSpriteValues.frontElevation + data->offsetsSpriteValues.offset_front_elevation == 0) + gSprites[data->frontShadowSpriteId].invisible = TRUE; + else + gSprites[data->frontShadowSpriteId].invisible = FALSE; +} + +static void SpriteCB_EnemyShadowCustom(struct Sprite *shadowSprite) +{ + u8 frontSpriteId = shadowSprite->data[0]; + struct Sprite *battlerSprite = &gSprites[frontSpriteId]; + + shadowSprite->x = battlerSprite->x; + shadowSprite->x2 = battlerSprite->x2; +} + +static void SpriteCB_Follower(struct Sprite *sprite) +{ + if (sprite->animDelayCounter == 0) + { + sprite->animDelayCounter = 60; + switch (sprite->animNum) + { + default: + case 0: + case 1: + StartSpriteAnim(sprite, GetFaceDirectionAnimNum(DIR_NORTH)); + break; + case 2: + StartSpriteAnim(sprite, GetFaceDirectionAnimNum(DIR_WEST)); + break; + case 3: + StartSpriteAnim(sprite, GetFaceDirectionAnimNum(DIR_EAST)); + break; + case 4: + StartSpriteAnim(sprite, GetFaceDirectionAnimNum(DIR_SOUTH)); + break; + } + } + else + { + sprite->animDelayCounter--; + } +} + +static void LoadAndCreateEnemyShadowSpriteCustom(struct PokemonSpriteVisualizer *data, u16 species) +{ + u8 x, y; + bool8 invisible = FALSE; + species = SanitizeSpeciesId(species); + if (gSpeciesInfo[species].enemyMonElevation == 0) + invisible = TRUE; + LoadCompressedSpriteSheet(&gSpriteSheet_EnemyShadow); + LoadSpritePalette(&sSpritePalettes_HealthBoxHealthBar[0]); + x = sBattlerCoords[0][1].x; + y = sBattlerCoords[0][1].y; + + data->frontShadowSpriteId = CreateSprite(&gSpriteTemplate_EnemyShadow, x, y + 29, 0xC8); + gSprites[data->frontShadowSpriteId].data[0] = data->frontspriteId; + + gSprites[data->frontShadowSpriteId].callback = SpriteCB_EnemyShadowCustom; + gSprites[data->frontShadowSpriteId].oam.priority = 0; + gSprites[data->frontShadowSpriteId].invisible = invisible; +} + +//Battle background functions +static void LoadBattleBg(u8 battleBgType, u8 battleTerrain) +{ + switch (battleBgType) + { + default: + case MAP_BATTLE_SCENE_NORMAL: + LZDecompressVram(sBattleTerrainTable[battleTerrain].tileset, (void*)(BG_CHAR_ADDR(2))); + LZDecompressVram(sBattleTerrainTable[battleTerrain].tilemap, (void*)(BG_SCREEN_ADDR(26))); + LoadCompressedPalette(sBattleTerrainTable[battleTerrain].palette, 0x20, 0x60); + break; + // TODO: debug + // case MAP_BATTLE_SCENE_GYM: + // LZDecompressVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_BuildingGym, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_MAGMA: + // LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_StadiumMagma, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_AQUA: + // LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_StadiumAqua, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_SIDNEY: + // LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_StadiumSidney, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_PHOEBE: + // LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_StadiumPhoebe, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_GLACIA: + // LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_StadiumGlacia, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_DRAKE: + // LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_StadiumDrake, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_FRONTIER: + // LZDecompressVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_Frontier, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_LEADER: + // LZDecompressVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_BuildingLeader, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_WALLACE: + // LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_StadiumWallace, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_GROUDON: + // LZDecompressVram(gBattleTerrainTiles_Cave, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_Groudon, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_KYOGRE: + // LZDecompressVram(gBattleTerrainTiles_Water, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Water, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_Kyogre, 0x20, 0x60); + // break; + // case MAP_BATTLE_SCENE_RAYQUAZA: + // LZDecompressVram(gBattleTerrainTiles_Rayquaza, (void*)(BG_CHAR_ADDR(2))); + // LZDecompressVram(gBattleTerrainTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(26))); + // LoadCompressedPalette(gBattleTerrainPalette_Rayquaza, 0x20, 0x60); + // break; + } +} +static void PrintBattleBgName(u8 taskId) +{ + struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); + u8 fontId = 0; + u8 text[30+1]; + + if (data->battleBgType == 0) + StringCopy(text, gBattleBackgroundTerrainNames[data->battleTerrain]); + else + StringCopy(text, gBattleBackgroundNames[data->battleBgType]); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, 0, 24, 0, NULL); +} +static void UpdateBattleBg(u8 taskId, bool8 increment) +{ + struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); + + if (data->battleBgType == MAP_BATTLE_SCENE_NORMAL) + { + if (increment) + { + if (data->battleTerrain == BATTLE_TERRAIN_PLAIN) + data->battleBgType += 1; + else + data->battleTerrain += 1; + } + else + { + if (data->battleTerrain == BATTLE_TERRAIN_GRASS) + data->battleBgType = MAP_BATTLE_SCENE_RAYQUAZA; + else + data->battleTerrain -= 1; + } + } + else if (data->battleBgType == MAP_BATTLE_SCENE_GYM) + { + if (increment) + data->battleBgType += 1; + else + { + data->battleBgType = MAP_BATTLE_SCENE_NORMAL; + data->battleTerrain = BATTLE_TERRAIN_PLAIN; + } + } + else if (data->battleBgType == MAP_BATTLE_SCENE_RAYQUAZA) + { + if (increment) + { + data->battleBgType = MAP_BATTLE_SCENE_NORMAL; + data->battleTerrain = BATTLE_TERRAIN_GRASS; + } + else + data->battleBgType -= 1; + } + else + { + if (increment) + data->battleBgType += 1; + else + data->battleBgType -= 1; + } + + PrintBattleBgName(taskId); + + LoadBattleBg(data->battleBgType, data->battleTerrain); +} + +// ******************************* +// Main functions +static void UpdateMonAnimNames(u8 taskId) +{ + struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); + u8 frontAnim = data->animIdFront; + u8 backAnim = data->animIdBack; + u8 text[34]; + u8 fontId = 0; + u8 textNum[4]; + + FillWindowPixelBuffer(WIN_BOTTOM_RIGHT, PIXEL_FILL(0)); + + //Back + StringCopy(text, gBackAnimNames[backAnim]); + ConvertIntToDecimalStringN(textNum, backAnim, STR_CONV_MODE_LEADING_ZEROS, 3); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, textNum, 0, 0, 0, NULL); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, 18, 0, 0, NULL); + //Front + StringCopy(text, gFrontAnimNames[frontAnim]); + ConvertIntToDecimalStringN(textNum, frontAnim, STR_CONV_MODE_LEADING_ZEROS, 3); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, textNum, 0, 12, 0, NULL); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, 18, 12, 0, NULL); + + PrintBattleBgName(taskId); +} + +static void UpdateYPosOffsetText(struct PokemonSpriteVisualizer *data) +{ + u8 text[34]; + u8 fontId = 0; + u8 textConst[] = _("const val:"); + u8 textNew[] = _("new val:"); + u8 x_const_val = 50; + u8 x_new_text = 70; + u8 x_new_val = 110; + u8 y = 0; + + u8 backPicCoords = data->constSpriteValues.backPicCoords; + u8 frontPicCoords = data->constSpriteValues.frontPicCoords; + u8 frontElevation = data->constSpriteValues.frontElevation; + + s8 offset_back_picCoords = data->offsetsSpriteValues.offset_back_picCoords; + s8 offset_front_picCoords = data->offsetsSpriteValues.offset_front_picCoords; + s8 offset_front_elevation = data->offsetsSpriteValues.offset_front_elevation; + + u8 newBackPicCoords = backPicCoords + offset_back_picCoords; + u8 newFrontPicCoords = frontPicCoords + offset_front_picCoords; + u8 newFrontElevation = frontElevation + offset_front_elevation; + + FillWindowPixelBuffer(WIN_BOTTOM_RIGHT, PIXEL_FILL(0)); + + //Back + y = 0; + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, textConst, 0, y, 0, NULL); + ConvertIntToDecimalStringN(text, backPicCoords , STR_CONV_MODE_LEFT_ALIGN, 2); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, x_const_val, y, 0, NULL); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, textNew, x_new_text, y, 0, NULL); + ConvertIntToDecimalStringN(text, newBackPicCoords , STR_CONV_MODE_LEFT_ALIGN, 2); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, x_new_val, y, 0, NULL); + //Front picCoords + y = 12; + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, textConst, 0, y, 0, NULL); + ConvertIntToDecimalStringN(text, frontPicCoords , STR_CONV_MODE_LEFT_ALIGN, 2); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, x_const_val, y, 0, NULL); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, textNew, x_new_text, y, 0, NULL); + ConvertIntToDecimalStringN(text, newFrontPicCoords , STR_CONV_MODE_LEFT_ALIGN, 2); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, x_new_val, y, 0, NULL); + //Front elevation + y = 24; + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, textConst, 0, y, 0, NULL); + ConvertIntToDecimalStringN(text, frontElevation , STR_CONV_MODE_LEFT_ALIGN, 2); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, x_const_val, y, 0, NULL); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, textNew, x_new_text, y, 0, NULL); + ConvertIntToDecimalStringN(text, newFrontElevation , STR_CONV_MODE_LEFT_ALIGN, 2); + AddTextPrinterParameterized(WIN_BOTTOM_RIGHT, fontId, text, x_new_val, y, 0, NULL); +} + +static void ResetPokemonSpriteVisualizerWindows(void) +{ + u8 i; + + FreeAllWindowBuffers(); + InitWindows(sPokemonSpriteVisualizerWindowTemplate); + + for (i = 0; i < WIN_END + 1; i++) + { + FillWindowPixelBuffer(i, PIXEL_FILL(0)); + PutWindowTilemap(i); + CopyWindowToVram(i, COPYWIN_FULL); + } +} + +#define MALE_PERSONALITY 0xFE +#define FEMALE_PERSONALITY 0X0 + +void CB2_Pokemon_Sprite_Visualizer(void) +{ + u8 taskId; + const u32 *palette; + struct PokemonSpriteVisualizer *data; + u16 species; + s16 offset_y; + u8 front_x = sBattlerCoords[0][1].x; + u8 front_y; + + switch (gMain.state) + { + case 0: + default: + SetVBlankCallback(NULL); + FreeMonSpritesGfx(); + ResetBGs_PokemonSpriteVisualizer(0); + DmaFillLarge16(3, 0, (u8 *)VRAM, VRAM_SIZE, 0x1000) + DmaClear32(3, OAM, OAM_SIZE); + DmaClear16(3, PLTT, PLTT_SIZE); + gMain.state = 1; + break; + case 1: + ScanlineEffect_Stop(); + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + FreeAllSpritePalettes(); + gReservedSpritePaletteCount = 8; + ResetAllPicSprites(); + BlendPalettes(PALETTES_ALL, 16, RGB_BLACK); + LoadPalette(GetTextWindowPalette(0), 15*16, 0x40); + + FillBgTilemapBufferRect(0, 0, 0, 0, 32, 20, 15); + InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); + LoadBattleBg(0, BATTLE_TERRAIN_GRASS); + + gMain.state++; + break; + case 2: + ResetPokemonSpriteVisualizerWindows(); + gMain.state++; + break; + case 3: + AllocateMonSpritesGfx(); + + LoadPalette(sBgColor, 0, 2); + LoadMonIconPalette(SPECIES_BULBASAUR); + + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); + ShowBg(0); + ShowBg(1); + ShowBg(2); + ShowBg(3); + + //input task handler + taskId = CreateTask(HandleInput_PokemonSpriteVisualizer, 0); + + data = AllocZeroed(sizeof(struct PokemonSpriteVisualizer)); + SetStructPtr(taskId, data); + + data->currentmonId = SPECIES_BULBASAUR; + species = data->currentmonId; + + //Print instructions + PrintInstructionsOnWindow(data); + + //Palettes + palette = GetMonSpritePalFromSpecies(species, data->isShiny, data->isFemale); + LoadCompressedSpritePaletteWithTag(palette, species); + //Front + HandleLoadSpecialPokePic(TRUE, gMonSpritesGfxPtr->sprites[1], species, (data->isFemale ? FEMALE_PERSONALITY : MALE_PERSONALITY)); + data->isShiny = FALSE; + data->isFemale = FALSE; + BattleLoadOpponentMonSpriteGfxCustom(species, data->isFemale, data->isShiny, 1); + SetMultiuseSpriteTemplateToPokemon(species, 1); + gMultiuseSpriteTemplate.paletteTag = species; + front_y = GetBattlerSpriteFinal_YCustom(species, 0, 0); + data->frontspriteId = CreateSprite(&gMultiuseSpriteTemplate, front_x, front_y, 0); + gSprites[data->frontspriteId].oam.paletteNum = 1; + gSprites[data->frontspriteId].callback = SpriteCallbackDummy; + gSprites[data->frontspriteId].oam.priority = 0; + //Front Shadow + LoadAndCreateEnemyShadowSpriteCustom(data, species); + + //Back + HandleLoadSpecialPokePic(FALSE, gMonSpritesGfxPtr->sprites[2], species, (data->isFemale ? FEMALE_PERSONALITY : MALE_PERSONALITY)); + BattleLoadOpponentMonSpriteGfxCustom(species, data->isFemale, data->isShiny, 4); + SetMultiuseSpriteTemplateToPokemon(species, 2); + offset_y = gSpeciesInfo[species].backPicYOffset; + data->backspriteId = CreateSprite(&gMultiuseSpriteTemplate, VISUALIZER_MON_BACK_X, VISUALIZER_MON_BACK_Y + offset_y, 0); + gSprites[data->backspriteId].oam.paletteNum = 4; + gSprites[data->backspriteId].callback = SpriteCallbackDummy; + gSprites[data->backspriteId].oam.priority = 0; + + //Icon Sprite + data->iconspriteId = CreateMonIcon(species, SpriteCB_MonIcon, VISUALIZER_ICON_X, VISUALIZER_ICON_Y, 4, (data->isFemale ? FEMALE_PERSONALITY : MALE_PERSONALITY)); + gSprites[data->iconspriteId].oam.priority = 0; + + //Follower Sprite + // data->followerspriteId = CreateObjectGraphicsSprite(OBJ_EVENT_GFX_MON_BASE + species, SpriteCB_Follower, VISUALIZER_FOLLOWER_X, VISUALIZER_FOLLOWER_Y, 0); + // gSprites[data->followerspriteId].oam.priority = 0; + // gSprites[data->followerspriteId].anims = sAnims_Follower; + + //Modify Arrows + SetUpModifyArrows(data); + PrintDigitChars(data); + + //Option Arrow + SetUpOptionArrows(data); + + //Modify Y Pos Arrow + SetUpYPosModifyArrows(data); + + //Anim names + // data->animIdBack = GetSpeciesBackAnimSet(species) + 1; + // data->animIdFront = gSpeciesInfo[data->currentmonId].frontAnimId; + UpdateMonAnimNames(taskId); + + //BattleNg Name + PrintBattleBgName(taskId); + + //Footprint + // DrawFootprint(WIN_FOOTPRINT, species); + // CopyWindowToVram(WIN_FOOTPRINT, COPYWIN_GFX); + + gMain.state++; + break; + case 4: + EnableInterrupts(1); + SetVBlankCallback(VBlankCB); + SetMainCallback2(CB2_PokemonSpriteVisualizerRunner); + m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x80); + break; + } +} + +static void CB2_PokemonSpriteVisualizerRunner(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void ResetBGs_PokemonSpriteVisualizer(u16 a) +{ + if (!(a & DISPCNT_BG0_ON)) + { + ClearGpuRegBits(0, DISPCNT_BG0_ON); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + } + if (!(a & DISPCNT_BG1_ON)) + { + ClearGpuRegBits(0, DISPCNT_BG1_ON); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + } + if (!(a & DISPCNT_BG2_ON)) + { + ClearGpuRegBits(0, DISPCNT_BG2_ON); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + } + if (!(a & DISPCNT_BG3_ON)) + { + ClearGpuRegBits(0, DISPCNT_BG3_ON); + SetGpuReg(REG_OFFSET_BG3CNT, 0); + SetGpuReg(REG_OFFSET_BG3HOFS, 0); + SetGpuReg(REG_OFFSET_BG3VOFS, 0); + } + if (!(a & DISPCNT_OBJ_ON)) + { + ClearGpuRegBits(0, DISPCNT_OBJ_ON); + ResetSpriteData(); + FreeAllSpritePalettes(); + gReservedSpritePaletteCount = 8; + } +} + +static void ApplyOffsetSpriteValues(struct PokemonSpriteVisualizer *data) +{ + u16 species = data->currentmonId; + //Back + gSprites[data->backspriteId].y = VISUALIZER_MON_BACK_Y + gSpeciesInfo[species].backPicYOffset + data->offsetsSpriteValues.offset_back_picCoords; + //Front + gSprites[data->frontspriteId].y = GetBattlerSpriteFinal_YCustom(species, data->offsetsSpriteValues.offset_front_picCoords, data->offsetsSpriteValues.offset_front_elevation); + + if (data->currentSubmenu == 2) + UpdateShadowSpriteInvisible(data); +} + +static void UpdateSubmenuOneOptionValue(u8 taskId, bool8 increment) +{ + struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); + u8 option = data->submenuYpos[1]; + + switch (option) + { + case 0: + if (increment) + { + if (data->animIdBack >= BACK_ANIM_SHAKE_GLOW_BLUE) + data->animIdBack = 1; + else + data->animIdBack += 1; + } + else + { + if (data->animIdBack <= 1) + data->animIdBack = BACK_ANIM_SHAKE_GLOW_BLUE; + else + data->animIdBack -= 1; + } + UpdateMonAnimNames(taskId); + break; + case 1: + if (increment) + { + if (data->animIdFront >= ANIM_SHAKE_GLOW_PURPLE_SLOW) + data->animIdFront = 0; + else + data->animIdFront += 1; + } + else + { + if (data->animIdFront <= 0) + data->animIdFront = ANIM_SHAKE_GLOW_PURPLE_SLOW; + else + data->animIdFront -= 1; + } + UpdateMonAnimNames(taskId); + break; + case 2: + UpdateBattleBg(taskId, increment); + break; + case 3: + if (GetSpeciesFormTable(data->currentmonId) != NULL) + { + struct PokemonSpriteVisualizerModifyArrows *modArrows = &data->modifyArrows; + u8 formId = GetFormIdFromFormSpeciesId(data->currentmonId); + const u16 *formTable = GetSpeciesFormTable(data->currentmonId); + if (increment) + { + if (formTable[formId + 1] != FORM_SPECIES_END) + modArrows->currValue = GetFormSpeciesId(data->currentmonId, formId + 1); + else + modArrows->currValue = formTable[0]; + } + else + { + if (formTable[formId] == formTable[0]) + { + u8 lastForm; + for (lastForm = 0; formTable[lastForm] != FORM_SPECIES_END; lastForm++) + { + if (formTable[lastForm + 1] == FORM_SPECIES_END) + break; + } + modArrows->currValue = formTable[lastForm]; + } + else + modArrows->currValue = GetFormSpeciesId(data->currentmonId, formId - 1); + } + // data->animIdBack = GetSpeciesBackAnimSet(modArrows->currValue) + 1; + // data->animIdFront = gSpeciesInfo[modArrows->currValue].frontAnimId; + UpdateMonAnimNames(taskId); + ResetOffsetSpriteValues(data); + + UpdateBattlerValue(data); + ReloadPokemonSprites(data); + VBlankIntrWait(); + PlaySE(SE_DEX_SCROLL); + } + break; + default: + break; + } +} + +static void UpdateSubmenuTwoOptionValue(u8 taskId, bool8 increment) +{ + struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); + u16 species = data->currentmonId; + u8 option = data->submenuYpos[2]; + s8 offset; + u8 y; + + switch (option) + { + case 0: //Back picCoords + offset = data->offsetsSpriteValues.offset_back_picCoords; + if (increment) + { + if (offset == MAX_Y_OFFSET) + offset = -data->constSpriteValues.backPicCoords; + else + offset += 1; + } + else + { + if (offset == -data->constSpriteValues.backPicCoords) + offset = MAX_Y_OFFSET; + else + offset -= 1; + } + data->offsetsSpriteValues.offset_back_picCoords = offset; + gSprites[data->backspriteId].y = VISUALIZER_MON_BACK_Y + gSpeciesInfo[species].backPicYOffset + offset; + break; + case 1: //Front picCoords + offset = data->offsetsSpriteValues.offset_front_picCoords; + if (increment) + { + if (offset == MAX_Y_OFFSET) + offset = -data->constSpriteValues.frontPicCoords; + else + offset += 1; + } + else + { + if (offset == -data->constSpriteValues.frontPicCoords) + offset = MAX_Y_OFFSET; + else + offset -= 1; + } + data->offsetsSpriteValues.offset_front_picCoords = offset; + y = GetBattlerSpriteFinal_YCustom(species, offset, data->offsetsSpriteValues.offset_front_elevation); + gSprites[data->frontspriteId].y = y; + break; + case 2: //Front elevation + offset = data->offsetsSpriteValues.offset_front_elevation; + if (increment) + { + if (offset == MAX_Y_OFFSET) + offset = -data->constSpriteValues.frontElevation; + else + offset += 1; + } + else + { + if (offset == -data->constSpriteValues.frontElevation) + offset = MAX_Y_OFFSET; + else + offset -= 1; + } + data->offsetsSpriteValues.offset_front_elevation = offset; + y = GetBattlerSpriteFinal_YCustom(species, data->offsetsSpriteValues.offset_front_picCoords, offset); + gSprites[data->frontspriteId].y = y; + UpdateShadowSpriteInvisible(data); + break; + } + + UpdateYPosOffsetText(data); +} + +#define READ_PTR_FROM_TASK(taskId, dataId) \ + (void *)( \ + ((u16)(gTasks[taskId].data[dataId]) | \ + ((u16)(gTasks[taskId].data[dataId + 1]) << 16))) + +#define STORE_PTR_IN_TASK(ptr, taskId, dataId) \ +{ \ + gTasks[taskId].data[dataId] = (u32)(ptr); \ + gTasks[taskId].data[dataId + 1] = (u32)(ptr) >> 16; \ +} + +#define sAnimId data[2] +#define sAnimDelay data[3] + +// static void Task_AnimateAfterDelay(u8 taskId) +// { +// if (--gTasks[taskId].sAnimDelay == 0) +// { +// LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].sAnimId); +// DestroyTask(taskId); +// } +// } + +static void HandleInput_PokemonSpriteVisualizer(u8 taskId) +{ + struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); + struct Sprite *Frontsprite = &gSprites[data->frontspriteId]; + struct Sprite *Backsprite = &gSprites[data->backspriteId]; + + if (JOY_NEW(L_BUTTON) && (Backsprite->callback == SpriteCallbackDummy)) + { + PlayCryInternal(data->currentmonId, 0, 120, 10, 0); + // LaunchAnimationTaskForBackSprite(Backsprite, data->animIdBack-1); + } + if (JOY_NEW(R_BUTTON) && (Frontsprite->callback == SpriteCallbackDummy)) + { + PlayCryInternal(data->currentmonId, 0, 120, 10, 0); + // if (HasTwoFramesAnimation(data->currentmonId)) + // StartSpriteAnim(Frontsprite, 1); + + // if (gSpeciesInfo[data->currentmonId].frontAnimDelay != 0) + // { + // // Animation has delay, start delay task + // u8 taskId = CreateTask(Task_AnimateAfterDelay, 0); + // STORE_PTR_IN_TASK(Frontsprite, taskId, 0); + // gTasks[taskId].sAnimId = data->animIdFront; + // gTasks[taskId].sAnimDelay = gSpeciesInfo[data->currentmonId].frontAnimDelay; + // } + // else + // { + // // No delay, start animation + // LaunchAnimationTaskForFrontSprite(Frontsprite, data->animIdFront); + // } + } + + if (JOY_NEW(START_BUTTON)) + { + data->isShiny = !data->isShiny; + + if(data->isShiny) + PlaySE(SE_SHINY); + + ReloadPokemonSprites(data); + ApplyOffsetSpriteValues(data); + } + if (JOY_NEW(SELECT_BUTTON) && SpeciesHasGenderDifferences(data->currentmonId)) + { + data->isFemale = !data->isFemale; + PrintDigitChars(data); + UpdateBattlerValue(data); + ReloadPokemonSprites(data); + VBlankIntrWait(); + PlaySE(SE_DEX_SCROLL); + } + + if (data->currentSubmenu == 0) + { + if (JOY_NEW(A_BUTTON)) + { + data->currentSubmenu = 1; + SetArrowInvisibility(data); + PrintInstructionsOnWindow(data); + } + else if (JOY_NEW(B_BUTTON)) + { + BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK); + gTasks[taskId].func = Exit_PokemonSpriteVisualizer; + PlaySE(SE_PC_OFF); + } + else if (JOY_NEW(DPAD_DOWN)) + { + if (TryMoveDigit(&data->modifyArrows, FALSE)) + { + data->isFemale = FALSE; + PrintDigitChars(data); + UpdateBattlerValue(data); + ReloadPokemonSprites(data); + // data->animIdBack = GetSpeciesBackAnimSet(data->currentmonId) + 1; + // data->animIdFront = gSpeciesInfo[data->currentmonId].frontAnimId; + UpdateMonAnimNames(taskId); + ResetOffsetSpriteValues(data); + } + PlaySE(SE_DEX_SCROLL); + VBlankIntrWait(); + } + else if (JOY_NEW(DPAD_UP)) + { + if (TryMoveDigit(&data->modifyArrows, TRUE)) + { + data->isFemale = FALSE; + PrintDigitChars(data); + UpdateBattlerValue(data); + ReloadPokemonSprites(data); + // data->animIdBack = GetSpeciesBackAnimSet(data->currentmonId) + 1; + // data->animIdFront = gSpeciesInfo[data->currentmonId].frontAnimId; + UpdateMonAnimNames(taskId); + ResetOffsetSpriteValues(data); + } + + PlaySE(SE_DEX_SCROLL); + } + else if (JOY_NEW(DPAD_LEFT)) + { + if (data->modifyArrows.currentDigit != 0) + { + data->modifyArrows.currentDigit--; + gSprites[data->modifyArrows.arrowSpriteId[0]].x2 -= 6; + gSprites[data->modifyArrows.arrowSpriteId[1]].x2 -= 6; + } + } + else if (JOY_NEW(DPAD_RIGHT)) + { + if (data->modifyArrows.currentDigit != (data->modifyArrows.maxDigits - 1)) + { + data->modifyArrows.currentDigit++; + gSprites[data->modifyArrows.arrowSpriteId[0]].x2 += 6; + gSprites[data->modifyArrows.arrowSpriteId[1]].x2 += 6; + } + } + + } + else if (data->currentSubmenu == 1) //Submenu 1 + { + if (JOY_NEW(A_BUTTON)) + { + data->currentSubmenu = 2; + PrintInstructionsOnWindow(data); + SetArrowInvisibility(data); + SetConstSpriteValues(data); + UpdateYPosOffsetText(data); + } + else if (JOY_NEW(B_BUTTON)) + { + data->currentSubmenu = 0; + if (data->submenuYpos[1] == 3) + { + data->submenuYpos[1] = 2; + data->optionArrows.currentDigit = data->submenuYpos[1]; + gSprites[data->optionArrows.arrowSpriteId[0]].y = OPTIONS_ARROW_Y + data->optionArrows.currentDigit * 12; + } + SetArrowInvisibility(data); + PrintInstructionsOnWindow(data); + } + else if (JOY_NEW(DPAD_DOWN)) + { + data->submenuYpos[1] += 1; + if (data->submenuYpos[1] >= 3) + { + if ((GetSpeciesFormTable(data->currentmonId) == NULL) || (data->submenuYpos[1] >= 4)) + data->submenuYpos[1] = 0; + } + data->optionArrows.currentDigit = data->submenuYpos[1]; + gSprites[data->optionArrows.arrowSpriteId[0]].y = OPTIONS_ARROW_Y + data->optionArrows.currentDigit * 12; + } + else if (JOY_NEW(DPAD_UP)) + { + if (data->submenuYpos[1] == 0) + { + if (GetSpeciesFormTable(data->currentmonId) != NULL) + data->submenuYpos[1] = 3; + else + data->submenuYpos[1] = 2; + } + else + data->submenuYpos[1] -= 1; + + data->optionArrows.currentDigit = data->submenuYpos[1]; + gSprites[data->optionArrows.arrowSpriteId[0]].y = OPTIONS_ARROW_Y + data->optionArrows.currentDigit * 12; + } + else if (JOY_NEW(DPAD_LEFT)) + { + UpdateSubmenuOneOptionValue(taskId, FALSE); + } + else if (JOY_NEW(DPAD_RIGHT)) + { + UpdateSubmenuOneOptionValue(taskId, TRUE); + } + } + else if (data->currentSubmenu == 2) //Submenu 2 + { + if (JOY_NEW(B_BUTTON)) + { + data->currentSubmenu = 1; + + SetArrowInvisibility(data); + PrintInstructionsOnWindow(data); + UpdateMonAnimNames(taskId); + } + else if (JOY_NEW(DPAD_DOWN)) + { + data->submenuYpos[2] += 1; + if (data->submenuYpos[2] >= 3) + data->submenuYpos[2] = 0; + + data->yPosModifyArrows.currentDigit = data->submenuYpos[2]; + gSprites[data->yPosModifyArrows.arrowSpriteId[0]].y = OPTIONS_ARROW_Y + data->yPosModifyArrows.currentDigit * 12; + } + else if (JOY_NEW(DPAD_UP)) + { + if (data->submenuYpos[2] == 0) + data->submenuYpos[2] = 2; + else + data->submenuYpos[2] -= 1; + + data->yPosModifyArrows.currentDigit = data->submenuYpos[2]; + gSprites[data->yPosModifyArrows.arrowSpriteId[0]].y = OPTIONS_ARROW_Y + data->yPosModifyArrows.currentDigit * 12; + } + else if (JOY_NEW(DPAD_LEFT)) + { + UpdateSubmenuTwoOptionValue(taskId, FALSE); + } + else if (JOY_NEW(DPAD_RIGHT)) + { + UpdateSubmenuTwoOptionValue(taskId, TRUE); + } + } +} +#undef sDelay +#undef sAnimId + +static void ReloadPokemonSprites(struct PokemonSpriteVisualizer *data) +{ + const u32 *palette; + u16 species = data->currentmonId; + s16 offset_y; + u8 front_x = sBattlerCoords[0][1].x; + u8 front_y; + + DestroySprite(&gSprites[data->frontspriteId]); + DestroySprite(&gSprites[data->backspriteId]); + DestroySprite(&gSprites[data->iconspriteId]); + DestroySprite(&gSprites[data->followerspriteId]); + + FreeMonSpritesGfx(); + ResetSpriteData(); + ResetPaletteFade(); + FreeAllSpritePalettes(); + ResetAllPicSprites(); + FreeMonIconPalettes(); + + AllocateMonSpritesGfx(); + LoadMonIconPalettePersonality(species, (data->isFemale ? FEMALE_PERSONALITY : MALE_PERSONALITY)); + + //Update instructions + PrintInstructionsOnWindow(data); + + //Palettes + palette = GetMonSpritePalFromSpecies(species, data->isShiny, data->isFemale); + LoadCompressedSpritePaletteWithTag(palette, species); + //Front + HandleLoadSpecialPokePic(TRUE, gMonSpritesGfxPtr->sprites[1], species, (data->isFemale ? FEMALE_PERSONALITY : MALE_PERSONALITY)); + BattleLoadOpponentMonSpriteGfxCustom(species, data->isFemale, data->isShiny, 1); + SetMultiuseSpriteTemplateToPokemon(species, 1); + gMultiuseSpriteTemplate.paletteTag = species; + front_y = GetBattlerSpriteFinal_YCustom(species, 0, 0); + data->frontspriteId = CreateSprite(&gMultiuseSpriteTemplate, front_x, front_y, 0); + gSprites[data->frontspriteId].oam.paletteNum = 1; + gSprites[data->frontspriteId].callback = SpriteCallbackDummy; + gSprites[data->frontspriteId].oam.priority = 0; + //Front Shadow + LoadAndCreateEnemyShadowSpriteCustom(data, species); + + //Back + HandleLoadSpecialPokePic(FALSE, gMonSpritesGfxPtr->sprites[2], species, (data->isFemale ? FEMALE_PERSONALITY : MALE_PERSONALITY)); + BattleLoadOpponentMonSpriteGfxCustom(species, data->isFemale, data->isShiny, 5); + SetMultiuseSpriteTemplateToPokemon(species, 2); + offset_y = gSpeciesInfo[species].backPicYOffset; + data->backspriteId = CreateSprite(&gMultiuseSpriteTemplate, VISUALIZER_MON_BACK_X, VISUALIZER_MON_BACK_Y + offset_y, 0); + gSprites[data->backspriteId].oam.paletteNum = 5; + gSprites[data->backspriteId].callback = SpriteCallbackDummy; + gSprites[data->backspriteId].oam.priority = 0; + + //Icon Sprite + data->iconspriteId = CreateMonIcon(species, SpriteCB_MonIcon, VISUALIZER_ICON_X, VISUALIZER_ICON_Y, 4, (data->isFemale ? FEMALE_PERSONALITY : MALE_PERSONALITY)); + gSprites[data->iconspriteId].oam.priority = 0; + + //Follower Sprite + // data->followerspriteId = CreateObjectGraphicsSprite(OBJ_EVENT_GFX_MON_BASE + species + (data->isShiny ? SPECIES_SHINY_TAG : 0), + // SpriteCB_Follower, + // VISUALIZER_FOLLOWER_X, + // VISUALIZER_FOLLOWER_Y, + // 0); + // gSprites[data->followerspriteId].oam.priority = 0; + // gSprites[data->followerspriteId].anims = sAnims_Follower; + + //Modify Arrows + LoadSpritePalette(&gSpritePalette_Arrow); + data->modifyArrows.arrowSpriteId[0] = CreateSprite(&gSpriteTemplate_Arrow, MODIFY_DIGITS_ARROW_X + (data->modifyArrows.currentDigit * 6), MODIFY_DIGITS_ARROW1_Y, 0); + data->modifyArrows.arrowSpriteId[1] = CreateSprite(&gSpriteTemplate_Arrow, MODIFY_DIGITS_ARROW_X + (data->modifyArrows.currentDigit * 6), MODIFY_DIGITS_ARROW2_Y, 0); + gSprites[data->modifyArrows.arrowSpriteId[1]].animNum = 1; + + //Option Arrow + LoadSpritePalette(&gSpritePalette_Arrow); + data->optionArrows.arrowSpriteId[0] = CreateSprite(&gSpriteTemplate_Arrow, OPTIONS_ARROW_1_X, OPTIONS_ARROW_Y + data->optionArrows.currentDigit * 12, 0); + gSprites[data->optionArrows.arrowSpriteId[0]].animNum = 2; + + //Y Pos Modify Arrow + LoadSpritePalette(&gSpritePalette_Arrow); + data->yPosModifyArrows.arrowSpriteId[0] = CreateSprite(&gSpriteTemplate_Arrow, OPTIONS_ARROW_1_X, OPTIONS_ARROW_Y + data->yPosModifyArrows.currentDigit * 12, 0); + gSprites[data->yPosModifyArrows.arrowSpriteId[0]].animNum = 2; + + //Arrow invisibility + SetArrowInvisibility(data); + + //Footprint + // DrawFootprint(WIN_FOOTPRINT, species); + // CopyWindowToVram(WIN_FOOTPRINT, COPYWIN_GFX); +} + +static void Exit_PokemonSpriteVisualizer(u8 taskId) +{ + if (!gPaletteFade.active) + { + struct PokemonSpriteVisualizer *data = GetStructPtr(taskId); + Free(data); + FreeMonSpritesGfx(); + DestroyTask(taskId); + SetMainCallback2(CB2_ReturnToFieldWithOpenMenu); + m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 0x100); + } +} + +#endif diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index cb7e2d5cf..4c9ef0fa9 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -12,6 +12,7 @@ #include "new_menu_helpers.h" #include "menu.h" #include "constants/items.h" +#include "pokemon_sprite_visualizer.h" #include "data.h" #include "item.h" #include "constants/party_menu.h" @@ -1203,6 +1204,16 @@ static void Task_InputHandler_Info(u8 taskId) { sMonSummaryScreen->state3270 = PSS_STATE3270_ATEXIT_FADEOUT; } +#if DEBUG_POKEMON_SPRITE_VISUALIZER == TRUE + else if (JOY_NEW(SELECT_BUTTON) && !gMain.inBattle) + { + sMonSummaryScreen->savedCallback = CB2_Pokemon_Sprite_Visualizer; + // StopPokemonAnimations(); + PlaySE(SE_SELECT); + // CloseSummaryScreen(taskId); + sMonSummaryScreen->state3270 = PSS_STATE3270_ATEXIT_FADEOUT; + } +#endif } break; case PSS_STATE3270_FLIPPAGES: diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index 748b02366..77d9ce6c6 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -436,3 +436,55 @@ void ReducePlayerPartyToThree(void) CalculatePlayerPartyCount(); Free(party); } + +void Script_GetChosenMonOffensiveEVs(void) +{ + ConvertIntToDecimalStringN(gStringVar1, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_ATK_EV), STR_CONV_MODE_LEFT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar2, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPATK_EV), STR_CONV_MODE_LEFT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar3, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPEED_EV), STR_CONV_MODE_LEFT_ALIGN, 3); +} + +void Script_GetChosenMonDefensiveEVs(void) +{ + ConvertIntToDecimalStringN(gStringVar1, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_HP_EV), STR_CONV_MODE_LEFT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar2, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_DEF_EV), STR_CONV_MODE_LEFT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar3, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPDEF_EV), STR_CONV_MODE_LEFT_ALIGN, 3); +} + +void Script_GetChosenMonOffensiveIVs(void) +{ + ConvertIntToDecimalStringN(gStringVar1, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_ATK_IV), STR_CONV_MODE_LEFT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar2, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPATK_IV), STR_CONV_MODE_LEFT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar3, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPEED_IV), STR_CONV_MODE_LEFT_ALIGN, 3); +} + +void Script_GetChosenMonDefensiveIVs(void) +{ + ConvertIntToDecimalStringN(gStringVar1, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_HP_IV), STR_CONV_MODE_LEFT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar2, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_DEF_IV), STR_CONV_MODE_LEFT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar3, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPDEF_IV), STR_CONV_MODE_LEFT_ALIGN, 3); +} + +void Script_SetStatus1(struct ScriptContext *ctx) +{ + u32 status1 = VarGet(ScriptReadHalfword(ctx)); + u32 slot = VarGet(ScriptReadHalfword(ctx)); + + if (slot >= PARTY_SIZE) + { + u16 species; + + for (slot = 0; slot < PARTY_SIZE; slot++) + { + species = GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES); + if (species != SPECIES_NONE + && species != SPECIES_EGG + && GetMonData(&gPlayerParty[slot], MON_DATA_HP) != 0) + SetMonData(&gPlayerParty[slot], MON_DATA_STATUS, &status1); + } + } + else + { + SetMonData(&gPlayerParty[slot], MON_DATA_STATUS, &status1); + } +} diff --git a/src/start_menu.c b/src/start_menu.c index d71359329..64619a5df 100644 --- a/src/start_menu.c +++ b/src/start_menu.c @@ -1,5 +1,6 @@ #include "global.h" #include "gflib.h" +#include "debug.h" #include "scanline_effect.h" #include "overworld.h" #include "link.h" @@ -49,6 +50,7 @@ enum StartMenuOption STARTMENU_EXIT, STARTMENU_RETIRE, STARTMENU_PLAYER2, + STARTMENU_DEBUG, MAX_STARTMENU_ITEMS }; @@ -89,6 +91,7 @@ static bool8 StartMenuOptionCallback(void); static bool8 StartMenuExitCallback(void); static bool8 StartMenuSafariZoneRetireCallback(void); static bool8 StartMenuLinkPlayerCallback(void); +static bool8 StartMenuDebugCallback(void); static bool8 StartCB_Save1(void); static bool8 StartCB_Save2(void); static void StartMenu_PrepareForSave(void); @@ -113,6 +116,9 @@ static void task50_after_link_battle_save(u8 taskId); static void PrintSaveStats(void); static void CloseSaveStatsWindow(void); static void CloseStartMenu(void); +static void HideStartMenuDebug(void); + +static const u8 sText_MenuDebug[] = _("DEBUG"); static const struct MenuAction sStartMenuActionTable[] = { { gText_MenuPokedex, {.u8_void = StartMenuPokedexCallback} }, @@ -123,7 +129,8 @@ static const struct MenuAction sStartMenuActionTable[] = { { gText_MenuOption, {.u8_void = StartMenuOptionCallback} }, { gText_MenuExit, {.u8_void = StartMenuExitCallback} }, { gText_MenuRetire, {.u8_void = StartMenuSafariZoneRetireCallback} }, - { gText_MenuPlayer, {.u8_void = StartMenuLinkPlayerCallback} } + { gText_MenuPlayer, {.u8_void = StartMenuLinkPlayerCallback} }, + [STARTMENU_DEBUG] = {sText_MenuDebug, {.u8_void = StartMenuDebugCallback}}, }; static const struct WindowTemplate sTimeWindowTemplate = { @@ -133,7 +140,7 @@ static const struct WindowTemplate sTimeWindowTemplate = { .width = 10, .height = 4, .paletteNum = 15, - .baseBlock = 0x198 + .baseBlock = 0x1A8 }; static const struct WindowTemplate sTimeSafariWindowTemplate = { @@ -165,7 +172,8 @@ static const u8 *const sStartMenuDescPointers[] = { gStartMenuDesc_Option, gStartMenuDesc_Exit, gStartMenuDesc_Retire, - gStartMenuDesc_Player + gStartMenuDesc_Player, + gStartMenuDesc_Debug, }; static const struct BgTemplate sBGTemplates_AfterLinkSaveMessage[] = { @@ -226,6 +234,9 @@ static void AppendToStartMenuItems(u8 newEntry) static void SetUpStartMenu_NormalField(void) { +#if DEBUG_OVERWORLD_MENU == TRUE + AppendToStartMenuItems(STARTMENU_DEBUG); +#endif if (FlagGet(FLAG_SYS_POKEDEX_GET) == TRUE) AppendToStartMenuItems(STARTMENU_POKEDEX); if (FlagGet(FLAG_SYS_POKEMON_GET) == TRUE) @@ -394,7 +405,9 @@ static s8 DoDrawStartMenu(void) sStartMenuCursorPos = Menu_InitCursor(GetStartMenuWindowId(), FONT_NORMAL, 0, 0, 15, sNumStartMenuItems, sStartMenuCursorPos); if (!MenuHelpers_IsLinkActive() && InUnionRoom() != TRUE && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_HELP) { +#if DEBUG_OVERWORLD_MENU != TRUE DrawHelpMessageWindowWithText(sStartMenuDescPointers[sStartMenuOrder[sStartMenuCursorPos]]); +#endif } CopyWindowToVram(GetStartMenuWindowId(), COPYWIN_MAP); return TRUE; @@ -478,7 +491,9 @@ static bool8 StartCB_HandleInput(void) sStartMenuCursorPos = Menu_MoveCursor(-1); if (!MenuHelpers_IsLinkActive() && InUnionRoom() != TRUE && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_HELP) { +#if DEBUG_OVERWORLD_MENU != TRUE PrintTextOnHelpMessageWindow(sStartMenuDescPointers[sStartMenuOrder[sStartMenuCursorPos]], 2); +#endif } } if (JOY_NEW(DPAD_DOWN)) @@ -487,7 +502,9 @@ static bool8 StartCB_HandleInput(void) sStartMenuCursorPos = Menu_MoveCursor(+1); if (!MenuHelpers_IsLinkActive() && InUnionRoom() != TRUE && gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_HELP) { +#if DEBUG_OVERWORLD_MENU != TRUE PrintTextOnHelpMessageWindow(sStartMenuDescPointers[sStartMenuOrder[sStartMenuCursorPos]], 2); +#endif } } if (JOY_NEW(A_BUTTON)) @@ -502,7 +519,9 @@ static bool8 StartCB_HandleInput(void) if (JOY_NEW(B_BUTTON | START_BUTTON)) { DestroySafariZoneStatsWindow(); +#if DEBUG_OVERWORLD_MENU != TRUE DestroyHelpMessageWindow_(); +#endif CloseStartMenu(); return TRUE; } @@ -513,6 +532,7 @@ static void StartMenu_FadeScreenIfLeavingOverworld(void) { if (sStartMenuCallback != StartMenuSaveCallback && sStartMenuCallback != StartMenuExitCallback + && sStartMenuCallback != StartMenuDebugCallback && sStartMenuCallback != StartMenuSafariZoneRetireCallback) { StopPokemonLeagueLightingEffectTask(); @@ -603,20 +623,43 @@ static bool8 StartMenuOptionCallback(void) static bool8 StartMenuExitCallback(void) { DestroySafariZoneStatsWindow(); +#if DEBUG_OVERWORLD_MENU != TRUE DestroyHelpMessageWindow_(); +#endif CloseStartMenu(); return TRUE; } +static bool8 StartMenuDebugCallback(void) +{ + DestroySafariZoneStatsWindow(); + HideStartMenuDebug(); // Hide start menu without enabling movement + +#if DEBUG_OVERWORLD_MENU == TRUE + FreezeObjectEvents(); + Debug_ShowMainMenu(); +#endif + +return TRUE; +} + static bool8 StartMenuSafariZoneRetireCallback(void) { DestroySafariZoneStatsWindow(); +#if DEBUG_OVERWORLD_MENU != TRUE DestroyHelpMessageWindow_(); +#endif CloseStartMenu(); SafariZoneRetirePrompt(); return TRUE; } +static void HideStartMenuDebug(void) +{ + PlaySE(SE_SELECT); + ClearStdWindowAndFrame(GetStartMenuWindowId(), TRUE); + RemoveStartMenuWindow(); +} static bool8 StartMenuLinkPlayerCallback(void) { @@ -775,7 +818,9 @@ static u8 SaveDialogCB_PrintAskSaveText(void) { ClearStdWindowAndFrame(GetStartMenuWindowId(), FALSE); RemoveStartMenuWindow(); +#if DEBUG_OVERWORLD_MENU != TRUE DestroyHelpMessageWindow(0); +#endif PrintSaveStats(); PrintSaveTextWithFollowupFunc(gText_WouldYouLikeToSaveTheGame, SaveDialogCB_AskSavePrintYesNoMenu); return SAVECB_RETURN_CONTINUE; diff --git a/src/strings.c b/src/strings.c index ef0a13fee..b1ef8e330 100644 --- a/src/strings.c +++ b/src/strings.c @@ -915,6 +915,7 @@ const u8 gStartMenuDesc_Save[] = _("Save your game with a complete record\nof yo const u8 gStartMenuDesc_Option[] = _("Adjust various game settings such as text\nspeed, game rules, etc."); const u8 gStartMenuDesc_Exit[] = _("Close this MENU window."); const u8 gStartMenuDesc_Retire[] = _("Retire from the SAFARI GAME and return to\nthe registration counter."); +const u8 gStartMenuDesc_Debug[] = _("Debug Menu."); #include "data/text/quest_log.h" @@ -1377,3 +1378,10 @@ const u8 gText_NextFusionMon[] = _("Choose {PKMN} to fuse with."); const u8 gText_ExpShareOn[] = _("The Exp. Share has been turned on.{PAUSE_UNTIL_PRESS}"); const u8 gText_ExpShareOff[] = _("The Exp. Share has been turned off.{PAUSE_UNTIL_PRESS}"); + +// stats +const u8 gText_Attack[] = _("ATTACK"); +const u8 gText_Defense[] = _("DEFENSE"); +const u8 gText_Speed[] = _("SPEED"); +const u8 gText_SpAtk[] = _("SP. ATK"); +const u8 gText_SpDef[] = _("SP. DEF"); diff --git a/src/trainer_see.c b/src/trainer_see.c index b66409c18..8a56a886f 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -43,6 +43,10 @@ static void Task_DestroyTrainerApproachTask(u8 taskId); static void SpriteCB_TrainerIcons(struct Sprite *sprite); static void SetIconSpriteData(struct Sprite *sprite, u16 fldEffId, u8 spriteAnimNum); +// IWRAM common +u16 gWhichTrainerToFaceAfterBattle; +u8 gNoOfApproachingTrainers; + static const u16 sGfx_Emoticons[] = INCBIN_U16("graphics/misc/emoticons.4bpp"); // u8 func(struct ObjectEvent * trainerObj, s16 range, s16 x, s16 y) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index e7f235015..75ceb5b84 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -1,5 +1,6 @@ #include "global.h" #include "random.h" +#include "battle_debug.h" #include "wild_encounter.h" #include "event_data.h" #include "fieldmap.h" diff --git a/tools/mapjson/mapjson.cpp b/tools/mapjson/mapjson.cpp index eef4835ee..bd3e00820 100644 --- a/tools/mapjson/mapjson.cpp +++ b/tools/mapjson/mapjson.cpp @@ -451,6 +451,7 @@ string generate_map_constants_text(string groups_filepath, Json groups_data) { char dir_separator = file_dir.back(); ostringstream text; + ostringstream mapCountText; text << "#ifndef GUARD_CONSTANTS_MAP_GROUPS_H\n" << "#define GUARD_CONSTANTS_MAP_GROUPS_H\n\n"; @@ -458,6 +459,7 @@ string generate_map_constants_text(string groups_filepath, Json groups_data) { text << "//\n// DO NOT MODIFY THIS FILE! It is auto-generated from data/maps/map_groups.json\n//\n\n"; int group_num = 0; + vector map_count_vec; //DEBUG for (auto &group : groups_data["group_order"].array_items()) { string groupName = json_to_string(group); @@ -465,6 +467,8 @@ string generate_map_constants_text(string groups_filepath, Json groups_data) { vector map_ids; size_t max_length = 0; + int map_count = 0; //DEBUG + for (auto &map_name : groups_data[groupName].array_items()) { string map_filepath = file_dir + json_to_string(map_name) + dir_separator + "map.json"; string err_str; @@ -475,6 +479,7 @@ string generate_map_constants_text(string groups_filepath, Json groups_data) { map_ids.push_back(id); if (id.length() > max_length) max_length = id.length(); + map_count++; //DEBUG } int map_id_num = 0; @@ -485,11 +490,20 @@ string generate_map_constants_text(string groups_filepath, Json groups_data) { text << "\n"; group_num++; + map_count_vec.push_back(map_count); //DEBUG } text << "#define MAP_GROUPS_COUNT " << group_num << "\n\n"; text << "#endif // GUARD_CONSTANTS_MAP_GROUPS_H\n"; + char s = file_dir.back(); + mapCountText << "static const u8 MAP_GROUP_COUNT[] = {"; //DEBUG + for(int i=0; i& buffer, int offset, int void CFile::TryConvertIncbin() { - std::string idents[6] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32" }; + std::string idents[8] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32", "DUMMY_PLACEHOLDER", "INCBIN_COMP"}; int incbinType = -1; - for (int i = 0; i < 6; i++) + for (int i = 0; i < 8; i++) { if (CheckIdentifier(idents[i])) { @@ -337,6 +337,8 @@ void CFile::TryConvertIncbin() return; int size = 1 << (incbinType / 2); + if (size > 4) + size = 4; bool isSigned = ((incbinType % 2) == 0); long oldPos = m_pos; @@ -389,6 +391,10 @@ void CFile::TryConvertIncbin() std::string path(&m_buffer[startPos], m_pos - startPos); + // INCBIN_COMP; include *compressed* version of file + if (incbinType == 7) + path = path.append(".lz"); + m_pos++; int fileSize;