Added movements/scripts for overworld follower field moves.

This commit is contained in:
Ariel A 2022-12-18 18:02:07 -05:00
parent e6d1cfae24
commit beb282a359
4 changed files with 180 additions and 30 deletions

View File

@ -11,27 +11,26 @@ EventScript_CutTree::
goto_if_eq VAR_RESULT, NO, EventScript_CancelCut
msgbox Text_MonUsedFieldMove, MSGBOX_DEFAULT
closemessage
EventScript_CutTreeCommon:
callfunc ScrFunc_IsFollowerFieldMoveUser
.2byte VAR_0x8004
setfieldeffectargument 3, VAR_0x8004 @ skip pose if so
dofieldeffect FLDEFF_USE_CUT_ON_TREE
waitstate
goto EventScript_CutTreeDown
end
@ Use cut from party menu
EventScript_UseCut::
lockall
dofieldeffect FLDEFF_USE_CUT_ON_TREE
waitstate
goto EventScript_CutTreeDown
end
EventScript_CutTreeDown::
setflag FLAG_SAFE_FOLLOWER_MOVEMENT
EventScript_CutTreeDown:: @ fallthrough
setflag FLAG_SAFE_FOLLOWER_MOVEMENT
call_if_eq VAR_0x8004, TRUE, EventScript_FollowerFieldMove
applymovement VAR_LAST_TALKED, Movement_CutTreeDown
waitmovement 0
removeobject VAR_LAST_TALKED
releaseall
end
@ Use cut from party menu
EventScript_UseCut::
lockall
goto EventScript_CutTreeCommon
Movement_CutTreeDown:
cut_tree
step_end
@ -58,6 +57,11 @@ Text_CantCut:
.string "This tree looks like it can be\n"
.string "CUT down!$"
@ Use rock smash from party menu
EventScript_UseRockSmash::
lockall
goto EventScript_RockSmashCommon
@ Interact with smashable rock
EventScript_RockSmash::
lockall
@ -71,20 +75,16 @@ EventScript_RockSmash::
goto_if_eq VAR_RESULT, NO, EventScript_CancelSmash
msgbox Text_MonUsedFieldMove, MSGBOX_DEFAULT
closemessage
EventScript_RockSmashCommon:
@ check if follower should use the field move
callfunc ScrFunc_IsFollowerFieldMoveUser
.2byte VAR_0x8004
setfieldeffectargument 3, VAR_0x8004 @ skip pose if so
dofieldeffect FLDEFF_USE_ROCK_SMASH
waitstate
goto EventScript_SmashRock
end
@ Use rock smash from party menu
EventScript_UseRockSmash::
lockall
dofieldeffect FLDEFF_USE_ROCK_SMASH
waitstate
goto EventScript_SmashRock
end
EventScript_SmashRock::
EventScript_SmashRock:: @ fallthrough
setflag FLAG_SAFE_FOLLOWER_MOVEMENT
call_if_eq VAR_0x8004, TRUE, EventScript_FollowerFieldMove
applymovement VAR_LAST_TALKED, Movement_SmashRock
waitmovement 0
removeobject VAR_LAST_TALKED
@ -96,10 +96,120 @@ EventScript_SmashRock::
releaseall
end
EventScript_FollowerFieldMove:
callfunc ScrFunc_GetDirectionToFace
.2byte VAR_0x8005
.byte OBJ_EVENT_ID_FOLLOWER
.byte OBJ_EVENT_ID_PLAYER
specialvar VAR_0x8006, GetPlayerFacingDirection
goto_if_eq VAR_0x8005, DIR_NONE, EventScript_FollowerFieldMoveEnd
@ Swap follower and player
call EventScript_FollowerSwap
@ Face follower in direction and jump
switch VAR_0x8006
case DIR_NORTH, EventScript_FollowerJumpNorth
case DIR_EAST, EventScript_FollowerJumpEast
case DIR_SOUTH, EventScript_FollowerJumpSouth
case DIR_WEST, EventScript_FollowerJumpWest
EventScript_FollowerFieldMoveEnd:
return
EventScript_FollowerSwap:
switch VAR_0x8005
case DIR_NORTH, EventScript_FollowerMoveNorth
case DIR_EAST, EventScript_FollowerMoveEast
case DIR_SOUTH, EventScript_FollowerMoveSouth
case DIR_WEST, EventScript_FollowerMoveWest
return
EventScript_FollowerMoveNorth:
applymovement OBJ_EVENT_ID_FOLLOWER, Movement_WalkUp
applymovement OBJ_EVENT_ID_PLAYER, Movement_WalkDown
waitmovement 0
applymovement OBJ_EVENT_ID_PLAYER, Common_Movement_FaceUp
waitmovement 0
return
EventScript_FollowerMoveEast:
applymovement OBJ_EVENT_ID_FOLLOWER, Movement_WalkRight
applymovement OBJ_EVENT_ID_PLAYER, Movement_WalkLeft
waitmovement 0
applymovement OBJ_EVENT_ID_PLAYER, Common_Movement_FaceRight
waitmovement 0
return
EventScript_FollowerMoveSouth:
applymovement OBJ_EVENT_ID_FOLLOWER, Movement_WalkDown
applymovement OBJ_EVENT_ID_PLAYER, Movement_WalkUp
waitmovement 0
applymovement OBJ_EVENT_ID_PLAYER, Common_Movement_FaceDown
waitmovement 0
return
EventScript_FollowerMoveWest:
applymovement OBJ_EVENT_ID_FOLLOWER, Movement_WalkLeft
applymovement OBJ_EVENT_ID_PLAYER, Movement_WalkRight
waitmovement 0
applymovement OBJ_EVENT_ID_PLAYER, Common_Movement_FaceLeft
waitmovement 0
return
EventScript_FollowerJumpNorth:
applymovement OBJ_EVENT_ID_FOLLOWER, Movement_JumpUp
waitmovement 0
return
EventScript_FollowerJumpEast:
applymovement OBJ_EVENT_ID_FOLLOWER, Movement_JumpRight
waitmovement 0
return
EventScript_FollowerJumpSouth:
applymovement OBJ_EVENT_ID_FOLLOWER, Movement_JumpDown
waitmovement 0
return
EventScript_FollowerJumpWest:
applymovement OBJ_EVENT_ID_FOLLOWER, Movement_JumpLeft
waitmovement 0
return
EventScript_EndSmash::
releaseall
end
Movement_WalkUp:
walk_up
step_end
Movement_JumpUp:
jump_in_place_up
step_end
Movement_WalkRight:
walk_right
step_end
Movement_JumpRight:
jump_in_place_right
step_end
Movement_WalkDown:
walk_down
step_end
Movement_JumpDown:
jump_in_place_down
step_end
Movement_WalkLeft:
walk_left
step_end
Movement_JumpLeft:
jump_in_place_left
step_end
Movement_SmashRock:
rock_smash_break
step_end

View File

@ -5492,6 +5492,41 @@ u8 GetDirectionToFace(s16 x, s16 y, s16 targetX, s16 targetY)
return DIR_SOUTH;
}
// Uses the above, but script accessible, and uses localIds
bool8 ScrFunc_GetDirectionToFace(struct ScriptContext *ctx) {
u16 *var = GetVarPointer(ScriptReadHalfword(ctx));
u8 id0 = GetObjectEventIdByLocalId(ScriptReadByte(ctx)); // source
u8 id1 = GetObjectEventIdByLocalId(ScriptReadByte(ctx)); // target
if (var == NULL)
return FALSE;
if (id0 >= OBJECT_EVENTS_COUNT || id1 >= OBJECT_EVENTS_COUNT)
*var = DIR_NONE;
else
*var = GetDirectionToFace(
gObjectEvents[id0].currentCoords.x,
gObjectEvents[id0].currentCoords.y,
gObjectEvents[id1].currentCoords.x,
gObjectEvents[id1].currentCoords.y);
return FALSE;
}
// Whether following pokemon is also the user of the field move
// Intended to be called before the field effect itself
bool8 ScrFunc_IsFollowerFieldMoveUser(struct ScriptContext *ctx) {
u16 *var = GetVarPointer(ScriptReadHalfword(ctx));
u16 userIndex = gFieldEffectArguments[0]; // field move user index
struct Pokemon *follower = GetFirstLiveMon();
struct ObjectEvent *obj = GetFollowerObject();
if (var == NULL)
return FALSE;
*var = FALSE;
if (follower && obj && !obj->invisible) {
u16 followIndex = ((u32)follower - (u32)gPlayerParty) / sizeof(struct Pokemon);
*var = userIndex == followIndex;
} else
return FALSE;
}
void SetTrainerMovementType(struct ObjectEvent *objectEvent, u8 movementType)
{
objectEvent->movementType = movementType;

View File

@ -61,9 +61,11 @@ static void Task_DoFieldMove_Init(u8 taskId)
if (!ObjectEventIsMovementOverridden(&gObjectEvents[objEventId])
|| ObjectEventClearHeldMovementIfFinished(&gObjectEvents[objEventId]))
{
if (gMapHeader.mapType == MAP_TYPE_UNDERWATER)
if (gMapHeader.mapType == MAP_TYPE_UNDERWATER || gFieldEffectArguments[3])
{
// Skip field move pose underwater
// Skip field move pose underwater, or if arg3 is nonzero
if (gFieldEffectArguments[3])
gFieldEffectArguments[3] = 0;
FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT);
gTasks[taskId].func = Task_DoFieldMove_WaitForMon;
}

View File

@ -53,7 +53,6 @@
typedef u16 (*SpecialFunc)(void);
typedef void (*NativeFunc)(void);
typedef bool8 (*ScrFunc)(struct ScriptContext*);
EWRAM_DATA const u8 *gRamScriptRetAddr = NULL;
static EWRAM_DATA u32 sAddressOffset = 0; // For relative addressing in vgoto etc., used by saved scripts (e.g. Mystery Event)
@ -144,7 +143,7 @@ bool8 ScrCmd_callnative(struct ScriptContext *ctx)
bool8 ScrCmd_callfunc(struct ScriptContext *ctx)
{
u32 func = ScriptReadWord(ctx);
return ((ScrFunc) func)(ctx);
return ((ScrCmdFunc) func)(ctx);
}
bool8 ScrCmd_waitstate(struct ScriptContext *ctx)
@ -1004,7 +1003,11 @@ bool8 ScrCmd_applymovement(struct ScriptContext *ctx)
const void *movementScript = (const void *)ScriptReadWord(ctx);
struct ObjectEvent *objEvent;
// When applying script movements to follower, it may have frozen animation that must be cleared
if (localId == OBJ_EVENT_ID_FOLLOWER && (objEvent = GetFollowerObject()) && objEvent->frozen) {
ClearObjectEventMovement(objEvent, &gSprites[objEvent->spriteId]);
gSprites[objEvent->spriteId].animCmdIndex = 0; // Needed to set start frame of animation
}
ScriptMovement_StartObjectMovementScript(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, movementScript);
sMovingNpcId = localId;
if (localId != OBJ_EVENT_ID_FOLLOWER && !FlagGet(FLAG_SAFE_FOLLOWER_MOVEMENT)) { // Force follower into pokeball