Decompiled source of ContagiousRepair v1.0.0

ContagiousRepair.dll

Decompiled 3 days ago
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("RepairTrickle")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RepairTrickle")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("527dfcf7-c0b5-4c36-8981-97f3afffa72d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ContagiousRepair;

[BepInPlugin("robit.contagiousrepair", "Contagious Repair", "1.0.0")]
public class ContagiousRepairPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "robit.contagiousrepair";

	public const string PluginName = "Contagious Repair";

	public const string PluginVersion = "1.0.0";

	internal static ContagiousRepairPlugin Instance;

	internal static ConfigEntry<bool> ModEnabled;

	internal static ConfigEntry<float> PropagationDelay;

	internal static ConfigEntry<float> TouchPadding;

	internal static ConfigEntry<int> MaxPieces;

	internal static ConfigEntry<bool> UseStamina;

	internal static ConfigEntry<float> StaminaPerRepair;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Expected O, but got Unknown
		Instance = this;
		ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable Repair Trickle.");
		PropagationDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PropagationDelay", 0.1f, "Delay in seconds between repair waves.");
		TouchPadding = ((BaseUnityPlugin)this).Config.Bind<float>("General", "TouchPadding", 0.08f, "Small amount added around colliders when detecting touching pieces.");
		MaxPieces = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxPiecesPerCascade", 250, "Maximum number of pieces that can be checked in one repair cascade.");
		UseStamina = ((BaseUnityPlugin)this).Config.Bind<bool>("Stamina", "UseStamina", true, "If enabled, each contagious repair consumes stamina.");
		StaminaPerRepair = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "StaminaPerRepair", 1f, "Stamina consumed for each contagious repair.");
		_harmony = new Harmony("robit.contagiousrepair");
		_harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Contagious Repair 1.0.0 loaded.");
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	internal void BeginCascade(Piece startingPiece)
	{
		if (ModEnabled.Value && !((Object)(object)startingPiece == (Object)null))
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Contagion started from: " + ((Object)startingPiece).name));
			((MonoBehaviour)this).StartCoroutine(ContagiousRepair(startingPiece));
		}
	}

	private IEnumerator ContagiousRepair(Piece startingPiece)
	{
		Queue<Piece> currentWave = new Queue<Piece>();
		Queue<Piece> nextWave = new Queue<Piece>();
		HashSet<int> visited = new HashSet<int>();
		currentWave.Enqueue(startingPiece);
		visited.Add(((Object)startingPiece).GetInstanceID());
		int checkedPieces = 1;
		while (currentWave.Count > 0)
		{
			yield return (object)new WaitForSeconds(PropagationDelay.Value);
			nextWave.Clear();
			while (currentWave.Count > 0)
			{
				Piece val = currentWave.Dequeue();
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				foreach (Piece item in FindTouchingPieces(val))
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					int instanceID = ((Object)item).GetInstanceID();
					if (visited.Contains(instanceID))
					{
						continue;
					}
					visited.Add(instanceID);
					checkedPieces++;
					if (checkedPieces > MaxPieces.Value)
					{
						((BaseUnityPlugin)this).Logger.LogDebug((object)$"Repair cascade reached limit of {MaxPieces.Value} pieces.");
						yield break;
					}
					WearNTear component = ((Component)item).GetComponent<WearNTear>();
					if ((Object)(object)component != (Object)null && component.GetHealthPercentage() < 0.9999f)
					{
						if (UseStamina.Value)
						{
							Player localPlayer = Player.m_localPlayer;
							if ((Object)(object)localPlayer == (Object)null)
							{
								yield break;
							}
							float value = StaminaPerRepair.Value;
							if (localPlayer.GetStamina() < value)
							{
								((BaseUnityPlugin)this).Logger.LogDebug((object)"Contagious repair stopped: not enough stamina.");
								yield break;
							}
							((Character)localPlayer).UseStamina(value);
						}
						if (component.Repair() && item.m_placeEffect != null)
						{
							item.m_placeEffect.Create(((Component)item).transform.position, ((Component)item).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
						}
					}
					nextWave.Enqueue(item);
					nextWave.Enqueue(item);
				}
			}
			Queue<Piece> queue = currentWave;
			currentWave = nextWave;
			nextWave = queue;
		}
	}

	private IEnumerable<Piece> FindTouchingPieces(Piece sourcePiece)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		HashSet<Piece> hashSet = new HashSet<Piece>();
		Collider[] componentsInChildren = ((Component)sourcePiece).GetComponentsInChildren<Collider>();
		foreach (Collider val in componentsInChildren)
		{
			if ((Object)(object)val == (Object)null || !val.enabled)
			{
				continue;
			}
			Bounds bounds = val.bounds;
			Vector3 val2 = ((Bounds)(ref bounds)).extents + Vector3.one * TouchPadding.Value;
			Collider[] array = Physics.OverlapBox(((Bounds)(ref bounds)).center, val2, Quaternion.identity, -1, (QueryTriggerInteraction)1);
			foreach (Collider val3 in array)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					Piece componentInParent = ((Component)val3).GetComponentInParent<Piece>();
					if (!((Object)(object)componentInParent == (Object)null) && !((Object)(object)componentInParent == (Object)(object)sourcePiece))
					{
						hashSet.Add(componentInParent);
					}
				}
			}
		}
		return hashSet;
	}
}
[HarmonyPatch(typeof(Player), "Repair")]
internal static class PlayerRepairPatch
{
	private struct RepairState
	{
		public Piece Piece;

		public float HealthBefore;
	}

	private static void Prefix(Player __instance, out RepairState __state)
	{
		__state = new RepairState
		{
			Piece = null,
			HealthBefore = 0f
		};
		if ((Object)(object)ContagiousRepairPlugin.Instance == (Object)null || !ContagiousRepairPlugin.ModEnabled.Value)
		{
			return;
		}
		Piece hoveringPiece = __instance.GetHoveringPiece();
		if ((Object)(object)hoveringPiece == (Object)null)
		{
			return;
		}
		WearNTear component = ((Component)hoveringPiece).GetComponent<WearNTear>();
		if (!((Object)(object)component == (Object)null))
		{
			float healthPercentage = component.GetHealthPercentage();
			if (!(healthPercentage >= 0.9999f))
			{
				__state = new RepairState
				{
					Piece = hoveringPiece,
					HealthBefore = healthPercentage
				};
			}
		}
	}

	private static void Postfix(RepairState __state)
	{
		if (!((Object)(object)__state.Piece == (Object)null) && !((Object)(object)ContagiousRepairPlugin.Instance == (Object)null))
		{
			WearNTear component = ((Component)__state.Piece).GetComponent<WearNTear>();
			if (!((Object)(object)component == (Object)null) && !(component.GetHealthPercentage() <= __state.HealthBefore + 0.0001f))
			{
				ContagiousRepairPlugin.Instance.BeginCascade(__state.Piece);
			}
		}
	}
}