2017-09-23 04:45:47 +02:00
|
|
|
#include "global.h"
|
2018-09-11 03:04:03 +02:00
|
|
|
#include "event_data.h"
|
2018-06-11 15:34:19 +02:00
|
|
|
#include "event_object_movement.h"
|
2018-12-27 23:30:47 +01:00
|
|
|
#include "field_camera.h"
|
|
|
|
#include "field_screen_effect.h"
|
|
|
|
#include "field_specials.h"
|
|
|
|
#include "fieldmap.h"
|
2018-09-11 03:04:03 +02:00
|
|
|
#include "main.h"
|
2018-12-27 23:30:47 +01:00
|
|
|
#include "overworld.h"
|
2017-09-23 04:45:47 +02:00
|
|
|
#include "palette.h"
|
|
|
|
#include "script.h"
|
2018-09-11 03:04:03 +02:00
|
|
|
#include "script_movement.h"
|
|
|
|
#include "sound.h"
|
|
|
|
#include "sprite.h"
|
|
|
|
#include "task.h"
|
|
|
|
#include "constants/songs.h"
|
2017-12-11 19:27:51 +01:00
|
|
|
#include "constants/vars.h"
|
2017-09-23 04:45:47 +02:00
|
|
|
|
|
|
|
#define SECONDS(value) ((signed) (60.0 * value + 0.5))
|
|
|
|
|
|
|
|
// porthole states
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
INIT_PORTHOLE,
|
|
|
|
IDLE_CHECK,
|
|
|
|
EXECUTE_MOVEMENT,
|
|
|
|
EXIT_PORTHOLE,
|
|
|
|
};
|
|
|
|
|
2018-09-11 03:04:03 +02:00
|
|
|
//. rodata
|
|
|
|
static const s8 gTruckCamera_HorizontalTable[] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, -1, -1, -1, 0};
|
|
|
|
const u8 gUnknown_0858E8AB[] = {0x18, 0xFE};
|
|
|
|
const u8 gUnknown_0858E8AD[] = {0x17, 0xFE};
|
2017-09-23 04:45:47 +02:00
|
|
|
|
2018-09-11 03:04:03 +02:00
|
|
|
// .text
|
2018-12-27 23:30:47 +01:00
|
|
|
static void Task_Truck3(u8);
|
2017-09-23 04:45:47 +02:00
|
|
|
|
2017-09-23 18:06:23 +02:00
|
|
|
s16 GetTruckCameraBobbingY(int a1)
|
2017-09-23 04:45:47 +02:00
|
|
|
{
|
|
|
|
if (!(a1 % 120))
|
|
|
|
return -1;
|
|
|
|
else if ((a1 % 10) <= 4)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-23 18:06:23 +02:00
|
|
|
s16 GetTruckBoxMovement(int a1) // for the box movement?
|
2017-09-23 04:45:47 +02:00
|
|
|
{
|
|
|
|
if (!((a1 + 120) % 180))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Task_Truck1(u8 taskId)
|
|
|
|
{
|
|
|
|
s16 *data = gTasks[taskId].data;
|
2018-08-16 03:50:56 +02:00
|
|
|
s16 cameraXpan = 0, cameraYpan = 0;
|
|
|
|
s16 box1, box2, box3;
|
2017-09-23 04:45:47 +02:00
|
|
|
|
|
|
|
box1 = GetTruckBoxMovement(data[0] + 30) * 4; // top box.
|
2018-08-16 03:50:56 +02:00
|
|
|
sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3 - cameraXpan, box1 + 3);
|
2017-09-23 04:45:47 +02:00
|
|
|
box2 = GetTruckBoxMovement(data[0]) * 2; // bottom left box.
|
2018-08-16 03:50:56 +02:00
|
|
|
sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -cameraXpan, box2 - 3);
|
2017-09-23 04:45:47 +02:00
|
|
|
box3 = GetTruckBoxMovement(data[0]) * 4; // bottom right box.
|
2018-08-16 03:50:56 +02:00
|
|
|
sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3 - cameraXpan, box3);
|
2017-09-23 04:45:47 +02:00
|
|
|
|
2017-09-23 18:42:06 +02:00
|
|
|
if (++data[0] == SECONDS(500)) // this will never run
|
2018-08-16 03:50:56 +02:00
|
|
|
data[0] = 0; // reset the timer if it gets stuck.
|
2017-09-23 04:45:47 +02:00
|
|
|
|
|
|
|
cameraYpan = GetTruckCameraBobbingY(data[0]);
|
2018-08-16 03:50:56 +02:00
|
|
|
SetCameraPanning(cameraXpan, cameraYpan);
|
2017-09-23 04:45:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Task_Truck2(u8 taskId)
|
|
|
|
{
|
|
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
s16 cameraYpan;
|
|
|
|
s16 cameraXpan;
|
|
|
|
s16 box1;
|
|
|
|
s16 box2;
|
|
|
|
s16 box3;
|
|
|
|
|
|
|
|
data[0]++;
|
|
|
|
data[2]++;
|
|
|
|
|
|
|
|
if (data[0] > 5)
|
|
|
|
{
|
|
|
|
data[0] = 0;
|
|
|
|
data[1]++;
|
|
|
|
}
|
|
|
|
if ((u16)data[1] == 19)
|
|
|
|
{
|
|
|
|
DestroyTask(taskId);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gTruckCamera_HorizontalTable[data[1]] == 2)
|
|
|
|
gTasks[taskId].func = Task_Truck3;
|
|
|
|
|
|
|
|
cameraXpan = gTruckCamera_HorizontalTable[data[1]];
|
|
|
|
cameraYpan = GetTruckCameraBobbingY(data[2]);
|
|
|
|
SetCameraPanning(cameraXpan, cameraYpan);
|
|
|
|
box1 = GetTruckBoxMovement(data[2] + 30) * 4;
|
|
|
|
sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3 - cameraXpan, box1 + 3);
|
|
|
|
box2 = GetTruckBoxMovement(data[2]) * 2;
|
|
|
|
sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -cameraXpan, box2 - 3);
|
|
|
|
box3 = GetTruckBoxMovement(data[2]) * 4;
|
|
|
|
sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3 - cameraXpan, box3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-27 23:30:47 +01:00
|
|
|
static void Task_Truck3(u8 taskId)
|
2017-09-23 04:45:47 +02:00
|
|
|
{
|
|
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
s16 cameraXpan;
|
|
|
|
s16 cameraYpan;
|
|
|
|
|
|
|
|
data[0]++;
|
|
|
|
|
|
|
|
if (data[0] > 5)
|
|
|
|
{
|
|
|
|
data[0] = 0;
|
|
|
|
data[1]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((u16)data[1] == 19)
|
|
|
|
{
|
|
|
|
DestroyTask(taskId);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cameraXpan = gTruckCamera_HorizontalTable[data[1]];
|
|
|
|
cameraYpan = 0;
|
|
|
|
SetCameraPanning(cameraXpan, 0);
|
|
|
|
sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3 - cameraXpan, cameraYpan + 3);
|
|
|
|
sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -cameraXpan, cameraYpan - 3);
|
|
|
|
sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3 - cameraXpan, cameraYpan);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Task_HandleTruckSequence(u8 taskId)
|
|
|
|
{
|
|
|
|
s16 *data = gTasks[taskId].data;
|
|
|
|
|
|
|
|
switch (data[0])
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Each case has a timer which is handled with data[1], incrementing
|
|
|
|
until it reaches the if function's condition, which sets the next task up.
|
|
|
|
*/
|
|
|
|
case 0:
|
|
|
|
data[1]++;
|
|
|
|
if (data[1] == SECONDS(1.5))
|
|
|
|
{
|
|
|
|
SetCameraPanningCallback(NULL);
|
|
|
|
data[1] = 0; // reset the timer.
|
|
|
|
data[2] = CreateTask(Task_Truck1, 0xA);
|
|
|
|
data[0] = 1; // run the next case.
|
|
|
|
PlaySE(SE_TRACK_MOVE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
data[1]++;
|
|
|
|
if (data[1] == SECONDS(2.5))
|
|
|
|
{
|
|
|
|
pal_fill_black();
|
|
|
|
data[1] = 0;
|
|
|
|
data[0] = 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
data[1]++;
|
|
|
|
if (!gPaletteFade.active && data[1] > SECONDS(5))
|
|
|
|
{
|
|
|
|
data[1] = 0;
|
|
|
|
DestroyTask(data[2]);
|
|
|
|
data[3] = CreateTask(Task_Truck2, 0xA);
|
|
|
|
data[0] = 3;
|
|
|
|
PlaySE(SE_TRACK_STOP);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (!gTasks[data[3]].isActive) // is Truck2 no longer active (is Truck3 active?)
|
|
|
|
{
|
|
|
|
InstallCameraPanAheadCallback();
|
|
|
|
data[1] = 0;
|
|
|
|
data[0] = 4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
data[1]++;
|
|
|
|
if (data[1] == 90)
|
|
|
|
{
|
2017-12-22 08:46:19 +01:00
|
|
|
PlaySE(SE_TRACK_HAIKI);
|
2017-09-23 04:45:47 +02:00
|
|
|
data[1] = 0;
|
|
|
|
data[0] = 5;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
data[1]++;
|
|
|
|
if (data[1] == 120)
|
|
|
|
{
|
|
|
|
MapGridSetMetatileIdAt(11, 8, 520);
|
|
|
|
MapGridSetMetatileIdAt(11, 9, 528);
|
|
|
|
MapGridSetMetatileIdAt(11, 10, 536);
|
|
|
|
DrawWholeMapView();
|
|
|
|
PlaySE(SE_TRACK_DOOR);
|
|
|
|
DestroyTask(taskId);
|
|
|
|
ScriptContext2_Disable();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExecuteTruckSequence(void)
|
|
|
|
{
|
|
|
|
MapGridSetMetatileIdAt(11, 8, 525);
|
|
|
|
MapGridSetMetatileIdAt(11, 9, 533);
|
|
|
|
MapGridSetMetatileIdAt(11, 10, 541);
|
|
|
|
DrawWholeMapView();
|
|
|
|
ScriptContext2_Enable();
|
|
|
|
CpuFastFill(0, gPlttBufferFaded, 0x400);
|
|
|
|
CreateTask(Task_HandleTruckSequence, 0xA);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EndTruckSequence(u8 taskId)
|
|
|
|
{
|
|
|
|
if (!FuncIsActiveTask(Task_HandleTruckSequence))
|
|
|
|
{
|
|
|
|
sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3, 3);
|
|
|
|
sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 0, -3);
|
|
|
|
sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 sub_80FB59C(void)
|
|
|
|
{
|
|
|
|
s8 mapGroup, mapNum;
|
|
|
|
s16 x, y;
|
|
|
|
|
|
|
|
if (GetSSTidalLocation(&mapGroup, &mapNum, &x, &y))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-27 23:30:47 +01:00
|
|
|
SetWarpDestination(mapGroup, mapNum, -1, x, y);
|
2017-09-23 04:45:47 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Task_HandlePorthole(u8 taskId)
|
|
|
|
{
|
|
|
|
s16 *data = gTasks[taskId].data;
|
2018-08-08 10:37:12 +02:00
|
|
|
u16 *var = GetVarPointer(VAR_PORTHOLE_STATE);
|
2017-09-23 04:45:47 +02:00
|
|
|
struct WarpData *location = &gSaveBlock1Ptr->location;
|
|
|
|
|
|
|
|
switch (data[0])
|
|
|
|
{
|
|
|
|
case INIT_PORTHOLE: // finish fading before making porthole finish.
|
|
|
|
if (!gPaletteFade.active)
|
|
|
|
{
|
|
|
|
data[1] = 0;
|
|
|
|
data[0] = EXECUTE_MOVEMENT; // execute movement before checking if should be exited. strange?
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IDLE_CHECK: // idle and move.
|
|
|
|
if (gMain.newKeys & A_BUTTON)
|
|
|
|
data[1] = 1;
|
2017-10-12 09:06:19 +02:00
|
|
|
if (!ScriptMovement_IsObjectMovementFinished(0xFF, location->mapNum, location->mapGroup))
|
2017-09-23 04:45:47 +02:00
|
|
|
return;
|
|
|
|
if (CountSSTidalStep(1) == TRUE)
|
|
|
|
{
|
|
|
|
if (*var == 2)
|
|
|
|
*var = 9;
|
|
|
|
else
|
|
|
|
*var = 10;
|
|
|
|
data[0] = 3;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
data[0] = 2;
|
|
|
|
case EXECUTE_MOVEMENT: // execute movement.
|
|
|
|
if (data[1])
|
|
|
|
{
|
|
|
|
data[0] = EXIT_PORTHOLE; // exit porthole.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// run this once.
|
|
|
|
if (*var == 2) // which direction?
|
|
|
|
{
|
2017-10-12 09:06:19 +02:00
|
|
|
ScriptMovement_StartObjectMovementScript(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AB);
|
2017-09-23 04:45:47 +02:00
|
|
|
data[0] = IDLE_CHECK; // run case 1.
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-10-12 09:06:19 +02:00
|
|
|
ScriptMovement_StartObjectMovementScript(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AD);
|
2017-09-23 04:45:47 +02:00
|
|
|
data[0] = IDLE_CHECK; // run case 1.
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EXIT_PORTHOLE: // exit porthole.
|
2019-02-02 07:25:43 +01:00
|
|
|
FlagClear(FLAG_SPECIAL_FLAG_0x4001);
|
|
|
|
FlagClear(FLAG_SPECIAL_FLAG_0x4000);
|
2018-12-27 23:30:47 +01:00
|
|
|
SetWarpDestinationToDynamicWarp(0);
|
2018-12-28 22:11:15 +01:00
|
|
|
DoDiveWarp();
|
2017-09-23 04:45:47 +02:00
|
|
|
DestroyTask(taskId);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub_80FB6EC(void)
|
|
|
|
{
|
2018-06-12 02:11:48 +02:00
|
|
|
u8 spriteId = AddPseudoEventObject(0x8C, SpriteCallbackDummy, 112, 80, 0);
|
2017-09-23 04:45:47 +02:00
|
|
|
|
|
|
|
gSprites[spriteId].coordOffsetEnabled = FALSE;
|
|
|
|
|
2019-02-02 07:25:43 +01:00
|
|
|
if (VarGet(VAR_PORTHOLE_STATE) == 2)
|
2017-09-23 04:45:47 +02:00
|
|
|
{
|
2018-06-14 00:51:26 +02:00
|
|
|
StartSpriteAnim(&gSprites[spriteId], GetFaceDirectionAnimNum(4));
|
2017-09-23 04:45:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-06-14 00:51:26 +02:00
|
|
|
StartSpriteAnim(&gSprites[spriteId], GetFaceDirectionAnimNum(3));
|
2017-09-23 04:45:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub_80FB768(void)
|
|
|
|
{
|
|
|
|
sub_80FB6EC();
|
2018-06-12 02:11:48 +02:00
|
|
|
gEventObjects[gPlayerAvatar.eventObjectId].invisible = TRUE;
|
2017-09-23 04:45:47 +02:00
|
|
|
pal_fill_black();
|
|
|
|
CreateTask(Task_HandlePorthole, 80);
|
|
|
|
ScriptContext2_Enable();
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub_80FB7A4(void)
|
|
|
|
{
|
2017-11-08 22:20:10 +01:00
|
|
|
FlagSet(FLAG_SYS_CRUISE_MODE);
|
2019-02-02 07:25:43 +01:00
|
|
|
FlagSet(FLAG_SPECIAL_FLAG_0x4001);
|
|
|
|
FlagSet(FLAG_SPECIAL_FLAG_0x4000);
|
2018-12-27 23:30:47 +01:00
|
|
|
SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1);
|
2017-09-23 04:45:47 +02:00
|
|
|
sub_80FB59C();
|
|
|
|
sub_80AF8B8();
|
|
|
|
}
|