From f0551fb20f92753e8d97bb746e3563364d09e7d9 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sun, 5 Apr 2026 15:54:53 -0400 Subject: Add PATCH_FLOAT and some test stuff Signed-off-by: Andrew Opalach --- Plugin.cs | 215 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 168 insertions(+), 47 deletions(-) diff --git a/Plugin.cs b/Plugin.cs index 0258ef9..a7d4394 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -9,6 +9,7 @@ using System.Runtime.InteropServices; using ImGuiNET; using SharpPluginLoader.Core; +//using SharpPluginLoader.Core.Resources; using SharpPluginLoader.Core.Configuration; using SharpPluginLoader.Core.Memory; using SharpPluginLoader.Core.Entities; @@ -16,8 +17,14 @@ using SharpPluginLoader.Core.Entities; // @TODO: // - Inter-op. // - Lights. +// - float format. +// - Override presets. +// - Centeralize transition from global to stage. // - Try to understand shadow distance vs backforward distance vs bias. +// - Re-evaluate volume upsample shaders. +// - Guiding lands? // - Shadow distance retuning. +// - Weird shadow area in Rotten Vale. // - Descriptions. namespace WorldTuningTool @@ -63,11 +70,26 @@ namespace WorldTuningTool COLOR, FLOAT, VECTOR3, - VECTOR4 + VECTOR4, + PATCH_FLOAT + } + + static IPlugin? Instance = null; + + static Config getConfig() + { + return ConfigManager.GetConfig(Instance!); } private const float defaultParamWidth = 0.215f; + private static Stage selectedStage = Stage.InfinityOfNothingHandler; + private static Stage previousStage = selectedStage; + private static bool stageIsGlobal(Stage stage) + { + return stage == Stage.InfinityOfNothingHandler; + } + public abstract class Parameter { public string Name; @@ -106,6 +128,11 @@ namespace WorldTuningTool hiddenName = "##" + Name; this.offset = offset; Type = type; + if (Type == ParameterType.PATCH_FLOAT) + { + valueV.X = MemoryUtil.Read(offset); + pendingUpdate = false; + } PerFrame = perFrame; } @@ -157,6 +184,9 @@ namespace WorldTuningTool case ParameterType.VECTOR4: MemoryUtil.GetRef(lastAddr + offset) = valueV; break; + case ParameterType.PATCH_FLOAT: + new Patch(offset, BitConverter.GetBytes(valueV.X)).Enable(); + break; } } @@ -511,6 +541,17 @@ namespace WorldTuningTool } break; } + case ParameterType.PATCH_FLOAT: + { + ImGui.SetNextItemWidth(width * defaultParamWidth); + float f1 = v4.X; + if (ImGui.InputFloat(label, ref f1, 0.0f, 0.0f, "%.4f", ImGuiInputTextFlags.EnterReturnsTrue)) + { + v4.X = f1; + valueChanged = true; + } + break; + } } return valueChanged; } @@ -546,7 +587,7 @@ namespace WorldTuningTool { if (overrideForStage) { - ImGui.Text("Overridden by Config"); + ImGui.Text("Set by Config/Preset"); } else { @@ -569,12 +610,29 @@ namespace WorldTuningTool { writeCurrentValue(); } + if (!assumeOverride && overrideValue && !overrideForStage) + { + ImGui.SameLine(); + if (ImGui.Button("▲")) + { + Config config = getConfig(); + List stageOverrides = config.Overrides[selectedStage]; + Override ov = new Override(this, v4, i1); + ov.Set(); + stageOverrides.Add(ov); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Add to Selected Stage"); + ImGui.EndTooltip(); + } + } if (!assumeOverride && overrideValue && !pendingUpdate) { ImGui.SameLine(); if (!bValue) { - if (ImGui.Button("B >")) + if (ImGui.Button("B")) { bValueV = oValueV; bValueInt = oValueInt; @@ -634,6 +692,7 @@ namespace WorldTuningTool break; } case ParameterType.FLOAT: + case ParameterType.PATCH_FLOAT: { ImGui.Text($"(Original: {oValueV.X:0.00000})"); break; @@ -768,6 +827,7 @@ namespace WorldTuningTool case ParameterType.COLOR: return valueInt.ToString("X8"); case ParameterType.FLOAT: + case ParameterType.PATCH_FLOAT: return valueV.X.ToString(); case ParameterType.VECTOR3: { @@ -804,6 +864,7 @@ namespace WorldTuningTool valueInt = Convert.ToInt32(value, 16); break; case ParameterType.FLOAT: + case ParameterType.PATCH_FLOAT: valueV.X = Convert.ToSingle(value); break; case ParameterType.VECTOR3: @@ -824,16 +885,13 @@ namespace WorldTuningTool private int valueInt = 0; private bool isSet = false; - public Override() - { - } + public Override() { } public Override(Parameter param, Vector4 v4, int i1) { Param = param; valueV = v4; valueInt = i1; - Set(); } public void Set() @@ -930,9 +988,9 @@ namespace WorldTuningTool private delegate void UpdateSSAOParams(nint sceneObjectInternal, nint stackOffset); private Hook? updateSSAOParams; private static Parameter[] ssaoParameters = { - new Parameter("SSAO Depth Bias", 0xB4B0, ParameterType.FLOAT, false, 0.0001f), - new Parameter("SSAO Sloped Depth Bias", 0xB4B4, ParameterType.FLOAT, false, 0.0001f), - new Parameter("SSAO Max Depth Bias", 0xB4B8, ParameterType.FLOAT, false, 0.0001f), + new Parameter("SSAO Depth Bias", 0xB4B0, ParameterType.FLOAT, false, 0.00001f), + new Parameter("SSAO Sloped Depth Bias", 0xB4B4, ParameterType.FLOAT, false, 0.00001f), + new Parameter("SSAO Max Depth Bias", 0xB4B8, ParameterType.FLOAT, false, 0.00001f), new Parameter("SSAO Dispersion", 0xB4BC, ParameterType.FLOAT, false), new Parameter("SSAO Effect", 0xB430, ParameterType.FLOAT, false), new Parameter("SSAO Effect GI", 0xB434, ParameterType.FLOAT, false), @@ -965,7 +1023,6 @@ namespace WorldTuningTool new Parameter("SSLR Use Mipmap", 0xE650, ParameterType.BOOL, false), new Parameter("SSLR GBuffer Jitter", 0xB440, ParameterType.BOOL, false), }; - //private NativeAction refreshBroadAreaShadow; private static Parameter[] sceneParameters = { new Parameter("HQ Mode", 0xE9A3, ParameterType.BOOL, false), new Parameter("Shadow Cascade 2Way Bias (HQ)", 0x58, ParameterType.FLOAT, false), @@ -988,6 +1045,17 @@ namespace WorldTuningTool new Parameter("LOD Culling Length Bias", 0x224, ParameterType.FLOAT, false), new Parameter("LOD Culling Pixel Bias", 0x228, ParameterType.FLOAT, false), new Parameter("Is Calc LOD Bias Use Boundary", 0x218, ParameterType.BOOL, false), + /* + new Parameter("Debug View", 0x264, ParameterType.INT, false, 1), + new Parameter("Debug View Channel", 0x268, ParameterType.INT, false, 1), + new Parameter("Debug View Bg Alpha", 0x26C, ParameterType.FLOAT, false), + new Parameter("Debug View Fg Alpha", 0x270, ParameterType.FLOAT, false), + new Parameter("Debug Texture", 0x274, ParameterType.INT, false, 1), + new Parameter("Debug Sampler", 0x278, ParameterType.INT, false, 1), + new Parameter("Debug Cluster", 0x27C, ParameterType.INT, false, 1), + new Parameter("Debug Light Max Count", 0x280, ParameterType.INT, false, 1), + new Parameter("Wireframe", 0x284, ParameterType.BOOL, false), + */ new Parameter("Material Draw SS Normal", 0x5626, ParameterType.BOOL, false), new Parameter("Material Height Factor", 0x5628, ParameterType.FLOAT, false), new Parameter("Model Detail", 0x190, ParameterType.INT, false, 1), @@ -1000,6 +1068,8 @@ namespace WorldTuningTool new Parameter("Passthrough Correct", 0xE950, ParameterType.FLOAT, false), new Parameter("LOD Length Platform Bias[2]", 0x22C + (4 * 2), ParameterType.FLOAT, false), new Parameter("LOD Pixel Size Platform Bias[2]", 0x244 + (4 * 2), ParameterType.FLOAT, false), + new Parameter("Fake Light Intensity", 0xEC40, ParameterType.FLOAT, false), + new Parameter("Fake Light Blend", new IntPtr(0x141CDE0CE) + 0x6, ParameterType.PATCH_FLOAT, false), new Parameter("Contact Shadows Enabled", 0xB4EC, ParameterType.BOOL, false), new Parameter("Force Disable Contact Shadows", 0xB4ED, ParameterType.BOOL, false), new Parameter("Facial Contact Shadows Enabled", 0xB4EE, ParameterType.BOOL, false), @@ -1023,9 +1093,9 @@ namespace WorldTuningTool new Parameter("Broad Area Shadow Center", 0x5540, ParameterType.VECTOR3, false), new Parameter("Broad Area Shadow Range", 0x5560, ParameterType.VECTOR3, false), new Parameter("Broad Area Shadow Dir", 0x5550, ParameterType.VECTOR4, false), - //new Parameter("Broad Area Shadow Depth Bias", 0x5570, ParameterType.FLOAT, false, 0.0001f), - //new Parameter("Broad Area Shadow Sloped Depth Bias", 0x5574, ParameterType.FLOAT, false, 0.0001f), - //new Parameter("Broad Area Shadow Max Depth Bias", 0x5578, ParameterType.FLOAT, false, 0.0001f), + //new Parameter("Broad Area Shadow Depth Bias", 0x5570, ParameterType.FLOAT, false, 0.00001f), + //new Parameter("Broad Area Shadow Sloped Depth Bias", 0x5574, ParameterType.FLOAT, false, 0.00001f), + //new Parameter("Broad Area Shadow Max Depth Bias", 0x5578, ParameterType.FLOAT, false, 0.00001f), new Parameter("Broad Area Shadow Max LOD Level", 0x5524, ParameterType.FLOAT, false), new Parameter("Broad Area Shadow Culling Size", 0x5528, ParameterType.FLOAT, false), new Parameter("Broad Area Shadow Precision", 0x5518, ParameterType.INT, false, 1, 0, 2), // Maybe 3? @@ -1084,7 +1154,8 @@ namespace WorldTuningTool new Parameter("Vignetting Ellipticity", 0x204, ParameterType.FLOAT, true), new Parameter("Vignetting Offset", 0x1F8, ParameterType.FLOAT, true), new Parameter("Vignetting Pow", 0x1FC, ParameterType.FLOAT, true), - new Parameter("Vignetting Color", 0x208, ParameterType.COLOR, true) + new Parameter("Vignetting Color", 0x208, ParameterType.COLOR, true), + //new Parameter("Target Joint No", 0x240, ParameterType.INT, true, 1), }; private delegate nint CreateMotionBlurObject(); @@ -1126,6 +1197,16 @@ namespace WorldTuningTool new Parameter("Compute Luminance", 0x241, ParameterType.BOOL, false) }; + private static MtObject? sLightProbes = null; + private static Parameter[] lightProbesParameters = { + //new Parameter("Enable Neighbor Search", 0x40, ParameterType.BOOL, false), + //new Parameter("WF Count", 0x90, ParameterType.INT, false, 1), + //new Parameter("CU Mask", 0x94, ParameterType.HEX, false), + new Parameter("Debug Mode", 0x98, ParameterType.INT, false, 1), + //new Parameter("Daytime State", 0x9C, ParameterType.INT, true, 1), + //new Parameter("Daytime Interpolation", 0xA0, ParameterType.FLOAT, false), + //new Parameter("Max Iter", 0xA4, ParameterType.INT, true, 1) + }; private delegate nint CreateLightingObject(); private delegate nint DestroyLightingObject(nint lightingObjectInternal, int unknownInt); private Hook? createLightingObject; @@ -1158,6 +1239,7 @@ namespace WorldTuningTool private Hook? staticShadowParams; private static Parameter[] shadowParameters1 = { }; + // This is actually an InfiniteLight object. private static Parameter[] shadowParameters2 = { new Parameter("Color", 0xE0, ParameterType.FLOAT, true), new Parameter("Intensity", 0xF4, ParameterType.FLOAT, true), @@ -1169,7 +1251,7 @@ namespace WorldTuningTool new Parameter("Shadow Cast", 0x23, ParameterType.BOOL, true), new Parameter("Near Clip Distance", 0x28, ParameterType.FLOAT, true), new Parameter("Shadow Sloped Depth Bias", 0x40, ParameterType.FLOAT, true, 0.00001f), - new Parameter("Shadow Map Size", 0x30, ParameterType.INT, true), + new Parameter("Shadow Map Size", 0x30, ParameterType.INT, true), // Aligned to 128. new Parameter("Shadow Depth Bias", 0x38, ParameterType.FLOAT, true, 0.00001f), new Parameter("Shadow Max Depth Bias", 0x48, ParameterType.FLOAT, true, 0.00001f), new Parameter("Do Volumetric", 0x1F, ParameterType.BOOL, true), @@ -1200,9 +1282,9 @@ namespace WorldTuningTool new Parameter("Shadow Culling Length[1]", 0x18C, ParameterType.FLOAT, true), new Parameter("Shadow Culling Length[2]", 0x194, ParameterType.FLOAT, true), //new Parameter("Broad Area Shadow Range", 0x1B0, ParameterType.VECTOR3, true), - new Parameter("Broad Area Shadow Depth Bias", 0x1C4, ParameterType.FLOAT, true, 0.0001f), - new Parameter("Broad Area Shadow Sloped Depth Bias", 0x1CC, ParameterType.FLOAT, true, 0.0001f), - new Parameter("Broad Area Shadow Max Depth Bias", 0x1D4, ParameterType.FLOAT, true, 0.0001f), + new Parameter("Broad Area Shadow Depth Bias", 0x1C4, ParameterType.FLOAT, true, 0.00001f), + new Parameter("Broad Area Shadow Sloped Depth Bias", 0x1CC, ParameterType.FLOAT, true, 0.00001f), + new Parameter("Broad Area Shadow Max Depth Bias", 0x1D4, ParameterType.FLOAT, true, 0.00001f), new Parameter("Primary Shadow Sample Num", 0x1DC, ParameterType.INT, true), new Parameter("Primary Shadow Radius", 0x1EC, ParameterType.FLOAT, true, 0.0001f), new Parameter("Fov", 0x1F4, ParameterType.FLOAT, true, 0.0001f), @@ -1211,6 +1293,10 @@ namespace WorldTuningTool new Parameter("Is Discretization Fov Mode", 0x205, ParameterType.BOOL, true) }; + private static MtObject? sMain = null; + private static MtObject? sLightLinker = null; + private static MtObject? sMhSpeedTree = null; + private static Parameter[] allParameters = sceneParameters .Concat(ssaoParameters) .Concat(sslrParameters) @@ -1338,6 +1424,7 @@ namespace WorldTuningTool new Parameter("Do Volumetric", 0x590, ParameterType.BOOL, true), new Parameter("Near Clip Distance", 0x1B4, ParameterType.FLOAT, true), new Parameter("Shadow Cast", 0x138, ParameterType.FLAG, false, (1 << 23)), + new Parameter("Shadow Map Size", 0x1B8, ParameterType.INT, false), // Aligned to 128. new Parameter("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, true, 0.00001f), new Parameter("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, true, 0.00001f), new Parameter("Shadow Max Depth Bias", 0x584, ParameterType.FLOAT, true, 0.00001f), @@ -1392,8 +1479,6 @@ namespace WorldTuningTool private delegate void UpdateLights(nint lightObject); private Hook? updateLights; - private static MtObject? sMain = null; - private Dictionary externalOverrides = new Dictionary(); private int externalId = 0; @@ -1404,7 +1489,9 @@ namespace WorldTuningTool if (param.Name == name) { externalId++; - externalOverrides.Add(externalId, new Override(param, v4, i1)); + Override ov = new Override(param, v4, i1); + ov.Set(); + externalOverrides.Add(externalId, ov); return externalId; } } @@ -1415,7 +1502,7 @@ namespace WorldTuningTool { if (externalOverrides.ContainsKey(id)) { - Config config = ConfigManager.GetConfig(this); + Config config = getConfig(); List globalOverrides = config.Overrides[Stage.InfinityOfNothingHandler]; Override ovE = externalOverrides[id]; ovE.Unset(); @@ -1426,6 +1513,8 @@ namespace WorldTuningTool public PluginData Initialize() { + Instance = this; + onAreaChange = Hook.Create(0x141AC27D0, OnAreaChangeHook); // nint // These run during cutscenes. @@ -1462,8 +1551,6 @@ namespace WorldTuningTool setShadowQuality = new NativeAction(0x14043FF80); - //refreshBroadAreaShadow = new NativeAction(0x142284B20); - addr = PatternScanner.FindFirst(Pattern.FromString("48 83 EC 28 F3 0F 10 0D ?? ?? ?? ?? 80 F9 04 75 2F 48 8B 0D ?? ?? ?? ?? E8 D3 8A E4 01 48 8B 0D ?? ?? ?? ?? 33 D2 E8 ?? ?? ?? ??")); #if ADDR_ASSERTS Assert(addr == 0x14043FF80); @@ -1595,12 +1682,15 @@ namespace WorldTuningTool removeFromScene = new NativeAction(0x142228F10); updateLights = Hook.Create(0x141F88F30, UpdateLightsHook); + // Gui animation rate? + //new Patch(new IntPtr(0x142F15C90), BitConverter.GetBytes(60.0f)).Enable(); + return new PluginData(); } public void OnPreMain() { - Config config = ConfigManager.GetConfig(this); + Config config = getConfig(); Config.PatchConfig patches = config.Patches; tripleShadowResolution = patches.TripleShadowResolution; if (tripleShadowResolution) @@ -1638,7 +1728,10 @@ namespace WorldTuningTool { sMain = SingletonManager.GetSingleton("sMhMain")!; sMhScene = SingletonManager.GetSingleton("sMhScene")!; - Config config = ConfigManager.GetConfig(this); + sLightProbes = SingletonManager.GetSingleton("sLightProbes")!; + sLightLinker = SingletonManager.GetSingleton("sLightLinker")!; + sMhSpeedTree = SingletonManager.GetSingleton("sMhSpeedTree")!; + Config config = getConfig(); foreach (Stage area in Enum.GetValues(typeof(Stage))) { if (!config.Overrides.ContainsKey(area)) @@ -1654,6 +1747,26 @@ namespace WorldTuningTool ConfigManager.SaveConfig(this); } + /* + // https://github.com/AsteriskAmpersand/CTC-MHW-Editor/blob/9ec6303042690478398801b1bb860a2d38298eee/structures/Ctc.py#L23 + private static bool adjustCtcParams = false; + private static float stepTimeFps = 60.0f; + public void OnResourceLoad(Resource? resource, MtDti dti, string path, LoadFlags flags) + { + if (adjustCtcParams && resource != null && resource.FileExtension == "ctc") + { + Log.Info($"Attempting to increase physics update rate of {resource.FilePath} @ {resource.Instance:X}."); + int numARecords = MemoryUtil.GetRef(resource.Instance + 0xB8); + nint aRecords = MemoryUtil.GetRef(resource.Instance + 0xF8); + for (int i = 0; i < numARecords; i++) + { + nint aRecord = aRecords + (0x50 * i); + } + MemoryUtil.GetRef(resource.Instance + 0xC4) = 1.0f / stepTimeFps; + } + } + */ + public void OnUpdate(float deltaTime) { if (fxaaObject != 0x0) @@ -1706,6 +1819,13 @@ namespace WorldTuningTool } } } + if (sLightProbes!.Instance != 0x0) + { + foreach (Parameter param in lightProbesParameters) + { + param.Update(sLightProbes!.Instance); + } + } if (sMhScene!.Instance != 0x0) { foreach (Parameter param in ssaoParameters) @@ -1962,13 +2082,6 @@ namespace WorldTuningTool staticShadowParams!.Original(shadowObjectStatic, shadowObjectInternal); } - private Stage previousStage = Stage.InfinityOfNothingHandler; - private Stage selectedStage = Stage.InfinityOfNothingHandler; - private static bool stageIsGlobal(Stage stage) - { - return stage == Stage.InfinityOfNothingHandler; - } - private void OnAreaChangeHook(nint unknownPtr) { onAreaChange!.Original(unknownPtr); @@ -1978,7 +2091,7 @@ namespace WorldTuningTool stage = Stage.InfinityOfNothingHandler; } if (stage == previousStage) return; - Config config = ConfigManager.GetConfig(this); + Config config = getConfig(); List prevOverrides = config.Overrides[previousStage]; previousStage = stage; List? globalOverrides = null; @@ -2081,7 +2194,7 @@ namespace WorldTuningTool { selectedStage = Stage.InfinityOfNothingHandler; } - Config config = ConfigManager.GetConfig(this); + Config config = getConfig(); List stageOverrides = config.Overrides[selectedStage]; List? globalOverrides = null; if (!stageIsGlobal(selectedStage)) @@ -2273,9 +2386,11 @@ namespace WorldTuningTool if (ImGui.CollapsingHeader("Lights")) { - ImGui.PushItemWidth(width * 0.25f); - //ImGui.InputInt("Type", ref requestLightType, 1); - //ImGui.SameLine(); + /* + ImGui.NextItemWidth(width * 0.25f); + ImGui.InputInt("Type", ref requestLightType, 1); + ImGui.SameLine(); + */ if (ImGui.Button("New")) { nint lightObject = createLight.Invoke(requestLightType); @@ -2284,13 +2399,12 @@ namespace WorldTuningTool if (player != null) { pos = player.Position; - pos.Y += 20.0f; + pos.Y += 30.0f; } ourLights.Add(new Light(lightObject, pos)); // mov byte ptr[rsp+20],00 unaccounted for, hopefully it doesn't matter. addToScene.Invoke(MemoryUtil.Read(0x1451238C8), 0x16, lightObject, 0x0); } - ImGui.PopItemWidth(); ImGui.Separator(); for (int i = 0; i < ourLights.Count; i++) { @@ -2450,16 +2564,21 @@ namespace WorldTuningTool ImGui.PopID(); } + if (ImGui.CollapsingHeader("Light Probes Parameters")) + { + ImGui.PushID("LightProbes"); + ImGui.Text($"Address: {sLightProbes!.Instance:X}"); + foreach (Parameter param in lightProbesParameters) + { + param.Draw(width); + } + ImGui.PopID(); + } + if (ImGui.CollapsingHeader("Scene Parameters")) { ImGui.PushID("Scene"); ImGui.Text($"Address: {sMhScene!.Instance:X}"); - /* - if (ImGui.Button("Refresh Broad Area Shadow")) - { - refreshBroadAreaShadow.Invoke(sMhScene!.Instance); - } - */ foreach (Parameter param in sceneParameters) { param.Draw(width); @@ -2482,6 +2601,8 @@ namespace WorldTuningTool } ImGui.InputFloat("Max FPS", ref MemoryUtil.GetRef(sMain!.Instance + 0x5C)); ImGui.PopItemWidth(); + ImGui.Text($"sLightLinker: {sLightLinker!.Instance:X}"); + ImGui.Text($"sMhSpeedTree: {sMhSpeedTree!.Instance:X}"); } } -- cgit v1.2.3-101-g0448