summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/field_tasks.c933
-rw-r--r--src/metatile_behavior.c32
-rw-r--r--src/secret_base.c181
3 files changed, 668 insertions, 478 deletions
diff --git a/src/field_tasks.c b/src/field_tasks.c
index 187270f7a..760d85369 100644
--- a/src/field_tasks.c
+++ b/src/field_tasks.c
@@ -21,20 +21,40 @@
#include "constants/songs.h"
#include "constants/metatile_labels.h"
+/* This file handles some persistent tasks that run in the overworld.
+ * - Task_RunTimeBasedEvents: Periodically updates local time and RTC events. Also triggers ambient cries.
+ * - Task_MuddySlope: Handles the metatile animation when the player steps on muddy slopes.
+ * - Task_RunPerStepCallback: Calls one of the functions in sPerStepCallbacks, listed below...
+ * . DummyPerStepCallback: Default, does nothing
+ * . AshGrassPerStepCallback: Removes the ash from ash-covered grass that the player steps on.
+ * . FortreeBridgePerStepCallback: Depresses Fortree log bridges that the player steps on.
+ * . PacifidlogBridgePerStepCallback: Submerges Pacifidlog log bridges that the player steps on.
+ * . SootopolisGymIcePerStepCallback: Cracks/breaks ice in Sootopolis Gym that the player steps on.
+ * . EndTruckSequence: Sets the moving truck boxes to their final position when the truck sequence ends.
+ * . SecretBasePerStepCallback: Records the decorations in a friend's secret base that the player steps on.
+ * . CrackedFloorPerStepCallback: 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.
+ */
+
struct PacifidlogMetatileOffsets
{
s8 x;
s8 y;
- u16 tileId;
+ u16 metatileId;
};
-static void DummyPerStepCallback(u8 taskId);
-static void AshGrassPerStepCallback(u8 taskId);
-static void FortreeBridgePerStepCallback(u8 taskId);
-static void PacifidlogBridgePerStepCallback(u8 taskId);
-static void SootopolisGymIcePerStepCallback(u8 taskId);
-static void CrackedFloorPerStepCallback(u8 taskId);
-static void Task_MuddySlope(u8 taskId);
+static void DummyPerStepCallback(u8);
+static void AshGrassPerStepCallback(u8);
+static void FortreeBridgePerStepCallback(u8);
+static void PacifidlogBridgePerStepCallback(u8);
+static void SootopolisGymIcePerStepCallback(u8);
+static void CrackedFloorPerStepCallback(u8);
+static void Task_MuddySlope(u8);
static const TaskFunc sPerStepCallbacks[] =
{
@@ -48,29 +68,35 @@ static const TaskFunc sPerStepCallbacks[] =
[STEP_CB_CRACKED_FLOOR] = CrackedFloorPerStepCallback
};
-// they are in pairs but declared as 1D array
+// Each array has 4 pairs of data, each pair representing two metatiles of a log and their relative position.
+// The 4 pairs are for:
+// 0: If the player is standing on the top of a vertical log
+// 1: If the player is standing on the bottom of a vertical log
+// 2: If the player is standing on the left of a horizontal log
+// 3: If the player is standing on the right of a horizontal log
+// i.e. the element with an offset of 0,0 is the one the player is standing on.
static const struct PacifidlogMetatileOffsets sHalfSubmergedBridgeMetatileOffsets[] =
{
- { 0, 0, METATILE_Pacifidlog_HalfSubmergedLogs_Vertical0}, {0, 1, METATILE_Pacifidlog_HalfSubmergedLogs_Vertical1},
- { 0, -1, METATILE_Pacifidlog_HalfSubmergedLogs_Vertical0}, {0, 0, METATILE_Pacifidlog_HalfSubmergedLogs_Vertical1},
- { 0, 0, METATILE_Pacifidlog_HalfSubmergedLogs_Horizontal0}, {1, 0, METATILE_Pacifidlog_HalfSubmergedLogs_Horizontal1},
- {-1, 0, METATILE_Pacifidlog_HalfSubmergedLogs_Horizontal0}, {0, 0, METATILE_Pacifidlog_HalfSubmergedLogs_Horizontal1}
+ { 0, 0, METATILE_Pacifidlog_HalfSubmergedLogs_VerticalTop}, {0, 1, METATILE_Pacifidlog_HalfSubmergedLogs_VerticalBottom},
+ { 0, -1, METATILE_Pacifidlog_HalfSubmergedLogs_VerticalTop}, {0, 0, METATILE_Pacifidlog_HalfSubmergedLogs_VerticalBottom},
+ { 0, 0, METATILE_Pacifidlog_HalfSubmergedLogs_HorizontalLeft}, {1, 0, METATILE_Pacifidlog_HalfSubmergedLogs_HorizontalRight},
+ {-1, 0, METATILE_Pacifidlog_HalfSubmergedLogs_HorizontalLeft}, {0, 0, METATILE_Pacifidlog_HalfSubmergedLogs_HorizontalRight}
};
static const struct PacifidlogMetatileOffsets sFullySubmergedBridgeMetatileOffsets[] =
{
- { 0, 0, METATILE_Pacifidlog_SubmergedLogs_Vertical0}, {0, 1, METATILE_Pacifidlog_SubmergedLogs_Vertical1},
- { 0, -1, METATILE_Pacifidlog_SubmergedLogs_Vertical0}, {0, 0, METATILE_Pacifidlog_SubmergedLogs_Vertical1},
- { 0, 0, METATILE_Pacifidlog_SubmergedLogs_Horizontal0}, {1, 0, METATILE_Pacifidlog_SubmergedLogs_Horizontal1},
- {-1, 0, METATILE_Pacifidlog_SubmergedLogs_Horizontal0}, {0, 0, METATILE_Pacifidlog_SubmergedLogs_Horizontal1}
+ { 0, 0, METATILE_Pacifidlog_SubmergedLogs_VerticalTop}, {0, 1, METATILE_Pacifidlog_SubmergedLogs_VerticalBottom},
+ { 0, -1, METATILE_Pacifidlog_SubmergedLogs_VerticalTop}, {0, 0, METATILE_Pacifidlog_SubmergedLogs_VerticalBottom},
+ { 0, 0, METATILE_Pacifidlog_SubmergedLogs_HorizontalLeft}, {1, 0, METATILE_Pacifidlog_SubmergedLogs_HorizontalRight},
+ {-1, 0, METATILE_Pacifidlog_SubmergedLogs_HorizontalLeft}, {0, 0, METATILE_Pacifidlog_SubmergedLogs_HorizontalRight}
};
static const struct PacifidlogMetatileOffsets sFloatingBridgeMetatileOffsets[] =
{
- { 0, 0, METATILE_Pacifidlog_FloatingLogs_Vertical0}, {0, 1, METATILE_Pacifidlog_FloatingLogs_Vertical1},
- { 0, -1, METATILE_Pacifidlog_FloatingLogs_Vertical0}, {0, 0, METATILE_Pacifidlog_FloatingLogs_Vertical1},
- { 0, 0, METATILE_Pacifidlog_FloatingLogs_Horizontal0}, {1, 0, METATILE_Pacifidlog_FloatingLogs_Horizontal1},
- {-1, 0, METATILE_Pacifidlog_FloatingLogs_Horizontal0}, {0, 0, METATILE_Pacifidlog_FloatingLogs_Horizontal1}
+ { 0, 0, METATILE_Pacifidlog_FloatingLogs_VerticalTop}, {0, 1, METATILE_Pacifidlog_FloatingLogs_VerticalBottom},
+ { 0, -1, METATILE_Pacifidlog_FloatingLogs_VerticalTop}, {0, 0, METATILE_Pacifidlog_FloatingLogs_VerticalBottom},
+ { 0, 0, METATILE_Pacifidlog_FloatingLogs_HorizontalLeft}, {1, 0, METATILE_Pacifidlog_FloatingLogs_HorizontalRight},
+ {-1, 0, METATILE_Pacifidlog_FloatingLogs_HorizontalLeft}, {0, 0, METATILE_Pacifidlog_FloatingLogs_HorizontalRight}
};
// Each element corresponds to a y coordinate row in the sootopolis gym 1F map.
@@ -104,16 +130,11 @@ static const u16 sSootopolisGymIceRowVars[] =
0
};
-static const u16 sMuddySlopeMetatiles[] = {
- METATILE_General_MuddySlope_Frame0,
- METATILE_General_MuddySlope_Frame3,
- METATILE_General_MuddySlope_Frame2,
- METATILE_General_MuddySlope_Frame1
-};
+#define tCallbackId data[0]
static void Task_RunPerStepCallback(u8 taskId)
{
- int idx = gTasks[taskId].data[0];
+ int idx = gTasks[taskId].tCallbackId;
sPerStepCallbacks[idx](taskId);
}
@@ -121,23 +142,23 @@ static void Task_RunPerStepCallback(u8 taskId)
#define tAmbientCryState data[1]
#define tAmbientCryDelay data[2]
+#define TIME_UPDATE_INTERVAL (1 << 12)
+
static void RunTimeBasedEvents(s16 *data)
{
switch (tState)
{
- case 0:
- if (gMain.vblankCounter1 & 0x1000)
- {
- DoTimeBasedEvents();
- tState++;
- }
- break;
- case 1:
- if (!(gMain.vblankCounter1 & 0x1000))
- {
- tState--;
- }
- break;
+ case 0:
+ if (gMain.vblankCounter1 & TIME_UPDATE_INTERVAL)
+ {
+ DoTimeBasedEvents();
+ tState++;
+ }
+ break;
+ case 1:
+ if (!(gMain.vblankCounter1 & TIME_UPDATE_INTERVAL))
+ tState--;
+ break;
}
}
@@ -153,22 +174,20 @@ static void Task_RunTimeBasedEvents(u8 taskId)
}
#undef tState
-#undef tAmbientCryState
-#undef tAmbientCryDelay
void SetUpFieldTasks(void)
{
if (!FuncIsActiveTask(Task_RunPerStepCallback))
{
- u8 taskId = CreateTask(Task_RunPerStepCallback, 0x50);
- gTasks[taskId].data[0] = 0;
+ u8 taskId = CreateTask(Task_RunPerStepCallback, 80);
+ gTasks[taskId].tCallbackId = STEP_CB_DUMMY;
}
if (!FuncIsActiveTask(Task_MuddySlope))
- CreateTask(Task_MuddySlope, 0x50);
+ CreateTask(Task_MuddySlope, 80);
if (!FuncIsActiveTask(Task_RunTimeBasedEvents))
- CreateTask(Task_RunTimeBasedEvents, 0x50);
+ CreateTask(Task_RunTimeBasedEvents, 80);
}
void ActivatePerStepCallback(u8 callbackId)
@@ -179,17 +198,13 @@ void ActivatePerStepCallback(u8 callbackId)
s32 i;
s16 *data = gTasks[taskId].data;
- for (i = 0; i < 16; i++)
+ for (i = 0; i < NUM_TASK_DATA; i++)
data[i] = 0;
if (callbackId >= ARRAY_COUNT(sPerStepCallbacks))
- {
- data[0] = 0;
- }
+ tCallbackId = STEP_CB_DUMMY;
else
- {
- data[0] = callbackId;
- }
+ tCallbackId = callbackId;
}
}
@@ -200,18 +215,20 @@ void ResetFieldTasksArgs(void)
taskId = FindTaskIdByFunc(Task_RunPerStepCallback);
if (taskId != TASK_NONE)
- {
data = gTasks[taskId].data;
- }
+
taskId = FindTaskIdByFunc(Task_RunTimeBasedEvents);
if (taskId != TASK_NONE)
{
data = gTasks[taskId].data;
- data[1] = 0;
- data[2] = 0;
+ tAmbientCryState = 0;
+ tAmbientCryDelay = 0;
}
}
+#undef tAmbientCryState
+#undef tAmbientCryDelay
+
static void DummyPerStepCallback(u8 taskId)
{
@@ -219,282 +236,377 @@ static void DummyPerStepCallback(u8 taskId)
static const struct PacifidlogMetatileOffsets *GetPacifidlogBridgeMetatileOffsets(const struct PacifidlogMetatileOffsets *offsets, u16 metatileBehavior)
{
- if (MetatileBehavior_IsPacifidlogVerticalLog1(metatileBehavior))
+ if (MetatileBehavior_IsPacifidlogVerticalLogTop(metatileBehavior))
return &offsets[0 * 2];
- else if (MetatileBehavior_IsPacifidlogVerticalLog2(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogVerticalLogBottom(metatileBehavior))
return &offsets[1 * 2];
- else if (MetatileBehavior_IsPacifidlogHorizontalLog1(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogHorizontalLogLeft(metatileBehavior))
return &offsets[2 * 2];
- else if (MetatileBehavior_IsPacifidlogHorizontalLog2(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogHorizontalLogRight(metatileBehavior))
return &offsets[3 * 2];
else
return NULL;
}
-static void SetPacifidlogBridgeMetatiles(const struct PacifidlogMetatileOffsets *offsets, s16 x, s16 y, bool32 redrawMap)
+static void TrySetPacifidlogBridgeMetatiles(const struct PacifidlogMetatileOffsets *offsets, s16 x, s16 y, bool32 redrawMap)
{
offsets = GetPacifidlogBridgeMetatileOffsets(offsets, MapGridGetMetatileBehaviorAt(x, y));
+
+ // If offsets is NULL, position is not a log (don't set it)
if (offsets)
{
- MapGridSetMetatileIdAt(x + offsets[0].x, y + offsets[0].y, offsets[0].tileId);
+ // Set both metatiles of the log
+ MapGridSetMetatileIdAt(x + offsets[0].x, y + offsets[0].y, offsets[0].metatileId);
if (redrawMap)
CurrentMapDrawMetatileAt(x + offsets[0].x, y + offsets[0].y);
- MapGridSetMetatileIdAt(x + offsets[1].x, y + offsets[1].y, offsets[1].tileId);
+ MapGridSetMetatileIdAt(x + offsets[1].x, y + offsets[1].y, offsets[1].metatileId);
if (redrawMap)
CurrentMapDrawMetatileAt(x + offsets[1].x, y + offsets[1].y);
}
}
-static void UpdateHalfSubmergedBridgeMetatiles(s16 x, s16 y, bool32 redrawMap)
+static void TrySetLogBridgeHalfSubmerged(s16 x, s16 y, bool32 redrawMap)
{
- SetPacifidlogBridgeMetatiles(sHalfSubmergedBridgeMetatileOffsets, x, y, redrawMap);
+ TrySetPacifidlogBridgeMetatiles(sHalfSubmergedBridgeMetatileOffsets, x, y, redrawMap);
}
-static void UpdateFullySubmergedBridgeMetatiles(s16 x, s16 y, bool32 redrawMap)
+static void TrySetLogBridgeFullySubmerged(s16 x, s16 y, bool32 redrawMap)
{
- SetPacifidlogBridgeMetatiles(sFullySubmergedBridgeMetatileOffsets, x, y, redrawMap);
+ TrySetPacifidlogBridgeMetatiles(sFullySubmergedBridgeMetatileOffsets, x, y, redrawMap);
}
-static void UpdateFloatingBridgeMetatiles(s16 x, s16 y, bool32 redrawMap)
+static void TrySetLogBridgeFloating(s16 x, s16 y, bool32 redrawMap)
{
- SetPacifidlogBridgeMetatiles(sFloatingBridgeMetatileOffsets, x, y, redrawMap);
+ TrySetPacifidlogBridgeMetatiles(sFloatingBridgeMetatileOffsets, x, y, redrawMap);
}
-static bool32 StandingOnNewPacifidlogBridge(s16 x1, s16 y1, s16 x2, s16 y2)
+// Returns FALSE if player has moved from one end of a log to the other (log should remain submerged).
+// Otherwise it returns TRUE.
+static bool32 ShouldRaisePacifidlogLogs(s16 newX, s16 newY, s16 oldX, s16 oldY)
{
- u16 metatileBehavior = MapGridGetMetatileBehaviorAt(x2, y2);
+ u16 oldBehavior = MapGridGetMetatileBehaviorAt(oldX, oldY);
- if (MetatileBehavior_IsPacifidlogVerticalLog1(metatileBehavior))
+ if (MetatileBehavior_IsPacifidlogVerticalLogTop(oldBehavior))
{
- if (y1 > y2)
+ // Still on same one if moved from top to bottom
+ if (newY > oldY)
return FALSE;
}
- else if (MetatileBehavior_IsPacifidlogVerticalLog2(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogVerticalLogBottom(oldBehavior))
{
- if (y1 < y2)
+ // Still on same one if moved from bottom to top
+ if (newY < oldY)
return FALSE;
}
- else if (MetatileBehavior_IsPacifidlogHorizontalLog1(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogHorizontalLogLeft(oldBehavior))
{
- if (x1 > x2)
+ // Still on same one if moved from left to right
+ if (newX > oldX)
return FALSE;
}
- else if (MetatileBehavior_IsPacifidlogHorizontalLog2(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogHorizontalLogRight(oldBehavior))
{
- if (x1 < x2)
+ // Still on same one if moved from right to left
+ if (newX < oldX)
return FALSE;
}
+
+ // Player is either on a different log or no log at all
return TRUE;
}
-static bool32 StandingOnSamePacifidlogBridge(s16 x1, s16 y1, s16 x2, s16 y2)
+// Returns FALSE if player has moved from one end of a log to the other (log should remain submerged).
+// Otherwise it returns TRUE.
+// This is the effectively the same as ShouldRaisePacifidlogLogs, as it swaps both the conditions and which position's behavior to check.
+// In effect the previous function asks "was the player's previous position not the other end of a log they're standing on?"
+// while this function asks "is the player's current position not the other end of a log they were previously standing on?"
+// and with the same positions both questions always have the same answer.
+static bool32 ShouldSinkPacifidlogLogs(s16 newX, s16 newY, s16 oldX, s16 oldY)
{
- u16 metatileBehavior = MapGridGetMetatileBehaviorAt(x1, y1);
+ u16 newBehavior = MapGridGetMetatileBehaviorAt(newX, newY);
- if (MetatileBehavior_IsPacifidlogVerticalLog1(metatileBehavior))
+ if (MetatileBehavior_IsPacifidlogVerticalLogTop(newBehavior))
{
- if (y1 < y2)
+ // Still on same one if moved from bottom to top
+ if (newY < oldY)
return FALSE;
}
- else if (MetatileBehavior_IsPacifidlogVerticalLog2(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogVerticalLogBottom(newBehavior))
{
- if (y1 > y2)
+ // Still on same one if moved from top to bottom
+ if (newY > oldY)
return FALSE;
}
- else if (MetatileBehavior_IsPacifidlogHorizontalLog1(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogHorizontalLogLeft(newBehavior))
{
- if (x1 < x2)
+ // Still on same one if moved from right to left
+ if (newX < oldX)
return FALSE;
}
- else if (MetatileBehavior_IsPacifidlogHorizontalLog2(metatileBehavior))
+ else if (MetatileBehavior_IsPacifidlogHorizontalLogRight(newBehavior))
{
- if (x1 > x2)
+ // Still on same one if moved from left to right
+ if (newX > oldX)
return FALSE;
}
return TRUE;
}
+#define tState data[1]
+#define tPrevX data[2]
+#define tPrevY data[3]
+#define tToRaiseX data[4]
+#define tToRaiseY data[5]
+#define tDelay data[6]
+
static void PacifidlogBridgePerStepCallback(u8 taskId)
{
s16 *data;
s16 x, y;
data = gTasks[taskId].data;
PlayerGetDestCoords(&x, &y);
- switch (data[1])
+ switch (tState)
{
- case 0:
- data[2] = x;
- data[3] = y;
- UpdateFullySubmergedBridgeMetatiles(x, y, TRUE);
- data[1] = 1;
- break;
- case 1:
- if (x != data[2] || y != data[3])
- {
- if (StandingOnNewPacifidlogBridge(x, y, data[2], data[3]))
- {
- UpdateHalfSubmergedBridgeMetatiles(data[2], data[3], TRUE);
- UpdateFloatingBridgeMetatiles(data[2], data[3], FALSE);
- data[4] = data[2];
- data[5] = data[3];
- data[1] = 2;
- data[6] = 8;
- }
- else
- {
- data[4] = -1;
- data[5] = -1;
- }
+ case 0:
+ tPrevX = x;
+ tPrevY = y;
+
+ // If player is already standing on a log when the callback
+ // is set then immediately set it to submerged
+ TrySetLogBridgeFullySubmerged(x, y, TRUE);
+ tState = 1;
+ break;
+ case 1:
+ // Skip if player hasn't moved
+ if (x == tPrevX && y == tPrevY)
+ return;
+
+ if (ShouldRaisePacifidlogLogs(x, y, tPrevX, tPrevY))
+ {
+ // Player's previous position is not the other end of a log
+ // they're standing on, try and set it half-submerged (rising to surface).
+ // The floating metatile is queued up by setting it but not drawing it,
+ // but this is pointless as state 2 will handle it in full anyway.
+ TrySetLogBridgeHalfSubmerged(tPrevX, tPrevY, TRUE);
+ TrySetLogBridgeFloating(tPrevX, tPrevY, FALSE);
+ tToRaiseX = tPrevX;
+ tToRaiseY = tPrevY;
+ tState = 2;
+ tDelay = 8;
+ }
+ else
+ {
+ // Player has moved but is still on the same log bridge section.
+ // Keep it submerged.
+ tToRaiseX = -1;
+ tToRaiseY = -1;
+ }
- if (StandingOnSamePacifidlogBridge(x, y, data[2], data[3]))
- {
- UpdateHalfSubmergedBridgeMetatiles(x, y, TRUE);
- data[1] = 2;
- data[6] = 8;
- }
+ if (ShouldSinkPacifidlogLogs(x, y, tPrevX, tPrevY))
+ {
+ // Player's current position is not the other end of a log
+ // they were previously standing on, try and set it half-submerged (sinking)
+ TrySetLogBridgeHalfSubmerged(x, y, TRUE);
+ tState = 2;
+ tDelay = 8;
+ }
- data[2] = x;
- data[3] = y;
- if (MetatileBehavior_IsPacifidlogLog(MapGridGetMetatileBehaviorAt(x, y)))
- PlaySE(SE_PUDDLE);
- }
- break;
- case 2:
- if ((--data[6]) == 0)
- {
- UpdateFullySubmergedBridgeMetatiles(x, y, TRUE);
- if (data[4] != -1 && data[5] != -1)
- UpdateFloatingBridgeMetatiles(data[4], data[5], TRUE);
+ tPrevX = x;
+ tPrevY = y;
- data[1] = 1;
- }
- break;
+ // If player's new position is a log play the puddle SE
+ if (MetatileBehavior_IsPacifidlogLog(MapGridGetMetatileBehaviorAt(x, y)))
+ PlaySE(SE_PUDDLE);
+ break;
+ case 2:
+ if (--tDelay == 0)
+ {
+ // If player's current position is a log submerge it fully.
+ TrySetLogBridgeFullySubmerged(x, y, TRUE);
+
+ // Player's previous position is not the other end of a log
+ // they're standing on, try to raise their previous position.
+ if (tToRaiseX != -1 && tToRaiseY != -1)
+ TrySetLogBridgeFloating(tToRaiseX, tToRaiseY, TRUE);
+
+ tState = 1;
+ }
+ break;
}
}
-static void SetLoweredForetreeBridgeMetatile(s16 x, s16 y)
+#undef tState
+#undef tPrevX
+#undef tPrevY
+#undef tToRaiseX
+#undef tToRaiseY
+#undef tDelay
+
+static void TryLowerFortreeBridge(s16 x, s16 y)
{
u8 z = PlayerGetZCoord();
if (!(z & 1))
{
switch (MapGridGetMetatileIdAt(x, y))
{
- case METATILE_Fortree_BridgeOverGrass_Raised:
- MapGridSetMetatileIdAt(x, y, METATILE_Fortree_BridgeOverGrass_Lowered);
- break;
- case METATILE_Fortree_BridgeOverTrees_Raised:
- MapGridSetMetatileIdAt(x, y, METATILE_Fortree_BridgeOverTrees_Lowered);
- break;
+ case METATILE_Fortree_BridgeOverGrass_Raised:
+ MapGridSetMetatileIdAt(x, y, METATILE_Fortree_BridgeOverGrass_Lowered);
+ break;
+ case METATILE_Fortree_BridgeOverTrees_Raised:
+ MapGridSetMetatileIdAt(x, y, METATILE_Fortree_BridgeOverTrees_Lowered);
+ break;
}
}
}
-static void SetNormalFortreeBridgeMetatile(s16 x, s16 y)
+static void TryRaiseFortreeBridge(s16 x, s16 y)
{
u8 z = PlayerGetZCoord();
if (!(z & 1))
{
switch (MapGridGetMetatileIdAt(x, y))
{
- case METATILE_Fortree_BridgeOverGrass_Lowered:
- MapGridSetMetatileIdAt(x, y, METATILE_Fortree_BridgeOverGrass_Raised);
- break;
- case METATILE_Fortree_BridgeOverTrees_Lowered:
- MapGridSetMetatileIdAt(x, y, METATILE_Fortree_BridgeOverTrees_Raised);
- break;
+ case METATILE_Fortree_BridgeOverGrass_Lowered:
+ MapGridSetMetatileIdAt(x, y, METATILE_Fortree_BridgeOverGrass_Raised);
+ break;
+ case METATILE_Fortree_BridgeOverTrees_Lowered:
+ MapGridSetMetatileIdAt(x, y, METATILE_Fortree_BridgeOverTrees_Raised);
+ break;
}
}
}
+#define tState data[1]
+#define tPrevX data[2]
+#define tPrevY data[3]
+#define tOldBridgeX data[4]
+#define tOldBridgeY data[5]
+#define tBounceTime data[6]
+
static void FortreeBridgePerStepCallback(u8 taskId)
{
bool8 isFortreeBridgeCur;
bool8 isFortreeBridgePrev;
- u8 z, flag;
- s16 x, y, x2, y2;
+ u8 z, onBridgeElevation;
+ s16 x, y, prevX, prevY;
s16 *data = gTasks[taskId].data;
PlayerGetDestCoords(&x, &y);
- switch (data[1])
+ switch (tState)
{
- default:
- break;
- case 0:
- data[2] = x;
- data[3] = y;
- if (MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x, y)))
- {
- SetLoweredForetreeBridgeMetatile(x, y);
- CurrentMapDrawMetatileAt(x, y);
- }
- data[1] = 1;
+ default:
+ break;
+ case 0:
+ tPrevX = x;
+ tPrevY = y;
+
+ // If player is already on bridge when callback is set then lower it immediately.
+ if (MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x, y)))
+ {
+ TryLowerFortreeBridge(x, y);
+ CurrentMapDrawMetatileAt(x, y);
+ }
+ tState = 1;
+ break;
+ case 1:
+ prevX = tPrevX;
+ prevY = tPrevY;
+
+ // Skip if player hasn't moved
+ if (x == prevX && y == prevY)
break;
- case 1:
- x2 = data[2];
- y2 = data[3];
- if (x == x2 && y == y2)
- break;
-
- isFortreeBridgeCur = MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x, y));
- isFortreeBridgePrev = MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x2, y2));
- z = PlayerGetZCoord();
- flag = 0;
- if ((u8)(z & 1) == 0)
- flag = 1;
-
- if (flag && (isFortreeBridgeCur == 1 || isFortreeBridgePrev == 1))
- PlaySE(SE_BRIDGE_WALK);
-
- if (isFortreeBridgePrev)
- {
- SetNormalFortreeBridgeMetatile(x2, y2);
- CurrentMapDrawMetatileAt(x2, y2);
- SetLoweredForetreeBridgeMetatile(x, y);
- CurrentMapDrawMetatileAt(x, y);
- }
- data[4] = x2;
- data[5] = y2;
- data[2] = x;
- data[3] = y;
- if (!isFortreeBridgePrev)
- break;
+ isFortreeBridgeCur = MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x, y));
+ isFortreeBridgePrev = MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(prevX, prevY));
+
+ // Make sure player isn't below bridge
+ z = PlayerGetZCoord();
+ onBridgeElevation = FALSE;
+ if ((u8)(z & 1) == 0)
+ onBridgeElevation = TRUE;
+
+ if (onBridgeElevation && (isFortreeBridgeCur == TRUE || isFortreeBridgePrev == TRUE))
+ PlaySE(SE_BRIDGE_WALK);
+
+ // Because this doesn't check for isFortreeBridgeCur, bridge sections aren't
+ // lowered when first stepping onto them from anything other than another bridge.
+ #ifdef BUGFIX
+ if (isFortreeBridgePrev || isFortreeBridgeCur)
+ #else
+ if (isFortreeBridgePrev)
+ #endif
+ {
+ // Raise old bridge
+ TryRaiseFortreeBridge(prevX, prevY);
+ CurrentMapDrawMetatileAt(prevX, prevY);
+
+ // Lower new bridge
+ TryLowerFortreeBridge(x, y);
+ CurrentMapDrawMetatileAt(x, y);
+ }
+
+ // These should really be set below the !isFortreeBridgePrev conditional,
+ // but it doesn't matter because it's not read until case 2 anyway.
+ tOldBridgeX = prevX;
+ tOldBridgeY = prevY;
+
+ tPrevX = x;
+ tPrevY = y;
+ if (!isFortreeBridgePrev)
+ break;
- data[6] = 16;
- data[1] = 2;
- // fallthrough
+ tBounceTime = 16;
+ tState = 2;
+ // fallthrough
+ case 2:
+ tBounceTime--;
+ prevX = tOldBridgeX;
+ prevY = tOldBridgeY;
+ switch (tBounceTime % 7)
+ {
+ case 0:
+ CurrentMapDrawMetatileAt(prevX, prevY);
+ case 1:
case 2:
- data[6]--;
- x2 = data[4];
- y2 = data[5];
- switch (data[6] % 7)
- {
- case 0:
- CurrentMapDrawMetatileAt(x2, y2);
- case 1:
- case 2:
- case 3:
- break;
- case 4:
- SetLoweredForetreeBridgeMetatile(x2, y2);
- CurrentMapDrawMetatileAt(x2, y2);
- SetNormalFortreeBridgeMetatile(x2, y2);
- case 5:
- case 6:
- case 7:
- break;
- }
- if (data[6] == 0)
- {
- data[1] = 1;
- }
+ case 3:
break;
+ case 4:
+ // Bounce bridge section that player has stepped off of
+ TryLowerFortreeBridge(prevX, prevY);
+ CurrentMapDrawMetatileAt(prevX, prevY);
+ TryRaiseFortreeBridge(prevX, prevY);
+ case 5:
+ case 6:
+ case 7: // Not possible with % 7
+ break;
+ }
+ if (tBounceTime == 0)
+ tState = 1;
+ break;
}
}
+#undef tState
+#undef tPrevX
+#undef tPrevY
+#undef tOldBridgeX
+#undef tOldBridgeY
+#undef tBounceTime
+
+// Boundaries of the ice puzzle in Sootopolis Gym
+#define ICE_PUZZLE_L 3
+#define ICE_PUZZLE_R 13
+#define ICE_PUZZLE_T 6
+#define ICE_PUZZLE_B 19
+
+#define ICE_PUZZLE_WIDTH (ICE_PUZZLE_R - ICE_PUZZLE_L + 1)
+#define ICE_PUZZLE_HEIGHT (ICE_PUZZLE_B - ICE_PUZZLE_T + 1)
+
static bool32 CoordInIcePuzzleRegion(s16 x, s16 y)
{
- if ((u16)(x - 3) < 11 && (u16)(y - 6) < 14 && sSootopolisGymIceRowVars[y])
+ if ((u16)(x - ICE_PUZZLE_L) < ICE_PUZZLE_WIDTH
+ && (u16)(y - ICE_PUZZLE_T) < ICE_PUZZLE_HEIGHT
+ && sSootopolisGymIceRowVars[y])
return TRUE;
else
return FALSE;
@@ -503,17 +615,17 @@ static bool32 CoordInIcePuzzleRegion(s16 x, s16 y)
static void MarkIcePuzzleCoordVisited(s16 x, s16 y)
{
if (CoordInIcePuzzleRegion(x, y))
- *GetVarPointer(sSootopolisGymIceRowVars[y]) |= (1 << (x - 3));
+ *GetVarPointer(sSootopolisGymIceRowVars[y]) |= (1 << (x - ICE_PUZZLE_L));
}
static bool32 IsIcePuzzleCoordVisited(s16 x, s16 y)
{
- u32 var;
+ u16 var;
if (!CoordInIcePuzzleRegion(x, y))
return FALSE;
- var = VarGet(sSootopolisGymIceRowVars[y]) << 16;
- if ((0x10000 << (x - 3)) & var) // TODO: fix that if
+ var = VarGet(sSootopolisGymIceRowVars[y]);
+ if (var &= (1 << (x - ICE_PUZZLE_L)))
return TRUE;
else
return FALSE;
@@ -534,116 +646,155 @@ void SetSootopolisGymCrackedIceMetatiles(void)
}
}
+#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 SootopolisGymIcePerStepCallback(u8 taskId)
{
s16 x, y;
u16 tileBehavior;
u16 *iceStepCount;
s16 *data = gTasks[taskId].data;
- switch (data[1])
+ switch (tState)
{
- case 0:
- PlayerGetDestCoords(&x, &y);
- data[2] = x;
- data[3] = y;
- data[1] = 1;
- break;
- case 1:
- PlayerGetDestCoords(&x, &y);
- if (x != data[2] || y != data[3])
- {
- data[2] = x;
- data[3] = y;
- tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
- iceStepCount = GetVarPointer(VAR_ICE_STEP_COUNT);
- if (MetatileBehavior_IsThinIce(tileBehavior) == TRUE)
- {
- (*iceStepCount)++;
- data[6] = 4;
- data[1] = 2;
- data[4] = x;
- data[5] = y;
- }
- else if (MetatileBehavior_IsCrackedIce(tileBehavior) == TRUE)
- {
- *iceStepCount = 0;
- data[6] = 4;
- data[1] = 3;
- data[4] = x;
- data[5] = y;
- }
- }
- break;
- case 2:
- if (data[6] != 0)
- {
- data[6]--;
- }
- else
- {
- x = data[4];
- y = data[5];
- PlaySE(SE_ICE_CRACK);
- MapGridSetMetatileIdAt(x, y, METATILE_SootopolisGym_Ice_Cracked);
- CurrentMapDrawMetatileAt(x, y);
- MarkIcePuzzleCoordVisited(x - MAP_OFFSET, y - MAP_OFFSET);
- data[1] = 1;
- }
- break;
- case 3:
- if (data[6] != 0)
- {
- data[6]--;
- }
- else
- {
- x = data[4];
- y = data[5];
- PlaySE(SE_ICE_BREAK);
- MapGridSetMetatileIdAt(x, y, METATILE_SootopolisGym_Ice_Broken);
- CurrentMapDrawMetatileAt(x, y);
- data[1] = 1;
- }
- break;
+ case 0:
+ PlayerGetDestCoords(&x, &y);
+ tPrevX = x;
+ tPrevY = y;
+ tState = 1;
+ break;
+ case 1:
+ PlayerGetDestCoords(&x, &y);
+ // End if player hasn't moved
+ if (x == tPrevX && y == tPrevY)
+ return;
+
+ tPrevX = x;
+ tPrevY = y;
+ tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
+ iceStepCount = GetVarPointer(VAR_ICE_STEP_COUNT);
+ if (MetatileBehavior_IsThinIce(tileBehavior) == TRUE)
+ {
+ // Thin ice, set it to cracked ice
+ (*iceStepCount)++;
+ tDelay = 4;
+ tState = 2;
+ tIceX = x;
+ tIceY = y;
+ }
+ else if (MetatileBehavior_IsCrackedIce(tileBehavior) == TRUE)
+ {
+ // Cracked ice, set it to broken ice
+ *iceStepCount = 0;
+ tDelay = 4;
+ tState = 3;
+ tIceX = x;
+ tIceY = y;
+ }
+ break;
+ case 2:
+ if (tDelay != 0)
+ {
+ tDelay--;
+ }
+ else
+ {
+ // Crack ice
+ x = tIceX;
+ y = tIceY;
+ PlaySE(SE_ICE_CRACK);
+ MapGridSetMetatileIdAt(x, y, METATILE_SootopolisGym_Ice_Cracked);
+ CurrentMapDrawMetatileAt(x, y);
+ MarkIcePuzzleCoordVisited(x - MAP_OFFSET, y - MAP_OFFSET);
+ tState = 1;
+ }
+ break;
+ case 3:
+ if (tDelay != 0)
+ {
+ tDelay--;
+ }
+ else
+ {
+ // Break ice
+ x = tIceX;
+ y = tIceY;
+ PlaySE(SE_ICE_BREAK);
+ MapGridSetMetatileIdAt(x, y, METATILE_SootopolisGym_Ice_Broken);
+ CurrentMapDrawMetatileAt(x, y);
+ tState = 1;
+ }
+ break;
}
}
+#undef tState
+#undef tPrevX
+#undef tPrevY
+#undef tIceX
+#undef tIceY
+#undef tDelay
+
+#define tPrevX data[1]
+#define tPrevY data[2]
+
static void AshGrassPerStepCallback(u8 taskId)
{
s16 x, y;
u16 *ashGatherCount;
s16 *data = gTasks[taskId].data;
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(MapGridGetMetatileBehaviorAt(x, y)))
{
- data[1] = x;
- data[2] = y;
- if (MetatileBehavior_IsAshGrass(MapGridGetMetatileBehaviorAt(x, y)))
- {
- if (MapGridGetMetatileIdAt(x, y) == METATILE_Fallarbor_AshGrass)
- StartAshFieldEffect(x, y, METATILE_Fallarbor_NormalGrass, 4);
- else
- StartAshFieldEffect(x, y, METATILE_Lavaridge_NormalGrass, 4);
+ // Remove ash from grass
+ if (MapGridGetMetatileIdAt(x, y) == METATILE_Fallarbor_AshGrass)
+ StartAshFieldEffect(x, y, METATILE_Fallarbor_NormalGrass, 4);
+ else
+ StartAshFieldEffect(x, y, METATILE_Lavaridge_NormalGrass, 4);
- if (CheckBagHasItem(ITEM_SOOT_SACK, 1))
- {
- ashGatherCount = GetVarPointer(VAR_ASH_GATHER_COUNT);
- if (*ashGatherCount < 9999)
- (*ashGatherCount)++;
- }
+ // Try to gather ash
+ if (CheckBagHasItem(ITEM_SOOT_SACK, 1))
+ {
+ ashGatherCount = GetVarPointer(VAR_ASH_GATHER_COUNT);
+ if (*ashGatherCount < 9999)
+ (*ashGatherCount)++;
}
}
}
+#undef tPrevX
+#undef tPrevY
+
// This function uses the constants for gTileset_Cave's metatile labels, but other tilesets with
// the CrackedFloorPerStepCallback callback use the same metatile numbers for the cracked floor
// and hole metatiles, such as gTileset_MirageTower.
static void SetCrackedFloorHoleMetatile(s16 x, s16 y)
{
- MapGridSetMetatileIdAt(x, y, MapGridGetMetatileIdAt(x, y) == METATILE_Cave_CrackedFloor ? METATILE_Cave_CrackedFloor_Hole : METATILE_Pacifidlog_SkyPillar_CrackedFloor_Hole);
+ u16 metatileId = MapGridGetMetatileIdAt(x, y) == METATILE_Cave_CrackedFloor ? METATILE_Cave_CrackedFloor_Hole : METATILE_Pacifidlog_SkyPillar_CrackedFloor_Hole;
+ MapGridSetMetatileIdAt(x, y, metatileId);
CurrentMapDrawMetatileAt(x, y);
}
+#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]
+
static void CrackedFloorPerStepCallback(u8 taskId)
{
s16 x, y;
@@ -651,113 +802,153 @@ static void CrackedFloorPerStepCallback(u8 taskId)
s16 *data = gTasks[taskId].data;
PlayerGetDestCoords(&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)
- SetCrackedFloorHoleMetatile(data[8], data[9]);
+ // Update up to 2 previous cracked floor spaces
+ if (tFloor1Delay != 0 && (--tFloor1Delay) == 0)
+ SetCrackedFloorHoleMetatile(tFloor1X, tFloor1Y);
+ if (tFloor2Delay != 0 && (--tFloor2Delay) == 0)
+ SetCrackedFloorHoleMetatile(tFloor2X, tFloor2Y);
if (MetatileBehavior_IsCrackedFloorHole(behavior))
VarSet(VAR_ICE_STEP_COUNT, 0); // this var does double duty
- 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;
- data[3] = y;
- if (MetatileBehavior_IsCrackedFloor(behavior))
- {
- if (GetPlayerSpeed() != 4)
- VarSet(VAR_ICE_STEP_COUNT, 0); // this var does double duty
+ if (GetPlayerSpeed() != BIKE_SPEED_FASTEST)
+ VarSet(VAR_ICE_STEP_COUNT, 0); // this var does double duty
- if (data[4] == 0)
- {
- data[4] = 3;
- data[5] = x;
- data[6] = y;
- }
- else if (data[7] == 0)
- {
- data[7] = 3;
- data[8] = x;
- data[9] = y;
- }
+ if (tFloor1Delay == 0)
+ {
+ tFloor1Delay = 3;
+ tFloor1X = x;
+ tFloor1Y = y;
+ }
+ else if (tFloor2Delay == 0)
+ {
+ tFloor2Delay = 3;
+ tFloor2X = x;
+ tFloor2Y = y;
}
}
}
+#undef tPrevX
+#undef tPrevY
+#undef tFloor1Delay
+#undef tFloor1X
+#undef tFloor1Y
+#undef tFloor2Delay
+#undef tFloor2X
+#undef tFloor2Y
+
+#define tMapId data[0]
+#define tState data[1]
+#define tPrevX data[2]
+#define tPrevY data[3]
+// data[4] - data[15] are data about up to 4 individual animating muddy slope metatiles
+// They're divided into groups of 3, i.e data[4]-[6] track one metatile, data[7]-[9] another, and so on.
+// For each data triplet, the 1sst is the animation time, and the 2nd/3rd are the x/y coordinates.
+#define SLOPE_DATA_START 4
+#define SLOPE_DATA_END (3 * SLOPE_DATA_SIZE + SLOPE_DATA_START) // 13, which is the last slope data start point
+enum {
+ SLOPE_TIME,
+ SLOPE_X,
+ SLOPE_Y,
+ SLOPE_DATA_SIZE
+};
+#define tSlopeAnimTime(i) data[(i) * SLOPE_DATA_SIZE + SLOPE_DATA_START + SLOPE_TIME]
+
+static const u16 sMuddySlopeMetatiles[] = {
+ METATILE_General_MuddySlope_Frame0,
+ METATILE_General_MuddySlope_Frame3,
+ METATILE_General_MuddySlope_Frame2,
+ METATILE_General_MuddySlope_Frame1
+};
+
+#define SLOPE_ANIM_TIME 32
+#define SLOPE_ANIM_STEP_TIME (SLOPE_ANIM_TIME / (int)ARRAY_COUNT(sMuddySlopeMetatiles))
+
static void SetMuddySlopeMetatile(s16 *data, s16 x, s16 y)
{
- u16 tile;
- if ((--data[0]) == 0)
- tile = METATILE_General_MuddySlope_Frame0;
+ u16 metatileId;
+ if ((--data[SLOPE_TIME]) == 0)
+ metatileId = METATILE_General_MuddySlope_Frame0;
else
- tile = sMuddySlopeMetatiles[data[0] / 8];
+ metatileId = sMuddySlopeMetatiles[data[SLOPE_TIME] / SLOPE_ANIM_STEP_TIME];
- MapGridSetMetatileIdAt(x, y, tile);
+ MapGridSetMetatileIdAt(x, y, metatileId);
CurrentMapDrawMetatileAt(x, y);
MapGridSetMetatileIdAt(x, y, METATILE_General_MuddySlope_Frame0);
}
static void Task_MuddySlope(u8 taskId)
{
- s16 x, y, x2, y2;
+ s16 x, y, cameraOffsetX, cameraOffsetY;
int i;
u16 mapId;
s16 *data = gTasks[taskId].data;
PlayerGetDestCoords(&x, &y);
mapId = (gSaveBlock1Ptr->location.mapGroup << 8) | gSaveBlock1Ptr->location.mapNum;
- switch (data[1])
+ switch (tState)
{
- case 0:
- data[0] = mapId;
- data[2] = x;
- data[3] = y;
- data[1] = 1;
- data[4] = 0;
- data[7] = 0;
- data[10] = 0;
- data[13] = 0;
+ case 0:
+ tMapId = mapId;
+ tPrevX = x;
+ tPrevY = y;
+ tState = 1;
+ tSlopeAnimTime(0) = 0;
+ tSlopeAnimTime(1) = 0;
+ tSlopeAnimTime(2) = 0;
+ tSlopeAnimTime(3) = 0;
+ break;
+ case 1:
+ // Skip if player hasn't moved
+ if (tPrevX == x && tPrevY == y)
break;
- case 1:
- if (data[2] != x || data[3] != y)
+
+ tPrevX = x;
+ tPrevY = y;
+ if (MetatileBehavior_IsMuddySlope(MapGridGetMetatileBehaviorAt(x, y)))
+ {
+ for (i = SLOPE_DATA_START; i <= SLOPE_DATA_END; i += SLOPE_DATA_SIZE)
{
- data[2] = x;
- data[3] = y;
- if (MetatileBehavior_IsMuddySlope(MapGridGetMetatileBehaviorAt(x, y)))
+ if (data[i] == 0)
{
- for (i = 4; i < 14; i += 3)
- {
- if (data[i] == 0)
- {
- data[i] = 32;
- data[i + 1] = x;
- data[i + 2] = y;
- break;
- }
- }
+ data[i + SLOPE_TIME] = SLOPE_ANIM_TIME;
+ data[i + SLOPE_X] = x;
+ data[i + SLOPE_Y] = y;
+ break;
}
}
- break;
+ }
+ break;
}
- if (gCamera.active && mapId != data[0])
+
+ if (gCamera.active && mapId != tMapId)
{
- data[0] = mapId;
- x2 = gCamera.x;
- y2 = gCamera.y;
+ tMapId = mapId;
+ cameraOffsetX = gCamera.x;
+ cameraOffsetY = gCamera.y;
}
else
{
- x2 = 0;
- y2 = 0;
+ cameraOffsetX = 0;
+ cameraOffsetY = 0;
}
- for (i = 4; i < 14; i += 3)
+ for (i = SLOPE_DATA_START; i <= SLOPE_DATA_END; i += SLOPE_DATA_SIZE)
{
- if (data[i])
+ if (data[i + SLOPE_TIME])
{
- data[i + 1] -= x2;
- data[i + 2] -= y2;
- SetMuddySlopeMetatile(&data[i], data[i + 1], data[i + 2]);
+ data[i + SLOPE_X] -= cameraOffsetX;
+ data[i + SLOPE_Y] -= cameraOffsetY;
+ SetMuddySlopeMetatile(&data[i + SLOPE_TIME], data[i + SLOPE_X], data[i + SLOPE_Y]);
}
}
}
diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c
index ad5eb42cc..6b58e3f05 100644
--- a/src/metatile_behavior.c
+++ b/src/metatile_behavior.c
@@ -126,10 +126,10 @@ static const u8 sTileBitAttributes[] =
[MB_BRIDGE_OVER_POND_LOW] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
[MB_BRIDGE_OVER_POND_MED] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
[MB_BRIDGE_OVER_POND_HIGH] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
- [MB_PACIFIDLOG_VERTICAL_LOG_1] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
- [MB_PACIFIDLOG_VERTICAL_LOG_2] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
- [MB_PACIFIDLOG_HORIZONTAL_LOG_1] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
- [MB_PACIFIDLOG_HORIZONTAL_LOG_2] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
+ [MB_PACIFIDLOG_VERTICAL_LOG_TOP] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
+ [MB_PACIFIDLOG_VERTICAL_LOG_BOTTOM] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
+ [MB_PACIFIDLOG_HORIZONTAL_LOG_LEFT] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
+ [MB_PACIFIDLOG_HORIZONTAL_LOG_RIGHT] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
[MB_FORTREE_BRIDGE] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
[MB_UNUSED_79] = TILE_ATTRIBUTES(FALSE, FALSE, FALSE),
[MB_BRIDGE_OVER_POND_MED_EDGE_1] = TILE_ATTRIBUTES(TRUE, FALSE, FALSE),
@@ -1131,33 +1131,33 @@ bool8 MetatileBehavior_IsFortreeBridge(u8 metatileBehavior)
return FALSE;
}
-bool8 MetatileBehavior_IsPacifidlogVerticalLog1(u8 metatileBehavior)
+bool8 MetatileBehavior_IsPacifidlogVerticalLogTop(u8 metatileBehavior)
{
- if (metatileBehavior == MB_PACIFIDLOG_VERTICAL_LOG_1)
+ if (metatileBehavior == MB_PACIFIDLOG_VERTICAL_LOG_TOP)
return TRUE;
else
return FALSE;
}
-bool8 MetatileBehavior_IsPacifidlogVerticalLog2(u8 metatileBehavior)
+bool8 MetatileBehavior_IsPacifidlogVerticalLogBottom(u8 metatileBehavior)
{
- if (metatileBehavior == MB_PACIFIDLOG_VERTICAL_LOG_2)
+ if (metatileBehavior == MB_PACIFIDLOG_VERTICAL_LOG_BOTTOM)
return TRUE;
else
return FALSE;
}
-bool8 MetatileBehavior_IsPacifidlogHorizontalLog1(u8 metatileBehavior)
+bool8 MetatileBehavior_IsPacifidlogHorizontalLogLeft(u8 metatileBehavior)
{
- if (metatileBehavior == MB_PACIFIDLOG_HORIZONTAL_LOG_1)
+ if (metatileBehavior == MB_PACIFIDLOG_HORIZONTAL_LOG_LEFT)
return TRUE;
else
return FALSE;
}
-bool8 MetatileBehavior_IsPacifidlogHorizontalLog2(u8 metatileBehavior)
+bool8 MetatileBehavior_IsPacifidlogHorizontalLogRight(u8 metatileBehavior)
{
- if (metatileBehavior == MB_PACIFIDLOG_HORIZONTAL_LOG_2)
+ if (metatileBehavior == MB_PACIFIDLOG_HORIZONTAL_LOG_RIGHT)
return TRUE;
else
return FALSE;
@@ -1165,10 +1165,10 @@ bool8 MetatileBehavior_IsPacifidlogHorizontalLog2(u8 metatileBehavior)
bool8 MetatileBehavior_IsPacifidlogLog(u8 metatileBehavior)
{
- if (metatileBehavior == MB_PACIFIDLOG_VERTICAL_LOG_1
- || metatileBehavior == MB_PACIFIDLOG_VERTICAL_LOG_2
- || metatileBehavior == MB_PACIFIDLOG_HORIZONTAL_LOG_1
- || metatileBehavior == MB_PACIFIDLOG_HORIZONTAL_LOG_2)
+ if (metatileBehavior == MB_PACIFIDLOG_VERTICAL_LOG_TOP
+ || metatileBehavior == MB_PACIFIDLOG_VERTICAL_LOG_BOTTOM
+ || metatileBehavior == MB_PACIFIDLOG_HORIZONTAL_LOG_LEFT
+ || metatileBehavior == MB_PACIFIDLOG_HORIZONTAL_LOG_RIGHT)
return TRUE;
else
return FALSE;
diff --git a/src/secret_base.c b/src/secret_base.c
index f971e24f6..8fc97141f 100644
--- a/src/secret_base.c
+++ b/src/secret_base.c
@@ -1214,108 +1214,107 @@ void SecretBasePerStepCallback(u8 taskId)
tState = 1;
break;
case 1:
+ // End if player hasn't moved
PlayerGetDestCoords(&x, &y);
- if (x != tPlayerX || y != tPlayerY)
+ if (x == tPlayerX && y == tPlayerY)
+ return;
+
+ tPlayerX = x;
+ tPlayerY = y;
+ VarSet(VAR_SECRET_BASE_STEP_COUNTER, VarGet(VAR_SECRET_BASE_STEP_COUNTER) + 1);
+ behavior = MapGridGetMetatileBehaviorAt(x, y);
+ tileId = MapGridGetMetatileIdAt(x, y);
+ if (tileId == METATILE_SecretBase_SolidBoard_Top || tileId == METATILE_SecretBase_SolidBoard_Bottom)
{
- tPlayerX = x;
- tPlayerY = y;
- VarSet(VAR_SECRET_BASE_STEP_COUNTER, VarGet(VAR_SECRET_BASE_STEP_COUNTER) + 1);
- behavior = MapGridGetMetatileBehaviorAt(x, y);
- tileId = MapGridGetMetatileIdAt(x, y);
- if (tileId == METATILE_SecretBase_SolidBoard_Top || tileId == METATILE_SecretBase_SolidBoard_Bottom)
- {
- if (sInFriendSecretBase == TRUE)
- {
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_SOLID_BOARD);
- }
- }
- else if (tileId == METATILE_SecretBase_SmallChair
- || tileId == METATILE_SecretBase_PokemonChair
- || tileId == METATILE_SecretBase_HeavyChair
- || tileId == METATILE_SecretBase_PrettyChair
- || tileId == METATILE_SecretBase_ComfortChair
- || tileId == METATILE_SecretBase_RaggedChair
- || tileId == METATILE_SecretBase_BrickChair
- || tileId == METATILE_SecretBase_CampChair
- || tileId == METATILE_SecretBase_HardChair)
- {
- if (sInFriendSecretBase == TRUE)
- VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_CHAIR);
- }
- else if (tileId == METATILE_SecretBase_RedTent_DoorTop
- || tileId == METATILE_SecretBase_RedTent_Door
- || tileId == METATILE_SecretBase_BlueTent_DoorTop
- || tileId == METATILE_SecretBase_BlueTent_Door)
- {
- if (sInFriendSecretBase == TRUE)
- VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_TENT);
- }
- else if ((behavior == MB_IMPASSABLE_NORTHEAST && tileId == METATILE_SecretBase_Stand_CornerRight)
- || (behavior == MB_IMPASSABLE_NORTHWEST && MapGridGetMetatileIdAt(x, y) == METATILE_SecretBase_Stand_CornerLeft))
- {
- if (sInFriendSecretBase == TRUE)
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_STAND);
- }
- else if (behavior == MB_IMPASSABLE_WEST_AND_EAST && tileId == METATILE_SecretBase_Slide_StairLanding)
- {
- if (sInFriendSecretBase == TRUE)
- {
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) ^ SECRET_BASE_USED_SLIDE);
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_DECLINED_SLIDE);
- }
- }
- else if (behavior == MB_SLIDE_SOUTH && tileId == METATILE_SecretBase_Slide_SlideTop)
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_SOLID_BOARD);
+ }
+ else if (tileId == METATILE_SecretBase_SmallChair
+ || tileId == METATILE_SecretBase_PokemonChair
+ || tileId == METATILE_SecretBase_HeavyChair
+ || tileId == METATILE_SecretBase_PrettyChair
+ || tileId == METATILE_SecretBase_ComfortChair
+ || tileId == METATILE_SecretBase_RaggedChair
+ || tileId == METATILE_SecretBase_BrickChair
+ || tileId == METATILE_SecretBase_CampChair
+ || tileId == METATILE_SecretBase_HardChair)
+ {
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_CHAIR);
+ }
+ else if (tileId == METATILE_SecretBase_RedTent_DoorTop
+ || tileId == METATILE_SecretBase_RedTent_Door
+ || tileId == METATILE_SecretBase_BlueTent_DoorTop
+ || tileId == METATILE_SecretBase_BlueTent_Door)
+ {
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_TENT);
+ }
+ else if ((behavior == MB_IMPASSABLE_NORTHEAST && tileId == METATILE_SecretBase_Stand_CornerRight)
+ || (behavior == MB_IMPASSABLE_NORTHWEST && MapGridGetMetatileIdAt(x, y) == METATILE_SecretBase_Stand_CornerLeft))
+ {
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_STAND);
+ }
+ else if (behavior == MB_IMPASSABLE_WEST_AND_EAST && tileId == METATILE_SecretBase_Slide_StairLanding)
+ {
+ if (sInFriendSecretBase == TRUE)
{
- if (sInFriendSecretBase == TRUE)
- {
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_SLIDE);
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) ^ SECRET_BASE_DECLINED_SLIDE);
- }
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) ^ SECRET_BASE_USED_SLIDE);
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_DECLINED_SLIDE);
}
- else if (MetatileBehavior_IsSecretBaseGlitterMat(behavior) == TRUE)
+ }
+ else if (behavior == MB_SLIDE_SOUTH && tileId == METATILE_SecretBase_Slide_SlideTop)
+ {
+ if (sInFriendSecretBase == TRUE)
{
- if (sInFriendSecretBase == TRUE)
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_GLITTER_MAT);
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_SLIDE);
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) ^ SECRET_BASE_DECLINED_SLIDE);
}
- else if (MetatileBehavior_IsSecretBaseBalloon(behavior) == TRUE)
+ }
+ else if (MetatileBehavior_IsSecretBaseGlitterMat(behavior) == TRUE)
+ {
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_GLITTER_MAT);
+ }
+ else if (MetatileBehavior_IsSecretBaseBalloon(behavior) == TRUE)
+ {
+ PopSecretBaseBalloon(MapGridGetMetatileIdAt(x, y), x, y);
+ if (sInFriendSecretBase == TRUE)
{
- PopSecretBaseBalloon(MapGridGetMetatileIdAt(x, y), x, y);
- if (sInFriendSecretBase == TRUE)
+ switch ((int)MapGridGetMetatileIdAt(x, y))
{
- switch ((int)MapGridGetMetatileIdAt(x, y))
- {
- case METATILE_SecretBase_RedBalloon:
- case METATILE_SecretBase_BlueBalloon:
- case METATILE_SecretBase_YellowBalloon:
- VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_BALLOON);
- break;
- case METATILE_SecretBase_MudBall:
- VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_MUD_BALL);
- break;
- }
+ case METATILE_SecretBase_RedBalloon:
+ case METATILE_SecretBase_BlueBalloon:
+ case METATILE_SecretBase_YellowBalloon:
+ VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_BALLOON);
+ break;
+ case METATILE_SecretBase_MudBall:
+ VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_MUD_BALL);
+ break;
}
}
- else if (MetatileBehavior_IsSecretBaseBreakableDoor(behavior) == TRUE)
- {
- if (sInFriendSecretBase == TRUE)
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_BREAKABLE_DOOR);
+ }
+ else if (MetatileBehavior_IsSecretBaseBreakableDoor(behavior) == TRUE)
+ {
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_BREAKABLE_DOOR);
- ShatterSecretBaseBreakableDoor(x, y);
- }
- else if (MetatileBehavior_IsSecretBaseSoundMat(behavior) == TRUE){
- if (sInFriendSecretBase == TRUE)
- VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_NOTE_MAT);
- }
- else if (MetatileBehavior_IsSecretBaseJumpMat(behavior) == TRUE)
- {
- if (sInFriendSecretBase == TRUE)
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_JUMP_MAT);
- }
- else if (MetatileBehavior_IsSecretBaseSpinMat(behavior) == TRUE)
- {
- if (sInFriendSecretBase == TRUE)
- VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_SPIN_MAT);
- }
+ ShatterSecretBaseBreakableDoor(x, y);
+ }
+ else if (MetatileBehavior_IsSecretBaseSoundMat(behavior) == TRUE){
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_LOW_TV_FLAGS, VarGet(VAR_SECRET_BASE_LOW_TV_FLAGS) | SECRET_BASE_USED_NOTE_MAT);
+ }
+ else if (MetatileBehavior_IsSecretBaseJumpMat(behavior) == TRUE)
+ {
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_JUMP_MAT);
+ }
+ else if (MetatileBehavior_IsSecretBaseSpinMat(behavior) == TRUE)
+ {
+ if (sInFriendSecretBase == TRUE)
+ VarSet(VAR_SECRET_BASE_HIGH_TV_FLAGS, VarGet(VAR_SECRET_BASE_HIGH_TV_FLAGS) | SECRET_BASE_USED_SPIN_MAT);
}
break;
case 2: