Decompiled source of SharedLiabilityDamage v1.0.0

SharedLiabilityDamage.dll

Decompiled a day ago
using System;
using System.Collections;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("zabu")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabumod")]
[assembly: AssemblyTitle("zabumod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJP.SharedLiabilityDamage
{
	[BepInPlugin("REPOJP.SharedLiabilityDamage", "SharedLiabilityDamage", "1.0.0")]
	public sealed class SharedLiabilityDamagePlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <ApplyDamageToSurvivorsNextFrame>d__12 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public SharedLiabilityDamagePlugin <>4__this;

			private int <percent>5__1;

			private PlayerAvatar[] <avatars>5__2;

			private PlayerAvatar[] <>s__3;

			private int <>s__4;

			private PlayerAvatar <avatar>5__5;

			private PlayerHealth <ph>5__6;

			private int <maxHealth>5__7;

			private int <damage>5__8;

			private Exception <ex>5__9;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ApplyDamageToSurvivorsNextFrame>d__12(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<avatars>5__2 = null;
				<>s__3 = null;
				<avatar>5__5 = null;
				<ph>5__6 = null;
				<ex>5__9 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<percent>5__1 = Mathf.Clamp(DamagePercent.Value, 0, 100);
					if (<percent>5__1 <= 0)
					{
						return false;
					}
					if (!GameManager.Multiplayer())
					{
						return false;
					}
					if (!PhotonNetwork.IsMasterClient)
					{
						return false;
					}
					PurgeExpiredMarks();
					<avatars>5__2 = Object.FindObjectsOfType<PlayerAvatar>();
					if (<avatars>5__2 == null || <avatars>5__2.Length == 0)
					{
						return false;
					}
					<>s__3 = <avatars>5__2;
					for (<>s__4 = 0; <>s__4 < <>s__3.Length; <>s__4++)
					{
						<avatar>5__5 = <>s__3[<>s__4];
						if (Object.op_Implicit((Object)(object)<avatar>5__5))
						{
							<ph>5__6 = <avatar>5__5.playerHealth;
							if (Object.op_Implicit((Object)(object)<ph>5__6) && IsAlive(<avatar>5__5, <ph>5__6))
							{
								<maxHealth>5__7 = GetIntField(Field_PlayerHealth_maxHealth, <ph>5__6, 100);
								if (<maxHealth>5__7 <= 0)
								{
									<maxHealth>5__7 = 1;
								}
								<damage>5__8 = Mathf.RoundToInt((float)<maxHealth>5__7 * ((float)<percent>5__1 / 100f));
								<damage>5__8 = Mathf.Clamp(<damage>5__8, 1, <maxHealth>5__7);
								MarkSolidarityTarget(<avatar>5__5);
								try
								{
									<ph>5__6.HurtOther(<damage>5__8, Vector3.zero, false, -1);
								}
								catch (Exception ex)
								{
									<ex>5__9 = ex;
									((BaseUnityPlugin)<>4__this).Logger.LogError((object)<ex>5__9);
								}
								<ph>5__6 = null;
								<avatar>5__5 = null;
							}
						}
					}
					<>s__3 = null;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string PluginGuid = "REPOJP.SharedLiabilityDamage";

		public const string PluginName = "SharedLiabilityDamage";

		public const string PluginVersion = "1.0.0";

		internal static SharedLiabilityDamagePlugin Instance;

		internal static ConfigEntry<int> DamagePercent;

		private static FieldInfo Field_PlayerAvatar_deadSet;

		private static FieldInfo Field_PlayerHealth_health;

		private static FieldInfo Field_PlayerHealth_maxHealth;

		private const float MarkTtlSeconds = 2f;

		private static readonly Dictionary<int, float> MarkedBySolidarityUntil = new Dictionary<int, float>(16);

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			DamagePercent = ((BaseUnityPlugin)this).Config.Bind<int>("General", "DamagePercent", 10, new ConfigDescription("Each death deals N% of each survivor's max health to that survivor (0-100), and 0 disables the mod.誰かが死ぬたびに生存者ごとの最大体力N%を生存者本人へ与える 0-100 0は無効化", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			Field_PlayerAvatar_deadSet = AccessTools.Field(typeof(PlayerAvatar), "deadSet");
			Field_PlayerHealth_health = AccessTools.Field(typeof(PlayerHealth), "health");
			Field_PlayerHealth_maxHealth = AccessTools.Field(typeof(PlayerHealth), "maxHealth");
			new Harmony("REPOJP.SharedLiabilityDamage").PatchAll();
		}

		internal void OnPlayerDeath(PlayerAvatar deadAvatar, int enemyIndex)
		{
			int num = Mathf.Clamp(DamagePercent.Value, 0, 100);
			if (num > 0 && GameManager.Multiplayer() && PhotonNetwork.IsMasterClient && (!Object.op_Implicit((Object)(object)deadAvatar) || enemyIndex != -1 || !ConsumeSolidarityMark(deadAvatar)))
			{
				((MonoBehaviour)this).StartCoroutine(ApplyDamageToSurvivorsNextFrame());
			}
		}

		[IteratorStateMachine(typeof(<ApplyDamageToSurvivorsNextFrame>d__12))]
		private IEnumerator ApplyDamageToSurvivorsNextFrame()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ApplyDamageToSurvivorsNextFrame>d__12(0)
			{
				<>4__this = this
			};
		}

		private static bool IsAlive(PlayerAvatar avatar, PlayerHealth ph)
		{
			if (GetBoolField(Field_PlayerAvatar_deadSet, avatar, defaultValue: false))
			{
				return false;
			}
			int intField = GetIntField(Field_PlayerHealth_health, ph, 1);
			if (intField <= 0)
			{
				return false;
			}
			return true;
		}

		private static void MarkSolidarityTarget(PlayerAvatar avatar)
		{
			if (Object.op_Implicit((Object)(object)avatar) && Object.op_Implicit((Object)(object)avatar.photonView))
			{
				int viewID = avatar.photonView.ViewID;
				if (viewID > 0)
				{
					MarkedBySolidarityUntil[viewID] = Time.time + 2f;
				}
			}
		}

		private static bool ConsumeSolidarityMark(PlayerAvatar avatar)
		{
			if (!Object.op_Implicit((Object)(object)avatar) || !Object.op_Implicit((Object)(object)avatar.photonView))
			{
				return false;
			}
			int viewID = avatar.photonView.ViewID;
			if (viewID <= 0)
			{
				return false;
			}
			float time = Time.time;
			if (!MarkedBySolidarityUntil.TryGetValue(viewID, out var value))
			{
				return false;
			}
			if (value < time)
			{
				MarkedBySolidarityUntil.Remove(viewID);
				return false;
			}
			MarkedBySolidarityUntil.Remove(viewID);
			return true;
		}

		private static void PurgeExpiredMarks()
		{
			if (MarkedBySolidarityUntil.Count == 0)
			{
				return;
			}
			float time = Time.time;
			List<int> list = null;
			foreach (KeyValuePair<int, float> item in MarkedBySolidarityUntil)
			{
				if (item.Value < time)
				{
					if (list == null)
					{
						list = new List<int>(8);
					}
					list.Add(item.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (int item2 in list)
			{
				MarkedBySolidarityUntil.Remove(item2);
			}
		}

		private static int GetIntField(FieldInfo fi, object instance, int defaultValue)
		{
			if (fi == null || instance == null)
			{
				return defaultValue;
			}
			try
			{
				object value = fi.GetValue(instance);
				if (value is int)
				{
					int result = (int)value;
					if (true)
					{
						return result;
					}
				}
			}
			catch
			{
				return defaultValue;
			}
			return defaultValue;
		}

		private static bool GetBoolField(FieldInfo fi, object instance, bool defaultValue)
		{
			if (fi == null || instance == null)
			{
				return defaultValue;
			}
			try
			{
				object value = fi.GetValue(instance);
				if (value is bool)
				{
					bool result = (bool)value;
					if (true)
					{
						return result;
					}
				}
			}
			catch
			{
				return defaultValue;
			}
			return defaultValue;
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")]
	internal static class Patch_PlayerAvatar_PlayerDeathRPC
	{
		private static void Postfix(PlayerAvatar __instance, int enemyIndex, PhotonMessageInfo _info)
		{
			if (GameManager.Multiplayer() && PhotonNetwork.IsMasterClient && !((Object)(object)SharedLiabilityDamagePlugin.Instance == (Object)null))
			{
				SharedLiabilityDamagePlugin.Instance.OnPlayerDeath(__instance, enemyIndex);
			}
		}
	}
}