Document more field effects

This commit is contained in:
GriffinR
2021-04-05 10:32:33 -04:00
parent f90026826a
commit 553fe6239a
4 changed files with 108 additions and 78 deletions
+14 -8
View File
@@ -1,16 +1,22 @@
#ifndef GUARD_FIELD_EFFECT_HELPERS_H #ifndef GUARD_FIELD_EFFECT_HELPERS_H
#define GUARD_FIELD_EFFECT_HELPERS_H #define GUARD_FIELD_EFFECT_HELPERS_H
// Exported type declarations // States for bobbing up and down while surfing
enum {
// No bobbing
BOB_NONE,
// Both the surf blob/mon should bob up and down
BOB_PLAYER_AND_MON,
// Only the surf blob/mon should bob up and down
// For when the player has jumped/flown off
BOB_JUST_MON,
};
// Exported RAM declarations
// Exported ROM declarations
u8 CreateWarpArrowSprite(void); u8 CreateWarpArrowSprite(void);
u8 sub_8155800(u8 oldSpriteId); u8 StartUnderwaterSurfBlobBobbing(u8 oldSpriteId);
void SetSurfBobState(u8 spriteId, u8 value); void SetSurfBlob_BobState(u8 spriteId, u8 state);
void SetSurfBobWhileFlyingOutState(u8 spriteId, u8 value); void SetSurfBlob_DontSyncAnim(u8 spriteId, bool8 dontSync);
void SetSurfBobWhileFishingState(u8 spriteId, u8 value, s16 data1); void SetSurfBlob_PlayerOffset(u8 spriteId, bool8 hasOffset, s16 offset);
bool8 sub_8155DA0(struct ObjectEvent *); bool8 sub_8155DA0(struct ObjectEvent *);
void sub_8155D78(struct ObjectEvent *); void sub_8155D78(struct ObjectEvent *);
void StartAshFieldEffect(s16, s16, u16, s16); void StartAshFieldEffect(s16, s16, u16, s16);
+5 -5
View File
@@ -3053,7 +3053,7 @@ static void SurfFieldEffect_End(struct Task *task)
gPlayerAvatar.preventStep = FALSE; gPlayerAvatar.preventStep = FALSE;
gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_5; gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_5;
ObjectEventSetHeldMovement(objectEvent, GetFaceDirectionMovementAction(objectEvent->movementDirection)); ObjectEventSetHeldMovement(objectEvent, GetFaceDirectionMovementAction(objectEvent->movementDirection));
SetSurfBobState(objectEvent->fieldEffectSpriteId, 1); SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_PLAYER_AND_MON);
UnfreezeObjectEvents(); UnfreezeObjectEvents();
ScriptContext2_Disable(); ScriptContext2_Disable();
FieldEffectActiveListRemove(FLDEFF_USE_SURF); FieldEffectActiveListRemove(FLDEFF_USE_SURF);
@@ -3204,8 +3204,8 @@ static void FlyOutFieldEffect_BirdLeaveBall(struct Task *task)
struct ObjectEvent *objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; struct ObjectEvent *objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId];
if (task->tAvatarFlags & PLAYER_AVATAR_FLAG_SURFING) if (task->tAvatarFlags & PLAYER_AVATAR_FLAG_SURFING)
{ {
SetSurfBobState(objectEvent->fieldEffectSpriteId, 2); SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_JUST_MON);
SetSurfBobWhileFlyingOutState(objectEvent->fieldEffectSpriteId, 0); SetSurfBlob_DontSyncAnim(objectEvent->fieldEffectSpriteId, FALSE);
} }
task->tBirdSpriteId = CreateFlyBirdSprite(); // Does "leave ball" animation by default task->tBirdSpriteId = CreateFlyBirdSprite(); // Does "leave ball" animation by default
task->tState++; task->tState++;
@@ -3473,7 +3473,7 @@ static void FlyInFieldEffect_BirdSwoopDown(struct Task *task)
SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_ON_FOOT); SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_ON_FOOT);
if (task->tAvatarFlags & PLAYER_AVATAR_FLAG_SURFING) if (task->tAvatarFlags & PLAYER_AVATAR_FLAG_SURFING)
{ {
SetSurfBobState(objectEvent->fieldEffectSpriteId, 0); SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_NONE);
} }
ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_SURFING)); ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_SURFING));
CameraObjectReset2(); CameraObjectReset2();
@@ -3582,7 +3582,7 @@ static void FlyInFieldEffect_End(struct Task *task)
if (task->tAvatarFlags & PLAYER_AVATAR_FLAG_SURFING) if (task->tAvatarFlags & PLAYER_AVATAR_FLAG_SURFING)
{ {
state = PLAYER_AVATAR_STATE_SURFING; state = PLAYER_AVATAR_STATE_SURFING;
SetSurfBobState(objectEvent->fieldEffectSpriteId, 1); SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_PLAYER_AND_MON);
} }
ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(state)); ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(state));
ObjectEventTurn(objectEvent, DIR_SOUTH); ObjectEventTurn(objectEvent, DIR_SOUTH);
+83 -59
View File
@@ -27,9 +27,9 @@ static void UpdateAshFieldEffect_Wait(struct Sprite *);
static void UpdateAshFieldEffect_Show(struct Sprite *); static void UpdateAshFieldEffect_Show(struct Sprite *);
static void UpdateAshFieldEffect_End(struct Sprite *); static void UpdateAshFieldEffect_End(struct Sprite *);
static void SynchroniseSurfAnim(struct ObjectEvent *, struct Sprite *); static void SynchroniseSurfAnim(struct ObjectEvent *, struct Sprite *);
static void sub_81556E8(struct ObjectEvent *, struct Sprite *); static void SynchroniseSurfPosition(struct ObjectEvent *, struct Sprite *);
static void CreateBobbingEffect(struct ObjectEvent *, struct Sprite *, struct Sprite *); static void UpdateBobbingEffect(struct ObjectEvent *, struct Sprite *, struct Sprite *);
static void sub_8155850(struct Sprite *); static void SpriteCB_UnderwaterSurfBlob(struct Sprite *);
static u32 ShowDisguiseFieldEffect(u8, u8, u8); static u32 ShowDisguiseFieldEffect(u8, u8, u8);
#define sReflectionObjEventId data[0] #define sReflectionObjEventId data[0]
@@ -995,6 +995,12 @@ static void UpdateAshFieldEffect_End(struct Sprite *sprite)
#undef sMetatileId #undef sMetatileId
#undef sDelay #undef sDelay
// Sprite data for FLDEFF_SURF_BLOB
#define tBitfield data[0]
#define tPlayerOffset data[1]
#define tPlayerObjId data[2]
u32 FldEff_SurfBlob(void) u32 FldEff_SurfBlob(void)
{ {
u8 spriteId; u8 spriteId;
@@ -1007,7 +1013,7 @@ u32 FldEff_SurfBlob(void)
sprite = &gSprites[spriteId]; sprite = &gSprites[spriteId];
sprite->coordOffsetEnabled = TRUE; sprite->coordOffsetEnabled = TRUE;
sprite->oam.paletteNum = 0; sprite->oam.paletteNum = 0;
sprite->data[2] = gFieldEffectArguments[2]; sprite->tPlayerObjId = gFieldEffectArguments[2];
sprite->data[3] = -1; sprite->data[3] = -1;
sprite->data[6] = -1; sprite->data[6] = -1;
sprite->data[7] = -1; sprite->data[7] = -1;
@@ -1016,53 +1022,55 @@ u32 FldEff_SurfBlob(void)
return spriteId; return spriteId;
} }
// States for bobbing up and down while surfing
void SetSurfBobState(u8 spriteId, u8 value) void SetSurfBlob_BobState(u8 spriteId, u8 state)
{ {
gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF) | (value & 0xF); gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF) | (state & 0xF);
} }
void SetSurfBobWhileFlyingOutState(u8 spriteId, u8 value) void SetSurfBlob_DontSyncAnim(u8 spriteId, bool8 dontSync)
{ {
gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF0) | ((value & 0xF) << 4); gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF0) | ((dontSync & 0xF) << 4);
} }
void SetSurfBobWhileFishingState(u8 spriteId, u8 value, s16 data1) void SetSurfBlob_PlayerOffset(u8 spriteId, bool8 hasOffset, s16 offset)
{ {
gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF00) | ((value & 0xF) << 8); gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF00) | ((hasOffset & 0xF) << 8);
gSprites[spriteId].data[1] = data1; gSprites[spriteId].tPlayerOffset = offset;
} }
static u8 GetSurfBobState(struct Sprite *sprite) static u8 GetSurfBlob_BobState(struct Sprite *sprite)
{ {
return sprite->data[0] & 0xF; return sprite->data[0] & 0xF;
} }
static u8 GetSurfBobWhileFlyingOutState(struct Sprite *sprite) // Never TRUE
static u8 GetSurfBlob_DontSyncAnim(struct Sprite *sprite)
{ {
return (sprite->data[0] & 0xF0) >> 4; return (sprite->data[0] & 0xF0) >> 4;
} }
static u8 GetSurfBobWhileFishingState(struct Sprite *sprite) static u8 GetSurfBlob_HasPlayerOffset(struct Sprite *sprite)
{ {
return (sprite->data[0] & 0xF00) >> 8; return (sprite->data[0] & 0xF00) >> 8;
} }
void UpdateSurfBlobFieldEffect(struct Sprite *sprite) void UpdateSurfBlobFieldEffect(struct Sprite *sprite)
{ {
struct ObjectEvent *objectEvent; struct ObjectEvent *playerObj;
struct Sprite *linkedSprite; struct Sprite *playerSprite;
objectEvent = &gObjectEvents[sprite->data[2]]; playerObj = &gObjectEvents[sprite->tPlayerObjId];
linkedSprite = &gSprites[objectEvent->spriteId]; playerSprite = &gSprites[playerObj->spriteId];
SynchroniseSurfAnim(objectEvent, sprite); SynchroniseSurfAnim(playerObj, sprite);
sub_81556E8(objectEvent, sprite); SynchroniseSurfPosition(playerObj, sprite);
CreateBobbingEffect(objectEvent, linkedSprite, sprite); UpdateBobbingEffect(playerObj, playerSprite, sprite);
sprite->oam.priority = linkedSprite->oam.priority; sprite->oam.priority = playerSprite->oam.priority;
} }
static void SynchroniseSurfAnim(struct ObjectEvent *objectEvent, struct Sprite *sprite) static void SynchroniseSurfAnim(struct ObjectEvent *playerObj, struct Sprite *sprite)
{ {
// Indexes into sAnimTable_SurfBlob
u8 surfBlobDirectionAnims[] = { u8 surfBlobDirectionAnims[] = {
[DIR_NONE] = 0, [DIR_NONE] = 0,
[DIR_SOUTH] = 0, [DIR_SOUTH] = 0,
@@ -1075,15 +1083,15 @@ static void SynchroniseSurfAnim(struct ObjectEvent *objectEvent, struct Sprite *
[DIR_NORTHEAST] = 1, [DIR_NORTHEAST] = 1,
}; };
if (GetSurfBobWhileFlyingOutState(sprite) == 0) if (!GetSurfBlob_DontSyncAnim(sprite))
StartSpriteAnimIfDifferent(sprite, surfBlobDirectionAnims[objectEvent->movementDirection]); StartSpriteAnimIfDifferent(sprite, surfBlobDirectionAnims[playerObj->movementDirection]);
} }
void sub_81556E8(struct ObjectEvent *objectEvent, struct Sprite *sprite) void SynchroniseSurfPosition(struct ObjectEvent *playerObj, struct Sprite *sprite)
{ {
u8 i; u8 i;
s16 x = objectEvent->currentCoords.x; s16 x = playerObj->currentCoords.x;
s16 y = objectEvent->currentCoords.y; s16 y = playerObj->currentCoords.y;
s32 spriteY = sprite->pos2.y; s32 spriteY = sprite->pos2.y;
if (spriteY == 0 && (x != sprite->data[6] || y != sprite->data[7])) if (spriteY == 0 && (x != sprite->data[6] || y != sprite->data[7]))
@@ -1103,61 +1111,74 @@ void sub_81556E8(struct ObjectEvent *objectEvent, struct Sprite *sprite)
} }
} }
static void CreateBobbingEffect(struct ObjectEvent *objectEvent, struct Sprite *linkedSprite, struct Sprite *sprite) static void UpdateBobbingEffect(struct ObjectEvent *playerObj, struct Sprite *playerSprite, struct Sprite *sprite)
{ {
u16 unk_085CDC6A[] = {3, 7}; u16 intervals[] = {3, 7};
u8 bobState = GetSurfBobState(sprite); u8 bobState = GetSurfBlob_BobState(sprite);
if (bobState != 0) if (bobState != BOB_NONE)
{ {
if (((u16)(++ sprite->data[4]) & unk_085CDC6A[sprite->data[5]]) == 0) // Update bobbing position of surf blob
if (((u16)(++sprite->data[4]) & intervals[sprite->data[5]]) == 0)
{ {
sprite->pos2.y += sprite->data[3]; sprite->pos2.y += sprite->data[3];
} }
if ((sprite->data[4] & 0x0F) == 0) if ((sprite->data[4] & 15) == 0)
{ {
sprite->data[3] = -sprite->data[3]; sprite->data[3] = -sprite->data[3];
} }
if (bobState != 2) if (bobState != BOB_JUST_MON)
{ {
if (GetSurfBobWhileFishingState(sprite) == 0) // Update bobbing position of player
linkedSprite->pos2.y = sprite->pos2.y; if (!GetSurfBlob_HasPlayerOffset(sprite))
playerSprite->pos2.y = sprite->pos2.y;
else else
linkedSprite->pos2.y = sprite->data[1] + sprite->pos2.y; playerSprite->pos2.y = sprite->tPlayerOffset + sprite->pos2.y;
sprite->pos1.x = linkedSprite->pos1.x; sprite->pos1.x = playerSprite->pos1.x;
sprite->pos1.y = linkedSprite->pos1.y + 8; sprite->pos1.y = playerSprite->pos1.y + 8;
} }
} }
} }
u8 sub_8155800(u8 oldSpriteId) #define sSpriteId data[0]
#define sBobY data[1]
#define sTimer data[2]
u8 StartUnderwaterSurfBlobBobbing(u8 blobSpriteId)
{ {
u8 spriteId; u8 spriteId;
struct Sprite *sprite; struct Sprite *sprite;
// Create a dummy sprite with its own callback
// that tracks the actual surf blob sprite and
// makes it bob up and down underwater
spriteId = CreateSpriteAtEnd(&gDummySpriteTemplate, 0, 0, -1); spriteId = CreateSpriteAtEnd(&gDummySpriteTemplate, 0, 0, -1);
sprite = &gSprites[spriteId]; sprite = &gSprites[spriteId];
sprite->callback = sub_8155850; sprite->callback = SpriteCB_UnderwaterSurfBlob;
sprite->invisible = TRUE; sprite->invisible = TRUE;
sprite->data[0] = oldSpriteId; sprite->sSpriteId = blobSpriteId;
sprite->data[1] = 1; sprite->sBobY = 1;
return spriteId; return spriteId;
} }
static void sub_8155850(struct Sprite *sprite) static void SpriteCB_UnderwaterSurfBlob(struct Sprite *sprite)
{ {
struct Sprite *oldSprite; struct Sprite *blobSprite;
oldSprite = &gSprites[sprite->data[0]]; blobSprite = &gSprites[sprite->sSpriteId];
if (((sprite->data[2]++) & 0x03) == 0) if (((sprite->sTimer++) & 3) == 0)
{ {
oldSprite->pos2.y += sprite->data[1]; blobSprite->pos2.y += sprite->sBobY;
} }
if ((sprite->data[2] & 0x0F) == 0) if ((sprite->sTimer & 15) == 0)
{ {
sprite->data[1] = -sprite->data[1]; sprite->sBobY = -sprite->sBobY;
} }
} }
#undef sSpriteId
#undef sBobY
#undef sTimer
u32 FldEff_Dust(void) u32 FldEff_Dust(void)
{ {
u8 spriteId; u8 spriteId;
@@ -1397,24 +1418,27 @@ u32 FldEff_Sparkle(void)
return 0; return 0;
} }
#define sFinished data[0]
#define sEndTimer data[1]
void UpdateSparkleFieldEffect(struct Sprite *sprite) void UpdateSparkleFieldEffect(struct Sprite *sprite)
{ {
if (sprite->data[0] == 0) if (!sprite->sFinished)
{ {
if (sprite->animEnded) if (sprite->animEnded)
{ {
sprite->invisible = TRUE; sprite->invisible = TRUE;
sprite->data[0]++; sprite->sFinished++;
}
} }
if (sprite->data[0] == 0) if (sprite->sFinished && ++sprite->sEndTimer > 34)
return;
}
if (++sprite->data[1] > 34)
FieldEffectStop(sprite, FLDEFF_SPARKLE); FieldEffectStop(sprite, FLDEFF_SPARKLE);
} }
#undef sFinished
#undef sEndTimer
#define sTimer data[0] #define sTimer data[0]
#define sState data[2] #define sState data[2]
#define sStartY data[4] #define sStartY data[4]
+6 -6
View File
@@ -863,7 +863,7 @@ static void PlayerAvatarTransition_Surfing(struct ObjectEvent *objEvent)
gFieldEffectArguments[2] = gPlayerAvatar.objectEventId; gFieldEffectArguments[2] = gPlayerAvatar.objectEventId;
spriteId = FieldEffectStart(FLDEFF_SURF_BLOB); spriteId = FieldEffectStart(FLDEFF_SURF_BLOB);
objEvent->fieldEffectSpriteId = spriteId; objEvent->fieldEffectSpriteId = spriteId;
SetSurfBobState(spriteId, 1); SetSurfBlob_BobState(spriteId, BOB_PLAYER_AND_MON);
} }
static void PlayerAvatarTransition_Underwater(struct ObjectEvent *objEvent) static void PlayerAvatarTransition_Underwater(struct ObjectEvent *objEvent)
@@ -871,7 +871,7 @@ static void PlayerAvatarTransition_Underwater(struct ObjectEvent *objEvent)
ObjectEventSetGraphicsId(objEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_UNDERWATER)); ObjectEventSetGraphicsId(objEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_UNDERWATER));
ObjectEventTurn(objEvent, objEvent->movementDirection); ObjectEventTurn(objEvent, objEvent->movementDirection);
SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_UNDERWATER); SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_UNDERWATER);
objEvent->fieldEffectSpriteId = sub_8155800(objEvent->spriteId); objEvent->fieldEffectSpriteId = StartUnderwaterSurfBlobBobbing(objEvent->spriteId);
} }
static void PlayerAvatarTransition_ReturnToField(struct ObjectEvent *objEvent) static void PlayerAvatarTransition_ReturnToField(struct ObjectEvent *objEvent)
@@ -1646,7 +1646,7 @@ static void Task_StopSurfingInit(u8 taskId)
if (!ObjectEventClearHeldMovementIfFinished(playerObjEvent)) if (!ObjectEventClearHeldMovementIfFinished(playerObjEvent))
return; return;
} }
SetSurfBobState(playerObjEvent->fieldEffectSpriteId, 2); SetSurfBlob_BobState(playerObjEvent->fieldEffectSpriteId, BOB_JUST_MON);
ObjectEventSetHeldMovement(playerObjEvent, GetJumpSpecialMovementAction((u8)gTasks[taskId].data[0])); ObjectEventSetHeldMovement(playerObjEvent, GetJumpSpecialMovementAction((u8)gTasks[taskId].data[0]));
gTasks[taskId].func = Task_WaitStopSurfing; gTasks[taskId].func = Task_WaitStopSurfing;
} }
@@ -1932,7 +1932,7 @@ static bool8 Fishing_StartEncounter(struct Task *task)
ObjectEventSetGraphicsId(playerObjEvent, task->tPlayerGfxId); ObjectEventSetGraphicsId(playerObjEvent, task->tPlayerGfxId);
ObjectEventTurn(playerObjEvent, playerObjEvent->movementDirection); ObjectEventTurn(playerObjEvent, playerObjEvent->movementDirection);
if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING)
SetSurfBobWhileFishingState(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, 0, 0); SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, FALSE, 0);
gSprites[gPlayerAvatar.spriteId].pos2.x = 0; gSprites[gPlayerAvatar.spriteId].pos2.x = 0;
gSprites[gPlayerAvatar.spriteId].pos2.y = 0; gSprites[gPlayerAvatar.spriteId].pos2.y = 0;
ClearDialogWindowAndFrame(0, TRUE); ClearDialogWindowAndFrame(0, TRUE);
@@ -1989,7 +1989,7 @@ static bool8 Fishing_PutRodAway(struct Task *task)
ObjectEventSetGraphicsId(playerObjEvent, task->tPlayerGfxId); ObjectEventSetGraphicsId(playerObjEvent, task->tPlayerGfxId);
ObjectEventTurn(playerObjEvent, playerObjEvent->movementDirection); ObjectEventTurn(playerObjEvent, playerObjEvent->movementDirection);
if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING)
SetSurfBobWhileFishingState(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, 0, 0); SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, FALSE, 0);
gSprites[gPlayerAvatar.spriteId].pos2.x = 0; gSprites[gPlayerAvatar.spriteId].pos2.x = 0;
gSprites[gPlayerAvatar.spriteId].pos2.y = 0; gSprites[gPlayerAvatar.spriteId].pos2.y = 0;
task->tStep++; task->tStep++;
@@ -2048,7 +2048,7 @@ static void AlignFishingAnimationFrames(void)
if (animType == 10 || animType == 11) if (animType == 10 || animType == 11)
playerSprite->pos2.y = 8; playerSprite->pos2.y = 8;
if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING)
SetSurfBobWhileFishingState(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, 1, playerSprite->pos2.y); SetSurfBlob_PlayerOffset(gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId, TRUE, playerSprite->pos2.y);
} }
void SetSpinStartFacingDir(u8 direction) void SetSpinStartFacingDir(u8 direction)