Decompiled source of NoRainDamage v1.3.2

BepInEx/plugins/Jowleth/NoRainDamage.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("NoRainDamage")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c4ccf3b6ff7a7b3d8c3fc4a836851696fe695e26")]
[assembly: AssemblyProduct("NoRainDamage")]
[assembly: AssemblyTitle("NoRainDamage")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace NoRainDamage
{
	[BepInPlugin("uk.co.oliapps.valheim.noraindamage", "No Rain Damage", "1.3.1")]
	public class NoRainDamage : BaseUnityPlugin
	{
		private enum DamageFilter
		{
			ALL,
			INCLUSIVE,
			EXCLUSIVE
		}

		private static readonly ManualLogSource MyLogger = Logger.CreateLogSource("NoRainDamage");

		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 ConfigEntry<bool> debugLogsEnabled;

		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.");
			debugLogsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debugging", "Enabled", false, "Enable debug logging");
			((BaseUnityPlugin)this).Config.Save();
			if (modEnabled.Value)
			{
				Harmony.CreateAndPatchAll(typeof(NoRainDamage), (string)null);
				minHealths = new Dictionary<int, float>();
				Log($"Config loaded: damageFilter={damageFilter.Value}, damagePerMinute={damagePerMinute.Value}, damageFilterValues={damageFilterValues.Value}, maxRainDamagePercentage={maxRainDamagePercentage.Value}");
			}
		}

		private static void Log(string message)
		{
			if (debugLogsEnabled.Value)
			{
				MyLogger.LogDebug((object)message);
			}
		}

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

		[HarmonyPatch(typeof(WearNTear), "UpdateWear")]
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		public static bool Prefix(WearNTear __instance, float time, ZNetView ___m_nview, ref int ___m_shieldChangeID, ref bool ___m_rainWet, ref bool ___m_haveRoof, bool ___m_noRoofWear, GameObject ___m_wet, ref float ___m_rainTimer, bool ___m_noSupportWear, string ___m_requiredPersistentEvent, bool ___m_takeDamageIfInsideEvent, float ___m_eventDamage, float ___m_eventDamageDeviation, ref Biome ___m_biome, ref bool ___m_heavySnow, ref bool ___m_addPreSnow, ref float ___m_snowBuildup, bool ___m_snowDamageImmune, ref float ___m_lastSupportColorValue, ref float ___m_snowDamageTimer, ref bool ___m_inAshlands, bool ___m_ashDamageImmune, bool ___m_haveAshRoof, bool ___m_ashDamageResist, ref float ___m_ashTimer, bool ___m_staticPosition, ref float ___m_lavaValue, Heightmap ___m_heightmap, float ___m_groundDist, ref float ___m_lavaTimer, Biome ___m_requiredBiome, float ___m_outsideRequiredBiomeDamage, ref float ___m_ashDamageTime, GameObject ___m_snow)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0623: Unknown result type (might be due to invalid IL or missing references)
			//IL_0627: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			if (!OverrideWearNTear(ref __instance))
			{
				return true;
			}
			if (!Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid())
			{
				return false;
			}
			ZDO zDO = ___m_nview.GetZDO();
			float currentHealth = ((zDO != null) ? zDO.GetFloat(ZDOVars.s_health, __instance.m_health) : __instance.m_health);
			if (___m_nview.IsOwner() && __instance.ShouldUpdate(time))
			{
				Vector3 position = ((Component)__instance).transform.position;
				if (ZNetScene.instance.OutsideActiveArea(position))
				{
					float maxSupport = __instance.GetMaxSupport();
					if (__instance.m_support.Equals(maxSupport))
					{
						return false;
					}
					___m_nview.GetZDO().Set(ZDOVars.s_support, maxSupport);
					return false;
				}
				bool flag = ShieldGenerator.IsInsideShieldCached(position, ref ___m_shieldChangeID);
				float num = 0f;
				___m_rainWet = !flag && !___m_haveRoof && ___m_noRoofWear && EnvMan.IsWet();
				if (Object.op_Implicit((Object)(object)___m_wet))
				{
					___m_wet.SetActive(___m_rainWet);
				}
				if (___m_noRoofWear && !flag && (double)__instance.GetHealthPercentage() > 0.5)
				{
					if (__instance.IsWet())
					{
						Log(((Object)((Component)__instance).gameObject).name + " is wet");
						if ((double)___m_rainTimer == 0.0)
						{
							___m_rainTimer = time;
						}
						else if ((double)time - (double)___m_rainTimer > 60.0)
						{
							___m_rainTimer = time;
							num += damagePerMinute.Value;
							if (IsTooMuchDamage(ref __instance, currentHealth, num))
							{
								float num2 = HowMuchIsTooMuch(ref __instance, currentHealth, num);
								Log($"{((Object)((Component)__instance).gameObject).name}: incoming rain damage ({num}) reduced by ({num2}");
								num -= num2;
							}
						}
					}
					else
					{
						___m_rainTimer = 0f;
					}
				}
				if (___m_noSupportWear)
				{
					__instance.UpdateSupport();
					if (!__instance.HaveSupport())
					{
						num = 100f;
					}
				}
				if (!string.IsNullOrEmpty(___m_requiredPersistentEvent))
				{
					PersistentEvent activeEvent = PersistentEventSystem.instance.GetActiveEvent(position);
					if (___m_takeDamageIfInsideEvent && activeEvent != null && activeEvent.internalName == ___m_requiredPersistentEvent)
					{
						num += ___m_eventDamage + Random.Range(0f - ___m_eventDamageDeviation, ___m_eventDamageDeviation);
					}
					else if ((activeEvent != null && activeEvent.internalName != ___m_requiredPersistentEvent) || activeEvent == null)
					{
						num += ___m_eventDamage + Random.Range(0f - ___m_eventDamageDeviation, ___m_eventDamageDeviation);
					}
				}
				bool flag2 = false;
				__instance.UpdateBiome();
				if ((int)___m_biome == 64)
				{
					bool flag3 = __instance.CanHaveSnow(flag);
					if (flag3 && (double)___m_snowBuildup < 1.0)
					{
						___m_heavySnow = false;
						float num3 = (___m_addPreSnow ? 1f : EnvMan.instance.GetSnowBuildup());
						if ((double)num3 > 0.0)
						{
							if (___m_addPreSnow)
							{
								___m_snowBuildup = 1f;
								___m_addPreSnow = false;
								___m_nview.GetZDO().Set(ZDOVars.s_preSnow, false);
							}
							else
							{
								___m_snowBuildup += num3 * Time.deltaTime * Game.instance.m_snowBuildupSpeed;
							}
							___m_nview.GetZDO().Set(ZDOVars.s_snow, ___m_snowBuildup);
						}
					}
					else if ((!___m_snowDamageImmune || ZoneSystem.instance.GetGlobalKey((GlobalKeys)39)) && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)38))
					{
						___m_heavySnow = flag3;
						if (___m_heavySnow)
						{
							___m_lastSupportColorValue = __instance.GetSupportColorValue();
							if ((double)___m_lastSupportColorValue != -1.0 && (double)___m_lastSupportColorValue < (double)Game.instance.m_snowSupportLevel)
							{
								___m_heavySnow = true;
								num += Game.instance.m_snowDamage;
								if (ZNet.instance.GetTimeSeconds() >= (double)___m_snowDamageTimer)
								{
									___m_snowDamageTimer = (float)ZNet.instance.GetTimeSeconds() + Random.Range(Game.instance.m_snowDamageEffectIntervalRange.x, Game.instance.m_snowDamageEffectIntervalRange.y);
									Game.instance.m_snowDamageEffect.Create(position, Quaternion.identity, ((Component)__instance).transform, 1f, -1, default(ZDOID));
								}
							}
						}
					}
				}
				if ((int)___m_biome == 32)
				{
					___m_inAshlands = true;
					if ((double)Game.instance.m_ashDamage > 0.0 && !flag && !___m_ashDamageImmune)
					{
						flag2 = !___m_haveAshRoof && (!___m_ashDamageResist || (double)__instance.GetHealthPercentage() > 0.1);
						if (flag2)
						{
							if ((double)___m_ashTimer == 0.0)
							{
								___m_ashTimer = time;
							}
							else if ((double)time - (double)___m_ashTimer > 5.0)
							{
								___m_ashTimer = time;
								num += Game.instance.m_ashDamage;
							}
						}
						else
						{
							___m_ashTimer = 0f;
						}
					}
					if (!___m_staticPosition && (Object)(object)___m_heightmap != (Object)null)
					{
						___m_lavaValue = ___m_heightmap.GetLava(position);
					}
					if ((double)___m_lavaValue > 0.2 && (double)___m_groundDist < 1.5 && !___m_ashDamageImmune)
					{
						if ((double)___m_lavaTimer == 0.0)
						{
							___m_lavaTimer = time;
						}
						else if ((double)time - (double)___m_lavaTimer > 2.0)
						{
							___m_lavaTimer = time;
							float num4 = (flag ? 30f : 70f) * ___m_lavaValue;
							num += num4 * (___m_ashDamageResist ? 0.33f : 1f);
						}
					}
					else
					{
						___m_lavaTimer = 0f;
					}
				}
				if ((int)___m_requiredBiome != 0 && !((Enum)___m_requiredBiome).HasFlag((Enum)(object)___m_biome))
				{
					num += ___m_outsideRequiredBiomeDamage;
				}
				___m_ashDamageTime = (flag2 ? 5f : 0f);
				if ((double)num > 0.0 && !__instance.CanBeRemoved())
				{
					num = 0f;
				}
				if ((double)num > 0.0)
				{
					float num5 = num / 100f * __instance.m_health;
					if (!ZoneSystem.instance.GetGlobalKey((GlobalKeys)37))
					{
						__instance.ApplyDamage(num5, (HitData)null);
					}
				}
			}
			if (Object.op_Implicit((Object)(object)___m_snow) && ___m_nview.IsValid())
			{
				___m_snowBuildup = ___m_nview.GetZDO().GetFloat(ZDOVars.s_snow, 0f);
			}
			__instance.UpdateVisual(true);
			return false;
		}

		private static bool OverrideWearNTear(ref WearNTear instance)
		{
			if (DamageFilter.ALL.Equals(damageFilter.Value))
			{
				return true;
			}
			string[] array = damageFilterValues.Value.Split(new char[1] { ',' });
			string[] array2 = array;
			foreach (string text in array2)
			{
				string value = text.Trim();
				if (!string.IsNullOrEmpty(value) && ((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 currentHealth, float damage)
		{
			int instanceID = ((Object)instance).GetInstanceID();
			if (!minHealths.TryGetValue(instanceID, out var value))
			{
				minHealthPercentage = 1f - Mathf.Clamp(maxRainDamagePercentage.Value, 0f, 1f);
				value = instance.m_health * minHealthPercentage;
				minHealths[instanceID] = value;
			}
			float num = currentHealth - damage / 100f * instance.m_health;
			return num < value;
		}

		private static float HowMuchIsTooMuch(ref WearNTear instance, float currentHealth, float damage)
		{
			int instanceID = ((Object)instance).GetInstanceID();
			if (!minHealths.TryGetValue(instanceID, out var value))
			{
				minHealthPercentage = 1f - Mathf.Clamp(maxRainDamagePercentage.Value, 0f, 1f);
				value = instance.m_health * minHealthPercentage;
				minHealths[instanceID] = value;
			}
			float num = currentHealth - damage / 100f * instance.m_health;
			float num2 = Mathf.Abs(value - num);
			return num2 / instance.m_health * 100f;
		}

		[HarmonyPatch(typeof(WearNTear), "OnDestroy")]
		[HarmonyPostfix]
		public static void WearNTear_OnDestroy(ref WearNTear __instance)
		{
			minHealths.Remove(((Object)__instance).GetInstanceID());
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}