Merge pull request #624 from GriffinRichards/field-tasks

Sync field_tasks
This commit is contained in:
GriffinR
2023-08-14 16:00:52 -04:00
committed by GitHub
6 changed files with 199 additions and 123 deletions
+5 -5
View File
@@ -6,11 +6,11 @@
// Player speeds // Player speeds
enum enum
{ {
SPEED_STANDING, PLAYER_SPEED_STANDING,
SPEED_NORMAL, PLAYER_SPEED_NORMAL,
SPEED_FAST, PLAYER_SPEED_FAST,
SPEED_FASTER, PLAYER_SPEED_FASTER,
SPEED_FASTEST, PLAYER_SPEED_FASTEST,
}; };
enum { enum {
+14
View File
@@ -35,6 +35,10 @@
// gTileset_DepartmentStore // gTileset_DepartmentStore
#define METATILE_DepartmentStore_ElevatorDoor 0x28D #define METATILE_DepartmentStore_ElevatorDoor 0x28D
// gTileset_Fallarbor
#define METATILE_Fallarbor_AshGrass 0x20A
#define METATILE_Fallarbor_NormalGrass 0x212
// gTileset_FuchsiaCity // gTileset_FuchsiaCity
#define METATILE_FuchsiaCity_Door 0x2BF #define METATILE_FuchsiaCity_Door 0x2BF
#define METATILE_FuchsiaCity_SafariZoneDoor 0x2D2 #define METATILE_FuchsiaCity_SafariZoneDoor 0x2D2
@@ -74,6 +78,9 @@
#define METATILE_GenericBuilding1_PlayersPCOff 0x28F #define METATILE_GenericBuilding1_PlayersPCOff 0x28F
#define METATILE_GenericBuilding1_PlayersPCOn 0x28A #define METATILE_GenericBuilding1_PlayersPCOn 0x28A
// gTileset_Lavaridge
#define METATILE_Lavaridge_NormalGrass 0x206
// gTileset_LavenderTown // gTileset_LavenderTown
#define METATILE_LavenderTown_Door 0x2A2 #define METATILE_LavenderTown_Door 0x2A2
@@ -84,6 +91,9 @@
// gTileset_MtEmber // gTileset_MtEmber
#define METATILE_MtEmber_CaveEntrance 0x346 #define METATILE_MtEmber_CaveEntrance 0x346
// gTileset_Pacifidlog
#define METATILE_Pacifidlog_SkyPillar_CrackedFloor_Hole 0x237
// gTileset_PalletTown // gTileset_PalletTown
#define METATILE_PalletTown_Door 0x2A3 #define METATILE_PalletTown_Door 0x2A3
#define METATILE_PalletTown_OaksLabDoor 0x2AC #define METATILE_PalletTown_OaksLabDoor 0x2AC
@@ -165,6 +175,10 @@
#define METATILE_PokemonMansion_Wall_EndPost_Bottom 0x2AD #define METATILE_PokemonMansion_Wall_EndPost_Bottom 0x2AD
#define METATILE_PokemonMansion_Wall_EndPost_Mid 0x2A5 #define METATILE_PokemonMansion_Wall_EndPost_Mid 0x2A5
// gTileset_RSCave
#define METATILE_RSCave_CrackedFloor 0x22F
#define METATILE_RSCave_CrackedFloor_Hole 0x206
// gTileset_SSAnne // gTileset_SSAnne
#define METATILE_SSAnne_Door 0x281 #define METATILE_SSAnne_Door 0x281
+6 -6
View File
@@ -338,7 +338,7 @@ void BikeClearState(u32 directionHistory, u32 abStartSelectHistory)
gPlayerAvatar.acroBikeState = BIKE_STATE_NORMAL; gPlayerAvatar.acroBikeState = BIKE_STATE_NORMAL;
gPlayerAvatar.newDirBackup = 0; gPlayerAvatar.newDirBackup = 0;
gPlayerAvatar.bikeFrameCounter = 0; gPlayerAvatar.bikeFrameCounter = 0;
gPlayerAvatar.bikeSpeed = SPEED_STANDING; gPlayerAvatar.bikeSpeed = PLAYER_SPEED_STANDING;
gPlayerAvatar.directionHistory = directionHistory; gPlayerAvatar.directionHistory = directionHistory;
gPlayerAvatar.abStartSelectHistory = abStartSelectHistory; gPlayerAvatar.abStartSelectHistory = abStartSelectHistory;
gPlayerAvatar.lastSpinTile = 0; gPlayerAvatar.lastSpinTile = 0;
@@ -355,21 +355,21 @@ void Bike_UpdateBikeCounterSpeed(u8 counter)
static void Bike_SetBikeStill(void) static void Bike_SetBikeStill(void)
{ {
gPlayerAvatar.bikeFrameCounter = 0; gPlayerAvatar.bikeFrameCounter = 0;
gPlayerAvatar.bikeSpeed = SPEED_STANDING; gPlayerAvatar.bikeSpeed = PLAYER_SPEED_STANDING;
} }
s16 GetPlayerSpeed(void) s16 GetPlayerSpeed(void)
{ {
s16 machBikeSpeeds[] = { SPEED_NORMAL, SPEED_FAST, SPEED_FASTEST }; s16 machBikeSpeeds[] = { PLAYER_SPEED_NORMAL, PLAYER_SPEED_FAST, PLAYER_SPEED_FASTEST };
if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_MACH_BIKE) if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_MACH_BIKE)
return machBikeSpeeds[gPlayerAvatar.bikeFrameCounter]; return machBikeSpeeds[gPlayerAvatar.bikeFrameCounter];
else if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE) else if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE)
return SPEED_FASTER; return PLAYER_SPEED_FASTER;
else if (gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_SURFING | PLAYER_AVATAR_FLAG_DASH)) else if (gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_SURFING | PLAYER_AVATAR_FLAG_DASH))
return SPEED_FAST; return PLAYER_SPEED_FAST;
else else
return SPEED_NORMAL; return PLAYER_SPEED_NORMAL;
} }
void Bike_HandleBumpySlopeJump(void) void Bike_HandleBumpySlopeJump(void)
+1 -1
View File
@@ -103,7 +103,7 @@ void FieldGetPlayerInput(struct FieldInput *input, u16 newKeys, u16 heldKeys)
} }
if ((tileTransitionState == T_TILE_CENTER && forcedMove == FALSE) || tileTransitionState == T_NOT_MOVING) if ((tileTransitionState == T_TILE_CENTER && forcedMove == FALSE) || tileTransitionState == T_NOT_MOVING)
{ {
if (GetPlayerSpeed() != 4) if (GetPlayerSpeed() != PLAYER_SPEED_FASTEST)
{ {
if ((newKeys & START_BUTTON) && !(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_FORCED)) if ((newKeys & START_BUTTON) && !(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_FORCED))
input->pressedStartButton = TRUE; input->pressedStartButton = TRUE;
+166 -111
View File
@@ -15,7 +15,20 @@
#include "constants/metatile_labels.h" #include "constants/metatile_labels.h"
#include "constants/songs.h" #include "constants/songs.h"
// TODO: Metatile IDs in this file /* This file handles some persistent tasks that run in the overworld.
* - Task_RunTimeBasedEvents: Triggers ambient cries. In RSE, this also periodically updates local time and RTC events.
* - Task_RunPerStepCallback: Calls one of the functions in sPerStepCallbacks, listed below...
* . DummyPerStepCallback: Default, does nothing. Includes functionality from RS that was removed.
* . AshGrassPerStepCallback: Leftover from RS. Removes the ash from ash-covered grass that the player steps on.
* . IcefallCaveIcePerStepCallback: Cracks/breaks ice in Icefall Cave that the player steps on.
* . CrackedFloorPerStepCallback: Leftover from RS. Breaks cracked floors that the player steps on.
*
* NOTE: "PerStep" is perhaps misleading. One function in sPerStepCallbacks is called
* every frame while in the overworld by Task_RunPerStepCallback regardless of
* whether or not steps are being taken. However, nearly all of the functions in
* the table check if the player has moved from their previous position before
* doing anything else.
*/
static void DummyPerStepCallback(u8 taskId); static void DummyPerStepCallback(u8 taskId);
static void AshGrassPerStepCallback(u8 taskId); static void AshGrassPerStepCallback(u8 taskId);
@@ -34,7 +47,8 @@ static const TaskFunc sPerStepCallbacks[] =
[STEP_CB_CRACKED_FLOOR] = CrackedFloorPerStepCallback [STEP_CB_CRACKED_FLOOR] = CrackedFloorPerStepCallback
}; };
static const u8 sIcefallCaveIceTileCoords[][2] = // The positions of each map space with crackable ice in Icefall Cave.
static const u8 sIcefallCaveIceCoords[][2] =
{ {
{ 8, 3 }, { 8, 3 },
{ 10, 5 }, { 10, 5 },
@@ -47,56 +61,53 @@ static const u8 sIcefallCaveIceTileCoords[][2] =
{ 8, 14 } { 8, 14 }
}; };
#define tCallbackId data[0]
static void Task_RunPerStepCallback(u8 taskId) static void Task_RunPerStepCallback(u8 taskId)
{ {
int idx = gTasks[taskId].data[0]; int idx = gTasks[taskId].tCallbackId;
sPerStepCallbacks[idx](taskId); sPerStepCallbacks[idx](taskId);
} }
#define tAmbientCryState data[1]
#define tAmbientCryDelay data[2]
// RTC functionality from RS was removed here.
static void Task_RunTimeBasedEvents(u8 taskId) static void Task_RunTimeBasedEvents(u8 taskId)
{ {
s16 *data = gTasks[taskId].data; s16 *data = gTasks[taskId].data;
if (!ArePlayerFieldControlsLocked()) if (!ArePlayerFieldControlsLocked() && !QL_IS_PLAYBACK_STATE)
{ UpdateAmbientCry(&tAmbientCryState, &tAmbientCryDelay);
if (!QL_IS_PLAYBACK_STATE)
{
UpdateAmbientCry(&data[1], &data[2]);
}
}
} }
void SetUpFieldTasks(void) void SetUpFieldTasks(void)
{ {
if (!FuncIsActiveTask(Task_RunPerStepCallback)) if (!FuncIsActiveTask(Task_RunPerStepCallback))
{ {
u8 taskId = CreateTask(Task_RunPerStepCallback, 0x50); u8 taskId = CreateTask(Task_RunPerStepCallback, 80);
gTasks[taskId].data[0] = 0; gTasks[taskId].tCallbackId = STEP_CB_DUMMY;
} }
if (!FuncIsActiveTask(Task_RunTimeBasedEvents)) if (!FuncIsActiveTask(Task_RunTimeBasedEvents))
CreateTask(Task_RunTimeBasedEvents, 0x50); CreateTask(Task_RunTimeBasedEvents, 80);
} }
void ActivatePerStepCallback(u8 callbackId) void ActivatePerStepCallback(u8 callbackId)
{ {
u8 taskId = FindTaskIdByFunc(Task_RunPerStepCallback); u8 taskId = FindTaskIdByFunc(Task_RunPerStepCallback);
if (taskId != 0xff) if (taskId != TASK_NONE)
{ {
s32 i; s32 i;
s16 *data = gTasks[taskId].data; s16 *data = gTasks[taskId].data;
for (i = 0; i < 16; i++) for (i = 0; i < NUM_TASK_DATA; i++)
data[i] = 0; data[i] = 0;
if (callbackId >= NELEMS(sPerStepCallbacks)) if (callbackId >= ARRAY_COUNT(sPerStepCallbacks))
{ tCallbackId = STEP_CB_DUMMY;
data[0] = 0;
}
else else
{ tCallbackId = callbackId;
data[0] = callbackId;
}
} }
} }
@@ -106,29 +117,31 @@ void ResetFieldTasksArgs(void)
s16 *data; s16 *data;
taskId = FindTaskIdByFunc(Task_RunPerStepCallback); taskId = FindTaskIdByFunc(Task_RunPerStepCallback);
if (taskId != 0xff) if (taskId != TASK_NONE)
{
data = gTasks[taskId].data; data = gTasks[taskId].data;
}
taskId = FindTaskIdByFunc(Task_RunTimeBasedEvents); taskId = FindTaskIdByFunc(Task_RunTimeBasedEvents);
if (taskId != 0xff) if (taskId != TASK_NONE)
{ {
data = gTasks[taskId].data; data = gTasks[taskId].data;
data[1] = 0; tAmbientCryState = 0;
data[2] = 0; tAmbientCryDelay = 0;
} }
} }
#undef tAmbientCryState
#undef tAmbientCryDelay
static void DummyPerStepCallback(u8 taskId) static void DummyPerStepCallback(u8 taskId)
{ {
} }
static void MarkIcefallCaveCoordVisited(s16 x, s16 y) static void MarkIcePuzzleCoordVisited(s16 x, s16 y)
{ {
u8 i = 0; u8 i;
for (; i < NELEMS(sIcefallCaveIceTileCoords); ++i) for (i = 0; i < ARRAY_COUNT(sIcefallCaveIceCoords); i++)
{ {
if (sIcefallCaveIceTileCoords[i][0] + 7 == x && sIcefallCaveIceTileCoords[i][1] + 7 == y) if (sIcefallCaveIceCoords[i][0] + MAP_OFFSET == x && sIcefallCaveIceCoords[i][1] + MAP_OFFSET == y)
{ {
FlagSet(i + 1); FlagSet(i + 1);
break; break;
@@ -138,118 +151,156 @@ static void MarkIcefallCaveCoordVisited(s16 x, s16 y)
void SetIcefallCaveCrackedIceMetatiles(void) void SetIcefallCaveCrackedIceMetatiles(void)
{ {
u8 i = 0; u8 i;
for (; i < NELEMS(sIcefallCaveIceTileCoords); ++i) for (i = 0; i < ARRAY_COUNT(sIcefallCaveIceCoords); i++)
{ {
if (FlagGet(i + 1) == TRUE) if (FlagGet(i + 1) == TRUE)
{ {
int x = sIcefallCaveIceTileCoords[i][0] + 7; int x = sIcefallCaveIceCoords[i][0] + MAP_OFFSET;
int y = sIcefallCaveIceTileCoords[i][1] + 7; int y = sIcefallCaveIceCoords[i][1] + MAP_OFFSET;
MapGridSetMetatileIdAt(x, y, METATILE_SeafoamIslands_CrackedIce); MapGridSetMetatileIdAt(x, y, METATILE_SeafoamIslands_CrackedIce);
} }
} }
} }
#define tState data[1]
#define tPrevX data[2]
#define tPrevY data[3]
#define tIceX data[4]
#define tIceY data[5]
#define tDelay data[6]
static void IcefallCaveIcePerStepCallback(u8 taskId) static void IcefallCaveIcePerStepCallback(u8 taskId)
{ {
s16 x, y; s16 x, y;
u8 tileBehavior; u8 tileBehavior;
u16 *iceStepCount; u16 *iceStepCount;
s16 *data = gTasks[taskId].data; s16 *data = gTasks[taskId].data;
switch (data[1]) switch (tState)
{ {
case 0: case 0:
PlayerGetDestCoords(&x, &y); PlayerGetDestCoords(&x, &y);
data[2] = x; tPrevX = x;
data[3] = y; tPrevY = y;
data[1] = 1; tState = 1;
break; break;
case 1: case 1:
PlayerGetDestCoords(&x, &y); PlayerGetDestCoords(&x, &y);
if (x != data[2] || y != data[3]) // End if player hasn't moved
if (x == tPrevX && y == tPrevY)
return;
tPrevX = x;
tPrevY = y;
tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
if (MetatileBehavior_IsThinIce(tileBehavior) == TRUE)
{ {
data[2] = x; // Thin ice, set it to cracked ice
data[3] = y; MarkIcePuzzleCoordVisited(x, y);
tileBehavior = MapGridGetMetatileBehaviorAt(x, y); tDelay = 4;
if (MetatileBehavior_IsThinIce(tileBehavior) == TRUE) tState = 2;
{ tIceX = x;
MarkIcefallCaveCoordVisited(x, y); tIceY = y;
data[6] = 4; }
data[1] = 2; else if (MetatileBehavior_IsCrackedIce(tileBehavior) == TRUE)
data[4] = x; {
data[5] = y; // Cracked ice, set it to broken ice
} tDelay = 4;
else if (MetatileBehavior_IsCrackedIce(tileBehavior) == TRUE) tState = 3;
{ tIceX = x;
data[6] = 4; tIceY = y;
data[1] = 3;
data[4] = x;
data[5] = y;
}
} }
break; break;
case 2: case 2:
if (data[6] != 0) if (tDelay != 0)
{ {
data[6]--; tDelay--;
} }
else else
{ {
x = data[4]; // Crack ice
y = data[5]; x = tIceX;
y = tIceY;
PlaySE(SE_ICE_CRACK); PlaySE(SE_ICE_CRACK);
MapGridSetMetatileIdAt(x, y, METATILE_SeafoamIslands_CrackedIce); MapGridSetMetatileIdAt(x, y, METATILE_SeafoamIslands_CrackedIce);
CurrentMapDrawMetatileAt(x, y); CurrentMapDrawMetatileAt(x, y);
data[1] = 1; tState = 1;
} }
break; break;
case 3: case 3:
if (data[6] != 0) if (tDelay != 0)
{ {
data[6]--; tDelay--;
} }
else else
{ {
x = data[4]; // Break ice
y = data[5]; x = tIceX;
y = tIceY;
PlaySE(SE_ICE_BREAK); PlaySE(SE_ICE_BREAK);
MapGridSetMetatileIdAt(x, y, METATILE_SeafoamIslands_IceHole); MapGridSetMetatileIdAt(x, y, METATILE_SeafoamIslands_IceHole);
CurrentMapDrawMetatileAt(x, y); CurrentMapDrawMetatileAt(x, y);
VarSet(VAR_TEMP_1, 1); VarSet(VAR_TEMP_1, 1);
data[1] = 1; tState = 1;
} }
break; break;
} }
} }
// This is leftover from pokeruby and effectively a no-op. #undef tState
#undef tPrevX
#undef tPrevY
#undef tIceX
#undef tIceY
#undef tDelay
#define tPrevX data[1]
#define tPrevY data[2]
// Unused. For some reason this was not dummied out like the other RSE-exclusive step callbacks.
static void AshGrassPerStepCallback(u8 taskId) static void AshGrassPerStepCallback(u8 taskId)
{ {
s16 x, y; s16 x, y;
u16 *ashGatherCount; u16 *ashGatherCount;
s16 *data = gTasks[taskId].data; s16 *data = gTasks[taskId].data;
PlayerGetDestCoords(&x, &y); PlayerGetDestCoords(&x, &y);
if (x != data[1] || y != data[2])
// End if player hasn't moved
if (x == tPrevX && y == tPrevY)
return;
tPrevX = x;
tPrevY = y;
if (MetatileBehavior_IsAshGrass((u8)MapGridGetMetatileBehaviorAt(x, y)))
{ {
data[1] = x; // Remove ash from grass
data[2] = y; if (MapGridGetMetatileIdAt(x, y) == METATILE_Fallarbor_AshGrass)
if (MetatileBehavior_IsAshGrass((u8)MapGridGetMetatileBehaviorAt(x, y))) StartAshFieldEffect(x, y, METATILE_Fallarbor_NormalGrass, 4);
{ else
if (MapGridGetMetatileIdAt(x, y) == 0x20a) StartAshFieldEffect(x, y, METATILE_Lavaridge_NormalGrass, 4);
StartAshFieldEffect(x, y, 0x212, 4);
else
StartAshFieldEffect(x, y, 0x206, 4);
}
} }
} }
#undef tPrevX
#undef tPrevY
// Unused. For some reason these were not dummied out like the other RSE-exclusive step callbacks.
static void SetCrackedFloorHoleMetatile(s16 x, s16 y) static void SetCrackedFloorHoleMetatile(s16 x, s16 y)
{ {
MapGridSetMetatileIdAt(x, y, MapGridGetMetatileIdAt(x, y) == 0x22f ? 0x206 : 0x237); MapGridSetMetatileIdAt(x, y, MapGridGetMetatileIdAt(x, y) == METATILE_RSCave_CrackedFloor ? METATILE_RSCave_CrackedFloor_Hole : METATILE_Pacifidlog_SkyPillar_CrackedFloor_Hole);
CurrentMapDrawMetatileAt(x, y); CurrentMapDrawMetatileAt(x, y);
} }
// This is leftover from pokeruby and effectively a no-op. #define tPrevX data[2]
#define tPrevY data[3]
#define tFloor1Delay data[4]
#define tFloor1X data[5]
#define tFloor1Y data[6]
#define tFloor2Delay data[7]
#define tFloor2X data[8]
#define tFloor2Y data[9]
// Unused. See above.
static void CrackedFloorPerStepCallback(u8 taskId) static void CrackedFloorPerStepCallback(u8 taskId)
{ {
s16 x, y; s16 x, y;
@@ -257,40 +308,44 @@ static void CrackedFloorPerStepCallback(u8 taskId)
s16 *data = gTasks[taskId].data; s16 *data = gTasks[taskId].data;
PlayerGetDestCoords(&x, &y); PlayerGetDestCoords(&x, &y);
behavior = MapGridGetMetatileBehaviorAt(x, y); behavior = MapGridGetMetatileBehaviorAt(x, y);
if (data[4] != 0 && (--data[4]) == 0)
SetCrackedFloorHoleMetatile(data[5], data[6]);
if (data[7] != 0 && (--data[7]) == 0) // Update up to 2 previous cracked floor spaces
SetCrackedFloorHoleMetatile(data[8], data[9]); if (tFloor1Delay != 0 && (--tFloor1Delay) == 0)
SetCrackedFloorHoleMetatile(tFloor1X, tFloor1Y);
if (tFloor2Delay != 0 && (--tFloor2Delay) == 0)
SetCrackedFloorHoleMetatile(tFloor2X, tFloor2Y);
if ((x != data[2] || y != data[3])) // End if player hasn't moved
if (x == tPrevX && y == tPrevY)
return;
tPrevX = x;
tPrevY = y;
if (MetatileBehavior_IsCrackedFloor(behavior))
{ {
data[2] = x; if (GetPlayerSpeed() != PLAYER_SPEED_FASTEST)
data[3] = y; VarSet(VAR_ICE_STEP_COUNT, 0); // this var does double duty
if (MetatileBehavior_IsCrackedFloor(behavior))
{
if (GetPlayerSpeed() != 4)
VarSet(VAR_ICE_STEP_COUNT, 0);
if (data[4] == 0) if (tFloor1Delay == 0)
{ {
data[4] = 3; tFloor1Delay = 3;
data[5] = x; tFloor1X = x;
data[6] = y; tFloor1Y = y;
} }
else if (data[7] == 0) else if (tFloor2Delay == 0)
{ {
data[7] = 3; tFloor2Delay = 3;
data[8] = x; tFloor2X = x;
data[9] = y; tFloor2Y = y;
}
} }
} }
} }
// Unused #undef tPrevX
static void SetHasPokedexAndPokemon(void) #undef tPrevY
{ #undef tFloor1Delay
FlagSet(FLAG_SYS_POKEDEX_GET); #undef tFloor1X
FlagSet(FLAG_SYS_POKEMON_GET); #undef tFloor1Y
} #undef tFloor2Delay
#undef tFloor2X
#undef tFloor2Y
+7
View File
@@ -184,6 +184,13 @@ static ALIGNED(2) const u8 sTextColor_StatName[] = { 1, 2, 3 };
static ALIGNED(2) const u8 sTextColor_StatValue[] = { 1, 4, 5 }; static ALIGNED(2) const u8 sTextColor_StatValue[] = { 1, 4, 5 };
static ALIGNED(2) const u8 sTextColor_LocationHeader[] = { 1, 6, 7 }; static ALIGNED(2) const u8 sTextColor_LocationHeader[] = { 1, 6, 7 };
// Unused
static void SetHasPokedexAndPokemon(void)
{
FlagSet(FLAG_SYS_POKEDEX_GET);
FlagSet(FLAG_SYS_POKEMON_GET);
}
static void SetUpStartMenu(void) static void SetUpStartMenu(void)
{ {
sNumStartMenuItems = 0; sNumStartMenuItems = 0;