summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2026-07-30 14:50:42 -0400
committerAndrew Opalach <andrew@akon.city> 2026-07-30 14:50:42 -0400
commita8c54700446b892efbed2253321a17a4989393a5 (patch)
tree69f18b967e3fa1288d87261888c9042ce38aa32b
parentfd94cced1f434107a18ca3b171a4211107fd2a21 (diff)
downloadWorldTuningTool-a8c54700446b892efbed2253321a17a4989393a5.tar.gz
WorldTuningTool-a8c54700446b892efbed2253321a17a4989393a5.tar.bz2
WorldTuningTool-a8c54700446b892efbed2253321a17a4989393a5.zip
Factor out lights, lots of cleanup
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--[-rwxr-xr-x]Config.cs17
-rw-r--r--LUT.cs61
-rw-r--r--Lights.cs264
-rw-r--r--[-rwxr-xr-x]Plugin.cs478
4 files changed, 410 insertions, 410 deletions
diff --git a/Config.cs b/Config.cs
index 3c14fa4..d456269 100755..100644
--- a/Config.cs
+++ b/Config.cs
@@ -1,8 +1,12 @@
-using SharpPluginLoader.Core.Configuration;
+//#define SHADER_FEATURES
+
+using SharpPluginLoader.Core.Configuration;
using SharpPluginLoader.Core;
namespace WorldTuningTool
{
+ using static Plugin;
+
public enum StageExt : uint
{
Global = 0,
@@ -45,7 +49,7 @@ namespace WorldTuningTool
SelianaRoom = 506
}
- internal class Config : IConfig
+ public class Config : IConfig
{
public String Name => "WorldTuningTool";
public String Version => "0.9.4";
@@ -136,6 +140,7 @@ namespace WorldTuningTool
public static readonly StageExt[] OrderedStages =
{
+ StageExt.Global,
StageExt.Astera,
StageExt.AsteraHub,
StageExt.ResearchBase,
@@ -177,7 +182,9 @@ namespace WorldTuningTool
public struct PatchConfig
{
+#if SHADER_FEATURES
public bool FullResolutionSSLR { get; set; } = false;
+#endif
public bool FullResolutionVolumeBlur { get; set; } = false;
public bool HigherThanHighestVolumeRendering { get; set; } = false;
public bool DisableLODLimits { get; set; } = false;
@@ -188,9 +195,9 @@ namespace WorldTuningTool
public PatchConfig Patches { get; set; } = new PatchConfig();
- public Dictionary<string, List<Plugin.Override>> Globals { get; set; } = new Dictionary<string, List<Plugin.Override>>();
+ public Dictionary<string, List<Override>> Globals { get; set; } = new Dictionary<string, List<Override>>();
public string SelectedGlobal { get; set; } = "";
- public Dictionary<StageExt, List<Plugin.Override>> Overrides { get; set; } = new Dictionary<StageExt, List<Plugin.Override>>();
- public Dictionary<string, List<Plugin.Override>> Sets { get; set; } = new Dictionary<string, List<Plugin.Override>>();
+ public Dictionary<StageExt, List<Override>> Overrides { get; set; } = new Dictionary<StageExt, List<Override>>();
+ public Dictionary<string, List<Override>> Sets { get; set; } = new Dictionary<string, List<Override>>();
}
}
diff --git a/LUT.cs b/LUT.cs
index f38010c..b688f0e 100644
--- a/LUT.cs
+++ b/LUT.cs
@@ -11,11 +11,13 @@ using SharpPluginLoader.Core.IO;
namespace WorldTuningTool
{
- public class WorldLUTs
+ using static Plugin;
+
+ public class LUT
{
private const string addPath = "nativePC/plugins/CSharp/LUT";
- public WorldLUTs() { }
+ public LUT() { }
// https://github.com/AsteriskAmpersand/CrappyLUTStudio--CLUTS-/blob/5af10daaa5f295b106cc5db09530a6fe5a4320d4/LUT.py#L35
private byte[]? parseWorldLUT(BinaryReader reader)
@@ -57,7 +59,7 @@ namespace WorldTuningTool
{
string? line;
Vector3[]? parsed = null;
- int dim = 0, idx = 0;
+ int dim = 0, i = 0;
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith("LUT_3D_SIZE"))
@@ -66,18 +68,8 @@ namespace WorldTuningTool
{
dim = Convert.ToInt32(line.Split(' ').Last());
}
- catch (FormatException)
- {
- return null;
- }
- catch (OverflowException)
- {
- return null;
- }
- if (dim != 32)
- {
- return null;
- }
+ catch (Exception) { return null; }
+ if (dim != 32) return null;
parsed = new Vector3[dim * dim * dim];
while ((line = reader.ReadLine()) != null)
{
@@ -87,26 +79,15 @@ namespace WorldTuningTool
break;
}
}
- if (line == null)
- {
- break;
- }
+ if (line == null) break;
}
if (parsed != null)
{
try
{
- parsed[idx] = Plugin.StringToVector3(line, ' ');
- }
- catch (FormatException)
- {
- return null;
- }
- catch (OverflowException)
- {
- return null;
+ parsed[i++] = StringToVector3(line, ' ');
}
- idx++;
+ catch (Exception) { return null; }
}
}
if (parsed == null)
@@ -116,24 +97,24 @@ namespace WorldTuningTool
const int lutDataSize = 32 * 32 * 32 * 8;
byte[] data = new byte[lutDataSize];
float scale = MathF.Pow(2, 14) - 1;
- for (idx = 0; idx < lutDataSize; idx+=8)
+ for (i = 0; i < lutDataSize; i += 8)
{
- Vector3 v = parsed[idx/8];
+ Vector3 v = parsed[i / 8];
ushort normX = (ushort)Math.Round(v.X * scale);
ushort normY = (ushort)Math.Round(v.Y * scale);
ushort normZ = (ushort)Math.Round(v.Z * scale);
byte[] bytes = BitConverter.GetBytes(normX);
- data[idx] = bytes[0];
- data[idx + 1] = bytes[1];
+ data[i] = bytes[0];
+ data[i + 1] = bytes[1];
bytes = BitConverter.GetBytes(normY);
- data[idx + 2] = bytes[0];
- data[idx + 3] = bytes[1];
+ data[i + 2] = bytes[0];
+ data[i + 3] = bytes[1];
bytes = BitConverter.GetBytes(normZ);
- data[idx + 4] = bytes[0];
- data[idx + 5] = bytes[1];
+ data[i + 4] = bytes[0];
+ data[i + 5] = bytes[1];
bytes = BitConverter.GetBytes(0x2B88); // Alpha constant.
- data[idx + 6] = bytes[0];
- data[idx + 7] = bytes[1];
+ data[i + 6] = bytes[0];
+ data[i + 7] = bytes[1];
}
return data;
}
@@ -189,7 +170,7 @@ namespace WorldTuningTool
private static bool[] selectionStarted = [ false, false ];
private static bool[] selectedInvalid = [ false, false ];
- public void DrawLUT(nint texture, nint lightingObject, int i, float width)
+ public void DrawUI(nint texture, nint lightingObject, int i, float width)
{
ImGui.PushID(i);
string lutPath = Marshal.PtrToStringAnsi(texture + 0xC)!;
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<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 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<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;
+
+ public void Initialize()
+ {
+ createLight = new NativeFunction<int, nint>(0x1418A3EF0);
+ //createLightObject = Hook.Create<CreateLightObject>(0x1418A3EF0, CreateLightObjectHook);
+ destroyLightObject = Hook.Create<DestroyLightObject>(0x141F87D90, DestroyLightObjectHook);
+ addToScene = new NativeAction<nint, int, nint, int>(0x142219070);
+ removeFromScene = new NativeAction<nint>(0x142228F10);
+ updateLights = Hook.Create<UpdateLights>(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<nint>(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<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.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();
+ }
+ }
+}
diff --git a/Plugin.cs b/Plugin.cs
index f05fbee..2241a88 100755..100644
--- a/Plugin.cs
+++ b/Plugin.cs
@@ -1,4 +1,4 @@
-//#define ENABLE_ASSERTS
+#define ENABLE_ASSERTS
//#define OVERSIZED_SHADOW_MAP
//#define SHADER_FEATURES
//#define RESOURCE_ADJUSTMENT
@@ -14,7 +14,6 @@ using ImGuiNET;
using SharpPluginLoader.Core;
using SharpPluginLoader.Core.Configuration;
using SharpPluginLoader.Core.Memory;
-using SharpPluginLoader.Core.Entities;
#if SHADER_FEATURES
using SharpPluginLoader.Core.Rendering;
#endif
@@ -31,33 +30,33 @@ using SharpPluginLoader.Core.Resources;
// - Lights refactor.
// - Descriptions.
// - float format.
-// - Min/Max.
// - Lights iterop.
// - SPL Patches:
// - No crash on empty config.
// - Style change
-// - Create light hook.
-// - Shadow distance retuning.
-// - Weird shadow area in Rotten Vale.
// - Hotload nukes config?
//
// Areas that need Shadow Distance retuning:
-// - Exit of central camp in Horfrost Reach.
-// - Sporepuff area in The Ancient Forest.
-// - Wildspire Waste entrence to enclosed area past the waterfall.
-// - The Rotten Vale jump out of Southeast Camp. Wall on the opposite side slightly to the left.
-// - Special Arena.
-// - Elder's Recess Lavasioth area.
-// - Hoarfrost pit area with wedge beetles.
+// - Exit of central camp in Horfrost Reach.
+// - Sporepuff area in The Ancient Forest.
+// - Wildspire Waste entrence to enclosed area past the waterfall.
+// - The Rotten Vale jump out of Southeast Camp. Wall on the opposite side slightly to the left.
+// - Rotten vale lower area.
+// - Special Arena.
+// - Elder's Recess Lavasioth area.
+// - Hoarfrost pit area with wedge beetles.
//
// Known issues to think about:
-// - Hair clipping while looking down.
+// - Hair clipping when character looks down.
+// - Vangis headband.
// - Volume rendering can look really bad with multiple overlapped sources(?) (Guding lands vines).
// - Screen space reflections often look bad.
-// - Facial contact shadows incorrectly move based on camera position.
+// - Facial contact shadows unnaturally move based on camera position.
namespace WorldTuningTool
{
+ using static Config;
+
public unsafe class Plugin : IPlugin
{
public string Name => "World Tuning Tool";
@@ -101,11 +100,8 @@ namespace WorldTuningTool
private static bool StringToBoolean(string s) { return Convert.ToBoolean(s, CultureInfo.InvariantCulture); }
private static int StringToInt32(string s, int fromBase = 10)
{
- if (fromBase == 10) {
- return Convert.ToInt32(s, CultureInfo.InvariantCulture);
- } else {
- return Convert.ToInt32(s, fromBase);
- }
+ if (fromBase == 10) return Convert.ToInt32(s, CultureInfo.InvariantCulture);
+ return Convert.ToInt32(s, fromBase);
}
private static string SingleToString(float f, string? format = null) { return f.ToString(format, CultureInfo.InvariantCulture); }
private static string BooleanToString(bool b) { return b.ToString(CultureInfo.InvariantCulture); }
@@ -113,16 +109,10 @@ namespace WorldTuningTool
public static Vector3 StringToVector3(string s, char delim = ',')
{
- if (String.IsNullOrEmpty(s))
- {
- throw new FormatException();
- }
- string[] vs = s.Split(delim).Select(v => v.Trim()).ToArray();
- if (vs.Length != 3)
- {
- throw new FormatException();
- }
- return new Vector3(StringToSingle(vs[0]), StringToSingle(vs[1]), StringToSingle(vs[2]));
+ if (String.IsNullOrEmpty(s)) throw new FormatException();
+ string[] sp = s.Split(delim).Select(v => v.Trim()).ToArray();
+ if (sp.Length != 3) throw new FormatException();
+ return new Vector3(StringToSingle(sp[0]), StringToSingle(sp[1]), StringToSingle(sp[2]));
}
private static string Vector3ToString(Vector3 v)
@@ -146,14 +136,14 @@ namespace WorldTuningTool
SHADOW_RESOLUTION
}
- static IPlugin? Instance = null;
+ private static IPlugin? Instance = null;
- static Config getConfig()
+ private static Config getConfig()
{
return ConfigManager.GetConfig<Config>(Instance!);
}
- static void reorderConfig(Config config, List<Override> overrides)
+ private static void rebuildConfig(Config config, List<Override> overrides)
{
List<Override> selectedGlobals = config.Globals[selectedGlobal];
selectedGlobals.Clear();
@@ -167,7 +157,7 @@ namespace WorldTuningTool
private const int SelectedNotSaved = 1;
private const int SetNotSaved = (1 << 1);
- static void saveConfig(Config config)
+ private static void saveConfig(Config config)
{
List<Override> tmpOverrides = config.Overrides[globalStage];
config.Overrides.Remove(globalStage);
@@ -249,10 +239,8 @@ namespace WorldTuningTool
if (!superseded && param != null)
{
// If Global is selected, check if superseded by a currentStage override.
- superseded |= globalOverrides == null && stageOverrides != null &&
- overridesContainsParam(stageOverrides, param);
- // Any other selectedStage override is either inactive or could only be superseded by a
- // set or external override.
+ superseded |= globalOverrides == null && stageOverrides != null && overridesContainsParam(stageOverrides, param);
+ // Any other selectedStage override is either inactive or could only be superseded by a set or external override.
superseded |= selectedSet != "" && overridesContainsParam(config.Sets[selectedSet], param);
superseded |= overridesContainsParam(externalOverrides.Values, param);
}
@@ -483,7 +471,7 @@ namespace WorldTuningTool
overrideForStage = false;
}
- public void OverrideValue(Vector4 v4, int i1)
+ public void SetOverrideValue(Vector4 v4, int i1)
{
if (queuedOverride)
{
@@ -818,6 +806,31 @@ namespace WorldTuningTool
ImGui.PopStyleVar();
}
+ public string SetByLine(Config config, List<Override>? stageOverrides, List<Override>? globalOverrides, bool forSet, bool allowGlobal)
+ {
+ // Reverse order of selectedOverrideSuperseded().
+ if (overridesContainsParam(externalOverrides.Values, this))
+ {
+ return "Set by 'External'";
+ }
+ Assert(!forSet);
+ if (selectedSet != "" && overridesContainsParam(config.Sets[selectedSet], this))
+ {
+ return $"Set by '{selectedSet}'";
+ }
+ if ((allowGlobal || globalOverrides == null) && stageOverrides != null && overridesContainsParam(stageOverrides, this))
+ {
+ return $"Set by '{StageToString(currentStage)}'";
+ }
+ if (allowGlobal)
+ {
+ return "Set by \'Global\'";
+ }
+ // Superseded because inactive.
+ Assert(globalOverrides != null && selectedStage != currentStage);
+ return "";
+ }
+
public void Draw(float width, bool assumeOverride = false)
{
Draw(ref valueV, ref valueInt, width, assumeOverride);
@@ -854,11 +867,18 @@ namespace WorldTuningTool
{
if (overrideForStage)
{
- ImGui.Text("Contained in Config");
+ Config config = getConfig();
+ List<Override>? globalOverrides = config.Overrides[globalStage];
+ List<Override>? stageOverrides = maybeGetStageOverrides(config);
+ ImGui.Text(SetByLine(config, stageOverrides, globalOverrides, false, true));
+ }
+ else if (overrideValue)
+ {
+ ImGui.Text("Set");
}
else
{
- ImGui.Text("Override");
+ ImGui.Text("Set override");
}
ImGui.EndTooltip();
}
@@ -977,13 +997,13 @@ namespace WorldTuningTool
selectedOverrides.Add(ov);
if (selectedStage == globalStage)
{
- reorderConfig(config, selectedOverrides);
+ rebuildConfig(config, selectedOverrides);
}
configState |= SelectedNotSaved;
}
if (ImGui.BeginItemTooltip())
{
- ImGui.Text($"Add to '{Config.StageToString(selectedStage)}'");
+ ImGui.Text($"Add to '{StageToString(selectedStage)}'");
ImGui.EndTooltip();
}
}
@@ -1186,7 +1206,7 @@ namespace WorldTuningTool
if (Param != null)
{
Param.OverrideOn(true);
- Param.OverrideValue(valueV, valueInt);
+ Param.SetOverrideValue(valueV, valueInt);
}
}
@@ -1203,8 +1223,7 @@ namespace WorldTuningTool
public void Draw(bool forSet, List<Override>? currentOverrides, List<Override>? stageOverrides, List<Override>? globalOverrides, bool superseded, float width)
{
Assert(!superseded == isSet);
- bool fade = superseded;
- if (fade)
+ if (superseded)
{
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
}
@@ -1213,7 +1232,13 @@ namespace WorldTuningTool
ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true);
}
ImGui.PushItemWidth(width * 0.475f);
- if (ImGui.BeginCombo("##Parameters", (Param != null) ? Param.Name : "", ImGuiComboFlags.HeightLarge))
+ bool beginCombo = ImGui.BeginCombo("##Parameters", (Param != null) ? Param.Name : "", ImGuiComboFlags.HeightLarge);
+ if (superseded)
+ {
+ ImGui.PopStyleVar();
+ }
+ Config config = getConfig();
+ if (beginCombo)
{
if (currentOverrides != null)
{
@@ -1268,7 +1293,6 @@ namespace WorldTuningTool
}
else
{
- Config config = getConfig();
superseded = selectedOverrideSuperseded(config, globalOverrides, stageOverrides, Param);
if (!superseded)
{
@@ -1296,11 +1320,15 @@ namespace WorldTuningTool
if (Param != null)
{
ImGui.SameLine();
+ if (superseded)
+ {
+ ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f);
+ }
if (Param.DrawValue(ref valueV, ref valueInt, width, false))
{
if (!superseded)
{
- Param.OverrideValue(valueV, valueInt);
+ Param.SetOverrideValue(valueV, valueInt);
}
}
(Vector4 v4, int i1) = Param.GetValue();
@@ -1315,11 +1343,11 @@ namespace WorldTuningTool
valueInt = sValueInt;
if (!superseded)
{
- Param.OverrideValue(valueV, valueInt);
+ Param.SetOverrideValue(valueV, valueInt);
}
}
}
- if (fade)
+ if (superseded)
{
ImGui.PopStyleVar();
}
@@ -1343,47 +1371,15 @@ namespace WorldTuningTool
else if (valueDiffers)
{
ImGui.SameLine();
- if (!superseded)
+ string byLine = "";
+ if (superseded)
{
- Param.DrawReferenceValue("Current", v4, i1);
- }
- else
- {
- if (forSet)
- {
- Assert(overridesContainsParam(externalOverrides.Values, Param));
- Param.DrawReferenceValue("Set by 'External'", v4, i1);
- }
- else
- {
- Config config = getConfig();
- // Reverse order of selectedOverrideSuperseded().
- if (overridesContainsParam(externalOverrides.Values, Param))
- {
- Param.DrawReferenceValue("Set by 'External'", v4, i1);
- }
- else if (selectedSet != "" && overridesContainsParam(config.Sets[selectedSet], Param))
- {
- Param.DrawReferenceValue($"Set by '{selectedSet}'", v4, i1);
- }
- else if (globalOverrides == null && stageOverrides != null &&
- overridesContainsParam(stageOverrides, Param))
- {
- Param.DrawReferenceValue($"Set by '{Config.StageToString(currentStage)}'", v4, i1);
- }
- else // Superseded because inactive.
- {
- Assert(globalOverrides != null && selectedStage != currentStage);
- Param.DrawReferenceValue("Current", v4, i1);
- }
- }
+ // Global is the lowest priority so "Set by 'Global'" never applies here.
+ byLine = Param.SetByLine(config, stageOverrides, globalOverrides, forSet, false);
}
+ Param.DrawReferenceValue((byLine == "") ? "Current" : byLine, v4, i1);
}
}
- else if (fade)
- {
- ImGui.PopStyleVar();
- }
}
}
@@ -1414,6 +1410,8 @@ namespace WorldTuningTool
private static MtObject? sMhMain = null;
private static MtObject? sMhRender = null;
+ private static Lights lights = new Lights();
+
private static Parameter hqMode = newParameter<bool>("HQ Mode", 0xE9A3, ParameterType.BOOL);
private static Parameter[] lodParameters = {
@@ -1487,7 +1485,7 @@ namespace WorldTuningTool
newParameter<float>("Capsule Light Dir XZY", 0xE548, ParameterType.VECTOR3),
newParameterView<float>("Capsule Light W Dir", 0xE560, ParameterType.VECTOR3),
newParameter<float>("Capsule Light Angle", 0xE5B0, ParameterType.FLOAT),
- newParameter<float>("Capsule AO Intensity", 0xE5B8, ParameterType.FLOAT)
+ newParameter<float>("Capsule AO Intensity", 0xE5B8, ParameterType.FLOAT, pStep(0.00025f))
};
private delegate void UpdateSSAOParams(nint stackOffset);
@@ -1595,7 +1593,7 @@ namespace WorldTuningTool
private delegate void UpdateLightingParameters(nint stackOffset, nint lightingObjectInternal);
private Hook<UpdateLightingParameters>? updateLightingParams;
private Hook<UpdateLightingParameters>? updateLutBlend;
- private static WorldLUTs luts = new WorldLUTs();
+ private static LUT luts = new LUT();
private static Parameter[] lightingParameters = {
newParameter<int>("Light Tone Map Type", 0x16C, ParameterType.INT, pMinMaxStep(1, 6, 1)),
newParameter<bool>("Light Compute Luminance", 0x170, ParameterType.BOOL),
@@ -1636,8 +1634,6 @@ namespace WorldTuningTool
private Hook<CreateBloomObject>? createBloomObject;
private Hook<CreateBloomObject2>? createBloomObject2;
private Hook<DestroyBloomObject>? destroyBloomObject;
- //private delegate void UpdateBloomParams(nint bloomObjectInternal, nint unknownPtr);
- //private Hook<UpdateBloomParams>? updateBloomParams;
private nint bloomObject = 0x0;
private static Parameter[] bloomParameters = {
// Disabling 'Draw' is a bad way to disable bloom. It breaks the filter on initial load which
@@ -1882,7 +1878,9 @@ namespace WorldTuningTool
setShadowQuality.Invoke(MemoryUtil.Read<int>(sMhScene!.Instance + 0x5530) + 1);
}
+#if SHADER_FEATURES
private bool fullResSSLR = false;
+#endif
private Patch ssrRes1;
private Patch ssrRes2;
private Patch ssrRes3;
@@ -1993,89 +1991,6 @@ namespace WorldTuningTool
private bool disableReducedRateAnimations = false;
private Patch zeroFrameSkip;
- private class Light
- {
- 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 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].OverrideValue(default, 255);
- Parameters[1].OverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0);
- Parameters[3].OverrideValue(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<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;
-
public int AddOverride(string name, Vector4 v4, int i1)
{
foreach (Parameter param in allParameters)
@@ -2138,7 +2053,7 @@ namespace WorldTuningTool
foreach (StageExt stage in Enum.GetValues(typeof(StageExt)))
{
if (stage == StageExt.Global) continue;
- Assert(Config.OrderedStages.Contains(stage));
+ Assert(OrderedStages.Contains(stage));
}
onAreaChange = Hook.Create<OnAreaChange>(0x141AC27D0, OnAreaChangeHook); // nint
@@ -2149,7 +2064,7 @@ namespace WorldTuningTool
// Light Dir XZY is updated seperately at 0x1420397F0, we assume this function always happens later, though.
updateCapsuleAoParams = Hook.Create<UpdateCapsuleAOParams>(0x141B19E10, UpdateCapsuleAOParamsHook); // nint
- // These run during cutscenes.
+ // These run in a loop during cutscenes.
updateSSAOParams = Hook.Create<UpdateSSAOParams>(0x1416D8B10, UpdateSSAOParamsHook); // nint
updateSSLRParams = Hook.Create<UpdateSSLRParams>(0x1416DA3F0, UpdateSSLRParamsHook); // nint
updateLightingParams = Hook.Create<UpdateLightingParameters>(0x1416DAAB0, UpdateLightingParametersHook); // nint, nint
@@ -2161,7 +2076,6 @@ namespace WorldTuningTool
createBloomObject = Hook.Create<CreateBloomObject>(0x1424CB3C0, CreateBloomObjectHook);
createBloomObject2 = Hook.Create<CreateBloomObject2>(0x1424CB5E0, CreateBloomObject2Hook); // nint
destroyBloomObject = Hook.Create<DestroyBloomObject>(0x1424CB750, DestroyBloomObjectHook); // nint, int
- //updateBloomParams = Hook.Create<UpdateBloomParams>(0x1424CD570, UpdateBloomParamsHook); // nint, nint
createDofObject = Hook.Create<CreateDofObject>(0x142421E80, CreateDofObjectHook);
createDofObject2 = Hook.Create<CreateDofObject2>(0x1424220A0, CreateDofObject2Hook); // nint
@@ -2181,12 +2095,7 @@ namespace WorldTuningTool
createTAAObject2 = Hook.Create<CreateTAAObject2>(0x142391320, CreateTAAObject2Hook); // nint
destroyTAAObject = Hook.Create<DestroyTAAObject>(0x1423916E0, DestroyTAAObjectHook); // nint, int
- createLight = new NativeFunction<int, nint>(0x1418A3EF0);
- //createLightObject = Hook.Create<CreateLightObject>(0x1418A3EF0, CreateLightObjectHook);
- destroyLightObject = Hook.Create<DestroyLightObject>(0x141F87D90, DestroyLightObjectHook);
- addToScene = new NativeAction<nint, int, nint, int>(0x142219070);
- removeFromScene = new NativeAction<nint>(0x142228F10);
- updateLights = Hook.Create<UpdateLights>(0x141F88F30, UpdateLightsHook);
+ lights.Initialize();
nint addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 10 48 89 74 24 18 48 89 7C 24 20 55 41 56 41 57 48 8B EC 48 83 EC 30 48 8B FA 48 8B D9 E8 AA B6 C1 FF 48 8B 47 10 48 8D 57 50"));
Assert(addr == 0x141AB2260); // nint, nint
@@ -2382,9 +2291,9 @@ namespace WorldTuningTool
public void OnPreMain()
{
Config config = getConfig();
- Config.PatchConfig patches = config.Patches;
- fullResSSLR = patches.FullResolutionSSLR;
+ PatchConfig patches = config.Patches;
#if SHADER_FEATURES
+ fullResSSLR = patches.FullResolutionSSLR;
if (fullResSSLR)
{
ssrRes1.Enable();
@@ -2478,7 +2387,7 @@ namespace WorldTuningTool
{
config.Overrides[globalStage].Add(ovG);
}
- foreach (StageExt area in Config.OrderedStages)
+ foreach (StageExt area in OrderedStages)
{
if (!config.Overrides.ContainsKey(area))
{
@@ -2873,20 +2782,6 @@ namespace WorldTuningTool
return destroyBloomObject!.Original(bloomObjectInternal, unknownInt);
}
- /*
- private void UpdateBloomParamsHook(nint bloomObjectInternal, nint unknownPtr)
- {
- if (bloomObject == bloomObjectInternal)
- {
- foreach (Parameter param in bloomParameters)
- {
- param.Update(bloomObject);
- }
- }
- updateBloomParams!.Original(bloomObjectInternal, unknownPtr);
- }
- */
-
private nint CreateLightingObjectHook()
{
lightingObject = createLightingObject!.Original();
@@ -2968,80 +2863,6 @@ namespace WorldTuningTool
staticShadowParams!.Original(shadowParamsStatic, shadowObjectInternal);
}
- /*
- 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 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);
- }
-
- 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 HandleSetChange(string prevSet, List<Override> globalOverrides, List<Override>? stageOverrides)
{
Config config = getConfig();
@@ -3124,10 +2945,6 @@ namespace WorldTuningTool
private void HandleAreaChange(StageExt stage)
{
Config config = getConfig();
- if (!config.Overrides.ContainsKey(stage))
- {
- return;
- }
List<Override> prevOverrides = config.Overrides[previousStage];
List<Override> globalOverrides = config.Overrides[globalStage];
BeginTransition();
@@ -3146,6 +2963,11 @@ namespace WorldTuningTool
}
}
}
+ if (!config.Overrides.ContainsKey(stage))
+ {
+ Log.Error($"Unknown stage: {stage}");
+ stage = globalStage;
+ }
if (stage != globalStage)
{
List<Override> stageOverrides = config.Overrides[stage];
@@ -3182,13 +3004,13 @@ namespace WorldTuningTool
float width = ImGui.GetWindowWidth();
width /= width / (600.0f * ImGui.GetIO().FontGlobalScale);
- ImGui.Text($"Current Stage: {Config.StageToString(currentStage)}");
+ ImGui.Text($"Current Stage: {StageToString(currentStage)}");
ImGui.PushItemWidth(width * 0.35f);
- if (ImGui.BeginCombo("##Stage", Config.StageToString(selectedStage), ImGuiComboFlags.HeightLarge))
+ if (ImGui.BeginCombo("##Stage", StageToString(selectedStage), ImGuiComboFlags.HeightLarge))
{
- foreach (StageExt area in Config.OrderedStages)
+ foreach (StageExt area in OrderedStages)
{
- string name = Config.StageToString(area);
+ string name = StageToString(area);
bool isSelected = selectedStage == area;
if (ImGui.Selectable(name, isSelected))
{
@@ -3326,7 +3148,7 @@ namespace WorldTuningTool
{
if (selectedStage == globalStage)
{
- reorderConfig(config, selectedOverrides);
+ rebuildConfig(config, selectedOverrides);
}
configState |= SelectedNotSaved;
}
@@ -3530,8 +3352,9 @@ namespace WorldTuningTool
if (ImGui.CollapsingHeader("Patches"))
{
- Config.PatchConfig patches = config.Patches;
+ PatchConfig patches = config.Patches;
+#if SHADER_FEATURES
if (ImGui.Checkbox("Full Resolution Screen Space Reflections (Requires Restart)", ref fullResSSLR))
{
patches.FullResolutionSSLR = fullResSSLR;
@@ -3543,6 +3366,7 @@ namespace WorldTuningTool
ImGui.Text("Restart Required");
ImGui.EndTooltip();
}
+#endif
if (ImGui.Checkbox("Volume Rendering Full Resolution Blur Pass (Requires Area Change)", ref fullResVolumeBlur))
{
@@ -3560,7 +3384,7 @@ namespace WorldTuningTool
}
if (ImGui.BeginItemTooltip())
{
- ImGui.Text("This can get rid of excessive aliasing when something is in front of a volumetric effect.\nMove to a different area for this to apply, it will stay applied after that.");
+ ImGui.Text("This can get rid of excessive aliasing when something is in front of a volumetric effect.\nMove to a different area for this to apply. It will stay applied after that.");
ImGui.EndTooltip();
}
@@ -3647,83 +3471,7 @@ namespace WorldTuningTool
if (ImGui.CollapsingHeader("Lights"))
{
- /*
- 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<nint>(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<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.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();
+ lights.DrawUI(width);
}
bool expanded = ImGui.CollapsingHeader("Parameters");
@@ -3864,12 +3612,12 @@ namespace WorldTuningTool
nint lutMap0 = MemoryUtil.Read<nint>(lightingObject + 0x1A8);
if (lutMap0 != 0x0)
{
- luts.DrawLUT(lutMap0, lightingObject, 0, width);
+ luts.DrawUI(lutMap0, lightingObject, 0, width);
}
nint lutMap1 = MemoryUtil.Read<nint>(lightingObject + 0x1B0);
if (lutMap1 != 0x0)
{
- luts.DrawLUT(lutMap1, lightingObject, 1, width);
+ luts.DrawUI(lutMap1, lightingObject, 1, width);
}
}
foreach (Parameter param in lightingParameters)