From a8c54700446b892efbed2253321a17a4989393a5 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Thu, 30 Jul 2026 14:50:42 -0400 Subject: Factor out lights, lots of cleanup Signed-off-by: Andrew Opalach --- Lights.cs | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 Lights.cs (limited to 'Lights.cs') diff --git a/Lights.cs b/Lights.cs new file mode 100644 index 0000000..0eed477 --- /dev/null +++ b/Lights.cs @@ -0,0 +1,264 @@ +using System.Numerics; + +using ImGuiNET; +using SharpPluginLoader.Core; +using SharpPluginLoader.Core.Memory; +using SharpPluginLoader.Core.Entities; + +namespace WorldTuningTool +{ + using static Plugin; + + public class Lights + { + public Lights() { } + + private class Light + { + public nint Object; + public int Type; + public Parameter[] Parameters = { + newParameter("Group", 0x13C, ParameterType.INT, pMinMaxStep(1, 255, 1)), // 1 = World, (1 << 1) = Player/Palico, (1 << 2) = NPCs + newFrameParameter("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)), + newFrameParameter("Color", 0x140, ParameterType.COLOR), + newFrameParameter("Intensity", 0x8A8, ParameterType.FLOAT), + newFrameParameter("Radius", 0x6A0, ParameterType.FLOAT, pStep(0.25f)), + newFrameParameter("Effective Radius", 0x588, ParameterType.FLOAT, pStep(0.25f)), + newFrameParameter("Min Roughness", 0x58C, ParameterType.FLOAT, pStep(0.0025f)), + newParameter("Do Volumetric", 0x590, ParameterType.BOOL), + newFlag("Shadow Cast", 0x138, ParameterType.FLAG, (1 << 23)), + newParameter("Shadow Map Size", 0x1B8, ParameterType.ALIGNED_INT, pMinStep(0, 128)), + newParameter("Shadow Near Clip Distance", 0x1B4, ParameterType.FLOAT), + newFrameParameter("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, pStep(0.00001f)), + newFrameParameter("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, pStep(0.00001f)), + newFrameParameter("Shadow Max Depth Bias", 0x584, ParameterType.FLOAT, pStep(0.00001f)), + }; + + public Light(nint lightObject, int type) + { + Object = lightObject; + Type = type; + foreach (Parameter param in Parameters) + { + param.Update(lightObject); + } + } + + public Light(nint lightObject, int type, Vector3 pos) + { + Object = lightObject; + Type = type; + foreach (Parameter param in Parameters) + { + param.OverrideOn(false); + } + Parameters[0].SetOverrideValue(default, 255); + Parameters[1].SetOverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0); + Parameters[3].SetOverrideValue(new Vector4(10.0f, 0.0f, 0.0f, 0.0f), 0); + foreach (Parameter param in Parameters) + { + param.Update(lightObject); + } + } + } + + // Point Light (2): + // Create1: 0x141F875A0 () + // Create2: 0x141F87CD0 (nint) + // Destroy: 0x141F87D90 (nint, int) + // + // Spot Light (3): + // Create1: 0x141F8AE80 () + // Create2: 0x141F8B2D0 (nint) + // Destroy: 0x141F8B390 (nint, int) + // + // Hemi Sphere Light (4): + // Create1: 0x141F84840 () + // Create2: 0x141F84990 (nint) + // Destroy: 0x141F84A40 (nint, int) + // + // Wrapper? (8): + // Create1: 0x141F816C0 () + // Create2: 0x141F81800 () + // Destroy: 0x141F81940 (nint, int) + + private int requestLightType = 2; + private NativeFunction createLight; + //private bool interceptCreateLight = false; + private List ourLights = new List(); + //private List sceneLights = new List(); + private NativeAction addToScene; + private NativeAction removeFromScene; + //private delegate nint CreateLightObject(int type); + //private Hook? createLightObject; + private delegate void DestroyLightObject(nint lightObject, int unknownInt); + private Hook? destroyLightObject; + private delegate void UpdateLights(nint lightObject); + private Hook? updateLights; + + public void Initialize() + { + createLight = new NativeFunction(0x1418A3EF0); + //createLightObject = Hook.Create(0x1418A3EF0, CreateLightObjectHook); + destroyLightObject = Hook.Create(0x141F87D90, DestroyLightObjectHook); + addToScene = new NativeAction(0x142219070); + removeFromScene = new NativeAction(0x142228F10); + updateLights = Hook.Create(0x141F88F30, UpdateLightsHook); + } + + /* + private nint CreateLightObjectHook(int type) + { + nint lightObject = createLightObject!.Original(type); + if (interceptCreateLight) + { + interceptCreateLight = false; + } + //else if (type == 2) + else + { + sceneLights.Add(new Light(lightObject, type)); + } + return lightObject; + } + */ + + private void UpdateLightsHook(nint lightObject) + { + Light? light = null; + /* + for (int i = 0; i < sceneLights.Count; i++) + { + if (lightObject == sceneLights[i].Object) + { + light = sceneLights[i]; + break; + } + } + */ + if (light == null) + { + for (int i = 0; i < ourLights.Count; i++) + { + if (lightObject == ourLights[i].Object) + { + light = ourLights[i]; + break; + } + } + } + updateLights!.Original(lightObject); + if (light != null) + { + foreach (Parameter param in light.Parameters) + { + param.Update(lightObject); + } + } + } + + private void DestroyLightObjectHook(nint lightObject, int unknownInt) + { + /* + for (int i = 0; i < sceneLights.Count; i++) + { + if (lightObject == sceneLights[i].Object) + { + sceneLights.RemoveAt(i); + break; + } + } + */ + for (int i = 0; i < ourLights.Count; i++) + { + if (lightObject == ourLights[i].Object) + { + ourLights.RemoveAt(i); + break; + } + } + destroyLightObject!.Original(lightObject, unknownInt); + } + + public unsafe void DrawUI(float width) + { + /* + ImGui.NextItemWidth(width * 0.25f); + ImGui.InputInt("Type", ref requestLightType, 1); + ImGui.SameLine(); + */ + if (ImGui.Button("New")) + { + //interceptCreateLight = true; + nint lightObject = createLight.Invoke(requestLightType); + Vector3 pos = default; + Player? player = Player.MainPlayer; + if (player != null) + { + pos = player.Position; + pos.Y += 30.0f; + } + ourLights.Add(new Light(lightObject, requestLightType, pos)); + // mov byte ptr[rsp+20],00 unaccounted for, hopefully it never matters. + addToScene.Invoke(MemoryUtil.Read(0x1451238C8), 0x16, lightObject, 0x0); + } + ImGui.Separator(); + ImGui.PushID("Ours"); + for (int i = 0; i < ourLights.Count; i++) + { + Light light = ourLights[i]; + ImGui.PushID(i); + ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); + foreach (Parameter param in light.Parameters) + { + param.Draw(width, true); + } + /* + if (ImGui.CollapsingHeader("Random Move")) + { + foreach (Parameter param in light.RandomMoveParameters) + { + param.Draw(width, true); + } + } + */ + if (ImGui.Button("Remove")) + { + /* + nint vTable = MemoryUtil.Read(lightObject); + NativeAction freeLight = new NativeAction(MemoryUtil.Read(vTable)); + freeLight.Invoke(lightObject, 1); + */ + // removeFromScene triggers destructor. + removeFromScene.Invoke(light.Object); + } + ImGui.PopID(); + ImGui.Separator(); + } + ImGui.PopID(); + ImGui.PushID("Scene"); + /* + if (ImGui.CollapsingHeader("Scene Lights")) + { + for (int i = 0; i < sceneLights.Count; i++) + { + Light light = sceneLights[i]; + ImGui.PushID(i); + ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); + foreach (Parameter param in light.Parameters) + { + param.Draw(width); + } + if (ImGui.Button("Remove")) + { + removeFromScene.Invoke(light.Object); + } + ImGui.PopID(); + ImGui.Separator(); + } + } + */ + ImGui.PopID(); + } + } +} -- cgit v1.2.3-101-g0448