pokefirered/src/field_tasks.c
2019-12-27 16:09:45 +00:00

294 lines
7.0 KiB
C

#include "global.h"
#include "bike.h"
#include "event_data.h"
#include "field_camera.h"
#include "field_effect_helpers.h"
#include "field_player_avatar.h"
#include "fieldmap.h"
#include "metatile_behavior.h"
#include "overworld.h"
#include "quest_log.h"
#include "script.h"
#include "sound.h"
#include "task.h"
#include "constants/flags.h"
#include "constants/songs.h"
#include "constants/vars.h"
static void DummyPerStepCallback(u8 taskId);
static void AshGrassPerStepCallback(u8 taskId);
static void IcefallCaveIcePerStepCallback(u8 taskId);
static void CrackedFloorPerStepCallback(u8 taskId);
static const TaskFunc sPerStepCallbacks[] =
{
DummyPerStepCallback,
AshGrassPerStepCallback,
DummyPerStepCallback,
DummyPerStepCallback,
IcefallCaveIcePerStepCallback,
DummyPerStepCallback,
DummyPerStepCallback,
CrackedFloorPerStepCallback
};
static const u8 sIcefallCaveIceTileCoords[][2] =
{
{ 0x08, 0x03 },
{ 0x0a, 0x05 },
{ 0x0f, 0x05 },
{ 0x08, 0x09 },
{ 0x09, 0x09 },
{ 0x10, 0x09 },
{ 0x08, 0x0a },
{ 0x09, 0x0a },
{ 0x08, 0x0e }
};
static void Task_RunPerStepCallback(u8 taskId)
{
int idx = gTasks[taskId].data[0];
sPerStepCallbacks[idx](taskId);
}
static void Task_RunTimeBasedEvents(u8 taskId)
{
s16 *data = gTasks[taskId].data;
if (!ScriptContext2_IsEnabled())
{
if (gUnknown_203ADFA != 2 && gUnknown_203ADFA != 3)
{
sub_8056078(&data[1], &data[2]);
}
}
}
void SetUpFieldTasks(void)
{
if (!FuncIsActiveTask(Task_RunPerStepCallback))
{
u8 taskId = CreateTask(Task_RunPerStepCallback, 0x50);
gTasks[taskId].data[0] = 0;
}
if (!FuncIsActiveTask(Task_RunTimeBasedEvents))
CreateTask(Task_RunTimeBasedEvents, 0x50);
}
void ActivatePerStepCallback(u8 callbackId)
{
u8 taskId = FindTaskIdByFunc(Task_RunPerStepCallback);
if (taskId != 0xff)
{
s32 i;
s16 *data = gTasks[taskId].data;
for (i = 0; i < 16; i++)
data[i] = 0;
if (callbackId >= NELEMS(sPerStepCallbacks))
{
data[0] = 0;
}
else
{
data[0] = callbackId;
}
}
}
void ResetFieldTasksArgs(void)
{
u8 taskId;
s16 *data;
taskId = FindTaskIdByFunc(Task_RunPerStepCallback);
if (taskId != 0xff)
{
data = gTasks[taskId].data;
}
taskId = FindTaskIdByFunc(Task_RunTimeBasedEvents);
if (taskId != 0xff)
{
data = gTasks[taskId].data;
data[1] = 0;
data[2] = 0;
}
}
static void DummyPerStepCallback(u8 taskId)
{
}
static void MarkIcefallCaveCoordVisited(s16 x, s16 y)
{
u8 i = 0;
for (; i < NELEMS(sIcefallCaveIceTileCoords); ++i)
{
if (sIcefallCaveIceTileCoords[i][0] + 7 == x && sIcefallCaveIceTileCoords[i][1] + 7 == y)
{
FlagSet(i + 1);
break;
}
}
}
void Special_SetIcefallCaveCrackedIceMetatiles(void)
{
u8 i = 0;
for (; i < NELEMS(sIcefallCaveIceTileCoords); ++i)
{
if (FlagGet(i + 1) == TRUE)
{
int x = sIcefallCaveIceTileCoords[i][0] + 7;
int y = sIcefallCaveIceTileCoords[i][1] + 7;
MapGridSetMetatileIdAt(x, y, 0x35a);
}
}
}
static void IcefallCaveIcePerStepCallback(u8 taskId)
{
s16 x, y;
u8 tileBehavior;
u16 *iceStepCount;
s16 *data = gTasks[taskId].data;
switch (data[1])
{
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);
if (MetatileBehavior_IsThinIce(tileBehavior) == TRUE)
{
MarkIcefallCaveCoordVisited(x, y);
data[6] = 4;
data[1] = 2;
data[4] = x;
data[5] = y;
}
else if (MetatileBehavior_IsCrackedIce(tileBehavior) == TRUE)
{
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_RU_BARI);
MapGridSetMetatileIdAt(x, y, 0x35a);
CurrentMapDrawMetatileAt(x, y);
data[1] = 1;
}
break;
case 3:
if (data[6] != 0)
{
data[6]--;
}
else
{
x = data[4];
y = data[5];
PlaySE(SE_RU_GASYAN);
MapGridSetMetatileIdAt(x, y, 0x35b);
CurrentMapDrawMetatileAt(x, y);
VarSet(VAR_0x4001, 1);
data[1] = 1;
}
break;
}
}
// This is leftover from pokeruby and effectively a no-op.
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])
{
data[1] = x;
data[2] = y;
if (MetatileBehavior_ReturnFalse_4((u8)MapGridGetMetatileBehaviorAt(x, y)))
{
if (MapGridGetMetatileIdAt(x, y) == 0x20a)
StartAshFieldEffect(x, y, 0x212, 4);
else
StartAshFieldEffect(x, y, 0x206, 4);
}
}
}
static void SetCrackedFloorHoleMetatile(s16 x, s16 y)
{
MapGridSetMetatileIdAt(x, y, MapGridGetMetatileIdAt(x, y) == 0x22f ? 0x206 : 0x237);
CurrentMapDrawMetatileAt(x, y);
}
// This is leftover from pokeruby and effectively a no-op.
static void CrackedFloorPerStepCallback(u8 taskId)
{
s16 x, y;
u16 behavior;
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]);
if ((x != data[2] || y != data[3]))
{
data[2] = x;
data[3] = y;
if (MetatileBehavior_ReturnFalse_13(behavior))
{
if (GetPlayerSpeed() != 4)
VarSet(VAR_0x4030, 0);
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;
}
}
}
}
static void sub_806ED38(void)
{
FlagSet(FLAG_SYS_POKEDEX_GET);
FlagSet(FLAG_SYS_POKEMON_GET);
}