diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/field_fadetransition.c | 2 | ||||
-rw-r--r-- | src/field_specials.c | 3 | ||||
-rw-r--r-- | src/trainer_see.c | 355 | ||||
-rw-r--r-- | src/vs_seeker.c | 4 |
4 files changed, 344 insertions, 20 deletions
diff --git a/src/field_fadetransition.c b/src/field_fadetransition.c index 2e1dcd919..5f97cd680 100644 --- a/src/field_fadetransition.c +++ b/src/field_fadetransition.c @@ -415,7 +415,7 @@ static void task_map_chg_seq_0807E20C(u8 taskId) if (sub_807E418()) { sub_807DCB0(TRUE); - ObjectEventSetHeldMovement(&gObjectEvents[GetObjectEventIdByLocalIdAndMap(0xFF, 0, 0)], sub_8063F84(GetPlayerFacingDirection())); + ObjectEventSetHeldMovement(&gObjectEvents[GetObjectEventIdByLocalIdAndMap(0xFF, 0, 0)], GetWalkNormalMovementAction(GetPlayerFacingDirection())); task->data[0] = 2; } break; diff --git a/src/field_specials.c b/src/field_specials.c index a1de82c0f..d9d15748a 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -46,6 +46,7 @@ #include "constants/region_map.h" #include "constants/moves.h" #include "constants/menu.h" +#include "constants/event_objects.h" static EWRAM_DATA u8 sElevatorCurrentFloorWindowId = 0; static EWRAM_DATA u16 sElevatorScroll = 0; @@ -315,7 +316,7 @@ void Special_AnimatePcTurnOff() void SpawnCameraObject(void) { - u8 objectEventId = SpawnSpecialObjectEventParameterized(OBJECT_EVENT_GFX_YOUNGSTER, 8, 127, gSaveBlock1Ptr->pos.x + 7, gSaveBlock1Ptr->pos.y + 7, 3); + u8 objectEventId = SpawnSpecialObjectEventParameterized(OBJECT_EVENT_GFX_YOUNGSTER, 8, OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->pos.x + 7, gSaveBlock1Ptr->pos.y + 7, 3); gObjectEvents[objectEventId].invisible = TRUE; CameraObjectSetFollowedObjectId(gObjectEvents[objectEventId].spriteId); } diff --git a/src/trainer_see.c b/src/trainer_see.c index a04fe83ec..93b22d2a3 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -1,28 +1,78 @@ #include "global.h" #include "battle_setup.h" -#include "field_player_avatar.h" #include "event_object_movement.h" +#include "field_effect.h" +#include "field_player_avatar.h" #include "quest_log.h" +#include "task.h" #include "constants/battle_setup.h" +#include "constants/event_object_movement.h" +#include "constants/event_objects.h" +#include "constants/object_events.h" + +typedef u8 (*TRAINER_APPROACH_FUNC)(struct ObjectEvent *, s16, s16, s16); +typedef bool8 (*TRAINER_SEE_FUNC)(u8, struct Task *, struct ObjectEvent *); -static bool8 CheckTrainer(u8 objectEventId); -static u8 GetTrainerApproachDistance(struct ObjectEvent * objectEvent); -static u8 GetTrainerApproachDistanceSouth(struct ObjectEvent * objectEvent, s16 range, s16 x, s16 y); -static u8 GetTrainerApproachDistanceNorth(struct ObjectEvent * objectEvent, s16 range, s16 x, s16 y); -static u8 GetTrainerApproachDistanceWest(struct ObjectEvent * objectEvent, s16 range, s16 x, s16 y); -static u8 GetTrainerApproachDistanceEast(struct ObjectEvent * objectEvent, s16 range, s16 x, s16 y); -static u8 CheckPathBetweenTrainerAndPlayer(struct ObjectEvent * objectEvent, u8 approachDistance, u8 facingDirection); -void sub_8081E68(struct ObjectEvent * objectEvent, u8 approachDistance); +static bool8 CheckTrainer(u8 trainerObjId); +static u8 GetTrainerApproachDistance(struct ObjectEvent * trainerObj); +static u8 GetTrainerApproachDistanceSouth(struct ObjectEvent * trainerObj, s16 range, s16 x, s16 y); +static u8 GetTrainerApproachDistanceNorth(struct ObjectEvent * trainerObj, s16 range, s16 x, s16 y); +static u8 GetTrainerApproachDistanceWest(struct ObjectEvent * trainerObj, s16 range, s16 x, s16 y); +static u8 GetTrainerApproachDistanceEast(struct ObjectEvent * trainerObj, s16 range, s16 x, s16 y); +static u8 CheckPathBetweenTrainerAndPlayer(struct ObjectEvent * trainerObj, u8 approachDistance, u8 facingDirection); +void TrainerApproachPlayer(struct ObjectEvent * trainerObj, u8 approachDistance); +void Task_RunTrainerSeeFuncList(u8 taskId); +bool8 sub_8081F34(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_8081F38(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_8081F90(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_8081FD0(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_808202C(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_80820BC(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_8082100(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_8082134(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_8082150(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_8082184(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_80821DC(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_8082250(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_808226C(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_80822CC(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); +bool8 sub_808237C(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj); const u16 gUnknown_83C6AC8[] = INCBIN_U16("graphics/object_events/emoticons.4bpp"); -u8 (*const sDirectionalApproachDistanceFuncs[])(struct ObjectEvent *, s16 range, s16 x, s16 y) = { +// u8 func(struct ObjectEvent * trainerObj, s16 range, s16 x, s16 y) +// range is the maximum distance the trainer can see +// x and y are the player's coordinates +// Returns distance to walk if trainer has unobstructed view of player +// Returns 0 if trainer can't see player +const TRAINER_APPROACH_FUNC sDirectionalApproachDistanceFuncs[] = { GetTrainerApproachDistanceSouth, GetTrainerApproachDistanceNorth, GetTrainerApproachDistanceWest, GetTrainerApproachDistanceEast }; +// bool8 func(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +// Returns TRUE to run the next func immediately +// Returns FALSE to delay the next func to the next frame +const TRAINER_SEE_FUNC sTrainerSeeFuncList[] = { + sub_8081F34, + sub_8081F38, + sub_8081F90, + sub_8081FD0, + sub_808202C, + sub_80820BC, + sub_8082100, + sub_8082134, + sub_8082150, + sub_8082184, + sub_80821DC, + sub_8082250, + sub_808226C, + sub_80822CC, + sub_808237C +}; + bool8 CheckForTrainersWantingBattle(void) { u8 i; @@ -43,19 +93,19 @@ bool8 CheckForTrainersWantingBattle(void) return FALSE; } -static bool8 CheckTrainer(u8 objectEventId) +static bool8 CheckTrainer(u8 trainerObjId) { - const u8 *script = GetObjectEventScriptPointerByObjectEventId(objectEventId); + const u8 *script = GetObjectEventScriptPointerByObjectEventId(trainerObjId); u8 approachDistance; if (GetTrainerFlagFromScriptPointer(script)) return FALSE; - approachDistance = GetTrainerApproachDistance(&gObjectEvents[objectEventId]); + approachDistance = GetTrainerApproachDistance(&gObjectEvents[trainerObjId]); if (approachDistance != 0) { if (script[1] == TRAINER_BATTLE_DOUBLE && GetMonsStateToDoubles()) return FALSE; - ConfigureAndSetUpOneTrainerBattle(objectEventId, script); - sub_8081E68(&gObjectEvents[objectEventId], approachDistance - 1); + ConfigureAndSetUpOneTrainerBattle(trainerObjId, script); + TrainerApproachPlayer(&gObjectEvents[trainerObjId], approachDistance - 1); return TRUE; } return FALSE; @@ -93,7 +143,7 @@ static u8 GetTrainerApproachDistanceSouth(struct ObjectEvent *trainerObj, s16 ra && y > trainerObj->currentCoords.y && y <= trainerObj->currentCoords.y + range) { - if (range > 3 && sub_805DF30() == OBJECT_EVENTS_COUNT) + if (range > 3 && GetIndexOfFirstInactiveObjectEvent() == OBJECT_EVENTS_COUNT) return 0; return (y - trainerObj->currentCoords.y); } @@ -172,3 +222,276 @@ static u8 CheckPathBetweenTrainerAndPlayer(struct ObjectEvent *trainerObj, u8 ap return 0; } + +#define tFuncId data[0] +#define tTrainerObjHi data[1] +#define tTrainerObjLo data[2] +#define tTrainerRange data[3] +#define tOutOfAshSpriteId data[4] +#define tData5 data[5] + +#define TaskGetTrainerObj(dest, task) do { \ + (dest) = (struct ObjectEvent *)(((task)->tTrainerObjHi << 16) | ((u16)(task)->tTrainerObjLo)); \ +} while (0) + +void TrainerApproachPlayer(struct ObjectEvent * trainerObj, u8 approachDistance) +{ + u8 taskId = CreateTask(Task_RunTrainerSeeFuncList, 80); + struct Task * task = &gTasks[taskId]; + task->tTrainerObjHi = ((uintptr_t)trainerObj) >> 16; + task->tTrainerObjLo = (uintptr_t)trainerObj; + task->tTrainerRange = approachDistance; +} + +void sub_8081E9C(TaskFunc taskFunc) +{ + u8 taskId = FindTaskIdByFunc(Task_RunTrainerSeeFuncList); + SetTaskFuncWithFollowupFunc(taskId, Task_RunTrainerSeeFuncList, taskFunc); + gTasks[taskId].tFuncId = 1; + Task_RunTrainerSeeFuncList(taskId); +} + +void Task_RunTrainerSeeFuncList(u8 taskId) +{ + struct Task * task = &gTasks[taskId]; + struct ObjectEvent * trainerObj; + TaskGetTrainerObj(trainerObj, task); + + if (!trainerObj->active) + { + SwitchTaskToFollowupFunc(taskId); + } + else + { + while (sTrainerSeeFuncList[task->tFuncId](taskId, task, trainerObj)) + ; + } +} + +// TrainerSeeFuncs + +bool8 sub_8081F34(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + return FALSE; +} + +bool8 sub_8081F38(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + u8 action; + // FRLG introduces trainers who can see the player from offscreen above. + // Handle this case here. + if (trainerObj->facingDirection == DIR_SOUTH && task->tTrainerRange > 2) + { + task->tFuncId = 12; + } + else + { + ObjectEventGetLocalIdAndMap(trainerObj, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_1); + action = GetFaceDirectionMovementAction(trainerObj->facingDirection); + ObjectEventSetHeldMovement(trainerObj, action); + task->tFuncId++; + } + return TRUE; +} + +bool8 sub_8081F90(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + if (FieldEffectActiveListContains(FLDEFF_EXCLAMATION_MARK_ICON_1)) + { + return FALSE; + } + else + { + task->tFuncId++; + if (trainerObj->animPattern == MOVEMENT_TYPE_TREE_DISGUISE || trainerObj->animPattern == MOVEMENT_TYPE_MOUNTAIN_DISGUISE) + task->tFuncId = 6; + if (trainerObj->animPattern == MOVEMENT_TYPE_HIDDEN) + task->tFuncId = 8; + return TRUE; + } +} + +bool8 sub_8081FD0(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + if (!ObjectEventIsMovementOverridden(trainerObj) || ObjectEventClearHeldMovementIfFinished(trainerObj)) + { + if (task->tTrainerRange) + { + ObjectEventSetHeldMovement(trainerObj, GetWalkNormalMovementAction(trainerObj->facingDirection)); + task->tTrainerRange--; + } + else + { + ObjectEventSetHeldMovement(trainerObj, MOVEMENT_ACTION_FACE_PLAYER); + task->tFuncId++; + } + } + return FALSE; +} + +bool8 sub_808202C(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + struct ObjectEvent *playerObj; + + if (ObjectEventIsMovementOverridden(trainerObj) && !ObjectEventClearHeldMovementIfFinished(trainerObj)) + return FALSE; + + SetTrainerMovementType(trainerObj, GetTrainerFacingDirectionMovementType(trainerObj->facingDirection)); + TryOverrideTemplateCoordsForObjectEvent(trainerObj, GetTrainerFacingDirectionMovementType(trainerObj->facingDirection)); + OverrideTemplateCoordsForObjectEvent(trainerObj); + + playerObj = &gObjectEvents[gPlayerAvatar.objectEventId]; + if (ObjectEventIsMovementOverridden(playerObj) && !ObjectEventClearHeldMovementIfFinished(playerObj)) + return FALSE; + + sub_805C774(); + // Uncomment to have player turn to face their opponent + // ObjectEventSetHeldMovement(&gObjectEvents[gPlayerAvatar.objectEventId], GetFaceDirectionMovementAction(GetOppositeDirection(trainerObj->facingDirection))); + task->tFuncId++; + return FALSE; +} + +bool8 sub_80820BC(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId]; + + if (!ObjectEventIsMovementOverridden(playerObj) + || ObjectEventClearHeldMovementIfFinished(playerObj)) + SwitchTaskToFollowupFunc(taskId); // This ends the trainer walk routine. + return FALSE; +} + +// Jumps here if disguised. Not used in FRLG. +bool8 sub_8082100(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + if (!ObjectEventIsMovementOverridden(trainerObj) + || ObjectEventClearHeldMovementIfFinished(trainerObj)) + { + ObjectEventSetHeldMovement(trainerObj, MOVEMENT_ACTION_REVEAL_TRAINER); + task->tFuncId++; + } + return FALSE; +} + +bool8 sub_8082134(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + if (ObjectEventClearHeldMovementIfFinished(trainerObj)) + task->tFuncId = 3; + + return FALSE; +} + +// Jump here if hidden in ash. Not used in FRLG. +bool8 sub_8082150(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + if (!ObjectEventIsMovementOverridden(trainerObj) + || ObjectEventClearHeldMovementIfFinished(trainerObj)) + { + ObjectEventSetHeldMovement(trainerObj, MOVEMENT_ACTION_FACE_PLAYER); + task->tFuncId++; + } + return FALSE; +} + +bool8 sub_8082184(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + if (ObjectEventCheckHeldMovementStatus(trainerObj)) + { + gFieldEffectArguments[0] = trainerObj->currentCoords.x; + gFieldEffectArguments[1] = trainerObj->currentCoords.y; + gFieldEffectArguments[2] = gSprites[trainerObj->spriteId].subpriority - 1; + gFieldEffectArguments[3] = 2; + task->tOutOfAshSpriteId = FieldEffectStart(FLDEFF_POP_OUT_OF_ASH); + task->tFuncId++; + } + return FALSE; +} + +bool8 sub_80821DC(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + struct Sprite *sprite; + + if (gSprites[task->tOutOfAshSpriteId].animCmdIndex == 2) + { + trainerObj->fixedPriority = 0; + trainerObj->triggerGroundEffectsOnMove = 1; + + sprite = &gSprites[trainerObj->spriteId]; + sprite->oam.priority = 2; + ObjectEventClearHeldMovementIfFinished(trainerObj); + ObjectEventSetHeldMovement(trainerObj, GetJumpInPlaceMovementAction(trainerObj->facingDirection)); + task->tFuncId++; + } + + return FALSE; +} + +bool8 sub_8082250(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj) +{ + if (!FieldEffectActiveListContains(FLDEFF_POP_OUT_OF_ASH)) + task->tFuncId = 3; + + return FALSE; +} + +// FRLG exclusive: Scroll the camera up to reveal an offscreen above trainer +bool8 sub_808226C(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj) +{ + int specialObjectId; + task->tData5 = 0; + specialObjectId = SpawnSpecialObjectEventParameterized(OBJECT_EVENT_GFX_YOUNGSTER, 7, OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->pos.x + 7, gSaveBlock1Ptr->pos.y + 7, 3); + gObjectEvents[specialObjectId].invisible = TRUE; + CameraObjectSetFollowedObjectId(gObjectEvents[specialObjectId].spriteId); + task->tFuncId++; + return FALSE; +} + +bool8 sub_80822CC(u8 taskId, struct Task *task, struct ObjectEvent *trainerObj) +{ + u8 specialObjectId; + TryGetObjectEventIdByLocalIdAndMap(OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &specialObjectId); + + if (ObjectEventIsMovementOverridden(&gObjectEvents[specialObjectId]) && !ObjectEventClearHeldMovementIfFinished(&gObjectEvents[specialObjectId])) + return FALSE; + + if (task->tData5 != task->tTrainerRange - 1) + { + ObjectEventSetHeldMovement(&gObjectEvents[specialObjectId], sub_8063FB0(DIR_NORTH)); + task->tData5++; + } + else + { + ObjectEventGetLocalIdAndMap(trainerObj, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_1); + task->tData5 = 0; + task->tFuncId++; + } + return FALSE; +} + +bool8 sub_808237C(u8 taskId, struct Task * task, struct ObjectEvent * trainerObj) +{ + u8 specialObjectId; + TryGetObjectEventIdByLocalIdAndMap(OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &specialObjectId); + + if (FieldEffectActiveListContains(FLDEFF_EXCLAMATION_MARK_ICON_1)) + return FALSE; + + if (ObjectEventIsMovementOverridden(&gObjectEvents[specialObjectId]) && !ObjectEventClearHeldMovementIfFinished(&gObjectEvents[specialObjectId])) + return FALSE; + + if (task->tData5 != task->tTrainerRange - 1) + { + ObjectEventSetHeldMovement(&gObjectEvents[specialObjectId], sub_8063FB0(DIR_SOUTH)); + task->tData5++; + } + else + { + CameraObjectSetFollowedObjectId(GetPlayerAvatarObjectId()); + RemoveObjectEventByLocalIdAndMap(OBJ_EVENT_ID_CAMERA, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); + task->tData5 = 0; + task->tFuncId = 2; + } + return FALSE; +} diff --git a/src/vs_seeker.c b/src/vs_seeker.c index 221108a8f..b74c345e4 100644 --- a/src/vs_seeker.c +++ b/src/vs_seeker.c @@ -951,7 +951,7 @@ void sub_810CB90(void) TryGetObjectEventIdByLocalIdAndMap(r4[r8].localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &sp0); r4_2 = &gObjectEvents[sp0]; sub_810CF54(&r4[r8]); // You are using this function incorrectly. Please consult the manual. - sub_805FE7C(r4_2, gUnknown_8453F67[r4_2->facingDirection]); + TryOverrideTemplateCoordsForObjectEvent(r4_2, gUnknown_8453F67[r4_2->facingDirection]); gSaveBlock1Ptr->trainerRematches[r4[r8].localId] = 0; if (gSelectedObjectEvent == sp0) r4_2->animPattern = gUnknown_8453F67[r4_2->facingDirection]; @@ -1312,7 +1312,7 @@ static void StartAllRespondantIdleMovements(void) if (sub_810CF04(sVsSeeker->trainerInfo[j].objectEventId) == 1) SetTrainerMovementType(r4, sVsSeeker->runningBehaviourEtcArray[i]); - sub_805FE7C(r4, sVsSeeker->runningBehaviourEtcArray[i]); + TryOverrideTemplateCoordsForObjectEvent(r4, sVsSeeker->runningBehaviourEtcArray[i]); gSaveBlock1Ptr->trainerRematches[sVsSeeker->trainerInfo[j].localId] = GetNextAvailableRematchTrainer(sVsSeekerData, sVsSeeker->trainerInfo[j].trainerIdx, &dummy); } } |