diff --git a/include/config/overworld.h b/include/config/overworld.h index d59adcbd04..3298a03209 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -4,6 +4,7 @@ // Movement config #define OW_RUNNING_INDOORS GEN_LATEST // In Gen4+, players are allowed to run indoors. #define OW_AUTO_SIGNPOST FALSE // When enabled, if the tile that the player is facing has MB_SIGNPOST, MB_POKEMART_SIGN, or MB_POKEMON_CENTER_SIGN, the player will automatically read the signpost, as seen in FRLG. +#define SLOW_MOVEMENT_ON_STAIRS FALSE // If enabled, the player will move slower up/down stairs like in FR // Other settings #define OW_POISON_DAMAGE GEN_LATEST // In Gen4, Pokémon no longer faint from Poison in the overworld. In Gen5+, they no longer take damage at all. diff --git a/include/constants/event_object_movement.h b/include/constants/event_object_movement.h index e7641f9826..650a6a2357 100755 --- a/include/constants/event_object_movement.h +++ b/include/constants/event_object_movement.h @@ -247,6 +247,10 @@ #define MOVEMENT_ACTION_EMOTE_DOUBLE_EXCL_MARK 0x9F #define MOVEMENT_ACTION_EXIT_POKEBALL 0xA0 #define MOVEMENT_ACTION_ENTER_POKEBALL 0xA1 +#define MOVEMENT_ACTION_RUN_DOWN_SLOW 0xA2 // slow running for rocky stairs +#define MOVEMENT_ACTION_RUN_UP_SLOW 0xA3 +#define MOVEMENT_ACTION_RUN_LEFT_SLOW 0xA4 +#define MOVEMENT_ACTION_RUN_RIGHT_SLOW 0xA5 #define MOVEMENT_ACTION_STEP_END 0xFE #define MOVEMENT_ACTION_NONE 0xFF diff --git a/include/constants/metatile_behaviors.h b/include/constants/metatile_behaviors.h index e033d88838..f5a8f38506 100755 --- a/include/constants/metatile_behaviors.h +++ b/include/constants/metatile_behaviors.h @@ -74,13 +74,13 @@ #define MB_SLIDE_NORTH 0x46 #define MB_SLIDE_SOUTH 0x47 #define MB_TRICK_HOUSE_PUZZLE_8_FLOOR 0x48 -#define MB_UNUSED_49 0x49 -#define MB_UNUSED_4A 0x4A -#define MB_UNUSED_4B 0x4B -#define MB_UNUSED_4C 0x4C -#define MB_UNUSED_4D 0x4D -#define MB_UNUSED_4E 0x4E -#define MB_UNUSED_4F 0x4F +#define MB_SIDEWAYS_STAIRS_RIGHT_SIDE 0x49 +#define MB_SIDEWAYS_STAIRS_LEFT_SIDE 0x4A +#define MB_SIDEWAYS_STAIRS_RIGHT_SIDE_TOP 0x4B +#define MB_SIDEWAYS_STAIRS_LEFT_SIDE_TOP 0x4C +#define MB_SIDEWAYS_STAIRS_RIGHT_SIDE_BOTTOM 0x4D +#define MB_SIDEWAYS_STAIRS_LEFT_SIDE_BOTTOM 0x4E +#define MB_ROCK_STAIRS 0x4F #define MB_EASTWARD_CURRENT 0x50 #define MB_WESTWARD_CURRENT 0x51 #define MB_NORTHWARD_CURRENT 0x52 diff --git a/include/event_object_movement.h b/include/event_object_movement.h index ff132eb95d..22993cddd9 100644 --- a/include/event_object_movement.h +++ b/include/event_object_movement.h @@ -483,6 +483,15 @@ void SetVirtualObjectInvisibility(u8 virtualObjId, bool32 invisible); bool32 IsVirtualObjectInvisible(u8 virtualObjId); void SetVirtualObjectSpriteAnim(u8 virtualObjId, u8 animNum); bool32 IsVirtualObjectAnimating(u8 virtualObjId); +u8 GetObjectEventIdByLocalId(u8 localId); +bool32 IsFollowerVisible(void); + +// run slow +u8 GetPlayerRunSlowMovementAction(u32); +//sideways stairs +u8 GetSidewaysStairsToRightDirection(s16, s16, u8); +u8 GetSidewaysStairsToLeftDirection(s16, s16, u8); +u8 GetSidewaysStairsCollision(struct ObjectEvent *objectEvent, u8 dir, u8 currentBehavior, u8 nextBehavior, u8 collision); bool8 MovementAction_EmoteX_Step0(struct ObjectEvent *, struct Sprite *); bool8 MovementAction_EmoteDoubleExclamationMark_Step0(struct ObjectEvent *, struct Sprite *); diff --git a/include/field_player_avatar.h b/include/field_player_avatar.h index caf28afb87..12de71be8f 100644 --- a/include/field_player_avatar.h +++ b/include/field_player_avatar.h @@ -64,5 +64,9 @@ bool32 IsPlayerSpinExitActive(void); void SetPlayerInvisibility(bool8 invisible); u8 player_get_pos_including_state_based_drift(s16 *x, s16 *y); void StartFishing(u8 rod); +bool8 ObjectMovingOnRockStairs(struct ObjectEvent *objectEvent, u8 direction); +//sideways stairs +u8 GetRightSideStairsDirection(u8 direction); +u8 GetLeftSideStairsDirection(u8 direction); #endif // GUARD_FIELD_PLAYER_AVATAR_H diff --git a/include/global.fieldmap.h b/include/global.fieldmap.h index 5fe34f1381..a9b859209b 100644 --- a/include/global.fieldmap.h +++ b/include/global.fieldmap.h @@ -217,7 +217,8 @@ struct ObjectEvent /*0x1D*/ u8 trainerRange_berryTreeId; /*0x1E*/ u8 currentMetatileBehavior; /*0x1F*/ u8 previousMetatileBehavior; - /*0x20*/ u8 previousMovementDirection; + /*0x20*/ u8 previousMovementDirection:4; + u8 directionOverwrite:4; /*0x21*/ u8 directionSequenceIndex; /*0x22*/ u8 playerCopyableMovement; // COPY_MOVE_* /*0x23*/ u8 spriteId; @@ -298,6 +299,8 @@ enum COLLISION_VERTICAL_RAIL, COLLISION_HORIZONTAL_RAIL, COLLISION_STAIR_WARP, + COLLISION_SIDEWAYS_STAIRS_TO_RIGHT, + COLLISION_SIDEWAYS_STAIRS_TO_LEFT }; // player running states diff --git a/include/metatile_behavior.h b/include/metatile_behavior.h index 77e865d4bf..58eb83ea7b 100644 --- a/include/metatile_behavior.h +++ b/include/metatile_behavior.h @@ -156,5 +156,14 @@ bool8 MetatileBehavior_IsDirectionalStairWarp(u8 metatileBehavior); bool8 MetatileBehavior_IsSignpost(u32); bool8 MetatileBehavior_IsPokemonCenterSign(u32); bool8 MetatileBehavior_IsPokeMartSign(u32); +bool8 MetatileBehavior_IsRockStairs(u8); +bool8 MetatileBehavior_IsSidewaysStairsRightSide(u8); +bool8 MetatileBehavior_IsSidewaysStairsLeftSide(u8); +bool8 MetatileBehavior_IsSidewaysStairsRightSideTop(u8 metatileBehavior); +bool8 MetatileBehavior_IsSidewaysStairsLeftSideTop(u8 metatileBehavior); +bool8 MetatileBehavior_IsSidewaysStairsRightSideBottom(u8 metatileBehavior); +bool8 MetatileBehavior_IsSidewaysStairsLeftSideBottom(u8 metatileBehavior); +bool8 MetatileBehavior_IsSidewaysStairsRightSideAny(u8 metatileBehavior); +bool8 MetatileBehavior_IsSidewaysStairsLeftSideAny(u8 metatileBehavior); #endif // GUARD_METATILE_BEHAVIOR_H diff --git a/src/bike.c b/src/bike.c index de150dae4b..427dfdfcf2 100644 --- a/src/bike.c +++ b/src/bike.c @@ -142,6 +142,19 @@ static u8 GetMachBikeTransition(u8 *dirTraveling) { // if the dir updated before this function, get the relevent new direction to check later. u8 direction = GetPlayerMovementDirection(); + + // fix direction when moving on sideways stairs + switch (direction) + { + case DIR_SOUTHWEST: + case DIR_NORTHWEST: + direction = DIR_WEST; + break; + case DIR_SOUTHEAST: + case DIR_NORTHEAST: + direction = DIR_EAST; + break; + } // is the player standing still? if (*dirTraveling == 0) @@ -234,6 +247,9 @@ static void MachBikeTransition_TrySpeedUp(u8 direction) else { // we did not hit anything that can slow us down, so perform the advancement callback depending on the bikeFrameCounter and try to increase the mach bike's speed. + if (ObjectMovingOnRockStairs(playerObjEvent, direction) && gPlayerAvatar.bikeFrameCounter > 1) + gPlayerAvatar.bikeFrameCounter--; + sMachBikeSpeedCallbacks[gPlayerAvatar.bikeFrameCounter](direction); gPlayerAvatar.bikeSpeed = gPlayerAvatar.bikeFrameCounter + (gPlayerAvatar.bikeFrameCounter >> 1); // same as dividing by 2, but compiler is insistent on >> 1 if (gPlayerAvatar.bikeFrameCounter < 2) // do not go faster than the last element in the mach bike array @@ -368,6 +384,7 @@ static u8 AcroBikeHandleInputWheelieStanding(u8 *newDirection, u16 newKeys, u16 struct ObjectEvent *playerObjEvent; direction = GetPlayerMovementDirection(); + playerObjEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; gPlayerAvatar.runningState = NOT_MOVING; @@ -563,7 +580,10 @@ static void AcroBikeTransition_Moving(u8 direction) } else { - PlayerRideWaterCurrent(direction); + if (ObjectMovingOnRockStairs(playerObjEvent, direction)) + PlayerWalkFast(direction); + else + PlayerRideWaterCurrent(direction); } } @@ -696,6 +716,7 @@ static void AcroBikeTransition_WheelieMoving(u8 direction) } return; } + PlayerWheelieMove(direction); gPlayerAvatar.runningState = MOVING; } @@ -730,6 +751,7 @@ static void AcroBikeTransition_WheelieRisingMoving(u8 direction) } return; } + PlayerPopWheelieWhileMoving(direction); gPlayerAvatar.runningState = MOVING; } @@ -753,6 +775,7 @@ static void AcroBikeTransition_WheelieLoweringMoving(u8 direction) PlayerEndWheelie(direction); return; } + PlayerEndWheelieWhileMoving(direction); } diff --git a/src/data/object_events/movement_action_func_tables.h b/src/data/object_events/movement_action_func_tables.h index a605b3f0b2..dda5ff3991 100755 --- a/src/data/object_events/movement_action_func_tables.h +++ b/src/data/object_events/movement_action_func_tables.h @@ -266,6 +266,11 @@ u8 MovementAction_FlyUp_Step1(struct ObjectEvent *, struct Sprite *); u8 MovementAction_Fly_Finish(struct ObjectEvent *, struct Sprite *); u8 MovementAction_FlyDown_Step0(struct ObjectEvent *, struct Sprite *); u8 MovementAction_FlyDown_Step1(struct ObjectEvent *, struct Sprite *); +u8 MovementActionFunc_RunSlowDown_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite); +u8 MovementActionFunc_RunSlowUp_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite); +u8 MovementActionFunc_RunSlowLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite); +u8 MovementActionFunc_RunSlowRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite); +u8 MovementActionFunc_RunSlow_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite); u8 (*const gMovementActionFuncs_FaceDown[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_FaceUp[])(struct ObjectEvent *, struct Sprite *); @@ -429,6 +434,10 @@ u8 (*const gMovementActionFuncs_FlyUp[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_FlyDown[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_EmoteX[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_EmoteDoubleExclMark[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_RunDownSlow[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_RunUpSlow[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_RunLeftSlow[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_RunRightSlow[])(struct ObjectEvent *, struct Sprite *); u8 (*const *const gMovementActionFuncs[])(struct ObjectEvent *, struct Sprite *) = { [MOVEMENT_ACTION_FACE_DOWN] = gMovementActionFuncs_FaceDown, @@ -593,6 +602,10 @@ u8 (*const *const gMovementActionFuncs[])(struct ObjectEvent *, struct Sprite *) [MOVEMENT_ACTION_EMOTE_DOUBLE_EXCL_MARK] = gMovementActionFuncs_EmoteDoubleExclMark, [MOVEMENT_ACTION_EXIT_POKEBALL] = gMovementActionFuncs_ExitPokeball, [MOVEMENT_ACTION_ENTER_POKEBALL] = gMovementActionFuncs_EnterPokeball, + [MOVEMENT_ACTION_RUN_DOWN_SLOW] = gMovementActionFuncs_RunDownSlow, + [MOVEMENT_ACTION_RUN_UP_SLOW] = gMovementActionFuncs_RunUpSlow, + [MOVEMENT_ACTION_RUN_LEFT_SLOW] = gMovementActionFuncs_RunLeftSlow, + [MOVEMENT_ACTION_RUN_RIGHT_SLOW] = gMovementActionFuncs_RunRightSlow, }; u8 (*const gMovementActionFuncs_FaceDown[])(struct ObjectEvent *, struct Sprite *) = { @@ -1554,3 +1567,27 @@ u8 (*const gMovementActionFuncs_EmoteDoubleExclMark[])(struct ObjectEvent *, str MovementAction_EmoteDoubleExclamationMark_Step0, MovementAction_Finish, }; + +u8 (*const gMovementActionFuncs_RunDownSlow[])(struct ObjectEvent *, struct Sprite *) = { + MovementActionFunc_RunSlowDown_Step0, + MovementActionFunc_RunSlow_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_RunUpSlow[])(struct ObjectEvent *, struct Sprite *) = { + MovementActionFunc_RunSlowUp_Step0, + MovementActionFunc_RunSlow_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_RunLeftSlow[])(struct ObjectEvent *, struct Sprite *) = { + MovementActionFunc_RunSlowLeft_Step0, + MovementActionFunc_RunSlow_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_RunRightSlow[])(struct ObjectEvent *, struct Sprite *) = { + MovementActionFunc_RunSlowRight_Step0, + MovementActionFunc_RunSlow_Step1, + MovementAction_PauseSpriteAnim, +}; diff --git a/src/event_object_movement.c b/src/event_object_movement.c index ef09ea93f3..7f913cde28 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -49,6 +49,7 @@ #include "constants/region_map_sections.h" #include "constants/songs.h" #include "constants/species.h" +#include "constants/metatile_behaviors.h" #include "constants/trainer_types.h" #include "constants/union_room.h" #include "constants/weather.h" @@ -158,7 +159,6 @@ static void ApplyLevitateMovement(u8); static bool8 MovementType_Disguise_Callback(struct ObjectEvent *, struct Sprite *); static bool8 MovementType_Buried_Callback(struct ObjectEvent *, struct Sprite *); static void CreateReflectionEffectSprites(void); -static u8 GetObjectEventIdByLocalId(u8); static u8 GetObjectEventIdByLocalIdAndMapInternal(u8, u8, u8); static bool8 GetAvailableObjectEventId(u16, u8, u8, u8 *); static void SetObjectEventDynamicGraphicsId(struct ObjectEvent *); @@ -208,6 +208,8 @@ static void CopyObjectGraphicsInfoToSpriteTemplate_WithMovementType(u16 graphics static const struct SpriteFrameImage sPicTable_PechaBerryTree[]; +static void StartSlowRunningAnim(struct ObjectEvent *objectEvent, struct Sprite *sprite, u8 direction); + const u8 gReflectionEffectPaletteMap[16] = { [PALSLOT_PLAYER] = PALSLOT_PLAYER_REFLECTION, [PALSLOT_PLAYER_REFLECTION] = PALSLOT_PLAYER_REFLECTION, @@ -745,10 +747,10 @@ static const u8 sFaceDirectionAnimNums[] = { [DIR_NORTH] = ANIM_STD_FACE_NORTH, [DIR_WEST] = ANIM_STD_FACE_WEST, [DIR_EAST] = ANIM_STD_FACE_EAST, - [DIR_SOUTHWEST] = ANIM_STD_FACE_SOUTH, - [DIR_SOUTHEAST] = ANIM_STD_FACE_SOUTH, - [DIR_NORTHWEST] = ANIM_STD_FACE_NORTH, - [DIR_NORTHEAST] = ANIM_STD_FACE_NORTH, + [DIR_SOUTHWEST] = ANIM_STD_FACE_WEST, + [DIR_SOUTHEAST] = ANIM_STD_FACE_EAST, + [DIR_NORTHWEST] = ANIM_STD_FACE_WEST, + [DIR_NORTHEAST] = ANIM_STD_FACE_EAST, }; static const u8 sMoveDirectionAnimNums[] = { [DIR_NONE] = ANIM_STD_GO_SOUTH, @@ -756,10 +758,10 @@ static const u8 sMoveDirectionAnimNums[] = { [DIR_NORTH] = ANIM_STD_GO_NORTH, [DIR_WEST] = ANIM_STD_GO_WEST, [DIR_EAST] = ANIM_STD_GO_EAST, - [DIR_SOUTHWEST] = ANIM_STD_GO_SOUTH, - [DIR_SOUTHEAST] = ANIM_STD_GO_SOUTH, - [DIR_NORTHWEST] = ANIM_STD_GO_NORTH, - [DIR_NORTHEAST] = ANIM_STD_GO_NORTH, + [DIR_SOUTHWEST] = ANIM_STD_GO_WEST, + [DIR_SOUTHEAST] = ANIM_STD_GO_EAST, + [DIR_NORTHWEST] = ANIM_STD_GO_WEST, + [DIR_NORTHEAST] = ANIM_STD_GO_EAST, }; static const u8 sMoveDirectionFastAnimNums[] = { [DIR_NONE] = ANIM_STD_GO_FAST_SOUTH, @@ -767,10 +769,10 @@ static const u8 sMoveDirectionFastAnimNums[] = { [DIR_NORTH] = ANIM_STD_GO_FAST_NORTH, [DIR_WEST] = ANIM_STD_GO_FAST_WEST, [DIR_EAST] = ANIM_STD_GO_FAST_EAST, - [DIR_SOUTHWEST] = ANIM_STD_GO_FAST_SOUTH, - [DIR_SOUTHEAST] = ANIM_STD_GO_FAST_SOUTH, - [DIR_NORTHWEST] = ANIM_STD_GO_FAST_NORTH, - [DIR_NORTHEAST] = ANIM_STD_GO_FAST_NORTH, + [DIR_SOUTHWEST] = ANIM_STD_GO_FAST_WEST, + [DIR_SOUTHEAST] = ANIM_STD_GO_FAST_EAST, + [DIR_NORTHWEST] = ANIM_STD_GO_FAST_WEST, + [DIR_NORTHEAST] = ANIM_STD_GO_FAST_EAST, }; static const u8 sMoveDirectionFasterAnimNums[] = { [DIR_NONE] = ANIM_STD_GO_FASTER_SOUTH, @@ -778,10 +780,10 @@ static const u8 sMoveDirectionFasterAnimNums[] = { [DIR_NORTH] = ANIM_STD_GO_FASTER_NORTH, [DIR_WEST] = ANIM_STD_GO_FASTER_WEST, [DIR_EAST] = ANIM_STD_GO_FASTER_EAST, - [DIR_SOUTHWEST] = ANIM_STD_GO_FASTER_SOUTH, - [DIR_SOUTHEAST] = ANIM_STD_GO_FASTER_SOUTH, - [DIR_NORTHWEST] = ANIM_STD_GO_FASTER_NORTH, - [DIR_NORTHEAST] = ANIM_STD_GO_FASTER_NORTH, + [DIR_SOUTHWEST] = ANIM_STD_GO_FASTER_WEST, + [DIR_SOUTHEAST] = ANIM_STD_GO_FASTER_EAST, + [DIR_NORTHWEST] = ANIM_STD_GO_FASTER_WEST, + [DIR_NORTHEAST] = ANIM_STD_GO_FASTER_EAST, }; static const u8 sMoveDirectionFastestAnimNums[] = { [DIR_NONE] = ANIM_STD_GO_FASTEST_SOUTH, @@ -789,10 +791,10 @@ static const u8 sMoveDirectionFastestAnimNums[] = { [DIR_NORTH] = ANIM_STD_GO_FASTEST_NORTH, [DIR_WEST] = ANIM_STD_GO_FASTEST_WEST, [DIR_EAST] = ANIM_STD_GO_FASTEST_EAST, - [DIR_SOUTHWEST] = ANIM_STD_GO_FASTEST_SOUTH, - [DIR_SOUTHEAST] = ANIM_STD_GO_FASTEST_SOUTH, - [DIR_NORTHWEST] = ANIM_STD_GO_FASTEST_NORTH, - [DIR_NORTHEAST] = ANIM_STD_GO_FASTEST_NORTH, + [DIR_SOUTHWEST] = ANIM_STD_GO_FASTEST_WEST, + [DIR_SOUTHEAST] = ANIM_STD_GO_FASTEST_EAST, + [DIR_NORTHWEST] = ANIM_STD_GO_FASTEST_WEST, + [DIR_NORTHEAST] = ANIM_STD_GO_FASTEST_EAST, }; static const u8 sJumpSpecialDirectionAnimNums[] = { // used for jumping onto surf mon [DIR_NONE] = ANIM_GET_ON_OFF_POKEMON_SOUTH, @@ -811,10 +813,10 @@ static const u8 sAcroWheelieDirectionAnimNums[] = { [DIR_NORTH] = ANIM_BUNNY_HOP_BACK_WHEEL_NORTH, [DIR_WEST] = ANIM_BUNNY_HOP_BACK_WHEEL_WEST, [DIR_EAST] = ANIM_BUNNY_HOP_BACK_WHEEL_EAST, - [DIR_SOUTHWEST] = ANIM_BUNNY_HOP_BACK_WHEEL_SOUTH, - [DIR_SOUTHEAST] = ANIM_BUNNY_HOP_BACK_WHEEL_SOUTH, - [DIR_NORTHWEST] = ANIM_BUNNY_HOP_BACK_WHEEL_NORTH, - [DIR_NORTHEAST] = ANIM_BUNNY_HOP_BACK_WHEEL_NORTH, + [DIR_SOUTHWEST] = ANIM_BUNNY_HOP_BACK_WHEEL_WEST, + [DIR_SOUTHEAST] = ANIM_BUNNY_HOP_BACK_WHEEL_EAST, + [DIR_NORTHWEST] = ANIM_BUNNY_HOP_BACK_WHEEL_WEST, + [DIR_NORTHEAST] = ANIM_BUNNY_HOP_BACK_WHEEL_EAST, }; static const u8 sAcroUnusedDirectionAnimNums[] = { [DIR_NONE] = ANIM_BUNNY_HOP_FRONT_WHEEL_SOUTH, @@ -833,10 +835,10 @@ static const u8 sAcroEndWheelieDirectionAnimNums[] = { [DIR_NORTH] = ANIM_STANDING_WHEELIE_BACK_WHEEL_NORTH, [DIR_WEST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_WEST, [DIR_EAST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_EAST, - [DIR_SOUTHWEST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_SOUTH, - [DIR_SOUTHEAST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_SOUTH, - [DIR_NORTHWEST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_NORTH, - [DIR_NORTHEAST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_NORTH, + [DIR_SOUTHWEST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_WEST, + [DIR_SOUTHEAST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_EAST, + [DIR_NORTHWEST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_WEST, + [DIR_NORTHEAST] = ANIM_STANDING_WHEELIE_BACK_WHEEL_EAST, }; static const u8 sAcroUnusedActionDirectionAnimNums[] = { [DIR_NONE] = ANIM_STANDING_WHEELIE_FRONT_WHEEL_SOUTH, @@ -855,10 +857,10 @@ static const u8 sAcroWheeliePedalDirectionAnimNums[] = { [DIR_NORTH] = ANIM_MOVING_WHEELIE_NORTH, [DIR_WEST] = ANIM_MOVING_WHEELIE_WEST, [DIR_EAST] = ANIM_MOVING_WHEELIE_EAST, - [DIR_SOUTHWEST] = ANIM_MOVING_WHEELIE_SOUTH, - [DIR_SOUTHEAST] = ANIM_MOVING_WHEELIE_SOUTH, - [DIR_NORTHWEST] = ANIM_MOVING_WHEELIE_NORTH, - [DIR_NORTHEAST] = ANIM_MOVING_WHEELIE_NORTH, + [DIR_SOUTHWEST] = ANIM_MOVING_WHEELIE_WEST, + [DIR_SOUTHEAST] = ANIM_MOVING_WHEELIE_EAST, + [DIR_NORTHWEST] = ANIM_MOVING_WHEELIE_WEST, + [DIR_NORTHEAST] = ANIM_MOVING_WHEELIE_EAST, }; static const u8 sFishingDirectionAnimNums[] = { [DIR_NONE] = ANIM_TAKE_OUT_ROD_SOUTH, @@ -899,10 +901,10 @@ static const u8 sRunningDirectionAnimNums[] = { [DIR_NORTH] = ANIM_RUN_NORTH, [DIR_WEST] = ANIM_RUN_WEST, [DIR_EAST] = ANIM_RUN_EAST, - [DIR_SOUTHWEST] = ANIM_RUN_SOUTH, - [DIR_SOUTHEAST] = ANIM_RUN_SOUTH, - [DIR_NORTHWEST] = ANIM_RUN_NORTH, - [DIR_NORTHEAST] = ANIM_RUN_NORTH, + [DIR_SOUTHWEST] = ANIM_RUN_WEST, + [DIR_SOUTHEAST] = ANIM_RUN_EAST, + [DIR_NORTHWEST] = ANIM_RUN_WEST, + [DIR_NORTHEAST] = ANIM_RUN_EAST, }; const u8 gTrainerFacingDirectionMovementTypes[] = { @@ -940,64 +942,72 @@ static const struct Coords16 sDirectionToVectors[] = { {-1, 1}, { 1, 1}, {-1, -1}, - { 1, -1} + { 1, -1}, + {-2, 1}, + { 2, 1}, + {-2, -1}, + { 2, -1} }; const u8 gFaceDirectionMovementActions[] = { - MOVEMENT_ACTION_FACE_DOWN, - MOVEMENT_ACTION_FACE_DOWN, - MOVEMENT_ACTION_FACE_UP, - MOVEMENT_ACTION_FACE_LEFT, - MOVEMENT_ACTION_FACE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_FACE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_FACE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_FACE_UP, + [DIR_WEST] = MOVEMENT_ACTION_FACE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_FACE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_FACE_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_FACE_RIGHT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_FACE_LEFT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_FACE_RIGHT }; const u8 gWalkSlowMovementActions[] = { - MOVEMENT_ACTION_WALK_SLOW_DOWN, - MOVEMENT_ACTION_WALK_SLOW_DOWN, - MOVEMENT_ACTION_WALK_SLOW_UP, - MOVEMENT_ACTION_WALK_SLOW_LEFT, - MOVEMENT_ACTION_WALK_SLOW_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_WALK_SLOW_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_WALK_SLOW_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_WALK_SLOW_UP, + [DIR_WEST] = MOVEMENT_ACTION_WALK_SLOW_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_WALK_SLOW_RIGHT, }; const u8 gWalkNormalMovementActions[] = { - MOVEMENT_ACTION_WALK_NORMAL_DOWN, - MOVEMENT_ACTION_WALK_NORMAL_DOWN, - MOVEMENT_ACTION_WALK_NORMAL_UP, - MOVEMENT_ACTION_WALK_NORMAL_LEFT, - MOVEMENT_ACTION_WALK_NORMAL_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_WALK_NORMAL_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_WALK_NORMAL_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_WALK_NORMAL_UP, + [DIR_WEST] = MOVEMENT_ACTION_WALK_NORMAL_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_WALK_NORMAL_RIGHT, }; const u8 gWalkFastMovementActions[] = { - MOVEMENT_ACTION_WALK_FAST_DOWN, - MOVEMENT_ACTION_WALK_FAST_DOWN, - MOVEMENT_ACTION_WALK_FAST_UP, - MOVEMENT_ACTION_WALK_FAST_LEFT, - MOVEMENT_ACTION_WALK_FAST_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_WALK_FAST_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_WALK_FAST_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_WALK_FAST_UP, + [DIR_WEST] = MOVEMENT_ACTION_WALK_FAST_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_WALK_FAST_RIGHT, }; const u8 gRideWaterCurrentMovementActions[] = { - MOVEMENT_ACTION_RIDE_WATER_CURRENT_DOWN, - MOVEMENT_ACTION_RIDE_WATER_CURRENT_DOWN, - MOVEMENT_ACTION_RIDE_WATER_CURRENT_UP, - MOVEMENT_ACTION_RIDE_WATER_CURRENT_LEFT, - MOVEMENT_ACTION_RIDE_WATER_CURRENT_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_RIDE_WATER_CURRENT_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_RIDE_WATER_CURRENT_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_RIDE_WATER_CURRENT_UP, + [DIR_WEST] = MOVEMENT_ACTION_RIDE_WATER_CURRENT_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_RIDE_WATER_CURRENT_RIGHT, }; const u8 gWalkFasterMovementActions[] = { - MOVEMENT_ACTION_WALK_FASTER_DOWN, - MOVEMENT_ACTION_WALK_FASTER_DOWN, - MOVEMENT_ACTION_WALK_FASTER_UP, - MOVEMENT_ACTION_WALK_FASTER_LEFT, - MOVEMENT_ACTION_WALK_FASTER_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_WALK_FASTER_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_WALK_FASTER_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_WALK_FASTER_UP, + [DIR_WEST] = MOVEMENT_ACTION_WALK_FASTER_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_WALK_FASTER_RIGHT, }; const u8 gSlideMovementActions[] = { - MOVEMENT_ACTION_SLIDE_DOWN, - MOVEMENT_ACTION_SLIDE_DOWN, - MOVEMENT_ACTION_SLIDE_UP, - MOVEMENT_ACTION_SLIDE_LEFT, - MOVEMENT_ACTION_SLIDE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_SLIDE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_SLIDE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_SLIDE_UP, + [DIR_WEST] = MOVEMENT_ACTION_SLIDE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_SLIDE_RIGHT, }; const u8 gPlayerRunMovementActions[] = { - MOVEMENT_ACTION_PLAYER_RUN_DOWN, - MOVEMENT_ACTION_PLAYER_RUN_DOWN, - MOVEMENT_ACTION_PLAYER_RUN_UP, - MOVEMENT_ACTION_PLAYER_RUN_LEFT, - MOVEMENT_ACTION_PLAYER_RUN_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_PLAYER_RUN_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_PLAYER_RUN_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_PLAYER_RUN_UP, + [DIR_WEST] = MOVEMENT_ACTION_PLAYER_RUN_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_PLAYER_RUN_RIGHT, }; const u8 gJump2MovementActions[] = { MOVEMENT_ACTION_JUMP_2_DOWN, @@ -1035,102 +1045,170 @@ const u8 gJumpSpecialMovementActions[] = { MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, }; const u8 gWalkInPlaceSlowMovementActions[] = { - MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_DOWN, - MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_DOWN, - MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_UP, - MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_LEFT, - MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_UP, + [DIR_WEST] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_LEFT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_RIGHT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_RIGHT }; const u8 gWalkInPlaceNormalMovementActions[] = { - MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_DOWN, - MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_DOWN, - MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_UP, - MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_LEFT, - MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_UP, + [DIR_WEST] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_LEFT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_RIGHT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_RIGHT }; const u8 gWalkInPlaceFastMovementActions[] = { - MOVEMENT_ACTION_WALK_IN_PLACE_FAST_DOWN, - MOVEMENT_ACTION_WALK_IN_PLACE_FAST_DOWN, - MOVEMENT_ACTION_WALK_IN_PLACE_FAST_UP, - MOVEMENT_ACTION_WALK_IN_PLACE_FAST_LEFT, - MOVEMENT_ACTION_WALK_IN_PLACE_FAST_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_UP, + [DIR_WEST] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_LEFT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_RIGHT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_WALK_IN_PLACE_FAST_RIGHT }; const u8 gWalkInPlaceFasterMovementActions[] = { - MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_DOWN, - MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_DOWN, - MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_UP, - MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_LEFT, - MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_UP, + [DIR_WEST] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_LEFT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_RIGHT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_RIGHT }; const u8 gAcroWheelieFaceDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_WHEELIE_FACE_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_FACE_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_FACE_UP, - MOVEMENT_ACTION_ACRO_WHEELIE_FACE_LEFT, - MOVEMENT_ACTION_ACRO_WHEELIE_FACE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_LEFT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_RIGHT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_FACE_RIGHT }; const u8 gAcroPopWheelieFaceDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_POP_WHEELIE_DOWN, - MOVEMENT_ACTION_ACRO_POP_WHEELIE_DOWN, - MOVEMENT_ACTION_ACRO_POP_WHEELIE_UP, - MOVEMENT_ACTION_ACRO_POP_WHEELIE_LEFT, - MOVEMENT_ACTION_ACRO_POP_WHEELIE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_RIGHT, }; const u8 gAcroEndWheelieFaceDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_DOWN, - MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_DOWN, - MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_UP, - MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_LEFT, - MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_RIGHT, }; const u8 gAcroWheelieHopFaceDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_UP, - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_LEFT, - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_RIGHT, }; const u8 gAcroWheelieHopDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_UP, - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_LEFT, - MOVEMENT_ACTION_ACRO_WHEELIE_HOP_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_HOP_RIGHT, }; const u8 gAcroWheelieJumpDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_UP, - MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_LEFT, - MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_RIGHT, }; const u8 gAcroWheelieInPlaceDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_UP, - MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_LEFT, - MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_RIGHT, }; const u8 gAcroPopWheelieMoveDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_DOWN, - MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_DOWN, - MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_UP, - MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_LEFT, - MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_RIGHT, }; const u8 gAcroWheelieMoveDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_DOWN, - MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_UP, - MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_LEFT, - MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_RIGHT, }; const u8 gAcroEndWheelieMoveDirectionMovementActions[] = { - MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_DOWN, - MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_DOWN, - MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_UP, - MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_LEFT, - MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_RIGHT, + [DIR_NONE] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_DOWN, + [DIR_SOUTH] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_DOWN, + [DIR_NORTH] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_UP, + [DIR_WEST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_LEFT, + [DIR_EAST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_RIGHT, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_LEFT, + [DIR_NORTHWEST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_LEFT, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_RIGHT, + [DIR_NORTHEAST] = MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_RIGHT, +}; +// run slow +const u8 gRunSlowMovementActions[] = { + [DIR_NONE] = MOVEMENT_ACTION_RUN_DOWN_SLOW, + [DIR_SOUTH] = MOVEMENT_ACTION_RUN_DOWN_SLOW, + [DIR_NORTH] = MOVEMENT_ACTION_RUN_UP_SLOW, + [DIR_WEST] = MOVEMENT_ACTION_RUN_LEFT_SLOW, + [DIR_EAST] = MOVEMENT_ACTION_RUN_RIGHT_SLOW, + [DIR_SOUTHWEST] = MOVEMENT_ACTION_RUN_LEFT_SLOW, + [DIR_SOUTHEAST] = MOVEMENT_ACTION_RUN_RIGHT_SLOW, + [DIR_NORTHWEST] = MOVEMENT_ACTION_RUN_LEFT_SLOW, + [DIR_NORTHEAST] = MOVEMENT_ACTION_RUN_RIGHT_SLOW, }; static const u8 sOppositeDirections[] = { @@ -1299,7 +1377,7 @@ static u8 GetObjectEventIdByLocalIdAndMapInternal(u8 localId, u8 mapNum, u8 mapG return OBJECT_EVENTS_COUNT; } -static u8 GetObjectEventIdByLocalId(u8 localId) +u8 GetObjectEventIdByLocalId(u8 localId) { u8 i; for (i = 0; i < OBJECT_EVENTS_COUNT; i++) @@ -2148,7 +2226,7 @@ void RemoveFollowingPokemon(void) } // Determine whether follower *should* be visible -static bool32 IsFollowerVisible(void) +bool32 IsFollowerVisible(void) { return !(TestPlayerAvatarFlags(FOLLOWER_INVISIBLE_FLAGS) || MetatileBehavior_IsSurfableWaterOrUnderwater(gObjectEvents[gPlayerAvatar.objectEventId].previousMetatileBehavior) @@ -5332,16 +5410,11 @@ bool8 MovementType_FollowPlayer_Active(struct ObjectEvent *objectEvent, struct S bool8 MovementType_FollowPlayer_Moving(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - #ifdef MB_SIDEWAYS_STAIRS_RIGHT_SIDE // Copied from ObjectEventExecSingleMovementAction if (gMovementActionFuncs[objectEvent->movementActionId][sprite->sActionFuncId](objectEvent, sprite)) { objectEvent->movementActionId = MOVEMENT_ACTION_NONE; sprite->sActionFuncId = 0; - #else - if (ObjectEventExecSingleMovementAction(objectEvent, sprite)) - { - #endif objectEvent->singleMovementActive = FALSE; if (sprite->sTypeFuncId) // restore nonzero state sprite->sTypeFuncId = 1; @@ -5395,10 +5468,8 @@ bool8 FollowablePlayerMovement_Step(struct ObjectEvent *objectEvent, struct Spri s16 y; s16 targetX; s16 targetY; - #ifdef MB_SIDEWAYS_STAIRS_RIGHT_SIDE u32 playerAction = gObjectEvents[gPlayerAvatar.objectEventId].movementActionId; - #endif - + targetX = gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.x; targetY = gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.y; x = gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x; @@ -5437,12 +5508,12 @@ bool8 FollowablePlayerMovement_Step(struct ObjectEvent *objectEvent, struct Spri // Follow player direction = GetDirectionToFace(x, y, targetX, targetY); MoveCoords(direction, &x, &y); - #ifdef MB_SIDEWAYS_STAIRS_RIGHT_SIDE // https://github.com/ghoulslash/pokeemerald/tree/sideways_stairs GetCollisionAtCoords(objectEvent, x, y, direction); // Sets directionOverwrite for stairs if (GetLedgeJumpDirection(x, y, direction) != DIR_NONE) { // InitJumpRegular will set the proper speed ObjectEventSetSingleMovement(objectEvent, sprite, GetJump2MovementAction(direction)); + } else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_DASH)) { // Set follow speed according to player's speed @@ -5469,7 +5540,6 @@ bool8 FollowablePlayerMovement_Step(struct ObjectEvent *objectEvent, struct Spri } } sprite->sActionFuncId = 0; - #else if (GetLedgeJumpDirection(x, y, direction) != DIR_NONE) { // InitJumpRegular will set the proper speed @@ -5491,7 +5561,6 @@ bool8 FollowablePlayerMovement_Step(struct ObjectEvent *objectEvent, struct Spri if (OW_FOLLOWERS_BOBBING == TRUE) sprite->y2 = -1; } - #endif objectEvent->singleMovementActive = TRUE; sprite->sTypeFuncId = 2; return TRUE; @@ -5941,7 +6010,7 @@ u8 GetTrainerFacingDirectionMovementType(u8 direction) return gTrainerFacingDirectionMovementTypes[direction]; } -static u8 GetCollisionInDirection(struct ObjectEvent *objectEvent, u8 direction) +u8 GetCollisionInDirection(struct ObjectEvent *objectEvent, u8 direction) { s16 x = objectEvent->currentCoords.x; s16 y = objectEvent->currentCoords.y; @@ -5949,18 +6018,56 @@ static u8 GetCollisionInDirection(struct ObjectEvent *objectEvent, u8 direction) return GetCollisionAtCoords(objectEvent, x, y, direction); } -u8 GetCollisionAtCoords(struct ObjectEvent *objectEvent, s16 x, s16 y, u32 dir) +u8 GetSidewaysStairsCollision(struct ObjectEvent *objectEvent, u8 dir, u8 currentBehavior, u8 nextBehavior, u8 collision) { - u8 direction = dir; - -#if OW_FLAG_NO_COLLISION != 0 - if (FlagGet(OW_FLAG_NO_COLLISION)) - return COLLISION_NONE; -#endif + if ((dir == DIR_SOUTH || dir == DIR_NORTH) && collision != COLLISION_NONE) + return collision; + + // cant descend stairs into water + if (MetatileBehavior_IsSurfableFishableWater(nextBehavior)) + return collision; + + if (MetatileBehavior_IsSidewaysStairsLeftSide(nextBehavior)) + { + //moving ONTO left side stair + if (dir == DIR_WEST && currentBehavior != nextBehavior) + return collision; //moving onto top part of left-stair going left, so no diagonal + else + return COLLISION_SIDEWAYS_STAIRS_TO_LEFT; // move diagonally + } + else if (MetatileBehavior_IsSidewaysStairsRightSide(nextBehavior)) + { + //moving ONTO right side stair + if (dir == DIR_EAST && currentBehavior != nextBehavior) + return collision; //moving onto top part of right-stair going right, so no diagonal + else + return COLLISION_SIDEWAYS_STAIRS_TO_RIGHT; + } + else if (MetatileBehavior_IsSidewaysStairsLeftSideAny(currentBehavior)) + { + //moving OFF of any left side stair + if (dir == DIR_WEST && nextBehavior != currentBehavior) + return COLLISION_SIDEWAYS_STAIRS_TO_LEFT; //moving off of left stairs onto non-stair -> move diagonal + else + return collision; //moving off of left side stair to east -> move east + } + else if (MetatileBehavior_IsSidewaysStairsRightSideAny(currentBehavior)) + { + //moving OFF of any right side stair + if (dir == DIR_EAST && nextBehavior != currentBehavior) + return COLLISION_SIDEWAYS_STAIRS_TO_RIGHT; //moving off right stair onto non-stair -> move diagonal + else + return collision; + } + + return collision; +} +static u8 GetVanillaCollision(struct ObjectEvent *objectEvent, s16 x, s16 y, u8 direction) +{ if (IsCoordOutsideObjectEventMovementRange(objectEvent, x, y)) return COLLISION_OUTSIDE_RANGE; - else if (MapGridGetCollisionAt(x, y) || GetMapBorderIdAt(x, y) == CONNECTION_INVALID || IsMetatileDirectionallyImpassable(objectEvent, x, y, direction)) + else if (MapGridGetCollisionAt(x, y) || GetMapBorderIdAt(x, y) == -1 || IsMetatileDirectionallyImpassable(objectEvent, x, y, direction)) return COLLISION_IMPASSABLE; else if (objectEvent->trackedByCamera && !CanCameraMoveInDirection(direction)) return COLLISION_IMPASSABLE; @@ -5968,9 +6075,94 @@ u8 GetCollisionAtCoords(struct ObjectEvent *objectEvent, s16 x, s16 y, u32 dir) return COLLISION_ELEVATION_MISMATCH; else if (DoesObjectCollideWithObjectAt(objectEvent, x, y)) return COLLISION_OBJECT_EVENT; + return COLLISION_NONE; } +static bool8 ObjectEventOnLeftSideStair(struct ObjectEvent *objectEvent, s16 x, s16 y, u8 direction) +{ + switch (direction) + { + case DIR_EAST: + MoveCoords(DIR_NORTH, &x, &y); + return DoesObjectCollideWithObjectAt(objectEvent, x, y); + case DIR_WEST: + MoveCoords(DIR_SOUTH, &x, &y); + return DoesObjectCollideWithObjectAt(objectEvent, x, y); + default: + return FALSE; //north/south taken care of in GetVanillaCollision + } +} + +static bool8 ObjectEventOnRightSideStair(struct ObjectEvent *objectEvent, s16 x, s16 y, u8 direction) +{ + switch (direction) + { + case DIR_EAST: + MoveCoords(DIR_SOUTH, &x, &y); + return DoesObjectCollideWithObjectAt(objectEvent, x, y); + case DIR_WEST: + MoveCoords(DIR_NORTH, &x, &y); + return DoesObjectCollideWithObjectAt(objectEvent, x, y); + default: + return FALSE; //north/south taken care of in GetVanillaCollision + } +} + +u8 GetCollisionAtCoords(struct ObjectEvent *objectEvent, s16 x, s16 y, u32 dir) +{ + u8 currentBehavior = MapGridGetMetatileBehaviorAt(objectEvent->currentCoords.x, objectEvent->currentCoords.y); + u8 nextBehavior = MapGridGetMetatileBehaviorAt(x, y); + u8 collision; + + #if OW_FLAG_NO_COLLISION != 0 + if (FlagGet(OW_FLAG_NO_COLLISION)) + return COLLISION_NONE; + #endif + + objectEvent->directionOverwrite = DIR_NONE; + + //sideways stairs checks + if (MetatileBehavior_IsSidewaysStairsLeftSideTop(nextBehavior) && dir == DIR_EAST) + return COLLISION_IMPASSABLE; //moving onto left-side top edge east from regular ground -> nope + else if (MetatileBehavior_IsSidewaysStairsRightSideTop(nextBehavior) && dir == DIR_WEST) + return COLLISION_IMPASSABLE; //moving onto left-side top edge east from regular ground -> nope + else if (MetatileBehavior_IsSidewaysStairsRightSideBottom(nextBehavior) && (dir == DIR_EAST || dir == DIR_SOUTH)) + return COLLISION_IMPASSABLE; //moving into right-side bottom edge from regular ground -> nah + else if (MetatileBehavior_IsSidewaysStairsLeftSideBottom(nextBehavior) && (dir == DIR_WEST || dir == DIR_SOUTH)) + return COLLISION_IMPASSABLE; //moving onto left-side bottom edge from regular ground -> nah + else if ((MetatileBehavior_IsSidewaysStairsLeftSideTop(currentBehavior) || MetatileBehavior_IsSidewaysStairsRightSideTop(currentBehavior)) + && dir == DIR_NORTH) + return COLLISION_IMPASSABLE; //trying to move north off of top-most tile onto same level doesn't work + else if (!(MetatileBehavior_IsSidewaysStairsLeftSideTop(currentBehavior) || MetatileBehavior_IsSidewaysStairsRightSideTop(currentBehavior)) + && dir == DIR_SOUTH && (MetatileBehavior_IsSidewaysStairsLeftSideTop(nextBehavior) || MetatileBehavior_IsSidewaysStairsRightSideTop(nextBehavior))) + return COLLISION_IMPASSABLE; //trying to move south onto top stair tile at same level from non-stair -> no + else if (!(MetatileBehavior_IsSidewaysStairsLeftSideBottom(currentBehavior) || MetatileBehavior_IsSidewaysStairsRightSideBottom(currentBehavior)) + && dir == DIR_NORTH && (MetatileBehavior_IsSidewaysStairsLeftSideBottom(nextBehavior) || MetatileBehavior_IsSidewaysStairsRightSideBottom(nextBehavior))) + return COLLISION_IMPASSABLE; //trying to move north onto top stair tile at same level from non-stair -> no + + // regular checks + collision = GetVanillaCollision(objectEvent, x, y, dir); + + //sideways stairs direction change checks + collision = GetSidewaysStairsCollision(objectEvent, dir, currentBehavior, nextBehavior, collision); + switch (collision) + { + case COLLISION_SIDEWAYS_STAIRS_TO_LEFT: + if (ObjectEventOnLeftSideStair(objectEvent, x, y, dir)) + return COLLISION_OBJECT_EVENT; + objectEvent->directionOverwrite = GetLeftSideStairsDirection(dir); + return COLLISION_NONE; + case COLLISION_SIDEWAYS_STAIRS_TO_RIGHT: + if (ObjectEventOnRightSideStair(objectEvent, x, y, dir)) + return COLLISION_OBJECT_EVENT; + objectEvent->directionOverwrite = GetRightSideStairsDirection(dir); + return COLLISION_NONE; + } + + return collision; +} + u8 GetCollisionFlagsAtCoords(struct ObjectEvent *objectEvent, s16 x, s16 y, u8 direction) { u8 flags = 0; @@ -6034,6 +6226,7 @@ static bool8 DoesObjectCollideWithObjectAt(struct ObjectEvent *objectEvent, s16 curObject = &gObjectEvents[i]; if (curObject->active && (curObject->movementType != MOVEMENT_TYPE_FOLLOW_PLAYER || objectEvent != &gObjectEvents[gPlayerAvatar.objectEventId]) && curObject != objectEvent) { + // check for collision if curObject is active, not the object in question, and not exempt from collisions if ((curObject->currentCoords.x == x && curObject->currentCoords.y == y) || (curObject->previousCoords.x == x && curObject->previousCoords.y == y)) { if (AreElevationsCompatible(objectEvent->currentElevation, curObject->currentElevation)) @@ -6170,10 +6363,35 @@ bool8 ObjectEventIsHeldMovementActive(struct ObjectEvent *objectEvent) return FALSE; } +static u8 TryUpdateMovementActionOnStairs(struct ObjectEvent *objectEvent, u8 movementActionId) +{ + if (objectEvent->isPlayer || objectEvent->localId == OBJ_EVENT_ID_FOLLOWER) + return movementActionId; // handled separately + + if (!ObjectMovingOnRockStairs(objectEvent, objectEvent->movementDirection)) + return movementActionId; + + switch (movementActionId) + { + case MOVEMENT_ACTION_WALK_NORMAL_DOWN: + return MOVEMENT_ACTION_WALK_SLOW_DOWN; + case MOVEMENT_ACTION_WALK_NORMAL_UP: + return MOVEMENT_ACTION_WALK_SLOW_UP; + case MOVEMENT_ACTION_WALK_NORMAL_LEFT: + return MOVEMENT_ACTION_WALK_SLOW_LEFT; + case MOVEMENT_ACTION_WALK_NORMAL_RIGHT: + return MOVEMENT_ACTION_WALK_SLOW_RIGHT; + default: + return movementActionId; + } +} + bool8 ObjectEventSetHeldMovement(struct ObjectEvent *objectEvent, u8 movementActionId) { if (ObjectEventIsMovementOverridden(objectEvent)) return TRUE; + + movementActionId = TryUpdateMovementActionOnStairs(objectEvent, movementActionId); UnfreezeObjectEvent(objectEvent); objectEvent->movementActionId = movementActionId; @@ -6185,6 +6403,7 @@ bool8 ObjectEventSetHeldMovement(struct ObjectEvent *objectEvent, u8 movementAct void ObjectEventForceSetHeldMovement(struct ObjectEvent *objectEvent, u8 movementActionId) { + movementActionId = TryUpdateMovementActionOnStairs(objectEvent, movementActionId); ObjectEventClearHeldMovementIfActive(objectEvent); ObjectEventSetHeldMovement(objectEvent, movementActionId); } @@ -6224,7 +6443,7 @@ u8 ObjectEventClearHeldMovementIfFinished(struct ObjectEvent *objectEvent) u8 ObjectEventGetHeldMovementActionId(struct ObjectEvent *objectEvent) { if (objectEvent->heldMovementActive) - return objectEvent->movementActionId; + return TryUpdateMovementActionOnStairs(objectEvent, objectEvent->movementActionId); return MOVEMENT_ACTION_NONE; } @@ -6253,12 +6472,13 @@ u8 name(u32 idx)\ u8 animIds[sizeof(table)];\ direction = idx;\ memcpy(animIds, (table), sizeof(table));\ - if (direction > DIR_EAST) direction = 0;\ + if (direction > sizeof(table)) direction = 0;\ return animIds[direction];\ } dirn_to_anim(GetFaceDirectionMovementAction, gFaceDirectionMovementActions); dirn_to_anim(GetWalkSlowMovementAction, gWalkSlowMovementActions); +dirn_to_anim(GetPlayerRunSlowMovementAction, gRunSlowMovementActions); dirn_to_anim(GetWalkNormalMovementAction, gWalkNormalMovementActions); dirn_to_anim(GetWalkFastMovementAction, gWalkFastMovementActions); dirn_to_anim(GetRideWaterCurrentMovementAction, gRideWaterCurrentMovementActions); @@ -6327,12 +6547,14 @@ static u32 GetCopyDirection(u8 copyInitDir, u32 playerInitDir, u32 playerMoveDir static void ObjectEventExecHeldMovementAction(struct ObjectEvent *objectEvent, struct Sprite *sprite) { + objectEvent->movementActionId = TryUpdateMovementActionOnStairs(objectEvent, objectEvent->movementActionId); if (gMovementActionFuncs[objectEvent->movementActionId][sprite->sActionFuncId](objectEvent, sprite)) objectEvent->heldMovementFinished = TRUE; } static bool8 ObjectEventExecSingleMovementAction(struct ObjectEvent *objectEvent, struct Sprite *sprite) { + objectEvent->movementActionId = TryUpdateMovementActionOnStairs(objectEvent, objectEvent->movementActionId); if (gMovementActionFuncs[objectEvent->movementActionId][sprite->sActionFuncId](objectEvent, sprite)) { objectEvent->movementActionId = MOVEMENT_ACTION_NONE; @@ -6344,7 +6566,7 @@ static bool8 ObjectEventExecSingleMovementAction(struct ObjectEvent *objectEvent static void ObjectEventSetSingleMovement(struct ObjectEvent *objectEvent, struct Sprite *sprite, u8 animId) { - objectEvent->movementActionId = animId; + objectEvent->movementActionId = TryUpdateMovementActionOnStairs(objectEvent, animId); sprite->sActionFuncId = 0; } @@ -6560,7 +6782,10 @@ bool8 MovementAction_WalkSlowUp_Step1(struct ObjectEvent *objectEvent, struct Sp bool8 MovementAction_WalkSlowLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitWalkSlow(objectEvent, sprite, DIR_WEST); + if (objectEvent->directionOverwrite) + InitWalkSlow(objectEvent, sprite, objectEvent->directionOverwrite); + else + InitWalkSlow(objectEvent, sprite, DIR_WEST); return MovementAction_WalkSlowLeft_Step1(objectEvent, sprite); } @@ -6576,7 +6801,10 @@ bool8 MovementAction_WalkSlowLeft_Step1(struct ObjectEvent *objectEvent, struct bool8 MovementAction_WalkSlowRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitWalkSlow(objectEvent, sprite, DIR_EAST); + if (objectEvent->directionOverwrite) + InitWalkSlow(objectEvent, sprite, objectEvent->directionOverwrite); + else + InitWalkSlow(objectEvent, sprite, DIR_EAST); return MovementAction_WalkSlowRight_Step1(objectEvent, sprite); } @@ -6688,7 +6916,10 @@ bool8 MovementAction_WalkNormalUp_Step1(struct ObjectEvent *objectEvent, struct bool8 MovementAction_WalkNormalLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_NORMAL); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_NORMAL); + else + InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_NORMAL); return MovementAction_WalkNormalLeft_Step1(objectEvent, sprite); } @@ -6704,7 +6935,10 @@ bool8 MovementAction_WalkNormalLeft_Step1(struct ObjectEvent *objectEvent, struc bool8 MovementAction_WalkNormalRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_NORMAL); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_NORMAL); + else + InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_NORMAL); return MovementAction_WalkNormalRight_Step1(objectEvent, sprite); } @@ -6982,7 +7216,10 @@ bool8 MovementAction_WalkFastUp_Step1(struct ObjectEvent *objectEvent, struct Sp bool8 MovementAction_WalkFastLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_FAST_1); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_FAST_1); + else + InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_FAST_1); return MovementAction_WalkFastLeft_Step1(objectEvent, sprite); } @@ -6998,7 +7235,10 @@ bool8 MovementAction_WalkFastLeft_Step1(struct ObjectEvent *objectEvent, struct bool8 MovementAction_WalkFastRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_FAST_1); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_FAST_1); + else + InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_FAST_1); return MovementAction_WalkFastRight_Step1(objectEvent, sprite); } @@ -7332,13 +7572,19 @@ bool8 MovementAction_WalkInPlaceFasterUp_Step0(struct ObjectEvent *objectEvent, bool8 MovementAction_WalkInPlaceFasterLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMoveInPlace(objectEvent, sprite, DIR_WEST, GetMoveDirectionFasterAnimNum(DIR_WEST), 4); + if (objectEvent->directionOverwrite) + InitMoveInPlace(objectEvent, sprite, objectEvent->directionOverwrite, GetMoveDirectionFasterAnimNum(DIR_WEST), 4); + else + InitMoveInPlace(objectEvent, sprite, DIR_WEST, GetMoveDirectionFasterAnimNum(DIR_WEST), 4); return MovementAction_WalkInPlace_Step1(objectEvent, sprite); } bool8 MovementAction_WalkInPlaceFasterRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMoveInPlace(objectEvent, sprite, DIR_EAST, GetMoveDirectionFasterAnimNum(DIR_EAST), 4); + if (objectEvent->directionOverwrite) + InitMoveInPlace(objectEvent, sprite, objectEvent->directionOverwrite, GetMoveDirectionFasterAnimNum(DIR_EAST), 4); + else + InitMoveInPlace(objectEvent, sprite, DIR_EAST, GetMoveDirectionFasterAnimNum(DIR_EAST), 4); return MovementAction_WalkInPlace_Step1(objectEvent, sprite); } @@ -7376,7 +7622,10 @@ bool8 MovementAction_RideWaterCurrentUp_Step1(struct ObjectEvent *objectEvent, s bool8 MovementAction_RideWaterCurrentLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_FAST_2); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_FAST_2); + else + InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_FAST_2); return MovementAction_RideWaterCurrentLeft_Step1(objectEvent, sprite); } @@ -7392,7 +7641,10 @@ bool8 MovementAction_RideWaterCurrentLeft_Step1(struct ObjectEvent *objectEvent, bool8 MovementAction_RideWaterCurrentRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_FAST_2); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_FAST_2); + else + InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_FAST_2); return MovementAction_RideWaterCurrentRight_Step1(objectEvent, sprite); } @@ -7440,7 +7692,10 @@ bool8 MovementAction_WalkFasterUp_Step1(struct ObjectEvent *objectEvent, struct bool8 MovementAction_WalkFasterLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_FASTER); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_FASTER); + else + InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_FASTER); return MovementAction_WalkFasterLeft_Step1(objectEvent, sprite); } @@ -7456,7 +7711,10 @@ bool8 MovementAction_WalkFasterLeft_Step1(struct ObjectEvent *objectEvent, struc bool8 MovementAction_WalkFasterRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_FASTER); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_FASTER); + else + InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_FASTER); return MovementAction_WalkFasterRight_Step1(objectEvent, sprite); } @@ -7504,7 +7762,10 @@ bool8 MovementAction_SlideUp_Step1(struct ObjectEvent *objectEvent, struct Sprit bool8 MovementAction_SlideLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_FASTEST); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_FASTEST); + else + InitMovementNormal(objectEvent, sprite, DIR_WEST, MOVE_SPEED_FASTEST); return MovementAction_SlideLeft_Step1(objectEvent, sprite); } @@ -7520,7 +7781,10 @@ bool8 MovementAction_SlideLeft_Step1(struct ObjectEvent *objectEvent, struct Spr bool8 MovementAction_SlideRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_FASTEST); + if (objectEvent->directionOverwrite) + InitMovementNormal(objectEvent, sprite, objectEvent->directionOverwrite, MOVE_SPEED_FASTEST); + else + InitMovementNormal(objectEvent, sprite, DIR_EAST, MOVE_SPEED_FASTEST); return MovementAction_SlideRight_Step1(objectEvent, sprite); } @@ -7568,7 +7832,10 @@ bool8 MovementAction_PlayerRunUp_Step1(struct ObjectEvent *objectEvent, struct S bool8 MovementAction_PlayerRunLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - StartRunningAnim(objectEvent, sprite, DIR_WEST); + if (objectEvent->directionOverwrite) + StartRunningAnim(objectEvent, sprite, objectEvent->directionOverwrite); + else + StartRunningAnim(objectEvent, sprite, DIR_WEST); return MovementAction_PlayerRunLeft_Step1(objectEvent, sprite); } @@ -7584,7 +7851,10 @@ bool8 MovementAction_PlayerRunLeft_Step1(struct ObjectEvent *objectEvent, struct bool8 MovementAction_PlayerRunRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - StartRunningAnim(objectEvent, sprite, DIR_EAST); + if (objectEvent->directionOverwrite) + StartRunningAnim(objectEvent, sprite, objectEvent->directionOverwrite); + else + StartRunningAnim(objectEvent, sprite, DIR_EAST); return MovementAction_PlayerRunRight_Step1(objectEvent, sprite); } @@ -8471,7 +8741,10 @@ bool8 MovementAction_AcroWheelieHopUp_Step1(struct ObjectEvent *objectEvent, str bool8 MovementAction_AcroWheelieHopLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroWheelieJump(objectEvent, sprite, DIR_WEST, JUMP_DISTANCE_NORMAL, JUMP_TYPE_LOW); + if (objectEvent->directionOverwrite) + InitAcroWheelieJump(objectEvent, sprite, objectEvent->directionOverwrite, JUMP_DISTANCE_NORMAL, JUMP_TYPE_LOW); + else + InitAcroWheelieJump(objectEvent, sprite, DIR_WEST, JUMP_DISTANCE_NORMAL, JUMP_TYPE_LOW); return MovementAction_AcroWheelieHopLeft_Step1(objectEvent, sprite); } @@ -8488,7 +8761,10 @@ bool8 MovementAction_AcroWheelieHopLeft_Step1(struct ObjectEvent *objectEvent, s bool8 MovementAction_AcroWheelieHopRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroWheelieJump(objectEvent, sprite, DIR_EAST, JUMP_DISTANCE_NORMAL, JUMP_TYPE_LOW); + if (objectEvent->directionOverwrite) + InitAcroWheelieJump(objectEvent, sprite, objectEvent->directionOverwrite, JUMP_DISTANCE_NORMAL, JUMP_TYPE_LOW); + else + InitAcroWheelieJump(objectEvent, sprite, DIR_EAST, JUMP_DISTANCE_NORMAL, JUMP_TYPE_LOW); return MovementAction_AcroWheelieHopRight_Step1(objectEvent, sprite); } @@ -8539,7 +8815,10 @@ bool8 MovementAction_AcroWheelieJumpUp_Step1(struct ObjectEvent *objectEvent, st bool8 MovementAction_AcroWheelieJumpLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroWheelieJump(objectEvent, sprite, DIR_WEST, JUMP_DISTANCE_FAR, JUMP_TYPE_HIGH); + if (objectEvent->directionOverwrite) + InitAcroWheelieJump(objectEvent, sprite, objectEvent->directionOverwrite, JUMP_DISTANCE_FAR, JUMP_TYPE_HIGH); + else + InitAcroWheelieJump(objectEvent, sprite, DIR_WEST, JUMP_DISTANCE_FAR, JUMP_TYPE_HIGH); return MovementAction_AcroWheelieJumpLeft_Step1(objectEvent, sprite); } @@ -8556,7 +8835,10 @@ bool8 MovementAction_AcroWheelieJumpLeft_Step1(struct ObjectEvent *objectEvent, bool8 MovementAction_AcroWheelieJumpRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroWheelieJump(objectEvent, sprite, DIR_EAST, JUMP_DISTANCE_FAR, JUMP_TYPE_HIGH); + if (objectEvent->directionOverwrite) + InitAcroWheelieJump(objectEvent, sprite, objectEvent->directionOverwrite, JUMP_DISTANCE_FAR, JUMP_TYPE_HIGH); + else + InitAcroWheelieJump(objectEvent, sprite, DIR_EAST, JUMP_DISTANCE_FAR, JUMP_TYPE_HIGH); return MovementAction_AcroWheelieJumpRight_Step1(objectEvent, sprite); } @@ -8585,13 +8867,19 @@ bool8 MovementAction_AcroWheelieInPlaceUp_Step0(struct ObjectEvent *objectEvent, bool8 MovementAction_AcroWheelieInPlaceLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMoveInPlace(objectEvent, sprite, DIR_WEST, GetAcroWheeliePedalDirectionAnimNum(DIR_WEST), 8); + if (objectEvent->directionOverwrite) + InitMoveInPlace(objectEvent, sprite, objectEvent->directionOverwrite, GetAcroWheeliePedalDirectionAnimNum(objectEvent->directionOverwrite), 8); + else + InitMoveInPlace(objectEvent, sprite, DIR_WEST, GetAcroWheeliePedalDirectionAnimNum(DIR_WEST), 8); return MovementAction_WalkInPlace_Step1(objectEvent, sprite); } bool8 MovementAction_AcroWheelieInPlaceRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitMoveInPlace(objectEvent, sprite, DIR_EAST, GetAcroWheeliePedalDirectionAnimNum(DIR_EAST), 8); + if (objectEvent->directionOverwrite) + InitMoveInPlace(objectEvent, sprite, objectEvent->directionOverwrite, GetAcroWheeliePedalDirectionAnimNum(objectEvent->directionOverwrite), 8); + else + InitMoveInPlace(objectEvent, sprite, DIR_EAST, GetAcroWheeliePedalDirectionAnimNum(DIR_EAST), 8); return MovementAction_WalkInPlace_Step1(objectEvent, sprite); } @@ -8636,7 +8924,10 @@ bool8 MovementAction_AcroPopWheelieMoveUp_Step1(struct ObjectEvent *objectEvent, bool8 MovementAction_AcroPopWheelieMoveLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroPopWheelie(objectEvent, sprite, DIR_WEST, 1); + if (objectEvent->directionOverwrite) + InitAcroPopWheelie(objectEvent, sprite, objectEvent->directionOverwrite, 1); + else + InitAcroPopWheelie(objectEvent, sprite, DIR_WEST, 1); return MovementAction_AcroPopWheelieMoveLeft_Step1(objectEvent, sprite); } @@ -8652,7 +8943,10 @@ bool8 MovementAction_AcroPopWheelieMoveLeft_Step1(struct ObjectEvent *objectEven bool8 MovementAction_AcroPopWheelieMoveRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroPopWheelie(objectEvent, sprite, DIR_EAST, 1); + if (objectEvent->directionOverwrite) + InitAcroPopWheelie(objectEvent, sprite, objectEvent->directionOverwrite, 1); + else + InitAcroPopWheelie(objectEvent, sprite, DIR_EAST, 1); return MovementAction_AcroPopWheelieMoveRight_Step1(objectEvent, sprite); } @@ -8706,7 +9000,10 @@ bool8 MovementAction_AcroWheelieMoveUp_Step1(struct ObjectEvent *objectEvent, st bool8 MovementAction_AcroWheelieMoveLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroWheelieMove(objectEvent, sprite, DIR_WEST, 1); + if (objectEvent->directionOverwrite) + InitAcroWheelieMove(objectEvent, sprite, objectEvent->directionOverwrite, 1); + else + InitAcroWheelieMove(objectEvent, sprite, DIR_WEST, 1); return MovementAction_AcroWheelieMoveLeft_Step1(objectEvent, sprite); } @@ -8722,7 +9019,10 @@ bool8 MovementAction_AcroWheelieMoveLeft_Step1(struct ObjectEvent *objectEvent, bool8 MovementAction_AcroWheelieMoveRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroWheelieMove(objectEvent, sprite, DIR_EAST, 1); + if (objectEvent->directionOverwrite) + InitAcroWheelieMove(objectEvent, sprite, objectEvent->directionOverwrite, 1); + else + InitAcroWheelieMove(objectEvent, sprite, DIR_EAST, 1); return MovementAction_AcroWheelieMoveRight_Step1(objectEvent, sprite); } @@ -8777,7 +9077,10 @@ bool8 MovementAction_AcroEndWheelieMoveUp_Step1(struct ObjectEvent *objectEvent, bool8 MovementAction_AcroEndWheelieMoveLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroEndWheelie(objectEvent, sprite, DIR_WEST, 1); + if (objectEvent->directionOverwrite) + InitAcroEndWheelie(objectEvent, sprite, objectEvent->directionOverwrite, 1); + else + InitAcroEndWheelie(objectEvent, sprite, DIR_WEST, 1); return MovementAction_AcroEndWheelieMoveLeft_Step1(objectEvent, sprite); } @@ -8793,7 +9096,10 @@ bool8 MovementAction_AcroEndWheelieMoveLeft_Step1(struct ObjectEvent *objectEven bool8 MovementAction_AcroEndWheelieMoveRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { - InitAcroEndWheelie(objectEvent, sprite, DIR_EAST, 1); + if (objectEvent->directionOverwrite) + InitAcroEndWheelie(objectEvent, sprite, objectEvent->directionOverwrite, 1); + else + InitAcroEndWheelie(objectEvent, sprite, DIR_EAST, 1); return MovementAction_AcroEndWheelieMoveRight_Step1(objectEvent, sprite); } @@ -8997,6 +9303,9 @@ static void GetGroundEffectFlags_LongGrassOnBeginStep(struct ObjectEvent *objEve static void GetGroundEffectFlags_Tracks(struct ObjectEvent *objEvent, u32 *flags) { + if (objEvent->directionOverwrite) + return; + if (MetatileBehavior_IsDeepSand(objEvent->previousMetatileBehavior)) *flags |= GROUND_EFFECT_FLAG_DEEP_SAND; else if (MetatileBehavior_IsSandOrDeepSand(objEvent->previousMetatileBehavior) @@ -9497,12 +9806,13 @@ static void DoTracksGroundEffect_BikeTireTracks(struct ObjectEvent *objEvent, st if (objEvent->currentCoords.x != objEvent->previousCoords.x || objEvent->currentCoords.y != objEvent->previousCoords.y) { + u8 movementDir = (objEvent->previousMovementDirection > DIR_EAST) ? (objEvent->previousMovementDirection - DIR_EAST) : objEvent->previousMovementDirection; gFieldEffectArguments[0] = objEvent->previousCoords.x; gFieldEffectArguments[1] = objEvent->previousCoords.y; gFieldEffectArguments[2] = 149; gFieldEffectArguments[3] = 2; gFieldEffectArguments[4] = - bikeTireTracks_Transitions[objEvent->previousMovementDirection][objEvent->facingDirection - 5]; + bikeTireTracks_Transitions[movementDir][objEvent->facingDirection - 5]; FieldEffectStart(FLDEFF_BIKE_TIRE_TRACKS); } } @@ -10650,3 +10960,50 @@ void GetDaycareGraphics(struct ScriptContext *ctx) } gSpecialVar_Result = i; } + +// running slow +static void StartSlowRunningAnim(struct ObjectEvent *objectEvent, struct Sprite *sprite, u8 direction) +{ + InitNpcForWalkSlow(objectEvent, sprite, direction); + SetStepAnimHandleAlternation(objectEvent, sprite, GetRunningDirectionAnimNum(objectEvent->facingDirection)); +} + +bool8 MovementActionFunc_RunSlowDown_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + StartSlowRunningAnim(objectEvent, sprite, DIR_SOUTH); + return MovementActionFunc_RunSlow_Step1(objectEvent, sprite); +} + +bool8 MovementActionFunc_RunSlowUp_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + StartSlowRunningAnim(objectEvent, sprite, DIR_NORTH); + return MovementActionFunc_RunSlow_Step1(objectEvent, sprite); +} + +bool8 MovementActionFunc_RunSlowLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + if (objectEvent->directionOverwrite) + StartSlowRunningAnim(objectEvent, sprite, objectEvent->directionOverwrite); + else + StartSlowRunningAnim(objectEvent, sprite, DIR_WEST); + return MovementActionFunc_RunSlow_Step1(objectEvent, sprite); +} + +bool8 MovementActionFunc_RunSlowRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + if (objectEvent->directionOverwrite) + StartSlowRunningAnim(objectEvent, sprite, objectEvent->directionOverwrite); + else + StartSlowRunningAnim(objectEvent, sprite, DIR_EAST); + return MovementActionFunc_RunSlow_Step1(objectEvent, sprite); +} + +bool8 MovementActionFunc_RunSlow_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + if (UpdateMovementNormal(objectEvent, sprite)) + { + sprite->sActionFuncId = 2; + return TRUE; + } + return FALSE; +} diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index 9f5e2536fb..51952c3627 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -332,8 +332,39 @@ static const u8 *GetInteractedObjectEventScript(struct MapPosition *position, u8 { u8 objectEventId; const u8 *script; - - objectEventId = GetObjectEventIdByPosition(position->x, position->y, position->elevation); + s16 currX = gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x; + s16 currY = gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.y; + u8 currBehavior = MapGridGetMetatileBehaviorAt(currX, currY); + + switch (direction) + { + case DIR_EAST: + if (MetatileBehavior_IsSidewaysStairsLeftSideAny(metatileBehavior)) + // sideways stairs left-side to your right -> check northeast + objectEventId = GetObjectEventIdByPosition(currX + 1, currY - 1, position->elevation); + else if (MetatileBehavior_IsSidewaysStairsRightSideAny(currBehavior)) + // on top of right-side stairs -> check southeast + objectEventId = GetObjectEventIdByPosition(currX + 1, currY + 1, position->elevation); + else + // check in front of player + objectEventId = GetObjectEventIdByPosition(position->x, position->y, position->elevation); + break; + case DIR_WEST: + if (MetatileBehavior_IsSidewaysStairsRightSideAny(metatileBehavior)) + // facing sideways stairs right side -> check northwest + objectEventId = GetObjectEventIdByPosition(currX - 1, currY - 1, position->elevation); + else if (MetatileBehavior_IsSidewaysStairsLeftSideAny(currBehavior)) + // on top of left-side stairs -> check southwest + objectEventId = GetObjectEventIdByPosition(currX - 1, currY + 1, position->elevation); + else + // check in front of player + objectEventId = GetObjectEventIdByPosition(position->x, position->y, position->elevation); + break; + default: + objectEventId = GetObjectEventIdByPosition(position->x, position->y, position->elevation); + break; + } + if (objectEventId == OBJECT_EVENTS_COUNT || gObjectEvents[objectEventId].localId == OBJ_EVENT_ID_PLAYER) { if (MetatileBehavior_IsCounter(metatileBehavior) != TRUE) diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c index 252fe42113..5f1710dbff 100644 --- a/src/field_player_avatar.c +++ b/src/field_player_avatar.c @@ -93,6 +93,8 @@ static bool8 PlayerAnimIsMultiFrameStationaryAndStateNotTurning(void); static bool8 PlayerIsAnimActive(void); static bool8 PlayerCheckIfAnimFinishedOrInactive(void); +static void PlayerWalkSlow(u8 direction); +static void PlayerRunSlow(u8 direction); static void PlayerRun(u8); static void PlayerNotOnBikeCollide(u8); static void PlayerNotOnBikeCollideWithFarawayIslandMew(u8); @@ -457,7 +459,22 @@ static bool8 ForcedMovement_None(void) static bool8 DoForcedMovement(u8 direction, void (*moveFunc)(u8)) { struct PlayerAvatar *playerAvatar = &gPlayerAvatar; - u8 collision = CheckForPlayerAvatarCollision(direction); + u8 collision; + + // Check for sideways stairs onto ice movement. + switch (direction) + { + case DIR_NORTHWEST: + case DIR_SOUTHWEST: + direction = DIR_WEST; + break; + case DIR_NORTHEAST: + case DIR_SOUTHEAST: + direction = DIR_EAST; + break; + } + + collision = CheckForPlayerAvatarCollision(direction); playerAvatar->flags |= PLAYER_AVATAR_FLAG_FORCED_MOVE; if (collision) @@ -658,13 +675,20 @@ static void PlayerNotOnBikeMoving(u8 direction, u16 heldKeys) if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_UNDERWATER) && (heldKeys & B_BUTTON) && FlagGet(FLAG_SYS_B_DASH) && IsRunningDisallowed(gObjectEvents[gPlayerAvatar.objectEventId].currentMetatileBehavior) == 0) { - PlayerRun(direction); + if (ObjectMovingOnRockStairs(&gObjectEvents[gPlayerAvatar.objectEventId], direction)) + PlayerRunSlow(direction); + else + PlayerRun(direction); + gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_DASH; return; } else { - PlayerWalkNormal(direction); + if (ObjectMovingOnRockStairs(&gObjectEvents[gPlayerAvatar.objectEventId], direction)) + PlayerWalkSlow(direction); + else + PlayerWalkNormal(direction); } } @@ -696,6 +720,7 @@ static u8 CheckForPlayerAvatarStaticCollision(u8 direction) u8 CheckForObjectEventCollision(struct ObjectEvent *objectEvent, s16 x, s16 y, u8 direction, u8 metatileBehavior) { u8 collision = GetCollisionAtCoords(objectEvent, x, y, direction); + if (collision == COLLISION_ELEVATION_MISMATCH && CanStopSurfing(x, y, direction)) return COLLISION_STOP_SURFING; @@ -713,6 +738,7 @@ u8 CheckForObjectEventCollision(struct ObjectEvent *objectEvent, s16 x, s16 y, u return COLLISION_ROTATING_GATE; CheckAcroBikeCollision(x, y, metatileBehavior, &collision); } + return collision; } @@ -975,6 +1001,17 @@ void PlayerSetAnimId(u8 movementActionId, u8 copyableMovement) } } +// slow +static void PlayerWalkSlow(u8 direction) +{ + PlayerSetAnimId(GetWalkSlowMovementAction(direction), 2); +} +static void PlayerRunSlow(u8 direction) +{ + PlayerSetAnimId(GetPlayerRunSlowMovementAction(direction), 2); +} + +// normal speed (1 speed) void PlayerWalkNormal(u8 direction) { PlayerSetAnimId(GetWalkNormalMovementAction(direction), COPY_MOVE_WALK); @@ -1636,7 +1673,7 @@ static void CreateStopSurfingTask(u8 direction) LockPlayerFieldControls(); Overworld_ClearSavedMusic(); Overworld_ChangeMusicToDefault(); - gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_SURFING; + gPlayerAvatar.flags ^= PLAYER_AVATAR_FLAG_SURFING; gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_ON_FOOT; gPlayerAvatar.preventStep = TRUE; taskId = CreateTask(Task_StopSurfingInit, 0xFF); @@ -2430,3 +2467,69 @@ static u8 TrySpinPlayerForWarp(struct ObjectEvent *object, s16 *delayTimer) *delayTimer = 0; return sSpinDirections[object->facingDirection]; } + +//sideways stairs +u8 GetRightSideStairsDirection(u8 direction) +{ + switch (direction) + { + case DIR_WEST: + return DIR_NORTHWEST; + case DIR_EAST: + return DIR_SOUTHEAST; + default: + if (direction > DIR_EAST) + direction -= DIR_EAST; + return direction; + } +} + +u8 GetLeftSideStairsDirection(u8 direction) +{ + switch (direction) + { + case DIR_WEST: + return DIR_SOUTHWEST; + case DIR_EAST: + return DIR_NORTHEAST; + default: + if (direction > DIR_EAST) + direction -= DIR_EAST; + return direction; + } +} + +bool8 ObjectMovingOnRockStairs(struct ObjectEvent *objectEvent, u8 direction) +{ + #if SLOW_MOVEMENT_ON_STAIRS == TRUE + s16 x = objectEvent->currentCoords.x; + s16 y = objectEvent->currentCoords.y; + + // TODO followers on sideways stairs + if (IsFollowerVisible() && GetFollowerObject() != NULL && (objectEvent->isPlayer || objectEvent->localId == OBJ_EVENT_ID_FOLLOWER)) + return FALSE; + + switch (direction) + { + case DIR_NORTH: + return MetatileBehavior_IsRockStairs(MapGridGetMetatileBehaviorAt(x,y)); + case DIR_SOUTH: + MoveCoords(DIR_SOUTH, &x, &y); + return MetatileBehavior_IsRockStairs(MapGridGetMetatileBehaviorAt(x,y)); + case DIR_WEST: + case DIR_EAST: + case DIR_NORTHEAST: + case DIR_NORTHWEST: + case DIR_SOUTHWEST: + case DIR_SOUTHEAST: + // directionOverwrite is only used for sideways stairs motion + if (objectEvent->directionOverwrite) + return TRUE; + default: + return FALSE; + } + #else + return FALSE; + #endif +} + diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c index ef349be7cf..98914ae5e8 100644 --- a/src/metatile_behavior.c +++ b/src/metatile_behavior.c @@ -8,126 +8,131 @@ static const u8 sTileBitAttributes[NUM_METATILE_BEHAVIORS] = { - [MB_NORMAL] = TILE_FLAG_UNUSED, - [MB_TALL_GRASS] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, - [MB_LONG_GRASS] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, - [MB_UNUSED_05] = TILE_FLAG_HAS_ENCOUNTERS, - [MB_DEEP_SAND] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, - [MB_SHORT_GRASS] = TILE_FLAG_UNUSED, - [MB_CAVE] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, - [MB_LONG_GRASS_SOUTH_EDGE] = TILE_FLAG_UNUSED, - [MB_NO_RUNNING] = TILE_FLAG_UNUSED, - [MB_INDOOR_ENCOUNTER] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, - [MB_MOUNTAIN_TOP] = TILE_FLAG_UNUSED, - [MB_BATTLE_PYRAMID_WARP] = TILE_FLAG_UNUSED, - [MB_MOSSDEEP_GYM_WARP] = TILE_FLAG_UNUSED, - [MB_MT_PYRE_HOLE] = TILE_FLAG_UNUSED, - [MB_POND_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, - [MB_INTERIOR_DEEP_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, - [MB_DEEP_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, - [MB_WATERFALL] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_SOOTOPOLIS_DEEP_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_OCEAN_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, - [MB_PUDDLE] = TILE_FLAG_UNUSED, - [MB_SHALLOW_WATER] = TILE_FLAG_UNUSED, - [MB_NO_SURFACING] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_STAIRS_OUTSIDE_ABANDONED_SHIP] = TILE_FLAG_UNUSED, - [MB_SHOAL_CAVE_ENTRANCE] = TILE_FLAG_UNUSED, - [MB_ICE] = TILE_FLAG_UNUSED, - [MB_SAND] = TILE_FLAG_UNUSED, - [MB_SEAWEED] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, - [MB_UNUSED_23] = TILE_FLAG_UNUSED, - [MB_ASHGRASS] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, - [MB_FOOTPRINTS] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, - [MB_THIN_ICE] = TILE_FLAG_UNUSED, - [MB_CRACKED_ICE] = TILE_FLAG_UNUSED, - [MB_HOT_SPRINGS] = TILE_FLAG_UNUSED, - [MB_LAVARIDGE_GYM_B1F_WARP] = TILE_FLAG_UNUSED, - [MB_SEAWEED_NO_SURFACING] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, - [MB_REFLECTION_UNDER_BRIDGE] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_EAST] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_WEST] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_NORTH] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_SOUTH] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_NORTHEAST] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_NORTHWEST] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_SOUTHEAST] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_SOUTHWEST] = TILE_FLAG_UNUSED, - [MB_JUMP_NORTHEAST] = TILE_FLAG_UNUSED, - [MB_JUMP_NORTHWEST] = TILE_FLAG_UNUSED, - [MB_JUMP_SOUTHEAST] = TILE_FLAG_UNUSED, - [MB_JUMP_SOUTHWEST] = TILE_FLAG_UNUSED, - [MB_WALK_EAST] = TILE_FLAG_UNUSED, - [MB_WALK_WEST] = TILE_FLAG_UNUSED, - [MB_WALK_NORTH] = TILE_FLAG_UNUSED, - [MB_WALK_SOUTH] = TILE_FLAG_UNUSED, - [MB_SLIDE_EAST] = TILE_FLAG_UNUSED, - [MB_SLIDE_WEST] = TILE_FLAG_UNUSED, - [MB_SLIDE_NORTH] = TILE_FLAG_UNUSED, - [MB_SLIDE_SOUTH] = TILE_FLAG_UNUSED, - [MB_TRICK_HOUSE_PUZZLE_8_FLOOR] = TILE_FLAG_UNUSED, - [MB_UNUSED_49] = TILE_FLAG_UNUSED, - [MB_UNUSED_4A] = TILE_FLAG_UNUSED, - [MB_EASTWARD_CURRENT] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_WESTWARD_CURRENT] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_NORTHWARD_CURRENT] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_SOUTHWARD_CURRENT] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_NON_ANIMATED_DOOR] = TILE_FLAG_UNUSED, - [MB_LADDER] = TILE_FLAG_UNUSED, - [MB_EAST_ARROW_WARP] = TILE_FLAG_UNUSED, - [MB_WEST_ARROW_WARP] = TILE_FLAG_UNUSED, - [MB_NORTH_ARROW_WARP] = TILE_FLAG_UNUSED, - [MB_SOUTH_ARROW_WARP] = TILE_FLAG_UNUSED, - [MB_CRACKED_FLOOR_HOLE] = TILE_FLAG_UNUSED, - [MB_AQUA_HIDEOUT_WARP] = TILE_FLAG_UNUSED, - [MB_LAVARIDGE_GYM_1F_WARP] = TILE_FLAG_UNUSED, - [MB_ANIMATED_DOOR] = TILE_FLAG_UNUSED, - [MB_UP_ESCALATOR] = TILE_FLAG_UNUSED, - [MB_DOWN_ESCALATOR] = TILE_FLAG_UNUSED, - [MB_WATER_DOOR] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_WATER_SOUTH_ARROW_WARP] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_DEEP_SOUTH_WARP] = TILE_FLAG_UNUSED, - [MB_UNUSED_6F] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, - [MB_BRIDGE_OVER_POND_LOW] = TILE_FLAG_UNUSED, - [MB_BRIDGE_OVER_POND_MED] = TILE_FLAG_UNUSED, - [MB_BRIDGE_OVER_POND_HIGH] = TILE_FLAG_UNUSED, - [MB_PACIFIDLOG_VERTICAL_LOG_TOP] = TILE_FLAG_UNUSED, - [MB_PACIFIDLOG_VERTICAL_LOG_BOTTOM] = TILE_FLAG_UNUSED, - [MB_PACIFIDLOG_HORIZONTAL_LOG_LEFT] = TILE_FLAG_UNUSED, - [MB_PACIFIDLOG_HORIZONTAL_LOG_RIGHT] = TILE_FLAG_UNUSED, - [MB_FORTREE_BRIDGE] = TILE_FLAG_UNUSED, - [MB_BRIDGE_OVER_POND_MED_EDGE_1] = TILE_FLAG_UNUSED, - [MB_BRIDGE_OVER_POND_MED_EDGE_2] = TILE_FLAG_UNUSED, - [MB_BRIDGE_OVER_POND_HIGH_EDGE_1] = TILE_FLAG_UNUSED, - [MB_BRIDGE_OVER_POND_HIGH_EDGE_2] = TILE_FLAG_UNUSED, - [MB_UNUSED_BRIDGE] = TILE_FLAG_UNUSED, - [MB_BIKE_BRIDGE_OVER_BARRIER] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_SCENERY] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_TRAINER_SPOT] = TILE_FLAG_UNUSED, - [MB_HOLDS_SMALL_DECORATION] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_BALLOON] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_IMPASSABLE] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_GLITTER_MAT] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_JUMP_MAT] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_SPIN_MAT] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_SOUND_MAT] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_BREAKABLE_DOOR] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_SOUTH_AND_NORTH] = TILE_FLAG_UNUSED, - [MB_IMPASSABLE_WEST_AND_EAST] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_HOLE] = TILE_FLAG_UNUSED, - [MB_HOLDS_LARGE_DECORATION] = TILE_FLAG_UNUSED, - [MB_SECRET_BASE_TV_SHIELD] = TILE_FLAG_UNUSED, - [MB_PLAYER_ROOM_PC_ON] = TILE_FLAG_UNUSED, - [MB_MUDDY_SLOPE] = TILE_FLAG_UNUSED, - [MB_BUMPY_SLOPE] = TILE_FLAG_UNUSED, - [MB_CRACKED_FLOOR] = TILE_FLAG_UNUSED, - [MB_ISOLATED_VERTICAL_RAIL] = TILE_FLAG_UNUSED, - [MB_ISOLATED_HORIZONTAL_RAIL] = TILE_FLAG_UNUSED, - [MB_VERTICAL_RAIL] = TILE_FLAG_UNUSED, - [MB_HORIZONTAL_RAIL] = TILE_FLAG_UNUSED, - [MB_SIGNPOST] = TILE_FLAG_UNUSED, - [MB_POKEMON_CENTER_SIGN] = TILE_FLAG_UNUSED, - [MB_POKEMART_SIGN] = TILE_FLAG_UNUSED, + [MB_NORMAL] = TILE_FLAG_UNUSED, + [MB_TALL_GRASS] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, + [MB_LONG_GRASS] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, + [MB_UNUSED_05] = TILE_FLAG_HAS_ENCOUNTERS, + [MB_DEEP_SAND] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, + [MB_SHORT_GRASS] = TILE_FLAG_UNUSED, + [MB_CAVE] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, + [MB_LONG_GRASS_SOUTH_EDGE] = TILE_FLAG_UNUSED, + [MB_NO_RUNNING] = TILE_FLAG_UNUSED, + [MB_INDOOR_ENCOUNTER] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, + [MB_MOUNTAIN_TOP] = TILE_FLAG_UNUSED, + [MB_BATTLE_PYRAMID_WARP] = TILE_FLAG_UNUSED, + [MB_MOSSDEEP_GYM_WARP] = TILE_FLAG_UNUSED, + [MB_MT_PYRE_HOLE] = TILE_FLAG_UNUSED, + [MB_POND_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, + [MB_INTERIOR_DEEP_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, + [MB_DEEP_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, + [MB_WATERFALL] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_SOOTOPOLIS_DEEP_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_OCEAN_WATER] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, + [MB_PUDDLE] = TILE_FLAG_UNUSED, + [MB_SHALLOW_WATER] = TILE_FLAG_UNUSED, + [MB_NO_SURFACING] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_STAIRS_OUTSIDE_ABANDONED_SHIP] = TILE_FLAG_UNUSED, + [MB_SHOAL_CAVE_ENTRANCE] = TILE_FLAG_UNUSED, + [MB_ICE] = TILE_FLAG_UNUSED, + [MB_SAND] = TILE_FLAG_UNUSED, + [MB_SEAWEED] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, + [MB_UNUSED_23] = TILE_FLAG_UNUSED, + [MB_ASHGRASS] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, + [MB_FOOTPRINTS] = TILE_FLAG_UNUSED | TILE_FLAG_HAS_ENCOUNTERS, + [MB_THIN_ICE] = TILE_FLAG_UNUSED, + [MB_CRACKED_ICE] = TILE_FLAG_UNUSED, + [MB_HOT_SPRINGS] = TILE_FLAG_UNUSED, + [MB_LAVARIDGE_GYM_B1F_WARP] = TILE_FLAG_UNUSED, + [MB_SEAWEED_NO_SURFACING] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE | TILE_FLAG_HAS_ENCOUNTERS, + [MB_REFLECTION_UNDER_BRIDGE] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_EAST] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_WEST] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_NORTH] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_SOUTH] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_NORTHEAST] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_NORTHWEST] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_SOUTHEAST] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_SOUTHWEST] = TILE_FLAG_UNUSED, + [MB_JUMP_NORTHEAST] = TILE_FLAG_UNUSED, + [MB_JUMP_NORTHWEST] = TILE_FLAG_UNUSED, + [MB_JUMP_SOUTHEAST] = TILE_FLAG_UNUSED, + [MB_JUMP_SOUTHWEST] = TILE_FLAG_UNUSED, + [MB_WALK_EAST] = TILE_FLAG_UNUSED, + [MB_WALK_WEST] = TILE_FLAG_UNUSED, + [MB_WALK_NORTH] = TILE_FLAG_UNUSED, + [MB_WALK_SOUTH] = TILE_FLAG_UNUSED, + [MB_SLIDE_EAST] = TILE_FLAG_UNUSED, + [MB_SLIDE_WEST] = TILE_FLAG_UNUSED, + [MB_SLIDE_NORTH] = TILE_FLAG_UNUSED, + [MB_SLIDE_SOUTH] = TILE_FLAG_UNUSED, + [MB_TRICK_HOUSE_PUZZLE_8_FLOOR] = TILE_FLAG_UNUSED, + [MB_EASTWARD_CURRENT] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_WESTWARD_CURRENT] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_NORTHWARD_CURRENT] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_SOUTHWARD_CURRENT] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_NON_ANIMATED_DOOR] = TILE_FLAG_UNUSED, + [MB_LADDER] = TILE_FLAG_UNUSED, + [MB_EAST_ARROW_WARP] = TILE_FLAG_UNUSED, + [MB_WEST_ARROW_WARP] = TILE_FLAG_UNUSED, + [MB_NORTH_ARROW_WARP] = TILE_FLAG_UNUSED, + [MB_SOUTH_ARROW_WARP] = TILE_FLAG_UNUSED, + [MB_CRACKED_FLOOR_HOLE] = TILE_FLAG_UNUSED, + [MB_AQUA_HIDEOUT_WARP] = TILE_FLAG_UNUSED, + [MB_LAVARIDGE_GYM_1F_WARP] = TILE_FLAG_UNUSED, + [MB_ANIMATED_DOOR] = TILE_FLAG_UNUSED, + [MB_UP_ESCALATOR] = TILE_FLAG_UNUSED, + [MB_DOWN_ESCALATOR] = TILE_FLAG_UNUSED, + [MB_WATER_DOOR] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_WATER_SOUTH_ARROW_WARP] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_DEEP_SOUTH_WARP] = TILE_FLAG_UNUSED, + [MB_UNUSED_6F] = TILE_FLAG_UNUSED | TILE_FLAG_SURFABLE, + [MB_BRIDGE_OVER_POND_LOW] = TILE_FLAG_UNUSED, + [MB_BRIDGE_OVER_POND_MED] = TILE_FLAG_UNUSED, + [MB_BRIDGE_OVER_POND_HIGH] = TILE_FLAG_UNUSED, + [MB_PACIFIDLOG_VERTICAL_LOG_TOP] = TILE_FLAG_UNUSED, + [MB_PACIFIDLOG_VERTICAL_LOG_BOTTOM] = TILE_FLAG_UNUSED, + [MB_PACIFIDLOG_HORIZONTAL_LOG_LEFT] = TILE_FLAG_UNUSED, + [MB_PACIFIDLOG_HORIZONTAL_LOG_RIGHT] = TILE_FLAG_UNUSED, + [MB_FORTREE_BRIDGE] = TILE_FLAG_UNUSED, + [MB_BRIDGE_OVER_POND_MED_EDGE_1] = TILE_FLAG_UNUSED, + [MB_BRIDGE_OVER_POND_MED_EDGE_2] = TILE_FLAG_UNUSED, + [MB_BRIDGE_OVER_POND_HIGH_EDGE_1] = TILE_FLAG_UNUSED, + [MB_BRIDGE_OVER_POND_HIGH_EDGE_2] = TILE_FLAG_UNUSED, + [MB_UNUSED_BRIDGE] = TILE_FLAG_UNUSED, + [MB_BIKE_BRIDGE_OVER_BARRIER] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_SCENERY] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_TRAINER_SPOT] = TILE_FLAG_UNUSED, + [MB_HOLDS_SMALL_DECORATION] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_BALLOON] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_IMPASSABLE] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_GLITTER_MAT] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_JUMP_MAT] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_SPIN_MAT] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_SOUND_MAT] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_BREAKABLE_DOOR] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_SOUTH_AND_NORTH] = TILE_FLAG_UNUSED, + [MB_IMPASSABLE_WEST_AND_EAST] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_HOLE] = TILE_FLAG_UNUSED, + [MB_HOLDS_LARGE_DECORATION] = TILE_FLAG_UNUSED, + [MB_SECRET_BASE_TV_SHIELD] = TILE_FLAG_UNUSED, + [MB_PLAYER_ROOM_PC_ON] = TILE_FLAG_UNUSED, + [MB_MUDDY_SLOPE] = TILE_FLAG_UNUSED, + [MB_BUMPY_SLOPE] = TILE_FLAG_UNUSED, + [MB_CRACKED_FLOOR] = TILE_FLAG_UNUSED, + [MB_ISOLATED_VERTICAL_RAIL] = TILE_FLAG_UNUSED, + [MB_ISOLATED_HORIZONTAL_RAIL] = TILE_FLAG_UNUSED, + [MB_VERTICAL_RAIL] = TILE_FLAG_UNUSED, + [MB_HORIZONTAL_RAIL] = TILE_FLAG_UNUSED, + [MB_SIGNPOST] = TILE_FLAG_UNUSED, + [MB_POKEMON_CENTER_SIGN] = TILE_FLAG_UNUSED, + [MB_POKEMART_SIGN] = TILE_FLAG_UNUSED, + [MB_SIDEWAYS_STAIRS_RIGHT_SIDE] = TILE_FLAG_UNUSED, + [MB_SIDEWAYS_STAIRS_LEFT_SIDE] = TILE_FLAG_UNUSED, + [MB_SIDEWAYS_STAIRS_RIGHT_SIDE_TOP] = TILE_FLAG_UNUSED, + [MB_SIDEWAYS_STAIRS_LEFT_SIDE_TOP] = TILE_FLAG_UNUSED, + [MB_SIDEWAYS_STAIRS_RIGHT_SIDE_BOTTOM] = TILE_FLAG_UNUSED, + [MB_SIDEWAYS_STAIRS_LEFT_SIDE_BOTTOM] = TILE_FLAG_UNUSED, + [MB_ROCK_STAIRS] = TILE_FLAG_UNUSED, }; bool8 MetatileBehavior_IsATile(u8 metatileBehavior) @@ -1461,3 +1466,79 @@ bool8 MetatileBehavior_IsPokeMartSign(u32 metatileBehavior) { return (metatileBehavior == MB_POKEMART_SIGN); } + +bool8 MetatileBehavior_IsSidewaysStairsRightSide(u8 metatileBehavior) +{ + if (metatileBehavior == MB_SIDEWAYS_STAIRS_RIGHT_SIDE || metatileBehavior == MB_SIDEWAYS_STAIRS_RIGHT_SIDE_BOTTOM) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSidewaysStairsLeftSide(u8 metatileBehavior) +{ + if (metatileBehavior == MB_SIDEWAYS_STAIRS_LEFT_SIDE || metatileBehavior == MB_SIDEWAYS_STAIRS_LEFT_SIDE_BOTTOM) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSidewaysStairsRightSideTop(u8 metatileBehavior) +{ + if (metatileBehavior == MB_SIDEWAYS_STAIRS_RIGHT_SIDE_TOP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSidewaysStairsLeftSideTop(u8 metatileBehavior) +{ + if (metatileBehavior == MB_SIDEWAYS_STAIRS_LEFT_SIDE_TOP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSidewaysStairsRightSideBottom(u8 metatileBehavior) +{ + if (metatileBehavior == MB_SIDEWAYS_STAIRS_RIGHT_SIDE_BOTTOM) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSidewaysStairsLeftSideBottom(u8 metatileBehavior) +{ + if (metatileBehavior == MB_SIDEWAYS_STAIRS_LEFT_SIDE_BOTTOM) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSidewaysStairsRightSideAny(u8 metatileBehavior) +{ + if (metatileBehavior == MB_SIDEWAYS_STAIRS_RIGHT_SIDE + || metatileBehavior == MB_SIDEWAYS_STAIRS_RIGHT_SIDE_BOTTOM + || metatileBehavior == MB_SIDEWAYS_STAIRS_RIGHT_SIDE_TOP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSidewaysStairsLeftSideAny(u8 metatileBehavior) +{ + if (metatileBehavior == MB_SIDEWAYS_STAIRS_LEFT_SIDE + || metatileBehavior == MB_SIDEWAYS_STAIRS_LEFT_SIDE_BOTTOM + || metatileBehavior == MB_SIDEWAYS_STAIRS_LEFT_SIDE_TOP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsRockStairs(u8 metatileBehavior) +{ + if (metatileBehavior == MB_ROCK_STAIRS) + return TRUE; + else + return FALSE; +} diff --git a/src/scrcmd.c b/src/scrcmd.c index 86be73404c..ef5084681e 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1009,6 +1009,8 @@ bool8 ScrCmd_applymovement(struct ScriptContext *ctx) ClearObjectEventMovement(objEvent, &gSprites[objEvent->spriteId]); gSprites[objEvent->spriteId].animCmdIndex = 0; // Reset start frame of animation } + + gObjectEvents[GetObjectEventIdByLocalId(localId)].directionOverwrite = DIR_NONE; ScriptMovement_StartObjectMovementScript(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, movementScript); sMovingNpcId = localId; objEvent = GetFollowerObject(); @@ -1033,6 +1035,7 @@ bool8 ScrCmd_applymovementat(struct ScriptContext *ctx) u8 mapGroup = ScriptReadByte(ctx); u8 mapNum = ScriptReadByte(ctx); + gObjectEvents[GetObjectEventIdByLocalId(localId)].directionOverwrite = DIR_NONE; ScriptMovement_StartObjectMovementScript(localId, mapNum, mapGroup, movementScript); sMovingNpcId = localId; return FALSE;