summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPikalaxALT <pikalaxalt@gmail.com>2019-10-03 12:12:06 -0400
committerPikalaxALT <pikalaxalt@gmail.com>2019-10-03 12:12:06 -0400
commit26d940dfeb48d8471db4a0cf2477aff68f681090 (patch)
treebc5b7c2fd69616bb79889ecef8604cdd1e6f61b5 /src
parentafd5f1f52f7a2b74e9850892aef118292a45df8e (diff)
Finish itemfinder dism/decomp
Diffstat (limited to 'src')
-rw-r--r--src/fieldmap.c2
-rw-r--r--src/item_use.c2
-rw-r--r--src/itemfinder.c613
3 files changed, 536 insertions, 81 deletions
diff --git a/src/fieldmap.c b/src/fieldmap.c
index 2683eaf62..000b8105b 100644
--- a/src/fieldmap.c
+++ b/src/fieldmap.c
@@ -833,7 +833,7 @@ s32 sub_80596FC(struct MapConnection *connection, s32 x, s32 y)
return FALSE;
}
-struct MapConnection *sub_805973C(s16 x, s16 y)
+struct MapConnection *GetMapConnectionAtPos(s16 x, s16 y)
{
s32 count;
struct MapConnection *connection;
diff --git a/src/item_use.c b/src/item_use.c
index 5fa9390c1..c472960bd 100644
--- a/src/item_use.c
+++ b/src/item_use.c
@@ -274,7 +274,7 @@ void ItemUseOnFieldCB_Rod(u8 taskId)
void ItemUseOutOfBattle_Itemfinder(u8 taskId)
{
IncrementGameStat(GAME_STAT_USED_ITEMFINDER);
- sItemUseOnFieldCB = sub_813EC8C;
+ sItemUseOnFieldCB = ItemUseOnFieldCB_Itemfinder;
sub_80A103C(taskId);
}
diff --git a/src/itemfinder.c b/src/itemfinder.c
index 20db9e5d2..e0300cac9 100644
--- a/src/itemfinder.c
+++ b/src/itemfinder.c
@@ -2,49 +2,153 @@
#include "task.h"
#include "new_menu_helpers.h"
#include "strings.h"
+#include "event_scripts.h"
#include "map_obj_lock.h"
#include "script.h"
#include "sound.h"
#include "event_data.h"
#include "field_player_avatar.h"
#include "field_specials.h"
+#include "fieldmap.h"
+#include "itemfinder.h"
#include "constants/songs.h"
-void sub_813ED18(u8 taskId);
-void sub_813ED3C(u8 taskId);
-void sub_813EDB0(u8 taskId);
-bool8 sub_813EE14(struct MapEvents *events, u8 taskId);
-void sub_813EF9C(u8 taskId);
-void sub_813F108(u8 taskId);
-void sub_813F220(u8 taskId, s16 dx, s16 dy);
-u8 GetPlayerDirectionTowardsHiddenItem(s16 x, s16 y);
-void sub_813F364(u8 taskId);
-void sub_813F3A8(u8 taskId);
-void sub_813F3EC(void);
-void sub_813F40C(u8 palIdx, u8 direction);
-u8 sub_813F5AC(void);
-void sub_813EF40(u8 taskId, struct HiddenItemStruct hiddenItem);
-
-void sub_813EC8C(u8 taskId)
+static void Task_NoResponse_CleanUp(u8 taskId);
+static void Task_ItemfinderResponseSoundsAndAnims(u8 taskId);
+static void Task_ItemfinderUnderfootSoundsAndAnims(u8 taskId);
+static bool8 HiddenItemIsWithinRangeOfPlayer(struct MapEvents *events, u8 taskId);
+static void SetUnderfootHiddenItem(u8 taskId, struct HiddenItemStruct hiddenItem);
+static void SetNormalHiddenItem(u8 taskId);
+static void FindHiddenItemsInConnectedMaps(u8 taskId);
+static void RegisterHiddenItemRelativeCoordsIfCloser(u8 taskId, s16 dx, s16 dy);
+static u8 GetPlayerDirectionTowardsHiddenItem(s16 itemX, s16 itemY);
+static void Task_ItemfinderResponsePrintMessage(u8 taskId);
+static void Task_ItemfinderResponseCleanUp(u8 taskId);
+static void Task_ItemfinderUnderfootPrintMessage(u8 taskId);
+static void Task_ItemfinderUnderfootDigUpItem(u8 taskId);
+static void DestroyArrowAndStarTiles(void);
+static void LoadArrowAndStarTiles(void);
+static void CreateArrowSprite(u8 animNum, u8 direction);
+static void SpriteCallback_Arrow(struct Sprite * sprite);
+static void SpriteCallback_DestroyArrow(struct Sprite * sprite);
+static u8 CreateStarSprite(void);
+static void SpriteCallback_Star(struct Sprite * sprite);
+static void SpriteCallback_DestroyStar(struct Sprite * sprite);
+
+#define ARROW_TILE_TAG 2000
+
+static const u16 sArrowAndStarSpriteTiles[] = INCBIN_U16("data/itemfinder/spr_tiles.4bpp");
+
+static const union AnimCmd sArrowAnim0[] = {
+ ANIMCMD_FRAME( 0, 10),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sArrowAnim1[] = {
+ ANIMCMD_FRAME( 4, 10),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sArrowAnim2[] = {
+ ANIMCMD_FRAME( 8, 10),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sArrowAnim3[] = {
+ ANIMCMD_FRAME(12, 10),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sStarAnim[] = {
+ ANIMCMD_FRAME(16, 10),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sArrowAndStarSpriteAnimTable[] = {
+ sArrowAnim0,
+ sArrowAnim1,
+ sArrowAnim2,
+ sArrowAnim3,
+ sStarAnim
+};
+
+static const struct OamData sArrowAndStarSpriteOamData = {
+ .affineMode = ST_OAM_AFFINE_NORMAL,
+ .shape = ST_OAM_SQUARE,
+ .size = ST_OAM_SIZE_1
+};
+
+static const union AffineAnimCmd sAffineAnim_Left[] = {
+ AFFINEANIMCMD_FRAME(0, 0, 0x00, 1),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sAffineAnim_Down[] = {
+ AFFINEANIMCMD_FRAME(0, 0, 0x40, 1),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sAffineAnim_Right[] = {
+ AFFINEANIMCMD_FRAME(0, 0, 0x80, 1),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd sAffineAnim_Up[] = {
+ AFFINEANIMCMD_FRAME(0, 0, 0xc0, 1),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const sArrowAndStarSpriteAffineAnimTable[] = {
+ sAffineAnim_Left,
+ sAffineAnim_Down,
+ sAffineAnim_Right,
+ sAffineAnim_Up
+};
+
+static const struct SpriteTemplate gUnknown_84647E4 = {
+ .tileTag = ARROW_TILE_TAG,
+ .paletteTag = 0xFFFF,
+ .oam = &sArrowAndStarSpriteOamData,
+ .anims = sArrowAndStarSpriteAnimTable,
+ .affineAnims = sArrowAndStarSpriteAffineAnimTable,
+ .callback = SpriteCallback_Arrow
+};
+
+static const struct SpriteSheet sArrowAndStarSpriteSheet = {
+ .data = sArrowAndStarSpriteTiles,
+ .size = sizeof(sArrowAndStarSpriteTiles),
+ .tag = ARROW_TILE_TAG
+};
+
+#define tItemX data[0]
+#define tItemY data[1]
+#define tHiddenItemFound data[2]
+#define tDingTimer data[3]
+#define tNumDingsRemaining data[4]
+#define tDingNum data[5]
+#define tUnderfoot data[6]
+#define tStartSpriteId data[7]
+
+void ItemUseOnFieldCB_Itemfinder(u8 taskId)
{
u8 i;
for (i = 0; i < 16; i++)
gTasks[taskId].data[i] = 0;
- if (sub_813EE14(gMapHeader.events, taskId) == TRUE)
+ if (HiddenItemIsWithinRangeOfPlayer(gMapHeader.events, taskId) == TRUE)
{
- sub_813F3EC();
- if (gTasks[taskId].data[6] == 1)
- gTasks[taskId].func = sub_813EDB0;
+ LoadArrowAndStarTiles();
+ if (gTasks[taskId].tUnderfoot == TRUE)
+ gTasks[taskId].func = Task_ItemfinderUnderfootSoundsAndAnims;
else
- gTasks[taskId].func = sub_813ED3C;
+ gTasks[taskId].func = Task_ItemfinderResponseSoundsAndAnims;
}
else
{
- DisplayItemMessageOnField(taskId, 2, gText_NopeTheresNoResponse, sub_813ED18);
+ DisplayItemMessageOnField(taskId, 2, gText_NopeTheresNoResponse, Task_NoResponse_CleanUp);
}
}
-void sub_813ED18(u8 taskId)
+static void Task_NoResponse_CleanUp(u8 taskId)
{
ClearDialogWindowAndFrame(0, TRUE);
sub_80696C0();
@@ -52,66 +156,66 @@ void sub_813ED18(u8 taskId)
DestroyTask(taskId);
}
-void sub_813ED3C(u8 taskId)
+static void Task_ItemfinderResponseSoundsAndAnims(u8 taskId)
{
s16 * data = gTasks[taskId].data;
u8 direction;
- if (data[3] % 25 == 0)
+ if (tDingTimer % 25 == 0)
{
- direction = GetPlayerDirectionTowardsHiddenItem(data[0], data[1]);
- if (data[4] == 0)
+ direction = GetPlayerDirectionTowardsHiddenItem(tItemX, tItemY);
+ if (tNumDingsRemaining == 0)
{
- gTasks[taskId].func = sub_813F364;
+ gTasks[taskId].func = Task_ItemfinderResponsePrintMessage;
return;
}
else
{
PlaySE(SE_TOY_F);
- sub_813F40C(data[5], direction);
- data[5]++;
- data[4]--;
+ CreateArrowSprite(tDingNum, direction);
+ tDingNum++;
+ tNumDingsRemaining--;
}
}
- data[3]++;
+ tDingTimer++;
}
-void sub_813EDB0(u8 taskId)
+static void Task_ItemfinderUnderfootSoundsAndAnims(u8 taskId)
{
s16 * data = gTasks[taskId].data;
- if (data[3] % 25 == 0)
+ if (tDingTimer % 25 == 0)
{
- if (data[4] == 0)
+ if (tNumDingsRemaining == 0)
{
- gTasks[taskId].func = sub_813F3A8;
+ gTasks[taskId].func = Task_ItemfinderUnderfootPrintMessage;
return;
}
else
{
PlaySE(SE_TOY_F);
- data[7] = sub_813F5AC();
- data[5]++;
- data[4]--;
+ tStartSpriteId = CreateStarSprite();
+ tDingNum++;
+ tNumDingsRemaining--;
}
}
- data[3]++;
+ tDingTimer++;
}
-bool8 sub_813EE14(struct MapEvents *events, u8 taskId)
+static bool8 HiddenItemIsWithinRangeOfPlayer(struct MapEvents *events, u8 taskId)
{
s16 x, y, i, dx, dy;
PlayerGetDestCoords(&x, &y);
- gTasks[taskId].data[2] = 0;
+ gTasks[taskId].tHiddenItemFound = FALSE;
for (i = 0; i < events->bgEventCount; i++)
{
- if (events->bgEvents[i].kind == 7 && !FlagGet(sub_80CC44C(events->bgEvents[i].bgUnion.hiddenItem, 1)))
+ if (events->bgEvents[i].kind == 7 && !FlagGet(GetHiddenItemAttr(events->bgEvents[i].bgUnion.hiddenItem, 1)))
{
dx = events->bgEvents[i].x + 7 - x;
dy = events->bgEvents[i].y + 7 - y;
- if (sub_80CC44C(events->bgEvents[i].bgUnion.hiddenItem, 3) == TRUE)
+ if (GetHiddenItemAttr(events->bgEvents[i].bgUnion.hiddenItem, 3) == TRUE)
{
if (dx == 0 && dy == 0)
{
- sub_813EF40(taskId, events->bgEvents[i].bgUnion.hiddenItem);
+ SetUnderfootHiddenItem(taskId, events->bgEvents[i].bgUnion.hiddenItem);
return TRUE;
}
}
@@ -122,69 +226,72 @@ bool8 sub_813EE14(struct MapEvents *events, u8 taskId)
&& dy <= 5
)
{
- sub_813F220(taskId, dx, dy);
+ RegisterHiddenItemRelativeCoordsIfCloser(taskId, dx, dy);
}
}
}
- sub_813F108(taskId);
- if (gTasks[taskId].data[2] == 1)
+ FindHiddenItemsInConnectedMaps(taskId);
+ if (gTasks[taskId].tHiddenItemFound == TRUE)
{
- sub_813EF9C(taskId);
+ SetNormalHiddenItem(taskId);
return TRUE;
}
return FALSE;
}
-void sub_813EF40(u8 taskId, struct HiddenItemStruct hiddenItem)
+static void SetUnderfootHiddenItem(u8 taskId, struct HiddenItemStruct hiddenItem)
{
s16 * data = gTasks[taskId].data;
- gSpecialVar_0x8004 = sub_80CC44C(hiddenItem, 1);
- gSpecialVar_0x8005 = sub_80CC44C(hiddenItem, 0);
+ gSpecialVar_0x8004 = GetHiddenItemAttr(hiddenItem, 1);
+ gSpecialVar_0x8005 = GetHiddenItemAttr(hiddenItem, 0);
gSpecialVar_0x8006 = 1;
TV_PrintIntToStringVar(0, gSpecialVar_0x8005);
- data[2] = 1;
- data[0] = 0;
- data[1] = 0;
- data[4] = 3;
- data[6] = 1;
+ tHiddenItemFound = TRUE;
+ tItemX = 0;
+ tItemY = 0;
+ tNumDingsRemaining = 3;
+ tUnderfoot = TRUE;
}
-void sub_813EF9C(u8 taskId)
+static void SetNormalHiddenItem(u8 taskId)
{
s16 * data = gTasks[taskId].data;
- s16 r3 = data[1];
- s16 r2 = data[0];
- if (data[0] == 0 && data[1] == 0)
- data[4] = 4;
+ s16 absY = tItemY;
+ s16 absX = tItemX;
+
+ // The strength of the response increases inversely with distance to the item.
+ if (tItemX == 0 && tItemY == 0)
+ tNumDingsRemaining = 4;
else
{
- if (data[0] < 0)
- r2 = data[0] * -1;
- if (data[1] < 0)
- r3 = data[1] * -1;
- if (r2 > r3)
+ if (tItemX < 0)
+ absX = tItemX * -1;
+ if (tItemY < 0)
+ absY = tItemY * -1;
+ if (absX > absY)
{
- if (r2 > 3)
- data[4] = 2;
+ if (absX > 3)
+ tNumDingsRemaining = 2;
else
- data[4] = 4;
+ tNumDingsRemaining = 4;
}
else
{
- if (r3 > 3)
- data[4] = 2;
+ if (absY > 3)
+ tNumDingsRemaining = 2;
else
- data[4] = 4;
+ tNumDingsRemaining = 4;
}
}
}
-bool8 sub_813F004(struct MapEvents *events, s16 x, s16 y)
+static bool8 HiddenItemAtPos(struct MapEvents *events, s16 x, s16 y)
{
- s32 i;
- u16 eventFlag;
- s32 bgEventCount = events->bgEventCount;
+ u8 bgEventCount = events->bgEventCount;
struct BgEvent *bgEvents = events->bgEvents;
+ u16 eventFlag;
+ int i;
+
for (i = 0; i < bgEventCount; i++)
{
if (
@@ -193,8 +300,8 @@ bool8 sub_813F004(struct MapEvents *events, s16 x, s16 y)
&& y == bgEvents[i].y
)
{
- eventFlag = sub_80CC44C(bgEvents[i].bgUnion.hiddenItem, 1);
- if (sub_80CC44C(bgEvents[i].bgUnion.hiddenItem, 3) != TRUE && !FlagGet(eventFlag))
+ eventFlag = GetHiddenItemAttr(bgEvents[i].bgUnion.hiddenItem, 1);
+ if (GetHiddenItemAttr(bgEvents[i].bgUnion.hiddenItem, 3) != TRUE && !FlagGet(eventFlag))
return TRUE;
else
return FALSE;
@@ -202,3 +309,351 @@ bool8 sub_813F004(struct MapEvents *events, s16 x, s16 y)
}
return FALSE;
}
+
+static bool8 HiddenItemInConnectedMapAtPos(struct MapConnection * connection, s32 x, s32 y)
+{
+ const struct MapHeader *mapHeader;
+ u16 localX, localY;
+ u32 localOffset;
+ s32 localLength;
+
+ mapHeader = mapconnection_get_mapheader(connection);
+
+ switch (connection->direction)
+ {
+ // same weird temp variable behavior seen in HiddenItemAtPos
+ case 2:
+ localOffset = connection->offset + 7;
+ localX = x - localOffset;
+ localLength = mapHeader->mapData->height - 7;
+ localY = localLength + y; // additions are reversed for some reason
+ break;
+ case 1:
+ localOffset = connection->offset + 7;
+ localX = x - localOffset;
+ localLength = gMapHeader.mapData->height + 7;
+ localY = y - localLength;
+ break;
+ case 3:
+ localLength = mapHeader->mapData->width - 7;
+ localX = localLength + x; // additions are reversed for some reason
+ localOffset = connection->offset + 7;
+ localY = y - localOffset;
+ break;
+ case 4:
+ localLength = gMapHeader.mapData->width + 7;
+ localX = x - localLength;
+ localOffset = connection->offset + 7;
+ localY = y - localOffset;
+ break;
+ default:
+ return FALSE;
+ }
+ return HiddenItemAtPos(mapHeader->events, localX, localY);
+}
+
+static void FindHiddenItemsInConnectedMaps(u8 taskId)
+{
+ s16 x, y;
+ s16 curX, curY;
+ s16 width = gMapHeader.mapData->width + 7;
+ s16 height = gMapHeader.mapData->height + 7;
+
+ s16 var1 = 7;
+ s16 var2 = 7;
+
+ PlayerGetDestCoords(&x, &y);
+
+ for (curX = x - 7; curX <= x + 7; curX++)
+ {
+ for (curY = y - 5; curY <= y + 5; curY++)
+ {
+ if (var1 > curX
+ || curX >= width
+ || var2 > curY
+ || curY >= height)
+ {
+ struct MapConnection *conn = GetMapConnectionAtPos(curX, curY);
+ if (conn != NULL && HiddenItemInConnectedMapAtPos(conn, curX, curY) == TRUE)
+ RegisterHiddenItemRelativeCoordsIfCloser(taskId, curX - x, curY - y);
+ }
+ }
+ }
+}
+
+static void RegisterHiddenItemRelativeCoordsIfCloser(u8 taskId, s16 dx, s16 dy)
+{
+ s16 *data = gTasks[taskId].data;
+ s16 dx2, dy2, dx3, dy3;
+
+ if (tHiddenItemFound == FALSE)
+ {
+ tItemX = dx;
+ tItemY = dy;
+ tHiddenItemFound = TRUE;
+ }
+ else
+ {
+ // tItemX and tItemY contain the player's coordinates.
+ // dx and dy contain the item's coordinates.
+ if (tItemX < 0)
+ dx2 = tItemX * -1; // item is to the left
+ else
+ dx2 = tItemX; // item is to the right
+
+ if (tItemY < 0)
+ dy2 = tItemY * -1; // item is to the north
+ else
+ dy2 = tItemY; // item is to the south
+
+ if (dx < 0)
+ dx3 = dx * -1;
+ else
+ dx3 = dx;
+
+ if (dy < 0)
+ dy3 = dy * -1;
+ else
+ dy3 = dy;
+
+ if (dx2 + dy2 > dx3 + dy3)
+ {
+ tItemX = dx;
+ tItemY = dy;
+ }
+ else
+ {
+ if (dx2 + dy2 == dx3 + dy3 && (dy2 > dy3 || (dy2 == dy3 && tItemY < dy)))
+ {
+ tItemX = dx;
+ tItemY = dy;
+ }
+ }
+ }
+}
+
+static u8 GetPlayerDirectionTowardsHiddenItem(s16 itemX, s16 itemY)
+{
+ s16 abX, abY;
+
+ if (itemX == 0 && itemY == 0)
+ return DIR_NONE; // player is standing on the item.
+
+ // get absolute X distance.
+ if (itemX < 0)
+ abX = itemX * -1;
+ else
+ abX = itemX;
+
+ // get absolute Y distance.
+ if (itemY < 0)
+ abY = itemY * -1;
+ else
+ abY = itemY;
+
+ if (abX > abY)
+ {
+ if (itemX < 0)
+ return DIR_EAST;
+ else
+ return DIR_NORTH;
+ }
+ else
+ {
+ if (abX < abY)
+ {
+ if (itemY < 0)
+ return DIR_SOUTH;
+ else
+ return DIR_WEST;
+ }
+ if (abX == abY)
+ {
+ if (itemY < 0)
+ return DIR_SOUTH;
+ else
+ return DIR_WEST;
+ }
+ return DIR_NONE; // should never get here. return something so it doesnt crash.
+ }
+}
+
+static void Task_ItemfinderResponsePrintMessage(u8 taskId)
+{
+ DisplayItemMessageOnField(taskId, 2, gText_ItemfinderResponding, Task_ItemfinderResponseCleanUp);
+}
+
+static void Task_ItemfinderResponseCleanUp(u8 taskId)
+{
+ DestroyArrowAndStarTiles();
+ ClearDialogWindowAndFrame(0, TRUE);
+ sub_80696C0();
+ ScriptContext2_Disable();
+ DestroyTask(taskId);
+}
+
+static void Task_ItemfinderUnderfootPrintMessage(u8 taskId)
+{
+ DisplayItemMessageOnField(taskId, 2, gText_ItemfinderShakingWildly, Task_ItemfinderUnderfootDigUpItem);
+}
+
+static void Task_ItemfinderUnderfootDigUpItem(u8 taskId)
+{
+ DestroyArrowAndStarTiles();
+ DestroyTask(taskId);
+ ScriptContext1_SetupScript(EventScript_ItemfinderDigUpUnderfootItem);
+ ScriptContext2_Enable();
+}
+
+#undef tStartSpriteId
+#undef tUnderfoot
+#undef tDingNum
+#undef tNumDingsRemaining
+#undef tDingTimer
+#undef tHiddenItemFound
+#undef tItemY
+#undef tItemX
+
+#define spData0 data[0]
+#define spDeltaX data[1]
+#define spDeltaY data[2]
+#define spCurX data[3]
+#define spCurY data[4]
+#define spCenterX data[5]
+#define spCenterY data[6]
+#define spAnimNum data[7]
+
+static void LoadArrowAndStarTiles(void)
+{
+ LoadSpriteSheet(&sArrowAndStarSpriteSheet);
+}
+
+static void DestroyArrowAndStarTiles(void)
+{
+ FreeSpriteTilesByTag(ARROW_TILE_TAG);
+}
+
+static void CreateArrowSprite(u8 animNum, u8 direction)
+{
+ u8 spriteId = CreateSprite(&gUnknown_84647E4, 120, 76, 0);
+ gSprites[spriteId].oam.paletteNum = 0;
+ StartSpriteAnim(&gSprites[spriteId], animNum);
+ gSprites[spriteId].spAnimNum = animNum;
+ gSprites[spriteId].spData0 = 0;
+ gSprites[spriteId].spCurX = 0;
+ gSprites[spriteId].spCurY = 0;
+ gSprites[spriteId].spCenterX = 120;
+ gSprites[spriteId].spCenterY = 76;
+ switch (direction)
+ {
+ case DIR_NONE:
+ switch (GetPlayerFacingDirection())
+ {
+ case DIR_WEST:
+ gSprites[spriteId].spDeltaX = -100;
+ gSprites[spriteId].spDeltaY = 0;
+ StartSpriteAffineAnim(&gSprites[spriteId], 0);
+ break;
+ case DIR_NORTH:
+ gSprites[spriteId].spDeltaX = 0;
+ gSprites[spriteId].spDeltaY = -100;
+ StartSpriteAffineAnim(&gSprites[spriteId], 3);
+ break;
+ case DIR_EAST:
+ gSprites[spriteId].spDeltaX = 100;
+ gSprites[spriteId].spDeltaY = 0;
+ StartSpriteAffineAnim(&gSprites[spriteId], 2);
+ break;
+ case DIR_SOUTH:
+ gSprites[spriteId].spDeltaX = 0;
+ gSprites[spriteId].spDeltaY = 100;
+ StartSpriteAffineAnim(&gSprites[spriteId], 1);
+ break;
+ }
+ break;
+ case DIR_SOUTH:
+ gSprites[spriteId].spDeltaX = 0;
+ gSprites[spriteId].spDeltaY = -100;
+ StartSpriteAffineAnim(&gSprites[spriteId], 3);
+ break;
+ case DIR_NORTH:
+ gSprites[spriteId].spDeltaX = 100;
+ gSprites[spriteId].spDeltaY = 0;
+ StartSpriteAffineAnim(&gSprites[spriteId], 2);
+ break;
+ case DIR_WEST:
+ gSprites[spriteId].spDeltaX = 0;
+ gSprites[spriteId].spDeltaY = 100;
+ StartSpriteAffineAnim(&gSprites[spriteId], 1);
+ break;
+ case DIR_EAST:
+ gSprites[spriteId].spDeltaX = -100;
+ gSprites[spriteId].spDeltaY = 0;
+ break;
+ }
+}
+
+static void SpriteCallback_Arrow(struct Sprite * sprite)
+{
+ s16 x, y;
+ sprite->spCurX += sprite->spDeltaX;
+ sprite->spCurY += sprite->spDeltaY;
+ sprite->pos1.x = sprite->spCenterX + (sprite->spCurX >> 8);
+ sprite->pos1.y = sprite->spCenterY + (sprite->spCurY >> 8);
+ if (sprite->pos1.x <= 104
+ || sprite->pos1.x > 132
+ || sprite->pos1.y <= 60
+ || sprite->pos1.y > 88)
+ sprite->callback = SpriteCallback_DestroyArrow;
+}
+
+static void SpriteCallback_DestroyArrow(struct Sprite * sprite)
+{
+ FreeSpriteOamMatrix(sprite);
+ DestroySprite(sprite);
+}
+
+static u8 CreateStarSprite(void)
+{
+ u8 spriteId = CreateSprite(&gUnknown_84647E4, 120, 76, 0);
+ gSprites[spriteId].oam.paletteNum = 0;
+ gSprites[spriteId].callback = SpriteCallback_Star;
+ StartSpriteAnim(&gSprites[spriteId], 4);
+ gSprites[spriteId].spAnimNum = 0;
+ gSprites[spriteId].spData0 = 0;
+ gSprites[spriteId].spCurX = 0;
+ gSprites[spriteId].spCurY = 0;
+ gSprites[spriteId].spCenterX = 120;
+ gSprites[spriteId].spCenterY = 76;
+ gSprites[spriteId].spDeltaX = 0;
+ gSprites[spriteId].spDeltaY = -100;
+ return spriteId;
+}
+
+static void SpriteCallback_Star(struct Sprite * sprite)
+{
+ s16 x, y;
+ sprite->spCurX += sprite->spDeltaX;
+ sprite->spCurY += sprite->spDeltaY;
+ sprite->pos1.x = sprite->spCenterX + (sprite->spCurX >> 8);
+ sprite->pos1.y = sprite->spCenterY + (sprite->spCurY >> 8);
+ if (sprite->pos1.x <= 104
+ || sprite->pos1.x > 132
+ || sprite->pos1.y <= 60
+ || sprite->pos1.y > 88)
+ sprite->callback = SpriteCallback_DestroyStar;
+}
+
+static void SpriteCallback_DestroyStar(struct Sprite * sprite)
+{
+ DestroySprite(sprite);
+}
+
+#undef spAnimNum
+#undef spCenterY
+#undef spCenterX
+#undef spCurY
+#undef spCurX
+#undef spDeltaY
+#undef spDeltaX
+#undef spData0