diff options
Diffstat (limited to 'src/field_control_avatar.c')
-rw-r--r-- | src/field_control_avatar.c | 1183 |
1 files changed, 1183 insertions, 0 deletions
diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c new file mode 100644 index 000000000..89b90ca92 --- /dev/null +++ b/src/field_control_avatar.c @@ -0,0 +1,1183 @@ +#include "global.h" +#include "gflib.h" +#include "bike.h" +#include "coord_event_weather.h" +#include "daycare.h" +#include "event_data.h" +#include "event_object_movement.h" +#include "event_scripts.h" +#include "fieldmap.h" +#include "field_control_avatar.h" +#include "field_fadetransition.h" +#include "field_player_avatar.h" +#include "field_poison.h" +#include "field_specials.h" +#include "item_menu.h" +#include "link.h" +#include "menews_jisan.h" +#include "metatile_behavior.h" +#include "overworld.h" +#include "renewable_hidden_items.h" +#include "quest_log.h" +#include "safari_zone.h" +#include "script.h" +#include "start_menu.h" +#include "trainer_see.h" +#include "vs_seeker.h" +#include "wild_encounter.h" +#include "constants/songs.h" +#include "constants/event_bg.h" +#include "constants/event_objects.h" +#include "constants/maps.h" +#include "constants/metatile_behaviors.h" + +#define SIGNPOST_POKECENTER 0 +#define SIGNPOST_POKEMART 1 +#define SIGNPOST_INDIGO_1 2 +#define SIGNPOST_INDIGO_2 3 +#define SIGNPOST_SCRIPTED 240 +#define SIGNPOST_NA 255 + +static void QuestLogOverrideJoyVars(struct FieldInput *input, u16 *newKeys, u16 *heldKeys); +static void Task_QuestLogPlayback_OpenStartMenu(u8 taskId); +static void GetPlayerPosition(struct MapPosition * position); +static void GetInFrontOfPlayerPosition(struct MapPosition * position); +static u16 GetPlayerCurMetatileBehavior(void); +static bool8 TryStartInteractionScript(struct MapPosition * position, u16 metatileBehavior, u8 playerDirection); +static const u8 *GetInteractionScript(struct MapPosition * position, u8 metatileBehavior, u8 playerDirection); +static const u8 *GetInteractedObjectEventScript(struct MapPosition * position, u8 metatileBehavior, u8 playerDirection); +static const u8 *GetInteractedBackgroundEventScript(struct MapPosition * position, u8 metatileBehavior, u8 playerDirection); +static const struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *, u16, u16, u8); +static const u8 *GetInteractedMetatileScript(struct MapPosition * position, u8 metatileBehavior, u8 playerDirection); +static const u8 *GetInteractedWaterScript(struct MapPosition * position, u8 metatileBehavior, u8 playerDirection); +static bool8 TryStartStepBasedScript(struct MapPosition * position, u16 metatileBehavior, u16 playerDirection); +static bool8 TryStartCoordEventScript(struct MapPosition * position); +static bool8 TryStartMiscWalkingScripts(u16 metatileBehavior); +static bool8 TryStartStepCountScript(u16 metatileBehavior); +static void UpdateHappinessStepCounter(void); +static bool8 UpdatePoisonStepCounter(void); +static bool8 CheckStandardWildEncounter(u32 encounter); +static bool8 TrySetUpWalkIntoSignpostScript(struct MapPosition * position, u16 metatileBehavior, u8 playerDirection); +static void SetUpWalkIntoSignScript(const u8 *script, u8 playerDirection); +static u8 GetFacingSignpostType(u16 metatileBehvaior, u8 direction); +static const u8 *GetSignpostScriptAtMapPosition(struct MapPosition * position); +static bool8 TryArrowWarp(struct MapPosition * position, u16 metatileBehavior, u8 playerDirection); +static bool8 TryStartWarpEventScript(struct MapPosition * position, u16 metatileBehavior); +static bool8 IsWarpMetatileBehavior(u16 metatileBehavior); +static void SetupWarp(struct MapHeader * mapHeader, s8 warpId, struct MapPosition * position); +static bool8 IsArrowWarpMetatileBehavior(u16 metatileBehavior, u8 playerDirection); +static s8 GetWarpEventAtMapPosition(struct MapHeader * mapHeader, struct MapPosition * mapPosition); +static bool8 TryDoorWarp(struct MapPosition * position, u16 metatileBehavior, u8 playerDirection); +static s8 GetWarpEventAtPosition(struct MapHeader * mapHeader, u16 x, u16 y, u8 z); +static const u8 *GetCoordEventScriptAtPosition(struct MapHeader * mapHeader, u16 x, u16 y, u8 z); + +struct FieldInput gInputToStoreInQuestLogMaybe; + +void FieldClearPlayerInput(struct FieldInput *input) +{ + input->pressedAButton = FALSE; + input->checkStandardWildEncounter = FALSE; + input->pressedStartButton = FALSE; + input->pressedSelectButton = FALSE; + input->heldDirection = FALSE; + input->heldDirection2 = FALSE; + input->tookStep = FALSE; + input->pressedBButton = FALSE; + input->pressedRButton = FALSE; + input->input_field_1_0 = FALSE; + input->input_field_1_1 = FALSE; + input->input_field_1_2 = FALSE; + input->input_field_1_3 = FALSE; + input->dpadDirection = 0; +} + +void FieldGetPlayerInput(struct FieldInput *input, u16 newKeys, u16 heldKeys) +{ + u8 runningState = gPlayerAvatar.runningState; + u8 tileTransitionState = gPlayerAvatar.tileTransitionState; + bool8 forcedMove = MetatileBehavior_IsForcedMovementTile(GetPlayerCurMetatileBehavior()); + + if (!ScriptContext1_IsScriptSetUp() && IsQuestLogInputDpad() == TRUE) + { + QuestLogOverrideJoyVars(input, &newKeys, &heldKeys); + } + if ((tileTransitionState == T_TILE_CENTER && forcedMove == FALSE) || tileTransitionState == T_NOT_MOVING) + { + if (GetPlayerSpeed() != 4) + { + if ((newKeys & START_BUTTON) && !(gPlayerAvatar.flags & 0x40)) + input->pressedStartButton = TRUE; + if (gQuestLogState != QL_STATE_2 && gQuestLogState != QL_STATE_3) + { + if (!(gPlayerAvatar.flags & 0x40)) + { + if (newKeys & SELECT_BUTTON) + input->pressedSelectButton = TRUE; + if (newKeys & A_BUTTON) + input->pressedAButton = TRUE; + if (newKeys & B_BUTTON) + input->pressedBButton = TRUE; + if (newKeys & R_BUTTON) + input->pressedRButton = TRUE; + } + } + } + + if (gQuestLogState != QL_STATE_2 && gQuestLogState != QL_STATE_3) + { + if (heldKeys & (DPAD_UP | DPAD_DOWN | DPAD_LEFT | DPAD_RIGHT)) + { + input->heldDirection = TRUE; + input->heldDirection2 = TRUE; + } + } + + } + + if (forcedMove == FALSE) + { + if (tileTransitionState == T_TILE_CENTER && runningState == MOVING) + input->tookStep = TRUE; + if (forcedMove == FALSE && tileTransitionState == T_TILE_CENTER) + input->checkStandardWildEncounter = TRUE; + } + + if (gQuestLogState != QL_STATE_2 && gQuestLogState != QL_STATE_3) + { + if (heldKeys & DPAD_UP) + input->dpadDirection = DIR_NORTH; + else if (heldKeys & DPAD_DOWN) + input->dpadDirection = DIR_SOUTH; + else if (heldKeys & DPAD_LEFT) + input->dpadDirection = DIR_WEST; + else if (heldKeys & DPAD_RIGHT) + input->dpadDirection = DIR_EAST; + } +} + +static void QuestLogOverrideJoyVars(struct FieldInput *input, u16 *newKeys, u16 *heldKeys) +{ + switch (GetRegisteredQuestLogInput()) + { + case QL_INPUT_OFF: + break; + case QL_INPUT_UP: + *heldKeys = *newKeys = DPAD_UP; + break; + case QL_INPUT_DOWN: + *heldKeys = *newKeys = DPAD_DOWN; + break; + case QL_INPUT_LEFT: + *heldKeys = *newKeys = DPAD_LEFT; + break; + case QL_INPUT_RIGHT: + *heldKeys = *newKeys = DPAD_RIGHT; + break; + case QL_INPUT_L: + *heldKeys = *newKeys = L_BUTTON; + break; + case QL_INPUT_R: + *heldKeys = *newKeys = R_BUTTON; + break; + case QL_INPUT_START: + *heldKeys = *newKeys = START_BUTTON; + break; + case QL_INPUT_SELECT: + *heldKeys = *newKeys = SELECT_BUTTON; + break; + } + ClearQuestLogInputIsDpadFlag(); + ClearQuestLogInput(); +} + +int ProcessPlayerFieldInput(struct FieldInput *input) +{ + struct MapPosition position; + u8 playerDirection; + u16 metatileBehavior; + u32 r8; + + ResetFacingNpcOrSignPostVars(); + playerDirection = GetPlayerFacingDirection(); + GetPlayerPosition(&position); + r8 = MapGridGetMetatileAttributeAt(position.x, position.y, 0xFF); + metatileBehavior = MapGridGetMetatileBehaviorAt(position.x, position.y); + + FieldClearPlayerInput(&gInputToStoreInQuestLogMaybe); + gInputToStoreInQuestLogMaybe.dpadDirection = input->dpadDirection; + + if (CheckForTrainersWantingBattle() == TRUE) + return TRUE; + + if (TryRunOnFrameMapScript() == TRUE) + return TRUE; + + if (input->tookStep) + { + IncrementGameStat(GAME_STAT_STEPS); + MENewsJisanStepCounter(); + IncrementRenewableHiddenItemStepCounter(); + RunMassageCooldownStepCounter(); + IncrementResortGorgeousStepCounter(); + IncrementBirthIslandRockStepCount(); + if (TryStartStepBasedScript(&position, metatileBehavior, playerDirection) == TRUE) + { + gInputToStoreInQuestLogMaybe.tookStep = TRUE; + return TRUE; + } + } + if (input->checkStandardWildEncounter) + { + if (input->dpadDirection == 0 || input->dpadDirection == playerDirection) + { + GetInFrontOfPlayerPosition(&position); + metatileBehavior = MapGridGetMetatileBehaviorAt(position.x, position.y); + if (TrySetUpWalkIntoSignpostScript(&position, metatileBehavior, playerDirection) == TRUE) + { + gInputToStoreInQuestLogMaybe.checkStandardWildEncounter = TRUE; + return TRUE; + } + GetPlayerPosition(&position); + metatileBehavior = MapGridGetMetatileBehaviorAt(position.x, position.y); + } + } + if (input->checkStandardWildEncounter && CheckStandardWildEncounter(r8) == TRUE) + { + gInputToStoreInQuestLogMaybe.checkStandardWildEncounter = TRUE; + return TRUE; + } + if (input->heldDirection && input->dpadDirection == playerDirection) + { + if (TryArrowWarp(&position, metatileBehavior, playerDirection) == TRUE) + { + gInputToStoreInQuestLogMaybe.heldDirection = TRUE; + return TRUE; + } + } + + GetInFrontOfPlayerPosition(&position); + metatileBehavior = MapGridGetMetatileBehaviorAt(position.x, position.y); + if (input->heldDirection && input->dpadDirection == playerDirection) + { + if (TrySetUpWalkIntoSignpostScript(&position, metatileBehavior, playerDirection) == TRUE) + { + gInputToStoreInQuestLogMaybe.heldDirection = TRUE; + return TRUE; + } + } + + if (input->pressedAButton && TryStartInteractionScript(&position, metatileBehavior, playerDirection) == TRUE) + { + gInputToStoreInQuestLogMaybe.pressedAButton = TRUE; + return TRUE; + } + + if (input->heldDirection2 && input->dpadDirection == playerDirection) + { + if (TryDoorWarp(&position, metatileBehavior, playerDirection) == TRUE) + { + gInputToStoreInQuestLogMaybe.heldDirection2 = TRUE; + return TRUE; + } + } + + if (input->pressedStartButton) + { + gInputToStoreInQuestLogMaybe.pressedStartButton = TRUE; + FlagSet(FLAG_OPENED_START_MENU); + PlaySE(SE_WIN_OPEN); + ShowStartMenu(); + return TRUE; + } + if (input->pressedSelectButton && UseRegisteredKeyItemOnField() == TRUE) + { + gInputToStoreInQuestLogMaybe.pressedSelectButton = TRUE; + return TRUE; + } + + return FALSE; +} + +void FieldInput_HandleCancelSignpost(struct FieldInput * input) +{ + if (ScriptContext1_IsScriptSetUp() == TRUE) + { + if (gWalkAwayFromSignInhibitTimer != 0) + gWalkAwayFromSignInhibitTimer--; + else if (CanWalkAwayToCancelMsgBox() == TRUE) + { + if (input->dpadDirection != 0 && GetPlayerFacingDirection() != input->dpadDirection) + { + if (sub_80699D4() == TRUE) + return; + if (input->dpadDirection == DIR_NORTH) + RegisterQuestLogInput(QL_INPUT_UP); + else if (input->dpadDirection == DIR_SOUTH) + RegisterQuestLogInput(QL_INPUT_DOWN); + else if (input->dpadDirection == DIR_WEST) + RegisterQuestLogInput(QL_INPUT_LEFT); + else if (input->dpadDirection == DIR_EAST) + RegisterQuestLogInput(QL_INPUT_RIGHT); + ScriptContext1_SetupScript(EventScript_CancelMessageBox); + ScriptContext2_Enable(); + } + else if (input->pressedStartButton) + { + ScriptContext1_SetupScript(EventScript_CancelMessageBox); + ScriptContext2_Enable(); + if (!FuncIsActiveTask(Task_QuestLogPlayback_OpenStartMenu)) + CreateTask(Task_QuestLogPlayback_OpenStartMenu, 8); + } + } + } +} + +static void Task_QuestLogPlayback_OpenStartMenu(u8 taskId) +{ + if (!ScriptContext2_IsEnabled()) + { + PlaySE(SE_WIN_OPEN); + ShowStartMenu(); + DestroyTask(taskId); + } +} + +static void GetPlayerPosition(struct MapPosition *position) +{ + PlayerGetDestCoords(&position->x, &position->y); + position->height = PlayerGetZCoord(); +} + +static void GetInFrontOfPlayerPosition(struct MapPosition *position) +{ + s16 x, y; + + GetXYCoordsOneStepInFrontOfPlayer(&position->x, &position->y); + PlayerGetDestCoords(&x, &y); + if (MapGridGetZCoordAt(x, y) != 0) + position->height = PlayerGetZCoord(); + else + position->height = 0; +} + +static u16 GetPlayerCurMetatileBehavior(void) +{ + s16 x, y; + + PlayerGetDestCoords(&x, &y); + return MapGridGetMetatileBehaviorAt(x, y); +} + +static bool8 TryStartInteractionScript(struct MapPosition *position, u16 metatileBehavior, u8 direction) +{ + const u8 *script = GetInteractionScript(position, metatileBehavior, direction); + if (script == NULL) + return FALSE; + + // Don't play interaction sound for certain scripts. + if (script != PalletTown_PlayersHouse_2F_EventScript_PC + && script != EventScript_PC) + PlaySE(SE_SELECT); + + ScriptContext1_SetupScript(script); + return TRUE; +} + +static const u8 *GetInteractionScript(struct MapPosition *position, u8 metatileBehavior, u8 direction) +{ + const u8 *script = GetInteractedObjectEventScript(position, metatileBehavior, direction); + if (script != NULL) + return script; + + script = GetInteractedBackgroundEventScript(position, metatileBehavior, direction); + if (script != NULL) + return script; + + script = GetInteractedMetatileScript(position, metatileBehavior, direction); + if (script != NULL) + return script; + + script = GetInteractedWaterScript(position, metatileBehavior, direction); + if (script != NULL) + return script; + + return NULL; +} + +const u8 *GetInteractedLinkPlayerScript(struct MapPosition *position, u8 metatileBehavior, u8 direction) +{ + u8 objectEventId; + s32 i; + + if (!MetatileBehavior_IsCounter(MapGridGetMetatileBehaviorAt(position->x, position->y))) + objectEventId = GetObjectEventIdByXYZ(position->x, position->y, position->height); + else + objectEventId = GetObjectEventIdByXYZ(position->x + gDirectionToVectors[direction].x, position->y + gDirectionToVectors[direction].y, position->height); + + if (objectEventId == OBJECT_EVENTS_COUNT || gObjectEvents[objectEventId].localId == OBJ_EVENT_ID_PLAYER) + return NULL; + + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + if (gLinkPlayerObjectEvents[i].active == TRUE && gLinkPlayerObjectEvents[i].objEventId == objectEventId) + return NULL; + } + + gSelectedObjectEvent = objectEventId; + gSpecialVar_LastTalked = gObjectEvents[objectEventId].localId; + gSpecialVar_Facing = direction; + return GetObjectEventScriptPointerByObjectEventId(objectEventId); +} + +static const u8 *GetInteractedObjectEventScript(struct MapPosition *position, u8 metatileBehavior, u8 direction) +{ + u8 objectEventId; + const u8 *script; + + objectEventId = GetObjectEventIdByXYZ(position->x, position->y, position->height); + if (objectEventId == OBJECT_EVENTS_COUNT || gObjectEvents[objectEventId].localId == OBJ_EVENT_ID_PLAYER) + { + if (MetatileBehavior_IsCounter(metatileBehavior) != TRUE) + return NULL; + + // Look for an object event on the other side of the counter. + objectEventId = GetObjectEventIdByXYZ(position->x + gDirectionToVectors[direction].x, position->y + gDirectionToVectors[direction].y, position->height); + if (objectEventId == OBJECT_EVENTS_COUNT || gObjectEvents[objectEventId].localId == OBJ_EVENT_ID_PLAYER) + return NULL; + } + + if (InUnionRoom() == TRUE && !ObjectEventCheckHeldMovementStatus(&gObjectEvents[objectEventId])) + return NULL; + + gSelectedObjectEvent = objectEventId; + gSpecialVar_LastTalked = gObjectEvents[objectEventId].localId; + gSpecialVar_Facing = direction; + + script = GetObjectEventScriptPointerByObjectEventId(objectEventId); + + script = GetRamScript(gSpecialVar_LastTalked, script); + return script; +} + +static const u8 *GetInteractedBackgroundEventScript(struct MapPosition *position, u8 metatileBehavior, u8 direction) +{ + u8 signpostType; + const struct BgEvent *bgEvent = GetBackgroundEventAtPosition(&gMapHeader, position->x - 7, position->y - 7, position->height); + + if (bgEvent == NULL) + return NULL; + if (bgEvent->bgUnion.script == NULL) + return EventScript_TestSignpostMsg; + + signpostType = GetFacingSignpostType(metatileBehavior, direction); + + switch (bgEvent->kind) + { + case BG_EVENT_PLAYER_FACING_ANY: + default: + break; + case BG_EVENT_PLAYER_FACING_NORTH: + if (direction != DIR_NORTH) + return NULL; + break; + case BG_EVENT_PLAYER_FACING_SOUTH: + if (direction != DIR_SOUTH) + return NULL; + break; + case BG_EVENT_PLAYER_FACING_EAST: + if (direction != DIR_EAST) + return NULL; + break; + case BG_EVENT_PLAYER_FACING_WEST: + if (direction != DIR_WEST) + return NULL; + break; + case 5: + case 6: + case BG_EVENT_HIDDEN_ITEM: + if (GetHiddenItemAttr((u32)bgEvent->bgUnion.script, HIDDEN_ITEM_UNDERFOOT) == TRUE) + return NULL; + gSpecialVar_0x8005 = GetHiddenItemAttr((u32)bgEvent->bgUnion.script, HIDDEN_ITEM_ID); + gSpecialVar_0x8004 = GetHiddenItemAttr((u32)bgEvent->bgUnion.script, HIDDEN_ITEM_FLAG); + gSpecialVar_0x8006 = GetHiddenItemAttr((u32)bgEvent->bgUnion.script, HIDDEN_ITEM_QUANTITY); + if (FlagGet(gSpecialVar_0x8004) == TRUE) + return NULL; + gSpecialVar_Facing = direction; + return EventScript_HiddenItemScript; + } + + if (signpostType != SIGNPOST_NA) + MsgSetSignPost(); + gSpecialVar_Facing = direction; + return bgEvent->bgUnion.script; +} + +static const u8 *GetInteractedMetatileScript(struct MapPosition *position, u8 metatileBehavior, u8 direction) +{ + gSpecialVar_Facing = direction; + if (MetatileBehavior_IsPC(metatileBehavior) == TRUE) + return EventScript_PC; + if (MetatileBehavior_IsRegionMap(metatileBehavior) == TRUE) + return EventScript_WallTownMap; + if (MetatileBehavior_IsBookshelf(metatileBehavior) == TRUE) + return gUnknown_81A7606; + if (MetatileBehavior_IsPokeMartShelf(metatileBehavior) == TRUE) + return gUnknown_81A760F; + if (MetatileBehavior_IsFood(metatileBehavior) == TRUE) + return gUnknown_81A7618; + if (MetatileBehavior_IsImpressiveMachine(metatileBehavior) == TRUE) + return gUnknown_81A7633; + if (MetatileBehavior_IsBlueprints(metatileBehavior) == TRUE) + return gUnknown_81A763C; + if (MetatileBehavior_IsVideoGame(metatileBehavior) == TRUE) + return gUnknown_81A7621; + if (MetatileBehavior_IsBurglary(metatileBehavior) == TRUE) + return gUnknown_81A7645; + if (MetatileBehavior_IsComputer(metatileBehavior) == TRUE) + return gUnknown_81A762A; + if (MetatileBehavior_IsMBA3(metatileBehavior) == TRUE) + return TrainerTower_EventScript_ShowTime; + if (MetatileBehavior_IsPlayerFacingTVScreen(metatileBehavior, direction) == TRUE) + return gUnknown_81A764E; + if (MetatileBehavior_IsCabinet(metatileBehavior) == TRUE) + return gUnknown_81A7657; + if (MetatileBehavior_IsKitchen(metatileBehavior) == TRUE) + return gUnknown_81A7660; + if (MetatileBehavior_IsDresser(metatileBehavior) == TRUE) + return gUnknown_81A7669; + if (MetatileBehavior_IsSnacks(metatileBehavior) == TRUE) + return gUnknown_81A7672; + if (MetatileBehavior_IsPainting(metatileBehavior) == TRUE) + return gUnknown_81A767B; + if (MetatileBehavior_IsPowerPlantMachine(metatileBehavior) == TRUE) + return gUnknown_81A7684; + if (MetatileBehavior_IsTelephone(metatileBehavior) == TRUE) + return gUnknown_81A768D; + if (MetatileBehavior_IsAdvertisingPoster(metatileBehavior) == TRUE) + return gUnknown_81A7696; + if (MetatileBehavior_IsTastyFood(metatileBehavior) == TRUE) + return gUnknown_81A769F; + if (MetatileBehavior_IsTrashBin(metatileBehavior) == TRUE) + return gUnknown_81A76A8; + if (MetatileBehavior_IsCup(metatileBehavior) == TRUE) + return gUnknown_81A76B1; + if (MetatileBehavior_ReturnFalse_19(metatileBehavior) == TRUE) + return gUnknown_81A76BA; + if (MetatileBehavior_ReturnFalse_20(metatileBehavior) == TRUE) + return gUnknown_81A76C3; + if (MetatileBehavior_IsBlinkingLights(metatileBehavior) == TRUE) + return gUnknown_81A76CC; + if (MetatileBehavior_IsMB9F(metatileBehavior) == TRUE) + return gUnknown_81A76D5; + if (MetatileBehavior_IsPlayerFacingMB_8D(metatileBehavior, direction) == TRUE) + return CableClub_EventScript_81BBFD8; + if (MetatileBehavior_IsQuestionnaire(metatileBehavior) == TRUE) + return EventScript_Questionnaire; + if (MetatileBehavior_IsPlayerFacingBattleRecords(metatileBehavior, direction) == TRUE) + return CableClub_EventScript_ShowBattleRecords; + if (MetatileBehavior_IsIndigoPlateauMark(metatileBehavior) == TRUE) + { + MsgSetSignPost(); + return EventScript_Indigo_UltimateGoal; + } + if (MetatileBehavior_IsIndigoPlateauMark2(metatileBehavior) == TRUE) + { + MsgSetSignPost(); + return EventScript_Indigo_HighestAuthority; + } + if (MetatileBehavior_IsPlayerFacingPokeMartSign(metatileBehavior, direction) == TRUE) + { + MsgSetSignPost(); + return EventScript_PokemartSign; + } + if (MetatileBehavior_IsPlayerFacingPokemonCenterSign(metatileBehavior, direction) == TRUE) + { + MsgSetSignPost(); + return EventScript_PokecenterSign; + } + return NULL; +} + +static const u8 *GetInteractedWaterScript(struct MapPosition *unused1, u8 metatileBehavior, u8 direction) +{ + if (MetatileBehavior_IsSemiDeepWater(metatileBehavior) == TRUE &&PartyHasMonWithSurf() == TRUE) + return EventScript_CurrentTooFast; + if (FlagGet(FLAG_BADGE05_GET) == TRUE && PartyHasMonWithSurf() == TRUE && IsPlayerFacingSurfableFishableWater() == TRUE) + return EventScript_UseSurf; + + if (MetatileBehavior_IsWaterfall(metatileBehavior) == TRUE) + { + if (FlagGet(FLAG_BADGE07_GET) == TRUE && IsPlayerSurfingNorth() == TRUE) + return EventScript_Waterfall; + else + return EventScript_CantUseWaterfall; + } + return NULL; +} + +static bool8 TryStartStepBasedScript(struct MapPosition *position, u16 metatileBehavior, u16 direction) +{ + if (TryStartCoordEventScript(position) == TRUE) + return TRUE; + if (TryStartWarpEventScript(position, metatileBehavior) == TRUE) + return TRUE; + if (TryStartMiscWalkingScripts(metatileBehavior) == TRUE) + return TRUE; + if (TryStartStepCountScript(metatileBehavior) == TRUE) + return TRUE; + if (!(gPlayerAvatar.flags & 0x40) && !MetatileBehavior_IsForcedMovementTile(metatileBehavior) && UpdateRepelCounter() == TRUE) + return TRUE; + return FALSE; +} + +static bool8 TryStartCoordEventScript(struct MapPosition *position) +{ + const u8 *script = GetCoordEventScriptAtPosition(&gMapHeader, position->x - 7, position->y - 7, position->height); + + if (script == NULL) + return FALSE; + ScriptContext1_SetupScript(script); + return TRUE; +} + +static bool8 TryStartMiscWalkingScripts(u16 metatileBehavior) +{ + // Dummied + return FALSE; +} + +static bool8 TryStartStepCountScript(u16 metatileBehavior) +{ + if (InUnionRoom() == TRUE) + return FALSE; + if (gQuestLogState == QL_STATE_2) + return FALSE; + + UpdateHappinessStepCounter(); + + if (!(gPlayerAvatar.flags & 0x40) && !MetatileBehavior_IsForcedMovementTile(metatileBehavior)) + { + if (sub_810C4EC() == TRUE) + { + ScriptContext1_SetupScript(gUnknown_81A8CED); + return TRUE; + } + else if (UpdatePoisonStepCounter() == TRUE) + { + ScriptContext1_SetupScript(EventScript_FieldPoison); + return TRUE; + } + else if (ShouldEggHatch()) + { + IncrementGameStat(GAME_STAT_HATCHED_EGGS); + ScriptContext1_SetupScript(EventScript_EggHatch); + return TRUE; + } + } + if (SafariZoneTakeStep() == TRUE) + return TRUE; + return FALSE; +} + +static void Unref_ClearHappinessStepCounter(void) +{ + VarSet(VAR_HAPPINESS_STEP_COUNTER, 0); +} + +static void UpdateHappinessStepCounter(void) +{ + u16 *ptr = GetVarPointer(VAR_HAPPINESS_STEP_COUNTER); + int i; + + (*ptr)++; + (*ptr) %= 128; + if (*ptr == 0) + { + struct Pokemon *mon = gPlayerParty; + for (i = 0; i < PARTY_SIZE; i++) + { + AdjustFriendship(mon, FRIENDSHIP_EVENT_WALKING); + mon++; + } + } +} + +void ClearPoisonStepCounter(void) +{ + VarSet(VAR_POISON_STEP_COUNTER, 0); +} + +static bool8 UpdatePoisonStepCounter(void) +{ + u16 *ptr; + + if (gMapHeader.mapType != MAP_TYPE_SECRET_BASE) + { + ptr = GetVarPointer(VAR_POISON_STEP_COUNTER); + (*ptr)++; + (*ptr) %= 5; + if (*ptr == 0) + { + switch (DoPoisonFieldEffect()) + { + case FLDPSN_NONE: + return FALSE; + case FLDPSN_PSN: + return FALSE; + case FLDPSN_FNT: + return TRUE; + } + } + } + return FALSE; +} + +void RestartWildEncounterImmunitySteps(void) +{ + ResetEncounterRateModifiers(); +} + +static bool8 CheckStandardWildEncounter(u32 encounter) +{ + return TryStandardWildEncounter(encounter); +} + +static bool8 TrySetUpWalkIntoSignpostScript(struct MapPosition * position, u16 metatileBehavior, u8 playerDirection) +{ + u8 r4; + const u8 * script; + if (JOY_HELD(DPAD_LEFT | DPAD_RIGHT)) + return FALSE; + if (playerDirection == DIR_EAST || playerDirection == DIR_WEST) + return FALSE; + + r4 = GetFacingSignpostType(metatileBehavior, playerDirection); + if (r4 == SIGNPOST_POKECENTER) + { + SetUpWalkIntoSignScript(EventScript_PokecenterSign, playerDirection); + return TRUE; + } + else if (r4 == SIGNPOST_POKEMART) + { + SetUpWalkIntoSignScript(EventScript_PokemartSign, playerDirection); + return TRUE; + } + else if (r4 == SIGNPOST_INDIGO_1) + { + SetUpWalkIntoSignScript(EventScript_Indigo_UltimateGoal, playerDirection); + return TRUE; + } + else if (r4 == SIGNPOST_INDIGO_2) + { + SetUpWalkIntoSignScript(EventScript_Indigo_HighestAuthority, playerDirection); + return TRUE; + } + else + { + script = GetSignpostScriptAtMapPosition(position); + if (script == NULL) + return FALSE; + if (r4 != SIGNPOST_SCRIPTED) + return FALSE; + SetUpWalkIntoSignScript(script, playerDirection); + return TRUE; + } +} + +static u8 GetFacingSignpostType(u16 metatileBehavior, u8 playerDirection) +{ + if (MetatileBehavior_IsPlayerFacingPokemonCenterSign(metatileBehavior, playerDirection) == TRUE) + return SIGNPOST_POKECENTER; + + if (MetatileBehavior_IsPlayerFacingPokeMartSign(metatileBehavior, playerDirection) == TRUE) + return SIGNPOST_POKEMART; + + if (MetatileBehavior_IsIndigoPlateauMark(metatileBehavior) == TRUE) + return SIGNPOST_INDIGO_1; + + if (MetatileBehavior_IsIndigoPlateauMark2(metatileBehavior) == TRUE) + return SIGNPOST_INDIGO_2; + + if (MetatileBehavior_IsSignpost(metatileBehavior) == TRUE) + return SIGNPOST_SCRIPTED; + + return SIGNPOST_NA; +} + +static void SetUpWalkIntoSignScript(const u8 *script, u8 playerDirection) +{ + gSpecialVar_Facing = playerDirection; + ScriptContext1_SetupScript(script); + SetWalkingIntoSignVars(); + MsgSetSignPost(); +} + +static const u8 *GetSignpostScriptAtMapPosition(struct MapPosition * position) +{ + const struct BgEvent * event = GetBackgroundEventAtPosition(&gMapHeader, position->x - 7, position->y - 7, position->height); + if (event == NULL) + return NULL; + if (event->bgUnion.script != NULL) + return event->bgUnion.script; + return EventScript_TestSignpostMsg; +} + +static bool8 TryArrowWarp(struct MapPosition *position, u16 metatileBehavior, u8 direction) +{ + s8 warpEventId = GetWarpEventAtMapPosition(&gMapHeader, position); + u16 delay; + + if (warpEventId != -1) + { + if (IsArrowWarpMetatileBehavior(metatileBehavior, direction) == TRUE) + { + StoreInitialPlayerAvatarState(); + SetupWarp(&gMapHeader, warpEventId, position); + DoWarp(); + return TRUE; + } + else if (sub_806DB84(metatileBehavior, direction) == TRUE) + { + delay = 0; + if (gPlayerAvatar.flags & 6) + { + SetPlayerAvatarTransitionFlags(1); + delay = 12; + } + StoreInitialPlayerAvatarState(); + SetupWarp(&gMapHeader, warpEventId, position); + sub_807E4A0(metatileBehavior, delay); + return TRUE; + } + } + return FALSE; +} + +static bool8 TryStartWarpEventScript(struct MapPosition *position, u16 metatileBehavior) +{ + s8 warpEventId = GetWarpEventAtMapPosition(&gMapHeader, position); + + if (warpEventId != -1 && IsWarpMetatileBehavior(metatileBehavior) == TRUE) + { + StoreInitialPlayerAvatarState(); + SetupWarp(&gMapHeader, warpEventId, position); + if (MetatileBehavior_IsEscalator(metatileBehavior) == TRUE) + { + DoEscalatorWarp(metatileBehavior); + return TRUE; + } + if (MetatileBehavior_IsLavaridgeB1FWarp(metatileBehavior) == TRUE) + { + DoLavaridgeGymB1FWarp(); + return TRUE; + } + if (MetatileBehavior_IsLavaridge1FWarp(metatileBehavior) == TRUE) + { + DoLavaridgeGym1FWarp(); + return TRUE; + } + if (MetatileBehavior_IsWarpPad(metatileBehavior) == TRUE) + { + DoTeleportWarp(); + return TRUE; + } + if (MetatileBehavior_IsUnionRoomWarp(metatileBehavior) == TRUE) + { + DoUnionRoomWarp(); + return TRUE; + } + if (MetatileBehavior_IsFallWarp(metatileBehavior) == TRUE) + { + ResetInitialPlayerAvatarState(); + ScriptContext1_SetupScript(EventScript_1C1361); + return TRUE; + } + DoWarp(); + return TRUE; + } + return FALSE; +} + +static bool8 IsWarpMetatileBehavior(u16 metatileBehavior) +{ + if (MetatileBehavior_IsWarpDoor(metatileBehavior) == TRUE) + return TRUE; + if (MetatileBehavior_IsLadder(metatileBehavior) == TRUE) + return TRUE; + if (MetatileBehavior_IsEscalator(metatileBehavior) == TRUE) + return TRUE; + if (MetatileBehavior_IsCaveDoor(metatileBehavior) == TRUE) + return TRUE; + if (MetatileBehavior_IsLavaridgeB1FWarp(metatileBehavior) == TRUE) + return TRUE; + if (MetatileBehavior_IsLavaridge1FWarp(metatileBehavior) == TRUE) + return TRUE; + if (MetatileBehavior_IsWarpPad(metatileBehavior) == TRUE) + return TRUE; + if (MetatileBehavior_IsFallWarp(metatileBehavior) == TRUE) + return TRUE; + if (MetatileBehavior_IsUnionRoomWarp(metatileBehavior) == TRUE) + return TRUE; + return FALSE; +} + +bool8 sub_806DB84(u16 metatileBehavior, u8 playerDirection) +{ + switch (playerDirection) + { + case DIR_WEST: + if (MetatileBehavior_IsUnknownWarp6D(metatileBehavior)) + return TRUE; + if (MetatileBehavior_IsUnknownWarp6F(metatileBehavior)) + return TRUE; + break; + case DIR_EAST: + if (MetatileBehavior_IsUnknownWarp6C(metatileBehavior)) + return TRUE; + if (MetatileBehavior_IsUnknownWarp6E(metatileBehavior)) + return TRUE; + break; + } + return FALSE; +} + +static bool8 IsArrowWarpMetatileBehavior(u16 metatileBehavior, u8 direction) +{ + switch (direction) + { + case DIR_NORTH: + return MetatileBehavior_IsNorthArrowWarp(metatileBehavior); + case DIR_SOUTH: + return MetatileBehavior_IsSouthArrowWarp(metatileBehavior); + case DIR_WEST: + return MetatileBehavior_IsWestArrowWarp(metatileBehavior); + case DIR_EAST: + return MetatileBehavior_IsEastArrowWarp(metatileBehavior); + } + return FALSE; +} + +static s8 GetWarpEventAtMapPosition(struct MapHeader *mapHeader, struct MapPosition *position) +{ + return GetWarpEventAtPosition(mapHeader, position->x - 7, position->y - 7, position->height); +} + +static void SetupWarp(struct MapHeader *unused, s8 warpEventId, struct MapPosition *position) +{ + const struct WarpEvent *warpEvent; + + warpEvent = &gMapHeader.events->warps[warpEventId]; + + if (warpEvent->mapNum == MAP_NUM(NONE)) + { + SetWarpDestinationToDynamicWarp(warpEvent->warpId); + } + else + { + const struct MapHeader *mapHeader; + + SetWarpDestinationToMapWarp(warpEvent->mapGroup, warpEvent->mapNum, warpEvent->warpId); + UpdateEscapeWarp(position->x, position->y); + mapHeader = Overworld_GetMapHeaderByGroupAndId(warpEvent->mapGroup, warpEvent->mapNum); + if (mapHeader->events->warps[warpEvent->warpId].mapNum == MAP_NUM(NONE)) + SetDynamicWarp(mapHeader->events->warps[warpEventId].warpId, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, warpEventId); + } +} + +static bool8 TryDoorWarp(struct MapPosition *position, u16 metatileBehavior, u8 direction) +{ + s8 warpEventId; + + if (direction == DIR_NORTH) + { + if (MetatileBehavior_IsWarpDoor(metatileBehavior) == TRUE) + { + warpEventId = GetWarpEventAtMapPosition(&gMapHeader, position); + if (warpEventId != -1 && IsWarpMetatileBehavior(metatileBehavior) == TRUE) + { + StoreInitialPlayerAvatarState(); + SetupWarp(&gMapHeader, warpEventId, position); + DoDoorWarp(); + return TRUE; + } + } + } + return FALSE; +} + +static s8 GetWarpEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) +{ + s32 i; + struct WarpEvent *warpEvent = mapHeader->events->warps; + u8 warpCount = mapHeader->events->warpCount; + + for (i = 0; i < warpCount; i++, warpEvent++) + { + if ((u16)warpEvent->x == x && (u16)warpEvent->y == y) + { + if (warpEvent->elevation == elevation || warpEvent->elevation == 0) + return i; + } + } + return -1; +} + +static const u8 *TryRunCoordEventScript(struct CoordEvent *coordEvent) +{ + if (coordEvent != NULL) + { + if (coordEvent->script == NULL) + { + DoCoordEventWeather(coordEvent->trigger); + return NULL; + } + if (coordEvent->trigger == 0) + { + ScriptContext2_RunNewScript(coordEvent->script); + return NULL; + } + if (VarGet(coordEvent->trigger) == (u8)coordEvent->index) + return coordEvent->script; + } + return NULL; +} + +static const u8 *GetCoordEventScriptAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) +{ + s32 i; + struct CoordEvent *coordEvents = mapHeader->events->coordEvents; + u8 coordEventCount = mapHeader->events->coordEventCount; + + for (i = 0; i < coordEventCount; i++) + { + if ((u16)coordEvents[i].x == x && (u16)coordEvents[i].y == y) + { + if (coordEvents[i].elevation == elevation || coordEvents[i].elevation == 0) + { + const u8 *script = TryRunCoordEventScript(&coordEvents[i]); + if (script != NULL) + return script; + } + } + } + return NULL; +} + +void sub_806DE28(struct ObjectEvent * object) +{ + if (MapGridGetMetatileBehaviorAt(object->currentCoords.x, object->currentCoords.y) == MB_FALL_WARP) + { + PlaySE(SE_RU_HYUU); + // w-why?! + RemoveObjectEventByLocalIdAndMap(object->localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + FlagClear(sub_805FCD8(object->localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup)); + } +} + +void sub_806DE70(u16 x, u16 y) +{ + int i; + const struct CoordEvent * events = gMapHeader.events->coordEvents; + int n = gMapHeader.events->coordEventCount; + + if (MapGridGetMetatileBehaviorAt(x, y) == MB_STRENGTH_BUTTON) + { + for (i = 0; i < n; i++) + { + if (events[i].x + 7 == x && events[i].y + 7 == y) + { + sub_8112364(); + ScriptContext1_SetupScript(events[i].script); + ScriptContext2_Enable(); + } + } + } +} + +const u8 *GetCoordEventScriptAtMapPosition(struct MapPosition *position) +{ + return GetCoordEventScriptAtPosition(&gMapHeader, position->x - 7, position->y - 7, position->height); +} + +static const struct BgEvent *GetBackgroundEventAtPosition(struct MapHeader *mapHeader, u16 x, u16 y, u8 elevation) +{ + u8 i; + struct BgEvent *bgEvents = mapHeader->events->bgEvents; + u8 bgEventCount = mapHeader->events->bgEventCount; + + for (i = 0; i < bgEventCount; i++) + { + if ((u16)bgEvents[i].x == x && (u16)bgEvents[i].y == y) + { + if (bgEvents[i].elevation == elevation || bgEvents[i].elevation == 0) + return &bgEvents[i]; + } + } + return NULL; +} + +bool8 dive_warp(struct MapPosition *position, u16 metatileBehavior) +{ + if (gMapHeader.mapType == MAP_TYPE_UNDERWATER && !MetatileBehavior_IsUnableToEmerge(metatileBehavior)) + { + if (SetDiveWarpEmerge(position->x - 7, position->y - 7)) + { + StoreInitialPlayerAvatarState(); + DoDiveWarp(); + PlaySE(SE_W291); + return TRUE; + } + } + else if (MetatileBehavior_IsDiveable(metatileBehavior) == TRUE) + { + if (SetDiveWarpDive(position->x - 7, position->y - 7)) + { + StoreInitialPlayerAvatarState(); + DoDiveWarp(); + PlaySE(SE_W291); + return TRUE; + } + } + return FALSE; +} + +static u8 TrySetDiveWarp(void) +{ + s16 x, y; + u8 metatileBehavior; + + PlayerGetDestCoords(&x, &y); + metatileBehavior = MapGridGetMetatileBehaviorAt(x, y); + if (gMapHeader.mapType == MAP_TYPE_UNDERWATER && !MetatileBehavior_IsUnableToEmerge(metatileBehavior)) + { + if (SetDiveWarpEmerge(x - 7, y - 7) == TRUE) + return 1; + } + else if (MetatileBehavior_IsDiveable(metatileBehavior) == TRUE) + { + if (SetDiveWarpDive(x - 7, y - 7) == TRUE) + return 2; + } + return 0; +} + +static const u8 *GetObjectEventScriptPointerPlayerFacing(void) +{ + u8 direction; + struct MapPosition position; + + direction = GetPlayerMovementDirection(); + GetInFrontOfPlayerPosition(&position); + return GetInteractedObjectEventScript(&position, MapGridGetMetatileBehaviorAt(position.x, position.y), direction); +} + +int SetCableClubWarp(void) +{ + struct MapPosition position; + + GetPlayerMovementDirection(); // unnecessary + GetPlayerPosition(&position); + MapGridGetMetatileBehaviorAt(position.x, position.y); // unnecessary + SetupWarp(&gMapHeader, GetWarpEventAtMapPosition(&gMapHeader, &position), &position); + return 0; +} |