2018-07-19 17:52:35 +01:00
|
|
|
#include "global.h"
|
|
|
|
#include "global.fieldmap.h"
|
|
|
|
#include "sprite.h"
|
|
|
|
#include "event_object_movement.h"
|
|
|
|
#include "bike.h"
|
|
|
|
|
2018-07-20 23:36:40 +01:00
|
|
|
extern bool8 (*const gUnknown_08497444[])(void);
|
|
|
|
extern bool8 (*const gUnknown_084973FC[])(u8);
|
|
|
|
|
|
|
|
void sub_808C5B0(void);
|
|
|
|
void sub_808C4D8(void);
|
|
|
|
void PlayerJumpLedge(u8);
|
|
|
|
u8 CheckForPlayerAvatarCollision(u8);
|
|
|
|
void PlayerGoSpeed1(u8);
|
|
|
|
void PlayerGoSpeed2(u8);
|
|
|
|
void PlayerGoSpeed3(u8);
|
2018-07-19 17:52:35 +01:00
|
|
|
static u8 EventObjectCB2_NoMovement2();
|
|
|
|
void sub_808C280(struct EventObject *); //struct EventObject *playerEventObj
|
|
|
|
bool8 TryInterruptEventObjectSpecialAnim(struct EventObject *, u8);
|
|
|
|
void npc_clear_strange_bits(struct EventObject *);
|
2018-07-20 00:14:20 +01:00
|
|
|
u8 EventObjectGetHeldMovementActionId(struct EventObject *);
|
2018-07-19 17:52:35 +01:00
|
|
|
void DoPlayerAvatarTransition(void);
|
|
|
|
bool8 TryDoMetatileBehaviorForcedMovement();
|
|
|
|
void MovePlayerAvatarUsingKeypadInput(u8, u16, u16);
|
|
|
|
void PlayerAllowForcedMovementIfMovingSameDirection();
|
2018-07-20 00:14:20 +01:00
|
|
|
void MovePlayerNotOnBike(u8 a, u16 b);
|
|
|
|
u8 sub_808B028(u8);
|
2018-07-20 23:36:40 +01:00
|
|
|
u8 GetForcedMovementByMetatileBehavior();
|
2018-07-19 17:52:35 +01:00
|
|
|
|
|
|
|
void MovementType_Player(struct Sprite *sprite)
|
|
|
|
{
|
|
|
|
// ((Sprite->data[0] << 3) + Sprite->data[0]) << 2
|
|
|
|
UpdateEventObjectCurrentMovement(&gEventObjects[sprite->data[0]], sprite, EventObjectCB2_NoMovement2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static u8 EventObjectCB2_NoMovement2()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void player_step(u8 direction, u16 newKeys, u16 heldKeys)
|
|
|
|
{
|
|
|
|
struct EventObject *playerEventObj = &gEventObjects[gPlayerAvatar.eventObjectId];
|
|
|
|
|
|
|
|
sub_808C280(playerEventObj);
|
|
|
|
if (gPlayerAvatar.preventStep == FALSE)
|
|
|
|
{
|
|
|
|
Bike_TryAcroBikeHistoryUpdate(newKeys, heldKeys);
|
|
|
|
if (TryInterruptEventObjectSpecialAnim(playerEventObj, direction) == 0)
|
|
|
|
{
|
|
|
|
npc_clear_strange_bits(playerEventObj);
|
|
|
|
DoPlayerAvatarTransition();
|
|
|
|
if (TryDoMetatileBehaviorForcedMovement() == 0)
|
|
|
|
{
|
|
|
|
MovePlayerAvatarUsingKeypadInput(direction, newKeys, heldKeys);
|
|
|
|
PlayerAllowForcedMovementIfMovingSameDirection();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-20 00:14:20 +01:00
|
|
|
|
|
|
|
NAKED
|
|
|
|
bool8 TryInterruptEventObjectSpecialAnim(struct EventObject *eventObject, u8 direction)
|
|
|
|
{
|
|
|
|
asm_unified("push {r4-r6,lr}\n\
|
|
|
|
adds r4, r0, 0\n\
|
|
|
|
lsls r1, 24\n\
|
|
|
|
lsrs r5, r1, 24\n\
|
|
|
|
adds r6, r5, 0\n\
|
|
|
|
bl EventObjectIsMovementOverridden\n\
|
|
|
|
lsls r0, 24\n\
|
|
|
|
cmp r0, 0\n\
|
|
|
|
beq _0808AA92\n\
|
|
|
|
adds r0, r4, 0\n\
|
|
|
|
bl EventObjectClearHeldMovementIfFinished\n\
|
|
|
|
lsls r0, 24\n\
|
|
|
|
cmp r0, 0\n\
|
|
|
|
bne _0808AA92\n\
|
|
|
|
adds r0, r4, 0\n\
|
|
|
|
bl EventObjectGetHeldMovementActionId\n\
|
|
|
|
lsls r0, 24\n\
|
|
|
|
movs r1, 0xE7\n\
|
|
|
|
lsls r1, 24\n\
|
|
|
|
adds r0, r1\n\
|
|
|
|
lsrs r0, 24\n\
|
|
|
|
cmp r0, 0x3\n\
|
|
|
|
bhi _0808AA70\n\
|
|
|
|
cmp r5, 0\n\
|
|
|
|
bne _0808AA74\n\
|
|
|
|
_0808AA70:\n\
|
|
|
|
movs r0, 0x1\n\
|
|
|
|
b _0808AA94\n\
|
|
|
|
_0808AA74:\n\
|
|
|
|
ldrb r0, [r4, 0x18]\n\
|
|
|
|
lsrs r0, 4\n\
|
|
|
|
cmp r0, r5\n\
|
|
|
|
beq _0808AA84\n\
|
|
|
|
_0808AA7C:\n\
|
|
|
|
adds r0, r4, 0\n\
|
|
|
|
bl EventObjectClearHeldMovement\n\
|
|
|
|
b _0808AA92\n\
|
|
|
|
_0808AA84:\n\
|
|
|
|
adds r0, r6, 0\n\
|
|
|
|
bl sub_808B028\n\
|
|
|
|
lsls r0, 24\n\
|
|
|
|
cmp r0, 0\n\
|
|
|
|
beq _0808AA7C\n\
|
|
|
|
b _0808AA70\n\
|
|
|
|
_0808AA92:\n\
|
|
|
|
movs r0, 0\n\
|
|
|
|
_0808AA94:\n\
|
|
|
|
pop {r4-r6}\n\
|
|
|
|
pop {r1}\n\
|
|
|
|
bx r1");
|
|
|
|
}
|
|
|
|
|
|
|
|
void npc_clear_strange_bits(struct EventObject *eventObj)
|
|
|
|
{
|
|
|
|
eventObj->inanimate = 0;
|
|
|
|
eventObj->disableAnim = 0;
|
|
|
|
eventObj->facingDirectionLocked = 0;
|
|
|
|
gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_DASH;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MovePlayerAvatarUsingKeypadInput(u8 direction, u16 newKeys, u16 heldKeys)
|
|
|
|
{
|
|
|
|
if ((gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_MACH_BIKE)
|
|
|
|
|| (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE))
|
|
|
|
MovePlayerOnBike(direction, newKeys, heldKeys);
|
|
|
|
else
|
|
|
|
MovePlayerNotOnBike(direction, heldKeys);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerAllowForcedMovementIfMovingSameDirection(void)
|
|
|
|
{
|
|
|
|
if (gPlayerAvatar.runningState == MOVING)
|
|
|
|
gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_5;
|
|
|
|
}
|
2018-07-20 23:36:40 +01:00
|
|
|
|
|
|
|
bool8 TryDoMetatileBehaviorForcedMovement()
|
|
|
|
{
|
|
|
|
return gUnknown_08497444[GetForcedMovementByMetatileBehavior()]();
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetForcedMovementByMetatileBehavior(void)
|
|
|
|
{
|
|
|
|
u8 i;
|
|
|
|
|
|
|
|
if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_5))
|
|
|
|
{
|
|
|
|
u8 metatileBehavior = gEventObjects[gPlayerAvatar.eventObjectId].currentMetatileBehavior;
|
|
|
|
|
|
|
|
for (i = 0; i < 18; i++)
|
|
|
|
{
|
|
|
|
if (gUnknown_084973FC[i](metatileBehavior))
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_None(void)
|
|
|
|
{
|
|
|
|
if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_6)
|
|
|
|
{
|
|
|
|
struct EventObject *playerEventObj = &gEventObjects[gPlayerAvatar.eventObjectId];
|
|
|
|
|
|
|
|
playerEventObj->facingDirectionLocked = 0;
|
|
|
|
playerEventObj->enableAnim = 1;
|
|
|
|
SetEventObjectDirection(playerEventObj, playerEventObj->facingDirection);
|
|
|
|
gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_6;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static u8 DoForcedMovement(u8 direction, void (*b)(u8))
|
|
|
|
{
|
|
|
|
struct PlayerAvatar *playerAvatar = &gPlayerAvatar;
|
|
|
|
u8 collisionType = CheckForPlayerAvatarCollision(direction);
|
|
|
|
|
|
|
|
playerAvatar->flags |= PLAYER_AVATAR_FLAG_6;
|
|
|
|
if (collisionType != 0)
|
|
|
|
{
|
|
|
|
ForcedMovement_None();
|
|
|
|
if (collisionType <= 4)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (collisionType == COLLISION_LEDGE_JUMP)
|
|
|
|
PlayerJumpLedge(direction);
|
|
|
|
playerAvatar->flags |= PLAYER_AVATAR_FLAG_6;
|
|
|
|
playerAvatar->runningState = MOVING;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
playerAvatar->runningState = MOVING;
|
|
|
|
b(direction);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 DoForcedMovementInCurrentDirection(void (*a)(u8))
|
|
|
|
{
|
|
|
|
struct EventObject *playerEventObj = &gEventObjects[gPlayerAvatar.eventObjectId];
|
|
|
|
|
|
|
|
playerEventObj->disableAnim = 1;
|
|
|
|
return DoForcedMovement(playerEventObj->movementDirection, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_Slip(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovementInCurrentDirection(PlayerGoSpeed2);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_WalkSouth(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovement(DIR_SOUTH, PlayerGoSpeed1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_WalkNorth(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovement(DIR_NORTH, PlayerGoSpeed1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_WalkWest(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovement(DIR_WEST, PlayerGoSpeed1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_WalkEast(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovement(DIR_EAST, PlayerGoSpeed1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_PushedSouthByCurrent(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovement(DIR_SOUTH, PlayerGoSpeed3);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_PushedNorthByCurrent(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovement(DIR_NORTH, PlayerGoSpeed3);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_PushedWestByCurrent(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovement(DIR_WEST, PlayerGoSpeed3);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_PushedEastByCurrent(void)
|
|
|
|
{
|
|
|
|
return DoForcedMovement(DIR_EAST, PlayerGoSpeed3);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 ForcedMovement_Slide(u8 direction, void (*b)(u8))
|
|
|
|
{
|
|
|
|
struct EventObject *playerEventObj = &gEventObjects[gPlayerAvatar.eventObjectId];
|
|
|
|
|
|
|
|
playerEventObj->disableAnim = 1;
|
|
|
|
playerEventObj->facingDirectionLocked = 1;
|
|
|
|
return DoForcedMovement(direction, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_SlideSouth(void)
|
|
|
|
{
|
|
|
|
return ForcedMovement_Slide(DIR_SOUTH, PlayerGoSpeed2);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_SlideNorth(void)
|
|
|
|
{
|
|
|
|
return ForcedMovement_Slide(DIR_NORTH, PlayerGoSpeed2);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_SlideWest(void)
|
|
|
|
{
|
|
|
|
return ForcedMovement_Slide(DIR_WEST, PlayerGoSpeed2);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_SlideEast(void)
|
|
|
|
{
|
|
|
|
return ForcedMovement_Slide(DIR_EAST, PlayerGoSpeed2);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_0xBB(void)
|
|
|
|
{
|
|
|
|
sub_808C4D8();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_0xBC(void)
|
|
|
|
{
|
|
|
|
sub_808C5B0();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool8 ForcedMovement_MuddySlope(void)
|
|
|
|
{
|
|
|
|
struct EventObject *playerEventObj = &gEventObjects[gPlayerAvatar.eventObjectId];
|
|
|
|
|
|
|
|
if (playerEventObj->movementDirection != DIR_NORTH || GetPlayerSpeed() <= 3)
|
|
|
|
{
|
|
|
|
Bike_UpdateBikeCounterSpeed(0);
|
|
|
|
playerEventObj->facingDirectionLocked = 1;
|
|
|
|
return DoForcedMovement(1, PlayerGoSpeed2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|