Add support for multiple roamers (#4762)

* Replicate initial commit

* Integrate the rest of Duke's vanilla commits

* Alter Roamer struct to add frostbite support

* Fix some indentation issues

* Add option to hide substitute followers

* Revert "Add option to hide substitute followers"

This reverts commit 3fadaafae5.

* Incorporate feedback
This commit is contained in:
Bassoonian 2024-06-15 11:17:32 +02:00 committed by GitHub
parent a118b2caa8
commit 22994c79d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 237 additions and 190 deletions

View file

@ -74,6 +74,7 @@
#define GIFT_RIBBONS_COUNT 11
#define SAVED_TRENDS_COUNT 5
#define PYRAMID_BAG_ITEMS_COUNT 10
#define ROAMER_COUNT 1 // Number of maximum concurrent active roamers
// Number of facilities for Ranking Hall.
// 7 facilities for single mode + tower double mode + tower multi mode.

View file

@ -600,14 +600,14 @@ struct Roamer
/*0x08*/ u16 species;
/*0x0A*/ u16 hp;
/*0x0C*/ u8 level;
/*0x0D*/ u8 status;
/*0x0E*/ u8 cool;
/*0x0F*/ u8 beauty;
/*0x10*/ u8 cute;
/*0x11*/ u8 smart;
/*0x12*/ u8 tough;
/*0x0D*/ u16 status;
/*0x0F*/ u8 cool;
/*0x10*/ u8 beauty;
/*0x11*/ u8 cute;
/*0x12*/ u8 smart;
/*0x13*/ bool8 active;
/*0x14*/ u8 filler[0x8];
/*0x14*/ u8 tough;
/*0x15*/ u8 filler[0x7];
};
struct RamScriptData
@ -1057,7 +1057,7 @@ struct SaveBlock1
/*0x31A8*/ u8 giftRibbons[GIFT_RIBBONS_COUNT];
/*0x31B3*/ struct ExternalEventData externalEventData;
/*0x31C7*/ struct ExternalEventFlags externalEventFlags;
/*0x31DC*/ struct Roamer roamer;
/*0x31DC*/ struct Roamer roamer[ROAMER_COUNT];
#if FREE_ENIGMA_BERRY == FALSE
/*0x31F8*/ struct EnigmaBerry enigmaBerry;
#endif //FREE_ENIGMA_BERRY

View file

@ -1,17 +1,21 @@
#ifndef GUARD_ROAMER_H
#define GUARD_ROAMER_H
void ClearRoamerData(void);
void ClearRoamerLocationData(void);
void DeactivateAllRoamers(void);
void InitRoamer(void);
void UpdateLocationHistoryForRoamer(void);
void RoamerMoveToOtherLocationSet(void);
void RoamerMove(void);
bool8 IsRoamerAt(u8 mapGroup, u8 mapNum);
void CreateRoamerMonInstance(void);
void RoamerMoveToOtherLocationSet(u32 roamerIndex);
void RoamerMove(u32 roamerIndex);
bool8 IsRoamerAt(u32 roamerIndex, u8 mapGroup, u8 mapNum);
void CreateRoamerMonInstance(u32 roamerIndex);
u8 TryStartRoamerEncounter(void);
void UpdateRoamerHPStatus(struct Pokemon *mon);
void SetRoamerInactive(void);
void GetRoamerLocation(u8 *mapGroup, u8 *mapNum);
void SetRoamerInactive(u32 roamerIndex);
void GetRoamerLocation(u32 roamerIndex, u8 *mapGroup, u8 *mapNum);
bool8 TryAddRoamer(u16 species, u8 level);
void MoveAllRoamersToOtherLocationSets(void);
void MoveAllRoamers(void);
extern u8 gEncounteredRoamerIndex;
#endif // GUARD_ROAMER_H

View file

@ -5657,7 +5657,7 @@ static void ReturnFromBattleToOverworld(void)
#else
if ((gBattleOutcome == B_OUTCOME_WON) || gBattleOutcome == B_OUTCOME_CAUGHT) // Bug: When Roar is used by roamer, gBattleOutcome is B_OUTCOME_PLAYER_TELEPORTED (5).
#endif // & with B_OUTCOME_WON (1) will return TRUE and deactivates the roamer.
SetRoamerInactive();
SetRoamerInactive(gEncounteredRoamerIndex);
}
m4aSongNumStop(SE_LOW_HEALTH);

View file

@ -181,8 +181,7 @@ void NewGameInitData(void)
gPlayerPartyCount = 0;
ZeroPlayerPartyMons();
ResetPokemonStorageSystem();
ClearRoamerData();
ClearRoamerLocationData();
DeactivateAllRoamers();
gSaveBlock1Ptr->registeredItem = ITEM_NONE;
ClearBag();
NewGameInitPCItems();

View file

@ -449,7 +449,7 @@ static void UpdateMiscOverworldStates(void)
ChooseAmbientCrySpecies();
ResetCyclingRoadChallengeData();
UpdateLocationHistoryForRoamer();
RoamerMoveToOtherLocationSet();
MoveAllRoamersToOtherLocationSets();
}
void ResetGameStats(void)
@ -847,7 +847,7 @@ if (I_VS_SEEKER_CHARGING != 0)
InitSecondaryTilesetAnimation();
UpdateLocationHistoryForRoamer();
RoamerMove();
MoveAllRoamers();
DoCurrentWeather();
ResetFieldTasksArgs();
RunOnResumeMapScript();
@ -906,7 +906,7 @@ if (I_VS_SEEKER_CHARGING != 0)
Overworld_ClearSavedMusic();
RunOnTransitionMapScript();
UpdateLocationHistoryForRoamer();
RoamerMoveToOtherLocationSet();
MoveAllRoamersToOtherLocationSets();
if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR)
InitBattlePyramidMap(FALSE);
else if (InTrainerHill())

View file

@ -252,72 +252,67 @@ static void FindMapsWithMon(u16 species)
if (sPokedexAreaScreen->alteringCaveId >= NUM_ALTERING_CAVE_TABLES)
sPokedexAreaScreen->alteringCaveId = 0;
roamer = &gSaveBlock1Ptr->roamer;
if (species != roamer->species)
sPokedexAreaScreen->numOverworldAreas = 0;
sPokedexAreaScreen->numSpecialAreas = 0;
// Check if this species should be hidden from the area map.
// This only applies to Wynaut, to hide the encounters on Mirage Island.
for (i = 0; i < ARRAY_COUNT(sSpeciesHiddenFromAreaScreen); i++)
{
sPokedexAreaScreen->numOverworldAreas = 0;
sPokedexAreaScreen->numSpecialAreas = 0;
if (sSpeciesHiddenFromAreaScreen[i] == species)
return;
}
// Check if this species should be hidden from the area map.
// This only applies to Wynaut, to hide the encounters on Mirage Island.
for (i = 0; i < ARRAY_COUNT(sSpeciesHiddenFromAreaScreen); i++)
// Add Pokémon with special encounter circumstances (i.e. not listed
// in the regular wild encounter table) to the area map.
// This only applies to Feebas on Route 119, but it was clearly set
// up to allow handling others.
for (i = 0; sFeebasData[i][0] != NUM_SPECIES; i++)
{
if (species == sFeebasData[i][0])
{
if (sSpeciesHiddenFromAreaScreen[i] == species)
return;
}
// Add Pokémon with special encounter circumstances (i.e. not listed
// in the regular wild encounter table) to the area map.
// This only applies to Feebas on Route 119, but it was clearly set
// up to allow handling others.
for (i = 0; sFeebasData[i][0] != NUM_SPECIES; i++)
{
if (species == sFeebasData[i][0])
switch (sFeebasData[i][1])
{
switch (sFeebasData[i][1])
{
case MAP_GROUP_TOWNS_AND_ROUTES:
SetAreaHasMon(sFeebasData[i][1], sFeebasData[i][2]);
break;
case MAP_GROUP_DUNGEONS:
case MAP_GROUP_SPECIAL_AREA:
SetSpecialMapHasMon(sFeebasData[i][1], sFeebasData[i][2]);
break;
}
}
}
// Add regular species to the area map
for (i = 0; gWildMonHeaders[i].mapGroup != MAP_GROUP(UNDEFINED); i++)
{
if (MapHasSpecies(&gWildMonHeaders[i], species))
{
switch (gWildMonHeaders[i].mapGroup)
{
case MAP_GROUP_TOWNS_AND_ROUTES:
SetAreaHasMon(gWildMonHeaders[i].mapGroup, gWildMonHeaders[i].mapNum);
break;
case MAP_GROUP_DUNGEONS:
case MAP_GROUP_SPECIAL_AREA:
SetSpecialMapHasMon(gWildMonHeaders[i].mapGroup, gWildMonHeaders[i].mapNum);
break;
}
case MAP_GROUP_TOWNS_AND_ROUTES:
SetAreaHasMon(sFeebasData[i][1], sFeebasData[i][2]);
break;
case MAP_GROUP_DUNGEONS:
case MAP_GROUP_SPECIAL_AREA:
SetSpecialMapHasMon(sFeebasData[i][1], sFeebasData[i][2]);
break;
}
}
}
else
// Add regular species to the area map
for (i = 0; gWildMonHeaders[i].mapGroup != MAP_GROUP(UNDEFINED); i++)
{
// This is the roamer's species, show where the roamer is currently
sPokedexAreaScreen->numSpecialAreas = 0;
if (roamer->active)
if (MapHasSpecies(&gWildMonHeaders[i], species))
{
GetRoamerLocation(&sPokedexAreaScreen->overworldAreasWithMons[0].mapGroup, &sPokedexAreaScreen->overworldAreasWithMons[0].mapNum);
sPokedexAreaScreen->overworldAreasWithMons[0].regionMapSectionId = Overworld_GetMapHeaderByGroupAndId(sPokedexAreaScreen->overworldAreasWithMons[0].mapGroup, sPokedexAreaScreen->overworldAreasWithMons[0].mapNum)->regionMapSectionId;
sPokedexAreaScreen->numOverworldAreas = 1;
switch (gWildMonHeaders[i].mapGroup)
{
case MAP_GROUP_TOWNS_AND_ROUTES:
SetAreaHasMon(gWildMonHeaders[i].mapGroup, gWildMonHeaders[i].mapNum);
break;
case MAP_GROUP_DUNGEONS:
case MAP_GROUP_SPECIAL_AREA:
SetSpecialMapHasMon(gWildMonHeaders[i].mapGroup, gWildMonHeaders[i].mapNum);
break;
}
}
else
}
// Add roamers to the area map
for (i = 0; i < ROAMER_COUNT; i++)
{
roamer = &gSaveBlock1Ptr->roamer[i];
if (species == roamer->species && roamer->active)
{
sPokedexAreaScreen->numOverworldAreas = 0;
// This is a roamer's species, show where this roamer is currently
struct OverworldArea *roamerLocation = &sPokedexAreaScreen->overworldAreasWithMons[sPokedexAreaScreen->numOverworldAreas];
GetRoamerLocation(i, &roamerLocation->mapGroup, &roamerLocation->mapNum);
roamerLocation->regionMapSectionId = Overworld_GetMapHeaderByGroupAndId(roamerLocation->mapGroup, roamerLocation->mapNum)->regionMapSectionId;
sPokedexAreaScreen->numOverworldAreas++;
}
}
}

View file

@ -14,9 +14,10 @@ enum
MAP_NUM, // map number
};
#define ROAMER (&gSaveBlock1Ptr->roamer)
EWRAM_DATA static u8 sLocationHistory[3][2] = {0};
EWRAM_DATA static u8 sRoamerLocation[2] = {0};
#define ROAMER(index) (&gSaveBlock1Ptr->roamer[index])
EWRAM_DATA static u8 sLocationHistory[ROAMER_COUNT][3][2] = {0};
EWRAM_DATA static u8 sRoamerLocation[ROAMER_COUNT][2] = {0};
EWRAM_DATA u8 gEncounteredRoamerIndex = 0;
#define ___ MAP_NUM(UNDEFINED) // For empty spots in the location table
@ -61,121 +62,165 @@ static const u8 sRoamerLocations[][6] =
#define NUM_LOCATION_SETS (ARRAY_COUNT(sRoamerLocations) - 1)
#define NUM_LOCATIONS_PER_SET (ARRAY_COUNT(sRoamerLocations[0]))
void ClearRoamerData(void)
void DeactivateAllRoamers(void)
{
memset(ROAMER, 0, sizeof(*ROAMER));
ROAMER->species = SPECIES_LATIAS;
u32 i;
for (i = 0; i < ROAMER_COUNT; i++)
SetRoamerInactive(i);
}
void ClearRoamerLocationData(void)
static void ClearRoamerLocationHistory(u32 roamerIndex)
{
u8 i;
u32 i;
for (i = 0; i < ARRAY_COUNT(sLocationHistory); i++)
for (i = 0; i < ARRAY_COUNT(sLocationHistory[roamerIndex]); i++)
{
sLocationHistory[i][MAP_GRP] = 0;
sLocationHistory[i][MAP_NUM] = 0;
sLocationHistory[roamerIndex][i][MAP_GRP] = 0;
sLocationHistory[roamerIndex][i][MAP_NUM] = 0;
}
}
void MoveAllRoamersToOtherLocationSets(void)
{
u32 i;
for (i = 0; i < ROAMER_COUNT; i++)
RoamerMoveToOtherLocationSet(i);
}
void MoveAllRoamers(void)
{
u32 i;
for (i = 0; i < ROAMER_COUNT; i++)
RoamerMove(i);
}
static void CreateInitialRoamerMon(u8 index, u16 species, u8 level)
{
ClearRoamerLocationHistory(index);
CreateMon(&gEnemyParty[0], species, level, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0);
ROAMER(index)->ivs = GetMonData(&gEnemyParty[0], MON_DATA_IVS);
ROAMER(index)->personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY);
ROAMER(index)->species = species;
ROAMER(index)->level = level;
ROAMER(index)->status = 0;
ROAMER(index)->hp = GetMonData(&gEnemyParty[0], MON_DATA_MAX_HP);
ROAMER(index)->cool = GetMonData(&gEnemyParty[0], MON_DATA_COOL);
ROAMER(index)->beauty = GetMonData(&gEnemyParty[0], MON_DATA_BEAUTY);
ROAMER(index)->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE);
ROAMER(index)->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART);
ROAMER(index)->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH);
ROAMER(index)->active = TRUE;
sRoamerLocation[index][MAP_GRP] = ROAMER_MAP_GROUP;
sRoamerLocation[index][MAP_NUM] = sRoamerLocations[Random() % NUM_LOCATION_SETS][0];
}
static u8 GetFirstInactiveRoamerIndex(void)
{
u32 i;
for (i = 0; i < ROAMER_COUNT; i++)
{
if (!ROAMER(i)->active)
return i;
}
return ROAMER_COUNT;
}
bool8 TryAddRoamer(u16 species, u8 level)
{
u8 index = GetFirstInactiveRoamerIndex();
if (index < ROAMER_COUNT)
{
// Create the roamer and stop searching
CreateInitialRoamerMon(index, species, level);
return TRUE;
}
sRoamerLocation[MAP_GRP] = 0;
sRoamerLocation[MAP_NUM] = 0;
}
static void CreateInitialRoamerMon(bool16 createLatios)
{
if (!createLatios)
ROAMER->species = SPECIES_LATIAS;
else
ROAMER->species = SPECIES_LATIOS;
CreateMon(&gEnemyParty[0], ROAMER->species, 40, USE_RANDOM_IVS, FALSE, 0, OT_ID_PLAYER_ID, 0);
ROAMER->level = 40;
ROAMER->status = 0;
ROAMER->active = TRUE;
ROAMER->ivs = GetMonData(&gEnemyParty[0], MON_DATA_IVS);
ROAMER->personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY);
ROAMER->hp = GetMonData(&gEnemyParty[0], MON_DATA_MAX_HP);
ROAMER->cool = GetMonData(&gEnemyParty[0], MON_DATA_COOL);
ROAMER->beauty = GetMonData(&gEnemyParty[0], MON_DATA_BEAUTY);
ROAMER->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE);
ROAMER->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART);
ROAMER->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH);
sRoamerLocation[MAP_GRP] = ROAMER_MAP_GROUP;
sRoamerLocation[MAP_NUM] = sRoamerLocations[Random() % NUM_LOCATION_SETS][0];
// Maximum active roamers found: do nothing and let the calling function know
return FALSE;
}
// gSpecialVar_0x8004 here corresponds to the options in the multichoice MULTI_TV_LATI (0 for 'Red', 1 for 'Blue')
void InitRoamer(void)
{
ClearRoamerData();
ClearRoamerLocationData();
CreateInitialRoamerMon(gSpecialVar_0x8004);
if (gSpecialVar_0x8004 == 0) // Red
TryAddRoamer(SPECIES_LATIAS, 40);
else
TryAddRoamer(SPECIES_LATIOS, 40);
}
void UpdateLocationHistoryForRoamer(void)
{
sLocationHistory[2][MAP_GRP] = sLocationHistory[1][MAP_GRP];
sLocationHistory[2][MAP_NUM] = sLocationHistory[1][MAP_NUM];
u32 i;
sLocationHistory[1][MAP_GRP] = sLocationHistory[0][MAP_GRP];
sLocationHistory[1][MAP_NUM] = sLocationHistory[0][MAP_NUM];
sLocationHistory[0][MAP_GRP] = gSaveBlock1Ptr->location.mapGroup;
sLocationHistory[0][MAP_NUM] = gSaveBlock1Ptr->location.mapNum;
}
void RoamerMoveToOtherLocationSet(void)
{
u8 mapNum = 0;
if (!ROAMER->active)
return;
sRoamerLocation[MAP_GRP] = ROAMER_MAP_GROUP;
// Choose a location set that starts with a map
// different from the roamer's current map
while (1)
for (i = 0; i < ROAMER_COUNT; i++)
{
mapNum = sRoamerLocations[Random() % NUM_LOCATION_SETS][0];
if (sRoamerLocation[MAP_NUM] != mapNum)
{
sRoamerLocation[MAP_NUM] = mapNum;
return;
}
sLocationHistory[i][2][MAP_GRP] = sLocationHistory[i][1][MAP_GRP];
sLocationHistory[i][2][MAP_NUM] = sLocationHistory[i][1][MAP_NUM];
sLocationHistory[i][1][MAP_GRP] = sLocationHistory[i][0][MAP_GRP];
sLocationHistory[i][1][MAP_NUM] = sLocationHistory[i][0][MAP_NUM];
sLocationHistory[i][0][MAP_GRP] = gSaveBlock1Ptr->location.mapGroup;
sLocationHistory[i][0][MAP_NUM] = gSaveBlock1Ptr->location.mapNum;
}
}
void RoamerMove(void)
void RoamerMoveToOtherLocationSet(u32 roamerIndex)
{
u8 mapNum = 0;
if (!ROAMER(roamerIndex)->active)
return;
sRoamerLocation[roamerIndex][MAP_GRP] = ROAMER_MAP_GROUP;
// Choose a location set that starts with a map
// different from the roamer's current map
do
{
mapNum = sRoamerLocations[Random() % NUM_LOCATION_SETS][0];
if (sRoamerLocation[roamerIndex][MAP_NUM] != mapNum)
{
sRoamerLocation[roamerIndex][MAP_NUM] = mapNum;
return;
}
} while (sRoamerLocation[roamerIndex][MAP_NUM] == mapNum);
sRoamerLocation[roamerIndex][MAP_NUM] = mapNum;
}
void RoamerMove(u32 roamerIndex)
{
u8 locSet = 0;
if ((Random() % 16) == 0)
{
RoamerMoveToOtherLocationSet();
RoamerMoveToOtherLocationSet(roamerIndex);
}
else
{
if (!ROAMER->active)
if (!ROAMER(roamerIndex)->active)
return;
while (locSet < NUM_LOCATION_SETS)
{
// Find the location set that starts with the roamer's current map
if (sRoamerLocation[MAP_NUM] == sRoamerLocations[locSet][0])
if (sRoamerLocation[roamerIndex][MAP_NUM] == sRoamerLocations[locSet][0])
{
u8 mapNum;
while (1)
// Choose a new map (excluding the first) within this set
// Also exclude a map if the roamer was there 2 moves ago
do
{
// Choose a new map (excluding the first) within this set
// Also exclude a map if the roamer was there 2 moves ago
mapNum = sRoamerLocations[locSet][(Random() % (NUM_LOCATIONS_PER_SET - 1)) + 1];
if (!(sLocationHistory[2][MAP_GRP] == ROAMER_MAP_GROUP
&& sLocationHistory[2][MAP_NUM] == mapNum)
&& mapNum != MAP_NUM(UNDEFINED))
break;
}
sRoamerLocation[MAP_NUM] = mapNum;
} while ((sLocationHistory[roamerIndex][2][MAP_GRP] == ROAMER_MAP_GROUP
&& sLocationHistory[roamerIndex][2][MAP_NUM] == mapNum)
|| mapNum == MAP_NUM(UNDEFINED));
sRoamerLocation[roamerIndex][MAP_NUM] = mapNum;
return;
}
locSet++;
@ -183,64 +228,67 @@ void RoamerMove(void)
}
}
bool8 IsRoamerAt(u8 mapGroup, u8 mapNum)
bool8 IsRoamerAt(u32 roamerIndex, u8 mapGroup, u8 mapNum)
{
if (ROAMER->active && mapGroup == sRoamerLocation[MAP_GRP] && mapNum == sRoamerLocation[MAP_NUM])
if (ROAMER(roamerIndex)->active && mapGroup == sRoamerLocation[roamerIndex][MAP_GRP] && mapNum == sRoamerLocation[roamerIndex][MAP_NUM])
return TRUE;
else
return FALSE;
}
void CreateRoamerMonInstance(void)
void CreateRoamerMonInstance(u32 roamerIndex)
{
u32 status;
struct Pokemon *mon = &gEnemyParty[0];
ZeroEnemyPartyMons();
CreateMonWithIVsPersonality(mon, ROAMER->species, ROAMER->level, ROAMER->ivs, ROAMER->personality);
// The roamer's status field is u8, but SetMonData expects status to be u32, so will set the roamer's status
// using the status field and the following 3 bytes (cool, beauty, and cute).
CreateMonWithIVsPersonality(mon, ROAMER(roamerIndex)->species, ROAMER(roamerIndex)->level, ROAMER(roamerIndex)->ivs, ROAMER(roamerIndex)->personality);
// The roamer's status field is u16, but SetMonData expects status to be u32, so will set the roamer's status
// using the status field and the following 3 bytes (cool, beauty, and cute).
#ifdef BUGFIX
status = ROAMER->status;
status = ROAMER(roamerIndex)->status;
SetMonData(mon, MON_DATA_STATUS, &status);
#else
SetMonData(mon, MON_DATA_STATUS, &ROAMER->status);
#endif
SetMonData(mon, MON_DATA_HP, &ROAMER->hp);
SetMonData(mon, MON_DATA_COOL, &ROAMER->cool);
SetMonData(mon, MON_DATA_BEAUTY, &ROAMER->beauty);
SetMonData(mon, MON_DATA_CUTE, &ROAMER->cute);
SetMonData(mon, MON_DATA_SMART, &ROAMER->smart);
SetMonData(mon, MON_DATA_TOUGH, &ROAMER->tough);
SetMonData(mon, MON_DATA_HP, &ROAMER(roamerIndex)->hp);
SetMonData(mon, MON_DATA_COOL, &ROAMER(roamerIndex)->cool);
SetMonData(mon, MON_DATA_BEAUTY, &ROAMER(roamerIndex)->beauty);
SetMonData(mon, MON_DATA_CUTE, &ROAMER(roamerIndex)->cute);
SetMonData(mon, MON_DATA_SMART, &ROAMER(roamerIndex)->smart);
SetMonData(mon, MON_DATA_TOUGH, &ROAMER(roamerIndex)->tough);
}
bool8 TryStartRoamerEncounter(void)
{
if (IsRoamerAt(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum) == TRUE && (Random() % 4) == 0)
u32 i;
for (i = 0; i < ROAMER_COUNT; i++)
{
CreateRoamerMonInstance();
return TRUE;
}
else
{
return FALSE;
if (IsRoamerAt(i, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum) == TRUE && (Random() % 4) == 0)
{
CreateRoamerMonInstance(i);
gEncounteredRoamerIndex = i;
return TRUE;
}
}
return FALSE;
}
void UpdateRoamerHPStatus(struct Pokemon *mon)
{
ROAMER->hp = GetMonData(mon, MON_DATA_HP);
ROAMER->status = GetMonData(mon, MON_DATA_STATUS);
ROAMER(gEncounteredRoamerIndex)->hp = GetMonData(mon, MON_DATA_HP);
ROAMER(gEncounteredRoamerIndex)->status = GetMonData(mon, MON_DATA_STATUS);
RoamerMoveToOtherLocationSet();
RoamerMoveToOtherLocationSet(gEncounteredRoamerIndex);
}
void SetRoamerInactive(void)
void SetRoamerInactive(u32 roamerIndex)
{
ROAMER->active = FALSE;
ROAMER(roamerIndex)->active = FALSE;
}
void GetRoamerLocation(u8 *mapGroup, u8 *mapNum)
void GetRoamerLocation(u32 roamerIndex, u8 *mapGroup, u8 *mapNum)
{
*mapGroup = sRoamerLocation[MAP_GRP];
*mapNum = sRoamerLocation[MAP_NUM];
*mapGroup = sRoamerLocation[roamerIndex][MAP_GRP];
*mapNum = sRoamerLocation[roamerIndex][MAP_NUM];
}

View file

@ -680,9 +680,9 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
else if (WildEncounterCheck(gWildMonHeaders[headerId].landMonsInfo->encounterRate, FALSE) != TRUE)
return FALSE;
if (TryStartRoamerEncounter() == TRUE)
if (TryStartRoamerEncounter())
{
roamer = &gSaveBlock1Ptr->roamer;
roamer = &gSaveBlock1Ptr->roamer[gEncounteredRoamerIndex];
if (!IsWildLevelAllowedByRepel(roamer->level))
return FALSE;
@ -729,9 +729,9 @@ bool8 StandardWildEncounter(u16 curMetatileBehavior, u16 prevMetatileBehavior)
else if (WildEncounterCheck(gWildMonHeaders[headerId].waterMonsInfo->encounterRate, FALSE) != TRUE)
return FALSE;
if (TryStartRoamerEncounter() == TRUE)
if (TryStartRoamerEncounter())
{
roamer = &gSaveBlock1Ptr->roamer;
roamer = &gSaveBlock1Ptr->roamer[gEncounteredRoamerIndex];
if (!IsWildLevelAllowedByRepel(roamer->level))
return FALSE;
@ -831,7 +831,7 @@ bool8 SweetScentWildEncounter(void)
if (gWildMonHeaders[headerId].landMonsInfo == NULL)
return FALSE;
if (TryStartRoamerEncounter() == TRUE)
if (TryStartRoamerEncounter())
{
BattleSetup_StartRoamerBattle();
return TRUE;
@ -852,7 +852,7 @@ bool8 SweetScentWildEncounter(void)
if (gWildMonHeaders[headerId].waterMonsInfo == NULL)
return FALSE;
if (TryStartRoamerEncounter() == TRUE)
if (TryStartRoamerEncounter())
{
BattleSetup_StartRoamerBattle();
return TRUE;