Debug parties and battles (#6884)

Co-authored-by: sbird <sbird@no.tld>
This commit is contained in:
Philipp AUER 2025-06-03 17:21:17 -04:00 committed by GitHub
parent 1a6ed20713
commit 21f0eb1583
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 276 additions and 44 deletions

View File

@ -5,6 +5,7 @@
#include "constants/trainers.h"
#include "constants/battle.h"
#include "difficulty.h"
#include "debug.h"
#define MAX_TRAINER_ITEMS 4
@ -205,7 +206,9 @@ static inline u16 SanitizeTrainerId(u16 trainerId)
static inline const struct Trainer *GetTrainerStructFromId(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
u32 sanitizedTrainerId = 0;
if (gIsDebugBattle) return GetDebugAiTrainer();
sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
return &gTrainers[difficulty][sanitizedTrainerId];
@ -213,10 +216,9 @@ static inline const struct Trainer *GetTrainerStructFromId(u16 trainerId)
static inline const enum TrainerClassID GetTrainerClassFromId(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
const struct Trainer *trainer = GetTrainerStructFromId(trainerId);
return gTrainers[difficulty][sanitizedTrainerId].trainerClass;
return trainer->trainerClass;
}
static inline const u8 *GetTrainerClassNameFromId(u16 trainerId)
@ -230,82 +232,62 @@ static inline const u8 *GetTrainerClassNameFromId(u16 trainerId)
static inline const u8 *GetTrainerNameFromId(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
enum DifficultyLevel partnerDifficulty = GetBattlePartnerDifficultyLevel(trainerId);
if (trainerId > TRAINER_PARTNER(PARTNER_NONE))
{
enum DifficultyLevel partnerDifficulty = GetBattlePartnerDifficultyLevel(trainerId);
return gBattlePartners[partnerDifficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName;
return gTrainers[difficulty][sanitizedTrainerId].trainerName;
}
return GetTrainerStructFromId(trainerId)->trainerName;
}
static inline const u8 GetTrainerPicFromId(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
enum DifficultyLevel partnerDifficulty = GetBattlePartnerDifficultyLevel(trainerId);
if (trainerId > TRAINER_PARTNER(PARTNER_NONE))
return gBattlePartners[partnerDifficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic;
return gTrainers[difficulty][sanitizedTrainerId].trainerPic;
return GetTrainerStructFromId(trainerId)->trainerPic;
}
static inline const u8 GetTrainerStartingStatusFromId(u16 trainerId)
{
return gTrainers[GetCurrentDifficultyLevel()][SanitizeTrainerId(trainerId)].startingStatus;
return GetTrainerStructFromId(trainerId)->startingStatus;
}
static inline const enum TrainerBattleType GetTrainerBattleType(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
return gTrainers[difficulty][sanitizedTrainerId].battleType;
return GetTrainerStructFromId(trainerId)->battleType;
}
static inline const u8 GetTrainerPartySizeFromId(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
return gTrainers[difficulty][sanitizedTrainerId].partySize;
return GetTrainerStructFromId(trainerId)->partySize;
}
static inline const bool32 DoesTrainerHaveMugshot(u16 trainerId)
{
return gTrainers[GetCurrentDifficultyLevel()][SanitizeTrainerId(trainerId)].mugshotColor;
return GetTrainerStructFromId(trainerId)->mugshotColor;
}
static inline const u8 GetTrainerMugshotColorFromId(u16 trainerId)
{
return gTrainers[GetCurrentDifficultyLevel()][SanitizeTrainerId(trainerId)].mugshotColor;
return GetTrainerStructFromId(trainerId)->mugshotColor;
}
static inline const u16 *GetTrainerItemsFromId(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
return gTrainers[difficulty][sanitizedTrainerId].items;
return GetTrainerStructFromId(trainerId)->items;
}
static inline const struct TrainerMon *GetTrainerPartyFromId(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
return gTrainers[difficulty][sanitizedTrainerId].party;
return GetTrainerStructFromId(trainerId)->party;
}
static inline const u64 GetTrainerAIFlagsFromId(u16 trainerId)
{
u32 sanitizedTrainerId = SanitizeTrainerId(trainerId);
enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId);
return gTrainers[difficulty][sanitizedTrainerId].aiFlags;
return GetTrainerStructFromId(trainerId)->aiFlags;
}
#endif // GUARD_DATA_H

View File

@ -4,6 +4,7 @@
void Debug_ShowMainMenu(void);
extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[];
const u8 *GetWeatherName(u32 weatherId);
const struct Trainer* GetDebugAiTrainer(void);
extern EWRAM_DATA bool8 gIsDebugBattle;
extern EWRAM_DATA u64 gDebugAIFlags;

132
src/data/debug_trainers.h Normal file
View File

@ -0,0 +1,132 @@
//
// DO NOT MODIFY THIS FILE! It is auto-generated from src/data/debug_trainers.party
//
// If you want to modify this file set COMPETITIVE_PARTY_SYNTAX to FALSE
// in include/config/general.h and remove this notice.
// Use sed -i '/^#line/d' 'src/data/debug_trainers.h' to remove #line markers.
//
#line 1 "src/data/debug_trainers.party"
#line 14
[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER] =
{
#line 15
.trainerName = _("Player"),
#line 16
.trainerClass = TRAINER_CLASS_PKMN_TRAINER_1,
#line 17
.trainerPic = TRAINER_PIC_BRENDAN,
.encounterMusic_gender =
#line 19
TRAINER_ENCOUNTER_MUSIC_MALE,
.partySize = 1,
.party = (const struct TrainerMon[])
{
{
#line 21
.nickname = COMPOUND_STRING("Buffie"),
#line 21
.species = SPECIES_WOBBUFFET,
.gender = TRAINER_MON_RANDOM_GENDER,
#line 25
.ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0),
#line 24
.iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31),
#line 23
.lvl = 100,
#line 22
.nature = NATURE_BRAVE,
.dynamaxLevel = MAX_DYNAMAX_LEVEL,
.moves = {
#line 26
MOVE_EARTHQUAKE,
MOVE_FLAMETHROWER,
MOVE_CELEBRATE,
MOVE_CELEBRATE,
},
},
},
},
#line 31
[DIFFICULTY_NORMAL][DEBUG_TRAINER_AI] =
{
#line 32
.trainerName = _("Debugger"),
#line 33
.trainerClass = TRAINER_CLASS_RIVAL,
#line 35
.trainerPic = TRAINER_PIC_STEVEN,
.encounterMusic_gender =
#line 37
TRAINER_ENCOUNTER_MUSIC_MALE,
#line 34
.battleType = TRAINER_BATTLE_TYPE_SINGLES,
.partySize = 3,
.party = (const struct TrainerMon[])
{
{
#line 39
.species = SPECIES_METANG,
.gender = TRAINER_MON_RANDOM_GENDER,
#line 43
.ev = TRAINER_PARTY_EVS(0, 252, 252, 0, 6, 0),
#line 42
.iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31),
#line 41
.lvl = 42,
#line 40
.nature = NATURE_BRAVE,
.dynamaxLevel = MAX_DYNAMAX_LEVEL,
.moves = {
#line 44
MOVE_LIGHT_SCREEN,
MOVE_PSYCHIC,
MOVE_REFLECT,
MOVE_METAL_CLAW,
},
},
{
#line 49
.species = SPECIES_SKARMORY,
.gender = TRAINER_MON_RANDOM_GENDER,
#line 53
.ev = TRAINER_PARTY_EVS(252, 0, 0, 0, 6, 252),
#line 52
.iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31),
#line 51
.lvl = 43,
#line 50
.nature = NATURE_IMPISH,
.dynamaxLevel = MAX_DYNAMAX_LEVEL,
.moves = {
#line 54
MOVE_TOXIC,
MOVE_AERIAL_ACE,
MOVE_PROTECT,
MOVE_STEEL_WING,
},
},
{
#line 59
.species = SPECIES_AGGRON,
.gender = TRAINER_MON_RANDOM_GENDER,
#line 63
.ev = TRAINER_PARTY_EVS(0, 252, 0, 0, 252, 6),
#line 62
.iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31),
#line 61
.lvl = 44,
#line 60
.nature = NATURE_ADAMANT,
.dynamaxLevel = MAX_DYNAMAX_LEVEL,
.moves = {
#line 64
MOVE_THUNDER,
MOVE_PROTECT,
MOVE_SOLAR_BEAM,
MOVE_DRAGON_CLAW,
},
},
},
},

View File

@ -0,0 +1,68 @@
/*
Parties for the debug menu.
The trainer description for DEBUG_TRAINER_PLAYER is not used,
its party is given to the player whenever the Set Party action is selected,
or the Start Debug Battle action is selected.
The debug menu will start a battle against DEBUG_TRAINER_AI when the
Start Debug Battle action is selected.
*/
=== DEBUG_TRAINER_PLAYER ===
Name: Player
Class: Pkmn Trainer 1
Pic: Brendan
Gender: Male
Music: Male
Buffie (Wobbuffet)
Brave Nature
Level: 100
IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe
EVs: 252 Atk / 252 Def / 6 SpA
- Earthquake
- Flamethrower
- Celebrate
- Celebrate
=== DEBUG_TRAINER_AI ===
Name: Debugger
AI: Basic Trainer
Class: Rival
Battle Type: Singles
Pic: Steven
Gender: Male
Music: Male
Metang
Brave Nature
Level: 42
IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe
EVs: 252 Atk / 252 Def / 6 SpA
- Light Screen
- Psychic
- Reflect
- Metal Claw
Skarmory
Impish Nature
Level: 43
IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe
EVs: 252 HP / 6 SpA / 252 SpD
- Toxic
- Aerial Ace
- Protect
- Steel Wing
Aggron
Adamant Nature
Level: 44
IVs: 31 HP / 31 Atk / 31 Def / 31 SpA / 31 SpD / 31 Spe
EVs: 252 Atk / 252 SpA / 6 SpD
- Thunder
- Protect
- Solar Beam
- Dragon Claw

View File

@ -159,6 +159,8 @@ enum PartyDebugMenu
DEBUG_PARTY_MENU_ITEM_CHECK_EVS,
DEBUG_PARTY_MENU_ITEM_CHECK_IVS,
DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY,
DEBUG_PARTY_MENU_ITEM_SET_PARTY,
DEBUG_PARTY_MENU_ITEM_BATTLE_SINGLE,
};
enum ScriptDebugMenu
@ -437,6 +439,8 @@ 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_Party_SetParty(u8 taskId);
static void DebugAction_Party_BattleSingle(u8 taskId);
static void DebugAction_FlagsVars_Flags(u8 taskId);
static void DebugAction_FlagsVars_FlagsSelect(u8 taskId);
@ -708,13 +712,15 @@ static const struct ListMenuItem sDebugMenu_Items_PCBag_Fill[] =
static const struct ListMenuItem sDebugMenu_Items_Party[] =
{
[DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER] = {COMPOUND_STRING("Move Reminder"), DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER},
[DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG] = {COMPOUND_STRING("Hatch an Egg"), DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG},
[DEBUG_PARTY_MENU_ITEM_HEAL_PARTY] = {COMPOUND_STRING("Heal party"), DEBUG_PARTY_MENU_ITEM_HEAL_PARTY},
[DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1] = {COMPOUND_STRING("Inflict Status1"), DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1},
[DEBUG_PARTY_MENU_ITEM_CHECK_EVS] = {COMPOUND_STRING("Check EVs"), DEBUG_PARTY_MENU_ITEM_CHECK_EVS},
[DEBUG_PARTY_MENU_ITEM_CHECK_IVS] = {COMPOUND_STRING("Check IVs"), DEBUG_PARTY_MENU_ITEM_CHECK_IVS},
[DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY] = {COMPOUND_STRING("Clear Party"), DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY},
[DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER] = {COMPOUND_STRING("Move Reminder"), DEBUG_PARTY_MENU_ITEM_MOVE_REMINDER},
[DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG] = {COMPOUND_STRING("Hatch an Egg"), DEBUG_PARTY_MENU_ITEM_HATCH_AN_EGG},
[DEBUG_PARTY_MENU_ITEM_HEAL_PARTY] = {COMPOUND_STRING("Heal party"), DEBUG_PARTY_MENU_ITEM_HEAL_PARTY},
[DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1] = {COMPOUND_STRING("Inflict Status1"), DEBUG_PARTY_MENU_ITEM_INFLICT_STATUS1},
[DEBUG_PARTY_MENU_ITEM_CHECK_EVS] = {COMPOUND_STRING("Check EVs"), DEBUG_PARTY_MENU_ITEM_CHECK_EVS},
[DEBUG_PARTY_MENU_ITEM_CHECK_IVS] = {COMPOUND_STRING("Check IVs"), DEBUG_PARTY_MENU_ITEM_CHECK_IVS},
[DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY] = {COMPOUND_STRING("Clear Party"), DEBUG_PARTY_MENU_ITEM_CLEAR_PARTY},
[DEBUG_PARTY_MENU_ITEM_SET_PARTY] = {COMPOUND_STRING("Set Party"), DEBUG_PARTY_MENU_ITEM_SET_PARTY},
[DEBUG_PARTY_MENU_ITEM_BATTLE_SINGLE] = {COMPOUND_STRING("Start Debug Battle"), DEBUG_PARTY_MENU_ITEM_BATTLE_SINGLE},
};
static const struct ListMenuItem sDebugMenu_Items_Scripts[] =
@ -897,6 +903,8 @@ static void (*const sDebugMenu_Actions_Party[])(u8) =
[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,
[DEBUG_PARTY_MENU_ITEM_SET_PARTY] = DebugAction_Party_SetParty,
[DEBUG_PARTY_MENU_ITEM_BATTLE_SINGLE] = DebugAction_Party_BattleSingle,
};
static void (*const sDebugMenu_Actions_Scripts[])(u8) =
@ -4893,6 +4901,47 @@ static void DebugAction_Party_ClearParty(u8 taskId)
Debug_DestroyMenu_Full(taskId);
}
enum DebugTrainerIds
{
DEBUG_TRAINER_PLAYER,
DEBUG_TRAINER_AI,
DEBUG_TRAINERS_COUNT
};
const struct Trainer sDebugTrainers[DIFFICULTY_COUNT][DEBUG_TRAINERS_COUNT] =
{
#include "data/debug_trainers.h"
};
const struct Trainer* GetDebugAiTrainer(void)
{
return &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_AI];
}
static void DebugAction_Party_SetParty(u8 taskId)
{
ZeroPlayerPartyMons();
CreateNPCTrainerPartyFromTrainer(gPlayerParty, &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER], TRUE, BATTLE_TYPE_TRAINER);
ScriptContext_Enable();
Debug_DestroyMenu_Full(taskId);
}
static void DebugAction_Party_BattleSingle(u8 taskId)
{
ZeroPlayerPartyMons();
ZeroEnemyPartyMons();
CreateNPCTrainerPartyFromTrainer(gPlayerParty, &sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_PLAYER], TRUE, BATTLE_TYPE_TRAINER);
CreateNPCTrainerPartyFromTrainer(gEnemyParty, GetDebugAiTrainer(), FALSE, BATTLE_TYPE_TRAINER);
gBattleTypeFlags = BATTLE_TYPE_TRAINER;
gDebugAIFlags = sDebugTrainers[DIFFICULTY_NORMAL][DEBUG_TRAINER_AI].aiFlags;
gIsDebugBattle = TRUE;
gBattleEnvironment = BattleSetup_GetEnvironmentId();
CalculateEnemyPartyCount();
BattleSetup_StartTrainerBattle_Debug();
Debug_DestroyMenu_Full(taskId);
}
void CheckEWRAMCounters(struct ScriptContext *ctx)
{
ConvertIntToDecimalStringN(gStringVar1, gFollowerSteps, STR_CONV_MODE_LEFT_ALIGN, 5);