Merge pull request #3755 from garrettjoecox/develop-rando-changes

Vanilla Behavior Overhaul
This commit is contained in:
Garrett Cox 2024-05-05 15:12:43 -05:00 committed by GitHub
commit 04f9ec1b78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
208 changed files with 6144 additions and 4529 deletions

@ -1 +1 @@
Subproject commit b135db823aaabf6e848fcbd2796933b0771f9968 Subproject commit 493639d5daf75c8fa5d374f96fc95b652714299f

View File

@ -183,6 +183,8 @@ void __osSetWatchLo(u32);
EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params); EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params);
EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params); EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params);
void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry giEntry); void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry giEntry);
void EnItem00_SetupAction(EnItem00* this, EnItem00ActionFunc actionFunc);
void func_8001E5C8(EnItem00* this, PlayState* play);
void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnPos, s16 params); void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnPos, s16 params);
void EffectBlure_ChangeType(EffectBlure* this, int type); void EffectBlure_ChangeType(EffectBlure* this, int type);
void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2); void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2);
@ -415,6 +417,7 @@ f32 Actor_WorldDistXZToPoint(Actor* actor, Vec3f* refPoint);
void func_8002DBD0(Actor* actor, Vec3f* result, Vec3f* arg2); void func_8002DBD0(Actor* actor, Vec3f* result, Vec3f* arg2);
f32 Actor_HeightDiff(Actor* actorA, Actor* actorB); f32 Actor_HeightDiff(Actor* actorA, Actor* actorB);
f32 Player_GetHeight(Player* player); f32 Player_GetHeight(Player* player);
s32 Player_ActionChange_2(Player* player, PlayState* play);
f32 func_8002DCE4(Player* player); f32 func_8002DCE4(Player* player);
s32 func_8002DD6C(Player* player); s32 func_8002DD6C(Player* player);
s32 func_8002DD78(Player* player); s32 func_8002DD78(Player* player);
@ -426,7 +429,7 @@ void Actor_MountHorse(PlayState* play, Player* player, Actor* horse);
s32 func_8002DEEC(Player* player); s32 func_8002DEEC(Player* player);
void func_8002DF18(PlayState* play, Player* player); void func_8002DF18(PlayState* play, Player* player);
s32 func_8002DF38(PlayState* play, Actor* actor, u8 csMode); s32 func_8002DF38(PlayState* play, Actor* actor, u8 csMode);
s32 func_8002DF54(PlayState* play, Actor* actor, u8 arg2); s32 Player_SetCsActionWithHaltedActors(PlayState* play, Actor* actor, u8 arg2);
void func_8002DF90(DynaPolyActor* dynaActor); void func_8002DF90(DynaPolyActor* dynaActor);
void func_8002DFA4(DynaPolyActor* dynaActor, f32 arg1, s16 arg2); void func_8002DFA4(DynaPolyActor* dynaActor, f32 arg1, s16 arg2);
s32 Player_IsFacingActor(Actor* actor, s16 angle, PlayState* play); s32 Player_IsFacingActor(Actor* actor, s16 angle, PlayState* play);
@ -454,11 +457,11 @@ u32 Actor_TextboxIsClosing(Actor* actor, PlayState* play);
s8 func_8002F368(PlayState* play); s8 func_8002F368(PlayState* play);
void Actor_GetScreenPos(PlayState* play, Actor* actor, s16* x, s16* y); void Actor_GetScreenPos(PlayState* play, Actor* actor, s16* x, s16* y);
u32 Actor_HasParent(Actor* actor, PlayState* play); u32 Actor_HasParent(Actor* actor, PlayState* play);
// TODO: Rename the follwing 3 functions using whatever scheme we use when we rename func_8002F434 and func_8002F554. // TODO: Rename the follwing 3 functions using whatever scheme we use when we rename Actor_OfferGetItem and func_8002F554.
s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry); s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry);
s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEntry, f32 xzRange, f32 yRange); s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEntry, f32 xzRange, f32 yRange);
s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry); s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry);
s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange); s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange);
void func_8002F554(Actor* actor, PlayState* play, s32 getItemId); void func_8002F554(Actor* actor, PlayState* play, s32 getItemId);
void func_8002F580(Actor* actor, PlayState* play); void func_8002F580(Actor* actor, PlayState* play);
u32 Actor_HasNoParent(Actor* actor, PlayState* play); u32 Actor_HasNoParent(Actor* actor, PlayState* play);
@ -572,8 +575,6 @@ void Flags_UnsetRandomizerInf(RandomizerInf flag);
u16 func_80037C30(PlayState* play, s16 arg1); u16 func_80037C30(PlayState* play, s16 arg1);
s32 func_80037D98(PlayState* play, Actor* actor, s16 arg2, s32* arg3); s32 func_80037D98(PlayState* play, Actor* actor, s16 arg2, s32* arg3);
s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f arg4); s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f arg4);
GetItemEntry GetChestGameRandoGetItem(s8 room, s16 ogDrawId, PlayState* play);
s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play);
// ? func_80038600(?); // ? func_80038600(?);
u16 DynaSSNodeList_GetNextNodeIdx(DynaSSNodeList*); u16 DynaSSNodeList_GetNextNodeIdx(DynaSSNodeList*);
@ -1106,6 +1107,7 @@ s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input);
u8 PlayerGrounded(Player* player); u8 PlayerGrounded(Player* player);
void Player_SetBootData(PlayState* play, Player* player); void Player_SetBootData(PlayState* play, Player* player);
s32 Player_InBlockingCsMode(PlayState* play, Player* player); s32 Player_InBlockingCsMode(PlayState* play, Player* player);
s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction);
s32 Player_InCsMode(PlayState* play); s32 Player_InCsMode(PlayState* play);
s32 func_8008E9C4(Player* player); s32 func_8008E9C4(Player* player);
s32 Player_IsChildWithHylianShield(Player* player); s32 Player_IsChildWithHylianShield(Player* player);

View File

@ -266,7 +266,12 @@ typedef enum {
/* 0x17 */ ITEM00_TUNIC_ZORA, /* 0x17 */ ITEM00_TUNIC_ZORA,
/* 0x18 */ ITEM00_TUNIC_GORON, /* 0x18 */ ITEM00_TUNIC_GORON,
/* 0x19 */ ITEM00_BOMBS_SPECIAL, /* 0x19 */ ITEM00_BOMBS_SPECIAL,
/* 0x20 */ ITEM00_BOMBCHU, /* 0x1A */ ITEM00_BOMBCHU,
/* 0x1B */ ITEM00_SOH_DUMMY,
/* 0x1C */ ITEM00_SOH_GIVE_ITEM_ENTRY,
/* 0x1D */ ITEM00_SOH_GIVE_ITEM_ENTRY_GI,
/* 0x1E */ ITEM00_MAX,
/* 0xFF */ ITEM00_NONE = 0xFF
} Item00Type; } Item00Type;
struct EnItem00; struct EnItem00;
@ -284,10 +289,13 @@ typedef struct EnItem00 {
/* 0x15A */ s16 unk_15A; /* 0x15A */ s16 unk_15A;
/* 0x15C */ f32 scale; /* 0x15C */ f32 scale;
/* 0x160 */ ColliderCylinder collider; /* 0x160 */ ColliderCylinder collider;
s16 ogParams; // #region SOH [Randomizer]
GetItemEntry randoGiEntry; GetItemEntry randoGiEntry;
RandomizerCheck randoCheck; RandomizerCheck randoCheck;
RandomizerInf randoInf; RandomizerInf randoInf;
/* */ s16 ogParams;
/* */ GetItemEntry itemEntry;
// #endregion
} EnItem00; // size = 0x1AC } EnItem00; // size = 0x1AC
// Only A_OBJ_SIGNPOST_OBLONG and A_OBJ_SIGNPOST_ARROW are used in room files. // Only A_OBJ_SIGNPOST_OBLONG and A_OBJ_SIGNPOST_ARROW are used in room files.

View File

@ -283,7 +283,7 @@ typedef struct {
// #endregion // #endregion
// #region SOH [Randomizer] // #region SOH [Randomizer]
// Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer // Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer
/* */ u16 randomizerInf[16]; /* */ u16 randomizerInf[17];
/* */ u8 mqDungeonCount; /* */ u8 mqDungeonCount;
/* */ u16 adultTradeItems; /* */ u16 adultTradeItems;
/* */ u8 triforcePiecesCollected; /* */ u8 triforcePiecesCollected;

View File

@ -129,15 +129,15 @@ void BossRush_SpawnBlueWarps(PlayState* play) {
// Spawn blue warps in Chamber of Sages based on what bosses have been defeated. // Spawn blue warps in Chamber of Sages based on what bosses have been defeated.
if (gSaveContext.linkAge == LINK_AGE_CHILD) { if (gSaveContext.linkAge == LINK_AGE_CHILD) {
// Forest Medallion (Gohma) // Forest Medallion (Gohma)
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) { if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false);
} }
// Fire Medallion (King Dodongo) // Fire Medallion (King Dodongo)
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) { if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false);
} }
// Water Medallion (Barinade) // Water Medallion (Barinade)
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) { if (!Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false);
} }
} else { } else {
@ -146,15 +146,15 @@ void BossRush_SpawnBlueWarps(PlayState* play) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -199, 6, 0, 0, 0, 0, -1, false); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -199, 6, 0, 0, 0, 0, -1, false);
} }
// Forest Medallion (Phantom Ganondorf) // Forest Medallion (Phantom Ganondorf)
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) { if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false);
} }
// Fire Medallion (Volvagia) // Fire Medallion (Volvagia)
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false);
} }
// Water Medallion (Morpha) // Water Medallion (Morpha)
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false); Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false);
} }
// Spirit Medallion (Twinrova) // Spirit Medallion (Twinrova)
@ -242,22 +242,22 @@ void BossRush_HandleCompleteBoss(PlayState* play) {
gSaveContext.isBossRushPaused = 1; gSaveContext.isBossRushPaused = 1;
switch (play->sceneNum) { switch (play->sceneNum) {
case SCENE_DEKU_TREE_BOSS: case SCENE_DEKU_TREE_BOSS:
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP);
break; break;
case SCENE_DODONGOS_CAVERN_BOSS: case SCENE_DODONGOS_CAVERN_BOSS:
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP);
break; break;
case SCENE_JABU_JABU_BOSS: case SCENE_JABU_JABU_BOSS:
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP);
break; break;
case SCENE_FOREST_TEMPLE_BOSS: case SCENE_FOREST_TEMPLE_BOSS:
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
break; break;
case SCENE_FIRE_TEMPLE_BOSS: case SCENE_FIRE_TEMPLE_BOSS:
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP);
break; break;
case SCENE_WATER_TEMPLE_BOSS: case SCENE_WATER_TEMPLE_BOSS:
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP);
break; break;
case SCENE_SPIRIT_TEMPLE_BOSS: case SCENE_SPIRIT_TEMPLE_BOSS:
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE);
@ -432,13 +432,13 @@ void BossRush_InitSave() {
// Set flags and Link's age based on chosen settings. // Set flags and Link's age based on chosen settings.
if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ADULT || if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ADULT ||
gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) { gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) {
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP);
if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) { if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) {
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE);
} }

View File

@ -0,0 +1,56 @@
#include <libultraship/bridge.h>
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/enhancementTypes.h"
extern "C" {
#include "macros.h"
#include "variables.h"
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
}
void CheatsOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) {
switch (id) {
case GI_VB_DEKU_STICK_BREAK: {
if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) {
*should = false;
}
break;
}
case GI_VB_DEKU_STICK_BE_ON_FIRE: {
if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) {
Player* player = GET_PLAYER(gPlayState);
player->unk_860 = 200; // Keeps the stick's flame lit
player->unk_85C = 1.0f; // Ensures the stick is the proper length
*should = true;
}
break;
}
case GI_VB_DEKU_STICK_BURN_OUT: {
if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) {
*should = false;
}
break;
}
case GI_VB_DEKU_STICK_BURN_DOWN: {
if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) {
*should = false;
}
break;
}
}
}
static uint32_t onVanillaBehaviorHook = 0;
void CheatsRegisterHooks() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) mutable {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(onVanillaBehaviorHook);
onVanillaBehaviorHook = 0;
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(CheatsOnVanillaBehaviorHandler);
});
}

View File

@ -0,0 +1,6 @@
#ifndef CHEAT_HOOK_HANDLERS_H
#define CHEAT_HOOK_HANDLERS_H
void CheatsRegisterHooks();
#endif // CHEAT_HOOK_HANDLERS_H

View File

@ -349,22 +349,9 @@ const std::vector<FlagTable> flagTables = {
{ 0x30, "Entered the Market" }, { 0x30, "Entered the Market" },
} }, } },
{ "Randomizer Inf Flags", RANDOMIZER_INF, 16, { { "Randomizer Inf Flags", RANDOMIZER_INF, 16, {
{ RAND_INF_DUNGEONS_DONE_DEKU_TREE, "DUNGEONS_DONE_DEKU_TREE" },
{ RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN, "DUNGEONS_DONE_DODONGOS_CAVERN" },
{ RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY, "DUNGEONS_DONE_JABU_JABUS_BELLY" },
{ RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE, "DUNGEONS_DONE_FOREST_TEMPLE" },
{ RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE, "DUNGEONS_DONE_FIRE_TEMPLE" },
{ RAND_INF_DUNGEONS_DONE_WATER_TEMPLE, "DUNGEONS_DONE_WATER_TEMPLE" },
{ RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "DUNGEONS_DONE_SPIRIT_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "DUNGEONS_DONE_SPIRIT_TEMPLE" },
{ RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "DUNGEONS_DONE_SHADOW_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "DUNGEONS_DONE_SHADOW_TEMPLE" },
{ RAND_INF_TRIALS_DONE_LIGHT_TRIAL, "TRIALS_DONE_LIGHT_TRIAL" },
{ RAND_INF_TRIALS_DONE_FOREST_TRIAL, "TRIALS_DONE_FOREST_TRIAL" },
{ RAND_INF_TRIALS_DONE_FIRE_TRIAL, "TRIALS_DONE_FIRE_TRIAL" },
{ RAND_INF_TRIALS_DONE_WATER_TRIAL, "TRIALS_DONE_WATER_TRIAL" },
{ RAND_INF_TRIALS_DONE_SPIRIT_TRIAL, "TRIALS_DONE_SPIRIT_TRIAL" },
{ RAND_INF_TRIALS_DONE_SHADOW_TRIAL, "TRIALS_DONE_SHADOW_TRIAL" },
{ RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW, "COWS_MILKED_KF_LINKS_HOUSE_COW" }, { RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW, "COWS_MILKED_KF_LINKS_HOUSE_COW" },
{ RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW, "COWS_MILKED_HF_COW_GROTTO_COW" }, { RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW, "COWS_MILKED_HF_COW_GROTTO_COW" },
{ RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW, "COWS_MILKED_LLR_STABLES_LEFT_COW" }, { RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW, "COWS_MILKED_LLR_STABLES_LEFT_COW" },
@ -505,6 +492,7 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" }, { RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" },
{ RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" }, { RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" },
{ RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" }, { RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" },
{ RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" },
{ RAND_INF_GOHMA_SOUL, "RAND_INF_GOHMA_SOUL" }, { RAND_INF_GOHMA_SOUL, "RAND_INF_GOHMA_SOUL" },
{ RAND_INF_KING_DODONGO_SOUL, "RAND_INF_KING_DODONGO_SOUL" }, { RAND_INF_KING_DODONGO_SOUL, "RAND_INF_KING_DODONGO_SOUL" },
@ -515,7 +503,6 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_BONGO_BONGO_SOUL, "RAND_INF_BONGO_BONGO_SOUL" }, { RAND_INF_BONGO_BONGO_SOUL, "RAND_INF_BONGO_BONGO_SOUL" },
{ RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" }, { RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" },
{ RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" }, { RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" },
{ RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" },
{ RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A"}, { RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A"},
{ RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" }, { RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" },
@ -607,7 +594,19 @@ const std::vector<FlagTable> flagTables = {
{ RAND_INF_ZD_FISH_2, "RAND_INF_ZD_FISH_2" }, { RAND_INF_ZD_FISH_2, "RAND_INF_ZD_FISH_2" },
{ RAND_INF_ZD_FISH_3, "RAND_INF_ZD_FISH_3" }, { RAND_INF_ZD_FISH_3, "RAND_INF_ZD_FISH_3" },
{ RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" }, { RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" },
{ RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" } { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" },
{ RAND_INF_LINKS_POCKET, "RAND_INF_LINKS_POCKET" },
{ RAND_INF_LEARNED_EPONA_SONG, "RAND_INF_LEARNED_EPONA_SONG" },
{ RAND_INF_DARUNIAS_JOY, "RAND_INF_DARUNIAS_JOY" },
{ RAND_INF_KING_ZORA_THAWED, "RAND_INF_KING_ZORA_THAWED" },
{ RAND_INF_HC_GREAT_FAIRY_REWARD, "RAND_INF_HC_GREAT_FAIRY_REWARD" },
{ RAND_INF_DMT_GREAT_FAIRY_REWARD, "RAND_INF_DMT_GREAT_FAIRY_REWARD" },
{ RAND_INF_DMC_GREAT_FAIRY_REWARD, "RAND_INF_DMC_GREAT_FAIRY_REWARD" },
{ RAND_INF_ZF_GREAT_FAIRY_REWARD, "RAND_INF_ZF_GREAT_FAIRY_REWARD" },
{ RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD, "RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD" },
{ RAND_INF_OGC_GREAT_FAIRY_REWARD, "RAND_INF_OGC_GREAT_FAIRY_REWARD" },
} }, } },
}; };

View File

@ -34,6 +34,8 @@ std::vector<ValueTableElement> valueTable = {
{ "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE }, { "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE },
{ "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE }, { "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE },
{ "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE }, { "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE },
{ "getItemID", "Player->getItemId", "ITEM:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->getItemId; }, WHITE },
{ "getItemEntry", "Player->getItemEntry", "IE:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->getItemEntry.itemId; }, WHITE },
/* TODO: Find these (from GZ) /* TODO: Find these (from GZ)
"XZ Units Traveled (Camera based speed variable)" f32 0x801C9018 "XZ Units Traveled (Camera based speed variable)" f32 0x801C9018
"Movement Angle" x16 0x801DBB1C "Movement Angle" x16 0x801DBB1C

View File

@ -14,6 +14,13 @@ typedef enum {
CSMC_SIZE CSMC_SIZE
} ChestStyleMatchesContentsType; } ChestStyleMatchesContentsType;
typedef enum {
SGIA_DISABLED,
SGIA_JUNK,
SGIA_ALL,
SGIA_SIZE
} SkipGetItemAnimationType;
typedef enum { typedef enum {
BUNNY_HOOD_VANILLA, BUNNY_HOOD_VANILLA,
BUNNY_HOOD_FAST_AND_JUMP, BUNNY_HOOD_FAST_AND_JUMP,

View File

@ -3,6 +3,7 @@
#ifndef GameInteractor_h #ifndef GameInteractor_h
#define GameInteractor_h #define GameInteractor_h
#include "libultraship/libultraship.h"
#include "GameInteractionEffect.h" #include "GameInteractionEffect.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h" #include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include <z64.h> #include <z64.h>
@ -67,6 +68,328 @@ typedef enum {
/* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_7, /* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_7,
} GITeleportDestinations; } GITeleportDestinations;
typedef enum {
// Vanilla condition: gSaveContext.showTitleCard
GI_VB_SHOW_TITLE_CARD,
// Opt: *EnWonderTalk2
GI_VB_WONDER_TALK,
// Opt: *ElfMsg
GI_VB_NAVI_TALK,
// Vanilla condition: INFTABLE_GREETED_BY_SARIA
GI_VB_NOT_BE_GREETED_BY_SARIA,
// Opt: *EnMd
// Vanilla condition: EnMd->interactInfo.talkState == NPC_TALK_STATE_ACTION
GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST,
// Opt: *EnMd
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)
GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD,
// Opt: *ObjDekujr
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)
GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED,
// Opt: *EnKo
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)
GI_VB_OPEN_KOKIRI_FOREST,
// Opt: *EnOwl
// Vanilla condition: EnOwl->actor.xzDistToPlayer < targetDist
GI_VB_OWL_INTERACTION,
// Vanilla condition: EVENTCHKINF_TALON_RETURNED_FROM_CASTLE
GI_VB_MALON_RETURN_FROM_CASTLE,
// Vanilla condition: CUR_UPG_VALUE(UPG_STRENGTH) <= 0
GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD,
/* Vanilla condition:
```
LINK_IS_ADULT &&
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
```
*/
GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS,
// Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SARIA)
GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG,
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_SONG_EPONA)
GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG,
// Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)
GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER,
// Vanilla condition: (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT
GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER,
// Vanilla condition: !EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT and EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP
GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT,
GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE,
/* Vanilla Condition:
```
LINK_IS_ADULT &&
gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 &&
Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) &&
Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) &&
Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) &&
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL);
```
*/
GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW,
// Opt: *EnGo2
// Vanilla condition: CUR_CAPACITY(UPG_BOMB_BAG) >= 20 && this->waypoint > 7 && this->waypoint < 12
GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD,
// Vanilla condition: !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON)
GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE,
// Opt: *EnMs
// Vanilla condition: gSaveContext.rupees >= sPrices[BEANS_BOUGHT]
GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE,
// Opt: *EnItem00
// Vanilla condition: Flags_GetCollectible(play, this->collectibleFlag)
GI_VB_ITEM00_DESPAWN,
// Opt: *EnTk
// Vanilla condition: gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD
GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN,
// Opt: *EnTk
// Vanilla condition: this->validDigHere == 1
GI_VB_BE_VALID_GRAVEDIGGING_SPOT,
// Opt: *EnTk
// Vanilla condition: this->currentReward == 3
GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE,
// Opt: *EnTk
// Vanilla condition: !Flags_GetItemGetInf(ITEMGETINF_1C)
GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE,
// Opt: *EnShopnuts
/* Vanilla Condition:
```
((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) ||
((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) ||
((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193)))
```
*/
GI_VB_BUSINESS_SCRUB_DESPAWN,
// Opt: *EnCow
// Vanilla condition: play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE))
GI_VB_DESPAWN_HORSE_RACE_COW,
// Opt: *EnHs
// Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30)
GI_VB_DESPAWN_GROG,
// Opt: *EnKo
// Vanilla condition: (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false;
GI_VB_SPAWN_LW_FADO,
// Opt: *EnMk
GI_VB_PLAY_EYEDROP_CREATION_ANIM,
// Opt: *EnDs
GI_VB_PLAY_ODD_POTION_ANIM,
// Opt: *EnMk
// Vanilla condition: INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS
GI_VB_USE_EYEDROP_DIALOGUE,
// Opt: *EnMk
// Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30)
GI_VB_OFFER_BLUE_POTION,
// Vanilla condition: Inventory_HasEmptyBottle() == 0
GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM,
// Opt: *EnNiwLady
GI_VB_SET_CUCCO_COUNT,
// Opt: *EnKz
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)
GI_VB_KING_ZORA_THANK_CHILD,
// Opt: *EnKz
// Vanilla condition: this->actor.textId == 0x401A
GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER,
// Opt: *EnKz
// Vanilla condition: Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)
GI_VB_KING_ZORA_BE_MOVED,
// Vanilla condition: gSaveState.bgsFlag
GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE,
// Vanilla condition: gSaveState.bgsFlag
GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED,
// Vanilla condition: Environment_GetBgsDayCount() >= 3
GI_VB_BIGGORON_CONSIDER_SWORD_FORGED,
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)
GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED,
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_GORON_RUBY)
GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED,
// Opt: *uint16_t
// Vanilla condition: false
GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE,
// Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)
GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED,
// Opt: *EnSyatekiMan
// Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50)
GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD,
// Opt: *EnOkarinaTag
// Vanilla condition: !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME)
GI_VB_BE_ELIGIBLE_TO_OPEN_DOT,
// Opt: *BgDyYoseizo
// Vanilla condition: see soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c
GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD,
// Vanilla condition: see CheckCarpentersFreed in z_en_ge1 and z_en_ge2
GI_VB_GERUDOS_BE_FRIENDLY,
// Vanilla condition: switch
GI_VB_GTG_GATE_BE_OPEN,
/*** Play Cutscenes ***/
GI_VB_PLAY_TRANSITION_CS,
// Opt: *EventChkInf flag
GI_VB_PLAY_ENTRANCE_CS,
// Opt: *cutsceneId
GI_VB_PLAY_ONEPOINT_CS,
// Opt: *actor
GI_VB_PLAY_ONEPOINT_ACTOR_CS,
// Opt: *BgTreemouth
GI_VB_PLAY_DEKU_TREE_INTRO_CS,
// Vanilla condition: !EventChkInf except for spirit & shadow temple which are !medallion, and Jabu which always is true
GI_VB_PLAY_BLUE_WARP_CS,
GI_VB_PLAY_DARUNIAS_JOY_CS,
GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS,
// Vanilla condition: !EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL
GI_VB_PLAY_PULL_MASTER_SWORD_CS,
GI_VB_PLAY_DROP_FISH_FOR_JABU_CS,
// Vanilla condition: player->getItemId == GI_GAUNTLETS_SILVER
GI_VB_PLAY_NABOORU_CAPTURED_CS,
GI_VB_PLAY_ZELDAS_LULLABY_CS,
// Opt: *EnSa
GI_VB_PLAY_SARIAS_SONG_CS,
GI_VB_PLAY_PRELUDE_OF_LIGHT_CS,
GI_VB_PLAY_MINUET_OF_FOREST_CS,
GI_VB_PLAY_BOLERO_OF_FIRE_CS,
GI_VB_PLAY_SERENADE_OF_WATER_CS,
GI_VB_PLAY_EYEDROPS_CS,
// Opt: *EnOkarinaTag
GI_VB_PLAY_DRAIN_WELL_CS,
// Opt: *EnOkarinaTag
// Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SUN)
GI_VB_PLAY_SUNS_SONG_CS,
// Opt: *EnOkarinaTag
GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS,
GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE,
// Opt: *EnOkarinaTag
GI_VB_PLAY_DOOR_OF_TIME_CS,
GI_VB_PLAY_RAINBOW_BRIDGE_CS,
/*** Give Items ***/
// Opt: *EnBox
GI_VB_GIVE_ITEM_FROM_CHEST,
GI_VB_GIVE_ITEM_FROM_BLUE_WARP,
// Opt: *EnItem00
GI_VB_GIVE_ITEM_FROM_ITEM_00,
// Opt: *EnSi
GI_VB_GIVE_ITEM_SKULL_TOKEN,
// Opt: *EnCow
GI_VB_GIVE_ITEM_FROM_COW,
// Opt: *EnDns
GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB,
// Opt: *EnMk
GI_VB_GIVE_ITEM_FROM_LAB_DIVE,
// Opt: *EnDs
GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP,
// Opt: *EnNiwLady
GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD,
// Opt: *EnNiwLady
GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT,
// Opt: *EnKz
// Vanilla condition: !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA)
GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA,
// Opt: *EnGo2
GI_VB_GIVE_ITEM_FROM_GORON,
// Opt: *EnJs
GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN,
// Opt: *EnGm
GI_VB_GIVE_ITEM_FROM_MEDIGORON,
// Opt: *EnMs
GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN,
// Opt: *EnFr
GI_VB_GIVE_ITEM_FROM_FROGS,
// Opt: *EnSkj
GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME,
// Opt: *EnSkj
GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG,
GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF,
// Opt: *EnSyatekiMan
GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY,
// Opt: *EnExItem
GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS,
// Opt: *EnTa
GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS,
// Opt: *EnDivingGame
GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME,
// Opt: *EnGe1
GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY,
// Opt: *EnSth
GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD,
// Opt: *EnHy
GI_VB_GIVE_ITEM_FROM_LOST_DOG,
// Opt: *EnBomBowlPit
GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING,
GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD,
GI_VB_GIVE_ITEM_FAIRY_OCARINA,
GI_VB_GIVE_ITEM_WEIRD_EGG,
GI_VB_GIVE_ITEM_LIGHT_ARROW,
GI_VB_GIVE_ITEM_STRENGTH_1,
GI_VB_GIVE_ITEM_ZELDAS_LETTER,
GI_VB_GIVE_ITEM_MASTER_SWORD,
GI_VB_GIVE_ITEM_OCARINA_OF_TIME,
GI_VB_GIVE_ITEM_KOKIRI_EMERALD,
GI_VB_GIVE_ITEM_GORON_RUBY,
GI_VB_GIVE_ITEM_ZORA_SAPPHIRE,
GI_VB_GIVE_ITEM_LIGHT_MEDALLION,
GI_VB_GIVE_ITEM_FOREST_MEDALLION,
GI_VB_GIVE_ITEM_FIRE_MEDALLION,
GI_VB_GIVE_ITEM_WATER_MEDALLION,
GI_VB_GIVE_ITEM_SPIRIT_MEDALLION,
GI_VB_GIVE_ITEM_SHADOW_MEDALLION,
/*** Give Songs ***/
GI_VB_GIVE_ITEM_ZELDAS_LULLABY,
GI_VB_GIVE_ITEM_SARIAS_SONG,
GI_VB_GIVE_ITEM_EPONAS_SONG,
GI_VB_GIVE_ITEM_SUNS_SONG,
GI_VB_GIVE_ITEM_SONG_OF_TIME,
GI_VB_GIVE_ITEM_SONG_OF_STORMS,
GI_VB_GIVE_ITEM_MINUET_OF_FOREST,
GI_VB_GIVE_ITEM_BOLERO_OF_FIRE,
GI_VB_GIVE_ITEM_SERENADE_OF_WATER,
GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT,
GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW,
GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT,
/*** Adult Trade ***/
// Opt: *EnNiwLady
GI_VB_TRADE_POCKET_CUCCO,
// Opt: *EnHs
GI_VB_TRADE_COJIRO,
// Opt: *EnDs
GI_VB_TRADE_ODD_MUSHROOM,
// Opt: *EnKo
GI_VB_TRADE_ODD_POTION,
// Opt: *EnToryo
GI_VB_TRADE_SAW,
// Opt: *EnKz,
GI_VB_TRADE_PRESCRIPTION,
// Opt: *EnMk
GI_VB_TRADE_FROG,
GI_VB_TRADE_TIMER_ODD_MUSHROOM,
GI_VB_TRADE_TIMER_EYEDROPS,
GI_VB_TRADE_TIMER_FROG,
// Opt: *EnNiwLady
GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM,
/*** Fixes ***/
// Vanilla condition: false
GI_VB_FIX_SAW_SOFTLOCK,
/*** Cheats? ***/
GI_VB_DEKU_STICK_BE_ON_FIRE,
GI_VB_DEKU_STICK_BREAK,
GI_VB_DEKU_STICK_BURN_DOWN,
GI_VB_DEKU_STICK_BURN_OUT,
GI_VB_DEKU_UPDATE_BURNING_DEKU_STICK,
/*** Quick Boss Deaths ***/
// Vanilla condition: true
GI_VB_PHANTOM_GANON_DEATH_SCENE,
GI_VB_NABOORU_KNUCKLE_DEATH_SCENE,
} GIVanillaBehavior;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -98,6 +421,7 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state);
#ifdef __cplusplus #ifdef __cplusplus
#include <thread> #include <thread>
#include <unordered_map>
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <string> #include <string>
@ -213,6 +537,8 @@ public:
DEFINE_HOOK(OnPlayDestroy, void()); DEFINE_HOOK(OnPlayDestroy, void());
DEFINE_HOOK(OnPlayDrawEnd, void()); DEFINE_HOOK(OnPlayDrawEnd, void());
DEFINE_HOOK(OnVanillaBehavior, void(GIVanillaBehavior flag, bool* result, void* opt));
DEFINE_HOOK(OnSaveFile, void(int32_t fileNum)); DEFINE_HOOK(OnSaveFile, void(int32_t fileNum));
DEFINE_HOOK(OnLoadFile, void(int32_t fileNum)); DEFINE_HOOK(OnLoadFile, void(int32_t fileNum));
DEFINE_HOOK(OnDeleteFile, void(int32_t fileNum)); DEFINE_HOOK(OnDeleteFile, void(int32_t fileNum));

View File

@ -90,6 +90,11 @@ void GameInteractor_ExecuteOnPlayDrawEnd() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDrawEnd>(); GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDrawEnd>();
} }
bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnVanillaBehavior>(flag, &result, opt);
return result;
}
// MARK: - Save Files // MARK: - Save Files
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) { void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) {

View File

@ -27,6 +27,7 @@ void GameInteractor_ExecuteOnOcarinaSongAction();
void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price); void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price);
void GameInteractor_ExecuteOnPlayDestroy(); void GameInteractor_ExecuteOnPlayDestroy();
void GameInteractor_ExecuteOnPlayDrawEnd(); void GameInteractor_ExecuteOnPlayDrawEnd();
bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt);
// MARK: - Save Files // MARK: - Save Files
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum); void GameInteractor_ExecuteOnSaveFile(int32_t fileNum);

View File

@ -10,6 +10,9 @@
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h" #include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#include <soh/Enhancements/item-tables/ItemTableManager.h> #include <soh/Enhancements/item-tables/ItemTableManager.h>
#include "soh/Enhancements/nametag.h" #include "soh/Enhancements/nametag.h"
#include "soh/Enhancements/timesaver_hook_handlers.h"
#include "soh/Enhancements/cheat_hook_handlers.h"
#include "soh/Enhancements/randomizer/hook_handlers.h"
#include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_compass/object_gi_compass.h"
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h" #include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
@ -1709,6 +1712,9 @@ void RegisterRandomizerCompasses() {
} }
void InitMods() { void InitMods() {
RandomizerRegisterHooks();
TimeSaverRegisterHooks();
CheatsRegisterHooks();
RegisterTTS(); RegisterTTS();
RegisterInfiniteMoney(); RegisterInfiniteMoney();
RegisterInfiniteHealth(); RegisterInfiniteHealth();

View File

@ -280,6 +280,20 @@ const std::vector<const char*> enhancementsCvars = {
"gPermanentHeartLoss", "gPermanentHeartLoss",
"gRemoveExplosiveLimit", "gRemoveExplosiveLimit",
"gToggleStrength", "gToggleStrength",
"gTimeSavers.SkipCutscene.Intro",
"gTimeSavers.SkipCutscene.Entrances",
"gTimeSavers.SkipCutscene.Story",
"gTimeSavers.SkipCutscene.LearnSong",
"gTimeSavers.SkipCutscene.BossIntro",
"gTimeSavers.SkipCutscene.GlitchAiding",
"gTimeSavers.SkipCutscene.OnePoint",
"gTimeSavers.NoForcedDialog",
"gTimeSavers.SkipOwlInteractions",
"gTimeSavers.SkipMiscInteractions",
"gTimeSavers.DisableTitleCard",
"gTimeSavers.SkipGetItemAnimation",
"gTimeSavers.SkipChildStealth",
"gTimeSavers.SkipTowerEscape",
}; };
const std::vector<const char*> cheatCvars = { const std::vector<const char*> cheatCvars = {

View File

@ -1121,7 +1121,19 @@ int Fill() {
std::vector<RandomizerGet> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; }); std::vector<RandomizerGet> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; });
FastFill(remainingPool, GetAllEmptyLocations(), false); FastFill(remainingPool, GetAllEmptyLocations(), false);
//Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile. //Add default prices to scrubs
for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) {
if (Rando::StaticData::scrubLocations[i] == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || Rando::StaticData::scrubLocations[i] == RC_LW_DEKU_SCRUB_GROTTO_FRONT) {
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(40);
} else if (Rando::StaticData::scrubLocations[i] == RC_HF_DEKU_SCRUB_GROTTO) {
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10);
} else {
auto loc = Rando::StaticData::GetLocation(Rando::StaticData::scrubLocations[i]);
auto item = Rando::StaticData::RetrieveItem(loc->GetVanillaItem());
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(item.GetPrice());
}
}
if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_AFFORDABLE)) { if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_AFFORDABLE)) {
for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) { for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) {
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10); ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10);

View File

@ -389,6 +389,76 @@ void StaticData::HintTable_Init() {
/*french*/ "Selon moi, le #neuvième ou dixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); /*french*/ "Selon moi, le #neuvième ou dixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})});
// /*spanish*/#el noveno o décimo cofre del azar# revela #[[1]]#. // /*spanish*/#el noveno o décimo cofre del azar# revela #[[1]]#.
hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_1] = HintText(CustomMessage("They say that the #first locked room# in the chest game contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, la #première salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#en la primera sala del Cofre del Tesoro# aguarda #[[1]]#.
{},
{CustomMessage("They say that #gambling once# grants #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, #parier une fois# donne #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#apostar solo una vez# revelará #[[1]]#.
CustomMessage("They say that the #first or second game chest# contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, le #premier ou deuxième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})});
// /*spanish*/#el primer o segundo cofre del azar# revela #[[1]]#.
hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_2] = HintText(CustomMessage("They say that the #second locked room# in the chest game contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, la #deuxième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#en la segunda sala del Cofre del Tesoro# aguarda #[[1]]#.
{},
{CustomMessage("They say that #gambling twice# grants #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, #parier deux fois# donne #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#apostar dos veces# revelará #[[1]]#.
CustomMessage("They say that the #third or fourth game chest# contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, le #troisième ou quatrième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})});
// /*spanish*/#el tercer o cuarto cofre del azar# revela #[[1]]#.
hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_3] = HintText(CustomMessage("They say that the #third locked room# in the chest game contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, la #troisième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#en la tercera sala del Cofre del Tesoro# aguarda #[[1]]#.
{},
{CustomMessage("They say that #gambling 3 times# grants #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, #parier trois fois# donne #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#apostar tres veces# revelará #[[1]]#.
CustomMessage("They say that the #fifth or sixth game chest# contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, le #cinquième ou sixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})});
// /*spanish*/#el quinto o sexto cofre del azar# revela #[[1]]#.
hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_4] = HintText(CustomMessage("They say that the #fourth locked room# in the chest game contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, la #quatrième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#en la cuarta sala del Cofre del Tesoro# aguarda #[[1]]#.
{},
{CustomMessage("They say that #gambling 4 times# grants #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, #parier quatre fois# donne #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#apostar cuatro veces# revelará #[[1]]#.
CustomMessage("They say that the #seventh or eighth game chest# contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, le #septième ou huitième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})});
// /*spanish*/#el séptimo u octavo cofre del azar# revela #[[1]]#.
hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_5] = HintText(CustomMessage("They say that the #fifth locked room# in the chest game contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, la #cinquième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#en la quinta sala del Cofre del Tesoro# aguarda #[[1]]#.
{},
{CustomMessage("They say that #gambling 5 times# grants #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, #parier cinq fois# donne #[[1]]#.", {QM_RED, QM_GREEN}),
// /*spanish*/#apostar cinco veces# revelará #[[1]]#.
CustomMessage("They say that the #ninth or tenth game chest# contains #[[1]]#.",
/*german*/ "",
/*french*/ "Selon moi, le #neuvième ou dixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})});
// /*spanish*/#el noveno o décimo cofre del azar# revela #[[1]]#.
hintTextTable[RHT_GF_HBA_1500_POINTS] = HintText(CustomMessage("They say that scoring 1500 in #horseback archery# grants #[[1]]#.", hintTextTable[RHT_GF_HBA_1500_POINTS] = HintText(CustomMessage("They say that scoring 1500 in #horseback archery# grants #[[1]]#.",
/*german*/ "", /*german*/ "",
/*french*/ "Selon moi, obtenir 1500 points dans l'#archerie équestre# donne #[[1]]#.", {QM_RED, QM_GREEN}), /*french*/ "Selon moi, obtenir 1500 points dans l'#archerie équestre# donne #[[1]]#.", {QM_RED, QM_GREEN}),

View File

@ -904,11 +904,16 @@ void GenerateItemPool() {
} else if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK)) { } else if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK)) {
AddItemToMainPool(RG_TREASURE_GAME_SMALL_KEY); // 1 key which will behave as a pack of 6 AddItemToMainPool(RG_TREASURE_GAME_SMALL_KEY); // 1 key which will behave as a pack of 6
} else { } else {
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, false, true); ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_GREEN_RUPEE, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, false, true); ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_GREEN_RUPEE, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_TREASURE_GAME_SMALL_KEY, false, true); ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_BLUE_RUPEE, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_TREASURE_GAME_SMALL_KEY, false, true); ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_BLUE_RUPEE, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, false, true); ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_RED_RUPEE, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, RG_TREASURE_GAME_SMALL_KEY, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, RG_TREASURE_GAME_SMALL_KEY, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, RG_TREASURE_GAME_SMALL_KEY, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, RG_TREASURE_GAME_SMALL_KEY, false, true);
ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RG_TREASURE_GAME_SMALL_KEY, false, true);
}; };
if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) { if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) {

View File

@ -65,6 +65,7 @@ void AreaTable_Init_CastleTown() {
}, { }, {
//Locations //Locations
LocationAccess(RC_TOT_MASTER_SWORD, {[]{return logic->IsAdult;}}), LocationAccess(RC_TOT_MASTER_SWORD, {[]{return logic->IsAdult;}}),
LocationAccess(RC_GIFT_FROM_SAGES, {[]{return logic->IsAdult;}}),
LocationAccess(RC_SHEIK_AT_TEMPLE, {[]{return logic->ForestMedallion && logic->IsAdult;}}), LocationAccess(RC_SHEIK_AT_TEMPLE, {[]{return logic->ForestMedallion && logic->IsAdult;}}),
}, { }, {
//Exits //Exits
@ -234,10 +235,15 @@ void AreaTable_Init_CastleTown() {
//Locations //Locations
LocationAccess(RC_GREG_HINT, {[]{return true;}}), LocationAccess(RC_GREG_HINT, {[]{return true;}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return logic->ChildsWallet && ((logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return logic->ChildsWallet && ((logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}),
}, { }, {
//Exits //Exits

View File

@ -18,16 +18,11 @@ typedef enum {
SPOILER_CHK_ITEM_GET_INF, SPOILER_CHK_ITEM_GET_INF,
SPOILER_CHK_EVENT_CHK_INF, SPOILER_CHK_EVENT_CHK_INF,
SPOILER_CHK_INF_TABLE, SPOILER_CHK_INF_TABLE,
SPOILER_CHK_COW,
SPOILER_CHK_FISH, SPOILER_CHK_FISH,
SPOILER_CHK_MINIGAME, SPOILER_CHK_MINIGAME,
SPOILER_CHK_SCRUB,
SPOILER_CHK_GERUDO_MEMBERSHIP_CARD,
SPOILER_CHK_POE_POINTS, SPOILER_CHK_POE_POINTS,
SPOILER_CHK_SHOP_ITEM, SPOILER_CHK_SHOP_ITEM,
SPOILER_CHK_MAGIC_BEANS,
SPOILER_CHK_MASTER_SWORD, SPOILER_CHK_MASTER_SWORD,
SPOILER_CHK_MERCHANT,
SPOILER_CHK_GRAVEDIGGER, SPOILER_CHK_GRAVEDIGGER,
SPOILER_CHK_RANDOMIZER_INF, SPOILER_CHK_RANDOMIZER_INF,
} SpoilerCollectionCheckType; } SpoilerCollectionCheckType;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
#ifndef RANDOMIZER_HOOK_HANDLERS_H
#define RANDOMIZER_HOOK_HANDLERS_H
void RandomizerRegisterHooks();
#endif // RANDOMIZER_HOOK_HANDLERS_H

View File

@ -101,6 +101,18 @@ void ItemLocation::SetCustomPrice(const uint16_t price_) {
hasCustomPrice = true; hasCustomPrice = true;
} }
bool ItemLocation::HasObtained() const {
return obtained;
}
void ItemLocation::MarkAsObtained() {
obtained = true;
}
void ItemLocation::MarkAsNotObtained() {
obtained = false;
}
bool ItemLocation::IsHintable() const { bool ItemLocation::IsHintable() const {
return isHintable; return isHintable;
} }
@ -201,5 +213,6 @@ void ItemLocation::ResetVariables() {
wothCandidate = false; wothCandidate = false;
barrenCandidate = false; barrenCandidate = false;
area = RA_NONE; area = RA_NONE;
obtained = false;
} }
} }

View File

@ -31,6 +31,9 @@ class ItemLocation {
void SetPrice(uint16_t price_); void SetPrice(uint16_t price_);
bool HasCustomPrice() const; bool HasCustomPrice() const;
void SetCustomPrice(uint16_t price_); void SetCustomPrice(uint16_t price_);
bool HasObtained() const;
void MarkAsObtained();
void MarkAsNotObtained();
bool IsHintable() const; bool IsHintable() const;
void SetAsHintable(); void SetAsHintable();
bool IsAHintAccessible() const; bool IsAHintAccessible() const;
@ -67,5 +70,6 @@ class ItemLocation {
bool visibleInImGui = false; bool visibleInImGui = false;
bool wothCandidate = false; bool wothCandidate = false;
bool barrenCandidate = false; bool barrenCandidate = false;
bool obtained = false;
}; };
} // namespace Rando } // namespace Rando

View File

@ -16,10 +16,10 @@ class SpoilerCollectionCheck {
public: public:
SpoilerCollectionCheckType type = SPOILER_CHK_NONE; SpoilerCollectionCheckType type = SPOILER_CHK_NONE;
uint8_t scene = 0; uint8_t scene = 0;
uint8_t flag = 0; uint16_t flag = 0;
SpoilerCollectionCheck() = default; SpoilerCollectionCheck() = default;
SpoilerCollectionCheck(const SpoilerCollectionCheckType type_, const uint8_t scene_, const uint8_t flag_) SpoilerCollectionCheck(const SpoilerCollectionCheckType type_, const uint8_t scene_, const uint16_t flag_)
: type(type_), scene(scene_), flag(flag_) { : type(type_), scene(scene_), flag(flag_) {
} }
@ -39,8 +39,8 @@ class SpoilerCollectionCheck {
return SpoilerCollectionCheck(SPOILER_CHK_EVENT_CHK_INF, 0xFF, flag); return SpoilerCollectionCheck(SPOILER_CHK_EVENT_CHK_INF, 0xFF, flag);
} }
static auto InfTable(const uint8_t offset, const uint8_t bit) { static auto InfTable(const uint16_t flag) {
return SpoilerCollectionCheck(SPOILER_CHK_INF_TABLE, offset, bit); return SpoilerCollectionCheck(SPOILER_CHK_INF_TABLE, 0xFF, flag);
} }
static auto Collectable(const uint8_t scene, const uint8_t flag) { static auto Collectable(const uint8_t scene, const uint8_t flag) {
@ -51,10 +51,6 @@ class SpoilerCollectionCheck {
return SpoilerCollectionCheck(SPOILER_CHK_CHEST, scene, flag); return SpoilerCollectionCheck(SPOILER_CHK_CHEST, scene, flag);
} }
static auto Cow(const uint8_t scene, const uint8_t flag) {
return SpoilerCollectionCheck(SPOILER_CHK_COW, scene, flag);
}
static auto Fish(const uint8_t flag, const uint8_t scene = SCENE_FISHING_POND) { static auto Fish(const uint8_t flag, const uint8_t scene = SCENE_FISHING_POND) {
return SpoilerCollectionCheck(SPOILER_CHK_FISH, scene, flag); return SpoilerCollectionCheck(SPOILER_CHK_FISH, scene, flag);
} }
@ -63,14 +59,6 @@ class SpoilerCollectionCheck {
return SpoilerCollectionCheck(SPOILER_CHK_MINIGAME, 0x00, bit); return SpoilerCollectionCheck(SPOILER_CHK_MINIGAME, 0x00, bit);
} }
static auto Scrub(const uint8_t scene, const uint8_t bit) {
return SpoilerCollectionCheck(SPOILER_CHK_SCRUB, scene, bit);
}
static auto GerudoToken() {
return SpoilerCollectionCheck(SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00);
}
static auto BigPoePoints() { static auto BigPoePoints() {
return SpoilerCollectionCheck(SPOILER_CHK_POE_POINTS, 0x00, 0x00); return SpoilerCollectionCheck(SPOILER_CHK_POE_POINTS, 0x00, 0x00);
} }
@ -83,20 +71,12 @@ class SpoilerCollectionCheck {
return SpoilerCollectionCheck(SPOILER_CHK_SHOP_ITEM, scene, itemSlot); return SpoilerCollectionCheck(SPOILER_CHK_SHOP_ITEM, scene, itemSlot);
} }
static auto MagicBeans(const uint8_t scene, const uint8_t flag) {
return SpoilerCollectionCheck(SPOILER_CHK_MAGIC_BEANS, scene, flag);
}
static auto MasterSword() { static auto MasterSword() {
return SpoilerCollectionCheck(SPOILER_CHK_MASTER_SWORD, 0x00, 0x00); return SpoilerCollectionCheck(SPOILER_CHK_MASTER_SWORD, 0x00, 0x00);
} }
static auto Merchant(const int8_t scene, const uint8_t flag) { static auto RandomizerInf(const uint16_t flag) {
return SpoilerCollectionCheck(SPOILER_CHK_MERCHANT, scene, flag); return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, 0x00, flag);
}
static auto RandomizerInf(const int8_t scene, const uint8_t flag) {
return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, scene, flag);
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@ -438,8 +438,6 @@ void Settings::CreateOptionDescriptions() {
"Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " "Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up "
"until after meeting Zelda. Disables the ability to shuffle Weird Egg."; "until after meeting Zelda. Disables the ability to shuffle Weird Egg.";
mOptionDescriptions[RSK_SKIP_EPONA_RACE] = "Epona can be summoned with Epona's Song without needing to race Ingo."; mOptionDescriptions[RSK_SKIP_EPONA_RACE] = "Epona can be summoned with Epona's Song without needing to race Ingo.";
mOptionDescriptions[RSK_SKIP_TOWER_ESCAPE] =
"The tower escape sequence between Ganondorf and Ganon will be skipped.";
mOptionDescriptions[RSK_COMPLETE_MASK_QUEST] = mOptionDescriptions[RSK_COMPLETE_MASK_QUEST] =
"Once the happy mask shop is opened, all masks will be available to be borrowed."; "Once the happy mask shop is opened, all masks will be available to be borrowed.";
mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG] = mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG] =

View File

@ -145,21 +145,6 @@ Randomizer::Randomizer() {
Randomizer::~Randomizer() { Randomizer::~Randomizer() {
} }
std::unordered_map<std::string, RandomizerInf> spoilerFileTrialToEnum = {
{ "the Forest Trial", RAND_INF_TRIALS_DONE_FOREST_TRIAL },
{ "l'épreuve de la Forêt", RAND_INF_TRIALS_DONE_FOREST_TRIAL },
{ "the Fire Trial", RAND_INF_TRIALS_DONE_FIRE_TRIAL },
{ "l'épreuve du Feu", RAND_INF_TRIALS_DONE_FIRE_TRIAL },
{ "the Water Trial", RAND_INF_TRIALS_DONE_WATER_TRIAL },
{ "l'épreuve de l'Eau", RAND_INF_TRIALS_DONE_WATER_TRIAL },
{ "the Spirit Trial", RAND_INF_TRIALS_DONE_SPIRIT_TRIAL },
{ "l'épreuve de l'Esprit", RAND_INF_TRIALS_DONE_SPIRIT_TRIAL },
{ "the Shadow Trial", RAND_INF_TRIALS_DONE_SHADOW_TRIAL },
{ "l'épreuve de l'Ombre", RAND_INF_TRIALS_DONE_SHADOW_TRIAL },
{ "the Light Trial", RAND_INF_TRIALS_DONE_LIGHT_TRIAL },
{ "l'épreuve de la Lumière", RAND_INF_TRIALS_DONE_LIGHT_TRIAL }
};
std::unordered_map<std::string, SceneID> spoilerFileDungeonToScene = { std::unordered_map<std::string, SceneID> spoilerFileDungeonToScene = {
{ "Deku Tree", SCENE_DEKU_TREE }, { "Deku Tree", SCENE_DEKU_TREE },
{ "Dodongo's Cavern", SCENE_DODONGOS_CAVERN }, { "Dodongo's Cavern", SCENE_DODONGOS_CAVERN },
@ -344,8 +329,17 @@ void Randomizer::LoadMerchantMessages() {
"Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w")); "Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w"));
} }
bool Randomizer::IsTrialRequired(RandomizerInf trial) { std::map<s32, TrialKey> trialFlagToTrialKey = {
return Rando::Context::GetInstance()->GetTrial(trial - RAND_INF_TRIALS_DONE_LIGHT_TRIAL)->IsRequired(); { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, TK_LIGHT_TRIAL, },
{ EVENTCHKINF_COMPLETED_FOREST_TRIAL, TK_FOREST_TRIAL, },
{ EVENTCHKINF_COMPLETED_FIRE_TRIAL, TK_FIRE_TRIAL, },
{ EVENTCHKINF_COMPLETED_WATER_TRIAL, TK_WATER_TRIAL, },
{ EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, TK_SPIRIT_TRIAL, },
{ EVENTCHKINF_COMPLETED_SHADOW_TRIAL, TK_SHADOW_TRIAL, }
};
bool Randomizer::IsTrialRequired(s32 trialFlag) {
return Rando::Context::GetInstance()->GetTrial(trialFlagToTrialKey[trialFlag])->IsRequired();
} }
GetItemEntry Randomizer::GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, GetItemEntry Randomizer::GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId,
@ -1417,21 +1411,28 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum,
RandomizerCheck specialRc = RC_UNKNOWN_CHECK; RandomizerCheck specialRc = RC_UNKNOWN_CHECK;
// TODO: Migrate these special cases into table, or at least document why they are special // TODO: Migrate these special cases into table, or at least document why they are special
switch(sceneNum) { switch(sceneNum) {
case SCENE_TREASURE_BOX_SHOP: case SCENE_TREASURE_BOX_SHOP: {
if(actorParams == 20170) specialRc = RC_MARKET_TREASURE_CHEST_GAME_REWARD; if ((actorId == ACTOR_EN_BOX && actorParams == 20170) || (actorId == ACTOR_ITEM_ETCETERA && actorParams == 2572)) {
specialRc = RC_MARKET_TREASURE_CHEST_GAME_REWARD;
}
// RANDOTODO update logic to match 3ds rando when we implement keysanity // todo: handle the itemetc part of this so drawing works when we implement shuffle
// keep keys og if (actorId == ACTOR_EN_BOX) {
if ((actorParams & 0x60) == 0x20) break; bool isAKey = (actorParams & 0x60) == 0x20;
if ((actorParams & 0xF) < 2) {
if (GetRandoSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_1 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_1;
if((actorParams & 0xF) < 2) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_1; } else if ((actorParams & 0xF) < 4) {
if((actorParams & 0xF) < 4) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_2; specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_2 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_2;
if((actorParams & 0xF) < 6) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_3; } else if ((actorParams & 0xF) < 6) {
if((actorParams & 0xF) < 8) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_4; specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_3 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_3;
if((actorParams & 0xF) < 10) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_5; } else if ((actorParams & 0xF) < 8) {
specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_4 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_4;
} else if ((actorParams & 0xF) < 10) {
specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_5 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_5;
}
} }
break; break;
}
case SCENE_SACRED_FOREST_MEADOW: case SCENE_SACRED_FOREST_MEADOW:
if (actorId == ACTOR_EN_SA) { if (actorId == ACTOR_EN_SA) {
specialRc = RC_SONG_FROM_SARIA; specialRc = RC_SONG_FROM_SARIA;

View File

@ -43,7 +43,7 @@ class Randomizer {
bool SpoilerFileExists(const char* spoilerFileName); bool SpoilerFileExists(const char* spoilerFileName);
void LoadMerchantMessages(); void LoadMerchantMessages();
void LoadHintMessages(); void LoadHintMessages();
bool IsTrialRequired(RandomizerInf trial); bool IsTrialRequired(s32 trialFlag);
u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey);
RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf); RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf);
RandomizerInf GetRandomizerInfFromCheck(RandomizerCheck rc); RandomizerInf GetRandomizerInfFromCheck(RandomizerCheck rc);

View File

@ -747,6 +747,11 @@ typedef enum {
RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RC_MARKET_TREASURE_CHEST_GAME_ITEM_3,
RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RC_MARKET_TREASURE_CHEST_GAME_ITEM_4,
RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RC_MARKET_TREASURE_CHEST_GAME_ITEM_5,
RC_MARKET_TREASURE_CHEST_GAME_KEY_1,
RC_MARKET_TREASURE_CHEST_GAME_KEY_2,
RC_MARKET_TREASURE_CHEST_GAME_KEY_3,
RC_MARKET_TREASURE_CHEST_GAME_KEY_4,
RC_MARKET_TREASURE_CHEST_GAME_KEY_5,
RC_MARKET_GS_GUARD_HOUSE, RC_MARKET_GS_GUARD_HOUSE,
RC_MARKET_BAZAAR_ITEM_1, RC_MARKET_BAZAAR_ITEM_1,
RC_MARKET_BAZAAR_ITEM_2, RC_MARKET_BAZAAR_ITEM_2,
@ -2354,6 +2359,11 @@ typedef enum {
RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3,
RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4,
RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5,
RHT_MARKET_TREASURE_CHEST_GAME_KEY_1,
RHT_MARKET_TREASURE_CHEST_GAME_KEY_2,
RHT_MARKET_TREASURE_CHEST_GAME_KEY_3,
RHT_MARKET_TREASURE_CHEST_GAME_KEY_4,
RHT_MARKET_TREASURE_CHEST_GAME_KEY_5,
RHT_MARKET_GS_GUARD_HOUSE, RHT_MARKET_GS_GUARD_HOUSE,
RHT_MARKET_BAZAAR_ITEM_1, RHT_MARKET_BAZAAR_ITEM_1,
RHT_MARKET_BAZAAR_ITEM_2, RHT_MARKET_BAZAAR_ITEM_2,
@ -3620,7 +3630,6 @@ typedef enum {
RSK_CUCCO_COUNT, RSK_CUCCO_COUNT,
RSK_BIG_POE_COUNT, RSK_BIG_POE_COUNT,
RSK_SKIP_EPONA_RACE, RSK_SKIP_EPONA_RACE,
RSK_SKIP_TOWER_ESCAPE,
RSK_COMPLETE_MASK_QUEST, RSK_COMPLETE_MASK_QUEST,
RSK_SKIP_SCARECROWS_SONG, RSK_SKIP_SCARECROWS_SONG,
RSK_ENABLE_GLITCH_CUTSCENES, RSK_ENABLE_GLITCH_CUTSCENES,

View File

@ -440,26 +440,19 @@ bool HasItemBeenCollected(RandomizerCheck rc) {
case SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE: case SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE:
return (gPlayState->sceneNum == scene && gPlayState->actorCtx.flags.collect & (1 << flag)) || return (gPlayState->sceneNum == scene && gPlayState->actorCtx.flags.collect & (1 << flag)) ||
gSaveContext.sceneFlags[scene].collect & (1 << flag); gSaveContext.sceneFlags[scene].collect & (1 << flag);
case SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT:
case SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM: case SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM:
case SpoilerCollectionCheckType::SPOILER_CHK_COW:
case SpoilerCollectionCheckType::SPOILER_CHK_FISH: case SpoilerCollectionCheckType::SPOILER_CHK_FISH:
case SpoilerCollectionCheckType::SPOILER_CHK_SCRUB:
case SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF: case SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF:
case SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD: case SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD:
return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc)); return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc));
case SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF: case SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF:
return gSaveContext.eventChkInf[flag / 16] & (0x01 << flag % 16); return gSaveContext.eventChkInf[flag / 16] & (0x01 << flag % 16);
case SpoilerCollectionCheckType::SPOILER_CHK_GERUDO_MEMBERSHIP_CARD:
return CHECK_FLAG_ALL(gSaveContext.eventChkInf[0x09], 0x0F);
case SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA: case SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA:
return GET_GS_FLAGS(scene) & flag; return GET_GS_FLAGS(scene) & flag;
case SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE: case SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE:
return gSaveContext.infTable[scene] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag); return gSaveContext.infTable[scene] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag);
case SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF: case SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF:
return gSaveContext.itemGetInf[flag / 16] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag); return gSaveContext.itemGetInf[flag / 16] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag);
case SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS:
return BEANS_BOUGHT >= 10;
case SpoilerCollectionCheckType::SPOILER_CHK_NONE: case SpoilerCollectionCheckType::SPOILER_CHK_NONE:
return false; return false;
case SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER: case SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER:
@ -782,11 +775,8 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) {
Rando::SpoilerCollectionCheck scCheck = loc.GetCollectionCheck(); Rando::SpoilerCollectionCheck scCheck = loc.GetCollectionCheck();
SpoilerCollectionCheckType scCheckType = scCheck.type; SpoilerCollectionCheckType scCheckType = scCheck.type;
if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF && if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF &&
(scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT || (scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_COW ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_FISH || scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_FISH ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SCRUB ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD || scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF)) { scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF)) {
if (flag == OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(loc.GetRandomizerCheck())) { if (flag == OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(loc.GetRandomizerCheck())) {
@ -1372,6 +1362,11 @@ void DrawLocation(RandomizerCheck rc) {
Rando::ItemLocation* itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc); Rando::ItemLocation* itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rc]; RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rc];
RandomizerCheckStatus status = checkData.status; RandomizerCheckStatus status = checkData.status;
if (itemLoc->HasObtained()) {
status = RCSHOW_COLLECTED;
}
bool skipped = checkData.skipped; bool skipped = checkData.skipped;
if (status == RCSHOW_COLLECTED) { if (status == RCSHOW_COLLECTED) {
if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0)) { if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0)) {
@ -1706,12 +1701,12 @@ void CheckTrackerWindow::InitElement() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnExitGame>([](uint32_t fileNum) { GameInteractor::Instance->RegisterGameHook<GameInteractor::OnExitGame>([](uint32_t fileNum) {
Teardown(); Teardown();
}); });
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(CheckTrackerItemReceive); // GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(CheckTrackerItemReceive);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(CheckTrackerFrame); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(CheckTrackerFrame);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(CheckTrackerTransition); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(CheckTrackerTransition);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnShopSlotChange>(CheckTrackerShopSlotChange); GameInteractor::Instance->RegisterGameHook<GameInteractor::OnShopSlotChange>(CheckTrackerShopSlotChange);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(CheckTrackerSceneFlagSet); // GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(CheckTrackerSceneFlagSet);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(CheckTrackerFlagSet); // GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(CheckTrackerFlagSet);
hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1); hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1);
alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0); alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0);

View File

@ -448,34 +448,31 @@ void Entrance_SetWarpSongEntrance(void) {
} }
void Entrance_OverrideBlueWarp(void) { void Entrance_OverrideBlueWarp(void) {
// Set nextEntranceIndex as a flag so that Grotto_CheckSpecialEntrance // Handles first time entering bluewarp (with item give)
// won't return index 0x7FFF, which can't work to override blue warps. switch (gSaveContext.entranceIndex) {
gPlayState->nextEntranceIndex = 0; case ENTR_KOKIRI_FOREST_11: // Gohma blue warp
case ENTR_DEATH_MOUNTAIN_TRAIL_5: // KD blue warp
case ENTR_ZORAS_FOUNTAIN_0: // Barinade blue warp
case ENTR_SACRED_FOREST_MEADOW_3: // Phantom Ganon blue warp
case ENTR_DEATH_MOUNTAIN_CRATER_5: // Volvagia blue warp
case ENTR_LAKE_HYLIA_9: // Morpha blue warp
case ENTR_DESERT_COLOSSUS_8: // Bongo-Bongo blue warp
case ENTR_GRAVEYARD_8: // Twinrova blue warp
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(gSaveContext.entranceIndex);
return;
}
switch (gPlayState->sceneNum) { // Handles second+ times entering bluewarp
case SCENE_DEKU_TREE_BOSS: // Ghoma boss room switch (gPlayState->nextEntranceIndex) {
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_KOKIRI_FOREST_11); case ENTR_KOKIRI_FOREST_11: // Gohma blue warp
return; case ENTR_DEATH_MOUNTAIN_TRAIL_5: // KD blue warp
case SCENE_DODONGOS_CAVERN_BOSS: // King Dodongo boss room case ENTR_ZORAS_FOUNTAIN_0: // Barinade blue warp
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DEATH_MOUNTAIN_TRAIL_5); case ENTR_SACRED_FOREST_MEADOW_3: // Phantom Ganon blue warp
return; case ENTR_DEATH_MOUNTAIN_CRATER_5: // Volvagia blue warp
case SCENE_JABU_JABU_BOSS: // Barinade boss room case ENTR_LAKE_HYLIA_9: // Morpha blue warp
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_ZORAS_FOUNTAIN_0); case ENTR_DESERT_COLOSSUS_8: // Bongo-Bongo blue warp
return; case ENTR_GRAVEYARD_8: // Twinrova blue warp
case SCENE_FOREST_TEMPLE_BOSS: // Phantom Ganon boss room gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(gPlayState->nextEntranceIndex);
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_SACRED_FOREST_MEADOW_3);
return;
case SCENE_FIRE_TEMPLE_BOSS: // Volvagia boss room
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DEATH_MOUNTAIN_CRATER_5);
return;
case SCENE_WATER_TEMPLE_BOSS: // Morpha boss room
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_LAKE_HYLIA_9);
return;
case SCENE_SPIRIT_TEMPLE_BOSS: // Twinrova boss room
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DESERT_COLOSSUS_8);
return;
case SCENE_SHADOW_TEMPLE_BOSS: // Bongo-Bongo boss room
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_GRAVEYARD_8);
return; return;
} }
} }

View File

@ -1,22 +1,9 @@
#pragma once #pragma once
typedef enum { typedef enum {
RAND_INF_DUNGEONS_DONE_DEKU_TREE,
RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN,
RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY,
RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE,
RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE,
RAND_INF_DUNGEONS_DONE_WATER_TEMPLE,
RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE,
RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE,
RAND_INF_TRIALS_DONE_LIGHT_TRIAL,
RAND_INF_TRIALS_DONE_FOREST_TRIAL,
RAND_INF_TRIALS_DONE_FIRE_TRIAL,
RAND_INF_TRIALS_DONE_WATER_TRIAL,
RAND_INF_TRIALS_DONE_SPIRIT_TRIAL,
RAND_INF_TRIALS_DONE_SHADOW_TRIAL,
RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW, RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW,
RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW, RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW,
RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW, RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW,
@ -143,12 +130,15 @@ typedef enum {
RAND_INF_MERCHANTS_CARPET_SALESMAN, RAND_INF_MERCHANTS_CARPET_SALESMAN,
RAND_INF_MERCHANTS_MEDIGORON, RAND_INF_MERCHANTS_MEDIGORON,
RAND_INF_MERCHANTS_GRANNYS_SHOP, RAND_INF_MERCHANTS_GRANNYS_SHOP,
RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN,
RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO, RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO,
RAND_INF_ADULT_TRADES_GV_TRADE_SAW, RAND_INF_ADULT_TRADES_GV_TRADE_SAW,
RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD, RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD,
RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION,
RAND_INF_ADULT_TRADES_LH_TRADE_FROG, RAND_INF_ADULT_TRADES_LH_TRADE_FROG,
RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS, RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS,
RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK,
RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD, RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD,
@ -267,6 +257,31 @@ typedef enum {
RAND_INF_ZD_FISH_4, RAND_INF_ZD_FISH_4,
RAND_INF_ZD_FISH_5, RAND_INF_ZD_FISH_5,
RAND_INF_LINKS_POCKET,
RAND_INF_LEARNED_EPONA_SONG,
RAND_INF_DARUNIAS_JOY,
RAND_INF_KING_ZORA_THAWED,
RAND_INF_HC_GREAT_FAIRY_REWARD,
RAND_INF_DMT_GREAT_FAIRY_REWARD,
RAND_INF_DMC_GREAT_FAIRY_REWARD,
RAND_INF_ZF_GREAT_FAIRY_REWARD,
RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD,
RAND_INF_OGC_GREAT_FAIRY_REWARD,
RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1,
RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2,
RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3,
RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4,
RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5,
RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1,
RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2,
RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3,
RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4,
RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5,
RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS,
RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN,
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
RAND_INF_MAX, RAND_INF_MAX,

View File

@ -97,6 +97,9 @@ void GiveLinksPocketItem() {
if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) { if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, (GetItemID)RG_NONE); GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, (GetItemID)RG_NONE);
StartingItemGive(getItemEntry); StartingItemGive(getItemEntry);
Rando::Context::GetInstance()->GetItemLocation(RC_LINKS_POCKET)->MarkAsObtained();
// If we re-add the above, we'll get the item on save creation, now it's given on first load
Flags_SetRandomizerInf(RAND_INF_LINKS_POCKET);
} }
} }
@ -202,99 +205,102 @@ void SetStartingItems() {
} }
extern "C" void Randomizer_InitSaveFile() { extern "C" void Randomizer_InitSaveFile() {
// Sets all rando flags to false // Now handled by cutscene skips
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) { // gSaveContext.cutsceneIndex = 0; // no intro cutscene
gSaveContext.randomizerInf[i] = 0; // Starts pending ice traps out at 0 before potentially incrementing them down the line.
} gSaveContext.pendingIceTrapCount = 0;
// Reset triforce pieces collected // Reset triforce pieces collected
gSaveContext.triforcePiecesCollected = 0; gSaveContext.triforcePiecesCollected = 0;
gSaveContext.cutsceneIndex = 0; // no intro cutscene
// Starts pending ice traps out at 0 before potentially incrementing them down the line.
gSaveContext.pendingIceTrapCount = 0;
// Set Cutscene flags and texts to skip them // Set Cutscene flags and texts to skip them
Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); // Now handled by cutscene skips
// Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA);
Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO); Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO);
Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); // Now handled by cutscene skips
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); // Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE);
// Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
Flags_SetInfTable(INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA); Flags_SetInfTable(INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); // Now handled by cutscene skips
Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
// Now using this to grant master sword check
// Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL);
Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); // Now used to give player LACS rewards
// Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
Flags_SetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO); Flags_SetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO);
Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET); Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET);
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE);
Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); // Now handled by cutscene skips
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); // Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET);
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS); // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET);
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS);
Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH);
Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); // Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON);
Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT); // Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU);
// Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT);
// Ruto already met in jabu and spawns down the hole immediately // Ruto already met in jabu and spawns down the hole immediately
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO); Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO);
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME); Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME);
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE); Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE);
// Now handled by cutscene skips
// Skip cutscenes before Nabooru fight // Skip cutscenes before Nabooru fight
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE);
Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA); // Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA);
// Now handled by cutscene skips
// Skip boss cutscenes // Skip boss cutscenes
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE);
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE);
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE);
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE);
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE);
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE);
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE);
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE);
// Entered areas // Now handled by cutscene skips
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR); // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR);
Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); // Ensure Malon appears at castle first time you enter
// Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE);
// skip the z target talk instructions by the kokiri shop // skip the z target talk instructions by the kokiri shop
gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 0x1F); // Now handled by cutscene skips
// gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 0x1F);
// Go away ruto (water temple first cutscene) // Go away ruto (water temple first cutscene)
gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10); gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10);
// Now handled by cutscene skips
// no more kaepora // no more kaepora
gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest // gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest
gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia // gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia
gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x7); // lost woods kaepora pre-saria // gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x7); // lost woods kaepora pre-saria
gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x8); // lost woods kaepora post-saria // gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x8); // lost woods kaepora post-saria
gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora // gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora
gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora // gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora
if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) {
Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); // Darunia in Fire Temple
}
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS) == RO_GENERIC_OFF) { if (Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS) == RO_GENERIC_OFF) {
Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_A); Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_A);
@ -341,10 +347,15 @@ extern "C" void Randomizer_InitSaveFile() {
gSaveContext.entranceIndex = -1; gSaveContext.entranceIndex = -1;
} }
// If any trials aren't required, set them as completed for (auto trialFlag : { EVENTCHKINF_COMPLETED_LIGHT_TRIAL,
for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) { EVENTCHKINF_COMPLETED_FOREST_TRIAL,
if (!OTRGlobals::Instance->gRandomizer->IsTrialRequired((RandomizerInf)i)) { EVENTCHKINF_COMPLETED_FIRE_TRIAL,
Flags_SetRandomizerInf((RandomizerInf)i); EVENTCHKINF_COMPLETED_WATER_TRIAL,
EVENTCHKINF_COMPLETED_SPIRIT_TRIAL,
EVENTCHKINF_COMPLETED_SHADOW_TRIAL }
) {
if (!OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag)) {
Flags_SetEventChkInf(trialFlag);
} }
} }
@ -398,15 +409,16 @@ extern "C" void Randomizer_InitSaveFile() {
gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15);
} }
int openForest = Randomizer_GetSettingValue(RSK_FOREST); // Now handled on the fly
switch (openForest) { // int openForest = Randomizer_GetSettingValue(RSK_FOREST);
case RO_FOREST_OPEN: // switch (openForest) {
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); // case RO_FOREST_OPEN:
// Fallthrough // Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
case RO_FOREST_CLOSED_DEKU: // // Fallthrough
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); // case RO_FOREST_CLOSED_DEKU:
break; // Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
} // break;
// }
int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
switch (doorOfTime) { switch (doorOfTime) {

View File

@ -147,7 +147,6 @@ void Settings::CreateOptions() {
mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::Bool("Ganon's Castle", "gRandomizeShuffleKeyRingsGanonsCastle"); mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::Bool("Ganon's Castle", "gRandomizeShuffleKeyRingsGanonsCastle");
mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildStealth", mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildStealth", mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildZelda", mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildZelda", mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
mOptions[RSK_SKIP_TOWER_ESCAPE] = Option::Bool("Skip Tower Escape", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipTowerEscape", mOptionDescriptions[RSK_SKIP_TOWER_ESCAPE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipEponaRace", mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipEponaRace", mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
mOptions[RSK_SKIP_SCARECROWS_SONG] = Option::Bool("Skip Scarecrow's Song", "gRandomizeSkipScarecrowsSong", mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]); mOptions[RSK_SKIP_SCARECROWS_SONG] = Option::Bool("Skip Scarecrow's Song", "gRandomizeSkipScarecrowsSong", mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]);
mOptions[RSK_BIG_POE_COUNT] = Option::U8("Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, "gRandomizeBigPoeTargetCount", mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9); mOptions[RSK_BIG_POE_COUNT] = Option::U8("Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, "gRandomizeBigPoeTargetCount", mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9);
@ -715,7 +714,6 @@ void Settings::CreateOptions() {
&mOptions[RSK_SKIP_CHILD_STEALTH], &mOptions[RSK_SKIP_CHILD_STEALTH],
&mOptions[RSK_SKIP_CHILD_ZELDA], &mOptions[RSK_SKIP_CHILD_ZELDA],
&mOptions[RSK_SKIP_EPONA_RACE], &mOptions[RSK_SKIP_EPONA_RACE],
&mOptions[RSK_SKIP_TOWER_ESCAPE],
&mOptions[RSK_COMPLETE_MASK_QUEST], &mOptions[RSK_COMPLETE_MASK_QUEST],
&mOptions[RSK_SKIP_SCARECROWS_SONG] &mOptions[RSK_SKIP_SCARECROWS_SONG]
}, false, WidgetContainerType::COLUMN); }, false, WidgetContainerType::COLUMN);
@ -1202,7 +1200,6 @@ void Settings::CreateOptions() {
{ "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT }, { "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT },
{ "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH }, { "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH },
{ "Timesaver Settings:Skip Epona Race", RSK_SKIP_EPONA_RACE }, { "Timesaver Settings:Skip Epona Race", RSK_SKIP_EPONA_RACE },
{ "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE },
{ "Timesaver Settings:Complete Mask Quest", RSK_COMPLETE_MASK_QUEST }, { "Timesaver Settings:Complete Mask Quest", RSK_COMPLETE_MASK_QUEST },
{ "Timesaver Settings:Skip Scarecrow's Song", RSK_SKIP_SCARECROWS_SONG }, { "Timesaver Settings:Skip Scarecrow's Song", RSK_SKIP_SCARECROWS_SONG },
{ "Timesaver Settings:Enable Glitch-Useful Cutscenes", RSK_ENABLE_GLITCH_CUTSCENES }, { "Timesaver Settings:Enable Glitch-Useful Cutscenes", RSK_ENABLE_GLITCH_CUTSCENES },
@ -2526,7 +2523,6 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
case RSK_SKIP_CHILD_ZELDA: case RSK_SKIP_CHILD_ZELDA:
case RSK_SKIP_CHILD_STEALTH: case RSK_SKIP_CHILD_STEALTH:
case RSK_SKIP_EPONA_RACE: case RSK_SKIP_EPONA_RACE:
case RSK_SKIP_TOWER_ESCAPE:
if (it.value() == "Don't Skip") { if (it.value() == "Don't Skip") {
mOptions[index].SetSelectedIndex(RO_GENERIC_DONT_SKIP); mOptions[index].SetSelectedIndex(RO_GENERIC_DONT_SKIP);
} else if (it.value() == "Skip") { } else if (it.value() == "Skip") {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
#ifndef TIMESAVER_HOOK_HANDLERS_H
#define TIMESAVER_HOOK_HANDLERS_H
void TimeSaverRegisterHooks();
#endif // TIMESAVER_HOOK_HANDLERS_H

View File

@ -3,6 +3,7 @@
#include <cassert> #include <cassert>
#include <File.h> #include <File.h>
#include <Json.h>
#include <libultraship/classes.h> #include <libultraship/classes.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <spdlog/fmt/fmt.h> #include <spdlog/fmt/fmt.h>
@ -12,7 +13,6 @@
#include "overlays/gamestates/ovl_file_choose/file_choose.h" #include "overlays/gamestates/ovl_file_choose/file_choose.h"
#include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/Enhancements/boss-rush/BossRush.h"
#include "soh/resource/type/SohResourceType.h" #include "soh/resource/type/SohResourceType.h"
#include "soh/resource/type/RawJson.h"
extern "C" { extern "C" {
extern MapData* gMapData; extern MapData* gMapData;
@ -1041,19 +1041,19 @@ void InitTTSBank() {
auto initData = std::make_shared<LUS::ResourceInitData>(); auto initData = std::make_shared<LUS::ResourceInitData>();
initData->Format = RESOURCE_FORMAT_BINARY; initData->Format = RESOURCE_FORMAT_BINARY;
initData->Type = static_cast<uint32_t>(SOH::ResourceType::SOH_RawJson); initData->Type = static_cast<uint32_t>(LUS::ResourceType::Json);
initData->ResourceVersion = 0; initData->ResourceVersion = 0;
sceneMap = std::static_pointer_cast<SOH::RawJson>( sceneMap = std::static_pointer_cast<LUS::Json>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data; LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data;
miscMap = std::static_pointer_cast<SOH::RawJson>( miscMap = std::static_pointer_cast<LUS::Json>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data; LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data;
kaleidoMap = std::static_pointer_cast<SOH::RawJson>( kaleidoMap = std::static_pointer_cast<LUS::Json>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data; LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data;
fileChooseMap = std::static_pointer_cast<SOH::RawJson>( fileChooseMap = std::static_pointer_cast<LUS::Json>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data; LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data;
} }

View File

@ -120,10 +120,13 @@ GameInteractorSail* GameInteractorSail::Instance;
#include "soh/resource/importer/SkeletonLimbFactory.h" #include "soh/resource/importer/SkeletonLimbFactory.h"
#include "soh/resource/importer/TextFactory.h" #include "soh/resource/importer/TextFactory.h"
#include "soh/resource/importer/BackgroundFactory.h" #include "soh/resource/importer/BackgroundFactory.h"
#include "soh/resource/importer/RawJsonFactory.h"
#include "soh/config/ConfigUpdaters.h" #include "soh/config/ConfigUpdaters.h"
extern "C" {
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
}
void SoH_ProcessDroppedFiles(std::string filePath); void SoH_ProcessDroppedFiles(std::string filePath);
OTRGlobals* OTRGlobals::Instance; OTRGlobals* OTRGlobals::Instance;
@ -345,7 +348,6 @@ OTRGlobals::OTRGlobals() {
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSoundFontV2>(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSoundFont), 2); loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSoundFontV2>(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSoundFont), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSequenceV2>(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSequence), 2); loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSequenceV2>(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSequence), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryBackgroundV0>(), RESOURCE_FORMAT_BINARY, "Background", static_cast<uint32_t>(SOH::ResourceType::SOH_Background), 0); loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryBackgroundV0>(), RESOURCE_FORMAT_BINARY, "Background", static_cast<uint32_t>(SOH::ResourceType::SOH_Background), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryRawJsonV0>(), RESOURCE_FORMAT_BINARY, "RawJson", static_cast<uint32_t>(SOH::ResourceType::SOH_RawJson), 0);
gSaveStateMgr = std::make_shared<SaveStateMgr>(); gSaveStateMgr = std::make_shared<SaveStateMgr>();
gRandoContext->InitStaticData(); gRandoContext->InitStaticData();
@ -2348,8 +2350,8 @@ extern "C" void Randomizer_LoadMerchantMessages() {
OTRGlobals::Instance->gRandomizer->LoadMerchantMessages(); OTRGlobals::Instance->gRandomizer->LoadMerchantMessages();
} }
extern "C" bool Randomizer_IsTrialRequired(RandomizerInf trial) { extern "C" bool Randomizer_IsTrialRequired(s32 trialFlag) {
return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trial); return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag);
} }
extern "C" u32 SpoilerFileExists(const char* spoilerFileName) { extern "C" u32 SpoilerFileExists(const char* spoilerFileName) {
@ -2563,9 +2565,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
} else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) {
messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId);
// textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT) // textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT)
} else if (textId >= TEXT_SCRUB_RANDOM && textId <= TEXT_SCRUB_RANDOM + NUM_SCRUBS) { } else if (textId == TEXT_SCRUB_RANDOM) {
RandomizerInf randoInf = (RandomizerInf)((textId - TEXT_SCRUB_RANDOM) + RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); EnDns* enDns = (EnDns*)GET_PLAYER(play)->targetActor;
messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF); messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(enDns->sohScrubIdentity.randomizerInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF);
// Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS
// textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)
// textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS)

View File

@ -159,7 +159,7 @@ FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams);
void Randomizer_ParseSpoiler(const char* fileLoc); void Randomizer_ParseSpoiler(const char* fileLoc);
void Randomizer_LoadHintMessages(); void Randomizer_LoadHintMessages();
void Randomizer_LoadMerchantMessages(); void Randomizer_LoadMerchantMessages();
bool Randomizer_IsTrialRequired(RandomizerInf trial); bool Randomizer_IsTrialRequired(s32 trialFlag);
GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId);
GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId);
GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);

View File

@ -403,6 +403,13 @@ void SaveManager::LoadRandomizerVersion3() {
// all ItemLocations is 0 anyway. // all ItemLocations is 0 anyway.
randoContext->GetItemLocation(i)->SetCustomPrice(price); randoContext->GetItemLocation(i)->SetCustomPrice(price);
} }
uint16_t obtained = 0;
SaveManager::Instance->LoadData("obtained", obtained, (uint16_t)0);
if (obtained) {
randoContext->GetItemLocation(i)->MarkAsObtained();
} else {
randoContext->GetItemLocation(i)->MarkAsNotObtained();
}
}); });
}); });
@ -488,6 +495,7 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
if (randoContext->GetItemLocation(i)->HasCustomPrice()) { if (randoContext->GetItemLocation(i)->HasCustomPrice()) {
SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice()); SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice());
} }
SaveManager::Instance->SaveData("obtained", randoContext->GetItemLocation(i)->HasObtained());
}); });
}); });
@ -817,6 +825,9 @@ void SaveManager::InitFileNormal() {
for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.infTable); flag++) { for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.infTable); flag++) {
gSaveContext.infTable[flag] = 0; gSaveContext.infTable[flag] = 0;
} }
for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.randomizerInf); flag++) {
gSaveContext.randomizerInf[flag] = 0;
}
gSaveContext.worldMapAreaData = 0; gSaveContext.worldMapAreaData = 0;
gSaveContext.scarecrowLongSongSet = 0; gSaveContext.scarecrowLongSongSet = 0;
for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowLongSong); i++) { for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowLongSong); i++) {

View File

@ -72,6 +72,7 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large
}; };
static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" }; static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" };
static const char* skipGetItemAnimationOptions[3] = { "Disabled", "Junk Items", "All Items" };
static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" }; static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" };
static const char* mirroredWorldModes[9] = { static const char* mirroredWorldModes[9] = {
"Disabled", "Always", "Random", "Random (Seeded)", "Dungeons", "Disabled", "Always", "Random", "Random (Seeded)", "Dungeons",
@ -574,6 +575,88 @@ void DrawEnhancementsMenu() {
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
ImGui::Text("Speed-ups:"); ImGui::Text("Speed-ups:");
UIWidgets::PaddedSeparator(); UIWidgets::PaddedSeparator();
bool allChecked =
CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) &&
CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) &&
CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) &&
CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) &&
CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) &&
CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO) &&
CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) &&
CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) &&
CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) &&
CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) &&
CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO);
bool someChecked =
CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) ||
CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) ||
CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) ||
CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) ||
CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) ||
CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO) ||
CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) ||
CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) ||
CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) ||
CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) ||
CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO);
ImGuiContext* g = ImGui::GetCurrentContext();
ImGuiItemFlags backup_item_flags = g->CurrentItemFlags;
if (!allChecked && someChecked) g->CurrentItemFlags |= ImGuiItemFlags_MixedValue;
if (ImGui::Checkbox("All", &allChecked)) {
if (allChecked) {
CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 1);
CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 1);
CVarSetInteger("gTimeSavers.SkipCutscene.Story", 1);
CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 1);
CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 1);
CVarSetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", 1);
CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 1);
CVarSetInteger("gTimeSavers.NoForcedDialog", 1);
CVarSetInteger("gTimeSavers.SkipOwlInteractions", 1);
CVarSetInteger("gTimeSavers.SkipMiscInteractions", 1);
CVarSetInteger("gTimeSavers.DisableTitleCard", 1);
} else {
CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 0);
CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 0);
CVarSetInteger("gTimeSavers.SkipCutscene.Story", 0);
CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 0);
CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 0);
CVarSetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", 0);
CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 0);
CVarSetInteger("gTimeSavers.NoForcedDialog", 0);
CVarSetInteger("gTimeSavers.SkipOwlInteractions", 0);
CVarSetInteger("gTimeSavers.SkipMiscInteractions", 0);
CVarSetInteger("gTimeSavers.DisableTitleCard", 0);
}
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
g->CurrentItemFlags = backup_item_flags;
UIWidgets::PaddedEnhancementCheckbox("Skip Intro", "gTimeSavers.SkipCutscene.Intro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Skip Entrance Cutscenes", "gTimeSavers.SkipCutscene.Entrances", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Quick Boss Deaths", "gTimeSavers.SkipCutscene.QuickBossDeaths", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::Tooltip("Prevent forced conversations with Navi or other NPCs");
UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0);
UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS");
UIWidgets::PaddedEnhancementCheckbox("Skip Child Stealth", "gTimeSavers.SkipChildStealth", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false);
UIWidgets::Tooltip("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards.");
UIWidgets::PaddedEnhancementCheckbox("Skip Tower Escape", "gTimeSavers.SkipTowerEscape", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false);
UIWidgets::Tooltip("Skip the tower escape sequence between Ganondorf and Ganon.");
UIWidgets::PaddedText("Skip Get Item Animations", true, false);
UIWidgets::EnhancementCombobox("gTimeSavers.SkipGetItemAnimation", skipGetItemAnimationOptions, SGIA_DISABLED);
if (CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) != SGIA_DISABLED) {
UIWidgets::EnhancementSliderFloat("Item Scale: %f", "##ItemScale", "gTimeSavers.SkipGetItemAnimationScale", 5.0f, 15.0f, "", 10.0f, false);
UIWidgets::Tooltip("The size of the item when it is picked up");
}
UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, true, false, true);
UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", false, true); UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", false, true);
@ -605,7 +688,7 @@ void DrawEnhancementsMenu() {
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
ImGui::Text("Changes:"); ImGui::Text("Changes:");
UIWidgets::PaddedSeparator(); UIWidgets::PaddedSeparator();
UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true);
UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword");
UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false); UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false);
@ -1208,7 +1291,8 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map");
UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false); UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false);
UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game");
UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false); UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false, SaveManager::Instance->IsRandoFile(),
"This setting is always enabled in randomizer files", UIWidgets::CheckboxGraphics::Checkmark);
UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads");
UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false); UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false);
UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw");

View File

@ -1,19 +0,0 @@
#include "soh/resource/importer/RawJsonFactory.h"
#include "soh/resource/type/RawJson.h"
#include "spdlog/spdlog.h"
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryRawJsonV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto rawJson = std::make_shared<RawJson>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
rawJson->DataSize = file->Buffer->size();
rawJson->Data = nlohmann::json::parse(reader->ReadCString(), nullptr, true, true);
return rawJson;
}
} // namespace SOH

View File

@ -1,11 +0,0 @@
#pragma once
#include "resource/Resource.h"
#include "resource/ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryRawJsonV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
}; // namespace SOH

View File

@ -1,14 +0,0 @@
#include "RawJson.h"
namespace SOH {
RawJson::RawJson() : Resource(std::shared_ptr<LUS::ResourceInitData>()) {
}
void* RawJson::GetPointer() {
return &Data;
}
size_t RawJson::GetPointerSize() {
return DataSize * sizeof(char);
}
} // namespace SOH

View File

@ -1,20 +0,0 @@
#pragma once
#include "resource/Resource.h"
#include <nlohmann/json.hpp>
namespace SOH {
class RawJson : public LUS::Resource<void> {
public:
using Resource::Resource;
RawJson();
void* GetPointer() override;
size_t GetPointerSize() override;
nlohmann::json Data;
size_t DataSize;
};
}; // namespace SOH

View File

@ -17,6 +17,5 @@ enum class ResourceType {
SOH_AudioSequence = 0x4F534551, // OSEQ SOH_AudioSequence = 0x4F534551, // OSEQ
SOH_Background = 0x4F424749, // OBGI SOH_Background = 0x4F424749, // OBGI
SOH_SceneCommand = 0x4F52434D, // ORCM SOH_SceneCommand = 0x4F52434D, // ORCM
SOH_RawJson = 0x4A534F4E, // JSON
}; };
} // namespace SOH } // namespace SOH

View File

@ -1462,7 +1462,7 @@ s32 func_8002DF38(PlayState* play, Actor* actor, u8 csAction) {
return true; return true;
} }
s32 func_8002DF54(PlayState* play, Actor* actor, u8 csAction) { s32 Player_SetCsActionWithHaltedActors(PlayState* play, Actor* actor, u8 csAction) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
func_8002DF38(play, actor, csAction); func_8002DF38(play, actor, csAction);
@ -2084,9 +2084,8 @@ s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemE
return GiveItemEntryFromActor(actor, play, getItemEntry, 50.0f, 10.0f); return GiveItemEntryFromActor(actor, play, getItemEntry, 50.0f, 10.0f);
} }
// TODO: Rename to GiveItemIdFromActor or similar
// If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActor // If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActor
s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange) { s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
if (!(player->stateFlags1 & if (!(player->stateFlags1 &
@ -2116,7 +2115,7 @@ s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32
// TODO: Rename to GiveItemIdFromActorWithFixedRange or similar // TODO: Rename to GiveItemIdFromActorWithFixedRange or similar
// If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActorWithFixedRange // If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActorWithFixedRange
void func_8002F554(Actor* actor, PlayState* play, s32 getItemId) { void func_8002F554(Actor* actor, PlayState* play, s32 getItemId) {
func_8002F434(actor, play, getItemId, 50.0f, 10.0f); Actor_OfferGetItem(actor, play, getItemId, 50.0f, 10.0f);
} }
void func_8002F580(Actor* actor, PlayState* play) { void func_8002F580(Actor* actor, PlayState* play) {
@ -6283,58 +6282,3 @@ s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f
return true; return true;
} }
GetItemEntry GetChestGameRandoGetItem(s8 room, s16 ogDrawId, PlayState* play) {
if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) {
// RANDOTODO update this logic when we implement keysanity
// because 3drando replaces the keys not the rupees
if (ogDrawId == GID_RUPEE_GREEN ||
ogDrawId == GID_RUPEE_BLUE ||
ogDrawId == GID_RUPEE_RED)
{
switch(room) {
case 1:
if(!Flags_GetCollectible(play, 0x1B)) {
return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, GI_RUPEE_GREEN);
}
break;
case 2:
if(!Flags_GetCollectible(play, 0x1C)) {
return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, GI_RUPEE_GREEN);
}
break;
case 3:
if(!Flags_GetCollectible(play, 0x1D)) {
return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, GI_RUPEE_BLUE);
}
break;
case 4:
if(!Flags_GetCollectible(play, 0x1E)) {
return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, GI_RUPEE_BLUE);
}
break;
case 5:
if(!Flags_GetCollectible(play, 0x1F)) {
return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, GI_RUPEE_RED);
}
break;
}
}
}
if(ogDrawId == GID_HEART_PIECE) {
return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_REWARD, GI_HEART_PIECE);
}
return (GetItemEntry)GET_ITEM_NONE;
}
s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play) {
GetItemEntry randoGetItem = GetChestGameRandoGetItem(room, ogDrawId, play);
if (randoGetItem.itemId != ITEM_NONE) {
return randoGetItem.gid;
}
return ogDrawId;
}

View File

@ -6184,14 +6184,14 @@ s32 Camera_Demo5(Camera* camera) {
pad = camera->play->state.frames - sDemo5PrevAction12Frame; pad = camera->play->state.frames - sDemo5PrevAction12Frame;
if (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { if (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
// holding object over head. // holding object over head.
func_8002DF54(camera->play, camera->target, 8); Player_SetCsActionWithHaltedActors(camera->play, camera->target, 8);
} else if (ABS(pad) > 3000) { } else if (ABS(pad) > 3000) {
func_8002DF54(camera->play, camera->target, 12); Player_SetCsActionWithHaltedActors(camera->play, camera->target, 12);
} else { } else {
func_8002DF54(camera->play, camera->target, 69); Player_SetCsActionWithHaltedActors(camera->play, camera->target, 69);
} }
} else { } else {
func_8002DF54(camera->play, camera->target, 1); Player_SetCsActionWithHaltedActors(camera->play, camera->target, 1);
} }
} }
@ -6250,7 +6250,7 @@ s32 Camera_Demo6(Camera* camera) {
camera->animState++; camera->animState++;
case 1: case 1:
if (stateTimers[camera->animState] < anim->animTimer) { if (stateTimers[camera->animState] < anim->animTimer) {
func_8002DF54(camera->play, &camera->player->actor, 8); Player_SetCsActionWithHaltedActors(camera->play, &camera->player->actor, 8);
Actor_GetWorld(&focusPosRot, camFocus); Actor_GetWorld(&focusPosRot, camFocus);
anim->atTarget.x = focusPosRot.pos.x; anim->atTarget.x = focusPosRot.pos.x;
anim->atTarget.y = focusPosRot.pos.y - 20.0f; anim->atTarget.y = focusPosRot.pos.y - 20.0f;
@ -7735,7 +7735,7 @@ void Camera_Finish(Camera* camera) {
player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE;
if (player->csAction != 0) { if (player->csAction != 0) {
func_8002DF54(camera->play, &player->actor, 7); Player_SetCsActionWithHaltedActors(camera->play, &player->actor, 7);
osSyncPrintf("camera: player demo end!!\n"); osSyncPrintf("camera: player demo end!!\n");
} }

View File

@ -32,6 +32,7 @@
#include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h" #include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h"
#include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
u16 D_8011E1C0 = 0; u16 D_8011E1C0 = 0;
u16 D_8011E1C4 = 0; u16 D_8011E1C4 = 0;
@ -485,6 +486,7 @@ void func_80065134(PlayState* play, CutsceneContext* csCtx, CsCmdDayTime* cmd) {
gSaveContext.dayTime = temp1 + temp2; gSaveContext.dayTime = temp1 + temp2;
gSaveContext.skyboxTime = temp1 + temp2; gSaveContext.skyboxTime = temp1 + temp2;
LUSLOG_INFO("SET TIME %d", gSaveContext.dayTime);
} }
} }
@ -493,11 +495,16 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
s32 temp = 0; s32 temp = 0;
// Automatically skip certain cutscenes when in rando bool shouldSkipCommand = false;
// cmd->base == 8: Traveling back/forward in time cutscene
// cmd->base == 24: Dropping a fish for Jabu Jabu if (cmd->base == 8 && !GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, true, NULL)) {
// cmd->base == 33: Zelda escaping with impa cutscene shouldSkipCommand = true;
bool randoCsSkip = (IS_RANDO && (cmd->base == 8 || cmd->base == 24 || cmd->base == 33)); }
if (cmd->base == 24 && !GameInteractor_Should(GI_VB_PLAY_DROP_FISH_FOR_JABU_CS, true, NULL)) {
shouldSkipCommand = true;
}
bool debugCsSkip = (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_START) && bool debugCsSkip = (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_START) &&
(gSaveContext.fileNum != 0xFEDC) && CVarGetInteger("gDebugEnabled", 0)); (gSaveContext.fileNum != 0xFEDC) && CVarGetInteger("gDebugEnabled", 0));
@ -558,7 +565,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
} }
} }
if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (randoCsSkip || debugCsSkip))) { if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (shouldSkipCommand || debugCsSkip))) {
csCtx->state = CS_STATE_UNSKIPPABLE_EXEC; csCtx->state = CS_STATE_UNSKIPPABLE_EXEC;
Audio_SetCutsceneFlag(0); Audio_SetCutsceneFlag(0);
@ -624,7 +631,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
gSaveContext.fw.set = 0; gSaveContext.fw.set = 0;
gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0; gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0;
} }
if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) { if (GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, !Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL), NULL)) {
Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
play->nextEntranceIndex = ENTR_CUTSCENE_MAP_0; play->nextEntranceIndex = ENTR_CUTSCENE_MAP_0;
play->transitionTrigger = TRANS_TRIGGER_START; play->transitionTrigger = TRANS_TRIGGER_START;
@ -716,7 +723,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
play->transitionType = TRANS_TYPE_FADE_WHITE; play->transitionType = TRANS_TYPE_FADE_WHITE;
break; break;
case 22: case 22:
Item_Give(play, ITEM_SONG_REQUIEM); if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) {
Item_Give(play, ITEM_SONG_REQUIEM);
}
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0;
play->transitionTrigger = TRANS_TRIGGER_START; play->transitionTrigger = TRANS_TRIGGER_START;
gSaveContext.cutsceneIndex = 0xFFF0; gSaveContext.cutsceneIndex = 0xFFF0;
@ -768,7 +777,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
play->transitionTrigger = TRANS_TRIGGER_START; play->transitionTrigger = TRANS_TRIGGER_START;
play->transitionType = TRANS_TYPE_FADE_WHITE; play->transitionType = TRANS_TYPE_FADE_WHITE;
Item_Give(play, ITEM_MEDALLION_FIRE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_FIRE);
}
gSaveContext.chamberCutsceneNum = 1; gSaveContext.chamberCutsceneNum = 1;
break; break;
case 31: case 31:
@ -848,7 +859,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
play->transitionType = TRANS_TYPE_FADE_BLACK_FAST; play->transitionType = TRANS_TYPE_FADE_BLACK_FAST;
break; break;
case 47: case 47:
Item_Give(play, ITEM_SONG_NOCTURNE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) {
Item_Give(play, ITEM_SONG_NOCTURNE);
}
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW); Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW);
play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0; play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0;
play->transitionTrigger = TRANS_TRIGGER_START; play->transitionTrigger = TRANS_TRIGGER_START;
@ -1292,7 +1305,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
break; break;
} }
if (randoCsSkip) { if (shouldSkipCommand && IS_RANDO) {
Entrance_OverrideCutsceneEntrance(cmd->base); Entrance_OverrideCutsceneEntrance(cmd->base);
} }
} }
@ -1561,7 +1574,49 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText
} else if ((cmd->type == 4) && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { } else if ((cmd->type == 4) && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
Message_StartTextbox(play, cmd->textId1, NULL); Message_StartTextbox(play, cmd->textId1, NULL);
} else { } else {
GetItemEntry getItemEntry = GET_ITEM_NONE;
if (IS_RANDO) {
switch (cmd->base) {
case 0x80:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD);
break;
case 0x81:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY);
break;
case 0x82:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE);
break;
case 0x3E:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION);
break;
case 0x3C:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION);
break;
case 0x3D:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION);
break;
case 0x3F:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION);
break;
case 0x41:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION);
break;
case 0x40:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION);
break;
case 0x72:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS);
break;
}
if (getItemEntry.getItemId != GI_NONE) {
// cmd->base = getItemEntry.textId;
// GET_PLAYER(play)->getItemEntry = getItemEntry;
}
}
Message_StartTextbox(play, cmd->base, NULL); Message_StartTextbox(play, cmd->base, NULL);
if (IS_RANDO && getItemEntry.getItemId != GI_NONE) {
// GET_PLAYER(play)->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
}
} }
return; return;
} }
@ -1584,12 +1639,14 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText
if ((dialogState == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { if ((dialogState == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) {
if (play->msgCtx.choiceIndex == 0) { if (play->msgCtx.choiceIndex == 0) {
if (cmd->textId1 != 0xFFFF) { if (cmd->textId1 != 0xFFFF) {
// LUSLOG_INFO("Cutscene_Command_Textbox D: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2);
Message_ContinueTextbox(play, cmd->textId1); Message_ContinueTextbox(play, cmd->textId1);
} else { } else {
csCtx->frames++; csCtx->frames++;
} }
} else { } else {
if (cmd->textId2 != 0xFFFF) { if (cmd->textId2 != 0xFFFF) {
// LUSLOG_INFO("Cutscene_Command_Textbox E: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2);
Message_ContinueTextbox(play, cmd->textId2); Message_ContinueTextbox(play, cmd->textId2);
} else { } else {
csCtx->frames++; csCtx->frames++;
@ -1599,6 +1656,7 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText
if (dialogState == TEXT_STATE_9) { if (dialogState == TEXT_STATE_9) {
if (cmd->textId1 != 0xFFFF) { if (cmd->textId1 != 0xFFFF) {
// LUSLOG_INFO("Cutscene_Command_Textbox F: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2);
Message_ContinueTextbox(play, cmd->textId1); Message_ContinueTextbox(play, cmd->textId1);
} else { } else {
csCtx->frames++; csCtx->frames++;
@ -2113,34 +2171,23 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) {
u8 requiredAge; u8 requiredAge;
s16 i; s16 i;
if (IS_RANDO &&
// don't skip epona escape cutscenes
gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_11 &&
gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_12 &&
gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_13 &&
gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_15 &&
// don't skip nabooru iron knuckle cs
gSaveContext.entranceIndex != ENTR_SPIRIT_TEMPLE_BOSS_0) {
gSaveContext.showTitleCard = false;
return;
}
for (i = 0; i < ARRAY_COUNT(sEntranceCutsceneTable); i++) { for (i = 0; i < ARRAY_COUNT(sEntranceCutsceneTable); i++) {
entranceCutscene = &sEntranceCutsceneTable[i]; entranceCutscene = &sEntranceCutsceneTable[i];
requiredAge = entranceCutscene->ageRestriction; requiredAge = entranceCutscene->ageRestriction;
if (requiredAge == 2) { if (requiredAge == 2) {
requiredAge = gSaveContext.linkAge; requiredAge = gSaveContext.linkAge;
} }
if ((gSaveContext.entranceIndex == entranceCutscene->entrance) && if ((gSaveContext.entranceIndex == entranceCutscene->entrance) &&
(!Flags_GetEventChkInf(entranceCutscene->flag) || (entranceCutscene->flag == 0x18)) && (!Flags_GetEventChkInf(entranceCutscene->flag) || (entranceCutscene->flag == EVENTCHKINF_EPONA_OBTAINED)) &&
(gSaveContext.cutsceneIndex < 0xFFF0) && ((u8)gSaveContext.linkAge == requiredAge) && (gSaveContext.cutsceneIndex < 0xFFF0) && ((u8)gSaveContext.linkAge == requiredAge) &&
(gSaveContext.respawnFlag <= 0)) { (gSaveContext.respawnFlag <= 0)) {
Flags_SetEventChkInf(entranceCutscene->flag); Flags_SetEventChkInf(entranceCutscene->flag);
Cutscene_SetSegment(play, entranceCutscene->segAddr); if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &entranceCutscene->flag)) {
gSaveContext.cutsceneTrigger = 2; Cutscene_SetSegment(play, entranceCutscene->segAddr);
gSaveContext.showTitleCard = false; gSaveContext.cutsceneTrigger = 2;
gSaveContext.showTitleCard = false;
}
break; break;
} }
} }
@ -2148,48 +2195,48 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) {
void Cutscene_HandleConditionalTriggers(PlayState* play) { void Cutscene_HandleConditionalTriggers(PlayState* play) {
osSyncPrintf("\ngame_info.mode=[%d] restart_flag", ((void)0, gSaveContext.respawnFlag)); osSyncPrintf("\ngame_info.mode=[%d] restart_flag", ((void)0, gSaveContext.respawnFlag));
LUSLOG_INFO("Cutscene_HandleConditionalTriggers - entranceIndex: %#x cutsceneIndex: %#x", gSaveContext.entranceIndex, gSaveContext.cutsceneIndex);
if (!GameInteractor_Should(GI_VB_PLAY_TRANSITION_CS, true, NULL)) {
return;
}
if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) { if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) {
const bool bShouldTowerRandoSkip =
(IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE));
if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) { if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) {
if (!IS_RANDO) { Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT);
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0;
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0; gSaveContext.cutsceneIndex = 0xFFF0;
gSaveContext.cutsceneIndex = 0xFFF0; } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, (
} (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) &&
} else if ((gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) && LINK_IS_ADULT && (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) && LINK_IS_ADULT &&
(Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) && (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) &&
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)) { Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) &&
if (!IS_RANDO) { Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) &&
Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)
gSaveContext.cutsceneIndex = 0xFFF0; ), NULL)) {
} Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL);
gSaveContext.cutsceneIndex = 0xFFF0;
} else if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { } else if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
if (!IS_RANDO) { Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) {
Item_Give(play, ITEM_OCARINA_FAIRY); Item_Give(play, ITEM_OCARINA_FAIRY);
gSaveContext.entranceIndex = ENTR_LOST_WOODS_0;
gSaveContext.cutsceneIndex = 0xFFF0;
} }
} else if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && gSaveContext.entranceIndex = ENTR_LOST_WOODS_0;
LINK_IS_ADULT && !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && gSaveContext.cutsceneIndex = 0xFFF0;
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME)) { } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, (
if (!IS_RANDO) { CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) &&
Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_0; LINK_IS_ADULT &&
gSaveContext.cutsceneIndex = 0xFFF8; !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) &&
} (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME)
} else if ((!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) && ), NULL)) {
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS) || Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
(bShouldTowerRandoSkip && gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_0;
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR)) { gSaveContext.cutsceneIndex = 0xFFF8;
} else if (!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) &&
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS)) {
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
gSaveContext.entranceIndex = ENTR_GANON_BOSS_0; gSaveContext.entranceIndex = ENTR_GANON_BOSS_0;
// In rando, skip the cutscene for the tower falling down after the escape.
if (IS_RANDO) {
return;
}
gSaveContext.cutsceneIndex = 0xFFF0; gSaveContext.cutsceneIndex = 0xFFF0;
} }
} }

View File

@ -3,6 +3,7 @@
#include "objects/gameplay_keep/gameplay_keep.h" #include "objects/gameplay_keep/gameplay_keep.h"
#include "overlays/effects/ovl_Effect_Ss_Dead_Sound/z_eff_ss_dead_sound.h" #include "overlays/effects/ovl_Effect_Ss_Dead_Sound/z_eff_ss_dead_sound.h"
#include "textures/icon_item_static/icon_item_static.h" #include "textures/icon_item_static/icon_item_static.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS 0 #define FLAGS 0
@ -349,6 +350,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
s32 getItemId = GI_NONE; s32 getItemId = GI_NONE;
this->randoGiEntry = (GetItemEntry)GET_ITEM_NONE; this->randoGiEntry = (GetItemEntry)GET_ITEM_NONE;
this->randoCheck = (RandomizerCheck)RC_UNKNOWN_CHECK; this->randoCheck = (RandomizerCheck)RC_UNKNOWN_CHECK;
this->itemEntry = (GetItemEntry)GET_ITEM_NONE;
s16 spawnParam8000 = this->actor.params & 0x8000; s16 spawnParam8000 = this->actor.params & 0x8000;
s32 pad1; s32 pad1;
@ -358,7 +360,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
this->actor.params &= 0xFF; this->actor.params &= 0xFF;
if (Flags_GetCollectible(play, this->collectibleFlag)) { if (GameInteractor_Should(GI_VB_ITEM00_DESPAWN, Flags_GetCollectible(play, this->collectibleFlag), this)) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
@ -381,12 +383,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
this->unk_158 = 0; this->unk_158 = 0;
Actor_SetScale(&this->actor, 0.03f); Actor_SetScale(&this->actor, 0.03f);
this->scale = 0.03f; this->scale = 0.03f;
// Offset keys in randomizer slightly higher for their GID replacement yOffset = 350.0f;
if (!IS_RANDO) {
yOffset = 350.0f;
} else {
yOffset = 430.0f;
}
break; break;
case ITEM00_HEART_PIECE: case ITEM00_HEART_PIECE:
this->unk_158 = 0; this->unk_158 = 0;
@ -479,6 +476,14 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
Actor_SetScale(&this->actor, 0.03f); Actor_SetScale(&this->actor, 0.03f);
this->scale = 0.03f; this->scale = 0.03f;
break; break;
case ITEM00_SOH_GIVE_ITEM_ENTRY:
case ITEM00_SOH_GIVE_ITEM_ENTRY_GI:
case ITEM00_SOH_DUMMY:
this->unk_158 = 0;
Actor_SetScale(&this->actor, 0.03f);
this->scale = 0.03f;
yOffset = 430.0f;
break;
} }
this->unk_156 = 0; this->unk_156 = 0;
@ -507,6 +512,10 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
this->actor.velocity.y = 0.0f; this->actor.velocity.y = 0.0f;
this->actor.gravity = 0.0f; this->actor.gravity = 0.0f;
if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) {
return;
}
switch (this->actor.params) { switch (this->actor.params) {
case ITEM00_RUPEE_GREEN: case ITEM00_RUPEE_GREEN:
Item_Give(play, ITEM_RUPEE_GREEN); Item_Give(play, ITEM_RUPEE_GREEN);
@ -576,16 +585,8 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
break; break;
} }
if (!Actor_HasParent(&this->actor, play)) { if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) {
if (getItemId != GI_NONE) { func_8002F554(&this->actor, play, getItemId);
if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) {
func_8002F554(&this->actor, play, getItemId);
} else {
if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) {
Flags_SetRandomizerInf(this->randoInf);
}
}
}
} }
EnItem00_SetupAction(this, func_8001E5C8); EnItem00_SetupAction(this, func_8001E5C8);
@ -603,8 +604,7 @@ void func_8001DFC8(EnItem00* this, PlayState* play) {
(this->actor.params == ITEM00_HEART_PIECE)) { (this->actor.params == ITEM00_HEART_PIECE)) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} else { } else {
if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) && if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params < ITEM00_BOMBS_SPECIAL)) {
(this->actor.params != ITEM00_BOMBCHU)) {
if (this->unk_15A == -1) { if (this->unk_15A == -1) {
if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) == if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) ==
0) { 0) {
@ -697,8 +697,7 @@ void func_8001E304(EnItem00* this, PlayState* play) {
if (this->actor.params <= ITEM00_RUPEE_RED) { if (this->actor.params <= ITEM00_RUPEE_RED) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) && } else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params < ITEM00_BOMBS_SPECIAL)) {
(this->actor.params != ITEM00_BOMBCHU)) {
this->actor.world.rot.x -= 700; this->actor.world.rot.x -= 700;
this->actor.shape.rot.y += 400; this->actor.shape.rot.y += 400;
this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000; this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000;
@ -733,13 +732,7 @@ void func_8001E5C8(EnItem00* this, PlayState* play) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
if (this->getItemId != GI_NONE) { if (this->getItemId != GI_NONE) {
if (!Actor_HasParent(&this->actor, play)) { if (!Actor_HasParent(&this->actor, play)) {
if (!IS_RANDO) { Actor_OfferGetItem(&this->actor, play, this->getItemId, 50.0f, 80.0f);
func_8002F434(&this->actor, play, this->getItemId, 50.0f, 80.0f);
} else {
if (GiveItemEntryFromActor(&this->actor, play, this->randoGiEntry, 50.0f, 80.0f) && this->randoInf != RAND_INF_MAX) {
Flags_SetRandomizerInf(this->randoInf);
}
}
this->unk_15A++; this->unk_15A++;
} else { } else {
this->getItemId = GI_NONE; this->getItemId = GI_NONE;
@ -781,13 +774,15 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
s32 pad; s32 pad;
// Rotate some drops when 3D drops are on, otherwise reset rotation back to 0 for billboard effect // Rotate some drops when 3D drops are on, otherwise reset rotation back to 0 for billboard effect
if ((this->actor.params == ITEM00_HEART && this->unk_15A >= 0) || if (
(this->actor.params == ITEM00_HEART && this->unk_15A >= 0) ||
(this->actor.params >= ITEM00_ARROWS_SMALL && this->actor.params <= ITEM00_SMALL_KEY) || (this->actor.params >= ITEM00_ARROWS_SMALL && this->actor.params <= ITEM00_SMALL_KEY) ||
this->actor.params == ITEM00_BOMBS_A || this->actor.params == ITEM00_ARROWS_SINGLE || this->actor.params == ITEM00_BOMBS_A ||
this->actor.params == ITEM00_BOMBS_SPECIAL || this->actor.params == ITEM00_BOMBCHU) { this->actor.params == ITEM00_ARROWS_SINGLE ||
if (CVarGetInteger("gNewDrops", 0) || this->actor.params == ITEM00_BOMBS_SPECIAL ||
// Keys in randomizer need to always rotate for their GID replacement (this->actor.params >= ITEM00_BOMBCHU && this->actor.params <= ITEM00_SOH_GIVE_ITEM_ENTRY_GI)
(IS_RANDO && this->actor.params == ITEM00_SMALL_KEY)) { ) {
if (CVarGetInteger("gNewDrops", 0) || (this->actor.params >= ITEM00_SOH_DUMMY && this->actor.params <= ITEM00_SOH_GIVE_ITEM_ENTRY_GI)) {
this->actor.shape.rot.y += 960; this->actor.shape.rot.y += 960;
} else { } else {
this->actor.shape.rot.y = 0; this->actor.shape.rot.y = 0;
@ -871,6 +866,10 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
return; return;
} }
if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) {
return;
}
switch (this->actor.params) { switch (this->actor.params) {
case ITEM00_RUPEE_GREEN: case ITEM00_RUPEE_GREEN:
Item_Give(play, ITEM_RUPEE_GREEN); Item_Give(play, ITEM_RUPEE_GREEN);
@ -955,14 +954,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
params = &this->actor.params; params = &this->actor.params;
if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) { if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) {
if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) { func_8002F554(&this->actor, play, getItemId);
func_8002F554(&this->actor, play, getItemId);
} else {
getItemId = this->randoGiEntry.getItemId;
if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) {
Flags_SetRandomizerInf(this->randoInf);
}
}
} }
switch (*params) { switch (*params) {
@ -1052,7 +1044,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) {
} }
break; break;
case ITEM00_HEART_PIECE: case ITEM00_HEART_PIECE:
if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) { if (CVarGetInteger("gNewDrops", 0)) {
mtxScale = 21.0f; mtxScale = 21.0f;
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
GetItem_Draw(play, GID_HEART_PIECE); GetItem_Draw(play, GID_HEART_PIECE);
@ -1162,7 +1154,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) {
break; break;
} }
case ITEM00_SMALL_KEY: case ITEM00_SMALL_KEY:
if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) { if (CVarGetInteger("gNewDrops", 0)) {
mtxScale = 8.0f; mtxScale = 8.0f;
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
GetItem_Draw(play, GID_KEY_SMALL); GetItem_Draw(play, GID_KEY_SMALL);
@ -1368,17 +1360,7 @@ static const Vtx customDropVtx[] = {
* Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...). * Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...).
*/ */
void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) {
if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) { if (this->actor.params == ITEM00_BOMBCHU) {
if (this->randoCheck != RC_UNKNOWN_CHECK) {
this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE);
this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
}
f32 mtxScale = 10.67f;
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry);
GetItemEntry_Draw(play, this->randoGiEntry);
} else if (this->actor.params == ITEM00_BOMBCHU) {
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
Matrix_ReplaceRotation(&play->billboardMtxF); Matrix_ReplaceRotation(&play->billboardMtxF);
@ -1458,29 +1440,17 @@ void EnItem00_DrawHeartContainer(EnItem00* this, PlayState* play) {
* Draw Function used for the Piece of Heart type of En_Item00. * Draw Function used for the Piece of Heart type of En_Item00.
*/ */
void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) { void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) {
if (IS_RANDO) { s32 pad;
if (this->randoCheck != RC_UNKNOWN_CHECK) {
this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE);
this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
}
f32 mtxScale = 16.0f; OPEN_DISPS(play->state.gfxCtx);
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry);
GetItemEntry_Draw(play, this->randoGiEntry);
} else {
s32 pad;
OPEN_DISPS(play->state.gfxCtx); Gfx_SetupDL_25Xlu(play->state.gfxCtx);
func_8002ED80(&this->actor, play, 0);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_XLU_DISP++, gHeartPieceInteriorDL);
Gfx_SetupDL_25Xlu(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
func_8002ED80(&this->actor, play, 0);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_XLU_DISP++, gHeartPieceInteriorDL);
CLOSE_DISPS(play->state.gfxCtx);
}
} }
/** /**

View File

@ -395,7 +395,7 @@ void Map_InitData(PlayState* play, s16 room) {
} else if (play->sceneNum == SCENE_LAKE_HYLIA) { } else if (play->sceneNum == SCENE_LAKE_HYLIA) {
if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && if ((LINK_AGE_IN_YEARS == YEARS_ADULT) &&
((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) || ((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) ||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)))) { (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)))) {
extendedMapIndex = 0x15; extendedMapIndex = 0x15;
} }
} else if (play->sceneNum == SCENE_GERUDO_VALLEY) { } else if (play->sceneNum == SCENE_GERUDO_VALLEY) {

View File

@ -2607,8 +2607,23 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
msgCtx->lastPlayedSong = msgCtx->ocarinaStaff->state; msgCtx->lastPlayedSong = msgCtx->ocarinaStaff->state;
msgCtx->msgMode = MSGMODE_SONG_PLAYBACK_SUCCESS; msgCtx->msgMode = MSGMODE_SONG_PLAYBACK_SUCCESS;
if (!IS_RANDO) { u8 songItemId = ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state];
Item_Give(play, ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state]);
if (
(songItemId == ITEM_SONG_MINUET && GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) ||
(songItemId == ITEM_SONG_BOLERO && GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) ||
(songItemId == ITEM_SONG_SERENADE && GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) ||
(songItemId == ITEM_SONG_REQUIEM && GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) ||
(songItemId == ITEM_SONG_NOCTURNE && GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) ||
(songItemId == ITEM_SONG_PRELUDE && GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) ||
(songItemId == ITEM_SONG_LULLABY && GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) ||
(songItemId == ITEM_SONG_EPONA && GameInteractor_Should(GI_VB_GIVE_ITEM_EPONAS_SONG, true, NULL)) ||
(songItemId == ITEM_SONG_SARIA && GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) ||
(songItemId == ITEM_SONG_SUN && GameInteractor_Should(GI_VB_GIVE_ITEM_SUNS_SONG, true, NULL)) ||
(songItemId == ITEM_SONG_TIME && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_TIME, true, NULL)) ||
(songItemId == ITEM_SONG_STORMS && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_STORMS, true, NULL))
) {
Item_Give(play, songItemId);
} }
osSyncPrintf(VT_FGCOL(YELLOW)); osSyncPrintf(VT_FGCOL(YELLOW));

View File

@ -1,6 +1,7 @@
#include "global.h" #include "global.h"
#include "vt.h" #include "vt.h"
#include "overlays/actors/ovl_En_Sw/z_en_sw.h" #include "overlays/actors/ovl_En_Sw/z_en_sw.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
static s16 sDisableAttention = false; static s16 sDisableAttention = false;
static s16 sUnused = -1; static s16 sUnused = -1;
@ -267,7 +268,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
case 2290: { case 2290: {
Actor* rideActor = player->rideActor; Actor* rideActor = player->rideActor;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
if (rideActor != NULL) { if (rideActor != NULL) {
rideActor->freezeTimer = 180; rideActor->freezeTimer = 180;
} }
@ -278,7 +279,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
} break; } break;
case 5120: case 5120:
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
csInfo->keyFrames = D_80121314; csInfo->keyFrames = D_80121314;
csInfo->keyFrameCnt = 1; csInfo->keyFrameCnt = 1;
@ -288,7 +289,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
case 4510: case 4510:
D_8012133C[0].eyeTargetInit = actor->world.pos; D_8012133C[0].eyeTargetInit = actor->world.pos;
D_8012133C[0].eyeTargetInit.y = player->actor.world.pos.y + 40.0f; D_8012133C[0].eyeTargetInit.y = player->actor.world.pos.y + 40.0f;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
csInfo->keyFrames = D_8012133C; csInfo->keyFrames = D_8012133C;
csInfo->keyFrameCnt = 3; csInfo->keyFrameCnt = 3;
@ -306,7 +307,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
OnePointCutscene_AddVecSphToVec3f(&spB4, &spC0, &spD0); OnePointCutscene_AddVecSphToVec3f(&spB4, &spC0, &spD0);
Play_CameraChangeSetting(play, camIdx, CAM_SET_FREE2); Play_CameraChangeSetting(play, camIdx, CAM_SET_FREE2);
Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); Play_CameraSetAtEye(play, camIdx, &spC0, &spB4);
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
csCam->roll = 0; csCam->roll = 0;
csCam->fov = 50.0f; csCam->fov = 50.0f;
if (csCam->childCamIdx != SUBCAM_FREE) { if (csCam->childCamIdx != SUBCAM_FREE) {
@ -320,7 +321,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
if (Rand_ZeroOne() < 0.0f) { if (Rand_ZeroOne() < 0.0f) {
D_801213B4[3].eyeTargetInit.x = -D_801213B4[3].eyeTargetInit.x; D_801213B4[3].eyeTargetInit.x = -D_801213B4[3].eyeTargetInit.x;
} }
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
csInfo->keyFrames = D_801213B4; csInfo->keyFrames = D_801213B4;
csInfo->keyFrameCnt = 5; csInfo->keyFrameCnt = 5;
@ -373,10 +374,10 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); Play_CameraSetAtEye(play, camIdx, &spC0, &spB4);
csCam->roll = 6; csCam->roll = 6;
csCam->fov = 75.0f; csCam->fov = 75.0f;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
break; break;
case 3040: case 3040:
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
D_8012151C[0].timerInit = timer - 1; D_8012151C[0].timerInit = timer - 1;
csInfo->keyFrames = D_8012151C; csInfo->keyFrames = D_8012151C;
@ -400,7 +401,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrameCnt = 2; csInfo->keyFrameCnt = 2;
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
break; break;
case 3010: case 3010:
D_801215BC[0].timerInit = timer; D_801215BC[0].timerInit = timer;
@ -428,7 +429,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
case 3090: case 3090:
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
csInfo->keyFrames = D_80121814; csInfo->keyFrames = D_80121814;
csInfo->keyFrameCnt = 4; csInfo->keyFrameCnt = 4;
@ -444,14 +445,14 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); Play_CameraSetAtEye(play, camIdx, &spC0, &spB4);
csCam->roll = 0; csCam->roll = 0;
csCam->fov = 70.0f; csCam->fov = 70.0f;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
break; break;
case 3380: case 3380:
case 3065: case 3065:
csInfo->keyFrames = D_801218B4; csInfo->keyFrames = D_801218B4;
csInfo->keyFrameCnt = 2; csInfo->keyFrameCnt = 2;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
i = Quake_Add(csCam, 1); i = Quake_Add(csCam, 1);
@ -463,12 +464,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_80121904; csInfo->keyFrames = D_80121904;
csInfo->keyFrameCnt = 2; csInfo->keyFrameCnt = 2;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
case 3050: case 3050:
Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3);
func_8002DF54(play, &player->actor, 5); Player_SetCsActionWithHaltedActors(play, &player->actor, 5);
OnePointCutscene_SetCsCamPoints(csCam, D_80120304 | 0x2000, D_80120300, D_8012013C, D_8012021C); OnePointCutscene_SetCsCamPoints(csCam, D_80120304 | 0x2000, D_80120300, D_8012013C, D_8012021C);
func_80078884(NA_SE_SY_CORRECT_CHIME); func_80078884(NA_SE_SY_CORRECT_CHIME);
OnePointCutscene_Vec3sToVec3f(&mainCam->at, &D_8012013C[D_801202FC - 2].pos); OnePointCutscene_Vec3sToVec3f(&mainCam->at, &D_8012013C[D_801202FC - 2].pos);
@ -497,14 +498,14 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csCam->unk_14C |= 2; csCam->unk_14C |= 2;
csInfo->keyFrameCnt = 2; csInfo->keyFrameCnt = 2;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
case 3130: case 3130:
csInfo->keyFrames = D_80121A44; csInfo->keyFrames = D_80121A44;
csInfo->keyFrameCnt = 12; csInfo->keyFrameCnt = 12;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
csCam->unk_14C |= 2; csCam->unk_14C |= 2;
break; break;
@ -635,7 +636,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csCam->roll = 0; csCam->roll = 0;
csCam->fov = 75.0f; csCam->fov = 75.0f;
player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = spD0.yaw + 0x7FFF; player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = spD0.yaw + 0x7FFF;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
break; break;
case 3240: case 3240:
D_80121D3C[2].timerInit = timer - 5; D_80121D3C[2].timerInit = timer - 5;
@ -643,12 +644,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_80121D3C; csInfo->keyFrames = D_80121D3C;
csInfo->keyFrameCnt = 3; csInfo->keyFrameCnt = 3;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
case 6001: case 6001:
Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3);
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
Actor_GetWorld(&spA0, actor); Actor_GetWorld(&spA0, actor);
if (spA0.pos.z > -750.0f) { if (spA0.pos.z > -750.0f) {
OnePointCutscene_SetCsCamPoints(csCam, D_801208E8, D_801208E4, D_801206A0, D_80120820); OnePointCutscene_SetCsCamPoints(csCam, D_801208E8, D_801208E4, D_801206A0, D_80120820);
@ -679,12 +680,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_80121DB4; csInfo->keyFrames = D_80121DB4;
csInfo->keyFrameCnt = 9; csInfo->keyFrameCnt = 9;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
case 3310: case 3310:
Play_CameraChangeSetting(play, camIdx, CAM_SET_FIRE_STAIRCASE); Play_CameraChangeSetting(play, camIdx, CAM_SET_FIRE_STAIRCASE);
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
Play_CopyCamera(play, camIdx, MAIN_CAM); Play_CopyCamera(play, camIdx, MAIN_CAM);
i = Quake_Add(csCam, 1); i = Quake_Add(csCam, 1);
@ -717,7 +718,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_80121FBC; csInfo->keyFrames = D_80121FBC;
csInfo->keyFrameCnt = 4; csInfo->keyFrameCnt = 4;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
i = Quake_Add(csCam, 3); i = Quake_Add(csCam, 3);
@ -744,7 +745,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
D_801220D4[1].eyeTargetInit.y = 80.0f; D_801220D4[1].eyeTargetInit.y = 80.0f;
D_801220D4[1].eyeTargetInit.x = -D_801220D4[1].eyeTargetInit.x; D_801220D4[1].eyeTargetInit.x = -D_801220D4[1].eyeTargetInit.x;
} }
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
csInfo->keyFrames = D_801220D4; csInfo->keyFrames = D_801220D4;
csInfo->keyFrameCnt = 5; csInfo->keyFrameCnt = 5;
@ -762,7 +763,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_801222B4; csInfo->keyFrames = D_801222B4;
csInfo->keyFrameCnt = 5; csInfo->keyFrameCnt = 5;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
i = Quake_Add(csCam, 1); i = Quake_Add(csCam, 1);
@ -786,7 +787,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_801223CC; csInfo->keyFrames = D_801223CC;
csInfo->keyFrameCnt = 6; csInfo->keyFrameCnt = 6;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
player->actor.freezeTimer = 90; player->actor.freezeTimer = 90;
@ -800,7 +801,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_801224BC; csInfo->keyFrames = D_801224BC;
csInfo->keyFrameCnt = 7; csInfo->keyFrameCnt = 7;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
i = Quake_Add(csCam, 1); i = Quake_Add(csCam, 1);
@ -810,16 +811,11 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
break; break;
case 4100: case 4100:
csInfo->keyFrames = D_801225D4; csInfo->keyFrames = D_801225D4;
// RANDO: Waterfall opening cutscene skips to the end of the cutscene data earlier by doing this csInfo->keyFrameCnt = ARRAY_COUNT(D_801225D4);
if (!(IS_RANDO)) {
csInfo->keyFrameCnt = 5;
} else {
csInfo->keyFrameCnt = 2;
}
player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = 0x3FFC; player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = 0x3FFC;
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
break; break;
case 4110: case 4110:
csInfo->keyFrames = D_8012269C; csInfo->keyFrames = D_8012269C;
@ -829,7 +825,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
case 4120: case 4120:
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
D_80122714[1].timerInit = 80; D_80122714[1].timerInit = 80;
csInfo->keyFrames = D_80122714; csInfo->keyFrames = D_80122714;
csInfo->keyFrameCnt = 4; csInfo->keyFrameCnt = 4;
@ -847,7 +843,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_801228A4; csInfo->keyFrames = D_801228A4;
csInfo->keyFrameCnt = 5; csInfo->keyFrameCnt = 5;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
@ -855,7 +851,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_8012296C; csInfo->keyFrames = D_8012296C;
csInfo->keyFrameCnt = 4; csInfo->keyFrameCnt = 4;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
@ -863,7 +859,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_80122A0C; csInfo->keyFrames = D_80122A0C;
csInfo->keyFrameCnt = 2; csInfo->keyFrameCnt = 2;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
@ -912,11 +908,11 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
csInfo->keyFrames = D_80122C8C; csInfo->keyFrames = D_80122C8C;
csInfo->keyFrameCnt = 1; csInfo->keyFrameCnt = 1;
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
case 3260: case 3260:
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
D_80122CB4[1].timerInit = timer - 5; D_80122CB4[1].timerInit = timer - 5;
csInfo->keyFrames = D_80122CB4; csInfo->keyFrames = D_80122CB4;
@ -925,7 +921,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
func_800C0808(play, camIdx, player, CAM_SET_CS_C); func_800C0808(play, camIdx, player, CAM_SET_CS_C);
break; break;
case 3261: case 3261:
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
D_80122D04[1].timerInit = timer - 10; D_80122D04[1].timerInit = timer - 10;
csInfo->keyFrames = D_80122D04; csInfo->keyFrames = D_80122D04;
@ -1176,6 +1172,16 @@ s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s1
s16 csCamIdx; s16 csCamIdx;
Camera* csCam; Camera* csCam;
if (actor != NULL && actor->id != ACTOR_PLAYER) {
if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, actor)) {
return SUBCAM_NONE;
}
} else {
if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_CS, true, &csId)) {
return SUBCAM_NONE;
}
}
if (parentCamIdx == SUBCAM_ACTIVE) { if (parentCamIdx == SUBCAM_ACTIVE) {
parentCamIdx = play->activeCamera; parentCamIdx = play->activeCamera;
} }

View File

@ -2128,7 +2128,9 @@ u8 Item_Give(PlayState* play, u8 item) {
AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS);
} }
} }
item = ITEM_STICK; // [SOH] This results in the same behavior as the original code, but also allows us to get an accurate ReceivedItemEntry hook
INV_CONTENT(ITEM_STICK) = ITEM_STICK;
return Return_Item(item, MOD_NONE, returnItem);
} else if (item == ITEM_NUT) { } else if (item == ITEM_NUT) {
if (gSaveContext.inventory.items[slot] == ITEM_NONE) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
Inventory_ChangeUpgrade(UPG_NUTS, 1); Inventory_ChangeUpgrade(UPG_NUTS, 1);
@ -2152,7 +2154,9 @@ u8 Item_Give(PlayState* play, u8 item) {
AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS);
} }
} }
item = ITEM_NUT; // [SOH] This results in the same behavior as the original code, but also allows us to get an accurate ReceivedItemEntry hook
INV_CONTENT(ITEM_NUT) = ITEM_NUT;
return Return_Item(item, MOD_NONE, returnItem);
} else if (item == ITEM_BOMB) { } else if (item == ITEM_BOMB) {
// "Bomb Bomb Bomb Bomb Bomb Bomb Bomb" // "Bomb Bomb Bomb Bomb Bomb Bomb Bomb"
osSyncPrintf(" 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 \n"); osSyncPrintf(" 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 \n");
@ -6155,7 +6159,7 @@ void Interface_Draw(PlayState* play) {
gSaveContext.timer2State = 5; gSaveContext.timer2State = 5;
gSaveContext.cutsceneIndex = 0; gSaveContext.cutsceneIndex = 0;
Message_StartTextbox(play, 0x71B0, NULL); Message_StartTextbox(play, 0x71B0, NULL);
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
} else { } else {
D_8015FFE6 = 40; D_8015FFE6 = 40;
gSaveContext.timer2State = 6; gSaveContext.timer2State = 6;

View File

@ -226,60 +226,6 @@ void Play_Destroy(GameState* thisx) {
gPlayState = NULL; gPlayState = NULL;
} }
void GivePlayerRandoRewardSongOfTime(PlayState* play, RandomizerCheck check) {
Player* player = GET_PLAYER(play);
if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_16 && player != NULL && !Player_InBlockingCsMode(play, player) &&
!Flags_GetTreasure(play, 0x1F) && gSaveContext.nextTransitionType == TRANS_NEXT_TYPE_DEFAULT && !gSaveContext.pendingIceTrapCount) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME);
GiveItemEntryWithoutActor(play, getItemEntry);
player->pendingFlag.flagID = 0x1F;
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
}
}
void GivePlayerRandoRewardNocturne(PlayState* play, RandomizerCheck check) {
Player* player = GET_PLAYER(play);
if ((gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 ||
gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_1 ||
gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_2) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER) && player != NULL &&
!Player_InBlockingCsMode(play, player) && !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_NOCTURNE_OF_SHADOW);
GiveItemEntryWithoutActor(play, getItemEntry);
player->pendingFlag.flagID = 0xAA;
player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF;
}
}
void GivePlayerRandoRewardRequiem(PlayState* play, RandomizerCheck check) {
Player* player = GET_PLAYER(play);
if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) {
if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT) && player != NULL &&
!Player_InBlockingCsMode(play, player)) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME);
GiveItemEntryWithoutActor(play, getItemEntry);
player->pendingFlag.flagID = 0xAC;
player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF;
}
}
}
void GivePlayerRandoRewardMasterSword(PlayState* play, RandomizerCheck check) {
Player* player = GET_PLAYER(play);
if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_2 && LINK_IS_ADULT && player != NULL &&
!Player_InBlockingCsMode(play, player) && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
!Flags_GetRandomizerInf(RAND_INF_TOT_MASTER_SWORD)) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_MASTER_SWORD);
GiveItemEntryWithoutActor(play, getItemEntry);
player->pendingFlag.flagID = RAND_INF_TOT_MASTER_SWORD;
player->pendingFlag.flagType = FLAG_RANDOMIZER_INF;
}
}
u8 CheckStoneCount() { u8 CheckStoneCount() {
u8 stoneCount = 0; u8 stoneCount = 0;
@ -331,27 +277,27 @@ u8 CheckMedallionCount() {
u8 CheckDungeonCount() { u8 CheckDungeonCount() {
u8 dungeonCount = 0; u8 dungeonCount = 0;
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) { if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) {
dungeonCount++; dungeonCount++;
} }
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) { if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
dungeonCount++; dungeonCount++;
} }
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) { if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
dungeonCount++; dungeonCount++;
} }
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) { if (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) {
dungeonCount++; dungeonCount++;
} }
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { if (Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) {
dungeonCount++; dungeonCount++;
} }
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { if (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
dungeonCount++; dungeonCount++;
} }
@ -402,69 +348,6 @@ u8 CheckLACSRewardCount() {
return lacsRewardCount; return lacsRewardCount;
} }
void GivePlayerRandoRewardZeldaLightArrowsGift(PlayState* play, RandomizerCheck check) {
Player* player = GET_PLAYER(play);
u8 meetsRequirements = 0;
switch (Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY)) {
case RO_GANON_BOSS_KEY_LACS_STONES:
if ((CheckStoneCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_STONE_COUNT)) {
meetsRequirements = true;
}
break;
case RO_GANON_BOSS_KEY_LACS_MEDALLIONS:
if ((CheckMedallionCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_MEDALLION_COUNT)) {
meetsRequirements = true;
}
break;
case RO_GANON_BOSS_KEY_LACS_REWARDS:
if ((CheckMedallionCount() + CheckStoneCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_REWARD_COUNT)) {
meetsRequirements = true;
}
break;
case RO_GANON_BOSS_KEY_LACS_DUNGEONS:
if ((CheckDungeonCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_DUNGEON_COUNT)) {
meetsRequirements = true;
}
break;
case RO_GANON_BOSS_KEY_LACS_TOKENS:
if (gSaveContext.inventory.gsTokens >= Randomizer_GetSettingValue(RSK_LACS_TOKEN_COUNT)) {
meetsRequirements = true;
}
break;
default:
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) {
meetsRequirements = true;
}
break;
}
if (meetsRequirements && LINK_IS_ADULT &&
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) &&
!Flags_GetTreasure(play, 0x1E) && player != NULL && !Player_InBlockingCsMode(play, player) &&
play->transitionTrigger == TRANS_TRIGGER_OFF) {
GetItemEntry getItem = Randomizer_GetItemFromKnownCheck(check, GI_ARROW_LIGHT);
if (GiveItemEntryWithoutActor(play, getItem)) {
player->pendingFlag.flagID = 0x1E;
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
}
}
}
void GivePlayerRandoRewardSariaGift(PlayState* play, RandomizerCheck check) {
Player* player = GET_PLAYER(play);
if (gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY);
if (!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE) && player != NULL && !Player_InBlockingCsMode(play, player)) {
GiveItemEntryWithoutActor(play, getItemEntry);
player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF;
player->pendingFlag.flagID = 0xC1;
}
}
}
void Play_Init(GameState* thisx) { void Play_Init(GameState* thisx) {
PlayState* play = (PlayState*)thisx; PlayState* play = (PlayState*)thisx;
GraphicsContext* gfxCtx = play->state.gfxCtx; GraphicsContext* gfxCtx = play->state.gfxCtx;
@ -480,18 +363,6 @@ void Play_Init(GameState* thisx) {
u8 tempSetupIndex; u8 tempSetupIndex;
s32 pad[2]; s32 pad[2];
// Skip Child Stealth when option is enabled, Zelda's Letter isn't obtained and Impa's reward hasn't been received
// eventChkInf[4] & 1 = Got Zelda's Letter
// eventChkInf[5] & 0x200 = Got Impa's reward
// entranceIndex 0x7A, ENTR_CASTLE_COURTYARD_GUARDS_DAY_0, Castle Courtyard - Day from crawlspace
// entranceIndex 0x400, ENTR_CASTLE_COURTYARD_ZELDA_0, Zelda's Courtyard
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_CHILD_STEALTH) &&
!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) {
if (gSaveContext.entranceIndex == ENTR_CASTLE_COURTYARD_GUARDS_DAY_0) {
gSaveContext.entranceIndex = ENTR_CASTLE_COURTYARD_ZELDA_0;
}
}
// Properly initialize the frame counter so it doesn't use garbage data // Properly initialize the frame counter so it doesn't use garbage data
if (!firstInit) { if (!firstInit) {
play->gameplayFrames = 0; play->gameplayFrames = 0;
@ -1448,15 +1319,6 @@ skip:
Environment_Update(play, &play->envCtx, &play->lightCtx, &play->pauseCtx, &play->msgCtx, Environment_Update(play, &play->envCtx, &play->lightCtx, &play->pauseCtx, &play->msgCtx,
&play->gameOverCtx, play->state.gfxCtx); &play->gameOverCtx, play->state.gfxCtx);
if (IS_RANDO) {
GivePlayerRandoRewardSariaGift(play, RC_LW_GIFT_FROM_SARIA);
GivePlayerRandoRewardSongOfTime(play, RC_SONG_FROM_OCARINA_OF_TIME);
GivePlayerRandoRewardZeldaLightArrowsGift(play, RC_TOT_LIGHT_ARROWS_CUTSCENE);
GivePlayerRandoRewardNocturne(play, RC_SHEIK_IN_KAKARIKO);
GivePlayerRandoRewardRequiem(play, RC_SHEIK_AT_COLOSSUS);
GivePlayerRandoRewardMasterSword(play, RC_TOT_MASTER_SWORD);
}
} }
void Play_DrawOverlayElements(PlayState* play) { void Play_DrawOverlayElements(PlayState* play) {

View File

@ -6,6 +6,7 @@
#include "z_bg_bdan_switch.h" #include "z_bg_bdan_switch.h"
#include "objects/object_bdan_objects/object_bdan_objects.h" #include "objects/object_bdan_objects/object_bdan_objects.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
@ -224,10 +225,12 @@ void func_8086D4B4(BgBdanSwitch* this, PlayState* play) {
if (!Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { if (!Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) {
type = this->dyna.actor.params & 0xFF; type = this->dyna.actor.params & 0xFF;
Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F);
if (type == BLUE || type == YELLOW_TALL_2) { if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); if (type == BLUE || type == YELLOW_TALL_2) {
} else { OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); } else {
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME);
}
} }
} }
} }
@ -236,7 +239,9 @@ void func_8086D548(BgBdanSwitch* this, PlayState* play) {
if (Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { if (Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) {
Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F);
if ((this->dyna.actor.params & 0xFF) == YELLOW_TALL_2) { if ((this->dyna.actor.params & 0xFF) == YELLOW_TALL_2) {
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
}
} }
} }
} }

View File

@ -8,6 +8,7 @@
#include "scenes/dungeons/ddan/ddan_scene.h" #include "scenes/dungeons/ddan/ddan_scene.h"
#include "objects/object_bwall/object_bwall.h" #include "objects/object_bwall/object_bwall.h"
#include "objects/object_kingdodongo/object_kingdodongo.h" #include "objects/object_kingdodongo/object_kingdodongo.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
@ -300,10 +301,13 @@ void BgBreakwall_Wait(BgBreakwall* this, PlayState* play) {
if ((wallType == BWALL_DC_ENTRANCE) && (!Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) { if ((wallType == BWALL_DC_ENTRANCE) && (!Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) {
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN);
Cutscene_SetSegment(play, gDcOpeningCs); s32 flag = EVENTCHKINF_ENTERED_DODONGOS_CAVERN;
gSaveContext.cutsceneTrigger = 1; if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) {
Cutscene_SetSegment(play, gDcOpeningCs);
gSaveContext.cutsceneTrigger = 1;
Player_SetCsActionWithHaltedActors(play, NULL, 0x31);
}
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
func_8002DF54(play, NULL, 0x31);
} }
if (this->dyna.actor.params < 0) { if (this->dyna.actor.params < 0) {

View File

@ -11,6 +11,7 @@
#include "scenes/indoors/yousei_izumi_yoko/yousei_izumi_yoko_scene.h" #include "scenes/indoors/yousei_izumi_yoko/yousei_izumi_yoko_scene.h"
#include "scenes/indoors/daiyousei_izumi/daiyousei_izumi_scene.h" #include "scenes/indoors/daiyousei_izumi/daiyousei_izumi_scene.h"
#include "soh/frame_interpolation.h" #include "soh/frame_interpolation.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA)
@ -68,19 +69,6 @@ const ActorInit Bg_Dy_Yoseizo_InitVars = {
NULL, NULL,
}; };
void GivePlayerRandoRewardGreatFairy(BgDyYoseizo* this, PlayState* play) {
Player* player = GET_PLAYER(play);
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->fountainType + 1, GI_NONE);
if (this->actor.parent == GET_PLAYER(play) && !Flags_GetTreasure(play, this->fountainType + 1) &&
!Player_InBlockingCsMode(play, GET_PLAYER(play))) {
Flags_SetTreasure(play, this->fountainType + 1);
Actor_Kill(&this->actor);
} else if (!Flags_GetTreasure(play, this->fountainType + 1)) {
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 100.0f);
}
}
void BgDyYoseizo_Init(Actor* thisx, PlayState* play2) { void BgDyYoseizo_Init(Actor* thisx, PlayState* play2) {
PlayState* play = play2; PlayState* play = play2;
BgDyYoseizo* this = (BgDyYoseizo*)thisx; BgDyYoseizo* this = (BgDyYoseizo*)thisx;
@ -196,32 +184,26 @@ void BgDyYoseizo_Bob(BgDyYoseizo* this, PlayState* play) {
} }
void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) {
u8 isEligible = true;
if (Flags_GetSwitch(play, 0x38)) { if (Flags_GetSwitch(play, 0x38)) {
play->msgCtx.ocarinaMode = OCARINA_MODE_04; play->msgCtx.ocarinaMode = OCARINA_MODE_04;
if(IS_RANDO) {
gSaveContext.healthAccumulator = 0x140;
Magic_Fill(play);
if(Flags_GetTreasure(play, this->fountainType + 1)) {
Actor_Kill(&this->actor);
} else {
GivePlayerRandoRewardGreatFairy(this, play);
}
return;
}
if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) {
if (!gSaveContext.isMagicAcquired && (this->fountainType != FAIRY_UPGRADE_MAGIC)) { if (!gSaveContext.isMagicAcquired && (this->fountainType != FAIRY_UPGRADE_MAGIC)) {
Actor_Kill(&this->actor); isEligible = false;
return;
} }
} else { } else {
if (!gSaveContext.isMagicAcquired) { if (!gSaveContext.isMagicAcquired) {
Actor_Kill(&this->actor); isEligible = false;
return;
} }
} }
func_8002DF54(play, &this->actor, 1);
if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, isEligible, this)) {
Actor_Kill(&this->actor);
return;
}
Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->actionFunc = BgDyYoseizo_ChooseType; this->actionFunc = BgDyYoseizo_ChooseType;
} }
} }
@ -229,7 +211,7 @@ void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) {
void BgDyYoseizo_ChooseType(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_ChooseType(BgDyYoseizo* this, PlayState* play) {
s32 givingReward; s32 givingReward;
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
// "Mode" // "Mode"
osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ もうど ☆☆☆☆☆ %d\n" VT_RST, play->msgCtx.ocarinaMode); osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ もうど ☆☆☆☆☆ %d\n" VT_RST, play->msgCtx.ocarinaMode);
givingReward = false; givingReward = false;
@ -345,12 +327,12 @@ void BgDyYoseizo_SetupSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) {
} }
Audio_PlayActorSound2(&this->actor, NA_SE_VO_FR_LAUGH_0); Audio_PlayActorSound2(&this->actor, NA_SE_VO_FR_LAUGH_0);
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->actionFunc = BgDyYoseizo_SpinGrow_NoReward; this->actionFunc = BgDyYoseizo_SpinGrow_NoReward;
} }
void BgDyYoseizo_SpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_SpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) {
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
Math_ApproachF(&this->actor.world.pos.y, this->grownHeight, this->heightFraction, 100.0f); Math_ApproachF(&this->actor.world.pos.y, this->grownHeight, this->heightFraction, 100.0f);
Math_ApproachF(&this->scale, 0.035f, this->scaleFraction, 0.005f); Math_ApproachF(&this->scale, 0.035f, this->scaleFraction, 0.005f);
Math_ApproachF(&this->heightFraction, 0.8f, 0.1f, 0.02f); Math_ApproachF(&this->heightFraction, 0.8f, 0.1f, 0.02f);
@ -376,7 +358,7 @@ void BgDyYoseizo_SpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) {
void BgDyYoseizo_CompleteSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_CompleteSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) {
f32 curFrame = this->skelAnime.curFrame; f32 curFrame = this->skelAnime.curFrame;
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
if ((this->frameCount * 1273.0f) <= this->bobTimer) { if ((this->frameCount * 1273.0f) <= this->bobTimer) {
this->bobTimer = 0.0f; this->bobTimer = 0.0f;
@ -390,7 +372,7 @@ void BgDyYoseizo_CompleteSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) {
} }
void BgDyYoseizo_SetupGreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_SetupGreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) {
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) {
this->frameCount = Animation_GetLastFrame(&gGreatFairySittingAnim); this->frameCount = Animation_GetLastFrame(&gGreatFairySittingAnim);
@ -410,7 +392,7 @@ void BgDyYoseizo_SetupGreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) {
} }
void BgDyYoseizo_GreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_GreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) {
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->bobTimer = this->skelAnime.curFrame * 1273.0f; this->bobTimer = this->skelAnime.curFrame * 1273.0f;
if ((this->frameCount * 1273.0f) <= this->bobTimer) { if ((this->frameCount * 1273.0f) <= this->bobTimer) {
@ -578,7 +560,7 @@ void BgDyYoseizo_Vanish(BgDyYoseizo* this, PlayState* play) {
Actor* findOcarinaSpot; Actor* findOcarinaSpot;
if (this->vanishTimer == 0) { if (this->vanishTimer == 0) {
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
play->envCtx.unk_BF = 0; play->envCtx.unk_BF = 0;
findOcarinaSpot = play->actorCtx.actorLists[ACTORCAT_PROP].head; findOcarinaSpot = play->actorCtx.actorLists[ACTORCAT_PROP].head;
@ -600,7 +582,7 @@ void BgDyYoseizo_SetupSpinGrow_Reward(BgDyYoseizo* this, PlayState* play) {
if (play->csCtx.state != CS_STATE_IDLE) { if (play->csCtx.state != CS_STATE_IDLE) {
if ((play->csCtx.npcActions[0] != NULL) && (play->csCtx.npcActions[0]->action == 2)) { if ((play->csCtx.npcActions[0] != NULL) && (play->csCtx.npcActions[0]->action == 2)) {
this->actor.draw = BgDyYoseizo_Draw; this->actor.draw = BgDyYoseizo_Draw;
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->finishedSpinGrow = false; this->finishedSpinGrow = false;
if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) {

View File

@ -7,6 +7,7 @@
#include "z_bg_gjyo_bridge.h" #include "z_bg_gjyo_bridge.h"
#include "objects/object_gjyo_objects/object_gjyo_objects.h" #include "objects/object_gjyo_objects/object_gjyo_objects.h"
#include "scenes/dungeons/ganon_tou/ganon_tou_scene.h" #include "scenes/dungeons/ganon_tou/ganon_tou_scene.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS 0 #define FLAGS 0
@ -50,8 +51,7 @@ void BgGjyoBridge_Init(Actor* thisx, PlayState* play) {
this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, thisx, colHeader); this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, thisx, colHeader);
int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); if (Flags_GetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT)) {
if (Flags_GetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT) || (IS_RANDO && bridge == RO_BRIDGE_ALWAYS_OPEN)) {
this->actionFunc = func_808787A4; this->actionFunc = func_808787A4;
} else { } else {
this->dyna.actor.draw = NULL; this->dyna.actor.draw = NULL;
@ -70,8 +70,10 @@ void func_808787A4(BgGjyoBridge* this, PlayState* play) {
} }
void LaunchBridgeCutscene(BgGjyoBridge* this, PlayState* play) { void LaunchBridgeCutscene(BgGjyoBridge* this, PlayState* play) {
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); if (GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL)) {
gSaveContext.cutsceneTrigger = 1; play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs);
gSaveContext.cutsceneTrigger = 1;
}
this->actionFunc = BgGjyoBridge_SpawnBridge; this->actionFunc = BgGjyoBridge_SpawnBridge;
} }
@ -84,70 +86,24 @@ u8 CheckPlayerPosition(Player* player, PlayState* play) {
void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, PlayState* play) { void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, PlayState* play) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
if (!IS_RANDO) { u8 vanillaBridgeCondition =
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) &&
(INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && CheckPlayerPosition(player, play)) { CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
LaunchBridgeCutscene(this, play); (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) &&
} CheckPlayerPosition(player, play);
} else {
int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE);
int bridgeStoneCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_STONE_COUNT);
int bridgeMedallionCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT);
int bridgeRewardCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_REWARD_COUNT);
int bridgeDungeonCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT);
int bridgeTokenCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_TOKEN_COUNT);
switch (bridge) { if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, vanillaBridgeCondition, NULL)) {
case RO_BRIDGE_VANILLA: LaunchBridgeCutscene(this, play);
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
(INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT)) {
this->actionFunc = BgGjyoBridge_SpawnBridge;
func_800F595C(NA_BGM_BRIDGE_TO_GANONS);
}
break;
case RO_BRIDGE_STONES:
if ((CheckStoneCount() + CheckBridgeRewardCount()) >= bridgeStoneCount) {
this->actionFunc = BgGjyoBridge_SpawnBridge;
func_800F595C(NA_BGM_BRIDGE_TO_GANONS);
}
break;
case RO_BRIDGE_MEDALLIONS:
if ((CheckMedallionCount() + CheckBridgeRewardCount()) >= bridgeMedallionCount) {
this->actionFunc = BgGjyoBridge_SpawnBridge;
func_800F595C(NA_BGM_BRIDGE_TO_GANONS);
}
break;
case RO_BRIDGE_DUNGEON_REWARDS:
if ((CheckMedallionCount() + CheckStoneCount() + CheckBridgeRewardCount()) >= bridgeRewardCount) {
this->actionFunc = BgGjyoBridge_SpawnBridge;
func_800F595C(NA_BGM_BRIDGE_TO_GANONS);
}
break;
case RO_BRIDGE_DUNGEONS:
if ((CheckDungeonCount() + CheckBridgeRewardCount()) >= bridgeDungeonCount) {
this->actionFunc = BgGjyoBridge_SpawnBridge;
func_800F595C(NA_BGM_BRIDGE_TO_GANONS);
}
break;
case RO_BRIDGE_TOKENS:
if (gSaveContext.inventory.gsTokens >= bridgeTokenCount) {
this->actionFunc = BgGjyoBridge_SpawnBridge;
func_800F595C(NA_BGM_BRIDGE_TO_GANONS);
}
break;
case RO_BRIDGE_GREG:
if (Flags_GetRandomizerInf(RAND_INF_GREG_FOUND)) {
this->actionFunc = BgGjyoBridge_SpawnBridge;
func_800F595C(NA_BGM_BRIDGE_TO_GANONS);
}
break;
}
} }
} }
void BgGjyoBridge_SpawnBridge(BgGjyoBridge* this, PlayState* play) { void BgGjyoBridge_SpawnBridge(BgGjyoBridge* this, PlayState* play) {
if (IS_RANDO || (play->csCtx.state != CS_STATE_IDLE) && (play->csCtx.npcActions[2] != NULL) && u8 vanillaBridgeCondition =
(play->csCtx.npcActions[2]->action == 2)) { (play->csCtx.state != CS_STATE_IDLE) &&
(play->csCtx.npcActions[2] != NULL) &&
(play->csCtx.npcActions[2]->action == 2);
if (!GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL) || vanillaBridgeCondition) {
this->dyna.actor.draw = BgGjyoBridge_Draw; this->dyna.actor.draw = BgGjyoBridge_Draw;
func_8003EC50(play, &play->colCtx.dyna, this->dyna.bgId); func_8003EC50(play, &play->colCtx.dyna, this->dyna.bgId);
Flags_SetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT); Flags_SetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT);

View File

@ -241,7 +241,7 @@ void BgGndIceblock_Idle(BgGndIceblock* this, PlayState* play) {
if (this->dyna.unk_150 > 0.0f) { if (this->dyna.unk_150 > 0.0f) {
BgGndIceblock_SetNextPosition(this); BgGndIceblock_SetNextPosition(this);
if (Actor_WorldDistXZToPoint(&this->dyna.actor, &this->targetPos) > 1.0f) { if (Actor_WorldDistXZToPoint(&this->dyna.actor, &this->targetPos) > 1.0f) {
func_8002DF54(play, &this->dyna.actor, 8); Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8);
this->actionFunc = BgGndIceblock_Slide; this->actionFunc = BgGndIceblock_Slide;
} }
} }
@ -282,7 +282,7 @@ void BgGndIceblock_Fall(BgGndIceblock* this, PlayState* play) {
thisx->world.pos.y = thisx->home.pos.y - 100.0f; thisx->world.pos.y = thisx->home.pos.y - 100.0f;
thisx->world.pos.z = thisx->home.pos.z; thisx->world.pos.z = thisx->home.pos.z;
if (Player_InCsMode(play)) { if (Player_InCsMode(play)) {
func_8002DF54(play, thisx, 7); Player_SetCsActionWithHaltedActors(play, thisx, 7);
} }
this->actionFunc = BgGndIceblock_Reset; this->actionFunc = BgGndIceblock_Reset;
} }
@ -295,7 +295,7 @@ void BgGndIceblock_Hole(BgGndIceblock* this, PlayState* play) {
if (Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y - 100.0f, thisx->velocity.y)) { if (Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y - 100.0f, thisx->velocity.y)) {
thisx->velocity.y = 0.0f; thisx->velocity.y = 0.0f;
if (Player_InCsMode(play)) { if (Player_InCsMode(play)) {
func_8002DF54(play, thisx, 7); Player_SetCsActionWithHaltedActors(play, thisx, 7);
} }
this->actionFunc = BgGndIceblock_Idle; this->actionFunc = BgGndIceblock_Idle;
} }
@ -319,7 +319,7 @@ void BgGndIceblock_Slide(BgGndIceblock* this, PlayState* play) {
switch (BgGndIceblock_NextAction(this)) { switch (BgGndIceblock_NextAction(this)) {
case GNDICE_IDLE: case GNDICE_IDLE:
this->actionFunc = BgGndIceblock_Idle; this->actionFunc = BgGndIceblock_Idle;
func_8002DF54(play, thisx, 7); Player_SetCsActionWithHaltedActors(play, thisx, 7);
break; break;
case GNDICE_FALL: case GNDICE_FALL:
this->actionFunc = BgGndIceblock_Fall; this->actionFunc = BgGndIceblock_Fall;

View File

@ -370,7 +370,7 @@ void BgHeavyBlock_LiftedUp(BgHeavyBlock* this, PlayState* play) {
this->timer++; this->timer++;
if (!CVarGetInteger("gFasterHeavyBlockLift", 0)) { if (!CVarGetInteger("gFasterHeavyBlockLift", 0)) {
func_8002DF54(play, &player->actor, 8); Player_SetCsActionWithHaltedActors(play, &player->actor, 8);
} }
// if parent is NULL, link threw it // if parent is NULL, link threw it

View File

@ -138,7 +138,7 @@ void BgHidanDalm_Wait(BgHidanDalm* this, PlayState* play) {
this->dyna.actor.world.pos.x += 32.5f * Math_SinS(this->dyna.actor.world.rot.y); this->dyna.actor.world.pos.x += 32.5f * Math_SinS(this->dyna.actor.world.rot.y);
this->dyna.actor.world.pos.z += 32.5f * Math_CosS(this->dyna.actor.world.rot.y); this->dyna.actor.world.pos.z += 32.5f * Math_CosS(this->dyna.actor.world.rot.y);
func_8002DF54(play, &this->dyna.actor, 8); Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8);
this->dyna.actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; this->dyna.actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED;
this->actionFunc = BgHidanDalm_Shrink; this->actionFunc = BgHidanDalm_Shrink;
this->dyna.actor.bgCheckFlags &= ~2; this->dyna.actor.bgCheckFlags &= ~2;
@ -159,7 +159,7 @@ void BgHidanDalm_Shrink(BgHidanDalm* this, PlayState* play) {
Vec3f pos; Vec3f pos;
if (Math_StepToF(&this->dyna.actor.scale.x, 0.0f, 0.004f)) { if (Math_StepToF(&this->dyna.actor.scale.x, 0.0f, 0.004f)) {
func_8002DF54(play, &this->dyna.actor, 7); Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 7);
Actor_Kill(&this->dyna.actor); Actor_Kill(&this->dyna.actor);
} }

View File

@ -14,4 +14,7 @@ typedef struct BgHidanKousi {
/* 0x0168 */ s16 unk_168; /* 0x0168 */ s16 unk_168;
} BgHidanKousi; // size = 0x016C } BgHidanKousi; // size = 0x016C
void BgHidanKousi_SetupAction(BgHidanKousi* bgHidanKousi, BgHidanKousiActionFunc actionFunc);
void func_80889C18(BgHidanKousi* bgHidanKousi, PlayState* play);
#endif #endif

View File

@ -126,7 +126,7 @@ void BgIceObjects_CheckPits(BgIceObjects* this, PlayState* play) {
thisx->world.pos.y = thisx->home.pos.y - 60.0f; thisx->world.pos.y = thisx->home.pos.y - 60.0f;
thisx->world.pos.z = thisx->home.pos.z; thisx->world.pos.z = thisx->home.pos.z;
if (thisx->params != 0) { if (thisx->params != 0) {
func_8002DF54(play, thisx, 7); Player_SetCsActionWithHaltedActors(play, thisx, 7);
} }
this->actionFunc = BgIceObjects_Reset; this->actionFunc = BgIceObjects_Reset;
} }
@ -143,7 +143,7 @@ void BgIceObjects_Idle(BgIceObjects* this, PlayState* play) {
BgIceObjects_SetNextTarget(this, play); BgIceObjects_SetNextTarget(this, play);
if (Actor_WorldDistXZToPoint(thisx, &this->targetPos) > 1.0f) { if (Actor_WorldDistXZToPoint(thisx, &this->targetPos) > 1.0f) {
thisx->flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; thisx->flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED;
func_8002DF54(play, thisx, 8); Player_SetCsActionWithHaltedActors(play, thisx, 8);
thisx->params = 1; thisx->params = 1;
this->actionFunc = BgIceObjects_Slide; this->actionFunc = BgIceObjects_Slide;
} }
@ -173,7 +173,7 @@ void BgIceObjects_Slide(BgIceObjects* this, PlayState* play) {
thisx->flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; thisx->flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED;
} }
thisx->params = 0; thisx->params = 0;
func_8002DF54(play, thisx, 7); Player_SetCsActionWithHaltedActors(play, thisx, 7);
Audio_PlayActorSound2(thisx, NA_SE_EV_BLOCK_BOUND); Audio_PlayActorSound2(thisx, NA_SE_EV_BLOCK_BOUND);
if ((fabsf(thisx->world.pos.x + 1387.0f) < 1.0f) && (fabsf(thisx->world.pos.z + 260.0f) < 1.0f)) { if ((fabsf(thisx->world.pos.x + 1387.0f) < 1.0f) && (fabsf(thisx->world.pos.z + 260.0f) < 1.0f)) {
this->actionFunc = BgIceObjects_Stuck; this->actionFunc = BgIceObjects_Stuck;

View File

@ -6,6 +6,7 @@
#include "z_bg_mori_bigst.h" #include "z_bg_mori_bigst.h"
#include "objects/object_mori_objects/object_mori_objects.h" #include "objects/object_mori_objects/object_mori_objects.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
@ -149,7 +150,9 @@ void BgMoriBigst_StalfosFight(BgMoriBigst* this, PlayState* play) {
if ((this->dyna.actor.home.rot.z == 0) && if ((this->dyna.actor.home.rot.z == 0) &&
((this->dyna.actor.home.pos.y - 5.0f) <= GET_PLAYER(play)->actor.world.pos.y)) { ((this->dyna.actor.home.pos.y - 5.0f) <= GET_PLAYER(play)->actor.world.pos.y)) {
BgMoriBigst_SetupFall(this, play); BgMoriBigst_SetupFall(this, play);
OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM); if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM);
}
} }
} }
@ -163,8 +166,10 @@ void BgMoriBigst_Fall(BgMoriBigst* this, PlayState* play) {
this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y; this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y;
BgMoriBigst_SetupLanding(this, play); BgMoriBigst_SetupLanding(this, play);
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND);
OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM); if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
func_8002DF38(play, NULL, 0x3C); OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM);
func_8002DF38(play, NULL, 0x3C);
}
} }
} }

View File

@ -96,7 +96,7 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, PlayState* play) {
this->timer++; this->timer++;
if ((this->timer > (28 - CVarGetInteger("gFasterBlockPush", 0) * 4)) && !Player_InCsMode(play)) { if ((this->timer > (28 - CVarGetInteger("gFasterBlockPush", 0) * 4)) && !Player_InCsMode(play)) {
BgMoriKaitenkabe_SetupRotate(this); BgMoriKaitenkabe_SetupRotate(this);
func_8002DF54(play, &this->dyna.actor, 8); Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8);
Math_Vec3f_Copy(&this->lockedPlayerPos, &player->actor.world.pos); Math_Vec3f_Copy(&this->lockedPlayerPos, &player->actor.world.pos);
push.x = Math_SinS(this->dyna.unk_158); push.x = Math_SinS(this->dyna.unk_158);
push.y = 0.0f; push.y = 0.0f;
@ -130,7 +130,7 @@ void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, PlayState* play) {
Math_StepToF(&this->rotSpeed, 0.6f, 0.02f); Math_StepToF(&this->rotSpeed, 0.6f, 0.02f);
if (Math_StepToF(&this->rotYdeg, this->rotDirection * 45.0f, this->rotSpeed)) { if (Math_StepToF(&this->rotYdeg, this->rotDirection * 45.0f, this->rotSpeed)) {
BgMoriKaitenkabe_SetupWait(this); BgMoriKaitenkabe_SetupWait(this);
func_8002DF54(play, thisx, 7); Player_SetCsActionWithHaltedActors(play, thisx, 7);
if (this->rotDirection > 0.0f) { if (this->rotDirection > 0.0f) {
thisx->home.rot.y += 0x2000; thisx->home.rot.y += 0x2000;
} else { } else {

View File

@ -321,7 +321,7 @@ void BgPoEvent_BlockFall(BgPoEvent* this, PlayState* play) {
if (firstFall == 0) { if (firstFall == 0) {
firstFall = 1; firstFall = 1;
} else { } else {
func_8002DF54(play, &GET_PLAYER(play)->actor, 7); Player_SetCsActionWithHaltedActors(play, &GET_PLAYER(play)->actor, 7);
} }
} }
this->direction = 0; this->direction = 0;
@ -358,7 +358,7 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, PlayState* play) {
if (sBgPoEventPuzzleState == 0x10) { if (sBgPoEventPuzzleState == 0x10) {
sBgPoEventPuzzleState = 0x40; sBgPoEventPuzzleState = 0x40;
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BLOCK_RISING); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BLOCK_RISING);
func_8002DF54(play, &player->actor, 8); Player_SetCsActionWithHaltedActors(play, &player->actor, 8);
} }
} else if (this->dyna.unk_150 != 0.0f) { } else if (this->dyna.unk_150 != 0.0f) {
if (this->direction == 0) { if (this->direction == 0) {

View File

@ -223,7 +223,7 @@ void BgSpot00Hanebasi_Update(Actor* thisx, PlayState* play) {
Flags_SetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE); Flags_SetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE);
Flags_SetEventChkInf(EVENTCHKINF_DRAWBRIDGE_OPENED_AFTER_ZELDA_FLED); Flags_SetEventChkInf(EVENTCHKINF_DRAWBRIDGE_OPENED_AFTER_ZELDA_FLED);
this->actionFunc = BgSpot00Hanebasi_DoNothing; this->actionFunc = BgSpot00Hanebasi_DoNothing;
func_8002DF54(play, &player->actor, 8); Player_SetCsActionWithHaltedActors(play, &player->actor, 8);
play->nextEntranceIndex = ENTR_HYRULE_FIELD_0; play->nextEntranceIndex = ENTR_HYRULE_FIELD_0;
gSaveContext.nextCutsceneIndex = 0xFFF1; gSaveContext.nextCutsceneIndex = 0xFFF1;
play->transitionTrigger = TRANS_TRIGGER_START; play->transitionTrigger = TRANS_TRIGGER_START;

View File

@ -6,6 +6,7 @@
#include "z_bg_spot02_objects.h" #include "z_bg_spot02_objects.h"
#include "objects/object_spot02_objects/object_spot02_objects.h" #include "objects/object_spot02_objects/object_spot02_objects.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
@ -129,20 +130,7 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) {
static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
Vec3f pos; Vec3f pos;
// We want to do most of the same things in rando, but we're not in a cutscene and the flag for if (GameInteractor_Should(GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, play->csCtx.state != 0 && play->csCtx.npcActions[3] != NULL && play->csCtx.npcActions[3]->action == 2, this)) {
// destroying the royal tombstone is already set.
if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) {
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION);
this->timer = 25;
pos.x = (Math_SinS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.x;
pos.y = this->dyna.actor.world.pos.y + 30.0f;
pos.z = (Math_CosS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.z;
EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30);
this->actionFunc = func_808ACA08;
}
if (play->csCtx.state != 0) {
if (play->csCtx.npcActions[3] != NULL && play->csCtx.npcActions[3]->action == 2) {
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION);
Flags_SetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); Flags_SetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB);
this->timer = 25; this->timer = 25;
@ -151,7 +139,6 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) {
pos.z = (Math_CosS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.z; pos.z = (Math_CosS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.z;
EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30); EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30);
this->actionFunc = func_808ACA08; this->actionFunc = func_808ACA08;
}
} }
} }
@ -174,7 +161,7 @@ void func_808ACA08(BgSpot02Objects* this, PlayState* play) {
// This shouldn't execute in rando even without the check since we never // This shouldn't execute in rando even without the check since we never
// enter the cutscene context. // enter the cutscene context.
if (play->csCtx.frames == 402 && !(IS_RANDO)) { if (play->csCtx.frames == 402) {
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
Player_PlaySfx(&player->actor, NA_SE_VO_LI_DEMO_DAMAGE_KID); Player_PlaySfx(&player->actor, NA_SE_VO_LI_DEMO_DAMAGE_KID);
} else { } else {
@ -217,13 +204,6 @@ void BgSpot02Objects_Draw(Actor* thisx, PlayState* play) {
} }
void func_808ACC34(BgSpot02Objects* this, PlayState* play) { void func_808ACC34(BgSpot02Objects* this, PlayState* play) {
// This is the actionFunc that the game settles on when you load the Graveyard
// When we're in rando and the flag for the gravestone being destroyed gets set,
// set the actionFunc to the function where the gravestone explodes.
if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) {
this->actionFunc = func_808AC908;
}
if (play->csCtx.state != 0 && play->csCtx.npcActions[0] != NULL && if (play->csCtx.state != 0 && play->csCtx.npcActions[0] != NULL &&
play->csCtx.npcActions[0]->action == 2) { play->csCtx.npcActions[0]->action == 2) {
this->unk_16A++; this->unk_16A++;

View File

@ -19,4 +19,7 @@ typedef struct BgSpot02Objects {
/* 0x0172 */ u16 unk_172; /* 0x0172 */ u16 unk_172;
} BgSpot02Objects; // size = 0x0174 } BgSpot02Objects; // size = 0x0174
void func_808ACC34(BgSpot02Objects* bgSpot02Objects, PlayState* play);
void func_808AC908(BgSpot02Objects* bgSpot02Objects, PlayState* play);
#endif #endif

View File

@ -217,7 +217,7 @@ void BgSpot06Objects_Destroy(Actor* thisx, PlayState* play) {
// Due to Ships resource caching, the water box collisions for the river have to be manually reset // Due to Ships resource caching, the water box collisions for the river have to be manually reset
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z; play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z;
if (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
// For randomizer when leaving lake hylia while the water level is lowered, // For randomizer when leaving lake hylia while the water level is lowered,
// reset the "raise lake hylia water" flag back to on if the water temple is cleared // reset the "raise lake hylia water" flag back to on if the water temple is cleared
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
@ -461,7 +461,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) {
Object_Spawn(&play->objectCtx, OBJECT_GAMEPLAY_DANGEON_KEEP); Object_Spawn(&play->objectCtx, OBJECT_GAMEPLAY_DANGEON_KEEP);
s16 switchParams; s16 switchParams;
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { if (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
// Toggle-able floor switch, // Toggle-able floor switch,
// linked to temp_switch 0x1E (room temporary, cleared when room unloads) // linked to temp_switch 0x1E (room temporary, cleared when room unloads)
switchParams = 0x3E10; switchParams = 0x3E10;
@ -477,7 +477,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) {
0x0000 | (TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN & 0xFF), false); 0x0000 | (TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN & 0xFF), false);
// Spawn a Navi check spot when Water Temple isn't cleared // Spawn a Navi check spot when Water Temple isn't cleared
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, -896.0f, -1243.0f, 6953.0f, 0, 0, 0, Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, -896.0f, -1243.0f, 6953.0f, 0, 0, 0,
0x3D00 | (TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI & 0xFF), false); 0x3D00 | (TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI & 0xFF), false);
} }
@ -485,7 +485,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) {
actionCounter++; actionCounter++;
return; return;
} else if (actionCounter == 1) { } else if (actionCounter == 1) {
if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
// Remove the link to ice block so melting it doesn't set the flag // Remove the link to ice block so melting it doesn't set the flag
lakeControlFloorSwitch->params = 0x3E01; lakeControlFloorSwitch->params = 0x3E01;
} }

View File

@ -6,6 +6,7 @@
#include "z_bg_spot12_saku.h" #include "z_bg_spot12_saku.h"
#include "objects/object_spot12_obj/object_spot12_obj.h" #include "objects/object_spot12_obj/object_spot12_obj.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS 0 #define FLAGS 0
@ -58,15 +59,9 @@ void func_808B3420(BgSpot12Saku* this, PlayState* play, CollisionHeader* collisi
void BgSpot12Saku_Init(Actor* thisx, PlayState* play) { void BgSpot12Saku_Init(Actor* thisx, PlayState* play) {
BgSpot12Saku* this = (BgSpot12Saku*)thisx; BgSpot12Saku* this = (BgSpot12Saku*)thisx;
// If ER is on, force the gate to always use its permanent flag
// (which it only uses in Child Gerudo Fortress in the vanilla game)
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) {
thisx->params = 0x0002;
}
func_808B3420(this, play, &gGerudoFortressGTGShutterCol, DPM_UNK); func_808B3420(this, play, &gGerudoFortressGTGShutterCol, DPM_UNK);
Actor_ProcessInitChain(&this->dyna.actor, sInitChain); Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { if (GameInteractor_Should(GI_VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) {
func_808B3714(this); func_808B3714(this);
} else { } else {
func_808B3550(this); func_808B3550(this);
@ -87,7 +82,7 @@ void func_808B3550(BgSpot12Saku* this) {
} }
void func_808B357C(BgSpot12Saku* this, PlayState* play) { void func_808B357C(BgSpot12Saku* this, PlayState* play) {
if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { if (GameInteractor_Should(GI_VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) {
func_808B35E4(this); func_808B35E4(this);
this->timer = 20; this->timer = 20;
OnePointCutscene_Init(play, 4170, -99, &this->dyna.actor, MAIN_CAM); OnePointCutscene_Init(play, 4170, -99, &this->dyna.actor, MAIN_CAM);
@ -131,12 +126,6 @@ void func_808B37AC(BgSpot12Saku* this, PlayState* play) {
void BgSpot12Saku_Update(Actor* thisx, PlayState* play) { void BgSpot12Saku_Update(Actor* thisx, PlayState* play) {
BgSpot12Saku* this = (BgSpot12Saku*)thisx; BgSpot12Saku* this = (BgSpot12Saku*)thisx;
// If ER is on, when the guard opens the GtG gate its permanent flag will be set.
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF &&
Flags_GetSwitch(play, 0x3A)) {
Flags_SetSwitch(play, 0x2);
}
if (this->timer > 0) { if (this->timer > 0) {
this->timer--; this->timer--;
} }

View File

@ -6,6 +6,7 @@
#include "z_bg_toki_swd.h" #include "z_bg_toki_swd.h"
#include "objects/object_toki_objects/object_toki_objects.h" #include "objects/object_toki_objects/object_toki_objects.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
@ -115,14 +116,17 @@ void func_808BAF40(BgTokiSwd* this, PlayState* play) {
if (((Flags_GetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER)) == 0) && (gSaveContext.sceneSetupIndex < 4) && if (((Flags_GetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER)) == 0) && (gSaveContext.sceneSetupIndex < 4) &&
Actor_IsFacingAndNearPlayer(&this->actor, 800.0f, 0x7530) && !Play_InCsMode(play)) { Actor_IsFacingAndNearPlayer(&this->actor, 800.0f, 0x7530) && !Play_InCsMode(play)) {
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
play->csCtx.segment = D_808BBD90; s32 flag = EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER;
gSaveContext.cutsceneTrigger = 1; if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) {
play->csCtx.segment = D_808BBD90;
gSaveContext.cutsceneTrigger = 1;
}
} }
if (!LINK_IS_ADULT || (Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && !IS_RANDO) || IS_RANDO) { if (!LINK_IS_ADULT || (Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && !IS_RANDO) || IS_RANDO) {
if (Actor_HasParent(&this->actor, play)) { if (Actor_HasParent(&this->actor, play)) {
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { if (GameInteractor_Should(GI_VB_GIVE_ITEM_MASTER_SWORD, true, NULL)) {
Item_Give(play, ITEM_SWORD_MASTER); Item_Give(play, ITEM_SWORD_MASTER);
} }
play->csCtx.segment = D_808BB2F0; play->csCtx.segment = D_808BB2F0;

View File

@ -7,6 +7,7 @@
#include "z_bg_treemouth.h" #include "z_bg_treemouth.h"
#include "objects/object_spot04_objects/object_spot04_objects.h" #include "objects/object_spot04_objects/object_spot04_objects.h"
#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
@ -73,11 +74,7 @@ void BgTreemouth_Init(Actor* thisx, PlayState* play) {
if ((gSaveContext.sceneSetupIndex < 4) && !LINK_IS_ADULT) { if ((gSaveContext.sceneSetupIndex < 4) && !LINK_IS_ADULT) {
BgTreemouth_SetupAction(this, func_808BC8B8); BgTreemouth_SetupAction(this, func_808BC8B8);
// If dungeon entrance randomizer is on, keep the tree mouth open } else if (LINK_IS_ADULT || (gSaveContext.sceneSetupIndex == 7)) {
// when Link is adult and sword & shield have been shown to Mido
} else if ((LINK_IS_ADULT && (!IS_RANDO ||
Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) == RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) ||
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) || (gSaveContext.sceneSetupIndex == 7)) {
this->unk_168 = 0.0f; this->unk_168 = 0.0f;
BgTreemouth_SetupAction(this, BgTreemouth_DoNothing); BgTreemouth_SetupAction(this, BgTreemouth_DoNothing);
} else { } else {
@ -157,9 +154,11 @@ void func_808BC8B8(BgTreemouth* this, PlayState* play) {
} }
} else if (Actor_IsFacingAndNearPlayer(&this->dyna.actor, 1658.0f, 0x4E20)) { } else if (Actor_IsFacingAndNearPlayer(&this->dyna.actor, 1658.0f, 0x4E20)) {
Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE);
play->csCtx.segment = D_808BCE20; if (GameInteractor_Should(GI_VB_PLAY_DEKU_TREE_INTRO_CS, true, this)) {
gSaveContext.cutsceneTrigger = 1; play->csCtx.segment = D_808BCE20;
BgTreemouth_SetupAction(this, func_808BC9EC); gSaveContext.cutsceneTrigger = 1;
BgTreemouth_SetupAction(this, func_808BC9EC);
}
} }
} }
} else { } else {

View File

@ -15,4 +15,7 @@ typedef struct BgTreemouth {
/* 0x016C */ BgTreemouthActionFunc actionFunc; /* 0x016C */ BgTreemouthActionFunc actionFunc;
} BgTreemouth; // size = 0x0170 } BgTreemouth; // size = 0x0170
void BgTreemouth_SetupAction(BgTreemouth* actor, BgTreemouthActionFunc actionFunc);
void func_808BC6F8(BgTreemouth* actor, PlayState* play);
#endif #endif

View File

@ -443,7 +443,7 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) {
break; break;
case 1: case 1:
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
Play_ClearAllSubCameras(play); Play_ClearAllSubCameras(play);
this->cutsceneCamera = Play_CreateSubCamera(play); this->cutsceneCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, 0, 1); Play_ChangeCameraStatus(play, 0, 1);
@ -470,11 +470,11 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) {
} }
if (this->unk_198 == 110) { if (this->unk_198 == 110) {
func_8002DF54(play, &this->actor, 9); Player_SetCsActionWithHaltedActors(play, &this->actor, 9);
} }
if (this->unk_198 == 5) { if (this->unk_198 == 5) {
func_8002DF54(play, &this->actor, 12); Player_SetCsActionWithHaltedActors(play, &this->actor, 12);
} }
if (this->unk_198 < 6) { if (this->unk_198 < 6) {
@ -589,7 +589,7 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) {
func_800C08AC(play, this->cutsceneCamera, 0); func_800C08AC(play, this->cutsceneCamera, 0);
this->cutsceneCamera = 0; this->cutsceneCamera = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
BossDodongo_SetupWalk(this); BossDodongo_SetupWalk(this);
this->unk_1DA = 50; this->unk_1DA = 50;
this->unk_1BC = 0; this->unk_1BC = 0;
@ -1535,7 +1535,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) {
case 0: case 0:
this->csState = 5; this->csState = 5;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->cutsceneCamera = Play_CreateSubCamera(play); this->cutsceneCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_UNK3); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_UNK3);
Play_ChangeCameraStatus(play, this->cutsceneCamera, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->cutsceneCamera, CAM_STAT_ACTIVE);
@ -1850,7 +1850,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) {
this->csState = 100; this->csState = 100;
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE);
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
if (!IS_BOSS_RUSH) { if (!IS_BOSS_RUSH) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, WARP_DUNGEON_CHILD); Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, WARP_DUNGEON_CHILD);
} else { } else {

View File

@ -323,7 +323,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) {
this->introState = BFD_CS_START; this->introState = BFD_CS_START;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->introCamera = Play_CreateSubCamera(play); this->introCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->introCamera, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->introCamera, CAM_STAT_ACTIVE);
@ -399,7 +399,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) {
Math_ApproachF(&this->camData.shake, 2.0f, 1.0f, 0.8 * 0.01f); Math_ApproachF(&this->camData.shake, 2.0f, 1.0f, 0.8 * 0.01f);
} }
if (this->timers[0] == 40) { if (this->timers[0] == 40) {
func_8002DF54(play, &this->actor, 0x13); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x13);
} }
if (this->timers[0] == 0) { if (this->timers[0] == 0) {
this->introState = BFD_CS_LOOK_GROUND; this->introState = BFD_CS_LOOK_GROUND;
@ -428,7 +428,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) {
this->timers[0] = 170; this->timers[0] = 170;
this->camData.speedMod = 0.0f; this->camData.speedMod = 0.0f;
this->camData.accel = 0.0f; this->camData.accel = 0.0f;
func_8002DF54(play, &this->actor, 0x14); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x14);
} }
break; break;
case BFD_CS_COLLAPSE: case BFD_CS_COLLAPSE:
@ -478,7 +478,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) {
if (this->timers[3] == 190) { if (this->timers[3] == 190) {
this->camData.atMaxVel.x = this->camData.atMaxVel.y = this->camData.atMaxVel.z = 0.05f; this->camData.atMaxVel.x = this->camData.atMaxVel.y = this->camData.atMaxVel.z = 0.05f;
this->platformSignal = VBSIMA_KILL; this->platformSignal = VBSIMA_KILL;
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
} }
if (this->actor.world.pos.y > 120.0f) { if (this->actor.world.pos.y > 120.0f) {
this->camData.nextAt = this->actor.world.pos; this->camData.nextAt = this->actor.world.pos;
@ -546,7 +546,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) {
func_800C08AC(play, this->introCamera, 0); func_800C08AC(play, this->introCamera, 0);
this->introState = this->introFlyState = this->introCamera = BFD_CS_NONE; this->introState = this->introFlyState = this->introCamera = BFD_CS_NONE;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
this->actionFunc = BossFd_Wait; this->actionFunc = BossFd_Wait;
this->handoffSignal = FD2_SIGNAL_GROUND; this->handoffSignal = FD2_SIGNAL_GROUND;
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE);
@ -854,7 +854,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) {
this->work[BFD_CAM_SHAKE_TIMER] = 20; this->work[BFD_CAM_SHAKE_TIMER] = 20;
Audio_PlaySoundGeneral(NA_SE_EN_VALVAISA_LAND2, &this->actor.projectedPos, 4, &D_801333E0, Audio_PlaySoundGeneral(NA_SE_EN_VALVAISA_LAND2, &this->actor.projectedPos, 4, &D_801333E0,
&D_801333E0, &D_801333E8); &D_801333E0, &D_801333E8);
func_8002DF54(play, &this->actor, 5); Player_SetCsActionWithHaltedActors(play, &this->actor, 5);
for (i1 = 0; i1 < 15; i1++) { for (i1 = 0; i1 < 15; i1++) {
Vec3f sp144 = { 0.0f, 0.0f, 0.0f }; Vec3f sp144 = { 0.0f, 0.0f, 0.0f };
Vec3f sp138 = { 0.0f, 0.0f, 0.0f }; Vec3f sp138 = { 0.0f, 0.0f, 0.0f };

View File

@ -661,7 +661,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) {
case DEATH_START: case DEATH_START:
this->deathState = DEATH_RETREAT; this->deathState = DEATH_RETREAT;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->deathCamera = Play_CreateSubCamera(play); this->deathCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->deathCamera, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->deathCamera, CAM_STAT_ACTIVE);
@ -754,7 +754,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) {
this->work[FD2_ACTION_STATE]++; this->work[FD2_ACTION_STATE]++;
this->camData.speedMod = 0.0f; this->camData.speedMod = 0.0f;
this->camData.accel = 0.02f; this->camData.accel = 0.02f;
func_8002DF54(play, &bossFd->actor, 1); Player_SetCsActionWithHaltedActors(play, &bossFd->actor, 1);
} }
} }
if ((bossFd->work[BFD_ACTION_STATE] == BOSSFD_BONES_FALL) && (bossFd->timers[0] == 5)) { if ((bossFd->work[BFD_ACTION_STATE] == BOSSFD_BONES_FALL) && (bossFd->timers[0] == 5)) {
@ -788,7 +788,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) {
func_800C08AC(play, this->deathCamera, 0); func_800C08AC(play, this->deathCamera, 0);
this->deathCamera = 0; this->deathCamera = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
if (!IS_BOSS_RUSH) { if (!IS_BOSS_RUSH) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0,
0, WARP_DUNGEON_ADULT); 0, WARP_DUNGEON_ADULT);

View File

@ -564,7 +564,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) {
this->actor.shape.rot.y = 0; this->actor.shape.rot.y = 0;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->csCamIndex = Play_CreateSubCamera(play); this->csCamIndex = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE);
@ -609,7 +609,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) {
BossGanon_SetIntroCsCamera(this, 1); BossGanon_SetIntroCsCamera(this, 1);
if (this->csTimer == 10) { if (this->csTimer == 10) {
func_8002DF54(play, &this->actor, 5); Player_SetCsActionWithHaltedActors(play, &this->actor, 5);
} }
if (this->csTimer == 13) { if (this->csTimer == 13) {
@ -642,7 +642,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) {
break; break;
} }
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->csState = 4; this->csState = 4;
BossGanon_SetIntroCsCamera(this, 2); BossGanon_SetIntroCsCamera(this, 2);
this->csTimer = 0; this->csTimer = 0;
@ -674,7 +674,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) {
} }
if (this->csTimer == 10) { if (this->csTimer == 10) {
func_8002DF54(play, &this->actor, 0x4B); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4B);
} }
if (this->csTimer == 70) { if (this->csTimer == 70) {
@ -740,7 +740,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) {
this->csState = 9; this->csState = 9;
this->csTimer = 0; this->csTimer = 0;
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
sBossGanonZelda->unk_3C8 = 0; sBossGanonZelda->unk_3C8 = 0;
this->triforceType = GDF_TRIFORCE_ZELDA; this->triforceType = GDF_TRIFORCE_ZELDA;
this->fwork[GDF_TRIFORCE_SCALE] = 10.0f; this->fwork[GDF_TRIFORCE_SCALE] = 10.0f;
@ -794,7 +794,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) {
player->actor.world.pos.z = 20.0f; player->actor.world.pos.z = 20.0f;
if (this->csTimer == 20) { if (this->csTimer == 20) {
func_8002DF54(play, &this->actor, 0x17); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x17);
Interface_ChangeAlpha(11); // show hearts only Interface_ChangeAlpha(11); // show hearts only
} }
@ -1031,7 +1031,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) {
} }
if (this->csTimer == 30) { if (this->csTimer == 30) {
func_8002DF54(play, &this->actor, 0x4A); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4A);
} }
if (this->csTimer <= 50) { if (this->csTimer <= 50) {
@ -1154,7 +1154,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) {
func_800C08AC(play, this->csCamIndex, 0); func_800C08AC(play, this->csCamIndex, 0);
this->csState = this->csCamIndex = 0; this->csState = this->csCamIndex = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
BossGanon_SetupWait(this, play); BossGanon_SetupWait(this, play);
} }
@ -1267,7 +1267,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) {
switch (this->csState) { switch (this->csState) {
case 0: case 0:
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->csCamIndex = Play_CreateSubCamera(play); this->csCamIndex = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE);
@ -1510,7 +1510,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_BODY_SPARK - SFX_FLAG); Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_BODY_SPARK - SFX_FLAG);
if (this->csTimer == 2) { if (this->csTimer == 2) {
func_8002DF54(play, &this->actor, 0x39); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39);
} }
if (this->csTimer > 50) { if (this->csTimer > 50) {
@ -1539,20 +1539,14 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) {
if (this->csTimer == 180) { if (this->csTimer == 180) {
play->transitionTrigger = TRANS_TRIGGER_START; play->transitionTrigger = TRANS_TRIGGER_START;
if ((IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE) || IS_BOSS_RUSH)) { play->nextEntranceIndex = ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0;
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
play->nextEntranceIndex = ENTR_GANON_BOSS_0;
}
else {
play->nextEntranceIndex = ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0;
}
play->transitionType = TRANS_TYPE_FADE_WHITE_FAST; play->transitionType = TRANS_TYPE_FADE_WHITE_FAST;
} }
break; break;
case 100: case 100:
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->csCamIndex = Play_CreateSubCamera(play); this->csCamIndex = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE);
@ -1651,11 +1645,11 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) {
this->csCamAt.z = -135.0f; this->csCamAt.z = -135.0f;
if (this->csTimer == 5) { if (this->csTimer == 5) {
func_8002DF54(play, &this->actor, 0x4C); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4C);
} }
if (this->csTimer == 70) { if (this->csTimer == 70) {
func_8002DF54(play, &this->actor, 0x4D); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4D);
} }
if (this->csTimer == 90) { if (this->csTimer == 90) {
@ -1754,7 +1748,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) {
if (this->csTimer == 20) { if (this->csTimer == 20) {
sBossGanonZelda->unk_3C8 = 5; sBossGanonZelda->unk_3C8 = 5;
func_8002DF54(play, &this->actor, 0x39); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39);
} }
if (this->csTimer == 40) { if (this->csTimer == 40) {
@ -1821,7 +1815,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) {
this->csState = 107; this->csState = 107;
this->csTimer = 0; this->csTimer = 0;
Message_StartTextbox(play, 0x70D2, NULL); Message_StartTextbox(play, 0x70D2, NULL);
func_8002DF54(play, &this->actor, 0x39); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39);
} }
break; break;
@ -1863,7 +1857,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) {
this->csState = 109; this->csState = 109;
this->csCamIndex = 0; this->csCamIndex = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
Flags_SetSwitch(play, 0x37); Flags_SetSwitch(play, 0x37);
} }
break; break;

View File

@ -228,7 +228,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
objectIdx = Object_GetIndex(&play->objectCtx, OBJECT_GANON_ANIME3); objectIdx = Object_GetIndex(&play->objectCtx, OBJECT_GANON_ANIME3);
if (Object_IsLoaded(&play->objectCtx, objectIdx)) { if (Object_IsLoaded(&play->objectCtx, objectIdx)) {
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->unk_39E = Play_CreateSubCamera(play); this->unk_39E = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE);
@ -306,11 +306,11 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
} }
if (this->csTimer == 40) { if (this->csTimer == 40) {
sBossGanon2Zelda->unk_3C8 = 1; sBossGanon2Zelda->unk_3C8 = 1;
func_8002DF54(play, &this->actor, 0x4E); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4E);
} }
if (this->csTimer == 85) { if (this->csTimer == 85) {
sBossGanon2Zelda->unk_3C8 = 2; sBossGanon2Zelda->unk_3C8 = 2;
func_8002DF54(play, &this->actor, 0x4F); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4F);
} }
this->unk_3A4.x = 930.0f; this->unk_3A4.x = 930.0f;
this->unk_3A4.y = 1129.0f; this->unk_3A4.y = 1129.0f;
@ -339,14 +339,14 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
} }
if (this->csTimer == 20) { if (this->csTimer == 20) {
sBossGanon2Zelda->unk_3C8 = 3; sBossGanon2Zelda->unk_3C8 = 3;
func_8002DF54(play, &this->actor, 0x50); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x50);
} }
if (this->csTimer == 55) { if (this->csTimer == 55) {
this->csState = 4; this->csState = 4;
this->csTimer = 0; this->csTimer = 0;
this->unk_410.x = 0.0f; this->unk_410.x = 0.0f;
sBossGanon2Zelda->unk_3C8 = 4; sBossGanon2Zelda->unk_3C8 = 4;
func_8002DF54(play, &this->actor, 0x50); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x50);
} }
break; break;
case 4: case 4:
@ -363,7 +363,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
func_800C08AC(play, this->unk_39E, 0); func_800C08AC(play, this->unk_39E, 0);
this->unk_39E = 0; this->unk_39E = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
this->csState = 5; this->csState = 5;
this->csTimer = 0; this->csTimer = 0;
} }
@ -409,7 +409,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
} }
if (this->csTimer == 30) { if (this->csTimer == 30) {
sBossGanon2Zelda->unk_3C8 = 5; sBossGanon2Zelda->unk_3C8 = 5;
func_8002DF54(play, &this->actor, 0x51); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x51);
} }
if (this->csTimer == 50) { if (this->csTimer == 50) {
this->csTimer = 0; this->csTimer = 0;
@ -440,7 +440,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
func_80078884(NA_SE_EV_STONE_BOUND); func_80078884(NA_SE_EV_STONE_BOUND);
} }
if (this->csTimer == 30) { if (this->csTimer == 30) {
func_8002DF54(play, &this->actor, 0x52); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x52);
} }
if (this->csTimer == 50) { if (this->csTimer == 50) {
this->csTimer = 0; this->csTimer = 0;
@ -505,7 +505,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
this->unk_3B0.y = player->actor.world.pos.y; this->unk_3B0.y = player->actor.world.pos.y;
this->unk_3B0.z = player->actor.world.pos.z - 200.0f; this->unk_3B0.z = player->actor.world.pos.z - 200.0f;
if (this->csTimer == 20) { if (this->csTimer == 20) {
func_8002DF54(play, &this->actor, 0x1E); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x1E);
} }
if (this->csTimer == 60) { if (this->csTimer == 60) {
this->unk_3A4.x = (this->actor.world.pos.x + 200.0f) - 154.0f; this->unk_3A4.x = (this->actor.world.pos.x + 200.0f) - 154.0f;
@ -593,7 +593,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
SkelAnime_Free(&this->skelAnime, play); SkelAnime_Free(&this->skelAnime, play);
SkelAnime_InitFlex(play, &this->skelAnime, &gGanonSkel, NULL, NULL, NULL, 0); SkelAnime_InitFlex(play, &this->skelAnime, &gGanonSkel, NULL, NULL, NULL, 0);
BossGanon2_SetObjectSegment(this, play, OBJECT_GANON_ANIME3, false); BossGanon2_SetObjectSegment(this, play, OBJECT_GANON_ANIME3, false);
func_8002DF54(play, &this->actor, 0x54); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x54);
this->unk_314 = 3; this->unk_314 = 3;
// At this point, the actor has Ganon's skeleton but is still playing an animation for Ganondorf. This // At this point, the actor has Ganon's skeleton but is still playing an animation for Ganondorf. This
@ -657,7 +657,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
this->actor.world.pos.x += 250; this->actor.world.pos.x += 250;
this->actor.world.pos.y = 1886.0f; this->actor.world.pos.y = 1886.0f;
this->unk_394 = 0.0f; this->unk_394 = 0.0f;
func_8002DF54(play, &this->actor, 0x53); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x53);
this->unk_30C = 5.0f; this->unk_30C = 5.0f;
this->unk_228 = 1.0f; this->unk_228 = 1.0f;
} }
@ -742,7 +742,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
if (this->csTimer == 215) { if (this->csTimer == 215) {
this->csState = 23; this->csState = 23;
this->unk_224 = 0.0f; this->unk_224 = 0.0f;
func_8002DF54(play, &this->actor, 0x55); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x55);
} }
break; break;
case 23: case 23:
@ -762,7 +762,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
this->unk_3B0.z = player->actor.world.pos.z; this->unk_3B0.z = player->actor.world.pos.z;
if (this->csTimer == 228) { if (this->csTimer == 228) {
func_80078884(NA_SE_IT_SHIELD_REFLECT_SW); func_80078884(NA_SE_IT_SHIELD_REFLECT_SW);
func_8002DF54(play, &this->actor, 0x56); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x56);
func_800A9F6C(0.0f, 0xFF, 0xA, 0x32); func_800A9F6C(0.0f, 0xFF, 0xA, 0x32);
} }
if (this->csTimer >= 229) { if (this->csTimer >= 229) {
@ -799,7 +799,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
func_80078884(NA_SE_IT_SWORD_SWING); func_80078884(NA_SE_IT_SWORD_SWING);
} }
if (this->csTimer == 25) { if (this->csTimer == 25) {
func_8002DF54(play, &this->actor, 0x57); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x57);
this->csState = 25; this->csState = 25;
this->csTimer = 0; this->csTimer = 0;
} }
@ -846,7 +846,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
case 27: case 27:
this->unk_3BC.z = 0.0f; this->unk_3BC.z = 0.0f;
if (this->csTimer == 4) { if (this->csTimer == 4) {
func_8002DF54(play, &this->actor, 0x58); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x58);
} }
this->unk_3A4.x = player->actor.world.pos.x - 20.0f; this->unk_3A4.x = player->actor.world.pos.x - 20.0f;
this->unk_3A4.y = player->actor.world.pos.y + 50.0f; this->unk_3A4.y = player->actor.world.pos.y + 50.0f;
@ -919,7 +919,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) {
func_800C08AC(play, this->unk_39E, 0); func_800C08AC(play, this->unk_39E, 0);
this->unk_39E = 0; this->unk_39E = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
this->csState = 0; this->csState = 0;
this->unk_337 = 1; this->unk_337 = 1;
func_808FFDB0(this, play); func_808FFDB0(this, play);
@ -1340,7 +1340,7 @@ void func_80900890(BossGanon2* this, PlayState* play) {
this->unk_39E = Play_CreateSubCamera(play); this->unk_39E = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->csState = 1; this->csState = 1;
this->unk_3A4 = sp4C->eye; this->unk_3A4 = sp4C->eye;
this->unk_3B0 = sp4C->at; this->unk_3B0 = sp4C->at;
@ -1388,7 +1388,7 @@ void func_80900890(BossGanon2* this, PlayState* play) {
func_800C08AC(play, this->unk_39E, 0); func_800C08AC(play, this->unk_39E, 0);
this->unk_39E = 0; this->unk_39E = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
this->csState = 3; this->csState = 3;
} }
break; break;
@ -1399,7 +1399,7 @@ void func_80900890(BossGanon2* this, PlayState* play) {
Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE);
this->csState = 11; this->csState = 11;
this->unk_334 = 1; this->unk_334 = 1;
func_8002DF54(play, &this->actor, 0x60); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x60);
this->csTimer = 0; this->csTimer = 0;
case 11: case 11:
player->actor.world.pos.x = sBossGanon2Zelda->actor.world.pos.x + 50.0f + 10.0f; player->actor.world.pos.x = sBossGanon2Zelda->actor.world.pos.x + 50.0f + 10.0f;
@ -1420,7 +1420,7 @@ void func_80900890(BossGanon2* this, PlayState* play) {
func_800C08AC(play, this->unk_39E, 0); func_800C08AC(play, this->unk_39E, 0);
this->unk_39E = 0; this->unk_39E = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
} }
break; break;
} }
@ -1536,7 +1536,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) {
this->unk_39E = Play_CreateSubCamera(play); this->unk_39E = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->csState = 1; this->csState = 1;
this->csTimer = 0; this->csTimer = 0;
sBossGanon2Zelda->unk_3C8 = 9; sBossGanon2Zelda->unk_3C8 = 9;
@ -1572,7 +1572,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) {
this->skelAnime.playSpeed = 3.0f; this->skelAnime.playSpeed = 3.0f;
} }
if (this->csTimer == 120) { if (this->csTimer == 120) {
func_8002DF54(play, &this->actor, 0x63); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x63);
} }
this->actor.world.rot.y = 0x4000; this->actor.world.rot.y = 0x4000;
this->actor.world.pos.x = this->actor.world.pos.z = 0.0f; this->actor.world.pos.x = this->actor.world.pos.z = 0.0f;
@ -1640,7 +1640,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) {
this->csState = 5; this->csState = 5;
this->csTimer = 40; this->csTimer = 40;
this->skelAnime.playSpeed = 1.0f; this->skelAnime.playSpeed = 1.0f;
func_8002DF54(play, &this->actor, 0x64); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x64);
} }
break; break;
case 5: case 5:
@ -1654,10 +1654,10 @@ void func_8090120C(BossGanon2* this, PlayState* play) {
Math_ApproachZeroF(&this->unk_38C, 1.0f, 8.0f); Math_ApproachZeroF(&this->unk_38C, 1.0f, 8.0f);
} }
if (this->csTimer == 70) { if (this->csTimer == 70) {
func_8002DF54(play, &this->actor, 0x65); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x65);
} }
if (this->csTimer == 150) { if (this->csTimer == 150) {
func_8002DF54(play, &this->actor, 0x66); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x66);
} }
this->unk_30C = 10.0f; this->unk_30C = 10.0f;
player->actor.world.pos.x = 250.0f; player->actor.world.pos.x = 250.0f;
@ -1676,7 +1676,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) {
func_800C08AC(play, this->unk_39E, 0); func_800C08AC(play, this->unk_39E, 0);
this->unk_39E = 0; this->unk_39E = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
this->csState = 6; this->csState = 6;
} }
break; break;
@ -1764,7 +1764,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) {
if (this->csTimer == 55) { if (this->csTimer == 55) {
Animation_MorphToPlayOnce(&this->skelAnime, &gGanonDeadStartAnim, 0.0f); Animation_MorphToPlayOnce(&this->skelAnime, &gGanonDeadStartAnim, 0.0f);
this->unk_194 = Animation_GetLastFrame(&gGanonDeadStartAnim); this->unk_194 = Animation_GetLastFrame(&gGanonDeadStartAnim);
func_8002DF54(play, &this->actor, 0x62); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x62);
this->csState = 8; this->csState = 8;
this->csTimer = 1000; this->csTimer = 1000;
} }

View File

@ -12,19 +12,10 @@
#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h"
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
#include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/Enhancements/boss-rush/BossRush.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
typedef enum {
/* 0 */ NOT_DEAD,
/* 1 */ DEATH_START,
/* 2 */ DEATH_THROES,
/* 3 */ DEATH_WARP,
/* 4 */ DEATH_SCREAM,
/* 5 */ DEATH_DISINTEGRATE,
/* 6 */ DEATH_FINISH
} BossGanondrofDeathState;
typedef enum { typedef enum {
/* 0 */ THROW_NORMAL, /* 0 */ THROW_NORMAL,
/* 1 */ THROW_SLOW /* 1 */ THROW_SLOW
@ -42,12 +33,6 @@ typedef enum {
/* 3 */ CHARGE_FINISH /* 3 */ CHARGE_FINISH
} BossGanondrofChargeAction; } BossGanondrofChargeAction;
typedef enum {
/* 0 */ DEATH_SPASM,
/* 1 */ DEATH_LIMP,
/* 2 */ DEATH_HUNCHED
} BossGanondrofDeathAction;
void BossGanondrof_Init(Actor* thisx, PlayState* play); void BossGanondrof_Init(Actor* thisx, PlayState* play);
void BossGanondrof_Destroy(Actor* thisx, PlayState* play); void BossGanondrof_Destroy(Actor* thisx, PlayState* play);
void BossGanondrof_Update(Actor* thisx, PlayState* play); void BossGanondrof_Update(Actor* thisx, PlayState* play);
@ -926,7 +911,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
switch (this->deathState) { switch (this->deathState) {
case DEATH_START: case DEATH_START:
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->deathCamera = Play_CreateSubCamera(play); this->deathCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
osSyncPrintf("7\n"); osSyncPrintf("7\n");
@ -959,26 +944,13 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
case DEATH_THROES: case DEATH_THROES:
switch (this->work[GND_ACTION_STATE]) { switch (this->work[GND_ACTION_STATE]) {
case DEATH_SPASM: case DEATH_SPASM:
if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME]) && !IS_RANDO && !IS_BOSS_RUSH) { if (GameInteractor_Should(GI_VB_PHANTOM_GANON_DEATH_SCENE, true, this)) {
this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim); if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) {
Animation_Change(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.5f, 0.0f, this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim);
this->fwork[GND_END_FRAME], ANIMMODE_ONCE_INTERP, 0.0f); Animation_Change(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.5f, 0.0f,
this->work[GND_ACTION_STATE] = DEATH_LIMP; this->fwork[GND_END_FRAME], ANIMMODE_ONCE_INTERP, 0.0f);
} else if (IS_RANDO || IS_BOSS_RUSH) { this->work[GND_ACTION_STATE] = DEATH_LIMP;
// Skip to death scream animation and move ganondrof to middle }
this->deathState = DEATH_SCREAM;
this->timers[0] = 50;
Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonScreamAnim, -10.0f);
this->actor.world.pos.x = GND_BOSSROOM_CENTER_X;
this->actor.world.pos.y = GND_BOSSROOM_CENTER_Y + 83.0f;
this->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
this->actor.shape.rot.y = 0;
this->work[GND_BODY_DECAY_INDEX] = 0;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_LAST);
// Move Player out of the center of the room
player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f;
player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
} }
break; break;
case DEATH_LIMP: case DEATH_LIMP:
@ -991,26 +963,25 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
bodyDecayLevel = 1; bodyDecayLevel = 1;
break; break;
} }
if (IS_RANDO || IS_BOSS_RUSH) { if (GameInteractor_Should(GI_VB_PHANTOM_GANON_DEATH_SCENE, true, NULL)) {
break; Math_ApproachS(&this->actor.shape.rot.y, this->work[GND_VARIANCE_TIMER] * -100, 5, 0xBB8);
} Math_ApproachF(&this->cameraNextEye.z, this->targetPos.z + 60.0f, 0.02f, 0.5f);
Math_ApproachS(&this->actor.shape.rot.y, this->work[GND_VARIANCE_TIMER] * -100, 5, 0xBB8); Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 133.0f, 0.05f, 100.0f);
Math_ApproachF(&this->cameraNextEye.z, this->targetPos.z + 60.0f, 0.02f, 0.5f); this->actor.world.pos.y += Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 133.0f, 0.05f, 100.0f); this->cameraNextAt.x = this->targetPos.x;
this->actor.world.pos.y += Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500); this->cameraNextAt.y = this->targetPos.y - 10.0f;
this->cameraNextAt.x = this->targetPos.x; this->cameraNextAt.z = this->targetPos.z;
this->cameraNextAt.y = this->targetPos.y - 10.0f; if (this->timers[0] == 0) {
this->cameraNextAt.z = this->targetPos.z; this->deathState = DEATH_WARP;
if (this->timers[0] == 0) { this->timers[0] = 350;
this->deathState = DEATH_WARP; this->timers[1] = 50;
this->timers[0] = 350; this->fwork[GND_CAMERA_ZOOM] = 300.0f;
this->timers[1] = 50; this->cameraNextEye.y = GND_BOSSROOM_CENTER_Y + 233.0f;
this->fwork[GND_CAMERA_ZOOM] = 300.0f; player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f;
this->cameraNextEye.y = GND_BOSSROOM_CENTER_Y + 233.0f; player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f; holdCamera = true;
player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z; bodyDecayLevel = 1;
holdCamera = true; }
bodyDecayLevel = 1;
} }
break; break;
case DEATH_WARP: case DEATH_WARP:
@ -1104,7 +1075,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
func_800C08AC(play, this->deathCamera, 0); func_800C08AC(play, this->deathCamera, 0);
this->deathCamera = 0; this->deathCamera = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
if (!IS_BOSS_RUSH) { if (!IS_BOSS_RUSH) {
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, GND_BOSSROOM_CENTER_X, GND_BOSSROOM_CENTER_Y, Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, GND_BOSSROOM_CENTER_X, GND_BOSSROOM_CENTER_Y,
GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0, true); GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0, true);

View File

@ -61,6 +61,23 @@ typedef enum {
/* 13 */ GND_FLOAT_COUNT = 13 /* 13 */ GND_FLOAT_COUNT = 13
} BossGanondrofF32Var; } BossGanondrofF32Var;
// SOH [Enhancements] Relocated from z_boss_ganondrof.c to use in time saver.
typedef enum {
/* 0 */ NOT_DEAD,
/* 1 */ DEATH_START,
/* 2 */ DEATH_THROES,
/* 3 */ DEATH_WARP,
/* 4 */ DEATH_SCREAM,
/* 5 */ DEATH_DISINTEGRATE,
/* 6 */ DEATH_FINISH
} BossGanondrofDeathState;
typedef enum {
/* 0 */ DEATH_SPASM,
/* 1 */ DEATH_LIMP,
/* 2 */ DEATH_HUNCHED
} BossGanondrofDeathAction;
typedef struct BossGanondrof { typedef struct BossGanondrof {
/* 0x0000 */ Actor actor; /* 0x0000 */ Actor actor;
/* 0x014C */ SkelAnime skelAnime; /* 0x014C */ SkelAnime skelAnime;

View File

@ -628,7 +628,7 @@ void BossGoma_SetupEncounterState4(BossGoma* this, PlayState* play) {
this->actionState = 4; this->actionState = 4;
this->actor.flags |= ACTOR_FLAG_TARGETABLE; this->actor.flags |= ACTOR_FLAG_TARGETABLE;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->subCameraId = Play_CreateSubCamera(play); this->subCameraId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, 0, 3); Play_ChangeCameraStatus(play, 0, 3);
Play_ChangeCameraStatus(play, this->subCameraId, 7); Play_ChangeCameraStatus(play, this->subCameraId, 7);
@ -685,7 +685,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_SHUTTER, 164.72f, Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_SHUTTER, 164.72f,
-480.0f, 397.68002f, 0, -0x705C, 0, 0x180); -480.0f, 397.68002f, 0, -0x705C, 0, 0x180);
} else { } else {
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->actionState = 1; this->actionState = 1;
} }
} }
@ -756,7 +756,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) {
} }
if (this->frameCount == 190) { if (this->frameCount == 190) {
func_8002DF54(play, &this->actor, 2); Player_SetCsActionWithHaltedActors(play, &this->actor, 2);
} }
if (this->frameCount >= 228) { if (this->frameCount >= 228) {
@ -767,7 +767,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) {
func_800C08AC(play, this->subCameraId, 0); func_800C08AC(play, this->subCameraId, 0);
this->subCameraId = 0; this->subCameraId = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
this->actionState = 3; this->actionState = 3;
} }
break; break;
@ -964,7 +964,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) {
this->disableGameplayLogic = false; this->disableGameplayLogic = false;
this->patienceTimer = 200; this->patienceTimer = 200;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
} }
break; break;
} }
@ -1054,7 +1054,7 @@ void BossGoma_Defeated(BossGoma* this, PlayState* play) {
case 0: case 0:
this->actionState = 1; this->actionState = 1;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
this->subCameraId = Play_CreateSubCamera(play); this->subCameraId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, 0, 3); Play_ChangeCameraStatus(play, 0, 3);
Play_ChangeCameraStatus(play, this->subCameraId, 7); Play_ChangeCameraStatus(play, this->subCameraId, 7);
@ -1189,7 +1189,7 @@ void BossGoma_Defeated(BossGoma* this, PlayState* play) {
func_800C08AC(play, this->subCameraId, 0); func_800C08AC(play, this->subCameraId, 0);
this->subCameraId = 0; this->subCameraId = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
} }

View File

@ -1249,7 +1249,7 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) {
(fabsf(player->actor.world.pos.x - -180.0f) < 40.0f))) { (fabsf(player->actor.world.pos.x - -180.0f) < 40.0f))) {
// checks if Link is on one of the four platforms // checks if Link is on one of the four platforms
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->csCamera = Play_CreateSubCamera(play); this->csCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->csCamera, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->csCamera, CAM_STAT_ACTIVE);
@ -1357,11 +1357,11 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) {
Math_ApproachF(&this->actor.speedXZ, sp80, 1.0f, sp78); Math_ApproachF(&this->actor.speedXZ, sp80, 1.0f, sp78);
Math_ApproachF(&this->cameraYawRate, sp7C, 1.0f, 128.0f); Math_ApproachF(&this->cameraYawRate, sp7C, 1.0f, 128.0f);
if (this->work[MO_TENT_MOVE_TIMER] == 525) { if (this->work[MO_TENT_MOVE_TIMER] == 525) {
func_8002DF54(play, &this->actor, 2); Player_SetCsActionWithHaltedActors(play, &this->actor, 2);
} }
if (this->work[MO_TENT_MOVE_TIMER] > 540) { if (this->work[MO_TENT_MOVE_TIMER] > 540) {
this->csState = MO_INTRO_REVEAL; this->csState = MO_INTRO_REVEAL;
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
sMorphaTent1->drawActor = true; sMorphaTent1->drawActor = true;
player->actor.world.pos.x = 180.0f; player->actor.world.pos.x = 180.0f;
player->actor.world.pos.z = -210.0f; player->actor.world.pos.z = -210.0f;
@ -1468,7 +1468,7 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) {
func_800C08AC(play, this->csCamera, 0); func_800C08AC(play, this->csCamera, 0);
this->csState = this->csCamera = MO_BATTLE; this->csState = this->csCamera = MO_BATTLE;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
} }
break; break;
} }
@ -1533,7 +1533,7 @@ void BossMo_DeathCs(BossMo* this, PlayState* play) {
switch (this->csState) { switch (this->csState) {
case MO_DEATH_START: case MO_DEATH_START:
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->csCamera = Play_CreateSubCamera(play); this->csCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->csCamera, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->csCamera, CAM_STAT_ACTIVE);
@ -1700,7 +1700,7 @@ void BossMo_DeathCs(BossMo* this, PlayState* play) {
func_800C08AC(play, this->csCamera, 0); func_800C08AC(play, this->csCamera, 0);
this->csCamera = 0; this->csCamera = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
sMorphaTent1->actor.world.pos.y = -1000.0f; sMorphaTent1->actor.world.pos.y = -1000.0f;
} }
} else { } else {

View File

@ -390,7 +390,7 @@ void BossSst_HeadSetupIntro(BossSst* this, PlayState* play) {
player->stateFlags1 |= PLAYER_STATE1_INPUT_DISABLED; player->stateFlags1 |= PLAYER_STATE1_INPUT_DISABLED;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
sCutsceneCamera = Play_CreateSubCamera(play); sCutsceneCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_ACTIVE);
@ -423,7 +423,7 @@ void BossSst_HeadIntro(BossSst* this, PlayState* play) {
sHands[LEFT]->actor.flags |= ACTOR_FLAG_TARGETABLE; sHands[LEFT]->actor.flags |= ACTOR_FLAG_TARGETABLE;
player->stateFlags1 &= ~PLAYER_STATE1_INPUT_DISABLED; player->stateFlags1 &= ~PLAYER_STATE1_INPUT_DISABLED;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
sCameraAt.y += 30.0f; sCameraAt.y += 30.0f;
sCameraAt.z += 300.0f; sCameraAt.z += 300.0f;
Play_CameraSetAtEye(play, sCutsceneCamera, &sCameraAt, &sCameraEye); Play_CameraSetAtEye(play, sCutsceneCamera, &sCameraAt, &sCameraEye);
@ -1032,7 +1032,7 @@ void BossSst_HeadSetupDeath(BossSst* this, PlayState* play) {
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_ACTIVE);
Play_CopyCamera(play, sCutsceneCamera, MAIN_CAM); Play_CopyCamera(play, sCutsceneCamera, MAIN_CAM);
func_8002DF54(play, &player->actor, 8); Player_SetCsActionWithHaltedActors(play, &player->actor, 8);
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
Math_Vec3f_Copy(&sCameraEye, &GET_ACTIVE_CAM(play)->eye); Math_Vec3f_Copy(&sCameraEye, &GET_ACTIVE_CAM(play)->eye);
this->actionFunc = BossSst_HeadDeath; this->actionFunc = BossSst_HeadDeath;
@ -1194,7 +1194,7 @@ void BossSst_HeadFinish(BossSst* this, PlayState* play) {
Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE);
Play_ClearCamera(play, sCutsceneCamera); Play_ClearCamera(play, sCutsceneCamera);
func_8002DF54(play, &GET_PLAYER(play)->actor, 7); Player_SetCsActionWithHaltedActors(play, &GET_PLAYER(play)->actor, 7);
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
Actor_Kill(&sHands[LEFT]->actor); Actor_Kill(&sHands[LEFT]->actor);

View File

@ -1466,7 +1466,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) {
case 0: case 0:
this->csState2 = 1; this->csState2 = 1;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 0x39); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39);
this->subCamId = Play_CreateSubCamera(play); this->subCamId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE);
@ -1606,7 +1606,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) {
Animation_MorphToPlayOnce(&this->skelAnime, &gTwinrovaIntroAnim, 0.0f); Animation_MorphToPlayOnce(&this->skelAnime, &gTwinrovaIntroAnim, 0.0f);
this->workf[ANIM_SW_TGT] = Animation_GetLastFrame(&gTwinrovaIntroAnim); this->workf[ANIM_SW_TGT] = Animation_GetLastFrame(&gTwinrovaIntroAnim);
this->timers[0] = 50; this->timers[0] = 50;
func_8002DF54(play, &this->actor, 2); Player_SetCsActionWithHaltedActors(play, &this->actor, 2);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_TWINROBA_TRANSFORM); Audio_PlayActorSound2(&this->actor, NA_SE_EN_TWINROBA_TRANSFORM);
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS); Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS);
} }
@ -1649,7 +1649,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) {
} }
if (this->timers[3] == 19) { if (this->timers[3] == 19) {
func_8002DF54(play, &this->actor, 5); Player_SetCsActionWithHaltedActors(play, &this->actor, 5);
} }
if (this->timers[3] == 16) { if (this->timers[3] == 16) {
@ -1682,7 +1682,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) {
this->subCamId = 0; this->subCamId = 0;
this->csState2 = this->subCamId; this->csState2 = this->subCamId;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
this->work[TW_PLLR_IDX] = 0; this->work[TW_PLLR_IDX] = 0;
this->targetPos = sTwinrovaPillarPos[0]; this->targetPos = sTwinrovaPillarPos[0];
BossTw_TwinrovaSetupFly(this, play); BossTw_TwinrovaSetupFly(this, play);
@ -1762,7 +1762,7 @@ void BossTw_TwinrovaIntroCS(BossTw* this, PlayState* play) {
player->actor.world.pos.x = player->actor.world.pos.z = .0f; player->actor.world.pos.x = player->actor.world.pos.z = .0f;
this->csState2 = 1; this->csState2 = 1;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 0x39); Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39);
this->subCamId = Play_CreateSubCamera(play); this->subCamId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE);
@ -2245,7 +2245,7 @@ void BossTw_TwinrovaIntroCS(BossTw* this, PlayState* play) {
this->subCamId = 0; this->subCamId = 0;
this->csState2 = this->subCamId; this->csState2 = this->subCamId;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
BossTw_SetupWait(this, play); BossTw_SetupWait(this, play);
} }
break; break;
@ -2666,7 +2666,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) {
case 0: case 0:
this->csState2 = 1; this->csState2 = 1;
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
this->subCamId = Play_CreateSubCamera(play); this->subCamId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE);
@ -2705,7 +2705,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) {
sKoumePtr->actor.world.pos.z = sKotakePtr->actor.world.pos.z; sKoumePtr->actor.world.pos.z = sKotakePtr->actor.world.pos.z;
sKoumePtr->work[YAW_TGT] = sKotakePtr->work[YAW_TGT] = sKoumePtr->actor.shape.rot.x = sKoumePtr->work[YAW_TGT] = sKotakePtr->work[YAW_TGT] = sKoumePtr->actor.shape.rot.x =
sKotakePtr->actor.shape.rot.x = sKoumePtr->actor.shape.rot.y = sKotakePtr->actor.shape.rot.y = 0; sKotakePtr->actor.shape.rot.x = sKoumePtr->actor.shape.rot.y = sKotakePtr->actor.shape.rot.y = 0;
func_8002DF54(play, &sKoumePtr->actor, 1); Player_SetCsActionWithHaltedActors(play, &sKoumePtr->actor, 1);
sKoumePtr->actor.flags |= ACTOR_FLAG_TARGETABLE; sKoumePtr->actor.flags |= ACTOR_FLAG_TARGETABLE;
} }
break; break;
@ -2793,7 +2793,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) {
this->csState2 = 4; this->csState2 = 4;
this->subCamId = 0; this->subCamId = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR); Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR);
if (!IS_BOSS_RUSH) { if (!IS_BOSS_RUSH) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0,

View File

@ -657,7 +657,7 @@ void BossVa_Init(Actor* thisx, PlayState* play2) {
} else { } else {
sCsState = INTRO_CALL_BARI; sCsState = INTRO_CALL_BARI;
sDoorState = 100; sDoorState = 100;
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
play->envCtx.screenFillColor[0] = 0xDC; play->envCtx.screenFillColor[0] = 0xDC;
play->envCtx.screenFillColor[1] = 0xDC; play->envCtx.screenFillColor[1] = 0xDC;
play->envCtx.screenFillColor[2] = 0xBE; play->envCtx.screenFillColor[2] = 0xBE;
@ -799,7 +799,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) {
play->envCtx.screenFillColor[1] = 0xDC; play->envCtx.screenFillColor[1] = 0xDC;
play->envCtx.screenFillColor[2] = 0xBE; play->envCtx.screenFillColor[2] = 0xBE;
play->envCtx.screenFillColor[3] = 0xD2; play->envCtx.screenFillColor[3] = 0xD2;
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
player->actor.world.rot.y = player->actor.shape.rot.y = 0x7FFF; player->actor.world.rot.y = player->actor.shape.rot.y = 0x7FFF;
sCsState++; sCsState++;
break; break;
@ -827,7 +827,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) {
case INTRO_CLOSE_DOOR: case INTRO_CLOSE_DOOR:
this->timer--; this->timer--;
if (this->timer == 0) { if (this->timer == 0) {
func_8002DF54(play, &this->actor, 2); Player_SetCsActionWithHaltedActors(play, &this->actor, 2);
sCsState++; sCsState++;
this->timer = 30; this->timer = 30;
} }
@ -842,7 +842,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) {
} }
break; break;
case INTRO_CRACKLE: case INTRO_CRACKLE:
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
sCsState++; sCsState++;
break; break;
case INTRO_SPAWN_BARI: case INTRO_SPAWN_BARI:
@ -973,7 +973,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) {
sCameraAtMaxVel = sCameraEyeMaxVel; sCameraAtMaxVel = sCameraEyeMaxVel;
if (this->timer >= 45000) { if (this->timer >= 45000) {
play->envCtx.unk_BF = 1; play->envCtx.unk_BF = 1;
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
} else if (this->timer >= 35000) { } else if (this->timer >= 35000) {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS); Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS);
} }
@ -1030,7 +1030,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) {
sCsCamera = 0; sCsCamera = 0;
func_80064534(play, &play->csCtx); func_80064534(play, &play->csCtx);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE);
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
sCsState++; sCsState++;
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE);
player->actor.shape.rot.y = player->actor.world.rot.y = this->actor.yawTowardsPlayer + 0x8000; player->actor.shape.rot.y = player->actor.world.rot.y = this->actor.yawTowardsPlayer + 0x8000;
@ -1550,7 +1550,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) {
switch (sCsState) { switch (sCsState) {
case DEATH_START: case DEATH_START:
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
func_80064520(play, &play->csCtx); func_80064520(play, &play->csCtx);
sCsCamera = Play_CreateSubCamera(play); sCsCamera = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
@ -1613,7 +1613,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) {
0x28); 0x28);
this->onCeiling = 2; // Not used by body this->onCeiling = 2; // Not used by body
BossVa_SetDeathEnv(play); BossVa_SetDeathEnv(play);
func_8002DF54(play, &this->actor, 8); Player_SetCsActionWithHaltedActors(play, &this->actor, 8);
} }
break; break;
case DEATH_CORE_BURST: case DEATH_CORE_BURST:
@ -1654,7 +1654,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) {
camera->at = sCameraAt; camera->at = sCameraAt;
func_8002DF54(play, &this->actor, 7); Player_SetCsActionWithHaltedActors(play, &this->actor, 7);
sCsState++; sCsState++;
if (!IS_BOSS_RUSH) { if (!IS_BOSS_RUSH) {
@ -2444,7 +2444,7 @@ void BossVa_BariIntro(BossVa* this, PlayState* play) {
switch (sCsState) { switch (sCsState) {
case INTRO_LOOK_BARI: case INTRO_LOOK_BARI:
if (this->actor.params == BOSSVA_BARI_UPPER_1) { if (this->actor.params == BOSSVA_BARI_UPPER_1) {
func_8002DF54(play, &this->actor, 1); Player_SetCsActionWithHaltedActors(play, &this->actor, 1);
if (Math_SmoothStepToF(&this->actor.world.pos.y, 60.0f, 0.3f, 1.0f, 0.15f) == 0.0f) { if (Math_SmoothStepToF(&this->actor.world.pos.y, 60.0f, 0.3f, 1.0f, 0.15f) == 0.0f) {
this->timer--; this->timer--;
if (this->timer == 0) { if (this->timer == 0) {

View File

@ -3,6 +3,7 @@
#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h" #include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
#include "vt.h" #include "vt.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
@ -184,7 +185,9 @@ void func_80969F38(DemoDu* this, PlayState* play) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
DEMO_EFFECT_MEDAL_FIRE); DEMO_EFFECT_MEDAL_FIRE);
Item_Give(play, ITEM_MEDALLION_FIRE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_FIRE);
}
} }
void func_80969FB4(DemoDu* this, PlayState* play) { void func_80969FB4(DemoDu* this, PlayState* play) {
@ -201,7 +204,9 @@ void DemoDu_CsFireMedallion_AdvanceTo01(DemoDu* this, PlayState* play) {
this->updateIndex = CS_FIREMEDALLION_SUBSCENE(1); this->updateIndex = CS_FIREMEDALLION_SUBSCENE(1);
play->csCtx.segment = D_8096C1A4; play->csCtx.segment = D_8096C1A4;
gSaveContext.cutsceneTrigger = 2; gSaveContext.cutsceneTrigger = 2;
Item_Give(play, ITEM_MEDALLION_FIRE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_FIRE);
}
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
} }

View File

@ -142,7 +142,7 @@ f32 DemoEffect_InterpolateCsFrames(PlayState* play, s32 csActionId) {
*/ */
void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) { void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) {
this->initDrawFunc = DemoEffect_DrawJewel; this->initDrawFunc = DemoEffect_DrawJewel;
if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) {
this->initDrawFunc = DemoEffect_DrawGetItem; this->initDrawFunc = DemoEffect_DrawGetItem;
} }
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
@ -156,7 +156,7 @@ void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) {
Actor_SetScale(&this->actor, 0.10f); Actor_SetScale(&this->actor, 0.10f);
} }
this->csActionId = 1; this->csActionId = 1;
this->actor.shape.rot.x = (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) ? 0 : 16384; this->actor.shape.rot.x = (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) ? 0 : 16384;
DemoEffect_InitJewelColor(this); DemoEffect_InitJewelColor(this);
this->jewel.alpha = 0; this->jewel.alpha = 0;
this->jewelCsRotation.x = this->jewelCsRotation.y = this->jewelCsRotation.z = 0; this->jewelCsRotation.x = this->jewelCsRotation.y = this->jewelCsRotation.z = 0;
@ -2087,13 +2087,48 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) {
this->getItem.isLoaded = 1; this->getItem.isLoaded = 1;
return; return;
} }
if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); GetItemEntry getItemEntry = GET_ITEM_NONE;
this->getItem.drawId = getItemEntry.gid;
func_8002EBCC(thisx, play, 0); switch (this->actor.params) {
func_8002ED80(thisx, play, 0); case DEMO_EFFECT_JEWEL_KOKIRI:
GetItemEntry_Draw(play, getItemEntry); getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD);
return; break;
case DEMO_EFFECT_JEWEL_GORON:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY);
break;
case DEMO_EFFECT_JEWEL_ZORA:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE);
break;
case DEMO_EFFECT_MEDAL_FOREST:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION);
break;
case DEMO_EFFECT_MEDAL_FIRE:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION);
break;
case DEMO_EFFECT_MEDAL_WATER:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION);
break;
case DEMO_EFFECT_MEDAL_SPIRIT:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION);
break;
case DEMO_EFFECT_MEDAL_SHADOW:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION);
break;
case DEMO_EFFECT_MEDAL_LIGHT:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION);
break;
case DEMO_EFFECT_LIGHTARROW:
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS);
break;
}
if (getItemEntry.getItemId != GI_NONE) {
this->getItem.drawId = getItemEntry.gid;
func_8002EBCC(thisx, play, 0);
func_8002ED80(thisx, play, 0);
GetItemEntry_Draw(play, getItemEntry);
return;
}
} }
func_8002EBCC(thisx, play, 0); func_8002EBCC(thisx, play, 0);
func_8002ED80(thisx, play, 0); func_8002ED80(thisx, play, 0);

View File

@ -10,6 +10,7 @@
#include "scenes/indoors/nakaniwa/nakaniwa_scene.h" #include "scenes/indoors/nakaniwa/nakaniwa_scene.h"
#include "objects/object_im/object_im.h" #include "objects/object_im/object_im.h"
#include "vt.h" #include "vt.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED) #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED)
@ -318,7 +319,9 @@ void func_809853B4(DemoIm* this, PlayState* play) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, playerX, playerY, playerZ, 0, Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, playerX, playerY, playerZ, 0,
0, 0, 0xD); 0, 0, 0xD);
Item_Give(play, ITEM_MEDALLION_SHADOW); if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_SHADOW);
}
} }
void func_80985430(DemoIm* this, PlayState* play) { void func_80985430(DemoIm* this, PlayState* play) {
@ -334,7 +337,9 @@ void func_8098544C(DemoIm* this, PlayState* play) {
this->action = 1; this->action = 1;
play->csCtx.segment = D_8098786C; play->csCtx.segment = D_8098786C;
gSaveContext.cutsceneTrigger = 2; gSaveContext.cutsceneTrigger = 2;
Item_Give(play, ITEM_MEDALLION_SHADOW); if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_SHADOW);
}
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
} }
} }
@ -875,7 +880,7 @@ void func_80986B2C(PlayState* play) {
} }
play->transitionType = TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST); play->transitionType = TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST);
play->transitionTrigger = TRANS_TRIGGER_START; play->transitionTrigger = TRANS_TRIGGER_START;
func_8002DF54(play, &player->actor, 8); Player_SetCsActionWithHaltedActors(play, &player->actor, 8);
} }
} }
@ -903,40 +908,17 @@ void func_80986BF8(DemoIm* this, PlayState* play) {
} }
} }
void GivePlayerRandoRewardImpa(Actor* impa, PlayState* play, RandomizerCheck check) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY);
if (impa->parent != NULL && impa->parent->id == GET_PLAYER(play)->actor.id &&
!Flags_GetTreasure(play, 0x1F)) {
Flags_SetTreasure(play, 0x1F);
} else if (!Flags_GetTreasure(play, 0x1F) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) {
GiveItemEntryFromActor(impa, play, getItemEntry, 75.0f, 50.0f);
} else if (!Player_InBlockingCsMode(play, GET_PLAYER(play))) {
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY);
play->transitionTrigger = TRANS_TRIGGER_START;
play->transitionType = TRANS_TYPE_FADE_WHITE;
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE;
// In entrance rando have impa bring link back to the front of castle grounds
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) {
play->nextEntranceIndex = ENTR_HYRULE_CASTLE_0;
} else {
play->nextEntranceIndex = ENTR_HYRULE_FIELD_17;
}
gSaveContext.nextCutsceneIndex = 0;
}
}
void func_80986C30(DemoIm* this, PlayState* play) { void func_80986C30(DemoIm* this, PlayState* play) {
if (func_80986A5C(this, play)) { if (func_80986A5C(this, play)) {
if (IS_RANDO) { if (GameInteractor_Should(GI_VB_PLAY_ZELDAS_LULLABY_CS, true, this)) {
GivePlayerRandoRewardImpa(this, play, RC_SONG_FROM_IMPA);
} else {
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardLullabyCs); play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardLullabyCs);
gSaveContext.cutsceneTrigger = 1; gSaveContext.cutsceneTrigger = 1;
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY);
Item_Give(play, ITEM_SONG_LULLABY);
func_80985F54(this); func_80985F54(this);
} }
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY);
if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) {
Item_Give(play, ITEM_SONG_LULLABY);
}
} }
} }
@ -960,7 +942,7 @@ void func_80986D40(DemoIm* this, PlayState* play) {
if (gSaveContext.sceneSetupIndex == 6) { if (gSaveContext.sceneSetupIndex == 6) {
this->action = 19; this->action = 19;
this->drawConfig = 1; this->drawConfig = 1;
} else if ((Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) && !IS_RANDO) { } else if ((Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) && !IS_RANDO) { // SoH [Randomizer] Not sure why we're not killing impa here.
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
} else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) { } else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) {
this->action = 23; this->action = 23;

View File

@ -51,4 +51,6 @@ typedef struct DemoIm {
/* 0x02D4 */ NpcInteractInfo interactInfo; /* 0x02D4 */ NpcInteractInfo interactInfo;
} DemoIm; // size = 0x02FC } DemoIm; // size = 0x02FC
void func_80986794(DemoIm* demoIm);
#endif #endif

View File

@ -64,66 +64,23 @@ static u8 sEnergyColors[] = {
/* Forest prim */ 255, 255, 170, /* env */ 0, 200, 0, /* Forest prim */ 255, 255, 170, /* env */ 0, 200, 0,
}; };
// Translates from the barrier's actor params to their corresponding randInf flags.
RandomizerInf trialParamToRandInf(u16 params) {
switch (params) {
case KEKKAI_LIGHT:
return RAND_INF_TRIALS_DONE_LIGHT_TRIAL;
case KEKKAI_FOREST:
return RAND_INF_TRIALS_DONE_FOREST_TRIAL;
case KEKKAI_FIRE:
return RAND_INF_TRIALS_DONE_FIRE_TRIAL;
case KEKKAI_WATER:
return RAND_INF_TRIALS_DONE_WATER_TRIAL;
case KEKKAI_SPIRIT:
return RAND_INF_TRIALS_DONE_SPIRIT_TRIAL;
case KEKKAI_SHADOW:
return RAND_INF_TRIALS_DONE_SHADOW_TRIAL;
}
}
s32 DemoKekkai_CheckEventFlag(s32 params) { s32 DemoKekkai_CheckEventFlag(s32 params) {
static s32 eventFlags[] = { 0xC3, 0xBC, 0xBF, 0xBE, 0xBD, 0xAD, 0xBB }; static s32 eventFlags[] = {
EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER,
EVENTCHKINF_COMPLETED_WATER_TRIAL,
EVENTCHKINF_COMPLETED_LIGHT_TRIAL,
EVENTCHKINF_COMPLETED_FIRE_TRIAL,
EVENTCHKINF_COMPLETED_SHADOW_TRIAL,
EVENTCHKINF_COMPLETED_SPIRIT_TRIAL,
EVENTCHKINF_COMPLETED_FOREST_TRIAL,
};
if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) { if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) {
return true; return true;
} }
if (IS_RANDO && params > KEKKAI_TOWER) {
return Flags_GetRandomizerInf(trialParamToRandInf(params));
}
return Flags_GetEventChkInf(eventFlags[params]); return Flags_GetEventChkInf(eventFlags[params]);
} }
u32 TrialsDoneCount() {
u8 trialCount = 0;
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) {
trialCount++;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) {
trialCount++;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) {
trialCount++;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) {
trialCount++;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) {
trialCount++;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) {
trialCount++;
}
return trialCount;
}
void DemoKekkai_Init(Actor* thisx, PlayState* play) { void DemoKekkai_Init(Actor* thisx, PlayState* play) {
s32 pad; s32 pad;
DemoKekkai* this = (DemoKekkai*)thisx; DemoKekkai* this = (DemoKekkai*)thisx;
@ -147,13 +104,6 @@ void DemoKekkai_Init(Actor* thisx, PlayState* play) {
this->collider2.dim.radius = thisx->scale.x * 6100.0f; this->collider2.dim.radius = thisx->scale.x * 6100.0f;
this->collider2.dim.height = thisx->scale.y * 5000.0f; this->collider2.dim.height = thisx->scale.y * 5000.0f;
this->collider2.dim.yShift = 300; this->collider2.dim.yShift = 300;
if (IS_RANDO) {
if (TrialsDoneCount() == NUM_TRIALS) {
Actor_Kill(thisx);
return;
}
}
break; break;
case KEKKAI_WATER: case KEKKAI_WATER:
case KEKKAI_LIGHT: case KEKKAI_LIGHT:
@ -161,10 +111,6 @@ void DemoKekkai_Init(Actor* thisx, PlayState* play) {
case KEKKAI_SHADOW: case KEKKAI_SHADOW:
case KEKKAI_SPIRIT: case KEKKAI_SPIRIT:
case KEKKAI_FOREST: case KEKKAI_FOREST:
if (IS_RANDO && Flags_GetRandomizerInf(trialParamToRandInf(thisx->params))) {
Actor_Kill(thisx);
return;
}
this->energyAlpha = 1.0f; this->energyAlpha = 1.0f;
this->orbScale = 1.0f; this->orbScale = 1.0f;
Actor_SetScale(thisx, 0.1f); Actor_SetScale(thisx, 0.1f);
@ -265,18 +211,10 @@ void DemoKekkai_Update(Actor* thisx, PlayState* play2) {
} }
void DemoKekkai_TrialBarrierDispel(Actor* thisx, PlayState* play) { void DemoKekkai_TrialBarrierDispel(Actor* thisx, PlayState* play) {
static s32 eventFlags[] = { 0xC3, 0xBC, 0xBF, 0xBE, 0xBD, 0xAD, 0xBB };
static u16 csFrames[] = { 0, 280, 280, 280, 280, 280, 280 }; static u16 csFrames[] = { 0, 280, 280, 280, 280, 280, 280 };
s32 pad; s32 pad;
DemoKekkai* this = (DemoKekkai*)thisx; DemoKekkai* this = (DemoKekkai*)thisx;
if (IS_RANDO) {
Flags_SetRandomizerInf(trialParamToRandInf(thisx->params));
// May or may not be needed. Not sure if needed for anything
// that randoInf isn't already covering. Leaving it for safety.
Flags_SetEventChkInf(eventFlags[thisx->params]);
}
if (play->csCtx.frames == csFrames[this->actor.params]) { if (play->csCtx.frames == csFrames[this->actor.params]) {
func_800F3F3C(0xA); func_800F3F3C(0xA);
} }

View File

@ -9,6 +9,7 @@
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
#include "objects/object_sa/object_sa.h" #include "objects/object_sa/object_sa.h"
#include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/Enhancements/boss-rush/BossRush.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "vt.h" #include "vt.h"
@ -241,7 +242,9 @@ void func_8098E8C8(DemoSa* this, PlayState* play) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
0xB); 0xB);
Item_Give(play, ITEM_MEDALLION_FOREST); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_FOREST);
}
} }
void func_8098E944(DemoSa* this, PlayState* play) { void func_8098E944(DemoSa* this, PlayState* play) {
@ -258,7 +261,9 @@ void func_8098E960(DemoSa* this, PlayState* play) {
this->action = 1; this->action = 1;
play->csCtx.segment = D_8099010C; play->csCtx.segment = D_8099010C;
gSaveContext.cutsceneTrigger = 2; gSaveContext.cutsceneTrigger = 2;
Item_Give(play, ITEM_MEDALLION_FOREST); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_FOREST);
}
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
} else { } else {
this->action = 1; this->action = 1;

View File

@ -20,7 +20,6 @@ void DoorAna_WaitClosed(DoorAna* this, PlayState* play);
void DoorAna_WaitOpen(DoorAna* this, PlayState* play); void DoorAna_WaitOpen(DoorAna* this, PlayState* play);
void DoorAna_GrabPlayer(DoorAna* this, PlayState* play); void DoorAna_GrabPlayer(DoorAna* this, PlayState* play);
s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play);
void Grotto_OverrideActorEntrance(Actor* thisx); void Grotto_OverrideActorEntrance(Actor* thisx);
const ActorInit Door_Ana_InitVars = { const ActorInit Door_Ana_InitVars = {

View File

@ -23,6 +23,7 @@
#include "objects/object_menkuri_objects/object_menkuri_objects.h" #include "objects/object_menkuri_objects/object_menkuri_objects.h"
#include "objects/object_demo_kekkai/object_demo_kekkai.h" #include "objects/object_demo_kekkai/object_demo_kekkai.h"
#include "objects/object_ouke_haka/object_ouke_haka.h" #include "objects/object_ouke_haka/object_ouke_haka.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
@ -354,9 +355,11 @@ void func_80996A54(DoorShutter* this, PlayState* play) {
if (Flags_GetClear(play, this->dyna.actor.room) || Flags_GetTempClear(play, this->dyna.actor.room)) { if (Flags_GetClear(play, this->dyna.actor.room) || Flags_GetTempClear(play, this->dyna.actor.room)) {
Flags_SetClear(play, this->dyna.actor.room); Flags_SetClear(play, this->dyna.actor.room);
DoorShutter_SetupAction(this, func_80997150); DoorShutter_SetupAction(this, func_80997150);
OnePointCutscene_Attention(play, &this->dyna.actor); if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor); OnePointCutscene_Attention(play, &this->dyna.actor);
this->unk_16F = -100; OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor);
this->unk_16F = -100;
}
} else if (func_809968D4(this, play) != 0) { } else if (func_809968D4(this, play) != 0) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
@ -470,8 +473,10 @@ void func_80996EE8(DoorShutter* this, PlayState* play) {
if (func_80996E08(this, play, 1.0f)) { if (func_80996E08(this, play, 1.0f)) {
if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) {
DoorShutter_SetupAction(this, func_80997150); DoorShutter_SetupAction(this, func_80997150);
OnePointCutscene_Attention(play, &this->dyna.actor); if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
this->unk_16F = -100; OnePointCutscene_Attention(play, &this->dyna.actor);
this->unk_16F = -100;
}
} else if (func_809968D4(this, play)) { } else if (func_809968D4(this, play)) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
// Jabu navi text for switch doors is different // Jabu navi text for switch doors is different
@ -555,7 +560,7 @@ void func_80997220(DoorShutter* this, PlayState* play) {
this->dyna.actor.velocity.y = 0.0f; this->dyna.actor.velocity.y = 0.0f;
if (DoorShutter_SetupDoor(this, play) && !(player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { if (DoorShutter_SetupDoor(this, play) && !(player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) {
DoorShutter_SetupAction(this, func_80997568); DoorShutter_SetupAction(this, func_80997568);
func_8002DF54(play, NULL, 2); Player_SetCsActionWithHaltedActors(play, NULL, 2);
} }
} }
@ -589,7 +594,7 @@ void func_80997528(DoorShutter* this, PlayState* play) {
void func_80997568(DoorShutter* this, PlayState* play) { void func_80997568(DoorShutter* this, PlayState* play) {
if (this->unk_16F++ > 30) { if (this->unk_16F++ > 30) {
func_8002DF54(play, NULL, 7); Player_SetCsActionWithHaltedActors(play, NULL, 7);
DoorShutter_SetupDoor(this, play); DoorShutter_SetupDoor(this, play);
} }
} }

View File

@ -2,6 +2,7 @@
#include "objects/object_warp1/object_warp1.h" #include "objects/object_warp1/object_warp1.h"
#include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h"
#include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/Enhancements/boss-rush/BossRush.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS 0 #define FLAGS 0
@ -487,44 +488,6 @@ s32 DoorWarp1_PlayerInRange(DoorWarp1* this, PlayState* play) {
return ret; return ret;
} }
void GivePlayerRandoReward(DoorWarp1* this, Player* player, PlayState* play, u8 ruto, u8 adult) {
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, 0x00, GI_NONE);
if (this->actor.parent != NULL && this->actor.parent->id == GET_PLAYER(play)->actor.id &&
!Flags_GetTreasure(play, 0x1F)) {
Flags_SetTreasure(play, 0x1F);
} else if (!Flags_GetTreasure(play, 0x1F)) {
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 100.0f);
} else if (!Player_InBlockingCsMode(play, GET_PLAYER(play))) {
if (adult) {
OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM);
func_8002DF54(play, &this->actor, 10);
player->unk_450.x = this->actor.world.pos.x;
player->unk_450.z = this->actor.world.pos.z;
this->unk_1B2 = 20;
DoorWarp1_SetupAction(this, func_8099A508);
} else {
if (ruto) {
this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED;
func_8002DF54(play, &this->actor, 10);
this->unk_1B2 = 1;
DoorWarp1_SetupAction(this, func_80999EE0);
} else {
Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
OnePointCutscene_Init(play, 0x25E7, 999, &this->actor, MAIN_CAM);
func_8002DF54(play, &this->actor, 10);
player->unk_450.x = this->actor.world.pos.x;
player->unk_450.z = this->actor.world.pos.z;
this->unk_1B2 = 1;
DoorWarp1_SetupAction(this, DoorWarp1_ChildWarpOut);
}
}
}
}
void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) { void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) {
Player* player; Player* player;
@ -532,16 +495,11 @@ void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) {
if (DoorWarp1_PlayerInRange(this, play)) { if (DoorWarp1_PlayerInRange(this, play)) {
player = GET_PLAYER(play); player = GET_PLAYER(play);
if (IS_RANDO) {
GivePlayerRandoReward(this, player, play, 0, 0);
return;
}
Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0, Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8); &D_801333E8);
OnePointCutscene_Init(play, 0x25E7, 999, &this->actor, MAIN_CAM); OnePointCutscene_Init(play, 0x25E7, 999, &this->actor, MAIN_CAM);
func_8002DF54(play, &this->actor, 10); Player_SetCsActionWithHaltedActors(play, &this->actor, 10);
player->unk_450.x = this->actor.world.pos.x; player->unk_450.x = this->actor.world.pos.x;
player->unk_450.z = this->actor.world.pos.z; player->unk_450.z = this->actor.world.pos.z;
@ -570,36 +528,26 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, PlayState* play) {
osSyncPrintf("\n\n\nじかんがきたからおーしまい fade_direction=[%d]", play->transitionTrigger, TRANS_TRIGGER_START); osSyncPrintf("\n\n\nじかんがきたからおーしまい fade_direction=[%d]", play->transitionTrigger, TRANS_TRIGGER_START);
if (play->sceneNum == SCENE_DODONGOS_CAVERN_BOSS) { if (play->sceneNum == SCENE_DODONGOS_CAVERN_BOSS) {
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_GORON_RUBY)) {
if (IS_RANDO) {
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5;
gSaveContext.nextCutsceneIndex = 0;
} else {
Item_Give(play, ITEM_GORON_RUBY); Item_Give(play, ITEM_GORON_RUBY);
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0;
gSaveContext.nextCutsceneIndex = 0xFFF1;
} }
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0;
gSaveContext.nextCutsceneIndex = 0xFFF1;
} else { } else {
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5;
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
} }
} else if (play->sceneNum == SCENE_DEKU_TREE_BOSS) { } else if (play->sceneNum == SCENE_DEKU_TREE_BOSS) {
if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || IS_RANDO) { if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD), EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) {
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP); Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_KOKIRI_EMERALD)) {
if (IS_RANDO) {
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11;
gSaveContext.nextCutsceneIndex = 0;
// Skip Mido complaining about dead Deku tree
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH);
} else {
Item_Give(play, ITEM_KOKIRI_EMERALD); Item_Give(play, ITEM_KOKIRI_EMERALD);
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0;
gSaveContext.nextCutsceneIndex = 0xFFF1;
} }
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0;
gSaveContext.nextCutsceneIndex = 0xFFF1;
} else { } else {
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11; play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11;
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
@ -635,14 +583,8 @@ void DoorWarp1_RutoWarpIdle(DoorWarp1* this, PlayState* play) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_WARP_HOLE - SFX_FLAG); Audio_PlayActorSound2(&this->actor, NA_SE_EV_WARP_HOLE - SFX_FLAG);
if (this->rutoWarpState != WARP_BLUE_RUTO_STATE_INITIAL && DoorWarp1_PlayerInRange(this, play)) { if (this->rutoWarpState != WARP_BLUE_RUTO_STATE_INITIAL && DoorWarp1_PlayerInRange(this, play)) {
if (IS_RANDO) {
GivePlayerRandoReward(this, GET_PLAYER(play), play, 1, 0);
return;
}
this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED; this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED;
func_8002DF54(play, &this->actor, 10); Player_SetCsActionWithHaltedActors(play, &this->actor, 10);
this->unk_1B2 = 1; this->unk_1B2 = 1;
DoorWarp1_SetupAction(this, func_80999EE0); DoorWarp1_SetupAction(this, func_80999EE0);
} }
@ -670,9 +612,8 @@ void func_80999EE0(DoorWarp1* this, PlayState* play) {
Play_CameraSetAtEye(play, sRutoWarpSubCamId, &at, &eye); Play_CameraSetAtEye(play, sRutoWarpSubCamId, &at, &eye);
Play_CameraSetFov(play, sRutoWarpSubCamId, 90.0f); Play_CameraSetFov(play, sRutoWarpSubCamId, 90.0f);
this->rutoWarpState = WARP_BLUE_RUTO_STATE_TALKING; this->rutoWarpState = WARP_BLUE_RUTO_STATE_TALKING;
if (!IS_RANDO) { // TODO: Why was this disabled in rando?
Message_StartTextbox(play, 0x4022, NULL); Message_StartTextbox(play, 0x4022, NULL);
}
DoorWarp1_SetupAction(this, func_80999FE4); DoorWarp1_SetupAction(this, func_80999FE4);
} }
} }
@ -704,17 +645,14 @@ void DoorWarp1_RutoWarpOut(DoorWarp1* this, PlayState* play) {
this->warpTimer++; this->warpTimer++;
if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) { if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) {
Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, true, EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP);
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_ZORA_SAPPHIRE)) {
if (IS_RANDO) { Item_Give(play, ITEM_ZORA_SAPPHIRE);
play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0; }
gSaveContext.nextCutsceneIndex = 0;
} else {
Item_Give(play, ITEM_ZORA_SAPPHIRE);
play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0;
gSaveContext.nextCutsceneIndex = 0xFFF0; gSaveContext.nextCutsceneIndex = 0xFFF0;
} }
play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0;
if (IS_RANDO && (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || if (IS_RANDO && (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) { Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) {
@ -767,13 +705,8 @@ void DoorWarp1_AdultWarpIdle(DoorWarp1* this, PlayState* play) {
player = GET_PLAYER(play); player = GET_PLAYER(play);
if (IS_RANDO) {
GivePlayerRandoReward(this, player, play, 0, 1);
return;
}
OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM); OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM);
func_8002DF54(play, &this->actor, 10); Player_SetCsActionWithHaltedActors(play, &this->actor, 10);
player->unk_450.x = this->actor.world.pos.x; player->unk_450.x = this->actor.world.pos.x;
player->unk_450.z = this->actor.world.pos.z; player->unk_450.z = this->actor.world.pos.z;
this->unk_1B2 = 20; this->unk_1B2 = 20;
@ -829,19 +762,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
if (IS_BOSS_RUSH) { if (IS_BOSS_RUSH) {
BossRush_HandleBlueWarp(play, this->actor.world.pos.x, this->actor.world.pos.z); BossRush_HandleBlueWarp(play, this->actor.world.pos.x, this->actor.world.pos.z);
} else if (play->sceneNum == SCENE_FOREST_TEMPLE_BOSS) { } else if (play->sceneNum == SCENE_FOREST_TEMPLE_BOSS) {
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) {
Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FOREST)) {
if (IS_RANDO) {
play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_3;
gSaveContext.nextCutsceneIndex = 0;
} else {
Item_Give(play, ITEM_MEDALLION_FOREST); Item_Give(play, ITEM_MEDALLION_FOREST);
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0;
gSaveContext.chamberCutsceneNum = CHAMBER_CS_FOREST;
} }
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0;
gSaveContext.chamberCutsceneNum = CHAMBER_CS_FOREST;
} else { } else {
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_2; play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_2;
@ -851,20 +779,13 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
} }
} else if (play->sceneNum == SCENE_FIRE_TEMPLE_BOSS) { } else if (play->sceneNum == SCENE_FIRE_TEMPLE_BOSS) {
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) {
Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FIRE)) {
if (IS_RANDO) {
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5;
gSaveContext.nextCutsceneIndex = 0;
// Change Death Mountain cloud since we aren't warping to the cutscene
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
} else {
Item_Give(play, ITEM_MEDALLION_FIRE); Item_Give(play, ITEM_MEDALLION_FIRE);
play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0;
gSaveContext.nextCutsceneIndex = 0xFFF3;
} }
play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0;
gSaveContext.nextCutsceneIndex = 0xFFF3;
} else { } else {
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_4; play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_4;
@ -874,21 +795,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
} }
} else if (play->sceneNum == SCENE_WATER_TEMPLE_BOSS) { } else if (play->sceneNum == SCENE_WATER_TEMPLE_BOSS) {
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_WATER)) {
if (IS_RANDO) {
play->nextEntranceIndex = ENTR_LAKE_HYLIA_9;
gSaveContext.nextCutsceneIndex = 0;
// Fill Lake Hylia since we aren't warping to the cutscene
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
} else {
Item_Give(play, ITEM_MEDALLION_WATER); Item_Give(play, ITEM_MEDALLION_WATER);
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0;
gSaveContext.chamberCutsceneNum = CHAMBER_CS_WATER;
} }
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0;
gSaveContext.chamberCutsceneNum = CHAMBER_CS_WATER;
} else { } else {
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
play->nextEntranceIndex = ENTR_LAKE_HYLIA_8; play->nextEntranceIndex = ENTR_LAKE_HYLIA_8;
@ -898,18 +812,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
} }
} else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { } else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) {
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) || IS_RANDO) { if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) {
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE);
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) {
if (IS_RANDO) {
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_8;
gSaveContext.nextCutsceneIndex = 0;
} else {
Item_Give(play, ITEM_MEDALLION_SPIRIT); Item_Give(play, ITEM_MEDALLION_SPIRIT);
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0;
gSaveContext.chamberCutsceneNum = CHAMBER_CS_SPIRIT;
} }
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0;
gSaveContext.chamberCutsceneNum = CHAMBER_CS_SPIRIT;
} else { } else {
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_5; play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_5;
@ -919,18 +829,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
} }
} else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { } else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) {
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) || IS_RANDO) { if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) {
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE);
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) {
if (IS_RANDO) {
play->nextEntranceIndex = ENTR_GRAVEYARD_8;
gSaveContext.nextCutsceneIndex = 0;
} else {
Item_Give(play, ITEM_MEDALLION_SHADOW); Item_Give(play, ITEM_MEDALLION_SHADOW);
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0;
gSaveContext.chamberCutsceneNum = CHAMBER_CS_SHADOW;
} }
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0;
gSaveContext.chamberCutsceneNum = CHAMBER_CS_SHADOW;
} else { } else {
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
play->nextEntranceIndex = ENTR_GRAVEYARD_7; play->nextEntranceIndex = ENTR_GRAVEYARD_7;

View File

@ -7,6 +7,7 @@
#include "z_elf_msg.h" #include "z_elf_msg.h"
#include "vt.h" #include "vt.h"
#include "overlays/actors/ovl_En_Elf/z_en_elf.h" #include "overlays/actors/ovl_En_Elf/z_en_elf.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
@ -110,7 +111,7 @@ void ElfMsg_Destroy(Actor* thisx, PlayState* play) {
s32 ElfMsg_GetMessageId(ElfMsg* this) { s32 ElfMsg_GetMessageId(ElfMsg* this) {
// Negative message ID forces link to talk to Navi // Negative message ID forces link to talk to Navi
if (this->actor.params & 0x8000 || CVarGetInteger("gNoForcedNavi", 0) != 0) { if (this->actor.params & 0x8000) {
return (this->actor.params & 0xFF) + 0x100; return (this->actor.params & 0xFF) + 0x100;
} else { } else {
return -((this->actor.params & 0xFF) + 0x100); return -((this->actor.params & 0xFF) + 0x100);
@ -125,8 +126,10 @@ void ElfMsg_CallNaviCuboid(ElfMsg* this, PlayState* play) {
(this->actor.world.pos.y <= player->actor.world.pos.y) && (this->actor.world.pos.y <= player->actor.world.pos.y) &&
((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y)) && ((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y)) &&
(fabsf(player->actor.world.pos.z - this->actor.world.pos.z) < (100.0f * this->actor.scale.z))) { (fabsf(player->actor.world.pos.z - this->actor.world.pos.z) < (100.0f * this->actor.scale.z))) {
player->naviTextId = ElfMsg_GetMessageId(this); if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) {
navi->elfMsg = this; player->naviTextId = ElfMsg_GetMessageId(this);
navi->elfMsg = this;
}
} }
} }
@ -145,8 +148,10 @@ void ElfMsg_CallNaviCylinder(ElfMsg* this, PlayState* play) {
if (ElfMsg_WithinXZDistance(&player->actor.world.pos, &this->actor.world.pos, this->actor.scale.x * 100.0f) && if (ElfMsg_WithinXZDistance(&player->actor.world.pos, &this->actor.world.pos, this->actor.scale.x * 100.0f) &&
(this->actor.world.pos.y <= player->actor.world.pos.y) && (this->actor.world.pos.y <= player->actor.world.pos.y) &&
((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y))) { ((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y))) {
player->naviTextId = ElfMsg_GetMessageId(this); if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) {
navi->elfMsg = this; player->naviTextId = ElfMsg_GetMessageId(this);
navi->elfMsg = this;
}
} }
} }

View File

@ -6,6 +6,7 @@
#include "z_en_ani.h" #include "z_en_ani.h"
#include "objects/object_ani/object_ani.h" #include "objects/object_ani/object_ani.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
@ -119,7 +120,7 @@ void func_809B0524(EnAni* this, PlayState* play) {
} }
void func_809B0558(EnAni* this, PlayState* play) { void func_809B0558(EnAni* this, PlayState* play) {
if (Actor_HasParent(&this->actor, play)) { if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) {
this->actor.parent = NULL; this->actor.parent = NULL;
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
EnAni_SetupAction(this, func_809B04F0); EnAni_SetupAction(this, func_809B04F0);
@ -128,11 +129,8 @@ void func_809B0558(EnAni* this, PlayState* play) {
} }
Flags_SetItemGetInf(ITEMGETINF_15); Flags_SetItemGetInf(ITEMGETINF_15);
} else { } else {
if (!IS_RANDO) { if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) {
func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f);
} else {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE);
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 200.0f);
} }
} }
} }
@ -142,11 +140,8 @@ void func_809B05F0(EnAni* this, PlayState* play) {
EnAni_SetupAction(this, func_809B0558); EnAni_SetupAction(this, func_809B0558);
} }
if (!IS_RANDO) { if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) {
func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f);
} else {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE);
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 200.0f);
} }
} }

View File

@ -295,7 +295,7 @@ void EnBomBowMan_RunGame(EnBomBowlMan* this, PlayState* play) {
Message_StartTextbox(play, this->actor.textId, NULL); Message_StartTextbox(play, this->actor.textId, NULL);
if (this->gameResult == 2) { if (this->gameResult == 2) {
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
} }
this->actionFunc = EnBomBowlMan_HandlePlayChoice; this->actionFunc = EnBomBowlMan_HandlePlayChoice;
} else { } else {
@ -345,7 +345,7 @@ void EnBomBowlMan_HandlePlayChoice(EnBomBowlMan* this, PlayState* play) {
Message_ContinueTextbox(play, this->actor.textId); Message_ContinueTextbox(play, this->actor.textId);
this->dialogState = TEXT_STATE_EVENT; this->dialogState = TEXT_STATE_EVENT;
OnePointCutscene_Init(play, 8010, -99, NULL, MAIN_CAM); OnePointCutscene_Init(play, 8010, -99, NULL, MAIN_CAM);
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
this->actionFunc = EnBomBowMan_SetupChooseShowPrize; this->actionFunc = EnBomBowMan_SetupChooseShowPrize;
} }
} else { } else {
@ -381,11 +381,11 @@ void func_809C41FC(EnBomBowlMan* this, PlayState* play) {
Message_ContinueTextbox(play, this->actor.textId); Message_ContinueTextbox(play, this->actor.textId);
this->dialogState = TEXT_STATE_EVENT; this->dialogState = TEXT_STATE_EVENT;
OnePointCutscene_Init(play, 8010, -99, NULL, MAIN_CAM); OnePointCutscene_Init(play, 8010, -99, NULL, MAIN_CAM);
func_8002DF54(play, NULL, 8); Player_SetCsActionWithHaltedActors(play, NULL, 8);
this->actionFunc = EnBomBowMan_SetupChooseShowPrize; this->actionFunc = EnBomBowMan_SetupChooseShowPrize;
} else { } else {
if (this->gameResult == 2) { if (this->gameResult == 2) {
func_8002DF54(play, NULL, 7); Player_SetCsActionWithHaltedActors(play, NULL, 7);
} }
this->actionFunc = EnBomBowMan_SetupRunGame; this->actionFunc = EnBomBowMan_SetupRunGame;
} }
@ -509,7 +509,7 @@ void EnBomBowlMan_BeginPlayGame(EnBomBowlMan* this, PlayState* play) {
// "Wow" // "Wow"
osSyncPrintf(VT_FGCOL(YELLOW) "☆ わー ☆ %d\n" VT_RST, play->bombchuBowlingStatus); osSyncPrintf(VT_FGCOL(YELLOW) "☆ わー ☆ %d\n" VT_RST, play->bombchuBowlingStatus);
func_8002DF54(play, NULL, 7); Player_SetCsActionWithHaltedActors(play, NULL, 7);
this->actionFunc = EnBomBowMan_SetupRunGame; this->actionFunc = EnBomBowMan_SetupRunGame;
} }
} }

Some files were not shown because too many files have changed in this diff Show More