1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-01-14 12:17:08 +00:00

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
This commit is contained in:
mzxrules 2024-12-17 10:51:56 -05:00 committed by GitHub
parent 524597dc14
commit 1adf696588
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 421 additions and 317 deletions

View file

@ -71,13 +71,6 @@ void CutsceneFlags_UnsetAll(PlayState* play);
void CutsceneFlags_Set(PlayState* play, s16 flag); void CutsceneFlags_Set(PlayState* play, s16 flag);
void CutsceneFlags_Unset(PlayState* play, s16 flag); void CutsceneFlags_Unset(PlayState* play, s16 flag);
s32 CutsceneFlags_Get(PlayState* play, s16 flag); s32 CutsceneFlags_Get(PlayState* play, s16 flag);
s32 func_8006CFC0(s32 sceneId);
void func_8006D074(PlayState* play);
void func_8006D0AC(PlayState* play);
void func_8006D0EC(PlayState* play, Player* player);
void func_8006D684(PlayState* play, Player* player);
void func_8006DC68(PlayState* play, Player* player);
void func_8006DD9C(Actor* actor, Vec3f* arg1, s16 arg2);
s32 Kanji_OffsetFromShiftJIS(s32 character); s32 Kanji_OffsetFromShiftJIS(s32 character);
void Font_LoadCharWide(Font* font, u16 character, u16 codePointIndex); void Font_LoadCharWide(Font* font, u16 character, u16 codePointIndex);

View file

@ -118,6 +118,8 @@
#define R_MESSAGE_DEBUGGER_TEXTID YREG(79) #define R_MESSAGE_DEBUGGER_TEXTID YREG(79)
#define R_C_UP_ICON_X YREG(88) #define R_C_UP_ICON_X YREG(88)
#define R_C_UP_ICON_Y YREG(89) #define R_C_UP_ICON_Y YREG(89)
#define R_EXITED_SCENE_RIDING_HORSE AREG(6) // Used to spawn the player on top of Epona in the next scene
#define R_DEBUG_FORCE_EPONA_OBTAINED DREG(1) // If set, overrides EVENTCHKINF_EPONA_OBTAINED state giving Epona
#define R_EPONAS_SONG_PLAYED DREG(53) #define R_EPONAS_SONG_PLAYED DREG(53)
#define R_MAGIC_FILL_COLOR(i) ZREG(0 + (i)) #define R_MAGIC_FILL_COLOR(i) ZREG(0 + (i))
#define R_PAUSE_PAGE_SWITCH_FRAME_ADVANCE_ON ZREG(13) #define R_PAUSE_PAGE_SWITCH_FRAME_ADVANCE_ON ZREG(13)

View file

@ -838,10 +838,10 @@ int func_8002DD78(struct Player* player);
s32 func_8002DDE4(struct PlayState* play); s32 func_8002DDE4(struct PlayState* play);
s32 func_8002DDF4(struct PlayState* play); s32 func_8002DDF4(struct PlayState* play);
void Actor_SwapHookshotAttachment(struct PlayState* play, Actor* srcActor, Actor* destActor); void Actor_SwapHookshotAttachment(struct PlayState* play, Actor* srcActor, Actor* destActor);
void func_8002DE74(struct PlayState* play, struct Player* player); void Actor_RequestHorseCameraSetting(struct PlayState* play, struct Player* player);
void Actor_MountHorse(struct PlayState* play, struct Player* player, Actor* horse); void Actor_MountHorse(struct PlayState* play, struct Player* player, Actor* horse);
int func_8002DEEC(struct Player* player); int func_8002DEEC(struct Player* player);
void func_8002DF18(struct PlayState* play, struct Player* player); void Actor_InitPlayerHorse(struct PlayState* play, struct Player* player);
s32 Player_SetCsAction(struct PlayState* play, Actor* csActor, u8 csAction); s32 Player_SetCsAction(struct PlayState* play, Actor* csActor, u8 csAction);
s32 Player_SetCsActionWithHaltedActors(struct PlayState* play, Actor* csActor, u8 csAction); s32 Player_SetCsActionWithHaltedActors(struct PlayState* play, Actor* csActor, u8 csAction);
void func_8002DF90(DynaPolyActor* dynaActor); void func_8002DF90(DynaPolyActor* dynaActor);

16
include/z64horse.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef Z64HORSE_H
#define Z64HORSE_H
#include "ultra64.h"
#include "z64math.h"
struct PlayState;
struct Actor;
struct Player;
void Horse_ResetHorseData(struct PlayState* play);
void Horse_FixLakeHyliaPosition(struct PlayState* play);
void Horse_InitPlayerHorse(struct PlayState* play, struct Player* player);
void Horse_RotateToPoint(struct Actor* actor, Vec3f* pos, s16 turnAmount);
#endif

View file

@ -893,66 +893,65 @@ typedef enum LinkAge {
* SaveContext.eventInf * SaveContext.eventInf
*/ */
// 0x00-0x0F // EVENTINF 0x00-0x0F
// horses related // Ingo Race, Lon Lon Ranch minigames, and Horseback Archery minigame flags
#define EVENTINF_HORSES_INDEX 0 #define EVENTINF_HORSES_INDEX 0
#define EVENTINF_HORSES_STATE_SHIFT 0 // EVENTINF 0x00-0x03 reserved for IngoRaceState
#define EVENTINF_HORSES_HORSETYPE_SHIFT 4 #define EVENTINF_INGO_RACE_STATE_MASK (0xF << 0)
#define EVENTINF_HORSES_05_SHIFT 5 typedef enum IngoRaceState {
#define EVENTINF_HORSES_06_SHIFT 6 /* 0 */ INGO_RACE_STATE_OFFER_RENTAL,
#define EVENTINF_HORSES_08_SHIFT 8 /* 1 */ INGO_RACE_STATE_HORSE_RENTAL_PERIOD,
#define EVENTINF_HORSES_0A_SHIFT 10 /* 2 */ INGO_RACE_STATE_RACING,
#define EVENTINF_HORSES_0F_SHIFT 15 // unused? /* 3 */ INGO_RACE_STATE_PLAYER_LOSE,
#define EVENTINF_HORSES_STATE_MASK (0xF << EVENTINF_HORSES_STATE_SHIFT) /* 4 */ INGO_RACE_STATE_FIRST_WIN,
#define EVENTINF_HORSES_HORSETYPE_MASK (1 << EVENTINF_HORSES_HORSETYPE_SHIFT) /* 5 */ INGO_RACE_STATE_TRAPPED_WIN_UNUSED,
#define EVENTINF_HORSES_05_MASK (1 << EVENTINF_HORSES_05_SHIFT) /* 6 */ INGO_RACE_STATE_TRAPPED_WIN_EPONA, // Ingo Traps you in Lon Lon
#define EVENTINF_HORSES_06_MASK (1 << EVENTINF_HORSES_06_SHIFT) /* 7 */ INGO_RACE_STATE_REMATCH
#define EVENTINF_HORSES_0F_MASK (1 << EVENTINF_HORSES_0F_SHIFT) } IngoRaceState;
#define EVENTINF_HORSES_05 ((EVENTINF_HORSES_INDEX << 4) | EVENTINF_HORSES_05_SHIFT)
#define EVENTINF_HORSES_06 ((EVENTINF_HORSES_INDEX << 4) | EVENTINF_HORSES_06_SHIFT) #define EVENTINF_INGO_RACE_HORSETYPE 4
#define EVENTINF_INGO_RACE_HORSETYPE_MASK (1 << EVENTINF_INGO_RACE_HORSETYPE)
#define EVENTINF_INGO_RACE_LOST_ONCE 5
#define EVENTINF_INGO_RACE_LOST_ONCE_MASK (1 << EVENTINF_INGO_RACE_LOST_ONCE)
#define EVENTINF_INGO_RACE_SECOND_RACE 6
#define EVENTINF_INGO_RACE_SECOND_RACE_MASK (1 << EVENTINF_INGO_RACE_SECOND_RACE)
// Used in z_en_ta (Talon) to store Cucco game winning status // Used in z_en_ta (Talon) to store Cucco game winning status
// and in z_en_ge1 (Gerudo) to store archery in-progress status // and in z_en_ge1 (Gerudo) to store archery in-progress status
#define EVENTINF_HORSES_08 ((EVENTINF_HORSES_INDEX << 4) | EVENTINF_HORSES_08_SHIFT) #define EVENTINF_HORSES_08 8
#define EVENTINF_CUCCO_GAME_WON EVENTINF_HORSES_08 #define EVENTINF_CUCCO_GAME_WON EVENTINF_HORSES_08
// Used in z_en_ta (Talon) and z_en_ma3 (Malon) to store minigame finishing status // Used in z_en_ta (Talon) and z_en_ma3 (Malon) to store minigame finishing status
#define EVENTINF_HORSES_0A ((EVENTINF_HORSES_INDEX << 4) | EVENTINF_HORSES_0A_SHIFT) #define EVENTINF_HORSES_0A 10
#define EVENTINF_CUCCO_GAME_FINISHED EVENTINF_HORSES_0A #define EVENTINF_CUCCO_GAME_FINISHED EVENTINF_HORSES_0A
#define EVENTINF_INGO_RACE_0F 15 // unused?
typedef enum EventInfHorsesState { #define EVENTINF_INGO_RACE_0F_MASK (1 << EVENTINF_INGO_RACE_0F)
/* 0 */ EVENTINF_HORSES_STATE_0,
/* 1 */ EVENTINF_HORSES_STATE_1,
/* 2 */ EVENTINF_HORSES_STATE_2,
/* 3 */ EVENTINF_HORSES_STATE_3,
/* 4 */ EVENTINF_HORSES_STATE_4,
/* 5 */ EVENTINF_HORSES_STATE_5,
/* 6 */ EVENTINF_HORSES_STATE_6,
/* 7 */ EVENTINF_HORSES_STATE_7
} EventInfHorsesState;
// "InRaceSeq" // "InRaceSeq"
#define GET_EVENTINF_HORSES_STATE() \ #define GET_EVENTINF_INGO_RACE_STATE() (gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & EVENTINF_INGO_RACE_STATE_MASK)
((gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & EVENTINF_HORSES_STATE_MASK) >> EVENTINF_HORSES_STATE_SHIFT)
#define SET_EVENTINF_HORSES_STATE(v) \ #define SET_EVENTINF_INGO_RACE_STATE(v) \
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & ~EVENTINF_HORSES_STATE_MASK) | \
((v) << EVENTINF_HORSES_STATE_SHIFT)
#define GET_EVENTINF_HORSES_HORSETYPE() \
((gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & EVENTINF_HORSES_HORSETYPE_MASK) >> EVENTINF_HORSES_HORSETYPE_SHIFT)
#define SET_EVENTINF_HORSES_HORSETYPE(v) \
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & ~EVENTINF_HORSES_HORSETYPE_MASK) | \
((v) << EVENTINF_HORSES_HORSETYPE_SHIFT)
#define SET_EVENTINF_HORSES_0F(v) \
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \ gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & ~EVENTINF_HORSES_0F_MASK) | ((v) << EVENTINF_HORSES_0F_SHIFT) (gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & ~EVENTINF_INGO_RACE_STATE_MASK) | (v)
#define GET_EVENTINF_INGO_RACE_FLAG(flag) \
((gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & (1 << ((flag) & 0xF))) >> ((flag) & 0xF))
#define SET_EVENTINF_INGO_RACE_FLAG(flag) \
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & 0xFFFF) | (1 << ((flag) & 0xF))
#define WRITE_EVENTINF_INGO_RACE_FLAG(flag, v) \
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = \
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & ~(1 << ((flag) & 0xF))) | ((v) << ((flag) & 0xF))
#define GET_EVENTINF_INGO_RACE_HORSETYPE() GET_EVENTINF_INGO_RACE_FLAG(EVENTINF_INGO_RACE_HORSETYPE)
#define WRITE_EVENTINF_INGO_RACE_HORSETYPE(v) WRITE_EVENTINF_INGO_RACE_FLAG(EVENTINF_INGO_RACE_HORSETYPE, v)
#define WRITE_EVENTINF_INGO_RACE_0F(v) WRITE_EVENTINF_INGO_RACE_FLAG(EVENTINF_INGO_RACE_0F, v)
// Is the running man race active // Is the running man race active
#define EVENTINF_MARATHON_ACTIVE 0x10 #define EVENTINF_MARATHON_ACTIVE 0x10
// 0x20-0x24 // EVENTINF 0x20-0x24
#define EVENTINF_20_21_22_23_24_INDEX 2 #define EVENTINF_20_21_22_23_24_INDEX 2
#define EVENTINF_20_MASK (1 << 0) #define EVENTINF_20_MASK (1 << 0)
#define EVENTINF_21_MASK (1 << 1) #define EVENTINF_21_MASK (1 << 1)
@ -962,7 +961,6 @@ typedef enum EventInfHorsesState {
#define EVENTINF_30 0x30 #define EVENTINF_30 0x30
#define GET_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] & (1 << ((flag) & 0xF))) #define GET_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] & (1 << ((flag) & 0xF)))
#define SET_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] |= (1 << ((flag) & 0xF))) #define SET_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] |= (1 << ((flag) & 0xF)))
#define CLEAR_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] &= ~(1 << ((flag) & 0xF))) #define CLEAR_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] &= ~(1 << ((flag) & 0xF)))

View file

@ -4,6 +4,7 @@
#include "rand.h" #include "rand.h"
#include "terminal.h" #include "terminal.h"
#include "versions.h" #include "versions.h"
#include "z64horse.h"
#include "overlays/actors/ovl_Arms_Hook/z_arms_hook.h" #include "overlays/actors/ovl_Arms_Hook/z_arms_hook.h"
#include "overlays/actors/ovl_En_Part/z_en_part.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; 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)) { if ((play->roomCtx.curRoom.type != ROOM_TYPE_4) && Play_CamIsNotFixed(play)) {
Camera_RequestSetting(Play_GetCamera(play, CAM_ID_MAIN), CAM_SET_HORSE); 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); (player->csAction != PLAYER_CSACTION_NONE);
} }
void func_8002DF18(PlayState* play, Player* player) { void Actor_InitPlayerHorse(PlayState* play, Player* player) {
func_8006DC68(play, player); Horse_InitPlayerHorse(play, player);
} }
/** /**

View file

@ -5,7 +5,7 @@
#include "overlays/actors/ovl_En_Horse/z_en_horse.h" #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" \ #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); s16 Camera_RequestSettingImpl(Camera* camera, s16 requestedSetting, s16 flags);
s32 Camera_RequestModeImpl(Camera* camera, s16 requestedMode, u8 forceModeChange); 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" \ #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) { s32 Camera_KeepOn4(Camera* camera) {
static Vec3f D_8015BD50; static Vec3f D_8015BD50;

View file

@ -1,30 +1,47 @@
#include "global.h"
#include "terminal.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" #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, s32 validSceneIds[] = { SCENE_HYRULE_FIELD, SCENE_LAKE_HYLIA, SCENE_GERUDO_VALLEY, SCENE_GERUDOS_FORTRESS,
SCENE_LON_LON_RANCH }; SCENE_LON_LON_RANCH };
s32 i; s32 i;
for (i = 0; i < ARRAY_COUNT(validSceneIds); i++) { for (i = 0; i < ARRAY_COUNT(validSceneIds); i++) {
if (sceneId == 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.sceneId = SCENE_HYRULE_FIELD;
gSaveContext.save.info.horseData.pos.x = -1840; gSaveContext.save.info.horseData.pos.x = -1840;
gSaveContext.save.info.horseData.pos.y = 72; gSaveContext.save.info.horseData.pos.y = 72;
gSaveContext.save.info.horseData.pos.z = 5497; 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) { if (gSaveContext.save.info.horseData.sceneId == SCENE_LAKE_HYLIA) {
gSaveContext.save.info.horseData.sceneId = SCENE_LAKE_HYLIA; gSaveContext.save.info.horseData.sceneId = SCENE_LAKE_HYLIA;
gSaveContext.save.info.horseData.pos.x = -2065; gSaveContext.save.info.horseData.pos.x = -2065;
@ -41,49 +58,59 @@ typedef struct HorseSpawn {
/* 0x0A */ s16 type; /* 0x0A */ s16 type;
} HorseSpawn; } HorseSpawn;
void func_8006D0EC(PlayState* play, Player* player) { void Horse_SetupInGameplay(PlayState* play, Player* player) {
s32 i; s32 i;
HorseSpawn horseSpawns[] = { HorseSpawn horseSpawns[] = {
{ SCENE_HYRULE_FIELD, -460, 100, 6640, 0, 2 }, { SCENE_LAKE_HYLIA, -1929, -1025, 768, 0, 2 }, { SCENE_HYRULE_FIELD, -460, 100, 6640, 0, HORSE_PTYPE_INACTIVE },
{ SCENE_GERUDO_VALLEY, 2566, -259, 767, 0, 2 }, { SCENE_GERUDOS_FORTRESS, -328, 10, 953, 0, 2 }, { SCENE_LAKE_HYLIA, -1929, -1025, 768, 0, HORSE_PTYPE_INACTIVE },
{ SCENE_LON_LON_RANCH, 928, 0, -2280, 0, 2 }, { 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))) { if (R_EXITED_SCENE_RIDING_HORSE &&
player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, player->actor.world.pos.x, (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) {
player->actor.world.pos.y, player->actor.world.pos.z, player->actor.shape.rot.x, // Player entering scene on top of horse
player->actor.shape.rot.y, player->actor.shape.rot.z, 9); 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); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 343);
Actor_MountHorse(play, player, player->rideActor); Actor_MountHorse(play, player, player->rideActor);
func_8002DE74(play, player); Actor_RequestHorseCameraSetting(play, player);
gSaveContext.save.info.horseData.sceneId = play->sceneId; gSaveContext.save.info.horseData.sceneId = play->sceneId;
if (play->sceneId == SCENE_GERUDOS_FORTRESS) { if (play->sceneId == SCENE_GERUDOS_FORTRESS) {
player->rideActor->room = -1; player->rideActor->room = -1;
} }
} else if ((play->sceneId == SCENE_GERUDOS_FORTRESS) && (gSaveContext.minigameState == 3)) { } else if ((play->sceneId == SCENE_GERUDOS_FORTRESS) && (gSaveContext.minigameState == 3)) {
// Completed Horseback Archery Minigame
Actor* horseActor; Actor* horseActor;
gSaveContext.minigameState = 0; 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; horseActor->room = -1;
} else if ((gSaveContext.save.entranceIndex == ENTR_LON_LON_RANCH_7) && } else if ((gSaveContext.save.entranceIndex == ENTR_LON_LON_RANCH_7) &&
GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) { GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) {
// Completed Horse Race
Actor* horseActor = 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); ASSERT(horseActor != NULL, "horse_actor != NULL", "../z_horse.c", 389);
} else if ((play->sceneId == gSaveContext.save.info.horseData.sceneId) && } 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"), 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* horseActor =
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, gSaveContext.save.info.horseData.pos.x, 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.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); ASSERT(horseActor != NULL, "horse_actor != NULL", "../z_horse.c", 414);
if (play->sceneId == SCENE_GERUDOS_FORTRESS) { if (play->sceneId == SCENE_GERUDOS_FORTRESS) {
horseActor->room = -1; 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"), T("Horse_SetNormal():%d セットスポットまずいです。\n", "Horse_SetNormal():%d set spot is no good.\n"),
gSaveContext.save.info.horseData.sceneId); gSaveContext.save.info.horseData.sceneId);
PRINTF(VT_RST); PRINTF(VT_RST);
func_8006D074(play); Horse_ResetHorseData(play);
} }
} else if ((play->sceneId == SCENE_LON_LON_RANCH) && !Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && } else if ((play->sceneId == SCENE_LON_LON_RANCH) &&
(DREG(1) == 0)) { !(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) {
Actor* horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -500.0f, 0, 0, 0, 1); // 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); 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++) { for (i = 0; i < ARRAY_COUNT(horseSpawns); i++) {
HorseSpawn* horseSpawn = &horseSpawns[i]; HorseSpawn* horseSpawn = &horseSpawns[i];
if (horseSpawn->sceneId == play->sceneId) { 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, Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawn->pos.x, horseSpawn->pos.y,
horseSpawn->pos.z, 0, horseSpawn->angle, 0, horseSpawn->type); horseSpawn->pos.z, 0, horseSpawn->angle, 0, horseSpawn->type);
ASSERT(horseActor != NULL, "horse_actor != NULL", "../z_horse.c", 466); ASSERT(horseActor != NULL, "horse_actor != NULL", "../z_horse.c", 466);
if (play->sceneId == SCENE_GERUDOS_FORTRESS) { if (play->sceneId == SCENE_GERUDOS_FORTRESS) {
horseActor->room = -1; horseActor->room = -1;
} }
break; break;
} }
} }
} else if (!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED)) { } else if (!(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED) &&
if ((DREG(1) == 0) && (play->sceneId == SCENE_LON_LON_BUILDINGS) && !IS_DAY) { (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); 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; /* 0x00 */ s16 sceneId;
/* 0x04 */ s32 cutsceneIndex; /* 0x04 */ s32 cutsceneIndex;
/* 0x08 */ Vec3s pos; /* 0x08 */ Vec3s pos;
/* 0x0E */ s16 angle; /* 0x0E */ s16 angle;
/* 0x10 */ s16 type; /* 0x10 */ s16 type;
} struct_8011F9B8; } HorseCutsceneSpawn;
void func_8006D684(PlayState* play, Player* player) { void Horse_SetupInCutscene(PlayState* play, Player* player) {
static struct_8011F9B8 D_8011F9B8[] = { static HorseCutsceneSpawn horseSpawns[] = {
{ SCENE_GERUDOS_FORTRESS, 0xFFF0, { 3600, 1413, 360 }, 0x8001, 8 }, { SCENE_GERUDOS_FORTRESS, 0xFFF0, { 3600, 1413, 360 }, 0x8001, HORSE_PTYPE_HORSEBACK_ARCHERY },
{ SCENE_LON_LON_RANCH, 0xFFF0, { -250, 1, -1580 }, 0x4000, 6 }, { SCENE_LON_LON_RANCH, 0xFFF0, { -250, 1, -1580 }, 0x4000, HORSE_PTYPE_6 }, // Horse Race
{ SCENE_LON_LON_RANCH, 0xFFF1, { 0, 0, 0 }, 0x0000, 5 }, { 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, 7 }, { SCENE_LON_LON_RANCH, 0xFFF5, { 0, 0, 0 }, 0x0000, HORSE_PTYPE_7 }, // Credits
{ SCENE_HYRULE_FIELD, 0xFFF3, { -2961, 313, 7700 }, 0x0000, 7 }, { SCENE_HYRULE_FIELD, 0xFFF3, { -2961, 313, 7700 }, 0x0000, HORSE_PTYPE_7 }, // Title Screen
{ SCENE_HYRULE_FIELD, 0xFFF4, { -1900, 313, 7015 }, 0x0000, 7 }, { SCENE_HYRULE_FIELD, 0xFFF4, { -1900, 313, 7015 }, 0x0000, HORSE_PTYPE_7 },
{ SCENE_HYRULE_FIELD, 0xFFF5, { -4043, 313, 6933 }, 0x0000, 7 }, { SCENE_HYRULE_FIELD, 0xFFF5, { -4043, 313, 6933 }, 0x0000, HORSE_PTYPE_7 }, // Credits
{ SCENE_HYRULE_FIELD, 0xFFF6, { -4043, 313, 6933 }, 0x0000, 7 }, { SCENE_HYRULE_FIELD, 0xFFF6, { -4043, 313, 6933 }, 0x0000, HORSE_PTYPE_7 }, // Unused. Hopping Lon Lon
// Ranch North Gate
}; };
s32 pad; s32 pad;
s32 i; s32 i;
Vec3s spawnPos;
if ((gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_11 || if ((gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_11 ||
gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12 ||
gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13 ||
gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15) && gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15) &&
(gSaveContext.respawnFlag == 0)) { (gSaveContext.respawnFlag == 0)) {
// Epona hopping over one of the Lon Lon Ranch fences
Vec3s spawnPos;
Vec3s spawnPositions[] = { Vec3s spawnPositions[] = {
{ -2961, 313, 7700 }, // Note: The east and west positions are paired with the wrong entranceIndex. However, the subsequent
{ -1900, 313, 7015 }, // cutscene repositions the horse will override these coordinates while the horse is still obstructed, so no
{ -4043, 313, 6933 }, // visual glitch occurs.
{ -2313, 313, 5990 }, { -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) { if (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_11) {
spawnPos = spawnPositions[0]; spawnPos = spawnPositions[0];
// West of Lon Lon player spawn
} else if (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12) { } else if (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12) {
spawnPos = spawnPositions[1]; spawnPos = spawnPositions[1];
// East of Lon Lon player spawn
} else if (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13) { } else if (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13) {
spawnPos = spawnPositions[2]; spawnPos = spawnPositions[2];
// Lon Lon exit player spawn
} else { } else {
spawnPos = spawnPositions[3]; spawnPos = spawnPositions[3];
} }
player->rideActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, spawnPos.x, spawnPos.y, spawnPos.z, 0, 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); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 561);
Actor_MountHorse(play, player, player->rideActor); Actor_MountHorse(play, player, player->rideActor);
func_8002DE74(play, player); Actor_RequestHorseCameraSetting(play, player);
gSaveContext.save.info.horseData.sceneId = play->sceneId; gSaveContext.save.info.horseData.sceneId = play->sceneId;
} else if ((play->sceneId == SCENE_LON_LON_RANCH) && (GET_EVENTINF_HORSES_STATE() == EVENTINF_HORSES_STATE_6) && } else if ((play->sceneId == SCENE_LON_LON_RANCH) &&
!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && (DREG(1) == 0)) { (GET_EVENTINF_INGO_RACE_STATE() == INGO_RACE_STATE_TRAPPED_WIN_EPONA) &&
!(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) {
player->rideActor = 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); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 582);
Actor_MountHorse(play, player, player->rideActor); Actor_MountHorse(play, player, player->rideActor);
func_8002DE74(play, player); Actor_RequestHorseCameraSetting(play, player);
gSaveContext.save.info.horseData.sceneId = play->sceneId; gSaveContext.save.info.horseData.sceneId = play->sceneId;
if (play->sceneId == SCENE_GERUDOS_FORTRESS) { if (play->sceneId == SCENE_GERUDOS_FORTRESS) {
player->rideActor->room = -1; player->rideActor->room = -1;
} }
} else { } else {
for (i = 0; i < ARRAY_COUNT(D_8011F9B8); i++) { for (i = 0; i < ARRAY_COUNT(horseSpawns); i++) {
if ((play->sceneId == D_8011F9B8[i].sceneId) && if ((play->sceneId == horseSpawns[i].sceneId) &&
(((void)0, gSaveContext.save.cutsceneIndex) == D_8011F9B8[i].cutsceneIndex)) { (((void)0, gSaveContext.save.cutsceneIndex) == horseSpawns[i].cutsceneIndex)) {
if (D_8011F9B8[i].type == 7) { if (horseSpawns[i].type == HORSE_PTYPE_7) {
if ((play->sceneId == SCENE_LON_LON_RANCH) && if ((play->sceneId == SCENE_LON_LON_RANCH) &&
(((void)0, gSaveContext.save.cutsceneIndex) == 0xFFF1)) { (((void)0, gSaveContext.save.cutsceneIndex) == 0xFFF1)) {
D_8011F9B8[i].pos.x = player->actor.world.pos.x; horseSpawns[i].pos.x = player->actor.world.pos.x;
D_8011F9B8[i].pos.y = player->actor.world.pos.y; horseSpawns[i].pos.y = player->actor.world.pos.y;
D_8011F9B8[i].pos.z = player->actor.world.pos.z; horseSpawns[i].pos.z = player->actor.world.pos.z;
} }
player->rideActor = player->rideActor =
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawns[i].pos.x, horseSpawns[i].pos.y,
D_8011F9B8[i].pos.z, 0, player->actor.world.rot.y, 0, D_8011F9B8[i].type); 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); ASSERT(player->rideActor != NULL, "player->ride.actor != NULL", "../z_horse.c", 628);
Actor_MountHorse(play, player, player->rideActor); Actor_MountHorse(play, player, player->rideActor);
func_8002DE74(play, player); Actor_RequestHorseCameraSetting(play, player);
} else if ((D_8011F9B8[i].type == 5) || (D_8011F9B8[i].type == 6) || (D_8011F9B8[i].type == 8)) { } else if ((horseSpawns[i].type == HORSE_PTYPE_5) || (horseSpawns[i].type == HORSE_PTYPE_6) ||
Vec3f sp54; (horseSpawns[i].type == HORSE_PTYPE_HORSEBACK_ARCHERY)) {
s32 temp = 0; Vec3f eye;
s32 paramFlag = 0;
if (GET_EVENTINF_HORSES_HORSETYPE() != HORSE_EPONA && D_8011F9B8[i].type == 6) {
temp = 0x8000; if (GET_EVENTINF_INGO_RACE_HORSETYPE() != HORSE_EPONA && horseSpawns[i].type == HORSE_PTYPE_6) {
// HORSE_HNI
paramFlag = 0x8000;
} }
player->rideActor = player->rideActor =
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawns[i].pos.x, horseSpawns[i].pos.y,
D_8011F9B8[i].pos.z, 0, D_8011F9B8[i].angle, 0, D_8011F9B8[i].type | temp); 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); 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.x = horseSpawns[i].pos.x;
player->actor.world.pos.y = D_8011F9B8[i].pos.y; player->actor.world.pos.y = horseSpawns[i].pos.y;
player->actor.world.pos.z = D_8011F9B8[i].pos.z; player->actor.world.pos.z = horseSpawns[i].pos.z;
player->actor.shape.rot.x = player->actor.shape.rot.z = 0; 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); Actor_MountHorse(play, player, player->rideActor);
func_8002DE74(play, player); Actor_RequestHorseCameraSetting(play, player);
sp54.x = player->actor.world.pos.x - 200.0f; eye.x = player->actor.world.pos.x - 200.0f;
sp54.y = player->actor.world.pos.y + 100.0f; eye.y = player->actor.world.pos.y + 100.0f;
sp54.z = player->actor.world.pos.z; 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 { } else {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, D_8011F9B8[i].pos.x, D_8011F9B8[i].pos.y, Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawns[i].pos.x, horseSpawns[i].pos.y,
D_8011F9B8[i].pos.z, 0, D_8011F9B8[i].angle, 0, D_8011F9B8[i].type); horseSpawns[i].pos.z, 0, horseSpawns[i].angle, 0, horseSpawns[i].type);
} }
break; 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 (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(VT_COL(RED, WHITE));
PRINTF( PRINTF(
T("Horse_Set_Check():%d セットスポットまずいです。\n", "Horse_Set_Check():%d set spot is no good.\n"), T("Horse_Set_Check():%d セットスポットまずいです。\n", "Horse_Set_Check():%d set spot is no good.\n"),
gSaveContext.save.info.horseData.sceneId); gSaveContext.save.info.horseData.sceneId);
PRINTF(VT_RST); PRINTF(VT_RST);
func_8006D074(play); Horse_ResetHorseData(play);
} }
if (func_8006CFC0(play->sceneId)) { if (Horse_CanSpawn(play->sceneId)) {
if (IS_CUTSCENE_LAYER || 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_11 ||
gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_12 ||
gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13 || gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13 ||
gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15) && gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15) &&
(gSaveContext.respawnFlag == 0)) || (gSaveContext.respawnFlag == 0)) ||
((play->sceneId == SCENE_LON_LON_RANCH) && (GET_EVENTINF_HORSES_STATE() == EVENTINF_HORSES_STATE_6) && // trapped in Lon Lon Ranch
!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && (DREG(1) == 0))) { ((play->sceneId == SCENE_LON_LON_RANCH) &&
func_8006D684(play, player); (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 { } else {
func_8006D0EC(play, player); Horse_SetupInGameplay(play, player);
} }
} }
} }
} }
void func_8006DD9C(Actor* actor, Vec3f* arg1, s16 arg2) { void Horse_RotateToPoint(Actor* actor, Vec3f* pos, s16 turnAmount) {
s16 x = Math_Vec3f_Yaw(&actor->world.pos, arg1) - actor->world.rot.y; s16 x = Math_Vec3f_Yaw(&actor->world.pos, pos) - actor->world.rot.y;
if (x > arg2) { if (x > turnAmount) {
actor->world.rot.y += arg2; actor->world.rot.y += turnAmount;
} else if (x < -arg2) { } else if (x < -turnAmount) {
actor->world.rot.y -= arg2; actor->world.rot.y -= turnAmount;
} else { } else {
actor->world.rot.y += x; actor->world.rot.y += x;
} }

View file

@ -3444,7 +3444,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
if (msgCtx->disableWarpSongs || interfaceCtx->restrictions.warpSongs == 3) { if (msgCtx->disableWarpSongs || interfaceCtx->restrictions.warpSongs == 3) {
Message_StartTextbox(play, 0x88C, NULL); // "You can't warp here!" Message_StartTextbox(play, 0x88C, NULL); // "You can't warp here!"
play->msgCtx.ocarinaMode = OCARINA_MODE_04; 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, Message_StartTextbox(play, msgCtx->lastPlayedSong + 0x88D,
NULL); // "Warp to [place name]?" NULL); // "Warp to [place name]?"
play->msgCtx.ocarinaMode = OCARINA_MODE_01; play->msgCtx.ocarinaMode = OCARINA_MODE_01;
@ -4247,7 +4247,7 @@ void Message_Update(PlayState* play) {
if (Message_ShouldAdvance(play)) { if (Message_ShouldAdvance(play)) {
PRINTF("OCARINA_MODE=%d -> ", play->msgCtx.ocarinaMode); PRINTF("OCARINA_MODE=%d -> ", play->msgCtx.ocarinaMode);
play->msgCtx.ocarinaMode = (msgCtx->choiceIndex == 0) ? OCARINA_MODE_02 : OCARINA_MODE_04; 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); play->msgCtx.ocarinaMode);
Message_CloseTextbox(play); Message_CloseTextbox(play);
PRINTF("OCARINA_MODE=%d\n", play->msgCtx.ocarinaMode); PRINTF("OCARINA_MODE=%d\n", play->msgCtx.ocarinaMode);

View file

@ -1,6 +1,7 @@
#include "global.h" #include "global.h"
#include "terminal.h" #include "terminal.h"
#include "versions.h" #include "versions.h"
#include "z64horse.h"
#include "assets/textures/parameter_static/parameter_static.h" #include "assets/textures/parameter_static/parameter_static.h"
#include "assets/textures/do_action_static/do_action_static.h" #include "assets/textures/do_action_static/do_action_static.h"
#include "assets/textures/icon_item_static/icon_item_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; gSaveContext.hudVisibilityMode = HUD_VISIBILITY_NO_CHANGE;
Interface_ChangeHudVisibilityMode(HUD_VISIBILITY_ALL); 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 (player->stateFlags1 & PLAYER_STATE1_23) {
if ((gSaveContext.save.info.equips.buttonItems[0] != ITEM_NONE) && if ((gSaveContext.save.info.equips.buttonItems[0] != ITEM_NONE) &&
(gSaveContext.save.info.equips.buttonItems[0] != ITEM_BOW)) { (gSaveContext.save.info.equips.buttonItems[0] != ITEM_BOW)) {
@ -1387,7 +1388,7 @@ u8 Item_Give(PlayState* play, u8 item) {
PRINTF(VT_RST); PRINTF(VT_RST);
if (item == ITEM_MEDALLION_WATER) { if (item == ITEM_MEDALLION_WATER) {
func_8006D0AC(play); Horse_FixLakeHyliaPosition(play);
} }
return ITEM_NONE; return ITEM_NONE;
@ -3545,8 +3546,9 @@ void Interface_Draw(PlayState* play) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[svar1]) { if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[svar1]) {
#if OOT_VERSION >= NTSC_1_1 #if OOT_VERSION >= NTSC_1_1
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] &= gSaveContext.eventInf[EVENTINF_HORSES_INDEX] &=
(u16) ~(EVENTINF_HORSES_STATE_MASK | EVENTINF_HORSES_HORSETYPE_MASK | EVENTINF_HORSES_05_MASK | (u16) ~(EVENTINF_INGO_RACE_STATE_MASK | EVENTINF_INGO_RACE_HORSETYPE_MASK |
EVENTINF_HORSES_06_MASK | EVENTINF_HORSES_0F_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]); PRINTF("EVENT_INF=%x\n", gSaveContext.eventInf[EVENTINF_HORSES_INDEX]);
#endif #endif
play->nextEntranceIndex = spoilingItemEntrances[svar1]; play->nextEntranceIndex = spoilingItemEntrances[svar1];

View file

@ -489,7 +489,7 @@ void Play_Init(GameState* thisx) {
Environment_PlaySceneSequence(this); Environment_PlaySceneSequence(this);
gSaveContext.seqId = this->sceneSequences.seqId; gSaveContext.seqId = this->sceneSequences.seqId;
gSaveContext.natureAmbienceId = this->sceneSequences.natureAmbienceId; gSaveContext.natureAmbienceId = this->sceneSequences.natureAmbienceId;
func_8002DF18(this, GET_PLAYER(this)); Actor_InitPlayerHorse(this, GET_PLAYER(this));
AnimTaskQueue_Update(this, &this->animTaskQueue); AnimTaskQueue_Update(this, &this->animTaskQueue);
gSaveContext.respawnFlag = 0; 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_12) ||
(gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13) || (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_13) ||
(gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15)) { (gSaveContext.save.entranceIndex == ENTR_HYRULE_FIELD_15)) {
// Avoid re-triggering the hop over Lon Lon fence cutscenes
this->nextEntranceIndex = ENTR_HYRULE_FIELD_6; this->nextEntranceIndex = ENTR_HYRULE_FIELD_6;
#endif #endif
} else { } else {

View file

@ -52,7 +52,7 @@ void BgInGate_Init(Actor* thisx, PlayState* play) {
Actor_SetScale(&this->dyna.actor, 0.1f); Actor_SetScale(&this->dyna.actor, 0.1f);
if ((PARAMS_GET_U(this->dyna.actor.params, 0, 1) != 0) && if ((PARAMS_GET_U(this->dyna.actor.params, 0, 1) != 0) &&
(GET_EVENTINF_HORSES_STATE() == EVENTINF_HORSES_STATE_6)) { (GET_EVENTINF_INGO_RACE_STATE() == INGO_RACE_STATE_TRAPPED_WIN_EPONA)) {
play->csCtx.curFrame = 0; play->csCtx.curFrame = 0;
BgInGate_SetupAction(this, func_80892890); BgInGate_SetupAction(this, func_80892890);
} else { } else {

View file

@ -41,7 +41,7 @@ void BgUmaJump_Init(Actor* thisx, PlayState* play) {
this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, &this->dyna.actor, colHeader); this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, &this->dyna.actor, colHeader);
if (this->dyna.actor.params == 1) { if (this->dyna.actor.params == 1) {
if (!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && (DREG(1) == 0)) { if (!(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) {
Actor_Kill(&this->dyna.actor); Actor_Kill(&this->dyna.actor);
return; return;
} }

View file

@ -5,6 +5,7 @@
*/ */
#include "z_en_ge1.h" #include "z_en_ge1.h"
#include "z64horse.h"
#include "terminal.h" #include "terminal.h"
#include "assets/objects/object_ge1/object_ge1.h" #include "assets/objects/object_ge1/object_ge1.h"
@ -224,7 +225,7 @@ void EnGe1_KickPlayer(EnGe1* this, PlayState* play) {
if (this->cutsceneTimer > 0) { if (this->cutsceneTimer > 0) {
this->cutsceneTimer--; this->cutsceneTimer--;
} else { } else {
func_8006D074(play); Horse_ResetHorseData(play);
if ((INV_CONTENT(ITEM_HOOKSHOT) == ITEM_NONE) || (INV_CONTENT(ITEM_LONGSHOT) == ITEM_NONE)) { if ((INV_CONTENT(ITEM_HOOKSHOT) == ITEM_NONE) || (INV_CONTENT(ITEM_LONGSHOT) == ITEM_NONE)) {
play->nextEntranceIndex = ENTR_GERUDO_VALLEY_1; play->nextEntranceIndex = ENTR_GERUDO_VALLEY_1;

View file

@ -5,6 +5,7 @@
*/ */
#include "z_en_ge2.h" #include "z_en_ge2.h"
#include "z64horse.h"
#include "terminal.h" #include "terminal.h"
#include "assets/objects/object_gla/object_gla.h" #include "assets/objects/object_gla/object_gla.h"
@ -238,7 +239,7 @@ void EnGe2_CaptureClose(EnGe2* this, PlayState* play) {
if (this->timer > 0) { if (this->timer > 0) {
this->timer--; this->timer--;
} else { } else {
func_8006D074(play); Horse_ResetHorseData(play);
if ((INV_CONTENT(ITEM_HOOKSHOT) == ITEM_NONE) || (INV_CONTENT(ITEM_LONGSHOT) == ITEM_NONE)) { if ((INV_CONTENT(ITEM_HOOKSHOT) == ITEM_NONE) || (INV_CONTENT(ITEM_LONGSHOT) == ITEM_NONE)) {
play->nextEntranceIndex = ENTR_GERUDO_VALLEY_1; play->nextEntranceIndex = ENTR_GERUDO_VALLEY_1;
@ -264,7 +265,7 @@ void EnGe2_CaptureCharge(EnGe2* this, PlayState* play) {
if (this->timer > 0) { if (this->timer > 0) {
this->timer--; this->timer--;
} else { } else {
func_8006D074(play); Horse_ResetHorseData(play);
if ((INV_CONTENT(ITEM_HOOKSHOT) == ITEM_NONE) || (INV_CONTENT(ITEM_LONGSHOT) == ITEM_NONE)) { if ((INV_CONTENT(ITEM_HOOKSHOT) == ITEM_NONE) || (INV_CONTENT(ITEM_LONGSHOT) == ITEM_NONE)) {
play->nextEntranceIndex = ENTR_GERUDO_VALLEY_1; play->nextEntranceIndex = ENTR_GERUDO_VALLEY_1;

View file

@ -5,6 +5,7 @@
*/ */
#include "z_en_horse.h" #include "z_en_horse.h"
#include "z64horse.h"
#include "global.h" #include "global.h"
#include "versions.h" #include "versions.h"
#include "overlays/actors/ovl_En_In/z_en_in.h" #include "overlays/actors/ovl_En_In/z_en_in.h"
@ -525,7 +526,7 @@ void EnHorse_RaceWaypointPos(RaceWaypoint* waypoints, s32 index, Vec3f* pos) {
} }
void EnHorse_RotateToPoint(EnHorse* this, PlayState* play, Vec3f* pos, s16 turnAmount) { void EnHorse_RotateToPoint(EnHorse* this, PlayState* play, Vec3f* pos, s16 turnAmount) {
func_8006DD9C(&this->actor, pos, turnAmount); Horse_RotateToPoint(&this->actor, pos, turnAmount);
} }
void EnHorse_UpdateIngoRaceInfo(EnHorse* this, PlayState* play, RaceInfo* raceInfo) { void EnHorse_UpdateIngoRaceInfo(EnHorse* this, PlayState* play, RaceInfo* raceInfo) {
@ -678,7 +679,7 @@ s32 EnHorse_Spawn(EnHorse* this, PlayState* play) {
if (play->sceneId != SCENE_LON_LON_RANCH || if (play->sceneId != SCENE_LON_LON_RANCH ||
//! Same flag checked twice //! Same flag checked twice
(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) &&
(GET_EVENTINF_HORSES_STATE() != EVENTINF_HORSES_STATE_6 || (GET_EVENTINF_INGO_RACE_STATE() != INGO_RACE_STATE_TRAPPED_WIN_EPONA ||
Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED))) || Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED))) ||
// always load two spawns inside lon lon // always load two spawns inside lon lon
((sHorseSpawns[i].pos.x == 856 && sHorseSpawns[i].pos.y == 0 && sHorseSpawns[i].pos.z == -918) || ((sHorseSpawns[i].pos.x == 856 && sHorseSpawns[i].pos.y == 0 && sHorseSpawns[i].pos.z == -918) ||
@ -747,7 +748,7 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) {
EnHorse* this = (EnHorse*)thisx; EnHorse* this = (EnHorse*)thisx;
PlayState* play = play2; PlayState* play = play2;
AREG(6) = 0; R_EXITED_SCENE_RIDING_HORSE = false;
Actor_ProcessInitChain(&this->actor, sInitChain); Actor_ProcessInitChain(&this->actor, sInitChain);
EnHorse_ClearDustFlags(&this->dustFlags); EnHorse_ClearDustFlags(&this->dustFlags);
R_EPONAS_SONG_PLAYED = false; R_EPONAS_SONG_PLAYED = false;
@ -782,7 +783,7 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) {
// params was -1 // params was -1
if (this->actor.params == 0x7FFF) { if (this->actor.params == 0x7FFF) {
this->actor.params = 1; this->actor.params = HORSE_PTYPE_1;
} }
if (play->sceneId == SCENE_LON_LON_BUILDINGS) { if (play->sceneId == SCENE_LON_LON_BUILDINGS) {
@ -790,25 +791,25 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) {
} else if (play->sceneId == SCENE_GERUDOS_FORTRESS && this->type == HORSE_HNI) { } else if (play->sceneId == SCENE_GERUDOS_FORTRESS && this->type == HORSE_HNI) {
this->stateFlags = ENHORSE_FLAG_18 | ENHORSE_UNRIDEABLE; this->stateFlags = ENHORSE_FLAG_18 | ENHORSE_UNRIDEABLE;
} else { } else {
if (this->actor.params == 3) { if (this->actor.params == HORSE_PTYPE_INGO_SPAWNED_RIDING) {
this->stateFlags = ENHORSE_FLAG_19 | ENHORSE_CANT_JUMP | ENHORSE_UNRIDEABLE; this->stateFlags = ENHORSE_FLAG_19 | ENHORSE_CANT_JUMP | ENHORSE_UNRIDEABLE;
} else if (this->actor.params == 6) { } else if (this->actor.params == HORSE_PTYPE_6) {
this->stateFlags = ENHORSE_FLAG_19 | ENHORSE_CANT_JUMP; this->stateFlags = ENHORSE_FLAG_19 | ENHORSE_CANT_JUMP;
if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || DREG(1) != 0) { if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED) {
this->stateFlags &= ~ENHORSE_CANT_JUMP; this->stateFlags &= ~ENHORSE_CANT_JUMP;
this->stateFlags |= ENHORSE_FLAG_26; this->stateFlags |= ENHORSE_FLAG_26;
} else if (GET_EVENTINF(EVENTINF_HORSES_06) && this->type == HORSE_HNI) { } else if (GET_EVENTINF(EVENTINF_INGO_RACE_SECOND_RACE) && this->type == HORSE_HNI) {
this->stateFlags |= ENHORSE_FLAG_21 | ENHORSE_FLAG_20; this->stateFlags |= ENHORSE_FLAG_21 | ENHORSE_FLAG_20;
} }
} else if (this->actor.params == 1) { } else if (this->actor.params == HORSE_PTYPE_1) {
this->stateFlags = ENHORSE_FLAG_7; this->stateFlags = ENHORSE_FLAG_7;
} else { } else {
this->stateFlags = 0; this->stateFlags = 0;
} }
} }
if (play->sceneId == SCENE_LON_LON_RANCH && GET_EVENTINF_HORSES_STATE() == EVENTINF_HORSES_STATE_6 && if (play->sceneId == SCENE_LON_LON_RANCH && GET_EVENTINF_INGO_RACE_STATE() == INGO_RACE_STATE_TRAPPED_WIN_EPONA &&
!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && !DREG(1)) { !(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) {
this->stateFlags |= ENHORSE_FLAG_25; this->stateFlags |= ENHORSE_FLAG_25;
} }
@ -842,12 +843,13 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
} else if (!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && !DREG(1) && !IS_DAY) { } else if (!(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED) && !IS_DAY) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
} else if (play->sceneId == SCENE_STABLE) { } else if (play->sceneId == SCENE_STABLE) {
if (IS_DAY || Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || DREG(1) != 0 || !LINK_IS_ADULT) { if (IS_DAY || Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED ||
!LINK_IS_ADULT) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
@ -865,24 +867,25 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) {
EnHorse_ResetRace(this, play); EnHorse_ResetRace(this, play);
EnHorse_ResetHorsebackArchery(this, play); EnHorse_ResetHorsebackArchery(this, play);
if (this->actor.params == 2) { if (this->actor.params == HORSE_PTYPE_INACTIVE) {
EnHorse_InitInactive(this); EnHorse_InitInactive(this);
} else if (this->actor.params == 3) { } else if (this->actor.params == HORSE_PTYPE_INGO_SPAWNED_RIDING) {
EnHorse_InitIngoHorse(this); EnHorse_InitIngoHorse(this);
this->rider = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_IN, this->actor.world.pos.x, this->actor.world.pos.y, this->rider = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_IN, this->actor.world.pos.x, this->actor.world.pos.y,
this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, 1, 1); this->actor.world.pos.z, this->actor.shape.rot.x, this->actor.shape.rot.y, 1, 1);
ASSERT(this->rider != NULL, "this->race.rider != NULL", "../z_en_horse.c", 3077); ASSERT(this->rider != NULL, "this->race.rider != NULL", "../z_en_horse.c", 3077);
if (!GET_EVENTINF(EVENTINF_HORSES_06)) { if (!GET_EVENTINF(EVENTINF_INGO_RACE_SECOND_RACE)) {
this->ingoHorseMaxSpeed = 12.07f; this->ingoHorseMaxSpeed = 12.07f;
} else { } else {
this->ingoHorseMaxSpeed = 12.625f; this->ingoHorseMaxSpeed = 12.625f;
} }
} else if (this->actor.params == 7) { } else if (this->actor.params == HORSE_PTYPE_7) {
EnHorse_InitCutscene(this, play); EnHorse_InitCutscene(this, play);
} else if (this->actor.params == 8) { } else if (this->actor.params == HORSE_PTYPE_HORSEBACK_ARCHERY) {
EnHorse_InitHorsebackArchery(this); EnHorse_InitHorsebackArchery(this);
Interface_InitHorsebackArchery(play); Interface_InitHorsebackArchery(play);
} else if (play->sceneId == SCENE_LON_LON_RANCH && !Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && !DREG(1)) { } else if (play->sceneId == SCENE_LON_LON_RANCH && !Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) &&
!R_DEBUG_FORCE_EPONA_OBTAINED) {
EnHorse_InitFleePlayer(this); EnHorse_InitFleePlayer(this);
} else { } else {
if (play->sceneId == SCENE_LON_LON_BUILDINGS) { if (play->sceneId == SCENE_LON_LON_BUILDINGS) {
@ -918,7 +921,7 @@ void EnHorse_RotateToPlayer(EnHorse* this, PlayState* play) {
void EnHorse_Freeze(EnHorse* this) { void EnHorse_Freeze(EnHorse* this) {
if (this->action != ENHORSE_ACT_CS_UPDATE && this->action != ENHORSE_ACT_HBA) { if (this->action != ENHORSE_ACT_CS_UPDATE && this->action != ENHORSE_ACT_HBA) {
if (sResetNoInput[this->actor.params] != 0 && this->actor.params != 4) { if (!(sResetNoInput[this->actor.params] == 0 || this->actor.params == HORSE_PTYPE_4)) {
this->noInputTimer = 0; this->noInputTimer = 0;
this->noInputTimerMax = 0; this->noInputTimerMax = 0;
} }
@ -945,10 +948,10 @@ void EnHorse_Frozen(EnHorse* this, PlayState* play) {
this->jntSph.base.ocFlags1 |= OC1_ON; this->jntSph.base.ocFlags1 |= OC1_ON;
if (this->playerControlled == true) { if (this->playerControlled == true) {
this->stateFlags &= ~ENHORSE_FLAG_7; this->stateFlags &= ~ENHORSE_FLAG_7;
if (this->actor.params == 4) { if (this->actor.params == HORSE_PTYPE_4) {
EnHorse_StartMountedIdleResetAnim(this); EnHorse_StartMountedIdleResetAnim(this);
} else if (this->actor.params == 9) { } else if (this->actor.params == HORSE_PTYPE_PLAYER_SPAWNED_RIDING) {
this->actor.params = 5; this->actor.params = HORSE_PTYPE_5;
if (play->csCtx.state != CS_STATE_IDLE) { if (play->csCtx.state != CS_STATE_IDLE) {
EnHorse_StartMountedIdle(this); EnHorse_StartMountedIdle(this);
} else { } else {
@ -960,8 +963,8 @@ void EnHorse_Frozen(EnHorse* this, PlayState* play) {
} else { } else {
EnHorse_StartMountedIdleResetAnim(this); EnHorse_StartMountedIdleResetAnim(this);
} }
if (this->actor.params != 0) { if (this->actor.params != HORSE_PTYPE_0) {
this->actor.params = 0; this->actor.params = HORSE_PTYPE_0;
return; return;
} }
} else { } else {
@ -1741,7 +1744,7 @@ void EnHorse_Inactive(EnHorse* this, PlayState* play2) {
if (R_EPONAS_SONG_PLAYED && this->type == HORSE_EPONA) { if (R_EPONAS_SONG_PLAYED && this->type == HORSE_EPONA) {
R_EPONAS_SONG_PLAYED = false; R_EPONAS_SONG_PLAYED = false;
if (EnHorse_Spawn(this, play) != 0) { if (EnHorse_Spawn(this, play)) {
#if OOT_VERSION >= PAL_1_0 #if OOT_VERSION >= PAL_1_0
Audio_PlaySfxGeneral(NA_SE_EV_HORSE_NEIGH, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySfxGeneral(NA_SE_EV_HORSE_NEIGH, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
@ -1758,7 +1761,7 @@ void EnHorse_Inactive(EnHorse* this, PlayState* play2) {
if (!(this->stateFlags & ENHORSE_INACTIVE)) { if (!(this->stateFlags & ENHORSE_INACTIVE)) {
this->followTimer = 0; this->followTimer = 0;
EnHorse_SetFollowAnimation(this, play); EnHorse_SetFollowAnimation(this, play);
this->actor.params = 0; this->actor.params = HORSE_PTYPE_0;
this->cyl1.base.ocFlags1 |= OC1_ON; this->cyl1.base.ocFlags1 |= OC1_ON;
this->cyl2.base.ocFlags1 |= OC1_ON; this->cyl2.base.ocFlags1 |= OC1_ON;
this->jntSph.base.ocFlags1 |= OC1_ON; this->jntSph.base.ocFlags1 |= OC1_ON;
@ -2397,7 +2400,7 @@ void EnHorse_CutsceneUpdate(EnHorse* this, PlayState* play) {
if (play->csCtx.state == 3) { if (play->csCtx.state == 3) {
this->playerControlled = 1; this->playerControlled = 1;
this->actor.params = 10; this->actor.params = HORSE_PTYPE_10;
this->action = ENHORSE_ACT_IDLE; this->action = ENHORSE_ACT_IDLE;
EnHorse_Freeze(this); EnHorse_Freeze(this);
return; return;

View file

@ -28,7 +28,7 @@ typedef enum EnHorseAction {
/* 19 */ ENHORSE_ACT_FLEE_PLAYER /* 19 */ ENHORSE_ACT_FLEE_PLAYER
} EnHorseAction; } EnHorseAction;
// stateFlags
#define ENHORSE_BOOST (1 << 0) /* 0x1 */ #define ENHORSE_BOOST (1 << 0) /* 0x1 */
#define ENHORSE_BOOST_DECEL (1 << 1) /* 0x2 */ #define ENHORSE_BOOST_DECEL (1 << 1) /* 0x2 */
#define ENHORSE_JUMPING (1 << 2) /* 0x4 */ #define ENHORSE_JUMPING (1 << 2) /* 0x4 */
@ -90,6 +90,21 @@ typedef enum HorseType {
/* 1 */ HORSE_HNI /* 1 */ HORSE_HNI
} HorseType; } HorseType;
typedef enum HorseParamType {
/* 00 */ HORSE_PTYPE_0,
/* 01 */ HORSE_PTYPE_1,
/* 02 */ HORSE_PTYPE_INACTIVE, // Waits for Epona's Song to appear
/* 03 */ HORSE_PTYPE_INGO_SPAWNED_RIDING,
/* 04 */ HORSE_PTYPE_4,
/* 05 */ HORSE_PTYPE_5,
/* 06 */ HORSE_PTYPE_6,
/* 07 */ HORSE_PTYPE_7,
/* 08 */ HORSE_PTYPE_HORSEBACK_ARCHERY,
/* 09 */ HORSE_PTYPE_PLAYER_SPAWNED_RIDING,
/* 10 */ HORSE_PTYPE_10,
/* 11 */ HORSE_PTYPE_11
} HorseParamType;
typedef void (*EnHorsePostdrawFunc)(struct EnHorse*, struct PlayState*); typedef void (*EnHorsePostdrawFunc)(struct EnHorse*, struct PlayState*);
typedef struct EnHorse { typedef struct EnHorse {

View file

@ -17,15 +17,15 @@
(Math3D_PointInSquare2D(sRanchExit[0], sRanchExit[1], sRanchExit[2], sRanchExit[3], (actor)->world.pos.x, \ (Math3D_PointInSquare2D(sRanchExit[0], sRanchExit[1], sRanchExit[2], sRanchExit[3], (actor)->world.pos.x, \
(actor)->world.pos.z)) (actor)->world.pos.z))
#define INGORACE_PLAYER_MOVE (1 << 0) #define INGO_RACE_PLAYER_MOVE (1 << 0)
#define INGORACE_SET_TIMER (1 << 1) #define INGO_RACE_SET_TIMER (1 << 1)
#define INGORACE_INGO_MOVE (1 << 2) #define INGO_RACE_INGO_MOVE (1 << 2)
typedef enum HorseGameIngoRaceResult { typedef enum HorseGameIngoRaceResult {
/* 0 */ INGORACE_NO_RESULT, /* 0 */ INGO_RACE_NO_RESULT,
/* 1 */ INGORACE_PLAYER_WIN, /* 1 */ INGO_RACE_PLAYER_WIN,
/* 2 */ INGORACE_INGO_WIN, /* 2 */ INGO_RACE_INGO_WIN,
/* 3 */ INGORACE_TIME_UP /* 3 */ INGO_RACE_TIME_UP
} HorseGameIngoRaceResult; } HorseGameIngoRaceResult;
#define MALONRACE_PLAYER_MOVE (1 << 0) #define MALONRACE_PLAYER_MOVE (1 << 0)
@ -96,7 +96,7 @@ s32 EnHorseGameCheck_InitIngoRace(EnHorseGameCheckBase* base, PlayState* play) {
this->startTimer = 0; this->startTimer = 0;
this->finishTimer = 0; this->finishTimer = 0;
this->result = INGORACE_NO_RESULT; this->result = INGO_RACE_NO_RESULT;
this->playerFinish = 0; this->playerFinish = 0;
this->ingoFinish = 0; this->ingoFinish = 0;
@ -109,24 +109,24 @@ s32 EnHorseGameCheck_DestroyIngoRace(EnHorseGameCheckBase* base, PlayState* play
void EnHorseGameCheck_FinishIngoRace(EnHorseGameCheckIngoRace* this, PlayState* play) { void EnHorseGameCheck_FinishIngoRace(EnHorseGameCheckIngoRace* this, PlayState* play) {
gSaveContext.save.cutsceneIndex = 0; gSaveContext.save.cutsceneIndex = 0;
if (this->result == INGORACE_PLAYER_WIN) { if (this->result == INGO_RACE_PLAYER_WIN) {
play->nextEntranceIndex = ENTR_LON_LON_RANCH_7; play->nextEntranceIndex = ENTR_LON_LON_RANCH_7;
if (GET_EVENTINF(EVENTINF_HORSES_06)) { if (GET_EVENTINF(EVENTINF_INGO_RACE_SECOND_RACE)) {
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_6); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_TRAPPED_WIN_EPONA);
SET_EVENTINF_HORSES_0F(1); WRITE_EVENTINF_INGO_RACE_0F(1);
play->transitionType = TRANS_TYPE_FADE_WHITE; play->transitionType = TRANS_TYPE_FADE_WHITE;
Environment_ForcePlaySequence(NA_BGM_INGO); Environment_ForcePlaySequence(NA_BGM_INGO);
} else { } else {
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_4); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_FIRST_WIN);
SET_EVENTINF_HORSES_0F(1); WRITE_EVENTINF_INGO_RACE_0F(1);
Environment_ForcePlaySequence(NA_BGM_INGO); Environment_ForcePlaySequence(NA_BGM_INGO);
play->transitionType = TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_WHITE, TCS_FAST); play->transitionType = TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_WHITE, TCS_FAST);
} }
} else { } else {
play->nextEntranceIndex = ENTR_LON_LON_RANCH_8; play->nextEntranceIndex = ENTR_LON_LON_RANCH_8;
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_3); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_PLAYER_LOSE);
play->transitionType = TRANS_TYPE_CIRCLE(TCA_NORMAL, TCC_BLACK, TCS_FAST); play->transitionType = TRANS_TYPE_CIRCLE(TCA_NORMAL, TCC_BLACK, TCS_FAST);
SET_EVENTINF_HORSES_0F(1); WRITE_EVENTINF_INGO_RACE_0F(1);
} }
DREG(25) = 0; DREG(25) = 0;
play->transitionTrigger = TRANS_TRIGGER_START; play->transitionTrigger = TRANS_TRIGGER_START;
@ -140,20 +140,20 @@ s32 EnHorseGameCheck_UpdateIngoRace(EnHorseGameCheckBase* base, PlayState* play)
EnHorse* ingoHorse; EnHorse* ingoHorse;
Player* player2 = player; Player* player2 = player;
if ((this->startTimer > 50) && !(this->startFlags & INGORACE_SET_TIMER)) { if ((this->startTimer > 50) && !(this->startFlags & INGO_RACE_SET_TIMER)) {
this->startFlags |= INGORACE_SET_TIMER; this->startFlags |= INGO_RACE_SET_TIMER;
Interface_SetTimer(0); Interface_SetTimer(0);
} else if ((this->startTimer > 80) && (player->rideActor != NULL) && !(this->startFlags & INGORACE_PLAYER_MOVE)) { } else if ((this->startTimer > 80) && (player->rideActor != NULL) && !(this->startFlags & INGO_RACE_PLAYER_MOVE)) {
EnHorse* horse; EnHorse* horse;
this->startFlags |= INGORACE_PLAYER_MOVE; this->startFlags |= INGO_RACE_PLAYER_MOVE;
horse = (EnHorse*)player->rideActor; horse = (EnHorse*)player->rideActor;
horse->inRace = 1; horse->inRace = 1;
} else if ((this->startTimer > 81) && !(this->startFlags & INGORACE_INGO_MOVE)) { } else if ((this->startTimer > 81) && !(this->startFlags & INGO_RACE_INGO_MOVE)) {
ingoHorse = (EnHorse*)this->ingoHorse; ingoHorse = (EnHorse*)this->ingoHorse;
ingoHorse->inRace = 1; ingoHorse->inRace = 1;
this->startFlags |= INGORACE_INGO_MOVE; this->startFlags |= INGO_RACE_INGO_MOVE;
Audio_PlaySfxGeneral(NA_SE_SY_START_SHOT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySfxGeneral(NA_SE_SY_START_SHOT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
} }
@ -178,11 +178,11 @@ s32 EnHorseGameCheck_UpdateIngoRace(EnHorseGameCheckBase* base, PlayState* play)
} }
} }
if (this->result == INGORACE_NO_RESULT) { if (this->result == INGO_RACE_NO_RESULT) {
if ((player2->rideActor != NULL) && (this->playerCheck[2] == 1) && AT_FINISH_LINE(player2->rideActor)) { if ((player2->rideActor != NULL) && (this->playerCheck[2] == 1) && AT_FINISH_LINE(player2->rideActor)) {
this->playerFinish++; this->playerFinish++;
if (this->playerFinish > 0) { if (this->playerFinish > 0) {
this->result = INGORACE_PLAYER_WIN; this->result = INGO_RACE_PLAYER_WIN;
this->finishTimer = 55; this->finishTimer = 55;
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, 0, NA_BGM_HORSE_GOAL); SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, 0, NA_BGM_HORSE_GOAL);
Audio_PlaySfxGeneral(NA_SE_SY_START_SHOT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySfxGeneral(NA_SE_SY_START_SHOT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
@ -197,7 +197,7 @@ s32 EnHorseGameCheck_UpdateIngoRace(EnHorseGameCheckBase* base, PlayState* play)
if (this->ingoFinish > 0) { if (this->ingoFinish > 0) {
ingoHorse = (EnHorse*)this->ingoHorse; ingoHorse = (EnHorse*)this->ingoHorse;
this->result = INGORACE_INGO_WIN; this->result = INGO_RACE_INGO_WIN;
this->finishTimer = 70; this->finishTimer = 70;
ingoHorse->stateFlags |= ENHORSE_INGO_WON; ingoHorse->stateFlags |= ENHORSE_INGO_WON;
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, 0, NA_BGM_HORSE_GOAL); SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, 0, NA_BGM_HORSE_GOAL);
@ -210,12 +210,12 @@ s32 EnHorseGameCheck_UpdateIngoRace(EnHorseGameCheckBase* base, PlayState* play)
} }
if (((player2->rideActor != NULL) && AT_RANCH_EXIT(player2->rideActor)) || AT_RANCH_EXIT(&player2->actor)) { if (((player2->rideActor != NULL) && AT_RANCH_EXIT(player2->rideActor)) || AT_RANCH_EXIT(&player2->actor)) {
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, 0, NA_BGM_HORSE_GOAL); SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, 0, NA_BGM_HORSE_GOAL);
this->result = INGORACE_INGO_WIN; this->result = INGO_RACE_INGO_WIN;
this->finishTimer = 20; this->finishTimer = 20;
} }
if ((gSaveContext.timerSeconds >= 180) && (this->startFlags & 2)) { if ((gSaveContext.timerSeconds >= 180) && (this->startFlags & 2)) {
SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, 0, NA_BGM_HORSE_GOAL); SEQCMD_PLAY_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0, 0, NA_BGM_HORSE_GOAL);
this->result = INGORACE_TIME_UP; this->result = INGO_RACE_TIME_UP;
this->finishTimer = 20; this->finishTimer = 20;
} }
} else { } else {
@ -447,7 +447,8 @@ void EnHorseGameCheck_Init(Actor* thisx, PlayState* play) {
s32 pad; s32 pad;
EnHorseGameCheckBase* this = (EnHorseGameCheckBase*)thisx; EnHorseGameCheckBase* this = (EnHorseGameCheckBase*)thisx;
if ((play->sceneId == SCENE_LON_LON_RANCH) && (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || DREG(1))) { if ((play->sceneId == SCENE_LON_LON_RANCH) &&
(Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED)) {
this->actor.params = HORSEGAME_MALON_RACE; this->actor.params = HORSEGAME_MALON_RACE;
} }
if (sInitFuncs[this->actor.params] != NULL) { if (sInitFuncs[this->actor.params] != NULL) {

View file

@ -4,6 +4,17 @@
* Description: Young Epona * Description: Young Epona
*/ */
#include "global.h"
#include "gfx.h"
#include "gfx_setupdl.h"
#include "ichain.h"
#include "rand.h"
#include "regs.h"
#include "sfx.h"
#include "z64actor.h"
#include "z64horse.h"
#include "z64player.h"
#include "z64play.h"
#include "z_en_horse_link_child.h" #include "z_en_horse_link_child.h"
#include "assets/objects/object_horse_link_child/object_horse_link_child.h" #include "assets/objects/object_horse_link_child/object_horse_link_child.h"
@ -451,7 +462,7 @@ void func_80A6A5A4(EnHorseLinkChild* this, PlayState* play) {
yawDiff = Actor_WorldYawTowardActor(&this->actor, &GET_PLAYER(play)->actor) - this->actor.world.rot.y; yawDiff = Actor_WorldYawTowardActor(&this->actor, &GET_PLAYER(play)->actor) - this->actor.world.rot.y;
// 0.7071 = cos(pi/4) // 0.7071 = cos(pi/4)
if ((Math_CosS(yawDiff) < 0.7071f) && (this->animationIdx == 2)) { if ((Math_CosS(yawDiff) < 0.7071f) && (this->animationIdx == 2)) {
func_8006DD9C(&this->actor, &GET_PLAYER(play)->actor.world.pos, 300); Horse_RotateToPoint(&this->actor, &GET_PLAYER(play)->actor.world.pos, 300);
} }
if (SkelAnime_Update(&this->skin.skelAnime)) { if (SkelAnime_Update(&this->skin.skelAnime)) {
@ -488,9 +499,9 @@ void func_80A6A7D0(EnHorseLinkChild* this, PlayState* play) {
if ((this->animationIdx == 4) || (this->animationIdx == 3) || (this->animationIdx == 2)) { if ((this->animationIdx == 4) || (this->animationIdx == 3) || (this->animationIdx == 2)) {
if (!this->unk_1E8) { if (!this->unk_1E8) {
func_8006DD9C(&this->actor, &player->actor.world.pos, 300); Horse_RotateToPoint(&this->actor, &player->actor.world.pos, 300);
} else { } else {
func_8006DD9C(&this->actor, &this->actor.home.pos, 300); Horse_RotateToPoint(&this->actor, &this->actor.home.pos, 300);
} }
} }

View file

@ -2,11 +2,12 @@
#define Z_EN_HORSE_LINK_CHILD_H #define Z_EN_HORSE_LINK_CHILD_H
#include "ultra64.h" #include "ultra64.h"
#include "global.h" #include "z64actor.h"
#include "z64skin.h"
struct EnHorseLinkChild; struct EnHorseLinkChild;
typedef void (*EnHorseLinkChildActionFunc)(struct EnHorseLinkChild*, PlayState*); typedef void (*EnHorseLinkChildActionFunc)(struct EnHorseLinkChild*, struct PlayState*);
typedef struct EnHorseLinkChild { typedef struct EnHorseLinkChild {
/* 0x0000 */ Actor actor; /* 0x0000 */ Actor actor;

View file

@ -216,7 +216,7 @@ void EnHorseNormal_Init(Actor* thisx, PlayState* play) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
} else if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || (DREG(1) != 0)) { } else if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED) {
if (this->actor.world.rot.z != 7) { if (this->actor.world.rot.z != 7) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;

View file

@ -72,6 +72,14 @@ typedef enum EnInAnimation {
/* 9 */ ENIN_ANIM_9 /* 9 */ ENIN_ANIM_9
} EnInAnimation; } EnInAnimation;
typedef enum EnInStartMode {
/* 0 */ ENIN_START_MODE_0,
/* 1 */ ENIN_START_MODE_1,
/* 2 */ ENIN_START_MODE_2,
/* 3 */ ENIN_START_MODE_3,
/* 4 */ ENIN_START_MODE_4
} EnInStartMode;
static AnimationFrameCountInfo sAnimationInfo[] = { static AnimationFrameCountInfo sAnimationInfo[] = {
{ &object_in_Anim_001CC0, 1.0f, ANIMMODE_LOOP, 0.0f }, { &object_in_Anim_001CC0, 1.0f, ANIMMODE_LOOP, -10.0f }, { &object_in_Anim_001CC0, 1.0f, ANIMMODE_LOOP, 0.0f }, { &object_in_Anim_001CC0, 1.0f, ANIMMODE_LOOP, -10.0f },
{ &object_in_Anim_013C6C, 1.0f, ANIMMODE_LOOP, 0.0f }, { &object_in_Anim_013C6C, 1.0f, ANIMMODE_LOOP, -10.0f }, { &object_in_Anim_013C6C, 1.0f, ANIMMODE_LOOP, 0.0f }, { &object_in_Anim_013C6C, 1.0f, ANIMMODE_LOOP, -10.0f },
@ -140,8 +148,8 @@ u16 EnIn_GetTextIdAdult(PlayState* play) {
if (IS_NIGHT) { if (IS_NIGHT) {
return 0x204E; return 0x204E;
} }
switch (GET_EVENTINF_HORSES_STATE()) { switch (GET_EVENTINF_INGO_RACE_STATE()) {
case EVENTINF_HORSES_STATE_1: case INGO_RACE_STATE_HORSE_RENTAL_PERIOD:
if (!(player->stateFlags1 & PLAYER_STATE1_23)) { if (!(player->stateFlags1 & PLAYER_STATE1_23)) {
return 0x2036; return 0x2036;
} else if (GET_EVENTCHKINF(EVENTCHKINF_1B)) { } else if (GET_EVENTCHKINF(EVENTCHKINF_1B)) {
@ -153,24 +161,27 @@ u16 EnIn_GetTextIdAdult(PlayState* play) {
} else { } else {
return 0x2037; return 0x2037;
} }
case EVENTINF_HORSES_STATE_3: case INGO_RACE_STATE_PLAYER_LOSE:
if (GET_EVENTINF(EVENTINF_HORSES_06) || GET_EVENTINF(EVENTINF_HORSES_05)) { if (GET_EVENTINF(EVENTINF_INGO_RACE_SECOND_RACE) || GET_EVENTINF(EVENTINF_INGO_RACE_LOST_ONCE)) {
return 0x203E; return 0x203E;
} else { } else {
return 0x203D; return 0x203D;
} }
case EVENTINF_HORSES_STATE_4: case INGO_RACE_STATE_FIRST_WIN:
return 0x203A; return 0x203A;
case EVENTINF_HORSES_STATE_5: case INGO_RACE_STATE_TRAPPED_WIN_UNUSED:
case EVENTINF_HORSES_STATE_6: case INGO_RACE_STATE_TRAPPED_WIN_EPONA:
return 0x203C; return 0x203C;
case EVENTINF_HORSES_STATE_7: case INGO_RACE_STATE_REMATCH:
// Ask to race again after losing race
return 0x205B; return 0x205B;
case EVENTINF_HORSES_STATE_2: case INGO_RACE_STATE_RACING:
default: default:
if (GET_INFTABLE(INFTABLE_9A)) { if (GET_INFTABLE(INFTABLE_9A)) {
// Pay to Ride
return 0x2031; return 0x2031;
} else { } else {
// Adult Ingo first dialog, branches to pay to ride
return 0x2030; return 0x2030;
} }
} }
@ -256,9 +267,9 @@ s16 EnIn_UpdateTalkStateOnChoice(PlayState* play, Actor* thisx) {
talkState = NPC_TALK_STATE_ACTION; talkState = NPC_TALK_STATE_ACTION;
} else { } else {
Message_ContinueTextbox(play, this->actor.textId = 0x2039); Message_ContinueTextbox(play, this->actor.textId = 0x2039);
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_0); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_OFFER_RENTAL);
CLEAR_EVENTINF(EVENTINF_HORSES_05); CLEAR_EVENTINF(EVENTINF_INGO_RACE_LOST_ONCE);
CLEAR_EVENTINF(EVENTINF_HORSES_06); CLEAR_EVENTINF(EVENTINF_INGO_RACE_SECOND_RACE);
this->actionFunc = func_80A7A4C8; this->actionFunc = func_80A7A4C8;
} }
break; break;
@ -361,40 +372,40 @@ s32 func_80A7975C(EnIn* this, PlayState* play) {
return 1; return 1;
} }
s32 func_80A79830(EnIn* this, PlayState* play) { s32 EnIn_GetStartMode(EnIn* this, PlayState* play) {
if (play->sceneId == SCENE_LON_LON_RANCH && LINK_IS_CHILD && IS_DAY && this->actor.shape.rot.z == 1 && if (play->sceneId == SCENE_LON_LON_RANCH && LINK_IS_CHILD && IS_DAY && this->actor.shape.rot.z == 1 &&
!GET_EVENTCHKINF(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) { !GET_EVENTCHKINF(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
return 1; return ENIN_START_MODE_1;
} }
if (play->sceneId == SCENE_STABLE && LINK_IS_CHILD && IS_DAY && this->actor.shape.rot.z == 3 && if (play->sceneId == SCENE_STABLE && LINK_IS_CHILD && IS_DAY && this->actor.shape.rot.z == 3 &&
GET_EVENTCHKINF(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) { GET_EVENTCHKINF(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
return 1; return ENIN_START_MODE_1;
} }
if (play->sceneId == SCENE_STABLE && LINK_IS_CHILD && IS_NIGHT) { if (play->sceneId == SCENE_STABLE && LINK_IS_CHILD && IS_NIGHT) {
if ((this->actor.shape.rot.z == 2) && !GET_EVENTCHKINF(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) { if ((this->actor.shape.rot.z == 2) && !GET_EVENTCHKINF(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
return 1; return ENIN_START_MODE_1;
} }
if ((this->actor.shape.rot.z == 4) && GET_EVENTCHKINF(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) { if ((this->actor.shape.rot.z == 4) && GET_EVENTCHKINF(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
return 1; return ENIN_START_MODE_1;
} }
} }
if (play->sceneId == SCENE_LON_LON_RANCH && LINK_IS_ADULT && IS_DAY) { if (play->sceneId == SCENE_LON_LON_RANCH && LINK_IS_ADULT && IS_DAY) {
if ((this->actor.shape.rot.z == 5) && !GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) { if ((this->actor.shape.rot.z == 5) && !GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) {
return 2; return ENIN_START_MODE_2;
} }
if ((this->actor.shape.rot.z == 7) && GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) { if ((this->actor.shape.rot.z == 7) && GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) {
return 4; return ENIN_START_MODE_4;
} }
} }
if (play->sceneId == SCENE_LON_LON_BUILDINGS && LINK_IS_ADULT && IS_NIGHT) { if (play->sceneId == SCENE_LON_LON_BUILDINGS && LINK_IS_ADULT && IS_NIGHT) {
if (this->actor.shape.rot.z == 6 && !GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) { if (this->actor.shape.rot.z == 6 && !GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) {
return 3; return ENIN_START_MODE_3;
} }
if (this->actor.shape.rot.z == 8 && GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) { if (this->actor.shape.rot.z == 8 && GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) {
return 3; return ENIN_START_MODE_3;
} }
} }
return 0; return ENIN_START_MODE_0;
} }
void EnIn_UpdateEyes(EnIn* this) { void EnIn_UpdateEyes(EnIn* this) {
@ -434,7 +445,7 @@ void func_80A79BAC(EnIn* this, PlayState* play, s32 index, u32 transitionType) {
Player_SetCsActionWithHaltedActors(play, &this->actor, PLAYER_CSACTION_8); Player_SetCsActionWithHaltedActors(play, &this->actor, PLAYER_CSACTION_8);
Interface_ChangeHudVisibilityMode(HUD_VISIBILITY_NOTHING); Interface_ChangeHudVisibilityMode(HUD_VISIBILITY_NOTHING);
if (index == 0) { if (index == 0) {
AREG(6) = 0; R_EXITED_SCENE_RIDING_HORSE = false;
} }
gSaveContext.timerState = TIMER_STATE_OFF; gSaveContext.timerState = TIMER_STATE_OFF;
} }
@ -506,7 +517,7 @@ void EnIn_Destroy(Actor* thisx, PlayState* play) {
// This function does not actually wait since it waits for OBJECT_IN, // This function does not actually wait since it waits for OBJECT_IN,
// but the object is already loaded at this point from being set in the ActorProfile data // but the object is already loaded at this point from being set in the ActorProfile data
void EnIn_WaitForObject(EnIn* this, PlayState* play) { void EnIn_WaitForObject(EnIn* this, PlayState* play) {
s32 sp3C = 0; s32 staySpawned = false;
if (Object_IsLoaded(&play->objectCtx, this->requiredObjectSlot) || this->actor.params <= 0) { if (Object_IsLoaded(&play->objectCtx, this->requiredObjectSlot) || this->actor.params <= 0) {
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 36.0f); ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 36.0f);
@ -515,7 +526,7 @@ void EnIn_WaitForObject(EnIn* this, PlayState* play) {
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
if (func_80A7975C(this, play)) { if (func_80A7975C(this, play)) {
SET_EVENTINF_HORSES_0F(0); WRITE_EVENTINF_INGO_RACE_0F(0);
return; return;
} }
Actor_SetScale(&this->actor, 0.01f); Actor_SetScale(&this->actor, 0.01f);
@ -523,83 +534,83 @@ void EnIn_WaitForObject(EnIn* this, PlayState* play) {
this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
this->actionFunc = func_80A7A4BC; this->actionFunc = func_80A7A4BC;
switch (func_80A79830(this, play)) { switch (EnIn_GetStartMode(this, play)) {
case 1: case ENIN_START_MODE_1:
EnIn_ChangeAnim(this, ENIN_ANIM_9); EnIn_ChangeAnim(this, ENIN_ANIM_9);
this->actionFunc = func_80A7A4BC; this->actionFunc = func_80A7A4BC;
break; break;
case 3: case ENIN_START_MODE_3:
EnIn_ChangeAnim(this, ENIN_ANIM_7); EnIn_ChangeAnim(this, ENIN_ANIM_7);
this->actionFunc = func_80A7A4BC; this->actionFunc = func_80A7A4BC;
if (!GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) { if (!GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED)) {
this->actor.params = 5; this->actor.params = 5;
} }
break; break;
case 4: case ENIN_START_MODE_4:
EnIn_ChangeAnim(this, ENIN_ANIM_8); EnIn_ChangeAnim(this, ENIN_ANIM_8);
this->eyeIndex = 3; this->eyeIndex = 3;
this->actionFunc = func_80A7A4BC; this->actionFunc = func_80A7A4BC;
break; break;
case 0: case ENIN_START_MODE_0:
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
break; break;
default: default: // ENIN_START_MODE_2
switch (GET_EVENTINF_HORSES_STATE()) { switch (GET_EVENTINF_INGO_RACE_STATE()) {
case EVENTINF_HORSES_STATE_0: case INGO_RACE_STATE_OFFER_RENTAL:
case EVENTINF_HORSES_STATE_2: case INGO_RACE_STATE_RACING:
case EVENTINF_HORSES_STATE_3: case INGO_RACE_STATE_PLAYER_LOSE:
case EVENTINF_HORSES_STATE_4: case INGO_RACE_STATE_FIRST_WIN:
case EVENTINF_HORSES_STATE_7: case INGO_RACE_STATE_REMATCH:
if (this->actor.params == 2) { if (this->actor.params == 2) {
sp3C = 1; staySpawned = true;
} }
break; break;
case EVENTINF_HORSES_STATE_1: case INGO_RACE_STATE_HORSE_RENTAL_PERIOD:
if (this->actor.params == 3) { if (this->actor.params == 3) {
sp3C = 1; staySpawned = true;
} }
break; break;
case EVENTINF_HORSES_STATE_5: case INGO_RACE_STATE_TRAPPED_WIN_UNUSED:
case EVENTINF_HORSES_STATE_6: case INGO_RACE_STATE_TRAPPED_WIN_EPONA:
if (this->actor.params == 4) { if (this->actor.params == 4) {
sp3C = 1; staySpawned = true;
} }
break; break;
} }
if (sp3C != 1) { if (staySpawned != true) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
switch (GET_EVENTINF_HORSES_STATE()) { switch (GET_EVENTINF_INGO_RACE_STATE()) {
case EVENTINF_HORSES_STATE_0: case INGO_RACE_STATE_OFFER_RENTAL:
case EVENTINF_HORSES_STATE_2: case INGO_RACE_STATE_RACING:
EnIn_ChangeAnim(this, ENIN_ANIM_2); EnIn_ChangeAnim(this, ENIN_ANIM_2);
this->actionFunc = func_80A7A4C8; this->actionFunc = func_80A7A4C8;
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = 0; gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = 0;
break; break;
case EVENTINF_HORSES_STATE_1: case INGO_RACE_STATE_HORSE_RENTAL_PERIOD:
this->actor.attentionRangeType = ATTENTION_RANGE_3; this->actor.attentionRangeType = ATTENTION_RANGE_3;
EnIn_ChangeAnim(this, ENIN_ANIM_2); EnIn_ChangeAnim(this, ENIN_ANIM_2);
this->actionFunc = func_80A7A568; this->actionFunc = func_80A7A568;
Interface_SetTimer(60); Interface_SetTimer(60);
break; break;
case EVENTINF_HORSES_STATE_3: case INGO_RACE_STATE_PLAYER_LOSE:
EnIn_ChangeAnim(this, ENIN_ANIM_4); EnIn_ChangeAnim(this, ENIN_ANIM_4);
this->actionFunc = func_80A7A770; this->actionFunc = func_80A7A770;
break; break;
case EVENTINF_HORSES_STATE_4: case INGO_RACE_STATE_FIRST_WIN:
EnIn_ChangeAnim(this, ENIN_ANIM_6); EnIn_ChangeAnim(this, ENIN_ANIM_6);
this->unk_1EC = 8; this->unk_1EC = 8;
this->actionFunc = func_80A7A940; this->actionFunc = func_80A7A940;
break; break;
case EVENTINF_HORSES_STATE_5: case INGO_RACE_STATE_TRAPPED_WIN_UNUSED:
case EVENTINF_HORSES_STATE_6: case INGO_RACE_STATE_TRAPPED_WIN_EPONA:
this->actor.attentionRangeType = ATTENTION_RANGE_3; this->actor.attentionRangeType = ATTENTION_RANGE_3;
EnIn_ChangeAnim(this, ENIN_ANIM_6); EnIn_ChangeAnim(this, ENIN_ANIM_6);
this->unk_1EC = 8; this->unk_1EC = 8;
this->actionFunc = func_80A7AA40; this->actionFunc = func_80A7AA40;
break; break;
case EVENTINF_HORSES_STATE_7: case INGO_RACE_STATE_REMATCH:
EnIn_ChangeAnim(this, ENIN_ANIM_2); EnIn_ChangeAnim(this, ENIN_ANIM_2);
this->actionFunc = func_80A7A848; this->actionFunc = func_80A7A848;
break; break;
@ -640,8 +651,8 @@ void func_80A7A4BC(EnIn* this, PlayState* play) {
void func_80A7A4C8(EnIn* this, PlayState* play) { void func_80A7A4C8(EnIn* this, PlayState* play) {
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
func_80A79BAC(this, play, 1, TRANS_TYPE_CIRCLE(TCA_NORMAL, TCC_BLACK, TCS_FAST)); func_80A79BAC(this, play, 1, TRANS_TYPE_CIRCLE(TCA_NORMAL, TCC_BLACK, TCS_FAST));
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_1); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_HORSE_RENTAL_PERIOD);
SET_EVENTINF_HORSES_0F(1); WRITE_EVENTINF_INGO_RACE_0F(1);
CLEAR_INFTABLE(INFTABLE_A2); CLEAR_INFTABLE(INFTABLE_A2);
Environment_ForcePlaySequence(NA_BGM_HORSE); Environment_ForcePlaySequence(NA_BGM_HORSE);
play->msgCtx.stateTimer = 0; play->msgCtx.stateTimer = 0;
@ -672,8 +683,8 @@ void func_80A7A568(EnIn* this, PlayState* play) {
this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
return; return;
} }
SET_EVENTINF_HORSES_HORSETYPE(((EnHorse*)GET_PLAYER(play)->rideActor)->type); WRITE_EVENTINF_INGO_RACE_HORSETYPE(((EnHorse*)GET_PLAYER(play)->rideActor)->type);
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_2); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_RACING);
phi_a2 = 2; phi_a2 = 2;
transitionType = TRANS_TYPE_FADE_BLACK; transitionType = TRANS_TYPE_FADE_BLACK;
} else { } else {
@ -685,13 +696,13 @@ void func_80A7A568(EnIn* this, PlayState* play) {
SET_INFTABLE(INFTABLE_AB); SET_INFTABLE(INFTABLE_AB);
} }
} }
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_0); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_OFFER_RENTAL);
phi_a2 = 0; phi_a2 = 0;
transitionType = TRANS_TYPE_CIRCLE(TCA_NORMAL, TCC_BLACK, TCS_FAST); transitionType = TRANS_TYPE_CIRCLE(TCA_NORMAL, TCC_BLACK, TCS_FAST);
} }
func_80A79BAC(this, play, phi_a2, transitionType); func_80A79BAC(this, play, phi_a2, transitionType);
play->msgCtx.stateTimer = 0; play->msgCtx.stateTimer = 0;
SET_EVENTINF_HORSES_0F(1); WRITE_EVENTINF_INGO_RACE_0F(1);
play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
} }
@ -705,11 +716,10 @@ void func_80A7A770(EnIn* this, PlayState* play) {
this->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED; this->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED;
EnIn_ChangeAnim(this, ENIN_ANIM_3); EnIn_ChangeAnim(this, ENIN_ANIM_3);
this->actionFunc = func_80A7A848; this->actionFunc = func_80A7A848;
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_7); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_REMATCH);
this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = SET_EVENTINF_INGO_RACE_FLAG(EVENTINF_INGO_RACE_LOST_ONCE);
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & 0xFFFF) | EVENTINF_HORSES_05_MASK; if (!GET_EVENTINF(EVENTINF_INGO_RACE_SECOND_RACE)) {
if (!GET_EVENTINF(EVENTINF_HORSES_06)) {
play->msgCtx.stateTimer = 4; play->msgCtx.stateTimer = 4;
play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
} }
@ -720,18 +730,18 @@ void func_80A7A848(EnIn* this, PlayState* play) {
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
if ((play->msgCtx.choiceIndex == 0 && gSaveContext.save.info.playerData.rupees < 50) || if ((play->msgCtx.choiceIndex == 0 && gSaveContext.save.info.playerData.rupees < 50) ||
play->msgCtx.choiceIndex == 1) { play->msgCtx.choiceIndex == 1) {
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_0); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_OFFER_RENTAL);
this->actionFunc = func_80A7A4C8; this->actionFunc = func_80A7A4C8;
} else { } else {
func_80A79BAC(this, play, 2, TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST)); func_80A79BAC(this, play, 2, TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST));
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_2); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_RACING);
SET_EVENTINF_HORSES_0F(1); WRITE_EVENTINF_INGO_RACE_0F(1);
play->msgCtx.stateTimer = 0; play->msgCtx.stateTimer = 0;
play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
} }
this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
CLEAR_EVENTINF(EVENTINF_HORSES_05); CLEAR_EVENTINF(EVENTINF_INGO_RACE_LOST_ONCE);
CLEAR_EVENTINF(EVENTINF_HORSES_06); CLEAR_EVENTINF(EVENTINF_INGO_RACE_SECOND_RACE);
} }
} }
@ -749,13 +759,12 @@ void func_80A7A940(EnIn* this, PlayState* play) {
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
this->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED; this->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED;
func_80A79BAC(this, play, 2, TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST)); func_80A79BAC(this, play, 2, TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST));
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_2); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_RACING);
SET_EVENTINF_HORSES_0F(1); WRITE_EVENTINF_INGO_RACE_0F(1);
play->msgCtx.stateTimer = 0; play->msgCtx.stateTimer = 0;
play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
gSaveContext.eventInf[EVENTINF_HORSES_INDEX] = SET_EVENTINF_INGO_RACE_FLAG(EVENTINF_INGO_RACE_SECOND_RACE);
(gSaveContext.eventInf[EVENTINF_HORSES_INDEX] & 0xFFFF) | EVENTINF_HORSES_06_MASK;
} }
} }
@ -904,8 +913,8 @@ void func_80A7B024(EnIn* this, PlayState* play) {
} }
func_80A79BAC(this, play, 0, TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST)); func_80A79BAC(this, play, 0, TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST));
SET_EVENTINF_HORSES_STATE(EVENTINF_HORSES_STATE_0); SET_EVENTINF_INGO_RACE_STATE(INGO_RACE_STATE_OFFER_RENTAL);
SET_EVENTINF_HORSES_0F(1); WRITE_EVENTINF_INGO_RACE_0F(1);
play->msgCtx.stateTimer = 4; play->msgCtx.stateTimer = 4;
play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
@ -925,7 +934,7 @@ void EnIn_Update(Actor* thisx, PlayState* play) {
if (this->actionFunc != func_80A7A304) { if (this->actionFunc != func_80A7A304) {
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
if (this->skelAnime.animation == &object_in_Anim_001BE0 && if (this->skelAnime.animation == &object_in_Anim_001BE0 &&
GET_EVENTINF_HORSES_STATE() != EVENTINF_HORSES_STATE_6) { GET_EVENTINF_INGO_RACE_STATE() != INGO_RACE_STATE_TRAPPED_WIN_EPONA) {
func_80A79690(&this->skelAnime, this, play); func_80A79690(&this->skelAnime, this, play);
} }
Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, UPDBGCHECKINFO_FLAG_2); Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, UPDBGCHECKINFO_FLAG_2);

View file

@ -81,7 +81,7 @@ void OceffSpot_End(OceffSpot* this, PlayState* play) {
} else { } else {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
if (gTimeSpeed != 400 && !play->msgCtx.disableSunsSong && if (gTimeSpeed != 400 && !play->msgCtx.disableSunsSong &&
GET_EVENTINF_HORSES_STATE() != EVENTINF_HORSES_STATE_1) { GET_EVENTINF_INGO_RACE_STATE() != INGO_RACE_STATE_HORSE_RENTAL_PERIOD) {
if (play->msgCtx.ocarinaAction != OCARINA_ACTION_CHECK_NOWARP_DONE || if (play->msgCtx.ocarinaAction != OCARINA_ACTION_CHECK_NOWARP_DONE ||
play->msgCtx.ocarinaMode != OCARINA_MODE_08) { play->msgCtx.ocarinaMode != OCARINA_MODE_08) {
gSaveContext.sunsSongState = SUNSSONG_START; gSaveContext.sunsSongState = SUNSSONG_START;

View file

@ -11842,7 +11842,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
if (DREG(25) != 0) { if (DREG(25) != 0) {
DREG(25) = 0; DREG(25) = 0;
} else { } else {
AREG(6) = 1; R_EXITED_SCENE_RIDING_HORSE = true;
} }
} }
} }
@ -13216,7 +13216,7 @@ void Player_Action_8084CC98(Player* this, PlayState* play) {
} }
if (LinkAnimation_OnFrame(&this->skelAnime, arr[1])) { if (LinkAnimation_OnFrame(&this->skelAnime, arr[1])) {
func_8002DE74(play, this); Actor_RequestHorseCameraSetting(play, this);
Player_PlaySfx(this, NA_SE_PL_SIT_ON_HORSE); Player_PlaySfx(this, NA_SE_PL_SIT_ON_HORSE);
return; return;
} }
@ -13224,7 +13224,7 @@ void Player_Action_8084CC98(Player* this, PlayState* play) {
return; return;
} }
func_8002DE74(play, this); Actor_RequestHorseCameraSetting(play, this);
this->skelAnime.prevTransl = D_8085499C; this->skelAnime.prevTransl = D_8085499C;
if ((rideActor->animationIdx != this->av2.actionVar2) && if ((rideActor->animationIdx != this->av2.actionVar2) &&
@ -13383,9 +13383,9 @@ void Player_Action_8084D3E4(Player* this, PlayState* play) {
func_8083C0E8(this, play); func_8083C0E8(this, play);
this->stateFlags1 &= ~PLAYER_STATE1_23; this->stateFlags1 &= ~PLAYER_STATE1_23;
this->actor.parent = NULL; this->actor.parent = NULL;
AREG(6) = 0; R_EXITED_SCENE_RIDING_HORSE = false;
if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || (DREG(1) != 0)) { if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || R_DEBUG_FORCE_EPONA_OBTAINED) {
gSaveContext.save.info.horseData.pos.x = rideActor->actor.world.pos.x; gSaveContext.save.info.horseData.pos.x = rideActor->actor.world.pos.x;
gSaveContext.save.info.horseData.pos.y = rideActor->actor.world.pos.y; gSaveContext.save.info.horseData.pos.y = rideActor->actor.world.pos.y;
gSaveContext.save.info.horseData.pos.z = rideActor->actor.world.pos.z; gSaveContext.save.info.horseData.pos.z = rideActor->actor.world.pos.z;