diff options
| author | 2026-08-07 15:38:44 -0400 | |
|---|---|---|
| committer | 2026-08-07 15:38:44 -0400 | |
| commit | 711137e40726578b8c62e959e1b9009b61cae50b (patch) | |
| tree | 7a2815464ff66d512b45041e528e4b45196cc727 /Lights.cs | |
| parent | d6822fe63f1023caf3c72bf3f9b654c8779c285a (diff) | |
| download | WorldTuningTool-711137e40726578b8c62e959e1b9009b61cae50b.tar.gz WorldTuningTool-711137e40726578b8c62e959e1b9009b61cae50b.tar.bz2 WorldTuningTool-711137e40726578b8c62e959e1b9009b61cae50b.zip | |
Massively improve update hooks, work on lights
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'Lights.cs')
| -rw-r--r-- | Lights.cs | 993 |
1 files changed, 854 insertions, 139 deletions
@@ -13,184 +13,869 @@ namespace WorldTuningTool { public Lights() { } - private class Light + private class uLight { - public nint Object; - public int Type; - public Parameter[] Parameters = { - newParameter<int>("Group", 0x13C, ParameterType.INT, pMinMaxStep(1, 255, 1)), // 1 = World, (1 << 1) = Player/Palico, (1 << 2) = NPCs - newFrameParameter<float>("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)), - newFrameParameter<int>("Color", 0x140, ParameterType.COLOR), - newFrameParameter<float>("Intensity", 0x8A8, ParameterType.FLOAT), - newFrameParameter<float>("Radius", 0x6A0, ParameterType.FLOAT, pStep(0.25f)), - newFrameParameter<float>("Effective Radius", 0x588, ParameterType.FLOAT, pStep(0.25f)), - newFrameParameter<float>("Min Roughness", 0x58C, ParameterType.FLOAT, pStep(0.0025f)), - newParameter<bool>("Do Volumetric", 0x590, ParameterType.BOOL), - newFlag<bool>("Shadow Cast", 0x138, ParameterType.FLAG, (1 << 23)), - newParameter<int>("Shadow Map Size", 0x1B8, ParameterType.ALIGNED_INT, pMinStep(0, 128)), - newParameter<float>("Shadow Near Clip Distance", 0x1B4, ParameterType.FLOAT), - newFrameParameter<float>("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, pStep(0.00001f)), - newFrameParameter<float>("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, pStep(0.00001f)), - newFrameParameter<float>("Shadow Max Depth Bias", 0x584, ParameterType.FLOAT, pStep(0.00001f)), - }; + public nint Object = 0x0; + public virtual int Type => -1; + public virtual string Name => $"uLight"; + public virtual string Info => $"0x{Object:X}"; + public List<Parameter> Parameters = new List<Parameter>(); - public Light(nint lightObject, int type) + public void UpdateParams() { - Object = lightObject; - Type = type; + Assert(Object != 0x0); foreach (Parameter param in Parameters) { - param.Update(lightObject); + param.Update(Object); } } - public Light(nint lightObject, int type, Vector3 pos) + public uLight(nint lightObject) { Object = lightObject; - Type = type; + Parameters.AddRange(new Parameter[]{ + M<int>("Group", 0x13C, ParameterType.INT, 0x7, pMinMaxStep(0, 7, 1)), // 1 = World, (1 << 1) = Player/Palico, (1 << 2) = NPCs + M<int>("Priority", 0x138, ParameterType.INT, (0xFF << 6), pMinMaxStep(0, 255, 1)), + P<int>("Color", 0x140, ParameterType.COLOR), + P<float>("Intensity", 0x144, ParameterType.FLOAT), + P<float>("Min Roughness", 0x58C, ParameterType.FLOAT, pStep(0.001f)), + M<bool>("Disp", 0x138, ParameterType.FLAG, (1 << 24)), + M<bool>("Primary", 0x138, ParameterType.FLAG, (1 << 26)), + M<bool>("Shadow Cast", 0x138, ParameterType.FLAG, (1 << 23)), + M<int>("Shadow Priority", 0x138, ParameterType.INT, (0xFF << 14), pMinMaxStep(0, 255, 1)), + P<int>("Shadow Map Size", 0x1B8, ParameterType.ALIGNED_INT, pMinStep(0, 128)), // Result of mShadowMapSize. + P<float>("Near Clip Distance", 0x1B4, ParameterType.FLOAT), + P<float>("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Shadow Max Depth Bias", 0x584, ParameterType.FLOAT, pStep(0.00001f)), + P<bool>("Use Umbra", 0x591, ParameterType.BOOL), + P<bool>("Enable Camera Lod", 0x592, ParameterType.BOOL), + P<bool>("Do Volumetric", 0x590, ParameterType.BOOL) + }); + UpdateParams(); + } + } + + private class uInfiniteLight : uLight + { + public override int Type => 1; + public override string Name => $"uInfiniteLight"; + // mpTexture unaccounted for. + + public uInfiniteLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<float>("Direction", 0x5A0, ParameterType.VECTOR3, pStep(0.00025f)), + P<float>("Shadow Distance", 0x5B0, ParameterType.FLOAT), + P<float>("Shadow Backforward Distance", 0x5B8, ParameterType.FLOAT), + P<float>("Shadow Distribution", 0x5B4, ParameterType.FLOAT), + P<float>("Shadow Radius Scale", 0x5BC, ParameterType.FLOAT), + P<bool>("Manual Split", 0x5C1, ParameterType.BOOL), + P<bool>("Individual Shadow Bias", 0x5D0, ParameterType.BOOL), + P<float>("Cascade Blend", 0x5C0, ParameterType.FLOAT), + P<float>("Fov", 0x630, ParameterType.FLOAT), + P<bool>("Is Fixed Fov Mode", 0x634, ParameterType.BOOL), + P<bool>("Is Discretized Fov Mode", 0x63C, ParameterType.BOOL), + P<float>("Discretization Angle", 0x638, ParameterType.FLOAT), + P<float>("Manual Split Distance[0]", 0x5C4, ParameterType.FLOAT), + P<float>("Cascade Depth Bias[0]", 0x5D4, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Cascade Sloped Depth Bias[0]", 0x5E0, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Cascade Max Depth Bias[0]", 0x5EC, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Manual Split Distance[1]", 0x5C8, ParameterType.FLOAT), + P<float>("Cascade Depth Bias[1]", 0x5D8, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Cascade Sloped Depth Bias[1]", 0x5E4, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Cascade Max Depth Bias[1]", 0x5F0, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Manual Split Distance[2]", 0x5CC, ParameterType.FLOAT), + P<float>("Cascade Depth Bias[2]", 0x5DC, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Cascade Sloped Depth Bias[2]", 0x5E8, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Cascade Max Depth Bias[2]", 0x5F4, ParameterType.FLOAT, pStep(0.00001f)), + P<float>("Projection Scale", 0x600, ParameterType.VECTOR2), + P<float>("Projection Offset", 0x60C, ParameterType.VECTOR2), + P<float>("Projection Up", 0x620, ParameterType.VECTOR3) + }); + UpdateParams(); + } + } + + private class uMhInfiniteLight : uInfiniteLight + { + public override string Name => $"uMhInfiniteLight"; + + public uMhInfiniteLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<float>("Projection Offset Speed", 0x6D0, ParameterType.VECTOR2), + P<float>("Projection Offset Current", 0x6D8, ParameterType.VECTOR2) + }); + UpdateParams(); + } + } + + private class uMhActorInfiniteLight : uMhInfiniteLight + { + public override string Name => $"uMhActorInfiniteLight"; + + public uMhActorInfiniteLight(nint lightObject) : base(lightObject) + { + } + } + + private class uLlkInfiniteLight : uInfiniteLight + { + public override string Name => $"uLlkInfiniteLight"; + public nint CycleTimelineRes => MemoryUtil.Read<nint>(Object + 0x658); + public int CycleAnimNo => MemoryUtil.Read<int>(Object + 0x7A8); + + public uLlkInfiniteLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<int>("Llk Color", 0x640, ParameterType.COLOR), + P<float>("Llk Intensity", 0x644, ParameterType.FLOAT), + P<float>("Projection Offset Speed", 0x648, ParameterType.VECTOR2) + }); + UpdateParams(); + } + } + + private class uLlkActorInfiniteLight : uLlkInfiniteLight + { + public override string Name => $"uLlkActorInfiniteLight"; + + public uLlkActorInfiniteLight(nint lightObject) : base(lightObject) + { + } + } + + private class uLlkFollowCameraInfiniteLight : uLlkInfiniteLight + { + public override string Name => $"uLlkFollowCameraInfiniteLight"; + + public uLlkFollowCameraInfiniteLight(nint lightObject) : base(lightObject) + { + } + } + + private class uPointLight : uLight + { + public override int Type => 2; + public override string Name => $"uPointLight"; + public override string Info => $"0x{Object:X}" + (Parent != 0x0 ? $", Parent: 0x{Parent:X}" : ""); + public nint Parent => MemoryUtil.Read<nint>(Object + 0x5C0); + public int ParentNo => MemoryUtil.Read<int>(Object + 0x5C8); + public Vector3 Position => MemoryUtil.Read<Vector3>(Object + 0x5A0); + + public uPointLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<float>("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)), + P<float>("Radius", 0x1B0, ParameterType.FLOAT), + P<float>("Effective Radius", 0x588, ParameterType.FLOAT) + }); + UpdateParams(); + } + } + + private class uMhPointLight : uPointLight + { + public override string Name => $"uMhPointLight"; + + public uMhPointLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<bool>("Multiply Radius Square", 0x5D0, ParameterType.BOOL) + }); + UpdateParams(); + } + + public uMhPointLight(nint lightObject, Vector3 pos) : this(lightObject) + { 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[0].SetOverrideValue(default, 0x7); Parameters[3].SetOverrideValue(new Vector4(10.0f, 0.0f, 0.0f, 0.0f), 0); + Parameters[17].SetOverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0); + } + } + + private class uMhActorPointLight : uMhPointLight + { + public override string Name => $"uMhActorPointLight"; + + public uMhActorPointLight(nint lightObject) : base(lightObject) + { + } + } + + private class uLlkPointLight : uPointLight + { + public override string Name => $"uLlkPointLight"; + public nint TimelineRes => MemoryUtil.Read<nint>(Object + 0x8A4); + public int AnimNo => MemoryUtil.Read<int>(Object + 0x7A8); + public NativeAction<nint> PlayResource = new NativeAction<nint>(0x141F89CB0); + public NativeAction<nint> StopResource = new NativeAction<nint>(0x141F8A0C0); + public nint CycleTimelineRes => MemoryUtil.Read<nint>(Object + 0x750); + public int CycleAnimNo => MemoryUtil.Read<int>(Object + 0x8A0); + + public uLlkPointLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<int>("Llk Color", 0x970, ParameterType.COLOR), + P<float>("Llk Intensity", 0x974, ParameterType.FLOAT), + P<float>("Llk Radius", 0x978, ParameterType.FLOAT), + P<float>("Llk Effective Radius", 0x97C, ParameterType.FLOAT), + P<bool>("Multiply Radius Square", 0x980, ParameterType.BOOL), + P<int>("Random Param Bits", 0x6C8, ParameterType.HEX), + P<float>("Force Set Time", 0x8B4, ParameterType.FLOAT), + P<float>("Near Fade Out Start Distance", 0x8D4, ParameterType.FLOAT), + P<float>("Near Fade Out End Distance", 0x8D8, ParameterType.FLOAT), + P<float>("Fade Out Start Distance", 0x8DC, ParameterType.FLOAT), + P<float>("Fade Out End Distance", 0x8E0, ParameterType.FLOAT), + P<float>("Random Move Radius", 0x8E8, ParameterType.FLOAT), + P<float>("Random Move Friction", 0x900, ParameterType.VECTOR3), + P<float>("Random Move Force To Center", 0x8EC, ParameterType.FLOAT), + P<float>("Random Move Time Min", 0x8F8, ParameterType.FLOAT), + P<float>("Random Move Time Max", 0x8FC, ParameterType.FLOAT), + P<float>("Random Move Speed V Max", 0x940, ParameterType.VECTOR3), + P<float>("Random Move Force V Max", 0x960, ParameterType.VECTOR3) + }); + UpdateParams(); + } + } + + private class uLlkActorPointLight : uLlkPointLight + { + public override string Name => $"uLlkActorPointLight"; + + public uLlkActorPointLight(nint lightObject) : base(lightObject) + { + } + } + + private class uLlkFollowCameraPointLight : uLlkPointLight + { + public override string Name => $"uLlkFollowCameraPointLight"; + + public uLlkFollowCameraPointLight(nint lightObject) : base(lightObject) + { + } + } + + private class uSpotLight : uLight + { + public override int Type => 3; + public override string Name => $"uSpotLight"; + public override string Info => $"0x{Object:X}, Parent: 0x{Parent:X}"; + public nint Parent => MemoryUtil.Read<nint>(Object + 0x600); + public int ParentNo => MemoryUtil.Read<int>(Object + 0x610); + public nint Target => MemoryUtil.Read<nint>(Object + 0x608); + public int TargetNo => MemoryUtil.Read<int>(Object + 0x614); + public nint Texture => MemoryUtil.Read<nint>(Object + 0x670); + public nint ShadowCacheResource => MemoryUtil.Read<nint>(Object + 0x698); + + public uSpotLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<float>("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)), + P<float>("Direction", 0x5B0, ParameterType.VECTOR3, pStep(0.0025f)), + P<float>("Target Position", 0x5C0, ParameterType.VECTOR3, pStep(0.15f)), + P<bool>("Target Mode", 0x5F8, ParameterType.BOOL), + P<float>("Radius", 0x1B0, ParameterType.FLOAT), + P<float>("Effective Radius", 0x588, ParameterType.FLOAT), + P<float>("Cone", 0x5F0, ParameterType.FLOAT, pStep(0.01f)), + P<float>("Spread", 0x5F0, ParameterType.FLOAT, pStep(0.01f)), + P<float>("Falloff", 0x618, ParameterType.FLOAT, pStep(0.01f)), + P<float>("Projection Scale", 0x67C, ParameterType.VECTOR2), + P<float>("Projection Offset", 0x684, ParameterType.VECTOR2), + P<float>("Projection Rotation Z", 0x68C, ParameterType.FLOAT), + P<int>("Texture Index", 0x678, ParameterType.INT, pStep(1)), + P<bool>("Use Shadow Cache", 0x690, ParameterType.BOOL) + }); + UpdateParams(); + } + } + + private class uMhSpotLight : uSpotLight + { + public override string Name => $"uMhSpotLight"; + + public uMhSpotLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<bool>("Multiply Radius Square", 0x6A0, ParameterType.BOOL), + }); + UpdateParams(); + } + + public uMhSpotLight(nint lightObject, Vector3 pos) : this(lightObject) + { + foreach (Parameter param in Parameters) + { + param.OverrideOn(false); + } + Parameters[0].SetOverrideValue(default, 0x7); + Parameters[3].SetOverrideValue(new Vector4(350.0f, 0.0f, 0.0f, 0.0f), 0); + Parameters[17].SetOverrideValue(new Vector4(pos.X, pos.Y + 200.0f, pos.Z, 0.0f), 0); + Parameters[19].SetOverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0); + Parameters[20].SetOverrideValue(default, 1); + Parameters[23].SetOverrideValue(new Vector4(45.0f, 0.0f, 0.0f, 0.0f), 0); + } + } + + private class uMhActorSpotLight : uMhSpotLight + { + public override string Name => $"uMhActorSpotLight"; + + public uMhActorSpotLight(nint lightObject) : base(lightObject) + { + } + } + + private class uLlkSpotLight : uSpotLight + { + public override string Name => $"uLlkSpotLight"; + public nint TimelineRes => MemoryUtil.Read<nint>(Object + 0x790); + public int AnimNo => MemoryUtil.Read<int>(Object + 0x974); + public NativeAction<nint> PlayResource = new NativeAction<nint>(0x141F8D550); + public NativeAction<nint> StopResource = new NativeAction<nint>(0x141F8D970); + public nint CycleTimelineRes => MemoryUtil.Read<nint>(Object + 0x820); + public int CycleAnimNo => MemoryUtil.Read<int>(Object + 0x970); + + public uLlkSpotLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<int>("Llk Color", 0xA40, ParameterType.COLOR), + P<float>("Llk Intensity", 0xA44, ParameterType.FLOAT), + P<float>("Llk Radius", 0xA48, ParameterType.FLOAT), + P<float>("Llk Effective Radius", 0xA4C, ParameterType.FLOAT), + P<float>("Llk Cone", 0xA50, ParameterType.FLOAT), + P<float>("Llk Spread", 0xA54, ParameterType.FLOAT), + P<float>("Llk Falloff", 0xA58, ParameterType.FLOAT), + P<bool>("Multiply Radius Square", 0xA68, ParameterType.BOOL), + P<int>("Random Param Bits", 0x798, ParameterType.HEX), + P<float>("Force Set Time", 0x984, ParameterType.FLOAT), + P<float>("Near Fade Out Start Distance", 0x9A4, ParameterType.FLOAT), + P<float>("Near Fade Out End Distance", 0x9A8, ParameterType.FLOAT), + P<float>("Fade Out Start Distance", 0x9AC, ParameterType.FLOAT), + P<float>("Fade Out End Distance", 0x9B0, ParameterType.FLOAT), + P<float>("Random Move Radius", 0x9B8, ParameterType.FLOAT), + P<float>("Random Move Friction", 0x9D0, ParameterType.VECTOR3), + P<float>("Random Move Force To Center", 0x9BC, ParameterType.FLOAT), + P<float>("Random Move Time Min", 0x9C8, ParameterType.FLOAT), + P<float>("Random Move Time Max", 0x9CC, ParameterType.FLOAT), + P<float>("Random Move Speed V Max", 0xA10, ParameterType.VECTOR3), + P<float>("Random Move Force V Max", 0xA30, ParameterType.VECTOR3), + P<float>("Projection Offset Speed", 0xA60, ParameterType.VECTOR2) + }); + UpdateParams(); + } + } + + private class uLlkActorSpotLight : uLlkSpotLight + { + public override string Name => $"uLlkActorSpotLight"; + + public uLlkActorSpotLight(nint lightObject) : base(lightObject) + { + } + } + + private class uLlkNullAngleSpotLight : uLlkSpotLight + { + public override string Name => $"uLlkNullAngleSpotLight"; + + public uLlkNullAngleSpotLight(nint lightObject) : base(lightObject) + { + } + } + + private class uLlkFollowCameraSpotLight : uLlkSpotLight + { + public override string Name => $"uLlkFollowCameraSpotLight"; + + public uLlkFollowCameraSpotLight(nint lightObject) : base(lightObject) + { + } + } + + private class uHemiSphereLight : uLight + { + public override int Type => 4; + public override string Name => $"uHemiSphereLight"; + + public uHemiSphereLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<int>("Rev Color", 0x5A0, ParameterType.COLOR), + P<float>("Rev Intensity", 0x5A4, ParameterType.FLOAT), + P<float>("Direction", 0x5B0, ParameterType.VECTOR3, pStep(0.00025f)) + }); + UpdateParams(); + } + } + + private class uMhHemiSphereLight : uHemiSphereLight + { + public override string Name => $"uMhHemiSphereLight"; + + public uMhHemiSphereLight(nint lightObject) : base(lightObject) + { + } + + public uMhHemiSphereLight(nint lightObject, Vector3 pos) : this(lightObject) + { foreach (Parameter param in Parameters) { - param.Update(lightObject); + param.OverrideOn(false); } } } - // 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 class uLlkHemiSphereLight : uHemiSphereLight + { + public override string Name => $"uLlkHemiSphereLight"; + public nint CycleTimelineRes => MemoryUtil.Read<nint>(Object + 0x5D0); + public int CycleAnimNo => MemoryUtil.Read<int>(Object + 0x720); + + public uLlkHemiSphereLight(nint lightObject) : base(lightObject) + { + Parameters.AddRange(new Parameter[]{ + P<int>("Llk Color", 0x5C0, ParameterType.COLOR), + P<float>("Llk Intensity", 0x5C8, ParameterType.FLOAT), + P<int>("Llk Rev Color", 0x5C4, ParameterType.COLOR), + P<float>("Llk Rev Intensity", 0x5CC, ParameterType.FLOAT) + }); + UpdateParams(); + } + } + + private class uMhObjectLight : uLight + { + public override int Type => 5; + public override string Name => $"uMhObjectLight"; + + public uMhObjectLight(nint lightObject) : base(lightObject) + { + } + } + + private class uLlkObjectLight : uLight + { + public override string Name => $"uLlkObjectLight"; + + public uLlkObjectLight(nint lightObject) : base(lightObject) + { + } + } + + private delegate nint CreateLightObject(nint lightObject); + private delegate nint DestroyLightObject(nint lightObjectInternal, int unknownInt); + private Hook<CreateLightObject>? createLightObject; + private static Dictionary<nint, Func<nint, uLight>> lightTypes = new Dictionary<nint, Func<nint, uLight>>() + { + { lton(0x143514168), (x) => new uLight(x) }, + { lton(0x143514288), (x) => new uInfiniteLight(x) }, + { lton(0x1434994D0), (x) => new uMhInfiniteLight(x) }, + { lton(0x1434954F0), (x) => new uMhActorInfiniteLight(x) }, + { lton(0x143494150), (x) => new uLlkInfiniteLight(x) }, + { lton(0x1434936A0), (x) => new uLlkActorInfiniteLight(x) }, + { lton(0x143493E30), (x) => new uLlkFollowCameraInfiniteLight(x) }, + { lton(0x1435143A8), (x) => new uPointLight(x) }, + { lton(0x14349A6C8), (x) => new uMhPointLight(x) }, + { lton(0x1434952B0), (x) => new uMhActorPointLight(x) }, + { lton(0x1434944E8), (x) => new uLlkPointLight(x) }, + { lton(0x143493460), (x) => new uLlkActorPointLight(x) }, + { lton(0x143493BF0), (x) => new uLlkFollowCameraPointLight(x) }, + { lton(0x1435144C8), (x) => new uSpotLight(x) }, + { lton(0x14349E280), (x) => new uMhSpotLight(x) }, + { lton(0x1434953D0), (x) => new uMhActorSpotLight(x) }, + { lton(0x143494888), (x) => new uLlkSpotLight(x) }, + { lton(0x143493580), (x) => new uLlkActorSpotLight(x) }, + { lton(0x1434937C0), (x) => new uLlkNullAngleSpotLight(x) }, + { lton(0x143493D10), (x) => new uLlkFollowCameraSpotLight(x) }, + { lton(0x1435145E8), (x) => new uHemiSphereLight(x) }, + { lton(0x143499378), (x) => new uMhHemiSphereLight(x) }, + { lton(0x143493F98), (x) => new uLlkHemiSphereLight(x) }, + { lton(0x14349A498), (x) => new uMhObjectLight(x) }, + { lton(0x1434942A0), (x) => new uLlkObjectLight(x) }, + { lton(0x143493918), (x) => new uLight(x) }, // @TODO: uLlkBaseModel is not implemented. + }; + private static nint[] lightObjectDestructors = { + lton(0x142311FF0), // # uLight + lton(0x142311F40), // # uInfiniteLight + lton(0x141FB8F50), // # uMhInfiniteLight + lton(0x141F91DE0), // # uMhActorInfiniteLight + lton(0x141F855A0), // # uLlkInfiniteLight + lton(0x141F81940), // # uLlkActorInfiniteLight + lton(0x141F83B00), // # uLlkFollowCameraInfiniteLight + lton(0x142312070), // # uPointLight + lton(0x141FC0950), // # uMhPointLight + lton(0x141F91E80), // # uMhActorPointLight + lton(0x141F87D90), // # uLlkPointLight + lton(0x141F819B0), // # uLlkActorPointLight + lton(0x141F83B70), // # uLlkFollowCameraPointLight + lton(0x1423120F0), // # uSpotLight + lton(0x141FDE0D0), // # uMhSpotLight + lton(0x141F91F20), // # uMhActorSpotLight + lton(0x141F8B390), // # uLlkSpotLight + lton(0x141F81A20), // # uLlkActorSpotLight + lton(0x141F81A90), // # uLlkNullAngleSpotLight + lton(0x141F83BE0), // # uLlkFollowCameraSpotLight + lton(0x142311EC0), // # uHemiSphereLight + lton(0x141FB8C20), // # uMhHemiSphereLight + lton(0x141F84A40), // # uLlkHemiSphereLight + lton(0x141FBF6B0), // # uMhObjectLight + lton(0x141F86270), // # uLlkObjectLight + lton(0x141F83460), // # uLlkBaseModel + }; + private Hook<DestroyLightObject>[] lightObjectDestructorHooks = new Hook<DestroyLightObject>[lightObjectDestructors.Length]; + + private List<uLight> newLights = new List<uLight>(); + private List<uLight> sceneLights = new List<uLight>(); + private bool sortByDistanceToPlayer = false; - private int requestLightType = 2; - private NativeFunction<int, nint> createLight; - //private bool interceptCreateLight = false; - private List<Light> ourLights = new List<Light>(); - //private List<Light> sceneLights = new List<Light>(); private NativeAction<nint, int, nint, int> addToScene; private NativeAction<nint> removeFromScene; - //private delegate nint CreateLightObject(int type); - //private Hook<CreateLightObject>? createLightObject; - private delegate void DestroyLightObject(nint lightObject, int unknownInt); - private Hook<DestroyLightObject>? destroyLightObject; - private delegate void UpdateLights(nint lightObject); - private Hook<UpdateLights>? updateLights; + private bool interceptCreateLight = false; + private List<uLight> ourLights = new List<uLight>(); public void Initialize() { - createLight = new NativeFunction<int, nint>(0x1418A3EF0); - //createLightObject = Hook.Create<CreateLightObject>(0x1418A3EF0, CreateLightObjectHook); - destroyLightObject = Hook.Create<DestroyLightObject>(0x141F87D90, DestroyLightObjectHook); + createLightObject = Hook.Create<CreateLightObject>(0x142311420, CreateLightObjectHook); + DestroyLightObject[] destructorHookFuncs = { + DestroyLightObjectHook0, + DestroyLightObjectHook1, + DestroyLightObjectHook2, + DestroyLightObjectHook3, + DestroyLightObjectHook4, + DestroyLightObjectHook5, + DestroyLightObjectHook6, + DestroyLightObjectHook7, + DestroyLightObjectHook8, + DestroyLightObjectHook9, + DestroyLightObjectHook10, + DestroyLightObjectHook11, + DestroyLightObjectHook12, + DestroyLightObjectHook13, + DestroyLightObjectHook14, + DestroyLightObjectHook15, + DestroyLightObjectHook16, + DestroyLightObjectHook17, + DestroyLightObjectHook18, + DestroyLightObjectHook19, + DestroyLightObjectHook20, + DestroyLightObjectHook21, + DestroyLightObjectHook22, + DestroyLightObjectHook23, + DestroyLightObjectHook24, + DestroyLightObjectHook25 + }; + for (int i = 0; i < lightObjectDestructors.Length; i++) + { + lightObjectDestructorHooks[i] = Hook.Create<DestroyLightObject>(lightObjectDestructors[i], destructorHookFuncs[i]); + } + addToScene = new NativeAction<nint, int, nint, int>(0x142219070); removeFromScene = new NativeAction<nint>(0x142228F10); - updateLights = Hook.Create<UpdateLights>(0x141F88F30, UpdateLightsHook); } - /* - private nint CreateLightObjectHook(int type) + public void PostUpdateUnits() { - nint lightObject = createLightObject!.Original(type); - if (interceptCreateLight) + for (int i = 0; i < sceneLights.Count; i++) { - interceptCreateLight = false; + uLight light = sceneLights[i]; + foreach (Parameter param in light.Parameters) + { + param.Update(light.Object); + } } - //else if (type == 2) - else + } + + public void OnUpdate() + { + for (int i = newLights.Count - 1; i >= 0; i--) { - sceneLights.Add(new Light(lightObject, type)); + uLight light = newLights[i]; + nint vTable = MemoryUtil.Read<nint>(light.Object); + newLights.RemoveAt(i); + if (lightTypes.ContainsKey(vTable)) + { + sceneLights.Add(lightTypes[vTable](light.Object)); + } + else + { + Log.Error($"Unknown Light Type: 0x{vTable:X}."); + } } - return lightObject; } - */ - private void UpdateLightsHook(nint lightObject) + private bool lightObjectIsTracked(nint lightObject) { - Light? light = null; - /* - for (int i = 0; i < sceneLights.Count; i++) + for (int i = 0; i < newLights.Count; i++) { - if (lightObject == sceneLights[i].Object) + if (lightObject == newLights[i].Object) { - light = sceneLights[i]; - break; + return true; } } - */ - if (light == null) + for (int i = 0; i < sceneLights.Count; i++) { - for (int i = 0; i < ourLights.Count; i++) + if (lightObject == sceneLights[i].Object) { - if (lightObject == ourLights[i].Object) - { - light = ourLights[i]; - break; - } + return true; } } - updateLights!.Original(lightObject); - if (light != null) + for (int i = 0; i < ourLights.Count; i++) { - foreach (Parameter param in light.Parameters) + if (lightObject == ourLights[i].Object) { - param.Update(lightObject); + return true; } } + return false; + } + + private nint CreateLightObjectHook(nint lightObject) + { + lightObject = createLightObject!.Original(lightObject); + if (!interceptCreateLight) + { + Assert(!lightObjectIsTracked(lightObject)); + newLights.Add(new uLight(lightObject)); + } + return lightObject; } - private void DestroyLightObjectHook(nint lightObject, int unknownInt) + private void cleanupCommon(nint lightObject) { - /* + for (int i = 0; i < newLights.Count; i++) + { + uLight light = newLights[i]; + if (lightObject == light.Object) + { + newLights.RemoveAt(i); + Assert(!lightObjectIsTracked(lightObject)); + return; + } + } for (int i = 0; i < sceneLights.Count; i++) { - if (lightObject == sceneLights[i].Object) + uLight light = sceneLights[i]; + if (lightObject == light.Object) { sceneLights.RemoveAt(i); - break; + Assert(!lightObjectIsTracked(lightObject)); + return; } } - */ for (int i = 0; i < ourLights.Count; i++) { - if (lightObject == ourLights[i].Object) + uLight light = ourLights[i]; + if (lightObject == light.Object) { ourLights.RemoveAt(i); - break; + Assert(!lightObjectIsTracked(lightObject)); + return; } } - destroyLightObject!.Original(lightObject, unknownInt); + } + + private nint DestroyLightObjectHook0(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[0]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook1(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[1]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook2(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[2]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook3(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[3]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook4(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[4]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook5(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[5]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook6(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[6]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook7(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[7]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook8(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[8]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook9(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[9]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook10(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[10]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook11(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[11]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook12(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[12]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook13(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[13]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook14(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[14]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook15(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[15]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook16(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[16]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook17(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[17]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook18(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[18]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook19(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[19]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook20(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[20]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook21(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[21]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook22(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[22]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook23(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[23]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook24(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[24]!.Original(lightObject, unknownInt); + } + private nint DestroyLightObjectHook25(nint lightObject, int unknownInt) + { + Assert(unknownInt == 1); cleanupCommon(lightObject); + return lightObjectDestructorHooks[25]!.Original(lightObject, unknownInt); + } + + private void DrawLights(IEnumerable<uLight> lights, float width) + { + bool disableAll = ImGui.Button("Disable All"); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Set \"Group\" to 0, Disable \"Shadow Cast\" and \"Do Volumetric\"."); + ImGui.EndTooltip(); + } + ImGui.SameLine(); + bool enableAll = ImGui.Button("Enable All"); + foreach (uLight light in lights) + { + ImGui.PushID(light.Object); + if (disableAll) + { + light.Parameters[0].ForceOverrideOn(); + light.Parameters[0].SetOverrideValue(default, 0); + light.Parameters[7].ForceOverrideOn(); + light.Parameters[7].SetOverrideValue(default, 0); + light.Parameters[16].ForceOverrideOn(); + light.Parameters[16].SetOverrideValue(default, 0); + } + if (enableAll) + { + light.Parameters[0].ForceOverrideOff(); + light.Parameters[7].ForceOverrideOff(); + light.Parameters[16].ForceOverrideOff(); + } + if (ImGui.CollapsingHeader(($"{light.Name} ({light.Info})"))) + { + foreach (Parameter param in light.Parameters) + { + param.Draw(width); + } + } + ImGui.PopID(); + } } public unsafe void DrawUI(float width) { - /* - ImGui.NextItemWidth(width * 0.25f); - ImGui.InputInt("Type", ref requestLightType, 1); + interceptCreateLight = true; + int lightType = -1; + nint lightObject = 0x0; + if (ImGui.Button("New Point Light")) + { + lightType = 2; + lightObject = new NativeFunction<nint>(0x141FC0780).Invoke(); + } + ImGui.SameLine(); + if (ImGui.Button("New Spot Light")) + { + lightType = 3; + lightObject = new NativeFunction<nint>(0x141FDDF00).Invoke(); + } ImGui.SameLine(); - */ - if (ImGui.Button("New")) + if (ImGui.Button("New Hemi Sphere Light")) + { + lightType = 4; + lightObject = new NativeFunction<nint>(0x141FB8A50).Invoke(); + } + interceptCreateLight = false; + if (lightObject != 0x0) { - //interceptCreateLight = true; - nint lightObject = createLight.Invoke(requestLightType); Vector3 pos = default; Player? player = Player.MainPlayer; if (player != null) @@ -198,66 +883,96 @@ namespace WorldTuningTool pos = player.Position; pos.Y += 30.0f; } - ourLights.Add(new Light(lightObject, requestLightType, pos)); + if (lightType == 2) + { + ourLights.Add(new uMhPointLight(lightObject, pos)); + } + else if (lightType == 3) + { + ourLights.Add(new uMhSpotLight(lightObject, pos)); + } + else if (lightType == 4) + { + ourLights.Add(new uMhHemiSphereLight(lightObject, pos)); + } // mov byte ptr[rsp+20],00 unaccounted for, hopefully it never matters. addToScene.Invoke(MemoryUtil.Read<nint>(0x1451238C8), 0x16, lightObject, 0x0); } - ImGui.Separator(); ImGui.PushID("Ours"); for (int i = 0; i < ourLights.Count; i++) { - Light light = ourLights[i]; + uLight light = ourLights[i]; ImGui.PushID(i); - ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); - foreach (Parameter param in light.Parameters) + if (ImGui.Button("X")) { - param.Draw(width, true); + removeFromScene.Invoke(light.Object); // removeFromScene triggers destructor. } - /* - if (ImGui.CollapsingHeader("Random Move")) + ImGui.SameLine(); + if (ImGui.CollapsingHeader(($"{light.Name} (0x{light.Object:X})"))) { - foreach (Parameter param in light.RandomMoveParameters) + foreach (Parameter param in light.Parameters) { param.Draw(width, true); } } - */ - if (ImGui.Button("Remove")) - { - /* - nint vTable = MemoryUtil.Read<nint>(lightObject); - NativeAction<nint, int> freeLight = new NativeAction<nint, int>(MemoryUtil.Read<nint>(vTable)); - freeLight.Invoke(lightObject, 1); - */ - // removeFromScene triggers destructor. - removeFromScene.Invoke(light.Object); - } ImGui.PopID(); - ImGui.Separator(); } ImGui.PopID(); + ImGui.Separator(); ImGui.PushID("Scene"); - /* - if (ImGui.CollapsingHeader("Scene Lights")) + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.Framed; + if (ImGui.TreeNodeEx("Scene Lights", flags)) { - for (int i = 0; i < sceneLights.Count; i++) + if (ImGui.CollapsingHeader("Infinite")) { - Light light = sceneLights[i]; - ImGui.PushID(i); - ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}"); - foreach (Parameter param in light.Parameters) + DrawLights(sceneLights.Where(x => (x.Type == 1)), width); + ImGui.Separator(); + } + if (ImGui.CollapsingHeader("Point")) + { + ImGui.Checkbox("Sort By Distance To Player", ref sortByDistanceToPlayer); + ImGui.SameLine(); + if (sortByDistanceToPlayer) { - param.Draw(width); + Vector3 pos = default; + Player? player = Player.MainPlayer; + if (player != null) + { + pos = player.Position; + } + uLight[] pointLights = sceneLights.Where(x => (x.Type == 2)).ToArray(); + Array.Sort(pointLights, delegate(uLight x, uLight y) + { + float distX = Vector3.Distance(pos, ((uPointLight)x).Position); + float distY = Vector3.Distance(pos, ((uPointLight)y).Position); + if (distX < distY) return -1; + else if (distX > distY) return 1; + return 0; + }); + DrawLights(pointLights, width); } - if (ImGui.Button("Remove")) + else { - removeFromScene.Invoke(light.Object); + DrawLights(sceneLights.Where(x => (x.Type == 2)), width); } - ImGui.PopID(); ImGui.Separator(); } + if (ImGui.CollapsingHeader("Spot")) + { + DrawLights(sceneLights.Where(x => (x.Type == 3)), width); + ImGui.Separator(); + } + if (ImGui.CollapsingHeader("Hemi Sphere")) + { + DrawLights(sceneLights.Where(x => (x.Type == 4)), width); + ImGui.Separator(); + } + if (ImGui.CollapsingHeader("Other")) + { + DrawLights(sceneLights.Where(x => (x.Type == -1 || x.Type == 5)), width); + } + ImGui.TreePop(); } - */ ImGui.PopID(); } } |