mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-29 04:42:18 -05:00
[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>
This commit is contained in:
parent
94ad837c02
commit
2af952b180
@ -148,6 +148,7 @@ public:
|
|||||||
DEFINE_HOOK(OnSaleEnd, void(GetItemEntry itemEntry));
|
DEFINE_HOOK(OnSaleEnd, void(GetItemEntry itemEntry));
|
||||||
DEFINE_HOOK(OnTransitionEnd, void(int16_t sceneNum));
|
DEFINE_HOOK(OnTransitionEnd, void(int16_t sceneNum));
|
||||||
DEFINE_HOOK(OnSceneInit, void(int16_t sceneNum));
|
DEFINE_HOOK(OnSceneInit, void(int16_t sceneNum));
|
||||||
|
DEFINE_HOOK(OnSceneSpawnActors, void());
|
||||||
DEFINE_HOOK(OnPlayerUpdate, void());
|
DEFINE_HOOK(OnPlayerUpdate, void());
|
||||||
DEFINE_HOOK(OnOcarinaSongAction, void());
|
DEFINE_HOOK(OnOcarinaSongAction, void());
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@ void GameInteractor_ExecuteOnSceneInitHooks(int16_t sceneNum) {
|
|||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneInit>(sceneNum);
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneInit>(sceneNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameInteractor_ExecuteOnSceneSpawnActors() {
|
||||||
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneSpawnActors>();
|
||||||
|
}
|
||||||
|
|
||||||
void GameInteractor_ExecuteOnPlayerUpdate() {
|
void GameInteractor_ExecuteOnPlayerUpdate() {
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerUpdate>();
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerUpdate>();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ extern "C" void GameInteractor_ExecuteOnItemReceiveHooks(GetItemEntry itemEntry)
|
|||||||
extern "C" void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry);
|
extern "C" void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry);
|
||||||
extern "C" void GameInteractor_ExecuteOnTransitionEndHooks(int16_t sceneNum);
|
extern "C" void GameInteractor_ExecuteOnTransitionEndHooks(int16_t sceneNum);
|
||||||
extern "C" void GameInteractor_ExecuteOnSceneInit(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_ExecuteOnPlayerUpdate();
|
||||||
extern "C" void GameInteractor_ExecuteOnOcarinaSongAction();
|
extern "C" void GameInteractor_ExecuteOnOcarinaSongAction();
|
||||||
extern "C" void GameInteractor_ExecuteOnActorUpdate(void* actor);
|
extern "C" void GameInteractor_ExecuteOnActorUpdate(void* actor);
|
||||||
|
@ -14,6 +14,8 @@ extern PlayState* gPlayState;
|
|||||||
extern void Play_PerformSave(PlayState* play);
|
extern void Play_PerformSave(PlayState* play);
|
||||||
extern s32 Health_ChangeBy(PlayState* play, s16 healthChange);
|
extern s32 Health_ChangeBy(PlayState* play, s16 healthChange);
|
||||||
extern void Rupees_ChangeBy(s16 rupeeChange);
|
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);
|
extern void Inventory_ChangeEquipment(s16 equipment, u16 value);
|
||||||
}
|
}
|
||||||
bool performDelayedSave = false;
|
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() {
|
void RegisterHyperBosses() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* refActor) {
|
||||||
// Run the update function a second time to make bosses move and act twice as fast.
|
// Run the update function a second time to make bosses move and act twice as fast.
|
||||||
@ -450,6 +508,7 @@ void InitMods() {
|
|||||||
RegisterSwitchAge();
|
RegisterSwitchAge();
|
||||||
RegisterOcarinaTimeTravel();
|
RegisterOcarinaTimeTravel();
|
||||||
RegisterAutoSave();
|
RegisterAutoSave();
|
||||||
|
RegisterDaytimeGoldSkultullas();
|
||||||
RegisterRupeeDash();
|
RegisterRupeeDash();
|
||||||
RegisterHyperBosses();
|
RegisterHyperBosses();
|
||||||
RegisterBonkDamage();
|
RegisterBonkDamage();
|
||||||
|
@ -181,6 +181,7 @@ const std::vector<const char*> enhancementsCvars = {
|
|||||||
"gStaticExplosionRadius",
|
"gStaticExplosionRadius",
|
||||||
"gNoInputForCredits",
|
"gNoInputForCredits",
|
||||||
"gFastFarores",
|
"gFastFarores",
|
||||||
|
"gNightGSAlwaysSpawn",
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<const char*> randomizerCvars = {
|
const std::vector<const char*> randomizerCvars = {
|
||||||
|
@ -354,6 +354,8 @@ namespace GameMenuBar {
|
|||||||
"to the guard next to the gate.");
|
"to the guard next to the gate.");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false);
|
||||||
UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell.");
|
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::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::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);
|
UIWidgets::PaddedEnhancementCheckbox("Time Travel with the Song of Time", "gTimeTravel", true, false);
|
||||||
|
@ -2516,6 +2516,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
|
|||||||
Actor_SpawnEntry(&play->actorCtx, actorEntry++, play);
|
Actor_SpawnEntry(&play->actorCtx, actorEntry++, play);
|
||||||
}
|
}
|
||||||
play->numSetupActors = 0;
|
play->numSetupActors = 0;
|
||||||
|
GameInteractor_ExecuteOnSceneSpawnActors();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actorCtx->unk_02 != 0) {
|
if (actorCtx->unk_02 != 0) {
|
||||||
|
@ -550,7 +550,7 @@ void func_80B0D590(EnSw* this, PlayState* play) {
|
|||||||
this->collider.elements[0].info.ocElemFlags = 1;
|
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);
|
Actor_SetScale(&this->actor, this->actor.scale.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +173,15 @@ void EnWood02_Init(Actor* thisx, PlayState* play2) {
|
|||||||
f32 floorY;
|
f32 floorY;
|
||||||
s16 extraRot;
|
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;
|
spawnType = WOOD_SPAWN_NORMAL;
|
||||||
actorScale = 1.0f;
|
actorScale = 1.0f;
|
||||||
this->unk_14C = (this->actor.params >> 8) & 0xFF;
|
this->unk_14C = (this->actor.params >> 8) & 0xFF;
|
||||||
|
Loading…
Reference in New Issue
Block a user