Refactor dexnav to not use overworld task (#8602)

This commit is contained in:
FosterProgramming 2026-01-02 09:38:55 +01:00 committed by GitHub
parent 4da0cf72e6
commit 9e1a593d35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 119 additions and 118 deletions

View File

@ -69,14 +69,15 @@ enum EncounterType
#define DEXNAV_MASK_SPECIES 0x3FFF // First 14 bits
#define DEXNAV_MASK_ENVIRONMENT 0xC000 // Last two bit
void EndDexNavSearch(u8 taskId);
void EndDexNavSearch(void);
void Task_OpenDexNavFromStartMenu(u8 taskId);
bool8 TryStartDexNavSearch(void);
bool32 TryStartDexNavSearch(void);
void TryIncrementSpeciesSearchLevel(void);
void ResetDexNavSearch(void);
bool8 TryFindHiddenPokemon(void);
bool32 TryFindHiddenPokemon(void);
u32 CalculateDexNavShinyRolls(void);
void IncrementDexNavChain(void);
bool32 OnStep_DexNavSearch(void);
extern u16 gDexNavSpecies;

View File

@ -107,6 +107,7 @@ struct DexNavSearch
u8 starSpriteIds[3];
u8 ownedIconSpriteId;
u8 exclamationSpriteId;
u32 startingTime;
u8 hiddenSearch:1;
u8 isHiddenMon:1;
u8 unk:6;
@ -155,11 +156,10 @@ static u8 DexNavPickTile(enum EncounterType environment, u8 xSize, u8 ySize, boo
static void DexNavProximityUpdate(void);
static void DexNavDrawIcons(void);
static void DexNavUpdateSearchWindow(u8 proximity, u8 searchLevel);
static void Task_DexNavSearch(u8 taskId);
static void EndDexNavSearchSetupScript(const u8 *script, u8 taskId);
// HIDDEN MONS
static void DexNavDrawHiddenIcons(void);
static void DrawHiddenSearchWindow(u8 width);
static void RevealHiddenMon(void);
//// Const Data
// gui image data
@ -818,16 +818,8 @@ static u8 GetSearchLevel(u16 species)
return searchLevel;
}
#define tProximity data[0]
#define tFrameCount data[1]
#define tSpecies data[2]
#define tEnvironment data[3]
#define tRevealed data[4]
static void Task_SetUpDexNavSearch(u8 taskId)
static void SetUpDexNavSearch(void)
{
struct Task *task = &gTasks[taskId];
u16 species = sDexNavSearchDataPtr->species;
u8 searchLevel = GetSearchLevel(species);
@ -859,34 +851,29 @@ static void Task_SetUpDexNavSearch(u8 taskId)
DexNavUpdateSearchWindow(sDexNavSearchDataPtr->proximity, searchLevel);
}
FlagSet(DN_FLAG_SEARCHING);
gPlayerAvatar.creeping = TRUE; //initialize as true in case mon appears beside you
task->tProximity = gSprites[gPlayerAvatar.spriteId].x;
task->tFrameCount = 0;
task->func = Task_DexNavSearch;
sDexNavSearchDataPtr->proximity = gSprites[gPlayerAvatar.spriteId].x;
sDexNavSearchDataPtr->startingTime = gMain.vblankCounter1;
IncrementGameStat(GAME_STAT_DEXNAV_SCANNED);
}
static void DexNavSearchBail(u8 taskId, const u8 *script)
static void DexNavSearchBail(const u8 *script)
{
TRY_FREE_AND_SET_NULL(sDexNavSearchDataPtr);
FlagClear(DN_FLAG_SEARCHING);
FreeMonIconPalettes();
ScriptContext_SetupScript(script);
DestroyTask(taskId);
}
static void Task_InitDexNavSearch(u8 taskId)
static bool8 InitDexNavSearch(u32 species, u32 environment)
{
struct Task *task = &gTasks[taskId];
u16 species = task->tSpecies;
u8 environment = task->tEnvironment;
sDexNavSearchDataPtr = AllocZeroed(sizeof(struct DexNavSearch));
if (sDexNavSearchDataPtr == NULL)
{
DexNavSearchBail(taskId, EventScript_NotFoundNearby);
return;
DexNavSearchBail(EventScript_NotFoundNearby);
return TRUE;
}
FlagSet(DN_FLAG_SEARCHING);
// assign non-objects to struct
sDexNavSearchDataPtr->species = species;
@ -896,19 +883,19 @@ static void Task_InitDexNavSearch(u8 taskId)
if (GetFlashLevel() > 0)
{
DexNavSearchBail(taskId, EventScript_TooDark);
return;
DexNavSearchBail(EventScript_TooDark);
return TRUE;
}
if (sDexNavSearchDataPtr->monLevel == MON_LEVEL_NONEXISTENT || !TryStartHiddenMonFieldEffect(sDexNavSearchDataPtr->environment, 12, 12, FALSE))
{
DexNavSearchBail(taskId, EventScript_NotFoundNearby);
return;
DexNavSearchBail(EventScript_NotFoundNearby);
return TRUE;
}
sDexNavSearchDataPtr->hiddenSearch = FALSE;
task->tRevealed = TRUE; //search window revealed
task->func = Task_SetUpDexNavSearch;
SetUpDexNavSearch();
return FALSE;
}
static void DexNavDrawPotentialStars(u8 potential, u8 *dst)
@ -977,36 +964,50 @@ static void DexNavDrawIcons(void)
/////////////////////
//// SEARCH TASK ////
/////////////////////
bool8 TryStartDexNavSearch(void)
static void RevealHiddenSearch(void)
{
PlaySE(SE_DEX_SEARCH);
ClearStdWindowAndFrameToTransparent(sDexNavSearchDataPtr->windowId, FALSE);
CopyWindowToVram(sDexNavSearchDataPtr->windowId, 3);
RemoveWindow(sDexNavSearchDataPtr->windowId);
DestroySprite(&gSprites[sDexNavSearchDataPtr->iconSpriteId]);
sDexNavSearchDataPtr->hiddenSearch = FALSE; //now its a regular dexnav search
RevealHiddenMon();
}
bool32 TryStartDexNavSearch(void)
{
u8 taskId;
u16 val = VarGet(DN_VAR_SPECIES);
if (FlagGet(DN_FLAG_SEARCHING) && sDexNavSearchDataPtr->hiddenSearch)
{
RevealHiddenSearch();
return FALSE;
}
if (FlagGet(DN_FLAG_SEARCHING) || (val & DEXNAV_MASK_SPECIES) == SPECIES_NONE)
return FALSE;
HideMapNamePopUpWindow();
ChangeBgY_ScreenOff(0, 0, 0);
taskId = CreateTask(Task_InitDexNavSearch, 0);
gTasks[taskId].tSpecies = val & DEXNAV_MASK_SPECIES;
gTasks[taskId].tEnvironment = val >> 14;
PlaySE(SE_DEX_SEARCH);
return FALSE; //we dont actually want to enable the script context
return InitDexNavSearch(val & DEXNAV_MASK_SPECIES, val >> 14);
}
void EndDexNavSearch(u8 taskId)
void EndDexNavSearch(void)
{
FlagClear(DN_FLAG_SEARCHING);
DestroyTask(taskId);
if (!FlagGet(DN_FLAG_SEARCHING))
return;
RemoveDexNavWindowAndGfx();
FieldEffectStop(&gSprites[sDexNavSearchDataPtr->fldEffSpriteId], sDexNavSearchDataPtr->fldEffId);
Free(sDexNavSearchDataPtr);
FREE_AND_SET_NULL(sDexNavSearchDataPtr);
FlagClear(DN_FLAG_SEARCHING);
}
static void EndDexNavSearchSetupScript(const u8 *script, u8 taskId)
static void EndDexNavSearchSetupScript(const u8 *script)
{
gSaveBlock3Ptr->dexNavChain = 0; //reset chain
EndDexNavSearch(taskId);
EndDexNavSearch();
ScriptContext_SetupScript(script);
}
@ -1020,9 +1021,8 @@ static u8 GetMovementProximityBySearchLevel(void)
return 4;
}
static void Task_RevealHiddenMon(u8 taskId)
static void RevealHiddenMon(void)
{
struct Task *task = &gTasks[taskId];
u16 species = sDexNavSearchDataPtr->species;
// remove owned icon if it exists
@ -1059,53 +1059,68 @@ static void Task_RevealHiddenMon(u8 taskId)
DrawDexNavSearchMonIcon(species, &sDexNavSearchDataPtr->iconSpriteId, GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT));
}
sDexNavSearchDataPtr->startingTime = gMain.vblankCounter1;
DexNavUpdateDirectionArrow();
task->func = Task_DexNavSearch;
task->tFrameCount = 0; //restart search clock
}
static void Task_DexNavSearch(u8 taskId)
bool32 OnStep_DexNavSearch(void)
{
struct Task *task = &gTasks[taskId];
if (!FlagGet(DN_FLAG_SEARCHING))
return FALSE;
u32 frameCount = gMain.vblankCounter1 - sDexNavSearchDataPtr->startingTime;
DexNavProximityUpdate();
if (!sDexNavSearchDataPtr->hiddenSearch) //update search window info only if revealed mon
DexNavUpdateSearchWindow(sDexNavSearchDataPtr->proximity, sDexNavSearchDataPtr->searchLevel);
if (sDexNavSearchDataPtr->proximity > MAX_PROXIMITY)
{ // out of range
if (sDexNavSearchDataPtr->hiddenSearch && !task->tRevealed)
EndDexNavSearch(taskId);
if (sDexNavSearchDataPtr->hiddenSearch)
{
EndDexNavSearch();
return FALSE;
}
else
EndDexNavSearchSetupScript(EventScript_LostSignal, taskId);
return;
{
EndDexNavSearchSetupScript(EventScript_LostSignal);
return TRUE;
}
}
if (sDexNavSearchDataPtr->proximity <= CREEPING_PROXIMITY && !gPlayerAvatar.creeping && task->tFrameCount > 60)
if (sDexNavSearchDataPtr->proximity <= CREEPING_PROXIMITY && !gPlayerAvatar.creeping && frameCount > 60)
{ //should be creeping but player walks normally
if (sDexNavSearchDataPtr->hiddenSearch && !task->tRevealed)
EndDexNavSearch(taskId);
if (sDexNavSearchDataPtr->hiddenSearch)
{
EndDexNavSearch();
return FALSE;
}
else
EndDexNavSearchSetupScript(EventScript_MovedTooFast, taskId);
return;
{
EndDexNavSearchSetupScript(EventScript_MovedTooFast);
return TRUE;
}
}
if (sDexNavSearchDataPtr->proximity <= SNEAKING_PROXIMITY && TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_DASH | PLAYER_AVATAR_FLAG_BIKE))
{ // running/biking too close
//always do event script, even if player hasn't revealed a hidden mon. It's assumed they would be creeping towards it
EndDexNavSearchSetupScript(EventScript_MovedTooFast, taskId);
return;
EndDexNavSearchSetupScript(EventScript_MovedTooFast);
return TRUE;
}
if (ArePlayerFieldControlsLocked() == TRUE)
{ // check if script just executed
EndDexNavSearch(taskId);
return;
}
if (gTasks[taskId].tFrameCount > DEXNAV_TIMEOUT * 60)
if (frameCount > DEXNAV_TIMEOUT * 60)
{ // player took too long
if (sDexNavSearchDataPtr->hiddenSearch && !task->tRevealed)
EndDexNavSearch(taskId);
if (sDexNavSearchDataPtr->hiddenSearch)
{
EndDexNavSearch();
return FALSE;
}
else
EndDexNavSearchSetupScript(EventScript_PokemonGotAway, taskId);
return;
{
EndDexNavSearchSetupScript(EventScript_PokemonGotAway);
return TRUE;
}
return FALSE;
}
if (sDexNavSearchDataPtr->proximity < 1)
@ -1114,54 +1129,34 @@ static void Task_DexNavSearch(u8 taskId)
CreateDexNavWildMon(sDexNavSearchDataPtr->species, sDexNavSearchDataPtr->potential, sDexNavSearchDataPtr->monLevel,
sDexNavSearchDataPtr->abilityNum, sDexNavSearchDataPtr->heldItem, sDexNavSearchDataPtr->moves);
FlagClear(DN_FLAG_SEARCHING);
ScriptContext_SetupScript(EventScript_StartDexNavBattle);
Free(sDexNavSearchDataPtr);
DestroyTask(taskId);
return;
FREE_AND_SET_NULL(sDexNavSearchDataPtr);
FlagClear(DN_FLAG_SEARCHING);
return TRUE;
}
if (sDexNavSearchDataPtr->hiddenSearch && !task->tRevealed &&
(JOY_NEW(R_BUTTON) || (sDexNavSearchDataPtr->proximity < CREEPING_PROXIMITY)))
if (sDexNavSearchDataPtr->hiddenSearch && sDexNavSearchDataPtr->proximity < CREEPING_PROXIMITY)
{
PlaySE(SE_DEX_SEARCH);
ClearStdWindowAndFrameToTransparent(sDexNavSearchDataPtr->windowId, FALSE);
CopyWindowToVram(sDexNavSearchDataPtr->windowId, 3);
RemoveWindow(sDexNavSearchDataPtr->windowId);
DestroySprite(&gSprites[sDexNavSearchDataPtr->iconSpriteId]);
task->tRevealed = TRUE; //regular dexnav search
//sDexNavSearchDataPtr->hiddenSearch = FALSE; //now its a regular dexnav search
task->func = Task_RevealHiddenMon;
return;
RevealHiddenSearch();
return FALSE;
}
//Caves and water the pokemon moves around
if ((sDexNavSearchDataPtr->environment == ENCOUNTER_TYPE_WATER || GetCurrentMapType() == MAP_TYPE_UNDERGROUND)
&& sDexNavSearchDataPtr->proximity < GetMovementProximityBySearchLevel() && sDexNavSearchDataPtr->movementCount < 2
&& task->tRevealed)
&& !sDexNavSearchDataPtr->hiddenSearch)
{
FieldEffectStop(&gSprites[sDexNavSearchDataPtr->fldEffSpriteId], sDexNavSearchDataPtr->fldEffId);
if (!TryStartHiddenMonFieldEffect(sDexNavSearchDataPtr->environment, 10, 10, TRUE))
{
EndDexNavSearchSetupScript(EventScript_PokemonGotAway, taskId);
return;
EndDexNavSearchSetupScript(EventScript_PokemonGotAway);
return TRUE;
}
sDexNavSearchDataPtr->movementCount++;
}
DexNavProximityUpdate();
if (task->tProximity != sDexNavSearchDataPtr->proximity)
{
//player has moved
if (task->tRevealed) //update search window info only if hidden mon has been revealed (always true for search mode)
DexNavUpdateSearchWindow(sDexNavSearchDataPtr->proximity, sDexNavSearchDataPtr->searchLevel);
task->tProximity = sDexNavSearchDataPtr->proximity;
}
task->tFrameCount++;
return FALSE;
}
static void DexNavUpdateSearchWindow(u8 proximity, u8 searchLevel)
@ -1864,14 +1859,10 @@ static void DexNavGuiFreeResources(void)
static void CB1_InitDexNavSearch(void)
{
u8 taskId;
if (!gPaletteFade.active && !ArePlayerFieldControlsLocked() && gMain.callback2 == CB2_Overworld)
{
SetMainCallback1(CB1_Overworld);
taskId = CreateTask(Task_InitDexNavSearch, 0);
gTasks[taskId].tSpecies = gSpecialVar_0x8000;
gTasks[taskId].tEnvironment = gSpecialVar_0x8001;
InitDexNavSearch(gSpecialVar_0x8000, gSpecialVar_0x8001);
}
}
@ -2232,6 +2223,9 @@ static void CreateTypeIconSprites(void)
}
}
#define tSpecies data[2]
#define tEnvironment data[3]
static bool8 DexNav_DoGfxSetup(void)
{
u8 taskId;
@ -2508,7 +2502,7 @@ static void Task_DexNavMain(u8 taskId)
/////////////////////////
//// HIDDEN POKEMON /////
/////////////////////////
bool8 TryFindHiddenPokemon(void)
bool32 TryFindHiddenPokemon(void)
{
u16 *stepPtr = GetVarPointer(DN_VAR_STEP_COUNTER);
@ -2531,7 +2525,6 @@ bool8 TryFindHiddenPokemon(void)
u8 index;
u16 species;
enum EncounterType environment;
u8 taskId;
enum TimeOfDay timeOfDay = GetTimeOfDayForEncounters(headerId, WILD_AREA_HIDDEN);
const struct WildPokemonInfo *hiddenMonsInfo = gWildMonHeaders[headerId].encounterTypes[timeOfDay].hiddenMonsInfo;
@ -2596,7 +2589,7 @@ bool8 TryFindHiddenPokemon(void)
return FALSE;
sDexNavSearchDataPtr = AllocZeroed(sizeof(struct DexNavSearch));
FlagSet(DN_FLAG_SEARCHING);
// init search data
sDexNavSearchDataPtr->isHiddenMon = isHiddenMon;
sDexNavSearchDataPtr->species = species;
@ -2605,13 +2598,18 @@ bool8 TryFindHiddenPokemon(void)
sDexNavSearchDataPtr->monLevel = DexNavTryGenerateMonLevel(species, environment);
if (sDexNavSearchDataPtr->monLevel == MON_LEVEL_NONEXISTENT)
{
Free(sDexNavSearchDataPtr);
FREE_AND_SET_NULL(sDexNavSearchDataPtr);
FlagClear(DN_FLAG_SEARCHING);
return FALSE;
}
// find tile for hidden mon and start effect if possible
if (!TryStartHiddenMonFieldEffect(sDexNavSearchDataPtr->environment, 8, 8, TRUE))
{
FREE_AND_SET_NULL(sDexNavSearchDataPtr);
FlagClear(DN_FLAG_SEARCHING);
return FALSE;
}
// exclamation mark over player
gFieldEffectArguments[0] = gSaveBlock1Ptr->pos.x;
@ -2622,10 +2620,7 @@ bool8 TryFindHiddenPokemon(void)
FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON);
PlayCry_Script(species, 0);
taskId = CreateTask(Task_SetUpDexNavSearch, 0);
gTasks[taskId].tSpecies = sDexNavSearchDataPtr->species;
gTasks[taskId].tEnvironment = sDexNavSearchDataPtr->environment;
gTasks[taskId].tRevealed = FALSE;
SetUpDexNavSearch();
HideMapNamePopUpWindow();
ChangeBgY_ScreenOff(0, 0, 0);
return FALSE; // we dont actually want to enable the script context or the game will freeze
@ -2699,7 +2694,7 @@ void ResetDexNavSearch(void)
gSaveBlock3Ptr->dexNavChain = 0; //reset dex nav chaining on new map
VarSet(DN_VAR_STEP_COUNTER, 0); //reset hidden pokemon step counter
if (FlagGet(DN_FLAG_SEARCHING))
EndDexNavSearch(FindTaskIdByFunc(Task_DexNavSearch)); //moving to new map ends dexnav search
EndDexNavSearch(); //moving to new map ends dexnav search
}
void IncrementDexNavChain(void)

View File

@ -119,7 +119,7 @@ void FieldGetPlayerInput(struct FieldInput *input, u16 newKeys, u16 heldKeys)
input->pressedAButton = TRUE;
if (newKeys & B_BUTTON)
input->pressedBButton = TRUE;
if (newKeys & R_BUTTON && !FlagGet(DN_FLAG_SEARCHING))
if (newKeys & R_BUTTON)
input->pressedRButton = TRUE;
}
@ -618,6 +618,8 @@ static bool8 TryStartStepBasedScript(struct MapPosition *position, u16 metatileB
return TRUE;
if (UpdateRepelCounter() == TRUE)
return TRUE;
if (OnStep_DexNavSearch())
return TRUE;
return FALSE;
}

View File

@ -10,6 +10,8 @@
#include "constants/map_scripts.h"
#include "field_message_box.h"
#include "dexnav.h"
#define RAM_SCRIPT_MAGIC 51
enum {
@ -199,6 +201,7 @@ u32 ScriptPeekWord(struct ScriptContext *ctx)
void LockPlayerFieldControls(void)
{
sLockFieldControls = TRUE;
EndDexNavSearch();
}
void UnlockPlayerFieldControls(void)