summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/new_game.c5
-rw-r--r--src/roamer.c226
-rw-r--r--src/rom4.c13
-rw-r--r--src/wild_encounter.c9
4 files changed, 241 insertions, 12 deletions
diff --git a/src/new_game.c b/src/new_game.c
index e058280af..3b93d37cc 100644
--- a/src/new_game.c
+++ b/src/new_game.c
@@ -9,6 +9,7 @@
#include "pokedex.h"
#include "pokemon_size_record.h"
#include "rng.h"
+#include "roamer.h"
#include "rom4.h"
#include "rtc.h"
#include "script.h"
@@ -135,8 +136,8 @@ void NewGameInitData(void)
gPlayerPartyCount = 0;
ZeroPlayerPartyMons();
sub_80961D8();
- sub_81341F8();
- sub_813420C();
+ ClearRoamerData();
+ ClearRoamerLocationData();
gSaveBlock1.registeredItem = 0;
sub_80A3714();
NewGameInitPCItems();
diff --git a/src/roamer.c b/src/roamer.c
new file mode 100644
index 000000000..394f81c75
--- /dev/null
+++ b/src/roamer.c
@@ -0,0 +1,226 @@
+#include "global.h"
+#include "pokemon.h"
+#include "rng.h"
+#include "roamer.h"
+#include "species.h"
+
+#ifdef SAPPHIRE
+#define ROAMER_SPECIES SPECIES_LATIAS
+#else
+#define ROAMER_SPECIES SPECIES_LATIOS
+#endif
+
+enum
+{
+ MAP_GRP = 0, // map group
+ MAP_NUM = 1, // map number
+};
+
+EWRAM_DATA static u8 sLocationHistory[3][2] = {0};
+EWRAM_DATA static u8 sRoamerLocation[2] = {0};
+
+static const u8 sRoamerLocations[][6] =
+{
+ { 0x19, 0x1A, 0x20, 0x21, 0x31, 0xFF },
+ { 0x1A, 0x19, 0x20, 0x21, 0xFF, 0xFF },
+ { 0x20, 0x1A, 0x19, 0x21, 0xFF, 0xFF },
+ { 0x21, 0x20, 0x19, 0x1A, 0x22, 0x26 },
+ { 0x22, 0x21, 0x23, 0xFF, 0xFF, 0xFF },
+ { 0x23, 0x22, 0x24, 0xFF, 0xFF, 0xFF },
+ { 0x24, 0x23, 0x25, 0x26, 0xFF, 0xFF },
+ { 0x25, 0x24, 0x26, 0xFF, 0xFF, 0xFF },
+ { 0x26, 0x25, 0x21, 0xFF, 0xFF, 0xFF },
+ { 0x27, 0x24, 0x28, 0x29, 0xFF, 0xFF },
+ { 0x28, 0x27, 0x2A, 0xFF, 0xFF, 0xFF },
+ { 0x29, 0x27, 0x2A, 0xFF, 0xFF, 0xFF },
+ { 0x2A, 0x28, 0x29, 0x2B, 0xFF, 0xFF },
+ { 0x2B, 0x2A, 0x2C, 0xFF, 0xFF, 0xFF },
+ { 0x2C, 0x2B, 0x2D, 0xFF, 0xFF, 0xFF },
+ { 0x2D, 0x2C, 0x2E, 0xFF, 0xFF, 0xFF },
+ { 0x2E, 0x2D, 0x2F, 0xFF, 0xFF, 0xFF },
+ { 0x2F, 0x2E, 0x30, 0xFF, 0xFF, 0xFF },
+ { 0x30, 0x2F, 0x31, 0xFF, 0xFF, 0xFF },
+ { 0x31, 0x30, 0x19, 0xFF, 0xFF, 0xFF },
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
+};
+
+void ClearRoamerData(void)
+{
+ memset(&gSaveBlock1.roamer, 0, sizeof(gSaveBlock1.roamer));
+}
+
+void ClearRoamerLocationData(void)
+{
+ u8 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ sLocationHistory[i][MAP_GRP] = 0;
+ sLocationHistory[i][MAP_NUM] = 0;
+ }
+
+ sRoamerLocation[MAP_GRP] = 0;
+ sRoamerLocation[MAP_NUM] = 0;
+}
+
+void CreateInitialRoamerMon(void)
+{
+ struct Roamer *roamer;
+ CreateMon(&gEnemyParty[0], ROAMER_SPECIES, 40, 0x20, 0, 0, 0, 0);
+ roamer = &gSaveBlock1.roamer;
+ roamer->species = ROAMER_SPECIES;
+ 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] = 0;
+ sRoamerLocation[MAP_NUM] = sRoamerLocations[Random() % 20][0];
+}
+
+void InitRoamer(void)
+{
+ ClearRoamerData();
+ ClearRoamerLocationData();
+ CreateInitialRoamerMon();
+}
+
+void UpdateLocationHistoryForRoamer(void)
+{
+ sLocationHistory[2][MAP_GRP] = sLocationHistory[1][MAP_GRP];
+ sLocationHistory[2][MAP_NUM] = sLocationHistory[1][MAP_NUM];
+
+ sLocationHistory[1][MAP_GRP] = sLocationHistory[0][MAP_GRP];
+ sLocationHistory[1][MAP_NUM] = sLocationHistory[0][MAP_NUM];
+
+ sLocationHistory[0][MAP_GRP] = gSaveBlock1.location.mapGroup;
+ sLocationHistory[0][MAP_NUM] = gSaveBlock1.location.mapNum;
+}
+
+void RoamerMoveToOtherLocationSet(void)
+{
+ u8 val = 0;
+ struct Roamer *roamer = &gSaveBlock1.roamer;
+
+ if (!roamer->active)
+ return;
+
+ sRoamerLocation[MAP_GRP] = val;
+
+ while (1)
+ {
+ val = sRoamerLocations[Random() % 20][0];
+ if (sRoamerLocation[MAP_NUM] != val)
+ {
+ sRoamerLocation[MAP_NUM] = val;
+ return;
+ }
+ }
+}
+
+void RoamerMove(void)
+{
+ u8 locSet = 0;
+
+ if ((Random() % 16) == 0)
+ {
+ RoamerMoveToOtherLocationSet();
+ }
+ else
+ {
+ struct Roamer *roamer = &gSaveBlock1.roamer;
+
+ if (!roamer->active)
+ return;
+
+ while (locSet < 20)
+ {
+ if (sRoamerLocation[MAP_NUM] == sRoamerLocations[locSet][0])
+ {
+ u8 mapNum;
+ while (1)
+ {
+ mapNum = sRoamerLocations[locSet][(Random() % 5) + 1];
+ if (!(sLocationHistory[2][MAP_GRP] == 0 && sLocationHistory[2][MAP_NUM] == mapNum) && mapNum != 0xFF)
+ break;
+ }
+ sRoamerLocation[MAP_NUM] = mapNum;
+ return;
+ }
+ locSet++;
+ }
+ }
+}
+
+bool8 IsRoamerAt(u8 mapGroup, u8 mapNum)
+{
+ struct Roamer *roamer = &gSaveBlock1.roamer;
+
+ if (roamer->active && mapGroup == sRoamerLocation[MAP_GRP] && mapNum == sRoamerLocation[MAP_NUM])
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void CreateRoamerMonInstance(void)
+{
+ struct Pokemon *mon = &gEnemyParty[0];
+ struct Roamer *roamer = &gSaveBlock1.roamer;
+ CreateMonWithIVsPersonality(mon, roamer->species, roamer->level, roamer->ivs, roamer->personality);
+ SetMonData(mon, MON_DATA_STATUS, (u8 *)&roamer->status);
+ SetMonData(mon, MON_DATA_HP, (u8 *)&roamer->hp);
+ SetMonData(mon, MON_DATA_COOL, (u8 *)&roamer->cool);
+ SetMonData(mon, MON_DATA_BEAUTY, (u8 *)&roamer->beauty);
+ SetMonData(mon, MON_DATA_CUTE, (u8 *)&roamer->cute);
+ SetMonData(mon, MON_DATA_SMART, (u8 *)&roamer->smart);
+ SetMonData(mon, MON_DATA_TOUGH, (u8 *)&roamer->tough);
+}
+
+bool8 TryStartRoamerEncounter(void)
+{
+ if (IsRoamerAt(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum) == TRUE && (Random() % 4) == 0)
+ {
+ CreateRoamerMonInstance();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void UpdateRoamerHPStatus(struct Pokemon *mon)
+{
+ struct Roamer *roamer;
+ u16 hp;
+ u8 status;
+
+ hp = GetMonData(mon, MON_DATA_HP);
+
+ roamer = &gSaveBlock1.roamer;
+ roamer->hp = hp;
+
+ status = GetMonData(mon, MON_DATA_STATUS);
+
+ roamer->status = status;
+
+ RoamerMoveToOtherLocationSet();
+}
+
+void SetRoamerInactive(void)
+{
+ struct Roamer *roamer = &gSaveBlock1.roamer;
+ roamer->active = FALSE;
+}
+
+void GetRoamerLocation(u8 *mapGroup, u8 *mapNum)
+{
+ *mapGroup = sRoamerLocation[MAP_GRP];
+ *mapNum = sRoamerLocation[MAP_NUM];
+}
diff --git a/src/rom4.c b/src/rom4.c
index 39c182731..5beb698ab 100644
--- a/src/rom4.c
+++ b/src/rom4.c
@@ -25,6 +25,7 @@
#include "palette.h"
#include "play_time.h"
#include "rng.h"
+#include "roamer.h"
#include "safari_zone.h"
#include "script.h"
#include "script_pokemon_80C4.h"
@@ -164,8 +165,8 @@ void sub_805308C(void)
FlagReset(SYS_SAFARI_MODE);
sub_8054164();
ResetCyclingRoadChallengeData();
- mapnumbers_history_shift_sav1_0_2_4_out();
- sub_8134348();
+ UpdateLocationHistoryForRoamer();
+ RoamerMoveToOtherLocationSet();
}
void ResetGameStats(void)
@@ -531,8 +532,8 @@ void sub_80538F0(u8 mapGroup, u8 mapNum)
sub_807D874(i);
sub_8072ED0();
- mapnumbers_history_shift_sav1_0_2_4_out();
- sub_8134394();
+ UpdateLocationHistoryForRoamer();
+ RoamerMove();
DoCurrentWeather();
ResetFieldTasksArgs();
mapheader_run_script_with_tag_x5();
@@ -561,8 +562,8 @@ void sub_8053994(u32 a1)
sub_8053C98();
sav1_reset_battle_music_maybe();
mapheader_run_script_with_tag_x3();
- mapnumbers_history_shift_sav1_0_2_4_out();
- sub_8134348();
+ UpdateLocationHistoryForRoamer();
+ RoamerMoveToOtherLocationSet();
not_trainer_hill_battle_pyramid();
if (a1 != 1 && v3)
{
diff --git a/src/wild_encounter.c b/src/wild_encounter.c
index 408dc69ce..9dfcf0e5c 100644
--- a/src/wild_encounter.c
+++ b/src/wild_encounter.c
@@ -7,6 +7,7 @@
#include "field_player_avatar.h"
#include "metatile_behavior.h"
#include "rng.h"
+#include "roamer.h"
#include "rom4.h"
#include "safari_zone.h"
#include "script.h"
@@ -3323,7 +3324,7 @@ bool8 StandardWildEncounter(u16 a, u16 b)
if (DoWildEncounterTest(gWildMonHeaders[headerNum].landMonsInfo->encounterRate, 0) == TRUE)
{
- if (sub_81344CC() == TRUE)
+ if (TryStartRoamerEncounter() == TRUE)
{
roamer = &gSaveBlock1.roamer;
if (RepelCheck(roamer->level))
@@ -3357,7 +3358,7 @@ bool8 StandardWildEncounter(u16 a, u16 b)
if (DoWildEncounterTest(gWildMonHeaders[headerNum].waterMonsInfo->encounterRate, 0) == TRUE)
{
- if (sub_81344CC() == TRUE)
+ if (TryStartRoamerEncounter() == TRUE)
{
roamer = &gSaveBlock1.roamer;
if (RepelCheck(roamer->level))
@@ -3425,7 +3426,7 @@ bool8 SweetScentWildEncounter(void)
wildPokemonInfo = gWildMonHeaders[headerNum].landMonsInfo;
if (wildPokemonInfo == NULL)
return FALSE;
- if (sub_81344CC() == TRUE)
+ if (TryStartRoamerEncounter() == TRUE)
{
StartBattle_Roamer();
return TRUE;
@@ -3442,7 +3443,7 @@ bool8 SweetScentWildEncounter(void)
wildPokemonInfo = gWildMonHeaders[headerNum].waterMonsInfo;
if (wildPokemonInfo == NULL)
return FALSE;
- if (sub_81344CC() == TRUE)
+ if (TryStartRoamerEncounter() == TRUE)
{
StartBattle_Roamer();
return TRUE;