Updated Adding Time Based Encounters with a Variable (markdown)

Iceman8911 2023-03-01 14:19:02 +01:00
parent 9666bcc55f
commit f6c9add26e
1 changed files with 80 additions and 4 deletions

@ -1,8 +1,13 @@
# Adding Time Based Encounters
In this tutorial, I'll be focusing on 4 encounter periods i.e Morning, Afternoon, Evening and Night.
You can do literally as much as you wish once you get the basics down, besides you can use this for other special encounter conditions such as weather.
Note that this isn't my idea, its based off the work of [Martyk](https://www.pokecommunity.com/showthread.php?p=10450677#post10450677) and [AmbientDinosaur](https://www.pokecommunity.com/showpost.php?p=10315616&postcount=236).
***
## Contents
* [Using a Variable](#using-a-variable)
* [Without a Variable](#without-a-variable)
***
## Using a Variable
Firstly, we'll need a way to keep track of what time period it is. We can make a function called **SetTimeBasedEncounters()** and use a variable (you can use any unused variable in _include/constants/vars.h_, I've renamed one of them to **VAR_TIME_BASED_ENCOUNTER**) for that:
#include "rtc.h"
@ -31,13 +36,15 @@ Paste that into a file like _src/script.c_.
**RtcCalcLocalTime()** calculates and stores the real time in **gLocalTime** while the remaining conditionals set the variable to a number depending on whether the time is between 6am - 8:59am, 9am - 17:59am, 18am - 20:59am, and the last time period (21:00am - 5:59am) which is night (You can edit the time periods as you wish). We are going to use this variable later.
Next, we'll want to make our new encounter groups. This can be done by going to PoryMap then clicking "Wild Pokemon" in the second highest bar, and then clicking the "+" button. Say, you're working with route 101, you could have your encounter groups as _gRoute101_Morning_, _gRoute101_Afternoon_, _gRoute101_Evening_, _gRoute101_Night_. Now add all the mons you want and then we can move on to the fun part :).
### Prepare your encounter groups.
This can be done by going to PoryMap then clicking "Wild Pokemon" in the second highest bar, and then clicking the "+" button. Say, you're working with route 101, you could have your encounter groups as _gRoute101_Morning_, _gRoute101_Afternoon_, _gRoute101_Evening_, _gRoute101_Night_. Now add all the mons you want and then we can move on to the fun part :).
All the encounter groups (note that an encounter group can have up to 5 encounter tables i.e land, water, fishing, rock smash, and hidden) are arranged in C format in _src/data/wild_encounters.h_ from _src/data/wild_encounters.json_ during compilation. The previous encounter groups you made (say Route101) are going to be stored side by side in the same format you made them.
At the moment, the first one (being _gRoute101_Morning _in this case) will be the only one accessible by the game, to fix that we need to edit the **GetCurrentMapWildMonHeaderId()** function in _src/wild_encounter.c_.
In summary, what that function does is to loop through all the encounter groups, if it encounters an undefined map group, it stops. It'll continue looping till it reaches the current map our player is in. Here, it will check if the current map is Altering Cave (since it has up to 8 encounter groups, see **NUM_ALTERING_CAVE_TABLES**), if so it shifts the index forward (depending on the value of **VAR_ALTERING_CAVE_WILD_SET**) to the seperate encounter table. The function then returns the index to the required encounter group.
### The GetCurrentMapWildMonHeaderId Function
What that function does is to loop through all the encounter groups, if it encounters an undefined map group, it stops. It'll continue looping till it reaches the current map our player is in. Here, it will check if the current map is Altering Cave (since it has up to 8 encounter groups, see **NUM_ALTERING_CAVE_TABLES**), if so it shifts the index forward (depending on the value of **VAR_ALTERING_CAVE_WILD_SET**) to the seperate encounter table. The function then returns the index to the required encounter group.
We're going to do something similar to the Altering Cave check but with the variable we made instead. This makes it very easy to switch between encounter groups when needed. Add these 2 lines just before the Altering Cave check:
@ -144,3 +151,72 @@ Those two lines make sure that the encounters will be rechecked(and adjusted if
* If you want more or less encounter periods, just alter **SetTimeBasedEncounters()** and your encounter groups in Porymap as required.
* If its weather-based encounters you want, you'll want to change the conditionals in **SetTimeBasedEncounters()** (rename that too) to check for the type of weather rather than time(something along `if (gSaveBlock1Ptr->weather == WEATHER_SNOW)`).
* If for some reason you want to stop or 'freeze' the encounters to a particular group, instead of using `callnative(SetTimeBasedEncounters)`, just hard set it with `setvar VAR_TIME_BASED_ENCOUNTER, <insert number here>`.
***
## Without a Variable
This option will be more useful if you will not have any "special" conditions to alter the encounters and it avoid the use of calling a script unlike the previous section.
Firstly, [make your encounter tables](#prepare-your-encounter-groups). To achieve this, we're going to have to alter the [GetCurrentMapWildMonHeaderId()](#the-getcurrentmapwildmonheaderid-function) function in _src/wild_encounter.c_ since that is responsible for getting the right encounter groups. We add a couple of checks to it to become:
#include "rtc.h"
u16 GetCurrentMapWildMonHeaderId(void)
{
u16 i;
for (i = 0; ; i++)
{
const struct WildPokemonHeader *wildHeader = &gWildMonHeaders[i];
if (wildHeader->mapGroup == MAP_GROUP(UNDEFINED))
break;
if (gWildMonHeaders[i].mapGroup == gSaveBlock1Ptr->location.mapGroup &&
gWildMonHeaders[i].mapNum == gSaveBlock1Ptr->location.mapNum)
{
+ RtcCalcLocalTime();
+ if (gSaveBlock1Ptr->location.mapGroup != MAP_GROUP(ALTERING_CAVE) &&
+ gSaveBlock1Ptr->location.mapNum != MAP_NUM(ALTERING_CAVE))
+ {
+ if (gLocalTime.hours >= 6 && gLocalTime.hours <= 8)
+ {
+ i += 0; // Morning
+ }
+ else if (gLocalTime.hours >= 9 && gLocalTime.hours <= 17 &&
+ gWildMonHeaders[i + 1].mapGroup == gSaveBlock1Ptr->location.mapGroup &&
+ gWildMonHeaders[i + 1].mapNum == gSaveBlock1Ptr->location.mapNum)
+ {
+ i += 1; // Day
+ }
+ else if (gLocalTime.hours >= 18 && gLocalTime.hours <= 20 &&
+ gWildMonHeaders[i + 2].mapGroup == gSaveBlock1Ptr->location.mapGroup &&
+ gWildMonHeaders[i + 2].mapNum == gSaveBlock1Ptr->location.mapNum)
+ {
+ i += 2; // Evening
+ }
+ else if (gWildMonHeaders[i + 3].mapGroup == gSaveBlock1Ptr->location.mapGroup &&
+ gWildMonHeaders[i + 3].mapNum == gSaveBlock1Ptr->location.mapNum)
+ {
+ i += 3; // Night
+ }
+ }
if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ALTERING_CAVE) &&
gSaveBlock1Ptr->location.mapNum == MAP_NUM(ALTERING_CAVE))
{
u16 alteringCaveId = VarGet(VAR_ALTERING_CAVE_WILD_SET);
if (alteringCaveId >= NUM_ALTERING_CAVE_TABLES)
alteringCaveId = 0;
i += alteringCaveId;
}
return i;
}
}
return HEADER_NONE;
}
**RtcCalcLocalTime()** calculates the real time and stores in **gLocalTime** for the following conditionals to use. The conditionals increment the index(i) to position of the appropriate encounter group in the array **gWildMonHeaders** (saying that you arranged your encounter groups in this order: _Morning_, _Afternoon_, _Evening_, _Night_ for this particular case) while leaving maps with singular encounter groups unaffected! This will work automatically for all maps with encounters.
**PS:**
* This will work assuming you don't have any "special" encounter groups for seperate conditions. In that case, the function needs to be modified more.