diff --git a/soh/soh/Enhancements/cosmetics/DynamicShadow.cpp b/soh/soh/Enhancements/cosmetics/DynamicShadow.cpp new file mode 100644 index 000000000..5ff596f13 --- /dev/null +++ b/soh/soh/Enhancements/cosmetics/DynamicShadow.cpp @@ -0,0 +1,39 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include "soh/OTRGlobals.h" + +#include + +extern "C" { +#include "functions.h" +#include "macros.h" +#include "variables.h" + +extern PlayState* gPlayState; +} + +#define CVAR_DYNAMICSHADOW_NAME CVAR_ENHANCEMENT("DynamicShadow") +#define CVAR_DYNAMICSHADOW_DEFAULT 0 +#define CVAR_DYNAMICSHADOW_VALUE CVarGetInteger(CVAR_DYNAMICSHADOW_NAME, CVAR_DYNAMICSHADOW_DEFAULT) + +void RegisterDynamicShadow() { + COND_VB_SHOULD(VB_EXECUTE_PLAYER_STARTMODE_FUNC, CVAR_DYNAMICSHADOW_VALUE, { + int32_t startMode = va_arg(args, int32_t); + Player* player = GET_PLAYER(gPlayState); + Actor* shadowActor; + + if ((player != nullptr) && (startMode != PLAYER_START_MODE_NOTHING)) { + SPDLOG_DEBUG("Spawning Dynamic Shadow"); + + // Spawn as Link's child so the shadow doesn't get unloaded on room change. + shadowActor = Actor_SpawnAsChild(&gPlayState->actorCtx, &player->actor, gPlayState, ACTOR_EN_SDA, 0, 0, 0, + 0, 0, 0, 0); + + // For whatever reason the dynamic shadow's category is ACTORCAT_BOSS. + // We're changing it to ACTORCAT_ITEMACTION, the same category as Navi. + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, shadowActor, ACTORCAT_ITEMACTION); + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterDynamicShadow, { CVAR_DYNAMICSHADOW_NAME }); diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 4aaf1fb67..f6cc01005 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -475,6 +475,11 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip( "When Medallions are collected, the Medallion imprints around the Master Sword Pedestal in the Temple " "of Time will become colored-in.")); + AddWidget(path, "EXPERIMENTAL", WIDGET_SEPARATOR_TEXT).Options(TextOptions().Color(Colors::Orange)); + AddWidget(path, "Dynamic Shadow", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("DynamicShadow")) + .Options(CheckboxOptions().Tooltip("Enable Dynamic Shadow for the player. May cause graphical glitches or " + "gameplay issues. Requires a scene reload to take effect.")); path.column = SECTION_COLUMN_2; AddWidget(path, "UI", WIDGET_SEPARATOR_TEXT);