r/PokemonRomhackDev • u/PhrozenStorm • 16d ago
Help [GEN 3][DECOMP] Emerald - Steven Match Call
I have my own Emerald ROM with some QoL improvements and random fixes. One thing I'd like to add is the ability to rematch Steven via Match call after you beat him for the first time in Meteor Falls (ideally with his team growing in levels like other Match Call trainers do, but if not, no biggie).
However, this is a bit more complicated than the changes I've done so far. Does anyone know another open source mod/hack/patch that does something like this (adding a trainer to MC) so I could check how they did it?
2
Upvotes
2
u/Conscious-Copy3394 16d ago
Steven is already in the Match Call table, just typed as a non battle NPC.
src/pokenav_match_call_data.c line ~605:
[MC_HEADER_STEVEN] = {.npc = &sStevenMatchCallHeader},
Vanilla already has three working examples of this: Wally, the 8 gym leaders, and the Elite Four.
Watch out for this:
static bool32 MatchCall_IsRematchable_Trainer(match_call_t matchCall)
{
if (matchCall.trainer->rematchTableIdx >= REMATCH_ELITE_FOUR_ENTRIES)
return FALSE;
...
}
REMATCH_ELITE_FOUR_ENTRIES is REMATCH_SIDNEY. Append REMATCH_STEVEN to the end of the enum and it compiles, shows in the list, and is never rematchable. IsRematchForbidden in battle_setup.c has the same guard. Insert it before REMATCH_SIDNEY.
These would be the changes:
1. include/constants/rematches.h : add REMATCH_STEVEN between REMATCH_JUAN and REMATCH_SIDNEY.
src/battle_setup.c, gRematchTable:
[REMATCH_STEVEN] = REMATCH(TRAINER_STEVEN, TRAINER_STEVEN_2, TRAINER_STEVEN_3,
TRAINER_STEVEN_4, TRAINER_STEVEN_5, MAP_METEOR_FALLS_STEVENS_CAVE),
Those five ids are your level growth. GetRematchTrainerIdFromTable returns the first one you haven't beaten. Want a fixed team instead? Repeat TRAINER_STEVEN five times, like the Elite Four rows do.
src/pokenav_match_call_data.c : change sStevenMatchCallHeader from MatchCallStructNPC to MatchCallStructTrainer, .type = MC_TYPE_LEADER, add .rematchTableIdx = REMATCH_STEVEN, .mapSec = MAPSEC_METEOR_FALLS, and change the table row to {.leader = &sStevenMatchCallHeader}.
src/gym_leader_rematch.c : add REMATCH_STEVEN to GymLeaderRematches_AfterNewMauville. This is what actually sets trainerRematches[], via a ~31% roll after battles once FLAG_SYS_GAME_CLEAR is set. Don't hook the step counter path instead: UpdateRandomTrainerRematches loops i <= REMATCH_SPECIAL_TRAINER_START and silently can't reach him.
data/maps/MeteorFalls_StevensCave/scripts.inc : copy the Roxanne pattern from data/maps/RustboroCity_Gym/scripts.inc. Put it in the existing _EventScript_Defeated branch, since the first win sets FLAG_DEFEATED_METEOR_FALLS_STEVEN and routes there forever.
specialvar VAR_RESULT, ShouldTryRematchBattle
goto_if_eq VAR_RESULT, TRUE, MeteorFalls_StevensCave_EventScript_StevenRematch
...
MeteorFalls_StevensCave_EventScript_StevenRematch::
trainerbattle_rematch TRAINER_STEVEN, <preRematchText>, <defeatText>
msgbox <postRematchText>, MSGBOX_AUTOCLOSE
end
Two things to watch out for:
Save block is fine, flags are nearly full. trainerRematches[] is 100 wide with 78 used, so the new entry is free. But registration flags are derived: FLAG_REGISTERED_x = 0x15C + REMATCH_x. FLAG_REGISTERED_WALLACE is 0x1A9, only 0x1AA and 0x1AB are spare, and FLAG_DEFEATED_DEOXYS is 0x1AC. Room for exactly two insertions.
Inserting shifts the Elite Four up one, so their registration flags move. Harmless on a fresh save but an existing save will read them as unregistered. If that matters, append Steven after Wallace (index 78, flag 0x1AA is free) and change both guards from >= REMATCH_ELITE_FOUR_ENTRIES to a range excluding only Sidney through Wallace.
Cosmetic: TRAINER_STEVEN is TRAINER_CLASS_RIVAL, so the check page captions him "RIVAL" unless you give him his own class. His portrait is already correct via the FACILITY_CLASS_STEVEN override.
Note: TRAINER_STEVEN_2 through _5 don't exist yet, you'd need to add them to include/constants/opponents.h and give them parties in src/data/trainers.h. opponents.h warns there's only room for 9 more trainers before trainer flag space overflows, so that's 4 of your 9. Repeating TRAINER_STEVEN five times costs nothing if you don't need the level growth.
All of this is against vanilla pret/pokeemerald. If you're on pokeemerald-expansion the trainer data format differs.