diff --git a/data/field_effect_scripts.s b/data/field_effect_scripts.s index 98ed66a13d..34678bb293 100644 --- a/data/field_effect_scripts.s +++ b/data/field_effect_scripts.s @@ -81,6 +81,8 @@ gFieldEffectScriptPointers:: .4byte gFieldEffectScript_TracksSpot @ FLDEFF_TRACKS_SPOT .4byte gFieldEffectScript_CaveDust @ FLDEFF_CAVE_DUST .4byte gFieldEffectScript_Defog @ FLDEFF_DEFOG + .4byte gFieldEffectScript_UseRockClimb @ FLDEFF_USE_ROCK_CLIMB + .4byte gFieldEffectScript_RockClimbDust @ FLDEFF_ROCK_CLIMB_DUST gFieldEffectScript_ExclamationMarkIcon1:: field_eff_callnative FldEff_ExclamationMarkIcon @@ -384,3 +386,11 @@ gFieldEffectScript_CaveDust:: gFieldEffectScript_Defog:: field_eff_callnative FldEff_Defog field_eff_end +gFieldEffectScript_UseRockClimb:: @ 82DBC3F + field_eff_callnative FldEff_UseRockClimb + field_eff_end + +gFieldEffectScript_RockClimbDust:: @ 82DBB28 + field_eff_loadfadedpal_callnative gSpritePalette_BigDust, FldEff_RockClimbDust + field_eff_end + diff --git a/data/scripts/field_move_scripts.inc b/data/scripts/field_move_scripts.inc index bfc6958138..e9a88367a7 100644 --- a/data/scripts/field_move_scripts.inc +++ b/data/scripts/field_move_scripts.inc @@ -441,3 +441,36 @@ EventScript_UseDefog:: waitstate releaseall end + +EventScript_UseRockClimb:: + lockall + checkfieldmove FIELD_MOVE_ROCK_CLIMB + goto_if_eq VAR_RESULT, PARTY_SIZE, EventScript_CantRockClimb + bufferpartymonnick STR_VAR_1, VAR_RESULT + setfieldeffectargument 0, VAR_RESULT + msgbox Text_WantToRockClimb, MSGBOX_YESNO + goto_if_eq VAR_RESULT, NO, EventScript_EndRockClimb + msgbox Text_MonUsedRockClimb, MSGBOX_DEFAULT + closemessage + dofieldeffect FLDEFF_USE_ROCK_CLIMB + waitstate + goto EventScript_EndRockClimb + end + +EventScript_CantRockClimb:: + msgbox Text_CantRockClimb, MSGBOX_DEFAULT + +EventScript_EndRockClimb:: + releaseall + end + +Text_WantToRockClimb: + .string "The cliff is steep.\n" + .string "Would you like to use Rock Climb?$" + +Text_MonUsedRockClimb: + .string "{STR_VAR_1} used Rock Climb!$" + +Text_CantRockClimb: + .string "The cliff is steep.\n" + .string "A Pokémon may be able to climb it.$" diff --git a/graphics/field_effects/palettes/big_dust.pal b/graphics/field_effects/palettes/big_dust.pal new file mode 100644 index 0000000000..34beaf0371 --- /dev/null +++ b/graphics/field_effects/palettes/big_dust.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +98 172 238 +198 181 156 +165 140 115 +181 165 140 +148 123 99 +206 198 173 +189 173 148 +82 74 57 +222 180 148 +140 123 82 +173 156 123 +238 213 180 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/field_effects/pics/rock_climb_blob.png b/graphics/field_effects/pics/rock_climb_blob.png new file mode 100644 index 0000000000..19a9a7cea9 Binary files /dev/null and b/graphics/field_effects/pics/rock_climb_blob.png differ diff --git a/graphics/field_effects/pics/rock_climb_dust.png b/graphics/field_effects/pics/rock_climb_dust.png new file mode 100644 index 0000000000..541c6ba9b8 Binary files /dev/null and b/graphics/field_effects/pics/rock_climb_dust.png differ diff --git a/include/config/overworld.h b/include/config/overworld.h index b1f107ce63..480c5dbcea 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -11,6 +11,7 @@ #define OW_HIDE_REPEAT_MAP_POPUP FALSE // If enabled, map popups will not appear if entering a map with the same Map Section Id as the last. #define OW_WHITEOUT_CUTSCENE GEN_LATEST // In Gen4+, whiting out shows an additional message and post whiteout event script cutscene with a healing NPC. (While this change was also in FRLG, for the sake of simplicity, setting this to GEN_3 will result in RSE behavior.) #define OW_DEFOG_FIELD_MOVE FALSE // If enabled, Defog can be used as a Field Move as seen in DPPt. +#define OW_ROCK_CLIMB_FIELD_MOVE FALSE // If enabled, Rock Climb can be used as a Field Move as seen in DPPt. // Item Obtain Description Box #define OW_ITEM_DESCRIPTIONS_OFF 0 // never show descriptions diff --git a/include/constants/event_object_movement.h b/include/constants/event_object_movement.h index 4e1b3a34ea..4f183d7667 100755 --- a/include/constants/event_object_movement.h +++ b/include/constants/event_object_movement.h @@ -259,6 +259,11 @@ #define MOVEMENT_ACTION_SURF_STILL_UP 0xAB #define MOVEMENT_ACTION_SURF_STILL_LEFT 0xAC #define MOVEMENT_ACTION_SURF_STILL_RIGHT 0xAD +//fast diagonal movement +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT 0xAE +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT 0xAF +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT 0xB0 +#define MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT 0xB1 #define MOVEMENT_ACTION_STEP_END 0xFE #define MOVEMENT_ACTION_NONE 0xFF diff --git a/include/constants/field_effects.h b/include/constants/field_effects.h index e47cc292c3..e38b25cac7 100644 --- a/include/constants/field_effects.h +++ b/include/constants/field_effects.h @@ -77,6 +77,8 @@ #define FLDEFF_TRACKS_BUG 72 #define FLDEFF_CAVE_DUST 73 #define FLDEFF_DEFOG 74 +#define FLDEFF_USE_ROCK_CLIMB 75 +#define FLDEFF_ROCK_CLIMB_DUST 76 #define FLDEFFOBJ_SHADOW_S 0 #define FLDEFFOBJ_SHADOW_M 1 @@ -119,6 +121,8 @@ #define FLDEFFOBJ_TRACKS_SPOT 38 #define FLDEFFOBJ_TRACKS_BUG 39 #define FLDEFFOBJ_CAVE_DUST 40 +#define FLDEFFOBJ_ROCK_CLIMB_BLOB 41 +#define FLDEFFOBJ_ROCK_CLIMB_DUST 42 #define FLDEFF_PAL_TAG_CUT_GRASS 0x1000 #define FLDEFF_PAL_TAG_SECRET_POWER_TREE 0x1003 @@ -133,6 +137,7 @@ #define FLDEFF_PAL_TAG_HOF_MONITOR 0x1010 #define FLDEFF_PAL_TAG_UNKNOWN 0x1011 #define FLDEFF_PAL_TAG_CAVE_DUST 0x1012 +#define FLDEFF_PAL_TAG_DUST_CLOUD 0x1013 #define FLDEFF_PAL_TAG_FIELD_MOVE_MON 0x8400 // tile tags, for field effects that may have many copies on screen at once diff --git a/include/constants/field_move.h b/include/constants/field_move.h index 1d0fb83977..c6c49c8708 100644 --- a/include/constants/field_move.h +++ b/include/constants/field_move.h @@ -18,6 +18,9 @@ enum FieldMove FIELD_MOVE_MILK_DRINK, FIELD_MOVE_SOFT_BOILED, FIELD_MOVE_SWEET_SCENT, +#if OW_ROCK_CLIMB_FIELD_MOVE == TRUE + FIELD_MOVE_ROCK_CLIMB, +#endif #if OW_DEFOG_FIELD_MOVE == TRUE FIELD_MOVE_DEFOG, #endif diff --git a/include/constants/metatile_behaviors.h b/include/constants/metatile_behaviors.h index 505f279f73..12ced67a9f 100755 --- a/include/constants/metatile_behaviors.h +++ b/include/constants/metatile_behaviors.h @@ -241,7 +241,7 @@ enum { MB_UP_LEFT_STAIR_WARP, MB_DOWN_RIGHT_STAIR_WARP, MB_DOWN_LEFT_STAIR_WARP, - MB_UNUSED_EF, + MB_ROCK_CLIMB, NUM_METATILE_BEHAVIORS }; diff --git a/include/event_scripts.h b/include/event_scripts.h index fa2df54740..646b054195 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -573,6 +573,7 @@ extern const u8 EventScript_UseWaterfall[]; extern const u8 EventScript_CannotUseWaterfall[]; extern const u8 EventScript_UseDive[]; extern const u8 EventScript_UseDiveUnderwater[]; +extern const u8 EventScript_UseRockClimb[]; extern const u8 EventScript_FallDownHole[]; extern const u8 EventScript_FieldPoison[]; extern const u8 EventScript_EggHatch[]; diff --git a/include/field_effect.h b/include/field_effect.h index 2e13879353..2b933e0c1f 100644 --- a/include/field_effect.h +++ b/include/field_effect.h @@ -49,5 +49,5 @@ void FreeResourcesAndDestroySprite(struct Sprite *sprite, u8 spriteId); u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y, u8 subpriority); void StartEscapeRopeFieldEffect(void); void FieldEffectFreeGraphicsResources(struct Sprite *sprite); - +bool8 IsRockClimbActive(void); #endif // GUARD_FIELD_EFFECTS_H diff --git a/include/metatile_behavior.h b/include/metatile_behavior.h index ecdc696d41..5e268d7262 100644 --- a/include/metatile_behavior.h +++ b/include/metatile_behavior.h @@ -164,5 +164,6 @@ bool8 MetatileBehavior_IsSidewaysStairsRightSideBottom(u8 metatileBehavior); bool8 MetatileBehavior_IsSidewaysStairsLeftSideBottom(u8 metatileBehavior); bool8 MetatileBehavior_IsSidewaysStairsRightSideAny(u8 metatileBehavior); bool8 MetatileBehavior_IsSidewaysStairsLeftSideAny(u8 metatileBehavior); +bool8 MetatileBehavior_IsRockClimbable(u8 metatileBehavior); #endif // GUARD_METATILE_BEHAVIOR_H diff --git a/include/party_menu.h b/include/party_menu.h index 5aa9472dac..c450ab02c0 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -110,5 +110,6 @@ bool32 SetUpFieldMove_Surf(void); bool32 SetUpFieldMove_Fly(void); bool32 SetUpFieldMove_Waterfall(void); bool32 SetUpFieldMove_Dive(void); +bool32 SetUpFieldMove_RockClimb(void); #endif // GUARD_PARTY_MENU_H diff --git a/spritesheet_rules.mk b/spritesheet_rules.mk index aaa346ccf1..ef5da9c091 100644 --- a/spritesheet_rules.mk +++ b/spritesheet_rules.mk @@ -663,6 +663,9 @@ $(FLDEFFGFXDIR)/deep_sand_footprints.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/ground_impact_dust.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 1 +$(FLDEFFGFXDIR)/rock_climb_dust.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 4 -mheight 4 + $(FLDEFFGFXDIR)/ash_puff.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 2 @@ -687,6 +690,9 @@ $(FLDEFFGFXDIR)/short_grass.4bpp: %.4bpp: %.png $(FLDEFFGFXDIR)/surf_blob.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 +$(FLDEFFGFXDIR)/rock_climb_blob.4bpp: %.4bpp: %.png + $(GFX) $< $@ -mwidth 4 -mheight 4 + $(FLDEFFGFXDIR)/tall_grass.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 2 -mheight 2 diff --git a/src/data/field_effects/field_effect_object_template_pointers.h b/src/data/field_effects/field_effect_object_template_pointers.h index 7173ffbe58..281c664f03 100755 --- a/src/data/field_effects/field_effect_object_template_pointers.h +++ b/src/data/field_effects/field_effect_object_template_pointers.h @@ -40,6 +40,8 @@ extern const struct SpriteTemplate gFieldEffectObjectTemplate_SlitherTracks; extern const struct SpriteTemplate gFieldEffectObjectTemplate_BugTracks; extern const struct SpriteTemplate gFieldEffectObjectTemplate_SpotTracks; extern const struct SpriteTemplate gFieldEffectObjectTemplate_CaveDust; +extern const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbBlob; +extern const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbDust; const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[] = { [FLDEFFOBJ_SHADOW_S] = &gFieldEffectObjectTemplate_ShadowSmall, @@ -83,4 +85,6 @@ const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[] = { [FLDEFFOBJ_TRACKS_SPOT] = &gFieldEffectObjectTemplate_SpotTracks, [FLDEFFOBJ_TRACKS_BUG] = &gFieldEffectObjectTemplate_BugTracks, [FLDEFFOBJ_CAVE_DUST] = &gFieldEffectObjectTemplate_CaveDust, + [FLDEFFOBJ_ROCK_CLIMB_BLOB] = &gFieldEffectObjectTemplate_RockClimbBlob, + [FLDEFFOBJ_ROCK_CLIMB_DUST] = &gFieldEffectObjectTemplate_RockClimbDust, }; diff --git a/src/data/field_effects/field_effect_objects.h b/src/data/field_effects/field_effect_objects.h index 5638ea46e2..aae9ad1948 100755 --- a/src/data/field_effects/field_effect_objects.h +++ b/src/data/field_effects/field_effect_objects.h @@ -1404,3 +1404,47 @@ const struct SpriteTemplate gFieldEffectObjectTemplate_CaveDust = { }; const struct SpritePalette gSpritePalette_CaveDust = {gFieldEffectObjectPalette_CaveDust, FLDEFF_PAL_TAG_CAVE_DUST}; +static const struct SpriteFrameImage sPicTable_RockClimbBlob[] = { + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 1), + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 0), + overworld_frame(gFieldEffectObjectPic_RockClimbBlob, 4, 4, 2), +}; + +const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbBlob = { + .tileTag = 0xFFFF, + .paletteTag = 0xFFFF, + .oam = &gObjectEventBaseOam_32x32, + .anims = sAnimTable_SurfBlob, + .images = sPicTable_RockClimbBlob, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = UpdateSurfBlobFieldEffect, +}; + + +static const union AnimCmd sAnim_RockClimbDust[] = +{ + ANIMCMD_FRAME(0, 12), + ANIMCMD_FRAME(1, 12), + ANIMCMD_FRAME(2, 12), + ANIMCMD_END, +}; +static const union AnimCmd *const sAnimTable_RockClimbDust[] = +{ + sAnim_RockClimbDust, +}; +static const struct SpriteFrameImage sPicTable_RockClimbDust[] = { + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 0), + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 1), + overworld_frame(gFieldEffectObjectPic_RockClimbDust, 4, 4, 2), +}; +const struct SpriteTemplate gFieldEffectObjectTemplate_RockClimbDust = { + .tileTag = 0xFFFF, + .paletteTag = FLDEFF_PAL_TAG_DUST_CLOUD, + .oam = &gObjectEventBaseOam_32x32, + .anims = sAnimTable_RockClimbDust, + .images = sPicTable_RockClimbDust, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = UpdateJumpImpactEffect, +}; + +const struct SpritePalette gSpritePalette_BigDust = {gFieldEffectPal_DustCloud, FLDEFF_PAL_TAG_DUST_CLOUD}; diff --git a/src/data/object_events/movement_action_func_tables.h b/src/data/object_events/movement_action_func_tables.h index 44639b6c9b..686e468fca 100755 --- a/src/data/object_events/movement_action_func_tables.h +++ b/src/data/object_events/movement_action_func_tables.h @@ -287,6 +287,12 @@ u8 MovementAction_SurfStillLeft_Step0(struct ObjectEvent *objectEvent, struct Sp u8 MovementAction_SurfStillLeft_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite); u8 MovementAction_SurfStillRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite); u8 MovementAction_SurfStillRight_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite); +//fast diagonal +u8 MovementAction_WalkFastDiagonalUpLeft_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalUpRight_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalDownLeft_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonalDownRight_Step0(struct ObjectEvent *, struct Sprite *); +u8 MovementAction_WalkFastDiagonal_Step1(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_FaceDown[])(struct ObjectEvent *, struct Sprite *); @@ -463,6 +469,12 @@ u8 (*const gMovementActionFuncs_SurfStillDown[])(struct ObjectEvent *, struct Sp u8 (*const gMovementActionFuncs_SurfStillUp[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_SurfStillLeft[])(struct ObjectEvent *, struct Sprite *); u8 (*const gMovementActionFuncs_SurfStillRight[])(struct ObjectEvent *, struct Sprite *); +//fast diagonal +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpLeft[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpRight[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownLeft[])(struct ObjectEvent *, struct Sprite *); +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownRight[])(struct ObjectEvent *, struct Sprite *); + u8 (*const *const gMovementActionFuncs[])(struct ObjectEvent *, struct Sprite *) = { [MOVEMENT_ACTION_FACE_DOWN] = gMovementActionFuncs_FaceDown, @@ -639,6 +651,12 @@ u8 (*const *const gMovementActionFuncs[])(struct ObjectEvent *, struct Sprite *) [MOVEMENT_ACTION_SURF_STILL_UP] = gMovementActionFuncs_SurfStillUp, [MOVEMENT_ACTION_SURF_STILL_LEFT] = gMovementActionFuncs_SurfStillLeft, [MOVEMENT_ACTION_SURF_STILL_RIGHT] = gMovementActionFuncs_SurfStillRight, + //fast diagonal + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT] = gMovementActionFuncs_WalkFastDiagonalUpLeft, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT] = gMovementActionFuncs_WalkFastDiagonalUpRight, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT] = gMovementActionFuncs_WalkFastDiagonalDownLeft, + [MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT] = gMovementActionFuncs_WalkFastDiagonalDownRight, + }; u8 (*const gMovementActionFuncs_FaceDown[])(struct ObjectEvent *, struct Sprite *) = { @@ -1676,3 +1694,28 @@ u8 (*const gMovementActionFuncs_SurfStillRight[])(struct ObjectEvent *, struct S MovementAction_SurfStillRight_Step1, MovementAction_PauseSpriteAnim, }; +// fast diagonal +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpLeft[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalUpLeft_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalUpRight[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalUpRight_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownLeft[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalDownLeft_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + +u8 (*const gMovementActionFuncs_WalkFastDiagonalDownRight[])(struct ObjectEvent *, struct Sprite *) = { + MovementAction_WalkFastDiagonalDownRight_Step0, + MovementAction_WalkFastDiagonal_Step1, + MovementAction_PauseSpriteAnim, +}; + diff --git a/src/data/object_events/object_event_graphics.h b/src/data/object_events/object_event_graphics.h index c7b92def91..e3d2c674ad 100755 --- a/src/data/object_events/object_event_graphics.h +++ b/src/data/object_events/object_event_graphics.h @@ -286,6 +286,8 @@ const u32 gObjectEventPic_CustapBerryTree[] = INCBIN_U32("graphics/object_events const u32 gObjectEventPic_JabocaBerryTree[] = INCBIN_U32("graphics/object_events/pics/berry_trees/jaboca.4bpp"); const u32 gObjectEventPic_RowapBerryTree[] = INCBIN_U32("graphics/object_events/pics/berry_trees/rowap.4bpp"); const u32 gFieldEffectObjectPic_SurfBlob[] = INCBIN_U32("graphics/field_effects/pics/surf_blob.4bpp"); +const u32 gFieldEffectObjectPic_RockClimbBlob[] = INCBIN_U32("graphics/field_effects/pics/rock_climb_blob.4bpp"); +const u32 gFieldEffectObjectPic_RockClimbDust[] = INCBIN_U32("graphics/field_effects/pics/rock_climb_dust.4bpp"); const u32 gObjectEventPic_QuintyPlump[] = INCBIN_U32("graphics/object_events/pics/people/quinty_plump.4bpp"); const u16 gObjectEventPal_QuintyPlump[] = INCBIN_U16("graphics/object_events/palettes/quinty_plump.gbapal"); const u16 gObjectEventPal_QuintyPlumpReflection[] = INCBIN_U16("graphics/object_events/palettes/quinty_plump_reflection.gbapal"); @@ -330,6 +332,7 @@ const u32 gFieldEffectObjectPic_MountainDisguise[] = INCBIN_U32("graphics/field_ const u32 gFieldEffectObjectPic_SandDisguisePlaceholder[] = INCBIN_U32("graphics/field_effects/pics/sand_disguise_placeholder.4bpp"); const u32 gFieldEffectObjectPic_HotSpringsWater[] = INCBIN_U32("graphics/field_effects/pics/hot_springs_water.4bpp"); const u16 gFieldEffectPal_Ash[] = INCBIN_U16("graphics/field_effects/palettes/ash.gbapal"); +const u16 gFieldEffectPal_DustCloud[] = INCBIN_U16("graphics/field_effects/palettes/big_dust.gbapal"); const u32 gFieldEffectObjectPic_AshPuff[] = INCBIN_U32("graphics/field_effects/pics/ash_puff.4bpp"); const u32 gFieldEffectObjectPic_AshLaunch[] = INCBIN_U32("graphics/field_effects/pics/ash_launch.4bpp"); const u32 gFieldEffectObjectPic_Bubbles[] = INCBIN_U32("graphics/field_effects/pics/bubbles.4bpp"); diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 7f4e7ec142..a91bb04b25 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -820,10 +820,10 @@ static const u8 sJumpSpecialDirectionAnimNums[] = { // used for jumping onto sur [DIR_NORTH] = ANIM_GET_ON_OFF_POKEMON_NORTH, [DIR_WEST] = ANIM_GET_ON_OFF_POKEMON_WEST, [DIR_EAST] = ANIM_GET_ON_OFF_POKEMON_EAST, - [DIR_SOUTHWEST] = ANIM_GET_ON_OFF_POKEMON_SOUTH, - [DIR_SOUTHEAST] = ANIM_GET_ON_OFF_POKEMON_SOUTH, - [DIR_NORTHWEST] = ANIM_GET_ON_OFF_POKEMON_NORTH, - [DIR_NORTHEAST] = ANIM_GET_ON_OFF_POKEMON_NORTH, + [DIR_SOUTHWEST] = ANIM_GET_ON_OFF_POKEMON_WEST, + [DIR_SOUTHEAST] = ANIM_GET_ON_OFF_POKEMON_EAST, + [DIR_NORTHWEST] = ANIM_GET_ON_OFF_POKEMON_WEST, + [DIR_NORTHEAST] = ANIM_GET_ON_OFF_POKEMON_EAST, }; static const u8 sAcroWheelieDirectionAnimNums[] = { [DIR_NONE] = ANIM_BUNNY_HOP_BACK_WHEEL_SOUTH, @@ -1068,6 +1068,10 @@ const u8 gJumpSpecialMovementActions[] = { MOVEMENT_ACTION_JUMP_SPECIAL_UP, MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, + MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, + MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, + MOVEMENT_ACTION_JUMP_SPECIAL_LEFT, + MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT, }; const u8 gWalkInPlaceSlowMovementActions[] = { [DIR_NONE] = MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_DOWN, @@ -11353,6 +11357,41 @@ bool8 MovementAction_WalkSlowStairsUp_Step1(struct ObjectEvent *objectEvent, str return FALSE; } +// fast diagonal +bool8 MovementAction_WalkFastDiagonalUpLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + InitMovementNormal(objectEvent, sprite, DIR_NORTHWEST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalUpRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + InitMovementNormal(objectEvent, sprite, DIR_NORTHEAST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalDownLeft_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + InitMovementNormal(objectEvent, sprite, DIR_SOUTHWEST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonalDownRight_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + InitMovementNormal(objectEvent, sprite, DIR_SOUTHEAST, 1); + return MovementAction_WalkFastDiagonal_Step1(objectEvent, sprite); +} + +bool8 MovementAction_WalkFastDiagonal_Step1(struct ObjectEvent *objectEvent, struct Sprite *sprite) +{ + if (UpdateMovementNormal(objectEvent, sprite)) + { + sprite->data[2] = 2; + return TRUE; + } + return FALSE; +} + bool8 MovementAction_WalkSlowStairsDown_Step0(struct ObjectEvent *objectEvent, struct Sprite *sprite) { InitWalkSlow(objectEvent, sprite, DIR_SOUTH); diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index ebcd775ed9..f35c349fc6 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -13,6 +13,7 @@ #include "field_control_avatar.h" #include "field_message_box.h" #include "field_move.h" +#include "field_effect.h" #include "field_player_avatar.h" #include "field_poison.h" #include "field_screen_effect.h" @@ -521,6 +522,8 @@ static const u8 *GetInteractedMetatileScript(struct MapPosition *position, u8 me SetMsgSignPostAndVarFacing(direction); return Common_EventScript_ShowPokemonCenterSign; } + if (MetatileBehavior_IsRockClimbable(metatileBehavior) == TRUE && !IsRockClimbActive()) + return EventScript_UseRockClimb; elevation = position->elevation; if (elevation == MapGridGetElevationAt(position->x, position->y)) diff --git a/src/field_effect.c b/src/field_effect.c index 5cdc3472fb..8a11f56a68 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -245,6 +245,18 @@ static void UseVsSeeker_DoPlayerAnimation(struct Task *task); static void UseVsSeeker_ResetPlayerGraphics(struct Task *task); static void UseVsSeeker_CleanUpFieldEffect(struct Task *task); +static void Task_UseRockClimb(u8); +static bool8 RockClimb_Init(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_FieldMovePose(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_ShowMon(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_JumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_WaitJumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_Ride(struct Task *task, struct ObjectEvent *objectEvent); +//static bool8 RockClimb_RideUp(struct Task *, struct ObjectEvent *); +//static bool8 RockClimb_RideDown(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_ContinueRideOrEnd(struct Task *, struct ObjectEvent *); +static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent *objectEvent); +static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent *objectEvent); // Static RAM declarations static u8 sActiveList[32]; @@ -1987,7 +1999,7 @@ static bool8 WaterfallFieldEffect_ContinueRideOrEnd(struct Task *task, struct Ob { if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) return FALSE; - + if (MetatileBehavior_IsWaterfall(objectEvent->currentMetatileBehavior)) { // Still ascending waterfall, back to WaterfallFieldEffect_RideUp @@ -4156,6 +4168,263 @@ u8 FldEff_CaveDust(void) return spriteId; } +// ROCK CLIMB +enum RockClimbState +{ + STATE_ROCK_CLIMB_INIT, + STATE_ROCK_CLIMB_POSE, + STATE_ROCK_CLIMB_SHOW_MON, + STATE_ROCK_CLIMB_JUMP_ON, + STATE_ROCK_CLIMB_WAIT_JUMP, + STATE_ROCK_CLIMB_RIDE, + STATE_ROCK_CLIMB_CONTINUE_RIDE, + STATE_ROCK_CLIMB_STOP_INIT, + STATE_ROCK_CLIMB_WAIT_STOP +}; + +#define tState data[0] +#define tDestX data[1] +#define tDestY data[2] +#define tMonId data[15] + +static u8 CreateRockClimbBlob(void) +{ + u8 spriteId; + struct Sprite *sprite; + + SetSpritePosToOffsetMapCoords((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_ROCK_CLIMB_BLOB], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x96); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.paletteNum = LoadPlayerObjectEventPalette(gSaveBlock2Ptr->playerGender); + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = -1; + sprite->data[6] = -1; + sprite->data[7] = -1; + } + + return spriteId; +} + +bool8 (*const sRockClimbFieldEffectFuncs[])(struct Task *, struct ObjectEvent *) = +{ + [STATE_ROCK_CLIMB_INIT] = RockClimb_Init, + [STATE_ROCK_CLIMB_POSE] = RockClimb_FieldMovePose, + [STATE_ROCK_CLIMB_SHOW_MON] = RockClimb_ShowMon, + [STATE_ROCK_CLIMB_JUMP_ON] = RockClimb_JumpOnRockClimbBlob, + [STATE_ROCK_CLIMB_WAIT_JUMP] = RockClimb_WaitJumpOnRockClimbBlob, + [STATE_ROCK_CLIMB_RIDE] = RockClimb_Ride, + [STATE_ROCK_CLIMB_CONTINUE_RIDE] = RockClimb_ContinueRideOrEnd, + [STATE_ROCK_CLIMB_STOP_INIT] = RockClimb_StopRockClimbInit, + [STATE_ROCK_CLIMB_WAIT_STOP] = RockClimb_WaitStopRockClimb +}; + +bool8 FldEff_UseRockClimb(void) +{ + u8 taskId; + taskId = CreateTask(Task_UseRockClimb, 0xff); + gTasks[taskId].tMonId = gFieldEffectArguments[0]; + Task_UseRockClimb(taskId); + return FALSE; +} + +static void Task_UseRockClimb(u8 taskId) +{ + while (sRockClimbFieldEffectFuncs[gTasks[taskId].tState](&gTasks[taskId], &gObjectEvents[gPlayerAvatar.objectEventId])); +} + +static bool8 RockClimb_Init(struct Task *task, struct ObjectEvent *objectEvent) +{ + LockPlayerFieldControls(); + FreezeObjectEvents(); + // Put follower into pokeball before using Rock Climb + HideFollowerForFieldEffect(); + gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_SURFING); + PlayerGetDestCoords(&task->tDestX, &task->tDestY); + MoveCoords(gObjectEvents[gPlayerAvatar.objectEventId].movementDirection, &task->tDestX, &task->tDestY); + task->tState++; + return FALSE; +} + +static bool8 RockClimb_FieldMovePose(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!ObjectEventIsMovementOverridden(objectEvent) || ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + SetPlayerAvatarFieldMove(); + ObjectEventSetHeldMovement(objectEvent, MOVEMENT_ACTION_START_ANIM_IN_DIRECTION); + task->tState++; + } + return FALSE; +} + +static bool8 RockClimb_ShowMon(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventCheckHeldMovementStatus(objectEvent)) + { + gFieldEffectArguments[0] = task->tMonId | 0x80000000; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->tState++; + return TRUE; + } + return FALSE; +} + +static bool8 RockClimb_JumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + objectEvent->noShadow = TRUE; // hide shadow + ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_SURFING)); + ObjectEventClearHeldMovementIfFinished(objectEvent); + ObjectEventSetHeldMovement(objectEvent, GetJumpSpecialMovementAction(objectEvent->movementDirection)); + gFieldEffectArguments[0] = task->tDestX; + gFieldEffectArguments[1] = task->tDestY; + gFieldEffectArguments[2] = gPlayerAvatar.objectEventId; + objectEvent->fieldEffectSpriteId = CreateRockClimbBlob(); + task->tState++; + } + + return FALSE; +} + +static bool8 RockClimb_WaitJumpOnRockClimbBlob(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_PLAYER_AND_MON); + switch (objectEvent->facingDirection) + { + case DIR_EAST: + //check southeast then northeast + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX + 1, task->tDestY + 1))) + objectEvent->movementDirection = DIR_SOUTHEAST; + else if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX + 1, task->tDestY - 1))) + objectEvent->movementDirection = DIR_NORTHEAST; + break; + case DIR_WEST: + //check northwest then southwest + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX - 1, task->tDestY - 1))) + objectEvent->movementDirection = DIR_NORTHWEST; + else if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX - 1, task->tDestY + 1))) + objectEvent->movementDirection = DIR_SOUTHWEST; + break; + } + + task->tState = STATE_ROCK_CLIMB_CONTINUE_RIDE; + } + + return FALSE; +} + +struct RockClimbRide +{ + u8 action; + s8 dx; + s8 dy; + u8 jumpDir; +}; +static const struct RockClimbRide sRockClimbMovement[] = +{ + [DIR_NONE] = {MOVEMENT_ACTION_WALK_FAST_DOWN, 0, 0, DIR_NONE}, + [DIR_SOUTH] = {MOVEMENT_ACTION_WALK_FAST_DOWN, 0, -1, DIR_SOUTH}, + [DIR_NORTH] = {MOVEMENT_ACTION_WALK_FAST_UP, 0, 1, DIR_NORTH}, + [DIR_WEST] = {MOVEMENT_ACTION_WALK_FAST_LEFT, 1, 1, DIR_WEST}, + [DIR_EAST] = {MOVEMENT_ACTION_WALK_FAST_RIGHT, -1, -1, DIR_EAST}, + [DIR_SOUTHWEST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_LEFT, 1, -1, DIR_WEST}, + [DIR_SOUTHEAST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_DOWN_RIGHT, -1, -1, DIR_EAST}, + [DIR_NORTHWEST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_LEFT, 1, 1, DIR_WEST}, + [DIR_NORTHEAST] = {MOVEMENT_ACTION_WALK_FAST_DIAGONAL_UP_RIGHT, -1, 1, DIR_EAST}, +}; + +static void RockClimbDust(struct ObjectEvent *objectEvent, u8 direction) +{ + s8 dx = sRockClimbMovement[direction].dx; + s8 dy = sRockClimbMovement[direction].dy; + + gFieldEffectArguments[0] = objectEvent->currentCoords.x + dx; + gFieldEffectArguments[1] = objectEvent->currentCoords.y + dy; + gFieldEffectArguments[2] = objectEvent->previousElevation; + gFieldEffectArguments[3] = gSprites[objectEvent->spriteId].oam.priority; + FieldEffectStart(FLDEFF_ROCK_CLIMB_DUST); +} + +static bool8 RockClimb_Ride(struct Task *task, struct ObjectEvent *objectEvent) +{ + ObjectEventSetHeldMovement(objectEvent, sRockClimbMovement[objectEvent->movementDirection].action); + PlaySE(SE_M_ROCK_THROW); + RockClimbDust(objectEvent, objectEvent->movementDirection); + task->tState++; + return FALSE; +} + +static bool8 RockClimb_ContinueRideOrEnd(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) + return FALSE; + + PlayerGetDestCoords(&task->tDestX, &task->tDestY); + MoveCoords(objectEvent->movementDirection, &task->tDestX, &task->tDestY); + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(task->tDestX, task->tDestY))) + { + task->tState = STATE_ROCK_CLIMB_RIDE; + return TRUE; + } + + LockPlayerFieldControls(); + gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_SURFING; + gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_ON_FOOT; + task->tState++; + return FALSE; +} + +static bool8 RockClimb_StopRockClimbInit(struct Task *task, struct ObjectEvent *objectEvent) +{ + if (ObjectEventIsMovementOverridden(objectEvent)) + { + if (!ObjectEventClearHeldMovementIfFinished(objectEvent)) + return FALSE; + } + + RockClimbDust(objectEvent, DIR_NONE); //dust on final spot + ObjectEventSetHeldMovement(objectEvent, GetJumpSpecialMovementAction(sRockClimbMovement[objectEvent->movementDirection].jumpDir)); + SetSurfBlob_BobState(objectEvent->fieldEffectSpriteId, BOB_NONE); + task->tState++; + return TRUE; +} + +static bool8 RockClimb_WaitStopRockClimb(struct Task *task, struct ObjectEvent *objectEvent) +{ + struct ObjectEvent *followerObject = GetFollowerObject(); + if (ObjectEventClearHeldMovementIfFinished(objectEvent)) + { + ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_NORMAL)); + ObjectEventSetHeldMovement(objectEvent, GetFaceDirectionMovementAction(objectEvent->facingDirection)); + gPlayerAvatar.preventStep = FALSE; + if (followerObject) + ObjectEventClearHeldMovementIfFinished(followerObject); // restore follower to normal + objectEvent->noShadow = FALSE; // restore shadow + UnfreezeObjectEvents(); + UnlockPlayerFieldControls(); + DestroySprite(&gSprites[objectEvent->fieldEffectSpriteId]); + FieldEffectActiveListRemove(FLDEFF_USE_ROCK_CLIMB); + objectEvent->triggerGroundEffectsOnMove = TRUE; // e.g. if dismount on grass + DestroyTask(FindTaskIdByFunc(Task_UseRockClimb)); + } + + return FALSE; +} + +bool8 IsRockClimbActive(void) +{ + if (FieldEffectActiveListContains(FLDEFF_USE_ROCK_CLIMB)) + return TRUE; + else + return FALSE; +} + #undef tState #undef tSpriteId #undef tTargetX diff --git a/src/field_effect_helpers.c b/src/field_effect_helpers.c index f7a6531ec2..2e9e1a8510 100755 --- a/src/field_effect_helpers.c +++ b/src/field_effect_helpers.c @@ -1263,10 +1263,10 @@ static void SynchroniseSurfAnim(struct ObjectEvent *playerObj, struct Sprite *sp [DIR_NORTH] = 1, [DIR_WEST] = 2, [DIR_EAST] = 3, - [DIR_SOUTHWEST] = 0, - [DIR_SOUTHEAST] = 0, - [DIR_NORTHWEST] = 1, - [DIR_NORTHEAST] = 1, + [DIR_SOUTHWEST] = 2, + [DIR_SOUTHEAST] = 3, + [DIR_NORTHWEST] = 2, + [DIR_NORTHEAST] = 3, }; if (!GetSurfBlob_DontSyncAnim(sprite)) @@ -1389,6 +1389,24 @@ u32 FldEff_Dust(void) return 0; } +u32 FldEff_RockClimbDust(void) +{ + u8 spriteId; + struct Sprite *sprite; + + SetSpritePosToOffsetMapCoords((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[FLDEFFOBJ_ROCK_CLIMB_DUST], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = FLDEFF_ROCK_CLIMB_DUST; + } + return 0; +} + // Sprite data for FLDEFF_SAND_PILE #define sLocalId data[0] #define sMapNum data[1] diff --git a/src/field_move.c b/src/field_move.c index ff9c986436..49c81bec9a 100644 --- a/src/field_move.c +++ b/src/field_move.c @@ -48,6 +48,13 @@ static bool32 IsFieldMoveUnlocked_Waterfall(void) return FlagGet(FLAG_BADGE08_GET); } +#if OW_ROCK_CLIMB_FIELD_MOVE == TRUE +static bool32 IsFieldMoveUnlocked_RockClimb(void) +{ + return TRUE; +} +#endif + static bool32 IsFieldMoveUnlocked_Teleport(void) { return TRUE; @@ -198,7 +205,15 @@ const struct FieldMoveInfo gFieldMoveInfo[FIELD_MOVES_COUNT] = .moveID = MOVE_SWEET_SCENT, .partyMsgID = PARTY_MSG_CANT_USE_HERE, }, - +#if OW_ROCK_CLIMB_FIELD_MOVE == TRUE + [FIELD_MOVE_ROCK_CLIMB] = + { + .fieldMoveFunc = SetUpFieldMove_RockClimb, + .isUnlockedFunc = IsFieldMoveUnlocked_RockClimb, + .moveID = MOVE_ROCK_CLIMB, + .partyMsgID = PARTY_MSG_CANT_USE_HERE, + }, +#endif #if OW_DEFOG_FIELD_MOVE == TRUE [FIELD_MOVE_DEFOG] = { @@ -208,5 +223,4 @@ const struct FieldMoveInfo gFieldMoveInfo[FIELD_MOVES_COUNT] = .partyMsgID = PARTY_MSG_CANT_USE_HERE, }, #endif - }; diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c index 2d61e9a75a..687b98ca27 100644 --- a/src/metatile_behavior.c +++ b/src/metatile_behavior.c @@ -133,6 +133,7 @@ static const u8 sTileBitAttributes[NUM_METATILE_BEHAVIORS] = [MB_SIDEWAYS_STAIRS_RIGHT_SIDE_BOTTOM] = TILE_FLAG_UNUSED, [MB_SIDEWAYS_STAIRS_LEFT_SIDE_BOTTOM] = TILE_FLAG_UNUSED, [MB_ROCK_STAIRS] = TILE_FLAG_UNUSED, + [MB_ROCK_CLIMB] = TILE_FLAG_UNUSED, }; bool8 MetatileBehavior_IsATile(u8 metatileBehavior) @@ -1542,3 +1543,11 @@ bool8 MetatileBehavior_IsRockStairs(u8 metatileBehavior) else return FALSE; } + +bool8 MetatileBehavior_IsRockClimbable(u8 metatileBehavior) +{ + if (metatileBehavior == MB_ROCK_CLIMB) + return TRUE; + else + return FALSE; +} diff --git a/src/party_menu.c b/src/party_menu.c index 71464969ba..9b48152b9b 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -489,6 +489,7 @@ void TryItemHoldFormChange(struct Pokemon *mon, s8 slotId); static void ShowMoveSelectWindow(u8 slot); static void Task_HandleWhichMoveInput(u8 taskId); static void Task_HideFollowerNPCForTeleport(u8); +static void FieldCallback_RockClimb(void); // static const data #include "data/party_menu.h" @@ -4194,6 +4195,21 @@ bool32 SetUpFieldMove_Waterfall(void) return FALSE; } +bool32 SetUpFieldMove_RockClimb(void) +{ + s16 x, y; + + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + if (MetatileBehavior_IsRockClimbable(MapGridGetMetatileBehaviorAt(x, y))) + { + gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu; + gPostMenuFieldCallback = FieldCallback_RockClimb; + return TRUE; + } + + return FALSE; +} + static void FieldCallback_Dive(void) { gFieldEffectArguments[0] = GetCursorSelectionMonId(); @@ -7997,3 +8013,10 @@ void CursorCb_MoveItem(u8 taskId) gTasks[taskId].func = Task_UpdateHeldItemSprite; } } + +static void FieldCallback_RockClimb(void) +{ + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + FieldEffectStart(FLDEFF_USE_ROCK_CLIMB); +} +