summaryrefslogtreecommitdiff
path: root/src/ss_anne.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ss_anne.c')
-rw-r--r--src/ss_anne.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/ss_anne.c b/src/ss_anne.c
new file mode 100644
index 000000000..f59f17a76
--- /dev/null
+++ b/src/ss_anne.c
@@ -0,0 +1,200 @@
+#include "global.h"
+#include "task.h"
+#include "sound.h"
+#include "field_map_obj.h"
+#include "script.h"
+#include "constants/songs.h"
+
+// Tasks governing the ship's departure after you've gotten HM01 CUT
+
+#define SPRITE_TAG_WAKE 4000
+#define SPRITE_TAG_SMOKE 4001
+
+static void Task_SSAnneInit(u8 taskId);
+static void Task_SSAnneRun(u8 taskId);
+static void Task_SSAnneFinish(u8 taskId);
+static void CreateWakeBehindBoat(void);
+static void WakeSpriteCallback(struct Sprite * sprite);
+static void CreateSmokeSprite(void);
+static void SmokeSpriteCallback(struct Sprite * sprite);
+
+static const u16 sWakeTiles[] = INCBIN_U16("graphics/ss_anne/unk_8479838.4bpp");
+static const u16 sSmokeTiles[] = INCBIN_U16("graphics/ss_anne/unk_8479A38.4bpp");
+
+static const struct SpriteSheet sSpriteSheets[] = {
+ {(const void *)sWakeTiles, sizeof(sWakeTiles), SPRITE_TAG_WAKE},
+ {(const void *)sSmokeTiles, sizeof(sSmokeTiles), SPRITE_TAG_SMOKE},
+ {0}
+};
+
+static const union AnimCmd sWakeAnim[] = {
+ ANIMCMD_FRAME(0, 12),
+ ANIMCMD_FRAME(8, 12),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd *const sWakeAnimTable[] = {
+ sWakeAnim
+};
+
+static const struct OamData sWakeOamData = {
+ .shape = ST_OAM_V_RECTANGLE,
+ .size = 2
+};
+
+static const struct SpriteTemplate sWakeSpriteTemplate = {
+ SPRITE_TAG_WAKE,
+ 0xFFFF,
+ &sWakeOamData,
+ sWakeAnimTable,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ WakeSpriteCallback
+};
+
+static const union AnimCmd sSmokeAnim[] = {
+ ANIMCMD_FRAME( 0, 10),
+ ANIMCMD_FRAME( 4, 20),
+ ANIMCMD_FRAME( 8, 20),
+ ANIMCMD_FRAME(12, 30),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSmokeAnimTable[] = {
+ sSmokeAnim
+};
+
+static const struct OamData sSmokeOamData = {
+ .shape = ST_OAM_SQUARE,
+ .size = 1
+};
+
+static const struct SpriteTemplate sSmokeSpriteTemplate = {
+ SPRITE_TAG_SMOKE,
+ 0xFFFF,
+ &sSmokeOamData,
+ sSmokeAnimTable,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SmokeSpriteCallback
+};
+
+void Special_SSAnneDepartureCutscene(void)
+{
+ u8 taskId;
+
+ PlaySE(SE_SHIP_HORN);
+ taskId = CreateTask(Task_SSAnneInit, 8);
+ gTasks[taskId].data[0] = 50;
+}
+
+static void Task_SSAnneInit(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (--data[0] == 0)
+ {
+ LoadSpriteSheets(sSpriteSheets);
+ CreateWakeBehindBoat();
+ gTasks[taskId].func = Task_SSAnneRun;
+ }
+}
+
+static void Task_SSAnneRun(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ u8 mapObjectId;
+ struct MapObject * boatObject;
+ s16 x;
+
+ data[1]++;
+ data[2]++;
+ if (data[1] == 70)
+ {
+ data[1] = 0;
+ CreateSmokeSprite();
+ }
+ TryGetFieldObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectId);
+ boatObject = &gMapObjects[mapObjectId];
+ if (gSprites[boatObject->spriteId].pos1.x + gSprites[boatObject->spriteId].pos2.x < -120)
+ {
+ PlaySE(SE_SHIP_HORN);
+ gTasks[taskId].func = Task_SSAnneFinish;
+ }
+ else
+ {
+ x = data[2] / 5;
+ gSprites[boatObject->spriteId].pos2.x = -x;
+ }
+}
+
+static void Task_SSAnneFinish(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (++data[3] == 40)
+ {
+ FreeSpriteTilesByTag(SPRITE_TAG_WAKE);
+ FreeSpriteTilesByTag(SPRITE_TAG_SMOKE);
+ DestroyTask(taskId);
+ EnableBothScriptContexts();
+ }
+}
+
+static void CreateWakeBehindBoat(void)
+{
+ u8 mapObjectId;
+ struct MapObject * boatObject;
+ u16 x;
+ u8 spriteId;
+
+ TryGetFieldObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectId);
+ boatObject = &gMapObjects[mapObjectId];
+ x = gSprites[boatObject->spriteId].pos1.x + gSprites[boatObject->spriteId].pos2.x + 80;
+ spriteId = CreateSprite(&sWakeSpriteTemplate, x, 109, 0xFF);
+ gSprites[spriteId].oam.priority = 2;
+ gSprites[spriteId].oam.paletteNum = 10;
+}
+
+static void WakeSpriteCallback(struct Sprite * sprite)
+{
+ u8 mapObjectId;
+ struct MapObject * boatObject;
+ u16 x;
+
+ TryGetFieldObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectId);
+ boatObject = &gMapObjects[mapObjectId];
+ x = gSprites[boatObject->spriteId].pos1.x + gSprites[boatObject->spriteId].pos2.x + 80;
+ sprite->pos1.x = x;
+ if (sprite->data[0] / 6 < 22)
+ sprite->data[0]++;
+ sprite->pos2.x = sprite->data[0] / 6;
+ if (sprite->pos1.x + sprite->pos2.x < -18)
+ DestroySprite(sprite);
+}
+
+static void CreateSmokeSprite(void)
+{
+ u8 mapObjectId;
+ struct MapObject * boatObject;
+ u16 x;
+ u8 spriteId;
+
+ TryGetFieldObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectId);
+ boatObject = &gMapObjects[mapObjectId];
+ x = gSprites[boatObject->spriteId].pos1.x + gSprites[boatObject->spriteId].pos2.x + 49;
+ if ((s16)x >= -32)
+ {
+ spriteId = CreateSprite(&sSmokeSpriteTemplate, x, 78, 8);
+ if (spriteId != MAX_SPRITES)
+ gSprites[spriteId].oam.paletteNum = 10;
+ }
+}
+
+static void SmokeSpriteCallback(struct Sprite * sprite)
+{
+ sprite->data[0]++;
+ sprite->pos2.x = sprite->data[0] / 4;
+ if (sprite->animEnded)
+ DestroySprite(sprite);
+}