diff options
| author | mzxrules <mzxrules@gmail.com> | 2024-12-17 10:51:56 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-17 10:51:56 -0500 |
| commit | 1adf696588d41d2c3fee4cb4f25cfa4c7d27be19 (patch) | |
| tree | a43f05e2785d2e745c7510a238520fd753c0ef36 /src/code | |
| parent | 524597dc145ef1b685d490fea6fd59eb3fff62fc (diff) | |
Document z_horse.c and related actors (#2278)
* document z_horse.h
* .bss
* suggestions and more comments
* bss
* INGORACE -> INGO_RACE
* format header macros
* FIx incorrect type comparision
* EnInMode -> EnInStartMode
* R_EXITED_SCENE_RIDING_HORSE
Diffstat (limited to 'src/code')
| -rw-r--r-- | src/code/z_actor.c | 7 | ||||
| -rw-r--r-- | src/code/z_camera.c | 4 | ||||
| -rw-r--r-- | src/code/z_horse.c | 249 | ||||
| -rw-r--r-- | src/code/z_message.c | 4 | ||||
| -rw-r--r-- | src/code/z_parameter.c | 10 | ||||
| -rw-r--r-- | src/code/z_play.c | 3 |
6 files changed, 165 insertions, 112 deletions
diff --git a/src/code/z_actor.c b/src/code/z_actor.c index e58729629..66b9601e5 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -4,6 +4,7 @@ #include "rand.h" #include "terminal.h" #include "versions.h" +#include "z64horse.h" #include "overlays/actors/ovl_Arms_Hook/z_arms_hook.h" #include "overlays/actors/ovl_En_Part/z_en_part.h" @@ -1139,7 +1140,7 @@ void Actor_SwapHookshotAttachment(PlayState* play, Actor* srcActor, Actor* destA srcActor->flags &= ~ACTOR_FLAG_HOOKSHOT_ATTACHED; } -void func_8002DE74(PlayState* play, Player* player) { +void Actor_RequestHorseCameraSetting(PlayState* play, Player* player) { if ((play->roomCtx.curRoom.type != ROOM_TYPE_4) && Play_CamIsNotFixed(play)) { Camera_RequestSetting(Play_GetCamera(play, CAM_ID_MAIN), CAM_SET_HORSE); } @@ -1156,8 +1157,8 @@ int func_8002DEEC(Player* player) { (player->csAction != PLAYER_CSACTION_NONE); } -void func_8002DF18(PlayState* play, Player* player) { - func_8006DC68(play, player); +void Actor_InitPlayerHorse(PlayState* play, Player* player) { + Horse_InitPlayerHorse(play, player); } /** diff --git a/src/code/z_camera.c b/src/code/z_camera.c index d5c97c109..e4090d484 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -5,7 +5,7 @@ #include "overlays/actors/ovl_En_Horse/z_en_horse.h" #pragma increment_block_number "gc-eu:192 gc-eu-mq:192 gc-jp:192 gc-jp-ce:192 gc-jp-mq:192 gc-us:192 gc-us-mq:192" \ - "ntsc-1.0:192 ntsc-1.1:192 ntsc-1.2:192 pal-1.0:192 pal-1.1:192" + "ntsc-1.0:128 ntsc-1.1:128 ntsc-1.2:128 pal-1.0:128 pal-1.1:128" s16 Camera_RequestSettingImpl(Camera* camera, s16 requestedSetting, s16 flags); s32 Camera_RequestModeImpl(Camera* camera, s16 requestedMode, u8 forceModeChange); @@ -3639,7 +3639,7 @@ s32 Camera_KeepOn3(Camera* camera) { } #pragma increment_block_number "gc-eu:128 gc-eu-mq:128 gc-jp:128 gc-jp-ce:128 gc-jp-mq:128 gc-us:128 gc-us-mq:128" \ - "ntsc-1.0:83 ntsc-1.1:83 ntsc-1.2:83 pal-1.0:81 pal-1.1:81" + "ntsc-1.0:144 ntsc-1.1:144 ntsc-1.2:144 pal-1.0:142 pal-1.1:142" s32 Camera_KeepOn4(Camera* camera) { static Vec3f D_8015BD50; diff --git a/src/code/z_horse.c b/src/code/z_horse.c index d3d66c3de..2935a66f8 100644 --- a/src/code/z_horse.c +++ b/src/code/z_horse.c @@ -1,30 +1,47 @@ -#include "global.h" #include "terminal.h" +#include "z_lib.h" +#include "regs.h" +#include "z64horse.h" +#include "z64play.h" +#include "z64player.h" #include "src/overlays/actors/ovl_En_Horse/z_en_horse.h" -s32 func_8006CFC0(s32 sceneId) { +/** + * Tests if the player horse can be spawned + * + * @param sceneId the checked scene + * @return true if the player horse can appear in the scene, else false + */ +s32 Horse_CanSpawn(s32 sceneId) { s32 validSceneIds[] = { SCENE_HYRULE_FIELD, SCENE_LAKE_HYLIA, SCENE_GERUDO_VALLEY, SCENE_GERUDOS_FORTRESS, SCENE_LON_LON_RANCH }; s32 i; for (i = 0; i < ARRAY_COUNT(validSceneIds); i++) { if (sceneId == validSceneIds[i]) { - return 1; + return true; } } - return 0; + return false; } -void func_8006D074(PlayState* play) { +/** + * Sets horseData to a neutral spawn in Hyrule Field + */ +void Horse_ResetHorseData(PlayState* play) { gSaveContext.save.info.horseData.sceneId = SCENE_HYRULE_FIELD; gSaveContext.save.info.horseData.pos.x = -1840; gSaveContext.save.info.horseData.pos.y = 72; gSaveContext.save.info.horseData.pos.z = 5497; - gSaveContext.save.info.horseData.angle = -27353; + gSaveContext.save.info.horseData.angle = -0x6AD9; } -void func_8006D0AC(PlayState* play) { +/** + * Forces the player horse to spawn in a safe spot if the current spawn is in Lake Hylia + * This prevents the horse from spawning underwater after obtaining the Water Medallion + */ +void Horse_FixLakeHyliaPosition(PlayState* play) { if (gSaveContext.save.info.horseData.sceneId == SCENE_LAKE_HYLIA) { gSaveContext.save.info.horseData.sceneId = SCENE_LAKE_HYLIA; gSaveContext.save.info.horseData.pos.x = -2065; @@ -41,49 +58,59 @@ typedef struct HorseSpawn { /* 0x0A */ s16 type; } HorseSpawn; -void func_8006D0EC(PlayState* play, Player* player) { +void Horse_SetupInGameplay(PlayState* play, Player* player) { s32 i; HorseSpawn horseSpawns[] = { - { SCENE_HYRULE_FIELD, -460, 100, 6640, 0, 2 }, { SCENE_LAKE_HYLIA, -1929, -1025, 768, 0, 2 }, - { SCENE_GERUDO_VALLEY, 2566, -259, 767, 0, 2 }, { SCENE_GERUDOS_FORTRESS, -328, 10, 953, 0, 2 }, - { SCENE_LON_LON_RANCH, 928, 0, -2280, 0, 2 }, + { SCENE_HYRULE_FIELD, -460, 100, 6640, 0, HORSE_PTYPE_INACTIVE }, + { SCENE_LAKE_HYLIA, -1929, -1025, 768, 0, HORSE_PTYPE_INACTIVE }, + { SCENE_GERUDO_VALLEY, 2566, -259, 767, 0, HORSE_PTYPE_INACTIVE }, + { SCENE_GERUDOS_FORTRESS, -328, 10, 953, 0, HORSE_PTYPE_INACTIVE }, + { SCENE_LON_LON_RANCH, 928, 0, -2280, 0, HORSE_PTYPE_INACTIVE }, }; - if ((AREG(6) != 0) && (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || (DREG(1) != 0))) { - player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, player->actor.world.pos.x, - player->actor.world.pos.y, player->actor.world.pos.z, player->actor.shape.rot.x, - player->actor.shape.rot.y, player->actor.shape.rot.z, 9); + if (R_EXITED_SCENE_RIDING_HORSE && + (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) { + // Player entering scene on top of horse + player->rideActor = + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, player->actor.world.pos.x, player->actor.world.pos.y, + player->actor.world.pos.z, player->actor.shape.rot.x, player->actor.shape.rot.y, + player->actor.shape.rot.z, HORSE_PTYPE_PLAYER_SPAWNED_RIDING); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 343); Actor_MountHorse(play, player, player->rideActor); - func_8002DE74(play, player); + Actor_RequestHorseCameraSetting(play, player); gSaveContext.save.info.horseData.sceneId = play->sceneId; - if (play->sceneId == SCENE_GERUDOS_FORTRESS) { player->rideActor->room = -1; } } else if ((play->sceneId == SCENE_GERUDOS_FORTRESS) && (gSaveContext.minigameState == 3)) { + // Completed Horseback Archery Minigame Actor* horseActor; gSaveContext.minigameState = 0; - horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 3586.0f, 1413.0f, -402.0f, 0, 0x4000, 0, 1); + horseActor = + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 3586.0f, 1413.0f, -402.0f, 0, 0x4000, 0, HORSE_PTYPE_1); horseActor->room = -1; } else if ((gSaveContext.save.entranceIndex == ENTR_LON_LON_RANCH_7) && GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) { + // Completed Horse Race Actor* horseActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -25.0f, 0.0f, -1600.0f, 0, -0x4000, 0, 1); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -25.0f, 0.0f, -1600.0f, 0, -0x4000, 0, HORSE_PTYPE_1); ASSERT(horseActor != NULL, "horse_actor != NULL", "../z_horse.c", 389); } else if ((play->sceneId == gSaveContext.save.info.horseData.sceneId) && - (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || DREG(1) != 0)) { + (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) { + // Player enters a scene where the horse was left previously PRINTF(T("馬存在によるセット %d %d %d\n", "Set by existence of horse %d %d %d\n"), - gSaveContext.save.info.horseData.sceneId, Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED), DREG(1)); + gSaveContext.save.info.horseData.sceneId, Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED), + R_DEBUG_FORCE_EPONA_OBTAINED); - if (func_8006CFC0(gSaveContext.save.info.horseData.sceneId)) { + if (Horse_CanSpawn(gSaveContext.save.info.horseData.sceneId)) { Actor* horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, gSaveContext.save.info.horseData.pos.x, gSaveContext.save.info.horseData.pos.y, gSaveContext.save.info.horseData.pos.z, 0, - gSaveContext.save.info.horseData.angle, 0, 1); + gSaveContext.save.info.horseData.angle, 0, HORSE_PTYPE_1); ASSERT(horseActor != NULL, "horse_actor != NULL", "../z_horse.c", 414); + if (play->sceneId == SCENE_GERUDOS_FORTRESS) { horseActor->room = -1; } @@ -93,13 +120,16 @@ void func_8006D0EC(PlayState* play, Player* player) { T("Horse_SetNormal():%d セットスポットまずいです。\n", "Horse_SetNormal():%d set spot is no good.\n"), gSaveContext.save.info.horseData.sceneId); PRINTF(VT_RST); - func_8006D074(play); + Horse_ResetHorseData(play); } - } else if ((play->sceneId == SCENE_LON_LON_RANCH) && !Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && - (DREG(1) == 0)) { - Actor* horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -500.0f, 0, 0, 0, 1); + } else if ((play->sceneId == SCENE_LON_LON_RANCH) && + !(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) { + // Player spawns in Lon-Lon Ranch without owning Epona + Actor* horseActor = + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -500.0f, 0, 0, 0, HORSE_PTYPE_1); ASSERT(horseActor != NULL, "horse_actor != NULL", "../z_horse.c", 443); - } else if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || (DREG(1) != 0)) { + } else if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED) { + // Player owns Epona, but isn't riding her and the current scene is not the same as the horse's last location. for (i = 0; i < ARRAY_COUNT(horseSpawns); i++) { HorseSpawn* horseSpawn = &horseSpawns[i]; if (horseSpawn->sceneId == play->sceneId) { @@ -107,134 +137,145 @@ void func_8006D0EC(PlayState* play, Player* player) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawn->pos.x, horseSpawn->pos.y, horseSpawn->pos.z, 0, horseSpawn->angle, 0, horseSpawn->type); ASSERT(horseActor != NULL, "horse_actor != NULL", "../z_horse.c", 466); + if (play->sceneId == SCENE_GERUDOS_FORTRESS) { horseActor->room = -1; } - break; } } - } else if (!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED)) { - if ((DREG(1) == 0) && (play->sceneId == SCENE_LON_LON_BUILDINGS) && !IS_DAY) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -60.0f, 0, 0x7360, 0, 1); - } + } else if (!(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED) && + (play->sceneId == SCENE_LON_LON_BUILDINGS) && !IS_DAY) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -60.0f, 0, 0x7360, 0, HORSE_PTYPE_1); } } -typedef struct struct_8011F9B8 { +typedef struct HorseCutsceneSpawn { /* 0x00 */ s16 sceneId; /* 0x04 */ s32 cutsceneIndex; /* 0x08 */ Vec3s pos; /* 0x0E */ s16 angle; /* 0x10 */ s16 type; -} struct_8011F9B8; - -void func_8006D684(PlayState* play, Player* player) { - static struct_8011F9B8 D_8011F9B8[] = { - { SCENE_GERUDOS_FORTRESS, 0xFFF0, { 3600, 1413, 360 }, 0x8001, 8 }, - { SCENE_LON_LON_RANCH, 0xFFF0, { -250, 1, -1580 }, 0x4000, 6 }, - { SCENE_LON_LON_RANCH, 0xFFF1, { 0, 0, 0 }, 0x0000, 5 }, - { SCENE_LON_LON_RANCH, 0xFFF5, { 0, 0, 0 }, 0x0000, 7 }, - { SCENE_HYRULE_FIELD, 0xFFF3, { -2961, 313, 7700 }, 0x0000, 7 }, - { SCENE_HYRULE_FIELD, 0xFFF4, { -1900, 313, 7015 }, 0x0000, 7 }, - { SCENE_HYRULE_FIELD, 0xFFF5, { -4043, 313, 6933 }, 0x0000, 7 }, - { SCENE_HYRULE_FIELD, 0xFFF6, { -4043, 313, 6933 }, 0x0000, 7 }, +} HorseCutsceneSpawn; + +void Horse_SetupInCutscene(PlayState* play, Player* player) { + static HorseCutsceneSpawn horseSpawns[] = { + { SCENE_GERUDOS_FORTRESS, 0xFFF0, { 3600, 1413, 360 }, 0x8001, HORSE_PTYPE_HORSEBACK_ARCHERY }, + { SCENE_LON_LON_RANCH, 0xFFF0, { -250, 1, -1580 }, 0x4000, HORSE_PTYPE_6 }, // Horse Race + { SCENE_LON_LON_RANCH, 0xFFF1, { 0, 0, 0 }, 0x0000, HORSE_PTYPE_5 }, // Learned Epona's Song + { SCENE_LON_LON_RANCH, 0xFFF5, { 0, 0, 0 }, 0x0000, HORSE_PTYPE_7 }, // Credits + { SCENE_HYRULE_FIELD, 0xFFF3, { -2961, 313, 7700 }, 0x0000, HORSE_PTYPE_7 }, // Title Screen + { SCENE_HYRULE_FIELD, 0xFFF4, { -1900, 313, 7015 }, 0x0000, HORSE_PTYPE_7 }, + { SCENE_HYRULE_FIELD, 0xFFF5, { -4043, 313, 6933 }, 0x0000, HORSE_PTYPE_7 }, // Credits + { SCENE_HYRULE_FIELD, 0xFFF6, { -4043, 313, 6933 }, 0x0000, HORSE_PTYPE_7 }, // Unused. Hopping Lon Lon + // Ranch North Gate }; s32 pad; s32 i; - Vec3s spawnPos; if ((gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_11 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15) && (gSaveContext.respawnFlag == 0)) { + // Epona hopping over one of the Lon Lon Ranch fences + Vec3s spawnPos; Vec3s spawnPositions[] = { - { -2961, 313, 7700 }, - { -1900, 313, 7015 }, - { -4043, 313, 6933 }, - { -2313, 313, 5990 }, + // Note: The east and west positions are paired with the wrong entranceIndex. However, the subsequent + // cutscene repositions the horse will override these coordinates while the horse is still obstructed, so no + // visual glitch occurs. + { -2961, 313, 7700 }, // South + { -1900, 313, 7015 }, // East + { -4043, 313, 6933 }, // West + { -2313, 313, 5990 }, // North-East }; + // South of Lon Lon player spawn if (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_11) { spawnPos = spawnPositions[0]; + // West of Lon Lon player spawn } else if (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12) { spawnPos = spawnPositions[1]; + // East of Lon Lon player spawn } else if (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13) { spawnPos = spawnPositions[2]; + // Lon Lon exit player spawn } else { spawnPos = spawnPositions[3]; } player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, spawnPos.x, spawnPos.y, spawnPos.z, 0, - player->actor.world.rot.y, 0, 7); + player->actor.world.rot.y, 0, HORSE_PTYPE_7); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 561); Actor_MountHorse(play, player, player->rideActor); - func_8002DE74(play, player); + Actor_RequestHorseCameraSetting(play, player); gSaveContext.save.info.horseData.sceneId = play->sceneId; - } else if ((play->sceneId == SCENE_LON_LON_RANCH) && (GET_EVENTINF_HORSES_STATE() == EVENTINF_HORSES_STATE_6) && - !Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && (DREG(1) == 0)) { + } else if ((play->sceneId == SCENE_LON_LON_RANCH) && + (GET_EVENTINF_INGO_RACE_STATE() == INGO_RACE_STATE_TRAPPED_WIN_EPONA) && + !(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) { player->rideActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 894.0f, 0.0f, -2084.0f, 0, -0x7FFF, 0, 5); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 894.0f, 0.0f, -2084.0f, 0, -0x7FFF, 0, HORSE_PTYPE_5); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 582); Actor_MountHorse(play, player, player->rideActor); - func_8002DE74(play, player); + Actor_RequestHorseCameraSetting(play, player); gSaveContext.save.info.horseData.sceneId = play->sceneId; if (play->sceneId == SCENE_GERUDOS_FORTRESS) { player->rideActor->room = -1; } } else { - for (i = 0; i < ARRAY_COUNT(D_8011F9B8); i++) { - if ((play->sceneId == D_8011F9B8[i].sceneId) && - (((void)0, gSaveContext.save.cutsceneIndex) == D_8011F9B8[i].cutsceneIndex)) { - if (D_8011F9B8[i].type == 7) { + for (i = 0; i < ARRAY_COUNT(horseSpawns); i++) { + if ((play->sceneId == horseSpawns[i].sceneId) && + (((void)0, gSaveContext.save.cutsceneIndex) == horseSpawns[i].cutsceneIndex)) { + if (horseSpawns[i].type == HORSE_PTYPE_7) { if ((play->sceneId == SCENE_LON_LON_RANCH) && (((void)0, gSaveContext.save.cutsceneIndex) == 0xFFF1)) { - D_8011F9B8[i].pos.x = player->actor.world.pos.x; - D_8011F9B8[i].pos.y = player->actor.world.pos.y; - D_8011F9B8[i].pos.z = player->actor.world.pos.z; + horseSpawns[i].pos.x = player->actor.world.pos.x; + horseSpawns[i].pos.y = player->actor.world.pos.y; + horseSpawns[i].pos.z = player->actor.world.pos.z; } player->rideActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, - D_8011F9B8[i].pos.z, 0, player->actor.world.rot.y, 0, D_8011F9B8[i].type); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawns[i].pos.x, horseSpawns[i].pos.y, + horseSpawns[i].pos.z, 0, player->actor.world.rot.y, 0, horseSpawns[i].type); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 628); Actor_MountHorse(play, player, player->rideActor); - func_8002DE74(play, player); - } else if ((D_8011F9B8[i].type == 5) || (D_8011F9B8[i].type == 6) || (D_8011F9B8[i].type == 8)) { - Vec3f sp54; - s32 temp = 0; - - if (GET_EVENTINF_HORSES_HORSETYPE() != HORSE_EPONA && D_8011F9B8[i].type == 6) { - temp = 0x8000; + Actor_RequestHorseCameraSetting(play, player); + } else if ((horseSpawns[i].type == HORSE_PTYPE_5) || (horseSpawns[i].type == HORSE_PTYPE_6) || + (horseSpawns[i].type == HORSE_PTYPE_HORSEBACK_ARCHERY)) { + Vec3f eye; + s32 paramFlag = 0; + + if (GET_EVENTINF_INGO_RACE_HORSETYPE() != HORSE_EPONA && horseSpawns[i].type == HORSE_PTYPE_6) { + // HORSE_HNI + paramFlag = 0x8000; } player->rideActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, - D_8011F9B8[i].pos.z, 0, D_8011F9B8[i].angle, 0, D_8011F9B8[i].type | temp); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawns[i].pos.x, horseSpawns[i].pos.y, + horseSpawns[i].pos.z, 0, horseSpawns[i].angle, 0, horseSpawns[i].type | paramFlag); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 667); - player->actor.world.pos.x = D_8011F9B8[i].pos.x; - player->actor.world.pos.y = D_8011F9B8[i].pos.y; - player->actor.world.pos.z = D_8011F9B8[i].pos.z; + player->actor.world.pos.x = horseSpawns[i].pos.x; + player->actor.world.pos.y = horseSpawns[i].pos.y; + player->actor.world.pos.z = horseSpawns[i].pos.z; player->actor.shape.rot.x = player->actor.shape.rot.z = 0; - player->actor.shape.rot.y = D_8011F9B8[i].angle; + player->actor.shape.rot.y = horseSpawns[i].angle; Actor_MountHorse(play, player, player->rideActor); - func_8002DE74(play, player); + Actor_RequestHorseCameraSetting(play, player); - sp54.x = player->actor.world.pos.x - 200.0f; - sp54.y = player->actor.world.pos.y + 100.0f; - sp54.z = player->actor.world.pos.z; + eye.x = player->actor.world.pos.x - 200.0f; + eye.y = player->actor.world.pos.y + 100.0f; + eye.z = player->actor.world.pos.z; - Play_SetCameraAtEye(play, play->activeCamId, &player->actor.world.pos, &sp54); + Play_SetCameraAtEye(play, play->activeCamId, &player->actor.world.pos, &eye); } else { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, - D_8011F9B8[i].pos.z, 0, D_8011F9B8[i].angle, 0, D_8011F9B8[i].type); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawns[i].pos.x, horseSpawns[i].pos.y, + horseSpawns[i].pos.z, 0, horseSpawns[i].angle, 0, horseSpawns[i].type); } break; } @@ -242,41 +283,49 @@ void func_8006D684(PlayState* play, Player* player) { } } -void func_8006DC68(PlayState* play, Player* player) { +/** + * Initializes the player's horse, but only if required. + * + * This function should be called during `Play_Init`. + */ +void Horse_InitPlayerHorse(PlayState* play, Player* player) { if (LINK_IS_ADULT) { - if (!func_8006CFC0(gSaveContext.save.info.horseData.sceneId)) { + if (!Horse_CanSpawn(gSaveContext.save.info.horseData.sceneId)) { PRINTF(VT_COL(RED, WHITE)); PRINTF( T("Horse_Set_Check():%d セットスポットまずいです。\n", "Horse_Set_Check():%d set spot is no good.\n"), gSaveContext.save.info.horseData.sceneId); PRINTF(VT_RST); - func_8006D074(play); + Horse_ResetHorseData(play); } - if (func_8006CFC0(play->sceneId)) { + if (Horse_CanSpawn(play->sceneId)) { if (IS_CUTSCENE_LAYER || + // has hopped over one of the Lon-Lon Ranch fences ((gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_11 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15) && (gSaveContext.respawnFlag == 0)) || - ((play->sceneId == SCENE_LON_LON_RANCH) && (GET_EVENTINF_HORSES_STATE() == EVENTINF_HORSES_STATE_6) && - !Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && (DREG(1) == 0))) { - func_8006D684(play, player); + // trapped in Lon Lon Ranch + ((play->sceneId == SCENE_LON_LON_RANCH) && + (GET_EVENTINF_INGO_RACE_STATE() == INGO_RACE_STATE_TRAPPED_WIN_EPONA) && + !(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED))) { + Horse_SetupInCutscene(play, player); } else { - func_8006D0EC(play, player); + Horse_SetupInGameplay(play, player); } } } } -void func_8006DD9C(Actor* actor, Vec3f* arg1, s16 arg2) { - s16 x = Math_Vec3f_Yaw(&actor->world.pos, arg1) - actor->world.rot.y; +void Horse_RotateToPoint(Actor* actor, Vec3f* pos, s16 turnAmount) { + s16 x = Math_Vec3f_Yaw(&actor->world.pos, pos) - actor->world.rot.y; - if (x > arg2) { - actor->world.rot.y += arg2; - } else if (x < -arg2) { - actor->world.rot.y -= arg2; + if (x > turnAmount) { + actor->world.rot.y += turnAmount; + } else if (x < -turnAmount) { + actor->world.rot.y -= turnAmount; } else { actor->world.rot.y += x; } diff --git a/src/code/z_message.c b/src/code/z_message.c index 610396ff8..e17b5f3aa 100644 --- a/src/code/z_message.c +++ b/src/code/z_message.c @@ -3444,7 +3444,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { if (msgCtx->disableWarpSongs || interfaceCtx->restrictions.warpSongs == 3) { Message_StartTextbox(play, 0x88C, NULL); // "You can't warp here!" play->msgCtx.ocarinaMode = OCARINA_MODE_04; - } else if (GET_EVENTINF_HORSES_STATE() != EVENTINF_HORSES_STATE_1) { + } else if (GET_EVENTINF_INGO_RACE_STATE() != INGO_RACE_STATE_HORSE_RENTAL_PERIOD) { Message_StartTextbox(play, msgCtx->lastPlayedSong + 0x88D, NULL); // "Warp to [place name]?" play->msgCtx.ocarinaMode = OCARINA_MODE_01; @@ -4247,7 +4247,7 @@ void Message_Update(PlayState* play) { if (Message_ShouldAdvance(play)) { PRINTF("OCARINA_MODE=%d -> ", play->msgCtx.ocarinaMode); play->msgCtx.ocarinaMode = (msgCtx->choiceIndex == 0) ? OCARINA_MODE_02 : OCARINA_MODE_04; - PRINTF("InRaceSeq=%d(%d) OCARINA_MODE=%d --> ", GET_EVENTINF_HORSES_STATE(), 1, + PRINTF("InRaceSeq=%d(%d) OCARINA_MODE=%d --> ", GET_EVENTINF_INGO_RACE_STATE(), 1, play->msgCtx.ocarinaMode); Message_CloseTextbox(play); PRINTF("OCARINA_MODE=%d\n", play->msgCtx.ocarinaMode); diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c index 7666b1ff0..65e92e33f 100644 --- a/src/code/z_parameter.c +++ b/src/code/z_parameter.c @@ -1,6 +1,7 @@ #include "global.h" #include "terminal.h" #include "versions.h" +#include "z64horse.h" #include "assets/textures/parameter_static/parameter_static.h" #include "assets/textures/do_action_static/do_action_static.h" #include "assets/textures/icon_item_static/icon_item_static.h" @@ -790,7 +791,7 @@ void func_80083108(PlayState* play) { gSaveContext.hudVisibilityMode = HUD_VISIBILITY_NO_CHANGE; Interface_ChangeHudVisibilityMode(HUD_VISIBILITY_ALL); } - } else if (GET_EVENTINF_HORSES_STATE() == EVENTINF_HORSES_STATE_1) { + } else if (GET_EVENTINF_INGO_RACE_STATE() == INGO_RACE_STATE_HORSE_RENTAL_PERIOD) { if (player->stateFlags1 & PLAYER_STATE1_23) { if ((gSaveContext.save.info.equips.buttonItems[0] != ITEM_NONE) && (gSaveContext.save.info.equips.buttonItems[0] != ITEM_BOW)) { @@ -1387,7 +1388,7 @@ u8 Item_Give(PlayState* play, u8 item) { PRINTF(VT_RST); if (item == ITEM_MEDALLION_WATER) { - func_8006D0AC(play); + Horse_FixLakeHyliaPosition(play); } return ITEM_NONE; @@ -3545,8 +3546,9 @@ void Interface_Draw(PlayState* play) { if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[svar1]) { #if OOT_VERSION >= NTSC_1_1 gSaveContext.eventInf[EVENTINF_HORSES_INDEX] &= - (u16) ~(EVENTINF_HORSES_STATE_MASK | EVENTINF_HORSES_HORSETYPE_MASK | EVENTINF_HORSES_05_MASK | - EVENTINF_HORSES_06_MASK | EVENTINF_HORSES_0F_MASK); + (u16) ~(EVENTINF_INGO_RACE_STATE_MASK | EVENTINF_INGO_RACE_HORSETYPE_MASK | + EVENTINF_INGO_RACE_LOST_ONCE_MASK | EVENTINF_INGO_RACE_SECOND_RACE_MASK | + EVENTINF_INGO_RACE_0F_MASK); PRINTF("EVENT_INF=%x\n", gSaveContext.eventInf[EVENTINF_HORSES_INDEX]); #endif play->nextEntranceIndex = spoilingItemEntrances[svar1]; diff --git a/src/code/z_play.c b/src/code/z_play.c index 29d692433..dc61e491c 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -489,7 +489,7 @@ void Play_Init(GameState* thisx) { Environment_PlaySceneSequence(this); gSaveContext.seqId = this->sceneSequences.seqId; gSaveContext.natureAmbienceId = this->sceneSequences.natureAmbienceId; - func_8002DF18(this, GET_PLAYER(this)); + Actor_InitPlayerHorse(this, GET_PLAYER(this)); AnimTaskQueue_Update(this, &this->animTaskQueue); gSaveContext.respawnFlag = 0; @@ -1879,6 +1879,7 @@ void Play_LoadToLastEntrance(PlayState* this) { (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12) || (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13) || (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15)) { + // Avoid re-triggering the hop over Lon Lon fence cutscenes this->nextEntranceIndex = ENTR_HYRULE_FIELD_6; #endif } else { |
