diff options
Diffstat (limited to 'src/special_field_anim.c')
-rw-r--r-- | src/special_field_anim.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/src/special_field_anim.c b/src/special_field_anim.c new file mode 100644 index 000000000..4193f0b5a --- /dev/null +++ b/src/special_field_anim.c @@ -0,0 +1,341 @@ +#include "global.h" +#include "event_data.h" +#include "task.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "field_camera.h" +#include "constants/metatile_labels.h" + +static EWRAM_DATA u8 sEscalatorTaskId = 0; + +static void SetEscalatorMetatile(u8 taskId, const s16 *metatileIds, u16 metatileMasks); +static void Task_DrawEscalator(u8 taskId); +static void Task_DrawTeleporterHousing(u8 taskId); +static void Task_DrawTeleporterCable(u8 taskId); + +#define ESCALATOR_STAGES 3 +#define LAST_ESCALATOR_STAGE (ESCALATOR_STAGES - 1) + +static const u16 sEscalatorMetatiles_BottomNextRail[ESCALATOR_STAGES] = +{ + METATILE_PokemonCenter_Escalator_BottomNextRail_Transition2, + METATILE_PokemonCenter_Escalator_BottomNextRail_Transition1, + METATILE_PokemonCenter_Escalator_BottomNextRail_Normal +}; + +static const u16 sEscalatorMetatiles_BottomRail[ESCALATOR_STAGES] = +{ + METATILE_PokemonCenter_Escalator_BottomRail_Transition2, + METATILE_PokemonCenter_Escalator_BottomRail_Transition1, + METATILE_PokemonCenter_Escalator_BottomRail_Normal +}; + +static const u16 sEscalatorMetatiles_BottomNext[ESCALATOR_STAGES] = +{ + METATILE_PokemonCenter_Escalator_BottomNext_Transition2, + METATILE_PokemonCenter_Escalator_BottomNext_Transition1, + METATILE_PokemonCenter_Escalator_BottomNext_Normal +}; + +static const u16 sEscalatorMetatiles_Bottom[ESCALATOR_STAGES] = +{ + METATILE_PokemonCenter_Escalator_Bottom_Transition2, + METATILE_PokemonCenter_Escalator_Bottom_Transition1, + METATILE_PokemonCenter_Escalator_Bottom_Normal +}; + +static const u16 sEscalatorMetatiles_TopNext[ESCALATOR_STAGES] = +{ + METATILE_PokemonCenter_Escalator_TopNext_Normal, + METATILE_PokemonCenter_Escalator_TopNext_Transition1, + METATILE_PokemonCenter_Escalator_TopNext_Transition2 +}; + +static const u16 sEscalatorMetatiles_Top[ESCALATOR_STAGES] = +{ + METATILE_PokemonCenter_Escalator_Top_Normal, + METATILE_PokemonCenter_Escalator_Top_Transition1, + METATILE_PokemonCenter_Escalator_Top_Transition2 +}; + +static const u16 sEscalatorMetatiles_TopNextRail[ESCALATOR_STAGES] = +{ + METATILE_PokemonCenter_Escalator_TopNextRail_Normal, + METATILE_PokemonCenter_Escalator_TopNextRail_Transition1, + METATILE_PokemonCenter_Escalator_TopNextRail_Transition2 +}; + +#define tState data[0] +#define tTransitionStage data[1] +#define tGoingUp data[2] +#define tDrawingEscalator data[3] +#define tPlayerX data[4] +#define tPlayerY data[5] + +static void SetEscalatorMetatile(u8 taskId, const s16 *metatileIds, u16 metatileMasks) +{ + s16 x, y, transitionStage; + s16 i, j; + + x = gTasks[taskId].tPlayerX - 1; + y = gTasks[taskId].tPlayerY - 1; + transitionStage = gTasks[taskId].tTransitionStage; + + // Check all the escalator sections and only progress the selected one to the next stage + if (!gTasks[taskId].tGoingUp) + { + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + s32 id = MapGridGetMetatileIdAt(x + j, y + i); + + if (metatileIds[transitionStage] == (s16)id) + { + if (transitionStage != LAST_ESCALATOR_STAGE) + MapGridSetMetatileIdAt(x + j, y + i, metatileMasks | metatileIds[transitionStage + 1]); + else + MapGridSetMetatileIdAt(x + j, y + i, metatileMasks | metatileIds[0]); + } + } + } + } + else + { + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + s32 id = MapGridGetMetatileIdAt(x + j, y + i); + + if (metatileIds[LAST_ESCALATOR_STAGE - transitionStage] == (s16)id) + { + if (transitionStage != LAST_ESCALATOR_STAGE) + MapGridSetMetatileIdAt(x + j, y + i, metatileMasks | metatileIds[1 - transitionStage]); + else + MapGridSetMetatileIdAt(x + j, y + i, metatileMasks | metatileIds[LAST_ESCALATOR_STAGE]); + } + } + } + } +} + +static void Task_DrawEscalator(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + u16 state; + + tDrawingEscalator = TRUE; + + // Set tile for each section of the escalator in sequence for current transition stage + switch (tState) + { + case 0: + SetEscalatorMetatile(taskId, sEscalatorMetatiles_BottomNextRail, 0); + break; + case 1: + SetEscalatorMetatile(taskId, sEscalatorMetatiles_BottomRail, 0); + break; + case 2: + SetEscalatorMetatile(taskId, sEscalatorMetatiles_BottomNext, METATILE_COLLISION_MASK); + break; + case 3: + SetEscalatorMetatile(taskId, sEscalatorMetatiles_Bottom, 0); + break; + case 4: + SetEscalatorMetatile(taskId, sEscalatorMetatiles_TopNext, METATILE_COLLISION_MASK); + break; + case 5: + SetEscalatorMetatile(taskId, sEscalatorMetatiles_Top, 0); + break; + case 6: + SetEscalatorMetatile(taskId, sEscalatorMetatiles_TopNextRail, 0); + default: + break; + } + + tState = (tState + 1) & 7; + state = tState & 7; + + // If all sections of the escalator have been set, draw map and progress to next stage + if (state == 0) + { + DrawWholeMapView(); + tTransitionStage = (tTransitionStage + 1) % ESCALATOR_STAGES; + tDrawingEscalator = FALSE; + } +} + +static u8 CreateEscalatorTask(bool16 goingUp) +{ + u8 taskId; + s16 *data; + + taskId = CreateTask(Task_DrawEscalator, 0); + data = gTasks[taskId].data; + PlayerGetDestCoords(&tPlayerX, &tPlayerY); + tState = 0; + tTransitionStage = 0; + tGoingUp = goingUp; + Task_DrawEscalator(taskId); + return taskId; +} + +void StartEscalator(bool8 goingUp) +{ + u8 taskId; + + taskId = CreateEscalatorTask(goingUp); + sEscalatorTaskId = taskId; +} + +void StopEscalator(void) +{ + DestroyTask(sEscalatorTaskId); +} + +bool8 IsEscalatorMoving(void) +{ + if (gTasks[sEscalatorTaskId].tDrawingEscalator == FALSE) + { + if (gTasks[sEscalatorTaskId].tTransitionStage != LAST_ESCALATOR_STAGE) + return TRUE; + return FALSE; + } + else + { + return TRUE; + } +} + +#undef tState +#undef tTransitionStage +#undef tGoingUp +#undef tDrawingEscalator +#undef tPlayerX +#undef tPlayerY + +#define tTimer data[0] +#define tState data[1] +#define tX data[2] +#define tY data[3] + +void AnimateTeleporterHousing(void) +{ + u8 taskId; + s16 *data; + + taskId = CreateTask(Task_DrawTeleporterHousing, 0); + gTasks[taskId].tTimer = 0; + gTasks[taskId].tState = 0; + data = gTasks[taskId].data; + PlayerGetDestCoords(&tX, &tY); + + // Set the coords of whichever teleporter is being animated + // 0 for the right teleporter, 1 for the left teleporter + if (gSpecialVar_0x8004 == 0) + { + gTasks[taskId].tX += 6; + gTasks[taskId].tY -= 5; + } + else + { + gTasks[taskId].tX -= 1; + gTasks[taskId].tY -= 5; + } +} + +static void Task_DrawTeleporterHousing(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + if (tTimer == 0) + { + // Alternate the teleporter light / brightness of the teleporter door + if ((tState & 1) == 0) + { + MapGridSetMetatileIdAt(tX, tY, METATILE_SeaCottage_Teleporter_Light_Yellow | METATILE_COLLISION_MASK); + MapGridSetMetatileIdAt(tX, tY + 2, METATILE_SeaCottage_Teleporter_Door_HalfGlowing | METATILE_COLLISION_MASK); + } + else + { + MapGridSetMetatileIdAt(tX, tY, METATILE_SeaCottage_Teleporter_Light_Red | METATILE_COLLISION_MASK); + MapGridSetMetatileIdAt(tX, tY + 2, METATILE_SeaCottage_Teleporter_Door_FullGlowing | METATILE_COLLISION_MASK); + } + CurrentMapDrawMetatileAt(tX, tY); + CurrentMapDrawMetatileAt(tX, tY + 2); + } + + tTimer++; + if (tTimer != 16) + return; + + tTimer = 0; + tState++; + if (tState != 13) + return; + + MapGridSetMetatileIdAt(tX, tY, METATILE_SeaCottage_Teleporter_Light_Green | METATILE_COLLISION_MASK); + MapGridSetMetatileIdAt(tX, tY + 2, METATILE_SeaCottage_Teleporter_Door | METATILE_COLLISION_MASK); + CurrentMapDrawMetatileAt(tX, tY); + CurrentMapDrawMetatileAt(tX, tY + 2); + DestroyTask(taskId); +} + +void AnimateTeleporterCable(void) +{ + u8 taskId; + s16 *data; + + taskId = CreateTask(Task_DrawTeleporterCable, 0); + gTasks[taskId].tTimer = 0; + gTasks[taskId].tState = 0; + data = gTasks[taskId].data; + PlayerGetDestCoords(&tX, &tY); + gTasks[taskId].tX += 4; + gTasks[taskId].tY -= 5; +} + +static void Task_DrawTeleporterCable(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + if (tTimer == 0) + { + if (tState != 0) + { + // Set default cable tiles to clear the ball + MapGridSetMetatileIdAt(tX, tY, METATILE_SeaCottage_Teleporter_Cable_Top | METATILE_COLLISION_MASK); + MapGridSetMetatileIdAt(tX, tY + 1, METATILE_SeaCottage_Teleporter_Cable_Bottom | METATILE_COLLISION_MASK); + CurrentMapDrawMetatileAt(tX, tY); + CurrentMapDrawMetatileAt(tX, tY + 1); + + // End after drawing 4 times (length of the cable) + if (tState == 4) + { + DestroyTask(taskId); + return; + } + + tX--; + } + + // Draw the cable ball + MapGridSetMetatileIdAt(tX, tY, METATILE_SeaCottage_Teleporter_CableBall_Top | METATILE_COLLISION_MASK); + MapGridSetMetatileIdAt(tX, tY + 1, METATILE_SeaCottage_Teleporter_CableBall_Bottom | METATILE_COLLISION_MASK); + CurrentMapDrawMetatileAt(tX, tY); + CurrentMapDrawMetatileAt(tX, tY + 1); + } + + tTimer++; + if (tTimer == 4) + { + tTimer = 0; + tState++; + } +} + +#undef tTimer +#undef tState +#undef tX +#undef tY |