diff --git a/asm/macros/event.inc b/asm/macros/event.inc index e0e221aa2..b021bf177 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1984,3 +1984,8 @@ setvar VAR_UNUSED_0x8014, 0 callnative FollowerIntoPokeball .endm + + .macro setfollowerwarppos pos:req + setvar VAR_RESULT, \pos + callnative SetFollowerWarpPosition + .endm diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 3720c79f4..0104814b3 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -10459,6 +10459,28 @@ u8 MovementAction_FollowingPokemon_Grow_Step1(struct ObjectEvent *objectEvent, s StartFieldEffectForObjectEvent(FLDEFF_FEET_IN_FLOWING_WATER, objectEvent); } gPlayerAvatar.preventStep = FALSE; + + // Account for warps in scripts where the follower needs to pop out of a pokeball afterwards + if (gSaveBlock2Ptr->follower.createSurfBlob == 2) + { + sprite->data[7] = 0; + gSaveBlock2Ptr->follower.createSurfBlob = 0; + switch(gObjectEvents[gPlayerAvatar.objectEventId].facingDirection) + { + case DIR_SOUTH: + ObjectEventForceSetHeldMovement(objectEvent, MOVEMENT_ACTION_FOLLOWING_POKEMON_FACESOUTH); + break; + case DIR_NORTH: + ObjectEventForceSetHeldMovement(objectEvent, MOVEMENT_ACTION_FOLLOWING_POKEMON_FACENORTH); + break; + case DIR_WEST: + ObjectEventForceSetHeldMovement(objectEvent, MOVEMENT_ACTION_FOLLOWING_POKEMON_FACEWEST); + break; + case DIR_EAST: + ObjectEventForceSetHeldMovement(objectEvent, MOVEMENT_ACTION_FOLLOWING_POKEMON_FACEEAST); + break; + } + } sprite->data[2]++; } diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index 69fab048a..9ac3085ee 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -161,8 +161,10 @@ int ProcessPlayerFieldInput(struct FieldInput *input) if (TryStartStepBasedScript(&position, metatileBehavior, playerDirection) == TRUE) return TRUE; } - else if(gSaveBlock2Ptr->follower.inProgress) + else if(gSaveBlock2Ptr->follower.inProgress && gSaveBlock2Ptr->follower.createSurfBlob != 2) { + // Keep the follower bouncing, unless we're dealing with a follower coming out of a pokeball after a scripted warp. + // Need to stop bouncing to run the grow-out-of-pokeball animation ObjectEventClearHeldMovementIfFinished(&gObjectEvents[gSaveBlock2Ptr->follower.objId]); ObjectEventSetHeldMovement(&gObjectEvents[gSaveBlock2Ptr->follower.objId], 0x9E); } diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 090f920ef..ce4d3ed2f 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -435,7 +435,11 @@ static void Task_ExitNonDoor(u8 taskId) if (WaitForWeatherFadeIn()) { UnfreezeObjectEvents(); - gSaveBlock2Ptr->follower.comeOutDoorStairs = 2; + + // Account for follower exiting pokeball after scripted warp + if (gSaveBlock2Ptr->follower.createSurfBlob != 2) + gSaveBlock2Ptr->follower.comeOutDoorStairs = 2; + UnlockPlayerFieldControls(); DestroyTask(taskId); } @@ -979,7 +983,7 @@ static void Task_SpinEnterWarp(u8 taskId) case 1: if (WaitForWeatherFadeIn() && IsPlayerSpinEntranceActive() != TRUE) { - FollowMe_WarpSetEnd(); + //FollowMe_WarpSetEnd(); UnfreezeObjectEvents(); UnlockPlayerFieldControls(); DestroyTask(taskId); diff --git a/src/follow_me.c b/src/follow_me.c index dbe0ebb2d..31af6212e 100644 --- a/src/follow_me.c +++ b/src/follow_me.c @@ -1528,3 +1528,7 @@ void ShowFollower(void) gObjectEvents[gSaveBlock2Ptr->follower.objId].invisible = FALSE; } +void SetFollowerWarpPosition(void) +{ + gSaveBlock2Ptr->follower.createSurfBlob = 1; +} diff --git a/src/overworld.c b/src/overworld.c index 5cd5b2859..4c8389826 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -1142,6 +1142,44 @@ static void SetPlayerCoordsFromWarp(void) } } +static void SetFollowerCoordsFromWarp(void) +{ + struct ObjectEvent* player = &gObjectEvents[gPlayerAvatar.objectEventId]; + struct ObjectEvent* follower = &gObjectEvents[gSaveBlock2Ptr->follower.objId]; + + gSaveBlock2Ptr->follower.warpEnd = 0; + + // Based on value passed in via setfollowerwarppos macro, place the follower relative to the player. + // If DIR_NONE, then setup for follower popping out of pokeball + switch(gSpecialVar_Result) + { + case DIR_NONE: + MoveObjectEventToMapCoords(follower, player->currentCoords.x, player->currentCoords.y); + gSaveBlock2Ptr->follower.createSurfBlob = 2; + break; + case DIR_SOUTH: + MoveObjectEventToMapCoords(follower, player->currentCoords.x, player->currentCoords.y + 1); + follower->invisible = FALSE; + gSaveBlock2Ptr->follower.createSurfBlob = 0; + break; + case DIR_NORTH: + MoveObjectEventToMapCoords(follower, player->currentCoords.x, player->currentCoords.y - 1); + follower->invisible = FALSE; + gSaveBlock2Ptr->follower.createSurfBlob = 0; + break; + case DIR_WEST: + MoveObjectEventToMapCoords(follower, player->currentCoords.x - 1, player->currentCoords.y); + follower->invisible = FALSE; + gSaveBlock2Ptr->follower.createSurfBlob = 0; + break; + case DIR_EAST: + MoveObjectEventToMapCoords(follower, player->currentCoords.x + 1, player->currentCoords.y); + follower->invisible = FALSE; + gSaveBlock2Ptr->follower.createSurfBlob = 0; + break; + } +} + void WarpIntoMap(void) { ApplyCurrentWarp(); @@ -2109,6 +2147,10 @@ static void CB2_LoadMap2(void) SetFieldVBlankCallback(); SetMainCallback1(CB1_Overworld); SetMainCallback2(CB2_Overworld); + + // Handle placing follower after warp as determined via setfollowerwarppos macro + if (gSaveBlock2Ptr->follower.inProgress && gSaveBlock2Ptr->follower.createSurfBlob == 1) + SetFollowerCoordsFromWarp(); } void CB2_ReturnToFieldContestHall(void) @@ -2497,6 +2539,12 @@ static bool32 ReturnToFieldLocal(u8 *state) break; case 1: InitViewGraphics(); + + #if FAST_FOLLOWERS == TRUE + if (FlagGet(FLAG_FOLLOWER_IN_BUILDING)) + FieldSetDoorOpened(gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x, gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.y - 1); + #endif + TryLoadTrainerHillEReaderPalette(); (*state)++; break;