From eb24680be36616c36009e17e1e09608db17560b8 Mon Sep 17 00:00:00 2001 From: Anghelo Carvajal Date: Thu, 1 Jun 2023 15:11:11 -0400 Subject: `z_horse.c` OK (#1245) * func_800F3940 * func_800F3B2C, func_800F415C and func_800F41E4 * func_800F40A0 * func_800F3ED4 * func_800F3C44 * func_800F3B68 NON_MATCHING * func_800F3A64 kinda * func_800F39B4 * cleanups * import data * fix fake match * format * Scene enum * minor cleanup on data usage * Horse_RotateToPoint and ENHORSE_PARAMS * scene setup index Co-authored-by: Tom Overton * fix merge * z64horse.h * Renames * and even more renames * format * fix * review * Horse_IsActive * review * bss * fix * remove comments * Update src/code/z_horse.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * review * Update src/code/z_horse.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * review --------- Co-authored-by: Tom Overton Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> --- src/code/z_actor.c | 7 +- src/code/z_horse.c | 232 +++++++++++++++++++++++++++++++++++++++++++++++--- src/code/z_sram_NES.c | 7 +- 3 files changed, 230 insertions(+), 16 deletions(-) (limited to 'src/code') diff --git a/src/code/z_actor.c b/src/code/z_actor.c index c46b6ec3b..b5a24cfac 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -4,6 +4,7 @@ */ #include "global.h" +#include "z64horse.h" #include "z64load.h" #include "z64quake.h" #include "z64rumble.h" @@ -1357,8 +1358,8 @@ s32 func_800B7200(Player* player) { return (player->stateFlags1 & (PLAYER_STATE1_80 | PLAYER_STATE1_20000000)) || (player->csMode != PLAYER_CSMODE_0); } -void func_800B722C(GameState* gameState, Player* player) { - func_800F40A0(gameState, player); +void Actor_SpawnHorse(PlayState* play, Player* player) { + Horse_Spawn(play, player); } s32 func_800B724C(PlayState* play, Actor* actor, u8 csMode) { @@ -2304,7 +2305,7 @@ void Actor_InitContext(PlayState* play, ActorContext* actorCtx, ActorEntry* acto Actor_TargetContextInit(&actorCtx->targetContext, actorCtx->actorLists[ACTORCAT_PLAYER].first, play); Actor_InitHalfDaysBit(actorCtx); Fault_AddClient(&sActorFaultClient, (void*)Actor_PrintLists, actorCtx, NULL); - func_800B722C(&play->state, (Player*)actorCtx->actorLists[ACTORCAT_PLAYER].first); + Actor_SpawnHorse(play, (Player*)actorCtx->actorLists[ACTORCAT_PLAYER].first); } /** diff --git a/src/code/z_horse.c b/src/code/z_horse.c index 976ea2948..ac0142fae 100644 --- a/src/code/z_horse.c +++ b/src/code/z_horse.c @@ -1,21 +1,233 @@ #include "global.h" +#include "z64horse.h" +#include "overlays/actors/ovl_Bg_Umajump/z_bg_umajump.h" +#include "overlays/actors/ovl_En_Horse/z_en_horse.h" -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F3940.s") +s32 Horse_GetJumpingFencePathIndex(PlayState* play) { + Actor* actor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F39B4.s") + for (actor = NULL;; actor = actor->next) { + actor = SubS_FindActor(play, actor, ACTORCAT_PROP, ACTOR_BG_UMAJUMP); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F3A64.s") + if (actor == NULL) { + break; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F3B2C.s") + if (actor->params == BG_UMAJUMP_TYPE_2) { + return ((BgUmajump*)actor)->pathIndex; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F3B68.s") + return -1; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F3C44.s") +// unused +s32 Horse_CopyPointFromPathList(PlayState* play, s32 pathIndex, s32 pointIndex, Vec3s* dst, s16* arg4) { + Path* path = &play->setupPathList[pathIndex]; + Vec3s* points; + s32 count = path->count; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F3ED4.s") + dst->x = 0; + dst->y = 0; + dst->z = 0; + *arg4 = 0; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F40A0.s") + if (count == 0) { + return false; + } + if (pointIndex >= count) { + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F415C.s") + points = Lib_SegmentedToVirtual(path->points); + points += pointIndex; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_horse/func_800F41E4.s") + dst->x = points->x; + dst->y = points->y; + dst->z = points->z; + *arg4 = 0; + + return true; +} + +typedef struct HorseValidScene { + /* 0x0 */ s16 sceneId; + /* 0x2 */ s16 sceneLayerMinusOne; +} HorseValidScene; // size = 0x4 + +HorseValidScene sHorseValidScenes[] = { + { SCENE_00KEIKOKU, 0 }, // Termina Field + { SCENE_24KEMONOMITI, 0 }, // Road to southern swap + { SCENE_F01, 0 }, // Romani ranch + { SCENE_KOEPONARACE, 0 }, // Gorman track + { SCENE_20SICHITAI, 0 }, // Southern swamp poisoned + { SCENE_20SICHITAI2, 0 }, // Souther swamp clear + { SCENE_30GYOSON, 0 }, // Great bay coast + { SCENE_31MISAKI, 0 }, // Zora cape + { SCENE_ROMANYMAE, 0 }, // Milk road + { SCENE_IKANAMAE, 0 }, // Road to Ikana + { SCENE_13HUBUKINOMITI, 0 }, // Path to Mountain Village +}; + +s32 Horse_IsValidSpawn(s16 sceneId) { + s32 i; + + for (i = 0; i < ARRAY_COUNT(sHorseValidScenes); i++) { + if (sceneId == sHorseValidScenes[i].sceneId) { + return true; + } + } + + return false; +} + +void Horse_ResetHorseData(PlayState* play) { + gSaveContext.save.saveInfo.horseData.sceneId = SCENE_F01; + gSaveContext.save.saveInfo.horseData.pos.x = -1420; + gSaveContext.save.saveInfo.horseData.pos.y = 257; + gSaveContext.save.saveInfo.horseData.pos.z = -1285; + gSaveContext.save.saveInfo.horseData.yaw = 0x2AAA; +} + +s32 gHorseIsMounted = false; +s32 D_801BDAA0 = false; +s32 gHorsePlayedEponasSong = false; + +HorseValidScene sHorseValidSceneLayers[] = { + { SCENE_00KEIKOKU, 5 - 1 }, // Termina Field - First Cycle + { SCENE_30GYOSON, 1 - 1 }, // Great Bay Coast - Post-Gyorg + { SCENE_31MISAKI, 1 - 1 }, // Zora Cape - Post-Gyorg + { SCENE_13HUBUKINOMITI, 1 - 1 }, // Path to Mountain Village - Post-Goht +}; + +s32 Horse_IsValidSceneLayer(PlayState* play, Player* player) { + s32 i; + + if (gSaveContext.sceneLayer == 0) { + return true; + } + + for (i = 0; i < ARRAY_COUNT(sHorseValidSceneLayers); i++) { + if ((sHorseValidSceneLayers[i].sceneId == play->sceneId) && + (gSaveContext.sceneLayer == sHorseValidSceneLayers[i].sceneLayerMinusOne + 1)) { + return true; + } + } + return false; +} + +void Horse_SpawnOverworld(PlayState* play, Player* player) { + if (!Horse_IsValidSceneLayer(play, player)) { + return; + } + + if (gHorseIsMounted && CHECK_QUEST_ITEM(QUEST_SONG_EPONA)) { + s32 pad; + Vec3f pos = player->actor.world.pos; + f32 yIntersect; + CollisionPoly* poly; + s32 pad2[3]; + + pos.y += 5.0f; + yIntersect = BgCheck_EntityRaycastFloor1(&play->colCtx, &poly, &pos); + if (yIntersect == BGCHECK_Y_MIN) { + yIntersect = player->actor.world.pos.y; + } + + player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, player->actor.world.pos.x, yIntersect, + player->actor.world.pos.z, player->actor.shape.rot.x, player->actor.shape.rot.y, + player->actor.shape.rot.z, ENHORSE_PARAMS(ENHORSE_PARAM_4000, ENHORSE_11)); + Actor_MountHorse(play, player, player->rideActor); + Actor_SetCameraHorseSetting(play, player); + } else if ((play->sceneId == gSaveContext.save.saveInfo.horseData.sceneId) && CHECK_QUEST_ITEM(QUEST_SONG_EPONA)) { + if (Horse_IsValidSpawn(gSaveContext.save.saveInfo.horseData.sceneId)) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, gSaveContext.save.saveInfo.horseData.pos.x, + gSaveContext.save.saveInfo.horseData.pos.y, gSaveContext.save.saveInfo.horseData.pos.z, 0, + gSaveContext.save.saveInfo.horseData.yaw, 0, ENHORSE_PARAMS(ENHORSE_PARAM_4000, ENHORSE_1)); + } else { + Horse_ResetHorseData(play); + } + } else if ((play->sceneId == SCENE_F01) && !CHECK_QUEST_ITEM(QUEST_SONG_EPONA)) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -1420.0f, 257.0f, -1285.0f, 0, 0x2AAA, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_4000, ENHORSE_1)); + } else if (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && Horse_IsValidSpawn(play->sceneId)) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, player->actor.world.pos.x, player->actor.world.pos.y, + player->actor.world.pos.z, 0, player->actor.shape.rot.y, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_4000, ENHORSE_2)); + } +} + +void Horse_SpawnMinigame(PlayState* play, Player* player) { + if ((play->sceneId == SCENE_KOEPONARACE) && + (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_START)) { + player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -1262.0f, -106.0f, 470.0f, 0, 0x7FFF, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_4000, ENHORSE_13)); + Actor_MountHorse(play, player, player->rideActor); + Actor_SetCameraHorseSetting(play, player); + } else if ((play->sceneId == SCENE_KOEPONARACE) && + ((GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_3) || + (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_2))) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -1741.0f, -106.0f, -641.0f, 0, -0x4FA4, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_4000, ENHORSE_1)); + } else if ((gSaveContext.save.entrance == ENTRANCE(ROMANI_RANCH, 0)) && (Cutscene_GetSceneLayer(play) != 0) && + (player->transformation == PLAYER_FORM_HUMAN)) { + player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -1106.0f, 260.0f, -1185.0f, 0, 0x13, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_4000, ENHORSE_7)); + Actor_MountHorse(play, player, player->rideActor); + Actor_SetCameraHorseSetting(play, player); + } +} + +void Horse_Spawn(PlayState* play, Player* player) { + if (((play->sceneId == SCENE_KOEPONARACE) && + (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_START)) || + ((play->sceneId == SCENE_F01) && (((gSaveContext.sceneLayer == 1)) || (gSaveContext.sceneLayer == 5)) && + (player->transformation == PLAYER_FORM_HUMAN)) || + ((play->sceneId == SCENE_KOEPONARACE) && + (((GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_3)) || + (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_2)))) { + // Gorman Track and horse state is either STATE_START, STATE_2 or STATE_3 + // or Romani Ranch, Player is Human and scene layer is either 1 or 5 + Horse_SpawnMinigame(play, player); + } else { + Horse_SpawnOverworld(play, player); + } + + D_801BDAA0 = false; +} + +void Horse_RotateToPoint(Actor* actor, Vec3f* pos, s16 turnYaw) { + s16 yaw = Math_Vec3f_Yaw(&actor->world.pos, pos) - actor->world.rot.y; + + if (yaw > turnYaw) { + actor->world.rot.y += turnYaw; + } else if (yaw < -turnYaw) { + actor->world.rot.y -= turnYaw; + } else { + actor->world.rot.y += yaw; + } + + actor->shape.rot.y = actor->world.rot.y; +} + +s32 Horse_IsActive(PlayState* play, ActorContext* actorCtx) { + Actor* bgActor = actorCtx->actorLists[ACTORCAT_BG].first; + + if (bgActor != NULL) { + while (true) { + if ((bgActor->update != NULL) && (bgActor->init == NULL)) { + if (Object_IsLoaded(&play->objectCtx, bgActor->objBankIndex)) { + if ((bgActor->id == ACTOR_EN_HORSE) && (((EnHorse*)bgActor)->action != ENHORSE_ACTION_INACTIVE)) { + return true; + } + } + } + bgActor = bgActor->next; + if (bgActor == NULL) { + break; + } + } + } + + return false; +} diff --git a/src/code/z_sram_NES.c b/src/code/z_sram_NES.c index cfd230569..ac68f0fac 100644 --- a/src/code/z_sram_NES.c +++ b/src/code/z_sram_NES.c @@ -1,5 +1,6 @@ #include "prevent_bss_reordering.h" #include "global.h" +#include "z64horse.h" #include "overlays/gamestates/ovl_file_choose/z_file_choose.h" void func_80146EBC(SramContext* sramCtx, s32 curPage, s32 numPages); @@ -454,7 +455,7 @@ void Sram_SaveEndOfCycle(PlayState* play) { gSaveContext.jinxTimer = 0; gSaveContext.rupeeAccumulator = 0; - func_800F3B2C(play); + Horse_ResetHorseData(play); } void Sram_IncrementDay(void) { @@ -884,8 +885,8 @@ void Sram_ResetSaveFromMoonCrash(SramContext* sramCtx) { gSaveContext.timerPausedOsTimes[i] = 0; } - D_801BDAA0 = 1; - D_801BDA9C = 0; + D_801BDAA0 = true; + gHorseIsMounted = false; gSaveContext.powderKegTimer = 0; gSaveContext.unk_1014 = 0; gSaveContext.jinxTimer = 0; -- cgit v1.2.3