summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick12115 <115201185+Patrick12115@users.noreply.github.com>2023-04-02 21:11:08 -0400
committerGitHub <noreply@github.com>2023-04-02 21:11:08 -0400
commit2af952b1803088766bb2a2dbbddaa33ac32f999b (patch)
tree4d04a86094df65b7229ccd353e929e5372b90b27
parent94ad837c0214268ec9c447987bee5133373cefdf (diff)
[Time Saver Enhancement] Nighttime GS Always Spawn (#2611)
* Nighttime GS Always Spawn * add hook onSceneSpawnActors * implement onSceneSpawnActors hook to spawn GS in various day scenes * handle the kak tree skull during the day * Update mods.cpp * Add the & * Fixes * Update soh/soh/Enhancements/mods.cpp Co-authored-by: Adam Bird <Archez@users.noreply.github.com> --------- Co-authored-by: Adam Bird <archez39@me.com> Co-authored-by: Adam Bird <Archez@users.noreply.github.com>
-rw-r--r--soh/soh/Enhancements/game-interactor/GameInteractor.h1
-rw-r--r--soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp4
-rw-r--r--soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h1
-rw-r--r--soh/soh/Enhancements/mods.cpp59
-rw-r--r--soh/soh/Enhancements/presets.h1
-rw-r--r--soh/soh/GameMenuBar.cpp2
-rw-r--r--soh/src/code/z_actor.c1
-rw-r--r--soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c2
-rw-r--r--soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c9
9 files changed, 79 insertions, 1 deletions
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h
index 59e322ed9..c2dd2c05f 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h
@@ -148,6 +148,7 @@ public:
DEFINE_HOOK(OnSaleEnd, void(GetItemEntry itemEntry));
DEFINE_HOOK(OnTransitionEnd, void(int16_t sceneNum));
DEFINE_HOOK(OnSceneInit, void(int16_t sceneNum));
+ DEFINE_HOOK(OnSceneSpawnActors, void());
DEFINE_HOOK(OnPlayerUpdate, void());
DEFINE_HOOK(OnOcarinaSongAction, void());
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
index 90074f4ff..e5159849e 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
@@ -30,6 +30,10 @@ void GameInteractor_ExecuteOnSceneInitHooks(int16_t sceneNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneInit>(sceneNum);
}
+void GameInteractor_ExecuteOnSceneSpawnActors() {
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneSpawnActors>();
+}
+
void GameInteractor_ExecuteOnPlayerUpdate() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerUpdate>();
}
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
index 7c9661cf0..b8029914f 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
@@ -8,6 +8,7 @@ extern "C" void GameInteractor_ExecuteOnItemReceiveHooks(GetItemEntry itemEntry)
extern "C" void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry);
extern "C" void GameInteractor_ExecuteOnTransitionEndHooks(int16_t sceneNum);
extern "C" void GameInteractor_ExecuteOnSceneInit(int16_t sceneNum);
+extern "C" void GameInteractor_ExecuteOnSceneSpawnActors();
extern "C" void GameInteractor_ExecuteOnPlayerUpdate();
extern "C" void GameInteractor_ExecuteOnOcarinaSongAction();
extern "C" void GameInteractor_ExecuteOnActorUpdate(void* actor);
diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp
index cffd00ffe..cdbacdf06 100644
--- a/soh/soh/Enhancements/mods.cpp
+++ b/soh/soh/Enhancements/mods.cpp
@@ -14,6 +14,8 @@ extern PlayState* gPlayState;
extern void Play_PerformSave(PlayState* play);
extern s32 Health_ChangeBy(PlayState* play, s16 healthChange);
extern void Rupees_ChangeBy(s16 rupeeChange);
+extern Actor* Actor_Spawn(ActorContext* actorCtx, PlayState* play, s16 actorId, f32 posX, f32 posY, f32 posZ,
+ s16 rotX, s16 rotY, s16 rotZ, s16 params, s16 canRandomize);
extern void Inventory_ChangeEquipment(s16 equipment, u16 value);
}
bool performDelayedSave = false;
@@ -350,6 +352,62 @@ void RegisterRupeeDash() {
});
}
+struct DayTimeGoldSkulltulas {
+ uint16_t scene;
+ uint16_t room;
+ bool forChild;
+ std::vector<ActorEntry> actorEntries;
+};
+
+using DayTimeGoldSkulltulasList = std::vector<DayTimeGoldSkulltulas>;
+
+void RegisterDaytimeGoldSkultullas() {
+ GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneSpawnActors>([]() {
+ if (!CVarGetInteger("gNightGSAlwaysSpawn", 0)) {
+ return;
+ }
+
+ // Gold Skulltulas that are not part of the scene actor list during the day
+ // Actor values copied from the night time scene actor list
+ static const DayTimeGoldSkulltulasList dayTimeGoldSkulltulas = {
+ // Graveyard
+ { SCENE_SPOT02, 1, true, { { ACTOR_EN_SW, { 156, 315, 795 }, { 16384, -32768, 0 }, -20096 } } },
+ // ZF
+ { SCENE_SPOT08, 0, true, { { ACTOR_EN_SW, { -1891, 187, 1911 }, { 16384, 18022, 0 }, -19964 } } },
+ // GF
+ { SCENE_SPOT12, 0, false, { { ACTOR_EN_SW, { 1598, 999, -2008 }, { 16384, -16384, 0 }, -19198 } } },
+ { SCENE_SPOT12, 1, false, { { ACTOR_EN_SW, { 3377, 1734, -4935 }, { 16384, 0, 0 }, -19199 } } },
+ // Kak
+ { SCENE_SPOT01, 0, false, { { ACTOR_EN_SW, { -18, 540, 1800 }, { 0, -32768, 0 }, -20160 } } },
+ { SCENE_SPOT01,
+ 0,
+ true,
+ { { ACTOR_EN_SW, { -465, 377, -888 }, { 0, 28217, 0 }, -20222 },
+ { ACTOR_EN_SW, { 5, 686, -171 }, { 0, -32768, 0 }, -20220 },
+ { ACTOR_EN_SW, { 324, 270, 905 }, { 16384, 0, 0 }, -20216 },
+ { ACTOR_EN_SW, { -602, 120, 1120 }, { 16384, 0, 0 }, -20208 } } },
+ // LLR
+ { SCENE_SPOT20,
+ 0,
+ true,
+ { { ACTOR_EN_SW, { -2344, 180, 672 }, { 16384, 22938, 0 }, -29695 },
+ { ACTOR_EN_SW, { 808, 48, 326 }, { 16384, 0, 0 }, -29694 },
+ { ACTOR_EN_SW, { 997, 286, -2698 }, { 16384, -16384, 0 }, -29692 } } },
+ };
+
+ for (const auto& dayTimeGS : dayTimeGoldSkulltulas) {
+ if (IS_DAY && dayTimeGS.forChild == LINK_IS_CHILD && dayTimeGS.scene == gPlayState->sceneNum &&
+ dayTimeGS.room == gPlayState->roomCtx.curRoom.num) {
+ for (const auto& actorEntry : dayTimeGS.actorEntries) {
+ Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorEntry.id, actorEntry.pos.x, actorEntry.pos.y,
+ actorEntry.pos.z, actorEntry.rot.x, actorEntry.rot.y, actorEntry.rot.z,
+ actorEntry.params, false);
+ }
+ }
+ }
+ });
+}
+
void RegisterHyperBosses() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
// Run the update function a second time to make bosses move and act twice as fast.
@@ -450,6 +508,7 @@ void InitMods() {
RegisterSwitchAge();
RegisterOcarinaTimeTravel();
RegisterAutoSave();
+ RegisterDaytimeGoldSkultullas();
RegisterRupeeDash();
RegisterHyperBosses();
RegisterBonkDamage();
diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h
index cf617021e..1a2319cdd 100644
--- a/soh/soh/Enhancements/presets.h
+++ b/soh/soh/Enhancements/presets.h
@@ -181,6 +181,7 @@ const std::vector<const char*> enhancementsCvars = {
"gStaticExplosionRadius",
"gNoInputForCredits",
"gFastFarores",
+ "gNightGSAlwaysSpawn",
};
const std::vector<const char*> randomizerCvars = {
diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp
index 075ea4134..7b9cbb288 100644
--- a/soh/soh/GameMenuBar.cpp
+++ b/soh/soh/GameMenuBar.cpp
@@ -354,6 +354,8 @@ namespace GameMenuBar {
"to the guard next to the gate.");
UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false);
UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell.");
+ UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false);
+ UIWidgets::Tooltip("Nighttime Skulltulas will spawn during both day and night.");
UIWidgets::PaddedEnhancementCheckbox("Dampe Appears All Night", "gDampeAllNight", true, false);
UIWidgets::Tooltip("Makes Dampe appear anytime during it's night, not just his usual working hours.");
UIWidgets::PaddedEnhancementCheckbox("Time Travel with the Song of Time", "gTimeTravel", true, false);
diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c
index ef7708919..26e0b6dfe 100644
--- a/soh/src/code/z_actor.c
+++ b/soh/src/code/z_actor.c
@@ -2516,6 +2516,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
Actor_SpawnEntry(&play->actorCtx, actorEntry++, play);
}
play->numSetupActors = 0;
+ GameInteractor_ExecuteOnSceneSpawnActors();
}
if (actorCtx->unk_02 != 0) {
diff --git a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c
index c26e017cc..db864d403 100644
--- a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c
+++ b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c
@@ -550,7 +550,7 @@ void func_80B0D590(EnSw* this, PlayState* play) {
this->collider.elements[0].info.ocElemFlags = 1;
}
- Math_ApproachF(&this->actor.scale.x, !IS_DAY ? 0.02f : 0.0f, 0.2f, 0.01f);
+ Math_ApproachF(&this->actor.scale.x, !IS_DAY || CVarGetInteger("gNightGSAlwaysSpawn", 0) ? 0.02f : 0.0f, 0.2f, 0.01f);
Actor_SetScale(&this->actor, this->actor.scale.x);
}
diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c
index abada7c12..d84e53756 100644
--- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c
+++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c
@@ -173,6 +173,15 @@ void EnWood02_Init(Actor* thisx, PlayState* play2) {
f32 floorY;
s16 extraRot;
+ // The tree in Kakariko's day scene does not have the same params to spawn the GS
+ // as the night scene, For the always spawn GS enhancement we apply the needed
+ // params to have the GS drop when bonking
+ if ((this->actor.params & 0xFF) == WOOD_TREE_CONICAL_MEDIUM && IS_DAY &&
+ play->sceneNum == SCENE_SPOT01 && CVarGetInteger("gNightGSAlwaysSpawn", 0)) {
+ this->actor.params = 0x2001;
+ this->actor.home.rot.z = 0x71;
+ }
+
spawnType = WOOD_SPAWN_NORMAL;
actorScale = 1.0f;
this->unk_14C = (this->actor.params >> 8) & 0xFF;