Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/Features/LightLimitFix.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,33 @@ struct LightLimitFix : Feature
static inline REL::Relocation<decltype(thunk)> func;
};

struct ValidLight1
{
static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light)
{
return func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
Comment on lines +283 to +285

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null pointer validation for runtime safety.

The thunk functions access a_light->portalStrict and a_light->portalGraph without null checks, which could cause crashes if a null pointer is passed.

 			static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light)
 			{
-				return func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
+				return a_light && func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
 			}

Also applies to: 292-294, 301-303

🤖 Prompt for AI Agents
In src/Features/LightLimitFix.h at lines 283-285, 292-294, and 301-303, the
thunk functions access a_light->portalStrict and a_light->portalGraph without
checking if a_light is null, risking crashes. Add null pointer checks for
a_light before accessing its members by returning false or handling the null
case appropriately to ensure runtime safety.

}
static inline REL::Relocation<decltype(thunk)> func;
};

struct ValidLight2
{
static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light)
{
return func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
}
static inline REL::Relocation<decltype(thunk)> func;
};

struct ValidLight3
{
static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light)
{
return func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
}
static inline REL::Relocation<decltype(thunk)> func;
};
Comment on lines +281 to +306

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Eliminate code duplication by creating a template or shared implementation.

All three ValidLight structs contain identical logic, which violates the DRY principle and increases maintenance overhead. Consider refactoring to use a template or shared base implementation.

-		struct ValidLight1
-		{
-			static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light)
-			{
-				return func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
-			}
-			static inline REL::Relocation<decltype(thunk)> func;
-		};
-
-		struct ValidLight2
-		{
-			static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light)
-			{
-				return func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
-			}
-			static inline REL::Relocation<decltype(thunk)> func;
-		};
-
-		struct ValidLight3
-		{
-			static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light)
-			{
-				return func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
-			}
-			static inline REL::Relocation<decltype(thunk)> func;
-		};
+		template<int N>
+		struct ValidLight
+		{
+			static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light)
+			{
+				return func(a_property, a_light) && (a_light->portalStrict || !a_light->portalGraph);
+			}
+			static inline REL::Relocation<decltype(thunk)> func;
+		};
+		
+		using ValidLight1 = ValidLight<1>;
+		using ValidLight2 = ValidLight<2>;
+		using ValidLight3 = ValidLight<3>;
🤖 Prompt for AI Agents
In src/Features/LightLimitFix.h between lines 281 and 306, the three ValidLight
structs have identical thunk functions causing code duplication. Refactor by
creating a single templated struct or a shared base struct that implements the
thunk function once, then instantiate or inherit it for ValidLight1,
ValidLight2, and ValidLight3 to eliminate redundancy and improve
maintainability.


static void Install()
{
stl::write_thunk_call<AIProcess_CalculateLightValue_GetLuminance>(REL::RelocationID(38900, 39946).address() + REL::Relocate(0x1C9, 0x1D3));
Expand All @@ -290,6 +317,10 @@ struct LightLimitFix : Feature

stl::detour_thunk<NiNode_Destroy>(REL::RelocationID(68937, 70288));

stl::write_thunk_call<ValidLight1>(REL::RelocationID(100994, 107781).address() + 0x92);
stl::write_thunk_call<ValidLight2>(REL::RelocationID(100997, 107784).address() + REL::Relocate(0x139, 0x12A));
stl::write_thunk_call<ValidLight3>(REL::RelocationID(101296, 108283).address() + REL::Relocate(0xB7, 0x7E));

logger::info("[LLF] Installed hooks");
}
};
Expand Down