From 9e1a593d3541ae55abb8cb44f0bcfb2ce9f075c1 Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Fri, 2 Jan 2026 09:38:55 +0100 Subject: [PATCH] Refactor dexnav to not use overworld task (#8602) --- include/dexnav.h | 7 +- src/dexnav.c | 223 ++++++++++++++++++------------------- src/field_control_avatar.c | 4 +- src/script.c | 3 + 4 files changed, 119 insertions(+), 118 deletions(-) diff --git a/include/dexnav.h b/include/dexnav.h index b1956349b3..82350f665a 100644 --- a/include/dexnav.h +++ b/include/dexnav.h @@ -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; diff --git a/src/dexnav.c b/src/dexnav.c index 3244d07a6f..adec596891 100644 --- a/src/dexnav.c +++ b/src/dexnav.c @@ -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) diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index f35c349fc6..d3272d33ae 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -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; } diff --git a/src/script.c b/src/script.c index 3a0c7c7afd..03fe4bb919 100644 --- a/src/script.c +++ b/src/script.c @@ -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)