Decompiled source of NoRainDamage v1.2.2

BepInEx/plugins/Jowleth/NoRainDamage.dll

Decompiled 7 months ago
using System;
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("NoRainDamage")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NoRainDamage")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("65825995-ebff-4e7e-81c3-6254d9832f19")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace NoRainDamage;

[BepInPlugin("uk.co.oliapps.valheim.noraindamage", "No Rain Damage", "1.2.2")]
public class NoRainDamage : BaseUnityPlugin
{
	private enum DamageFilter
	{
		ALL,
		INCLUSIVE,
		EXCLUSIVE
	}

	private static ConfigEntry<float> damagePerMinute;

	private static ConfigEntry<float> maxRainDamagePercentage;

	private static ConfigEntry<DamageFilter> damageFilter;

	private static ConfigEntry<string> damageFilterValues;

	private static ConfigEntry<bool> modEnabled;

	private static Dictionary<int, float> minHealths;

	private static float minHealthPercentage;

	public void Awake()
	{
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Set whether the mod is enabled");
		maxRainDamagePercentage = ((BaseUnityPlugin)this).Config.Bind<float>("Rain Damage", "Max Damage", 0f, "Maximum damage rain can do to uncovered structures between 0.0 and 1.0");
		damagePerMinute = ((BaseUnityPlugin)this).Config.Bind<float>("Rain Damage", "Damage Per Minute", 5f, "Damage per minute rain deals to uncovered structures");
		damageFilter = ((BaseUnityPlugin)this).Config.Bind<DamageFilter>("Damage Filter", "Filter Type", DamageFilter.ALL, "Set whether everything should be protected (ALL), certain things should be protected (INCLUSIVE) or certain things should not be protected (EXCLUSIVE)");
		damageFilterValues = ((BaseUnityPlugin)this).Config.Bind<string>("Damage Filter", "Filter List", "", "If Filter type is INCLUSIVE or EXCLUSIVE, this list of comma-separated values will be used as a filter (will protect or damage if piece name contains value). Piece list included in mod download.");
		((BaseUnityPlugin)this).Config.Save();
		if (modEnabled.Value)
		{
			Harmony.CreateAndPatchAll(typeof(NoRainDamage), (string)null);
			minHealths = new Dictionary<int, float>();
		}
	}

	[HarmonyPatch(typeof(WearNTear), "Awake")]
	[HarmonyPostfix]
	public static void WearNTear_Awake(ref WearNTear __instance)
	{
		minHealthPercentage = 1f - Mathf.Clamp(maxRainDamagePercentage.Value, 0f, 1f);
		minHealths.Add(((Object)__instance).GetInstanceID(), __instance.m_health * minHealthPercentage);
	}

	[HarmonyPatch(typeof(WearNTear), "UpdateWear")]
	[HarmonyPrefix]
	[HarmonyPriority(0)]
	public static bool WearNTear_UpdateWear(ref WearNTear __instance)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		if (OverrideWearNTear(ref __instance))
		{
			ZNetView val = (ZNetView)AccessTools.Field(typeof(WearNTear), "m_nview").GetValue(__instance);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return false;
			}
			bool flag = (bool)AccessTools.Method(typeof(WearNTear), "ShouldUpdate", (Type[])null, (Type[])null).Invoke(__instance, new object[0]);
			if (val.IsOwner() && flag)
			{
				if (ZNetScene.instance.OutsideActiveArea(((Component)__instance).transform.position))
				{
					float num = (float)AccessTools.Method(typeof(WearNTear), "GetMaxSupport", (Type[])null, (Type[])null).Invoke(__instance, new object[0]);
					AccessTools.Field(typeof(WearNTear), "m_support").SetValue(__instance, num);
					val.GetZDO().Set("support", num);
					return false;
				}
				float num2 = 0f;
				bool flag2 = (bool)AccessTools.Method(typeof(WearNTear), "HaveRoof", (Type[])null, (Type[])null).Invoke(__instance, new object[0]);
				bool flag3 = EnvMan.IsWet() && !flag2;
				if (Object.op_Implicit((Object)(object)__instance.m_wet))
				{
					__instance.m_wet.SetActive(flag3);
				}
				if (__instance.m_noRoofWear && (double)__instance.GetHealthPercentage() > (double)minHealthPercentage)
				{
					bool flag4 = (bool)AccessTools.Method(typeof(WearNTear), "IsUnderWater", (Type[])null, (Type[])null).Invoke(__instance, new object[0]);
					float num3 = (float)AccessTools.Field(typeof(WearNTear), "m_rainTimer").GetValue(__instance);
					float @float = val.GetZDO().GetFloat("health", __instance.m_health);
					if (flag3 || flag4)
					{
						if ((double)num3 == 0.0)
						{
							num3 = Time.time;
						}
						else if ((double)Time.time - (double)num3 > 60.0)
						{
							num3 = Time.time;
							num2 += damagePerMinute.Value;
							if (IsTooMuchDamage(ref __instance, @float, num2))
							{
								float num4 = HowMuchIsTooMuch(ref __instance, @float, num2);
								num2 -= num4;
							}
						}
					}
					else
					{
						num3 = 0f;
					}
					AccessTools.Field(typeof(WearNTear), "m_rainTimer").SetValue(__instance, num3);
				}
				if (__instance.m_noSupportWear)
				{
					AccessTools.Method(typeof(WearNTear), "UpdateSupport", (Type[])null, (Type[])null).Invoke(__instance, new object[0]);
					if (!(bool)AccessTools.Method(typeof(WearNTear), "HaveSupport", (Type[])null, (Type[])null).Invoke(__instance, new object[0]))
					{
						num2 = 100f;
					}
				}
				bool flag5 = (bool)AccessTools.Method(typeof(WearNTear), "CanBeRemoved", (Type[])null, (Type[])null).Invoke(__instance, new object[0]);
				if ((double)num2 > 0.0 && !flag5)
				{
					num2 = 0f;
				}
				if ((double)num2 > 0.0)
				{
					__instance.ApplyDamage(num2 / 100f * __instance.m_health, (HitData)null);
				}
			}
			AccessTools.Method(typeof(WearNTear), "UpdateVisual", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { true });
			return false;
		}
		return true;
	}

	private static bool OverrideWearNTear(ref WearNTear instance)
	{
		if (DamageFilter.ALL.Equals(damageFilter.Value))
		{
			return true;
		}
		string[] array = damageFilterValues.Value.Split(new char[1] { ',' });
		foreach (string value in array)
		{
			if (((Object)((Component)instance).gameObject).name.Contains(value))
			{
				return damageFilter.Value switch
				{
					DamageFilter.INCLUSIVE => true, 
					DamageFilter.EXCLUSIVE => false, 
					_ => true, 
				};
			}
		}
		return DamageFilter.EXCLUSIVE.Equals(damageFilter.Value);
	}

	private static bool IsTooMuchDamage(ref WearNTear instance, float health, float damage)
	{
		return health - damage / 100f * instance.m_health < minHealths[((Object)instance).GetInstanceID()];
	}

	private static float HowMuchIsTooMuch(ref WearNTear instance, float health, float damage)
	{
		float num = health - damage / 100f * instance.m_health;
		return Mathf.Abs(minHealths[((Object)instance).GetInstanceID()] - num) / instance.m_health * 100f;
	}

	private static void Log(string message)
	{
		ZLog.Log((object)("[No Rain Damage] " + message));
	}

	[HarmonyPatch(typeof(WearNTear), "OnDestroy")]
	[HarmonyPostfix]
	public static void WearNTear_OnDestroy(ref WearNTear __instance)
	{
		minHealths.Remove(((Object)__instance).GetInstanceID());
	}
}