Some constants in wild_encounter.c, document Feebas spot generation

This commit is contained in:
GriffinR 2021-10-09 14:18:05 -04:00
parent ff01eb951b
commit b01213b8bc

View file

@ -25,9 +25,27 @@
extern const u8 EventScript_RepelWoreOff[];
#define NUM_FEEBAS_SPOTS 6
#define MAX_ENCOUNTER_RATE 2880
#define NUM_FEEBAS_SPOTS 6
// Number of accessible fishing spots in each section of Route 119
// Each section is an area of the route between the y coordinates in sRoute119WaterTileData
#define NUM_FISHING_SPOTS_1 131
#define NUM_FISHING_SPOTS_2 167
#define NUM_FISHING_SPOTS_3 149
#define NUM_FISHING_SPOTS (NUM_FISHING_SPOTS_1 + NUM_FISHING_SPOTS_2 + NUM_FISHING_SPOTS_3)
enum {
WILD_AREA_LAND,
WILD_AREA_WATER,
WILD_AREA_ROCKS,
WILD_AREA_FISHING,
};
#define WILD_CHECK_REPEL (1 << 0)
#define WILD_CHECK_KEEN_EYE (1 << 1)
// this file's functions
static u16 FeebasRandom(void);
static void FeebasSeedRng(u16 seed);
static bool8 IsWildLevelAllowedByRepel(u8 level);
@ -36,60 +54,64 @@ static void ApplyCleanseTagEncounterRateMod(u32 *encRate);
static bool8 TryGetAbilityInfluencedWildMonIndex(const struct WildPokemon *wildMon, u8 type, u8 ability, u8 *monIndex);
static bool8 IsAbilityAllowingEncounter(u8 level);
// EWRAM vars
EWRAM_DATA static u8 sWildEncountersDisabled = 0;
EWRAM_DATA static u32 sFeebasRngValue = 0;
#include "data/wild_encounters.h"
//Special Feebas-related data.
const struct WildPokemon gWildFeebasRoute119Data = {20, 25, SPECIES_FEEBAS};
static const struct WildPokemon sWildFeebas = {20, 25, SPECIES_FEEBAS};
const u16 gRoute119WaterTileData[] =
static const u16 sRoute119WaterTileData[] =
{
0, 0x2D, 0,
0x2E, 0x5B, 0x83,
0x5C, 0x8B, 0x12A,
//yMin, yMax, numSpots in previous sections
0, 45, 0,
46, 91, NUM_FISHING_SPOTS_1,
92, 139, NUM_FISHING_SPOTS_1 + NUM_FISHING_SPOTS_2,
};
// code
void DisableWildEncounters(bool8 disabled)
{
sWildEncountersDisabled = disabled;
}
static u16 GetRoute119WaterTileNum(s16 x, s16 y, u8 section)
// Each fishing spot on Route 119 is given a number between 1 and NUM_FISHING_SPOTS inclusive.
// The number is determined by counting the valid fishing spots left to right top to bottom.
// The map is divided into three sections, with each section having a pre-counted number of
// fishing spots to start from to avoid counting a large number of spots at the bottom of the map.
// Note that a spot is considered valid if it is surfable and not a waterfall. To exclude all
// of the inaccessible water metatiles (so that they can't be selected as a Feebas spot) they
// use a different metatile that isn't actually surfable because it has MB_NORMAL instead.
// This function is given the coordinates and section of a fishing spot and returns which number it is.
static u16 GetFeebasFishingSpotId(s16 targetX, s16 targetY, u8 section)
{
u16 xCur;
u16 yCur;
u16 yMin = gRoute119WaterTileData[section * 3 + 0];
u16 yMax = gRoute119WaterTileData[section * 3 + 1];
u16 tileNum = gRoute119WaterTileData[section * 3 + 2];
u16 x, y;
u16 yMin = sRoute119WaterTileData[section * 3 + 0];
u16 yMax = sRoute119WaterTileData[section * 3 + 1];
u16 spotId = sRoute119WaterTileData[section * 3 + 2];
for (yCur = yMin; yCur <= yMax; yCur++)
for (y = yMin; y <= yMax; y++)
{
for (xCur = 0; xCur < gMapHeader.mapLayout->width; xCur++)
for (x = 0; x < gMapHeader.mapLayout->width; x++)
{
u8 tileBehaviorId = MapGridGetMetatileBehaviorAt(xCur + MAP_OFFSET, yCur + MAP_OFFSET);
if (MetatileBehavior_IsSurfableAndNotWaterfall(tileBehaviorId) == TRUE)
u8 behavior = MapGridGetMetatileBehaviorAt(x + MAP_OFFSET, y + MAP_OFFSET);
if (MetatileBehavior_IsSurfableAndNotWaterfall(behavior) == TRUE)
{
tileNum++;
if (x == xCur && y == yCur)
return tileNum;
spotId++;
if (targetX == x && targetY == y)
return spotId;
}
}
}
return tileNum + 1;
return spotId + 1;
}
static bool8 CheckFeebas(void)
{
u8 i;
u16 feebasSpots[NUM_FEEBAS_SPOTS];
s16 x;
s16 y;
s16 x, y;
u8 route119Section = 0;
u16 waterTileNum;
u16 spotId;
if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE119)
&& gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE119))
@ -98,29 +120,42 @@ static bool8 CheckFeebas(void)
x -= MAP_OFFSET;
y -= MAP_OFFSET;
if (y >= gRoute119WaterTileData[3 * 0 + 0] && y <= gRoute119WaterTileData[3 * 0 + 1])
// Get which third of the map the player is in
if (y >= sRoute119WaterTileData[3 * 0 + 0] && y <= sRoute119WaterTileData[3 * 0 + 1])
route119Section = 0;
if (y >= gRoute119WaterTileData[3 * 1 + 0] && y <= gRoute119WaterTileData[3 * 1 + 1])
if (y >= sRoute119WaterTileData[3 * 1 + 0] && y <= sRoute119WaterTileData[3 * 1 + 1])
route119Section = 1;
if (y >= gRoute119WaterTileData[3 * 2 + 0] && y <= gRoute119WaterTileData[3 * 2 + 1])
if (y >= sRoute119WaterTileData[3 * 2 + 0] && y <= sRoute119WaterTileData[3 * 2 + 1])
route119Section = 2;
if (Random() % 100 > 49) // 50% chance of encountering Feebas
// 50% chance of encountering Feebas (assuming this is a Feebas spot)
if (Random() % 100 > 49)
return FALSE;
FeebasSeedRng(gSaveBlock1Ptr->dewfordTrends[0].rand);
// Assign each Feebas spot to a random fishing spot.
// Randomness is fixed depending on the seed above.
for (i = 0; i != NUM_FEEBAS_SPOTS;)
{
feebasSpots[i] = FeebasRandom() % 447;
feebasSpots[i] = FeebasRandom() % NUM_FISHING_SPOTS;
if (feebasSpots[i] == 0)
feebasSpots[i] = 447;
feebasSpots[i] = NUM_FISHING_SPOTS;
// < 1 below is a pointless check, it will never be TRUE.
// >= 4 to skip fishing spots 1-3, because these are inaccessible
// spots at the top of the map, at (9,7), (7,13), and (15,16).
// The first accessible fishing spot is spot 4 at (18,18).
if (feebasSpots[i] < 1 || feebasSpots[i] >= 4)
i++;
}
waterTileNum = GetRoute119WaterTileNum(x, y, route119Section);
// Check which fishing spot the player is at, and see if
// it matches any of the Feebas spots.
spotId = GetFeebasFishingSpotId(x, y, route119Section);
for (i = 0; i < NUM_FEEBAS_SPOTS; i++)
{
if (waterTileNum == feebasSpots[i])
if (spotId == feebasSpots[i])
return TRUE;
}
}
@ -256,7 +291,6 @@ static u8 ChooseWildMonLevel(const struct WildPokemon *wildPokemon)
rand--;
}
}
return min + rand;
}
@ -365,24 +399,13 @@ static void CreateWildMon(u16 species, u8 level)
else
gender = MON_FEMALE;
CreateMonWithGenderNatureLetter(&gEnemyParty[0], species, level, 32, gender, PickWildMonNature(), 0);
CreateMonWithGenderNatureLetter(&gEnemyParty[0], species, level, USE_RANDOM_IVS, gender, PickWildMonNature(), 0);
return;
}
CreateMonWithNature(&gEnemyParty[0], species, level, 32, PickWildMonNature());
CreateMonWithNature(&gEnemyParty[0], species, level, USE_RANDOM_IVS, PickWildMonNature());
}
enum
{
WILD_AREA_LAND,
WILD_AREA_WATER,
WILD_AREA_ROCKS,
WILD_AREA_FISHING,
};
#define WILD_CHECK_REPEL 0x1
#define WILD_CHECK_KEEN_EYE 0x2
static bool8 TryGenerateWildMon(const struct WildPokemonInfo *wildMonInfo, u8 area, u8 flags)
{
u8 wildMonIndex = 0;
@ -436,7 +459,7 @@ static bool8 SetUpMassOutbreakEncounter(u8 flags)
return FALSE;
CreateWildMon(gSaveBlock1Ptr->outbreakPokemonSpecies, gSaveBlock1Ptr->outbreakPokemonLevel);
for (i = 0; i < 4; i++)
for (i = 0; i < MAX_MON_MOVES; i++)
SetMonMoveSlot(&gEnemyParty[0], gSaveBlock1Ptr->outbreakPokemonMoves[i], i);
return TRUE;
@ -444,7 +467,7 @@ static bool8 SetUpMassOutbreakEncounter(u8 flags)
static bool8 DoMassOutbreakEncounterTest(void)
{
if (gSaveBlock1Ptr->outbreakPokemonSpecies != 0
if (gSaveBlock1Ptr->outbreakPokemonSpecies != SPECIES_NONE
&& gSaveBlock1Ptr->location.mapNum == gSaveBlock1Ptr->outbreakLocationMapNum
&& gSaveBlock1Ptr->location.mapGroup == gSaveBlock1Ptr->outbreakLocationMapGroup)
{
@ -456,7 +479,7 @@ static bool8 DoMassOutbreakEncounterTest(void)
static bool8 DoWildEncounterRateDiceRoll(u16 encounterRate)
{
if (Random() % 2880 < encounterRate)
if (Random() % MAX_ENCOUNTER_RATE < encounterRate)
return TRUE;
else
return FALSE;
@ -486,8 +509,8 @@ static bool8 DoWildEncounterRateTest(u32 encounterRate, bool8 ignoreAbility)
else if (ability == ABILITY_SAND_VEIL && gSaveBlock1Ptr->weather == WEATHER_SANDSTORM)
encounterRate /= 2;
}
if (encounterRate > 2880)
encounterRate = 2880;
if (encounterRate > MAX_ENCOUNTER_RATE)
encounterRate = MAX_ENCOUNTER_RATE;
return DoWildEncounterRateDiceRoll(encounterRate);
}
@ -639,7 +662,7 @@ void RockSmashWildEncounter(void)
gSpecialVar_Result = FALSE;
}
else if (DoWildEncounterRateTest(wildPokemonInfo->encounterRate, 1) == TRUE
&& TryGenerateWildMon(wildPokemonInfo, 2, WILD_CHECK_REPEL | WILD_CHECK_KEEN_EYE) == TRUE)
&& TryGenerateWildMon(wildPokemonInfo, WILD_AREA_ROCKS, WILD_CHECK_REPEL | WILD_CHECK_KEEN_EYE) == TRUE)
{
BattleSetup_StartWildBattle();
gSpecialVar_Result = TRUE;
@ -744,9 +767,9 @@ void FishingWildEncounter(u8 rod)
if (CheckFeebas() == TRUE)
{
u8 level = ChooseWildMonLevel(&gWildFeebasRoute119Data);
u8 level = ChooseWildMonLevel(&sWildFeebas);
species = gWildFeebasRoute119Data.species;
species = sWildFeebas.species;
CreateWildMon(species, level);
}
else