Rock climb by ghoulslash (#7432)

Co-authored-by: Evan <eroelke@gmail.com>
Co-authored-by: Jaizu <jaizu85@gmail.com>
Co-authored-by: ghoulslash <41651341+ghoulslash@users.noreply.github.com>
Co-authored-by: ghoulslash <pokevoyager0@gmail.com>
Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
This commit is contained in:
pokesidv
2025-08-03 14:52:07 +02:00
committed by GitHub
parent 3841fee888
commit 4d31693005
26 changed files with 567 additions and 13 deletions

View File

@@ -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

View File

@@ -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.$"

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
};

View File

@@ -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[];

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,
};

View File

@@ -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};

View File

@@ -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,
};

View File

@@ -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");

View File

@@ -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);

View File

@@ -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))

View File

@@ -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

View File

@@ -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]

View File

@@ -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
};

View File

@@ -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;
}

View File

@@ -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);
}