diff --git a/include/constants/global.h b/include/constants/global.h index cd0f1b471529..f389c44d53be 100644 --- a/include/constants/global.h +++ b/include/constants/global.h @@ -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. diff --git a/include/global.h b/include/global.h index f5834e9e75e5..a2ff87651ed4 100644 --- a/include/global.h +++ b/include/global.h @@ -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 diff --git a/include/roamer.h b/include/roamer.h index ba1b09b54dac..36e9f1400012 100644 --- a/include/roamer.h +++ b/include/roamer.h @@ -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 diff --git a/src/battle_main.c b/src/battle_main.c index 3168b95b3a90..9e6993c5413f 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5655,7 +5655,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); diff --git a/src/new_game.c b/src/new_game.c index ece85ac544dc..783c6893c8d0 100644 --- a/src/new_game.c +++ b/src/new_game.c @@ -181,8 +181,7 @@ void NewGameInitData(void) gPlayerPartyCount = 0; ZeroPlayerPartyMons(); ResetPokemonStorageSystem(); - ClearRoamerData(); - ClearRoamerLocationData(); + DeactivateAllRoamers(); gSaveBlock1Ptr->registeredItem = ITEM_NONE; ClearBag(); NewGameInitPCItems(); diff --git a/src/overworld.c b/src/overworld.c index 15f0c1081240..ca5a268a82c4 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -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()) diff --git a/src/pokedex_area_screen.c b/src/pokedex_area_screen.c index 1c155bf5ec4f..a3bbafa92632 100755 --- a/src/pokedex_area_screen.c +++ b/src/pokedex_area_screen.c @@ -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; + 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++) - { - 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++) + { + 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++) + // 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 (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; - } + 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++) + // Add regular species to the area map + for (i = 0; gWildMonHeaders[i].mapGroup != MAP_GROUP(UNDEFINED); i++) + { + if (MapHasSpecies(&gWildMonHeaders[i], species)) { - if (MapHasSpecies(&gWildMonHeaders[i], species)) + switch (gWildMonHeaders[i].mapGroup) { - 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(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++) { - // This is the roamer's species, show where the roamer is currently - sPokedexAreaScreen->numSpecialAreas = 0; - if (roamer->active) - { - 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; - } - else + 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++; } } } diff --git a/src/roamer.c b/src/roamer.c index e9dc72a99383..7940c4b49bdf 100644 --- a/src/roamer.c +++ b/src/roamer.c @@ -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; } +} - sRoamerLocation[MAP_GRP] = 0; - sRoamerLocation[MAP_NUM] = 0; +void MoveAllRoamersToOtherLocationSets(void) +{ + u32 i; + + for (i = 0; i < ROAMER_COUNT; i++) + RoamerMoveToOtherLocationSet(i); } -static void CreateInitialRoamerMon(bool16 createLatios) +void MoveAllRoamers(void) { - 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]; + 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; + } + + // 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; + + for (i = 0; i < ROAMER_COUNT; i++) + { + sLocationHistory[i][2][MAP_GRP] = sLocationHistory[i][1][MAP_GRP]; + sLocationHistory[i][2][MAP_NUM] = sLocationHistory[i][1][MAP_NUM]; - sLocationHistory[1][MAP_GRP] = sLocationHistory[0][MAP_GRP]; - sLocationHistory[1][MAP_NUM] = sLocationHistory[0][MAP_NUM]; + sLocationHistory[i][1][MAP_GRP] = sLocationHistory[i][0][MAP_GRP]; + sLocationHistory[i][1][MAP_NUM] = sLocationHistory[i][0][MAP_NUM]; - sLocationHistory[0][MAP_GRP] = gSaveBlock1Ptr->location.mapGroup; - sLocationHistory[0][MAP_NUM] = gSaveBlock1Ptr->location.mapNum; + sLocationHistory[i][0][MAP_GRP] = gSaveBlock1Ptr->location.mapGroup; + sLocationHistory[i][0][MAP_NUM] = gSaveBlock1Ptr->location.mapNum; + } } -void RoamerMoveToOtherLocationSet(void) +void RoamerMoveToOtherLocationSet(u32 roamerIndex) { u8 mapNum = 0; - if (!ROAMER->active) + if (!ROAMER(roamerIndex)->active) return; - sRoamerLocation[MAP_GRP] = ROAMER_MAP_GROUP; + sRoamerLocation[roamerIndex][MAP_GRP] = ROAMER_MAP_GROUP; // Choose a location set that starts with a map // different from the roamer's current map - while (1) + do { mapNum = sRoamerLocations[Random() % NUM_LOCATION_SETS][0]; - if (sRoamerLocation[MAP_NUM] != mapNum) + if (sRoamerLocation[roamerIndex][MAP_NUM] != mapNum) { - sRoamerLocation[MAP_NUM] = mapNum; + sRoamerLocation[roamerIndex][MAP_NUM] = mapNum; return; } - } + } while (sRoamerLocation[roamerIndex][MAP_NUM] == mapNum); + sRoamerLocation[roamerIndex][MAP_NUM] = mapNum; } -void RoamerMove(void) +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) - { - CreateRoamerMonInstance(); - return TRUE; - } - else + u32 i; + + for (i = 0; i < ROAMER_COUNT; i++) { - 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]; } diff --git a/src/wild_encounter.c b/src/wild_encounter.c index f42513cf66e0..273f9f312a7d 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -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;