- 250
- Posts
- 7
- Years
- Seen Apr 23, 2025
Have you ever thought: "Man, the boss battles are just too easy in these Pokemon games!" Have I got the solution for you! I've gathered and created a collection of code that you can put in your decomp so that any battle of your choosing can be a bit more challenging, but not unfairly so. I've broken them up into a few sections, so you can pick and choose which elements that you want to implement.
1. Level Balancing
Some people just want to grind xp until their Pokemon are strong enough to smite any foe they come across. Others accidentally level up their Pokemon a bit too much, making a battle far less challenging than they were hoping for. With level balancing, however, these issues are a thing of the past! With a bit of code from this post, you can make it so that every trainer's party will be roughly the same level as the player's party, no matter how strong the player's team is. If you wanted only certain trainers to get this dynamic leveling, all you have to do is make the following change. At every instance of this:
Change it to this:
This will make it so that only Gym Leaders, Elite Four Members, the Champion, your rival, and Wally will have dynamic leveling. You can, of course, add or take away other trainer classes if you wish, or keep the original code and make every single trainer be dynamically leveled. You just need to look into src/data/trainers.h and put in the whatever filter you want based on the information in there.
2. Item Balancing
I've noticed that, when I play a Pokemon game, I tend to rely on a lot of items on the harder battles. With the following code, however, I or any other player will be forced to strategize more. This code will cause the player to have the same items as they're opponent, making the battle a bit more fair.
The first bit of code you'll need is this:
In src/item.c:
Add this at the end:
These functions will, as the names imply, give the player their opponent's items, take away the player's items and berries, and give them back, respectively. They aren't just taken away, but saved until they are returned. Those variables added at the top hold the items and berries that are taken away.
In data/specials.inc:
Add this at the end:
This is needed so that those functions can be used in scripts.
In include/item.h:
Add this at the end:
This establishes those variables and functions that hold the items and berries, as well as gives back the items and berries that are taken away.
In include/constants/flags.h:
In this file, you'll see many flags that are labeled "// Unused Flag". Choose any flag that has this label past the temp flags and rename it to be "FLAG_STARTED_BOSS".
In src/battle_setup.c:
This code accounts for if the player loses a boss battle. I've added in a check to see if the player has lost a boss fight, and if so, it returns the player's items and berries.
In asm/marcos/event.inc:
This is all you need for the item balancing. At the end of the post, I'll show how to apply this code.
3. Pokemon Count Balancing
In every battle except the Champion battle, your opponent will never have a full team of Pokemon, whereas the player tends to have a full set of six Pokemon on their side. The following code evens the playing field, forcing the player to choose only a select few of their Pokemon for the coming battle.
In src/scrcmd.c:
Add this to the end:
These functions serve a few specific purposes. deletepokemon does as the name suggests: it deletes Pokemon from the player's party. This may sound like a terrible idea, but when used in conjunction with some other functions, you won't need to worry about wiping a player's team off of the face of Hoenn. To use this function, you give it the number of Pokemon that you want the player to have. For example, if you wanted to limit the player to using only 3 Pokemon, you'd give it 3. This function then will wipe out every Pokemon on the player's team except for the first 3. savepartofteam and loadpartofteam work together. savepartofteam saves the player's team, and loadpartofteam restores the player's party to whatever it was when savepartofteam was used. It is important not to get these confused with SavePlayerParty and LoadPlayerParty, which are already in the game's files. These functions will also be used, but they will serve a different purpose than savepartofteam and loadpartofteam.
In include/global.h:
This variable BossTeam holds the player's team after the boss fight. I'll explain why this is important later.
In asm/macros/event.inc:
Add this at the end:
This allows the previous functions to be used in scripts.
In include/constants/flags.h:
In this file, you'll see many flags that are labeled "// Unused Flag". Choose any flag that has this label past the temp flags and rename it to be "FLAG_STARTED_BOSS". If you already did this while setting up the Item Balancing, then skip this.
In src/battle_setup.c:
This code accounts for if the player loses a boss battle. The only thing I've done to this code is add a check to see if the player lost to a boss. If so, the game returns the player's Pokemon. This is the same code as for returning the player's items after a loss, but I added LoadPlayerParty().
Now it's time to show how to actually use all of this stuff. I'm going to apply this code to the Roxanne Gym Battle. This is in data/maps/RustboroCity_Gym/scripts.inc. Or you can just open up the script for RustboroCity_Gym in PoryMap:
In RustboroCity_Gym:
Let's break this down. In the first script, right before the battle begins, I set FLAG_STARTED_BOSS, used battleitemsetup, SavePlayerParty, deletepokemon, and giveitem, all in that exact order. Technically, you could set FLAG_STARTED_BOSS at any point before the battle, but the other four scripts needed to be put in this order, and here's why. battleitemsetup and SavePlayerParty are put first so that the player doesn't have any of their items or berries, and their original team composition is saved. This is necessary so that the player will only have their opponent's items, which is determined by passing TRAINER_ROXANNE_1 to the macro, and so the player doesn't permanently lose their Pokemon after deletepokemon does its thing. You'll also notice that there's a 3 next to deletepokemon. That's because I wanted the player to only have 3 Pokemon in the battle.
Moving on to the second script, again, right at the top, we've added some scripts. These also need to be put in basically the exact order as you see them here. Again, the clearing of FLAG_STARTED_BOSS can be put at any point in the order. First, savepartofteam saves the current team. The reason this is used rather than SavePlayerParty is because if we used SavePlayerParty again, we would overwrite the player's original team, wiping out those Pokemon forever. This is why we created BossTeam in global.h. savepartofteam saves the player's team in that variable, so it doesn't overwrite what SavePlayerParty saved. You may be wondering, "Why do we need savepartofteam at all? Can't we just use LoadPlayerParty and restore the player's team?" No, you can't. If one of the Pokemon had leveled up or consumed a held item, using LoadPlayerParty would undo both the level up and the consuming of the item. They would be exactly the same as they were before the battle. savepartofteam is used to account for this, and saves the team in a different variable than SavePlayerParty. Immediately after we use savepartofteam, we use LoadPlayerParty. This restores the entire team to exactly how they were before the battle. We then immediately use loadpartofteam after LoadPlayerParty. This restores the Pokemon that were used in the battle to the state they were in after the battle. We have now restored the player's team AND kept any changes that happened in the battle. GiveBackItemsAndBerries is used next, but it could have happened first if you wanted it to.
BE WARNED: This exact script layout is not all that safe to use, since it assumes that, when the player interacts with Roxanne, they are starting the first gym battle. If that isn't the case, the player will just lose their Pokemon and items.
Now, this does work, but how the script is right now, the player would have no idea that they would have limited items or Pokemon, and if the player talked to Roxanne after they had already won the battle, they would lose their Pokemon and items, and then won't get them back. It's not very user-friendly. If you add a Yes/No messagebox before you take away the player's items and Pokemon that tells them what to expect and allows them to say No so that they can reorganize their team, that would be more user-friendly, and give us an opportunity to avoid prematurely taking the player's mons and items. Here's my current collection of scripts for this boss fight:
This is added at the end:
With this layout, the game checks to see if the player has already gotten the Gym Badge from Roxanne yet. If they have, then the game will see if Roxanne is ready for a rematch, and if so, starts that battle. This script is only designed to limit Pokemon and items for the first Gym battle, not any of the rematches. If Roxanne is not ready for a rematch, it plays the normal post-battle text. If the player doesn't have the first Gym Badge, it jumps down to one of the scripts that I added, RoxanneNoBadge. It plays one of two different sets of text, depending on if this is the first time the player has talked to Roxanne or not. Both texts tell the player what to expect in this battle and ask if they are ready. If the player says no, a bit of text plays, and the script ends, allowing the player to move about freely. If they say yes, the script saves the player's team, and then limits the player's team to their first three Pokemon, takes away all of their items and berries, and gives the player Roxanne's items, which normally consists of two potions. If you wanted to just take away the player's items without giving any items back, you can replace battleitemsetup with
There you have it! With all three of these elements in play, you will have a much more challenging, but still fair, boss battle. You can also only use one or two of these elements, in case you find any one of them disagreeable. I hope you enjoy forcing your players to be more strategic and not grind for xp to breeze through your hacks!
1. Level Balancing
Spoiler:
Some people just want to grind xp until their Pokemon are strong enough to smite any foe they come across. Others accidentally level up their Pokemon a bit too much, making a battle far less challenging than they were hoping for. With level balancing, however, these issues are a thing of the past! With a bit of code from this post, you can make it so that every trainer's party will be roughly the same level as the player's party, no matter how strong the player's team is. If you wanted only certain trainers to get this dynamic leveling, all you have to do is make the following change. At every instance of this:
Code:
if (partyData[i].lvl >= dynamicLevel)
Code:
if (partyData[i].lvl >= dynamicLevel || (gTrainers[trainerNum].trainerClass != TRAINER_CLASS_PKMN_TRAINER_3 && gTrainers[trainerNum].trainerClass != TRAINER_CLASS_ELITE_FOUR && gTrainers[trainerNum].trainerClass != TRAINER_CLASS_CHAMPION && gTrainers[trainerNum].trainerClass != TRAINER_CLASS_LEADER))
2. Item Balancing
Spoiler:
I've noticed that, when I play a Pokemon game, I tend to rely on a lot of items on the harder battles. With the following code, however, I or any other player will be forced to strategize more. This code will cause the player to have the same items as they're opponent, making the battle a bit more fair.
The first bit of code you'll need is this:
In src/item.c:
Spoiler:
Code:
#include "data.h"
............................................
// EWRAM variables
EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0};
EWRAM_DATA u16 Items[BAG_ITEMS_COUNT][2] = {0};
EWRAM_DATA u16 Berries[BAG_BERRIES_COUNT][2] = {0};
Code:
void GivePlayerOpponentItems(void)
{
u8 i = 0;
u16 opponentId = gSpecialVar_Unused_0x8014;
while(gTrainers[opponentId].items[i])
{
u16 item = gTrainers[opponentId].items[i];
u8 pocket = ItemId_GetPocket(item) - 1;
if(CheckBagHasItem(item, 1))
{
u8 j;
u8 itemCount = ARRAY_COUNT(gBagPockets[pocket].itemSlots);
for(j = 0; j < itemCount; j++)
{
if(gBagPockets[pocket].itemSlots[j].itemId == item)
{
SetBagItemQuantity(&gBagPockets[pocket].itemSlots[j].quantity, GetBagItemQuantity(&gBagPockets[pocket].itemSlots[j].quantity) + 1);
break;
}
}
}
else
{
gBagPockets[pocket].itemSlots[i].itemId = item;
SetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity, 1);
}
i++;
}
}
void TakeAwayItemsAndBerries(void)
{
if(IsBagPocketNonEmpty(ITEMS_POCKET + 1))
{
u16 i;
for(i = 0; i < gBagPockets[ITEMS_POCKET].capacity; i++)
{
if(gBagPockets[ITEMS_POCKET].itemSlots[i].itemId != ITEM_NONE)
{
Items[i][0] = gBagPockets[ITEMS_POCKET].itemSlots[i].itemId;
Items[i][1] = GetBagItemQuantity(&gBagPockets[ITEMS_POCKET].itemSlots[i].quantity);
}
}
ClearItemSlots(gBagPockets[ITEMS_POCKET].itemSlots, gBagPockets[ITEMS_POCKET].capacity);
}
if(IsBagPocketNonEmpty(BERRIES_POCKET + 1))
{
u16 j;
for(j = 0; j < gBagPockets[BERRIES_POCKET].capacity; j++)
{
if(gBagPockets[BERRIES_POCKET].itemSlots[j].itemId != ITEM_NONE)
{
Berries[j][0] = gBagPockets[BERRIES_POCKET].itemSlots[j].itemId;
Berries[j][1] = GetBagItemQuantity(&gBagPockets[BERRIES_POCKET].itemSlots[j].quantity);
}
}
ClearItemSlots(gBagPockets[BERRIES_POCKET].itemSlots, gBagPockets[BERRIES_POCKET].capacity);
}
}
void GiveBackItemsAndBerries(void)
{
u16 i = 0;
while(Items[i][0])
{
gBagPockets[ITEMS_POCKET].itemSlots[i].itemId = Items[i][0];
SetBagItemQuantity(&gBagPockets[ITEMS_POCKET].itemSlots[i].quantity, Items[i][1]);
Items[i][0], Items[i][1] = 0;
i++;
}
i = 0;
while(Berries[i][0])
{
gBagPockets[BERRIES_POCKET].itemSlots[i].itemId = Berries[i][0];
SetBagItemQuantity(&gBagPockets[BERRIES_POCKET].itemSlots[i].quantity, Items[i][1]);
Berries[i][0], Berries[i][1] = 0;
i++;
}
}
In data/specials.inc:
Spoiler:
Add this at the end:
Code:
def_special TakeAwayItemsAndBerries
def_special GiveBackItemsAndBerries
In include/item.h:
Spoiler:
Add this at the end:
Code:
extern u16 Items[][2];
extern u16 Berries[][2];
void GiveBackItemsAndBerries(void);
In include/constants/flags.h:
Spoiler:
In this file, you'll see many flags that are labeled "// Unused Flag". Choose any flag that has this label past the temp flags and rename it to be "FLAG_STARTED_BOSS".
In src/battle_setup.c:
Spoiler:
Code:
#include "item.h"
....................
....................
....................
static void CB2_EndTrainerBattle(void)
{
if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE)
{
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
}
else if (IsPlayerDefeated(gBattleOutcome) == TRUE)
{
if (InBattlePyramid() || InTrainerHillChallenge())
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
else
{
if(FlagGet(FLAG_STARTED_BOSS))
{
FlagClear(FLAG_STARTED_BOSS);
GiveBackItemsAndBerries();
}
SetMainCallback2(CB2_WhiteOut);
}
}
else
{
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
if (!InBattlePyramid() && !InTrainerHillChallenge())
{
RegisterTrainerInMatchCall();
SetBattledTrainersFlags();
}
}
}
In asm/marcos/event.inc:
Spoiler:
Add this at the bottom.
This script simplifies the process of taking away the player's items and giving the player their opponent's items into a single macro.
Code:
.macro battleitemsetup opponent:req
callnative TakeAwayItemsAndBerries
setvar VAR_UNUSED_0x8014, \opponent
callnative GivePlayerOpponentItems
.endm
This is all you need for the item balancing. At the end of the post, I'll show how to apply this code.
3. Pokemon Count Balancing
Spoiler:
In every battle except the Champion battle, your opponent will never have a full team of Pokemon, whereas the player tends to have a full set of six Pokemon on their side. The following code evens the playing field, forcing the player to choose only a select few of their Pokemon for the coming battle.
In src/scrcmd.c:
Spoiler:
Code:
...........................................................
extern const u8 *gStdScripts[];
extern const u8 *gStdScripts_End[];
extern void ZeroMonData(struct Pokemon *); ← ← ← ← ←
Code:
void ScrCmd_deletepokemon(void)
{
u8 NumberDelete = gSpecialVar_0x8004;
u8 i;
for(i = 5; i >= NumberDelete; i--)
{
if(GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL))
ZeroMonData(&gPlayerParty[i]);
}
}
void ScrCmd_savepartofteam(void)
{
u8 i;
for (i = 0; i < PARTY_SIZE; i++)
gSaveBlock1Ptr->BossTeam[i] = gPlayerParty[i];
}
void ScrCmd_loadpartofteam(void)
{
u8 i;
for(i = 0; !GetMonData(gSaveBlock1Ptr->BossTeam[i], MON_DATA_SPECIES, NULL); i++)
gPlayerParty[i] = gSaveBlock1Ptr->BossTeam[i];
}
In include/global.h:
Spoiler:
Code:
struct SaveBlock1
{
..............
struct Pokemon BossTeam[PARTY_SIZE - 1];
// sizeof: 0x3???
};
In asm/macros/event.inc:
Spoiler:
Add this at the end:
Code:
.macro deletepokemon num:req
setvar VAR_0x8004, \num,
callnative ScrCmd_deletepokemon
.endm
.macro savepartofteam
callnative ScrCmd_savepartofteam
.endm
.macro loadpartofteam
callnative ScrCmd_loadpartofteam
.endm
In include/constants/flags.h:
Spoiler:
In this file, you'll see many flags that are labeled "// Unused Flag". Choose any flag that has this label past the temp flags and rename it to be "FLAG_STARTED_BOSS". If you already did this while setting up the Item Balancing, then skip this.
In src/battle_setup.c:
Spoiler:
Code:
#include "load_save.h"
..................
..................
..................
static void CB2_EndTrainerBattle(void)
{
if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE)
{
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
}
else if (IsPlayerDefeated(gBattleOutcome) == TRUE)
{
if (InBattlePyramid() || InTrainerHillChallenge())
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
else
{
if(FlagGet(FLAG_STARTED_BOSS))
{
FlagClear(FLAG_STARTED_BOSS);
LoadPlayerParty();
GiveBackItemsAndBerries();
}
SetMainCallback2(CB2_WhiteOut);
}
}
else
{
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
if (!InBattlePyramid() && !InTrainerHillChallenge())
{
RegisterTrainerInMatchCall();
SetBattledTrainersFlags();
}
}
}
Now it's time to show how to actually use all of this stuff. I'm going to apply this code to the Roxanne Gym Battle. This is in data/maps/RustboroCity_Gym/scripts.inc. Or you can just open up the script for RustboroCity_Gym in PoryMap:
Spoiler:
In RustboroCity_Gym:
Spoiler:
Code:
RustboroCity_Gym_EventScript_Roxanne:: @ 8212F31
setflag FLAG_STARTED_BOSS
battleitemsetup TRAINER_ROXANNE_1
special SavePlayerParty
deletepokemon 3
trainerbattle_single TRAINER_ROXANNE_1, RustboroCity_Gym_Text_RoxanneIntro, RustboroCity_Gym_Text_RoxanneDefeat, RustboroCity_Gym_EventScript_RoxanneDefeated, NO_MUSIC
specialvar VAR_RESULT, ShouldTryRematchBattle
compare VAR_RESULT, TRUE
goto_if_eq RustboroCity_Gym_EventScript_RoxanneRematch
goto_if_unset FLAG_RECEIVED_TM39, RustboroCity_Gym_EventScript_GiveRockTomb
msgbox RustboroCity_Gym_Text_RoxannePostBattle, MSGBOX_DEFAULT
release
end
RustboroCity_Gym_EventScript_RoxanneDefeated:: @ 8212F66
savepartofteam
special LoadPlayerParty
loadpartofteam
special GiveBackItemsAndBerries
clearflag FLAG_STARTED_BOSS
message RustboroCity_Gym_Text_ReceivedStoneBadge
waitmessage
call Common_EventScript_PlayGymBadgeFanfare
msgbox RustboroCity_Gym_Text_StoneBadgeInfoTakeThis, MSGBOX_DEFAULT
setflag FLAG_DEFEATED_RUSTBORO_GYM
setflag FLAG_BADGE01_GET
setvar VAR_RUSTBORO_CITY_STATE, 1
addvar VAR_PETALBURG_GYM_STATE, 1
setvar VAR_0x8008, 1
call Common_EventScript_SetGymTrainers
compare VAR_PETALBURG_GYM_STATE, 6
call_if_eq Common_EventScript_ReadyPetalburgGymForBattle
goto RustboroCity_Gym_EventScript_GiveRockTomb
end
Moving on to the second script, again, right at the top, we've added some scripts. These also need to be put in basically the exact order as you see them here. Again, the clearing of FLAG_STARTED_BOSS can be put at any point in the order. First, savepartofteam saves the current team. The reason this is used rather than SavePlayerParty is because if we used SavePlayerParty again, we would overwrite the player's original team, wiping out those Pokemon forever. This is why we created BossTeam in global.h. savepartofteam saves the player's team in that variable, so it doesn't overwrite what SavePlayerParty saved. You may be wondering, "Why do we need savepartofteam at all? Can't we just use LoadPlayerParty and restore the player's team?" No, you can't. If one of the Pokemon had leveled up or consumed a held item, using LoadPlayerParty would undo both the level up and the consuming of the item. They would be exactly the same as they were before the battle. savepartofteam is used to account for this, and saves the team in a different variable than SavePlayerParty. Immediately after we use savepartofteam, we use LoadPlayerParty. This restores the entire team to exactly how they were before the battle. We then immediately use loadpartofteam after LoadPlayerParty. This restores the Pokemon that were used in the battle to the state they were in after the battle. We have now restored the player's team AND kept any changes that happened in the battle. GiveBackItemsAndBerries is used next, but it could have happened first if you wanted it to.
BE WARNED: This exact script layout is not all that safe to use, since it assumes that, when the player interacts with Roxanne, they are starting the first gym battle. If that isn't the case, the player will just lose their Pokemon and items.
Now, this does work, but how the script is right now, the player would have no idea that they would have limited items or Pokemon, and if the player talked to Roxanne after they had already won the battle, they would lose their Pokemon and items, and then won't get them back. It's not very user-friendly. If you add a Yes/No messagebox before you take away the player's items and Pokemon that tells them what to expect and allows them to say No so that they can reorganize their team, that would be more user-friendly, and give us an opportunity to avoid prematurely taking the player's mons and items. Here's my current collection of scripts for this boss fight:
Spoiler:
Code:
RustboroCity_Gym_EventScript_Roxanne:: @ 8212F31
call_if_unset FLAG_BADGE01_GET, RustboroCity_Gym_EventScript_RoxanneNoBadge
clearflag FLAG_BOSS_TALK
trainerbattle_single TRAINER_ROXANNE_1, RustboroCity_Gym_Text_RoxanneIntro, RustboroCity_Gym_Text_RoxanneDefeat, RustboroCity_Gym_EventScript_RoxanneDefeated, NO_MUSIC
specialvar VAR_RESULT, ShouldTryRematchBattle
compare VAR_RESULT, TRUE
goto_if_eq RustboroCity_Gym_EventScript_RoxanneRematch
goto_if_unset FLAG_RECEIVED_TM39, RustboroCity_Gym_EventScript_GiveRockTomb
msgbox RustboroCity_Gym_Text_RoxannePostBattle, MSGBOX_DEFAULT
release
end
RustboroCity_Gym_EventScript_RoxanneDefeated:: @ 8212F66
message RustboroCity_Gym_Text_ReceivedStoneBadge
waitmessage
call Common_EventScript_PlayGymBadgeFanfare
msgbox RustboroCity_Gym_Text_StoneBadgeInfoTakeThis, MSGBOX_DEFAULT
setflag FLAG_DEFEATED_RUSTBORO_GYM
setflag FLAG_BADGE01_GET
setvar VAR_RUSTBORO_CITY_STATE, 1
addvar VAR_PETALBURG_GYM_STATE, 1
setvar VAR_0x8008, 1
call Common_EventScript_SetGymTrainers
compare VAR_PETALBURG_GYM_STATE, 6
call_if_eq Common_EventScript_ReadyPetalburgGymForBattle
goto RustboroCity_Gym_EventScript_GiveRockTomb
end
RustboroCity_Gym_EventScript_GiveRockTomb:: @ 8212FA4
giveitem ITEM_TM39
compare VAR_RESULT, 0
goto_if_eq Common_EventScript_ShowBagIsFull
setflag FLAG_RECEIVED_TM39
msgbox RustboroCity_Gym_Text_ExplainRockTomb, MSGBOX_DEFAULT
closemessage
savepartofteam
special LoadPlayerParty
loadpartofteam
special GiveBackItemsAndBerries
clearflag FLAG_STARTED_BOSS
release
end
.............................
RustboroCity_Gym_Text_RoxanneIntro:
.string "Would you kindly demonstrate how you\n"
.string "battle, and with which POKéMON?$"
Code:
RustboroCity_Gym_EventScript_NotReady::
msgbox Text_Prepare, MSGBOX_DEFAULT
closemessage
end
RustboroCity_Gym_EventScript_RoxanneNoBadge::
call_if_set FLAG_BOSS_TALK, RustboroCity_Gym_EventScript_RoxanneWarning
call_if_unset FLAG_BOSS_TALK, RustboroCity_Gym_EventScript_RoxanneWelcome
compare VAR_RESULT, NO
goto_if_eq RustboroCity_Gym_EventScript_NotReady
setflag FLAG_STARTED_BOSS
battleitemsetup TRAINER_ROXANNE_1
special SavePlayerParty
deletepokemon 3
return
RustboroCity_Gym_EventScript_RoxanneWelcome::
setflag FLAG_BOSS_TALK
msgbox Text_Welcome_Warning, MSGBOX_YESNO
return
RustboroCity_Gym_EventScript_RoxanneWarning::
msgbox Text_Warning, MSGBOX_YESNO
return
Text_Welcome_Warning: @ 821362A
.string "Hello, I am ROXANNE, the RUSTBORO\n"
.string "POKéMON GYM LEADER.\p"
.string "I became a GYM LEADER so that I might\n"
.string "apply what I learned at the POKéMON\l"
.string "TRAINER'S SCHOOL in battle.\p"
.string "In GYM battles, the number of POKéMON\n"
.string "that you may use will be limited.\p"
.string "You also only have access to the same\n"
.string "items that the GYM LEADER can use.\p"
.string "In this battle, you will only have\n"
.string "2 Potions and can only use 3 POKéMON.\p"
.string "Make sure that the 3 POKéMON you\n"
.string "choose are at the front of your team.\p"
.string "Are you ready to battle, or do you need\n"
.string "time to prepare?$"
Text_Warning:
.string "In this battle, you will only have\n"
.string "2 Potions and can only use 3 POKéMON.\p"
.string "Make sure that the 3 POKéMON you\n"
.string "choose are at the front of your team.\p"
.string "Are you ready to battle, or do you need\n"
.string "more time to prepare?$"
Text_Prepare:
.string "Then take your time and come back\n"
.string "when you are ready for battle.$"
special TakeAwayItemsAndBerries
. It sets FLAG_STARTED_BOSS and then goes back to the original script, where the battle begins. I decided to put the returning of the player's items and Pokemon in GiveRockTomb, but there was no reason I couldn't have just put it in RoxanneDefeated. I just wanted it to be the very last script that was run. If you want to use this exact collection of scripts, you'll need to go back to include/constanst/flags.h and add another flag called FLAG_BOSS_TALK over another unused flag, which is used to check if the player has already talked to the boss or not.
There you have it! With all three of these elements in play, you will have a much more challenging, but still fair, boss battle. You can also only use one or two of these elements, in case you find any one of them disagreeable. I hope you enjoy forcing your players to be more strategic and not grind for xp to breeze through your hacks!
Last edited: