Refactor the fuck out of ModuleShieldGeneratorManager with generic multiplier handling

This commit is contained in:
2025-02-24 00:06:04 +01:00
parent 5df952a69a
commit a53bcc246e

View File

@@ -1,116 +1,129 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using BepInEx.Configuration;
using HarmonyLib; using HarmonyLib;
namespace TerraTech { namespace TerraTech {
[HarmonyPatch] [HarmonyPatch]
public class ModuleShieldGeneratorManager { public class ModuleShieldGeneratorManager {
private static Dictionary<ModuleShieldGenerator, float> healingHeartbeatInterval = private class MultipliedField<TObject, TValue> {
new Dictionary<ModuleShieldGenerator, float>(); private readonly string fieldName;
private static Dictionary<ModuleShieldGenerator, float> radius = new Dictionary<ModuleShieldGenerator, float>(); private readonly ConfigEntry<TValue> multiplier;
private static Dictionary<ModuleShieldGenerator, float> powerUpDelay = private readonly Traverse parentTraverse;
new Dictionary<ModuleShieldGenerator, float>(); private TValue originalValue;
public MultipliedField(string fieldName, ConfigEntry<TValue> multiplier, Traverse parentTraverse) {
this.fieldName = fieldName;
this.multiplier = multiplier;
this.parentTraverse = parentTraverse;
}
public TValue GetValue() {
return (TValue)parentTraverse.Field(fieldName).GetValue();
}
public void SetValue(TValue value) {
parentTraverse.Field(fieldName).SetValue(value);
}
public void CaptureOriginal() {
originalValue = GetValue();
}
public void Apply() {
// This assumes TValue implements multiplication with multiplier.Value
// For float, this would be originalValue * multiplier.Value
dynamic originalDynamic = originalValue;
dynamic multiplierDynamic = multiplier.Value;
SetValue((TValue)(originalDynamic * multiplierDynamic));
}
public void Restore() {
SetValue(originalValue);
}
public void LogValue(string prefix) {
if (!Main.debug.Value)
return;
Console.WriteLine("{0} {1}; {2}: {3}", prefix, parentTraverse.ToString(), fieldName, GetValue());
}
}
private class MultipliedObject<T> {
private readonly Traverse objectTraverse;
private readonly List<MultipliedField<T, float>> fields = new List<MultipliedField<T, float>>();
public MultipliedObject(T instance) objectTraverse = Traverse.Create(instance);
public void AddField(string fieldName, ConfigEntry<float> multiplier) fields.Add(
new MultipliedField<T, float>(fieldName, multiplier, objectTraverse));
public void CaptureFrom() foreach (var field in fields) field.CaptureOriginal();
public void ApplyTo() foreach (var field in fields) field.Apply();
public void RestoreTo() foreach (var field in fields) field.Restore();
public void LogValues(string prefix) {
if (!Main.debug.Value)
return;
foreach (var field in fields) field.LogValue(prefix);
}
}
private static Dictionary<ModuleShieldGenerator, MultipliedObject<ModuleShieldGenerator>> originalProperties =
new Dictionary<ModuleShieldGenerator, MultipliedObject<ModuleShieldGenerator>>();
[HarmonyPrefix] [HarmonyPrefix]
[HarmonyPatch(typeof(ModuleShieldGenerator), "OnAttached")] [HarmonyPatch(typeof(ModuleShieldGenerator), "OnAttached")]
static void PostfixCreate(ModuleShieldGenerator __instance) { static void PostfixCreate(ModuleShieldGenerator __instance) {
var trav = Traverse.Create(__instance);
var powerUpDelayField = trav.Field("m_PowerUpDelay");
if (Main.debug.Value) if (Main.debug.Value)
Console.WriteLine("ModuleShieldGenerator.OnAttached"); Console.WriteLine("ModuleShieldGenerator.OnAttached");
if (!healingHeartbeatInterval.ContainsKey(__instance)) {
healingHeartbeatInterval.Add(__instance, __instance.m_HealingHeartbeatInterval); if (!originalProperties.ContainsKey(__instance)) {
if (Main.debug.Value) var props = new MultipliedObject<ModuleShieldGenerator>(__instance);
Console.WriteLine("Patching {0}; m_HealingHeartbeatInterval: {1}", __instance.ToString(), props.AddField("m_HealingHeartbeatInterval", Main.shieldHeartbeatIntervalMultiplier);
__instance.m_HealingHeartbeatInterval); props.AddField("m_Radius", Main.shieldRadiusMultiplier);
} props.AddField("m_PowerUpDelay", Main.powerUpDelayMultiplier);
if (!radius.ContainsKey(__instance)) {
radius.Add(__instance, __instance.m_Radius); props.CaptureFrom();
if (Main.debug.Value) originalProperties.Add(__instance, props);
Console.WriteLine("Patching {0}; m_Radius: {1}", __instance.ToString(), __instance.m_Radius); props.LogValues("Patching");
}
if (!powerUpDelay.ContainsKey(__instance)) {
powerUpDelay.Add(__instance, (float)powerUpDelayField.GetValue());
if (Main.debug.Value)
Console.WriteLine("Patching {0}; m_PowerUpDelay: {1}", __instance.ToString(),
(float)powerUpDelayField.GetValue());
} }
DoPatchSingle(__instance); DoPatchSingle(__instance);
if (Main.debug.Value) if (Main.debug.Value) {
Console.WriteLine("Patched {0}; m_HealingHeartbeatInterval: {1}", __instance.ToString(), originalProperties[__instance].LogValues("Patched");
__instance.m_HealingHeartbeatInterval); }
if (Main.debug.Value)
Console.WriteLine("Patched {0}; m_Radius: {1}", __instance.ToString(), __instance.m_Radius);
if (Main.debug.Value)
Console.WriteLine("Patched {0}; m_PowerUpDelay: {1}", __instance.ToString(),
(float)powerUpDelayField.GetValue());
} }
[HarmonyPrefix] [HarmonyPrefix]
[HarmonyPatch(typeof(ModuleShieldGenerator), "OnDetaching")] [HarmonyPatch(typeof(ModuleShieldGenerator), "OnDetaching")]
static void PostfixDestroy(ModuleShieldGenerator __instance) { static void PostfixDestroy(ModuleShieldGenerator __instance) {
var trav = Traverse.Create(__instance); if (Main.debug.Value) {
var powerUpDelayField = trav.Field("m_PowerUpDelay");
if (Main.debug.Value)
Console.WriteLine("ModuleShieldGenerator.OnDetaching"); Console.WriteLine("ModuleShieldGenerator.OnDetaching");
if (Main.debug.Value) originalProperties[__instance].LogValues("Restoring");
Console.WriteLine("Restoring {0}; m_HealingHeartbeatInterval: {1}", __instance.ToString(), }
__instance.m_HealingHeartbeatInterval);
if (Main.debug.Value)
Console.WriteLine("Restoring {0}; m_Radius: {1}", __instance.ToString(), __instance.m_Radius);
if (Main.debug.Value)
Console.WriteLine("Restoring {0}; m_PowerUpDelay: {1}", __instance.ToString(),
(float)powerUpDelayField.GetValue());
DoRestoreSingle(__instance); DoRestoreSingle(__instance);
if (Main.debug.Value) if (Main.debug.Value) {
Console.WriteLine("Restored {0}; m_HealingHeartbeatInterval: {1}", __instance.ToString(), originalProperties[__instance].LogValues("Restored");
__instance.m_HealingHeartbeatInterval); }
if (Main.debug.Value)
Console.WriteLine("Restored {0}; m_Radius: {1}", __instance.ToString(), __instance.m_Radius);
if (Main.debug.Value)
Console.WriteLine("Restored {0}; m_PowerUpDelay: {1}", __instance.ToString(),
(float)powerUpDelayField.GetValue());
healingHeartbeatInterval.Remove(__instance); originalProperties.Remove(__instance);
radius.Remove(__instance);
powerUpDelay.Remove(__instance);
} }
public static void DoPatch() { public static void DoPatch() {
if (Main.debug.Value) if (Main.debug.Value)
Console.WriteLine("Modifying {0} ModuleShieldGenerator", healingHeartbeatInterval.Count); Console.WriteLine("Modifying {0} ModuleShieldGenerator", originalProperties.Count);
foreach (KeyValuePair<ModuleShieldGenerator, float> keyValuePair in healingHeartbeatInterval) { foreach (var kvp in originalProperties) {
DoRestoreSingle(keyValuePair.Key); DoRestoreSingle(kvp.Key);
DoPatchSingle(keyValuePair.Key); DoPatchSingle(kvp.Key);
} }
} }
static void DoPatchSingle(ModuleShieldGenerator moduleShieldGenerator) { static void DoPatchSingle(ModuleShieldGenerator moduleShieldGenerator) if (
var trav = Traverse.Create(moduleShieldGenerator); originalProperties.TryGetValue(moduleShieldGenerator, out var props)) props.ApplyTo();
var powerUpDelayField = trav.Field("m_PowerUpDelay");
moduleShieldGenerator.m_HealingHeartbeatInterval = static void DoRestoreSingle(ModuleShieldGenerator moduleShieldGenerator) if (
healingHeartbeatInterval[moduleShieldGenerator] * Main.shieldHeartbeatIntervalMultiplier.Value; originalProperties.TryGetValue(moduleShieldGenerator, out var props)) props.RestoreTo();
moduleShieldGenerator.m_Radius = radius[moduleShieldGenerator] * Main.shieldRadiusMultiplier.Value;
powerUpDelayField.SetValue(powerUpDelay[moduleShieldGenerator] * Main.powerUpDelayMultiplier.Value);
}
static void DoRestoreSingle(ModuleShieldGenerator moduleShieldGenerator) {
var trav = Traverse.Create(moduleShieldGenerator);
var powerUpDelayField = trav.Field("m_PowerUpDelay");
if (healingHeartbeatInterval.ContainsKey(moduleShieldGenerator))
moduleShieldGenerator.m_HealingHeartbeatInterval = healingHeartbeatInterval[moduleShieldGenerator];
if (radius.ContainsKey(moduleShieldGenerator))
moduleShieldGenerator.m_Radius = radius[moduleShieldGenerator];
if (powerUpDelay.ContainsKey(moduleShieldGenerator))
powerUpDelayField.SetValue(powerUpDelay[moduleShieldGenerator]);
}
} }
} }