Decompiled source of DeathResistance v1.0.0

plugins\DeathResistance.Server.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Gameplay.Scripting;
using ProjectM.Gameplay.Systems;
using ProjectM.Network;
using ProjectM.UI;
using Unity.Collections;
using Unity.Entities;
using VampireCommandFramework;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("DeathResistance.GameTests")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("DeathResistance.Server")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DeathResistance.Server")]
[assembly: AssemblyTitle("DeathResistance.Server")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[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]
	[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]
	[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 DeathResistance
{
	[CommandGroup("dr", null)]
	public static class Commands
	{
		[Command("off", null, null, "Clear Death Resistance and opt out until .dr on.", null, false)]
		public static void Off(ChatCommandContext ctx)
		{
			Run(ctx, delegate
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Runtime.Put(ctx.Event.User.PlatformId, new PlayerState
				{
					OptedOut = true,
					HasPreference = true
				});
				Status(ctx);
			});
		}

		[Command("on", null, null, "Enable future Death Resistance gains; no stacks are granted.", null, false)]
		public static void On(ChatCommandContext ctx)
		{
			Run(ctx, delegate
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				PlayerState playerState = Runtime.Get(ctx.Event.User.PlatformId);
				Runtime.Put(ctx.Event.User.PlatformId, playerState with
				{
					OptedOut = false,
					HasPreference = true
				});
				Status(ctx);
			});
		}

		[Command("status", null, null, "Show your participation, resistance, stacks and remaining time.", null, false)]
		public static void Status(ChatCommandContext ctx)
		{
			Run(ctx, delegate
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				string[] array = Rules.Card(Runtime.Get(ctx.Event.User.PlatformId), Plugin.Settings.Current, Runtime.Now).Split('\n');
				foreach (string text in array)
				{
					ctx.Reply(text);
				}
			});
		}

		[Command("settings", null, null, "Show protection and death-stack settings.", null, false)]
		public static void Settings(ChatCommandContext ctx)
		{
			string[] array = Rules.SettingsCard(Plugin.Settings.Current).Split('\n');
			foreach (string text in array)
			{
				ctx.Reply(text);
			}
		}

		[Command("config", null, null, "List Death Resistance server settings.", null, true)]
		public static void Config(ChatCommandContext ctx)
		{
			foreach (string item in Plugin.Settings.Lines())
			{
				ctx.Reply(item);
			}
		}

		[Command("set", null, ".dr set <setting> <value>", "Validate, save and apply an admin setting immediately.", null, true)]
		public static void Set(ChatCommandContext ctx, string setting, string value)
		{
			Run(ctx, delegate
			{
				ctx.Reply(Plugin.Settings.Set(setting, value));
				Runtime.RefreshState();
			});
		}

		private static void Run(ChatCommandContext ctx, Action action)
		{
			try
			{
				action();
			}
			catch (Exception ex) when (((ex is ArgumentException || ex is FormatException || ex is OverflowException || ex is InvalidOperationException) ? 1 : 0) != 0)
			{
				ctx.Reply(ex.Message);
			}
			catch (Exception ex2)
			{
				((BasePlugin)Plugin.Instance).Log.LogError((object)ex2);
				ctx.Reply("Death Resistance could not save or load player state. Your existing data has been preserved; see the server log.");
			}
		}
	}
	internal sealed class Configuration
	{
		private readonly ConfigFile file;

		private readonly Dictionary<string, ConfigEntryBase> entries = new Dictionary<string, ConfigEntryBase>(StringComparer.OrdinalIgnoreCase);

		private bool restoring;

		internal Settings Current { get; private set; } = new Settings();

		internal Configuration(ConfigFile file)
		{
			this.file = file;
			Bind("LogDamage", value: false, "Log player damage before/after Death Resistance, eligibility and health changes for diagnosis.");
			Bind("EnabledByDefault", value: true, "Whether players without an explicit .dr on/off preference participate. Explicit saved player choices always win.");
			Bind("LevelAllowance", 3, "Maximum levels above the victim for an incoming source to qualify. Inclusive; lower levels always qualify.");
			Bind("ReductionPerStack", 10.0, "Additive percentage points per stack, 0.01–100. Reduction is capped at 100%.");
			Bind("MaxStacks", 0, "0 means stack until 100% immunity to eligible damage; otherwise 1–10000.");
			Bind("DurationSeconds", 3600.0, "Shared duration in real seconds. Qualifying deaths refresh it; offline time counts.");
			Bind("ReduceSunDamage", value: false, "Reduce sun damage regardless of level; independent of sun death stack grants.");
			Bind("SunDeathsGrantStacks", value: false, "Sun deaths add a stack and refresh the timer.");
			Bind("ReducePvpDamage", value: false, "Reduce player-owned damage when the source passes the level check.");
			Bind("PvpDeathsGrantStacks", value: false, "Completed PvP deaths add a stack and refresh the timer.");
			Bind("PvpDowningsGrantStacks", value: false, "PvP downings add a stack. At most one stack per downing/death episode.");
			Bind("OnlyVBloodDeathsGrantStacks", value: false, "Only deaths caused by V Bloods grant stacks or refresh the timer. Overrides sun/PvP grants; damage coverage is unchanged.");
			Read().Validate();
			Current = Read();
			file.SettingChanged += delegate
			{
				Refresh();
			};
		}

		private void Bind<T>(string key, T value, string description)
		{
			entries[key] = (ConfigEntryBase)(object)file.Bind<T>("General", key, value, description);
		}

		private T Value<T>(string key)
		{
			return (T)entries[key].BoxedValue;
		}

		private Settings Read()
		{
			return new Settings
			{
				LogDamage = Value<bool>("LogDamage"),
				EnabledByDefault = Value<bool>("EnabledByDefault"),
				LevelAllowance = Value<int>("LevelAllowance"),
				ReductionPerStack = Value<double>("ReductionPerStack"),
				MaxStacks = Value<int>("MaxStacks"),
				DurationSeconds = Value<double>("DurationSeconds"),
				ReduceSunDamage = Value<bool>("ReduceSunDamage"),
				SunDeathsGrantStacks = Value<bool>("SunDeathsGrantStacks"),
				ReducePvpDamage = Value<bool>("ReducePvpDamage"),
				PvpDeathsGrantStacks = Value<bool>("PvpDeathsGrantStacks"),
				PvpDowningsGrantStacks = Value<bool>("PvpDowningsGrantStacks"),
				OnlyVBloodDeathsGrantStacks = Value<bool>("OnlyVBloodDeathsGrantStacks")
			};
		}

		private void Refresh()
		{
			if (restoring)
			{
				return;
			}
			try
			{
				Settings next = Read();
				next.Validate();
				Current = next;
				Runtime.Guard(delegate
				{
					Runtime.Reconfigure(next);
				});
			}
			catch (ArgumentException ex)
			{
				restoring = true;
				try
				{
					foreach (ConfigEntryBase value in entries.Values)
					{
						value.BoxedValue = typeof(Settings).GetProperty(value.Definition.Key).GetValue(Current);
					}
					file.Save();
				}
				finally
				{
					restoring = false;
				}
				((BasePlugin)Plugin.Instance).Log.LogError((object)("Rejected config change; restored last valid settings: " + ex.Message));
			}
		}

		internal string Set(string key, string value)
		{
			if (!entries.TryGetValue(key, out ConfigEntryBase value2))
			{
				throw new ArgumentException("Unknown setting. Use .dr config.");
			}
			object obj = ((value2.SettingType == typeof(bool)) ? ((object)bool.Parse(value)) : ((object)((value2.SettingType == typeof(int)) ? ((double)int.Parse(value, CultureInfo.InvariantCulture)) : double.Parse(value, CultureInfo.InvariantCulture))));
			Settings current = Current;
			(value2.Definition.Key switch
			{
				"LogDamage" => current with
				{
					LogDamage = (bool)obj
				}, 
				"EnabledByDefault" => current with
				{
					EnabledByDefault = (bool)obj
				}, 
				"LevelAllowance" => current with
				{
					LevelAllowance = (int)obj
				}, 
				"ReductionPerStack" => current with
				{
					ReductionPerStack = (double)obj
				}, 
				"MaxStacks" => current with
				{
					MaxStacks = (int)obj
				}, 
				"DurationSeconds" => current with
				{
					DurationSeconds = (double)obj
				}, 
				"ReduceSunDamage" => current with
				{
					ReduceSunDamage = (bool)obj
				}, 
				"SunDeathsGrantStacks" => current with
				{
					SunDeathsGrantStacks = (bool)obj
				}, 
				"ReducePvpDamage" => current with
				{
					ReducePvpDamage = (bool)obj
				}, 
				"PvpDeathsGrantStacks" => current with
				{
					PvpDeathsGrantStacks = (bool)obj
				}, 
				"PvpDowningsGrantStacks" => current with
				{
					PvpDowningsGrantStacks = (bool)obj
				}, 
				"OnlyVBloodDeathsGrantStacks" => current with
				{
					OnlyVBloodDeathsGrantStacks = (bool)obj
				}, 
				_ => throw new ArgumentException("Unknown setting."), 
			}).Validate();
			value2.BoxedValue = obj;
			file.Save();
			return Display.Setting(value2.Definition.Key, obj);
		}

		internal IEnumerable<string> Lines()
		{
			return entries.Values.Select((ConfigEntryBase e) => Display.Setting(e.Definition.Key, e.BoxedValue));
		}
	}
	[BepInPlugin("DeathResistance", "Death Resistance", "1.0.0")]
	[BepInDependency("gg.deca.VampireCommandFramework", "0.10.4")]
	public sealed class Plugin : BasePlugin
	{
		public const string Guid = "DeathResistance";

		internal static Plugin Instance;

		internal static Configuration Settings;

		private Harmony? harmony;

		public override void Load()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Instance = this;
			Settings = new Configuration(((BasePlugin)this).Config);
			harmony = new Harmony("DeathResistance");
			try
			{
				harmony.PatchAll(typeof(Plugin).Assembly);
				CommandRegistry.RegisterAll();
				((BasePlugin)this).Log.LogInfo((object)"Death Resistance 1.0.0 loaded. Server-only mod; use .dr status to view resistance and remaining time.");
			}
			catch
			{
				harmony.UnpatchSelf();
				throw;
			}
		}

		public override bool Unload()
		{
			CommandRegistry.UnregisterAssembly();
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			Runtime.Reset();
			return true;
		}
	}
	internal static class Runtime
	{
		private sealed record HitBatch(float Before, Cause Cause, bool VBlood, Entity Source);

		private static World? world;

		private static StateStore? store;

		private static readonly HashSet<Entity> observedDownings = new HashSet<Entity>();

		private static readonly HashSet<Entity> observedDeaths = new HashSet<Entity>();

		private static readonly Dictionary<Entity, (Cause Cause, bool VBlood)> downingCauses = new Dictionary<Entity, (Cause, bool)>();

		private static readonly Dictionary<Entity, (ulong Player, float Health)> damageHealth = new Dictionary<Entity, (ulong, float)>();

		private static readonly List<(Entity Victim, Entity Downed, Cause Cause, bool VBlood)> releaseCandidates = new List<(Entity, Entity, Cause, bool)>();

		private static readonly HashSet<Entity> awardedDraculaDownings = new HashSet<Entity>();

		private static readonly HashSet<Entity> destroyEventsBeforeRelease = new HashSet<Entity>();

		private static readonly Dictionary<Entity, HitBatch> hitBatches = new Dictionary<Entity, HitBatch>();

		private static readonly Dictionary<Entity, (HitBatch Hit, long Time)> lethalHits = new Dictionary<Entity, (HitBatch, long)>();

		private static long nextTick;

		private static long nextError;

		private static bool failed;

		internal static long Now => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

		internal static PlayerState Get(ulong id)
		{
			if (store == null || failed)
			{
				throw new InvalidOperationException("Death Resistance is waiting for the world save, or is disabled after an error. Check the server log.");
			}
			return Rules.Normalize(store.Get(id), Plugin.Settings.Current, Now);
		}

		internal static void Put(ulong id, PlayerState state)
		{
			if (store == null || failed)
			{
				throw new InvalidOperationException("Death Resistance persistence is unavailable. Check the server log.");
			}
			store.Put(id, state);
			RefreshState();
		}

		internal static void RefreshState()
		{
			nextTick = 0L;
		}

		internal static void Reconfigure(Settings settings)
		{
			store?.NormalizeAll(settings, Now);
			RefreshState();
		}

		internal static void Reset()
		{
			world = null;
			store = null;
			observedDeaths.Clear();
			observedDownings.Clear();
			downingCauses.Clear();
			damageHealth.Clear();
			hitBatches.Clear();
			lethalHits.Clear();
			releaseCandidates.Clear();
			awardedDraculaDownings.Clear();
			destroyEventsBeforeRelease.Clear();
			failed = false;
			nextTick = 0L;
		}

		private static bool Ready(World candidate)
		{
			//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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (candidate == null || !candidate.IsCreated || candidate.Name != "Server")
			{
				return false;
			}
			if (world == null || ((Il2CppObjectBase)world).Pointer != ((Il2CppObjectBase)candidate).Pointer)
			{
				Reset();
				world = candidate;
			}
			if (failed)
			{
				return false;
			}
			if (store != null)
			{
				return true;
			}
			EntityManager entityManager = candidate.EntityManager;
			List<Entity> list = Ecs.All<ServerRuntimeSettings>(entityManager);
			if (list.Count == 0)
			{
				return false;
			}
			string text = ((object)Ecs.Field<ServerRuntimeSettings, FixedString512Bytes>(entityManager, list[0], "SaveDirectoryPath", 4)/*cast due to .constrained prefix*/).ToString();
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			string text2 = text;
			if (string.IsNullOrWhiteSpace(text2) || !Path.IsPathFullyQualified(text2))
			{
				throw new InvalidOperationException("Cannot determine the active world's absolute save folder.");
			}
			string text3 = Path.Combine(text2, "DeathResistance", "players.json");
			store = new StateStore(text3);
			((BasePlugin)Plugin.Instance).Log.LogInfo((object)("Death Resistance state: " + text3));
			return true;
		}

		internal static void Tick(World candidate)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			if (Now < nextTick)
			{
				return;
			}
			nextTick = Now + 2000;
			if (!Ready(candidate))
			{
				return;
			}
			EntityManager em = candidate.EntityManager;
			((EntityManager)(ref em)).CompleteAllTrackedJobs();
			ScanDownings(em);
			foreach (Entity item in Ecs.All<User>(em))
			{
				User componentData = ((EntityManager)(ref em)).GetComponentData<User>(item);
				if (componentData.IsConnected)
				{
					PlayerState playerState = Rules.Normalize(Get(componentData.PlatformId), Plugin.Settings.Current, Now);
					Entity entityOnServer = ((NetworkedEntity)(ref componentData.LocalCharacter)).GetEntityOnServer();
					if (playerState.DowningAwarded && ((EntityManager)(ref em)).Exists(entityOnServer) && !Ecs.Has<Dead>(em, entityOnServer) && !HasDowning(em, entityOnServer))
					{
						playerState = playerState with
						{
							DowningAwarded = false
						};
					}
					if (playerState != store.Get(componentData.PlatformId))
					{
						store.Put(componentData.PlatformId, playerState);
					}
				}
			}
			Entity[] array = lethalHits.Keys.ToArray();
			foreach (Entity val in array)
			{
				if (!((EntityManager)(ref em)).Exists(val) || Now - lethalHits[val].Time > 10000 || (Ecs.Has<Health>(em, val) && Ecs.Field<Health, float>(em, val, "Value", 16) > 0f))
				{
					lethalHits.Remove(val);
				}
			}
			observedDeaths.RemoveWhere((Entity e) => !((EntityManager)(ref em)).Exists(e));
			array = downingCauses.Keys.ToArray();
			foreach (Entity val2 in array)
			{
				if (!((EntityManager)(ref em)).Exists(val2) || (!Ecs.Has<Dead>(em, val2) && !HasDowning(em, val2)))
				{
					downingCauses.Remove(val2);
				}
			}
		}

		internal static void Damage(StatChangeSystem system)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready(((ComponentSystemBase)system).World))
			{
				return;
			}
			EntityManager entityManager = ((ComponentSystemBase)system).EntityManager;
			EntityQuery query = system._Query;
			((EntityQuery)(ref query)).CompleteDependency();
			hitBatches.Clear();
			List<Entity> list = Ecs.Entities(system._Query);
			Settings current = Plugin.Settings.Current;
			long now = Now;
			foreach (Entity item in list)
			{
				if (!Ecs.Has<StatChangeEvent>(entityManager, item))
				{
					continue;
				}
				StatChangeEvent componentData = ((EntityManager)(ref entityManager)).GetComponentData<StatChangeEvent>(item);
				if ((int)componentData.StatType != 0 || componentData.Change >= 0f || !TryPlayer(entityManager, componentData.Entity, out var user))
				{
					continue;
				}
				PlayerState playerState = Get(user.PlatformId);
				Entity val = Source(entityManager, componentData.Source);
				Cause cause = Classify(entityManager, val, componentData.Entity, componentData.Reason);
				if (Ecs.Has<Health>(entityManager, componentData.Entity))
				{
					HitBatch hitBatch = new HitBatch(Ecs.Field<Health, float>(entityManager, componentData.Entity, "Value", 16), cause, Ecs.Has<VBloodUnit>(entityManager, val), val);
					if (hitBatches.TryGetValue(componentData.Entity, out HitBatch value))
					{
						hitBatch = ((value.Cause == hitBatch.Cause && value.VBlood == hitBatch.VBlood) ? value : value with
						{
							Cause = Cause.Other,
							VBlood = false,
							Source = Entity.Null
						});
					}
					hitBatches[componentData.Entity] = hitBatch;
				}
				double num = Level(entityManager, componentData.Entity);
				double num2 = Level(entityManager, val);
				float num3 = Rules.Damage(componentData.Change, playerState, current, now, cause, num, num2);
				if (current.LogDamage)
				{
					string text = (playerState.OptedOut ? "opted-out" : ((playerState.Stacks == 0) ? "no-active-stacks" : ((!Rules.Covers(current, cause, num, num2)) ? "source-excluded" : "eligible")));
					((BasePlugin)Plugin.Instance).Log.LogInfo((object)FormattableString.Invariant($"DR DAMAGE player={user.PlatformId} event={item} source={val} reason={componentData.Reason} cause={cause} playerLevel={num:0.##} sourceLevel={num2:0.##} allowance={current.LevelAllowance} stacks={playerState.Stacks} resistance={Rules.Reduction(playerState, current, now):0.##}% verdict={text} incoming={0f - componentData.Change:0.####} outgoing={0f - num3:0.####} prevented={num3 - componentData.Change:0.####}"));
					if (!damageHealth.ContainsKey(componentData.Entity) && Ecs.Has<Health>(entityManager, componentData.Entity))
					{
						damageHealth[componentData.Entity] = (user.PlatformId, Ecs.Field<Health, float>(entityManager, componentData.Entity, "Value", 16));
					}
				}
				if (num3 != componentData.Change)
				{
					componentData.Change = num3;
					((EntityManager)(ref entityManager)).SetComponentData<StatChangeEvent>(item, componentData);
				}
			}
		}

		internal static void DamageAfter(StatChangeSystem system)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			if (damageHealth.Count == 0 && hitBatches.Count == 0)
			{
				return;
			}
			EntityManager entityManager = ((ComponentSystemBase)system).EntityManager;
			((EntityManager)(ref entityManager)).CompleteAllTrackedJobs();
			bool flag = default(bool);
			foreach (KeyValuePair<Entity, HitBatch> hitBatch in hitBatches)
			{
				if (!Ecs.Has<Health>(entityManager, hitBatch.Key))
				{
					continue;
				}
				float num = Ecs.Field<Health, float>(entityManager, hitBatch.Key, "Value", 16);
				if (hitBatch.Value.Before > 0f && num <= 0f)
				{
					lethalHits[hitBatch.Key] = (hitBatch.Value, Now);
					if (Plugin.Settings.Current.LogDamage)
					{
						ManualLogSource log = ((BasePlugin)Plugin.Instance).Log;
						BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(60, 7, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("DR LETHAL utc=");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(Now);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" victim=");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Entity>(hitBatch.Key);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" source=");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Entity>(hitBatch.Value.Source);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" cause=");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Cause>(hitBatch.Value.Cause);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" VBlood=");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(hitBatch.Value.VBlood);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" before=");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(hitBatch.Value.Before);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" after=");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num);
						}
						log.LogInfo(val);
					}
				}
				else if (num > 0f)
				{
					lethalHits.Remove(hitBatch.Key);
				}
			}
			hitBatches.Clear();
			foreach (KeyValuePair<Entity, (ulong, float)> item in damageHealth)
			{
				if (Ecs.Has<Health>(entityManager, item.Key))
				{
					float num2 = Ecs.Field<Health, float>(entityManager, item.Key, "Value", 16);
					((BasePlugin)Plugin.Instance).Log.LogInfo((object)FormattableString.Invariant($"DR HEALTH player={item.Value.Item1} before={item.Value.Item2:0.####} after={num2:0.####} netLoss={item.Value.Item2 - num2:0.####} scope=stat-change-batch"));
				}
			}
			damageHealth.Clear();
		}

		internal unsafe static void Deaths(DeathEventListenerSystem system)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Invalid comparison between Unknown and I4
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready(((ComponentSystemBase)system).World))
			{
				return;
			}
			EntityManager entityManager = ((ComponentSystemBase)system).EntityManager;
			EntityQuery deathEventQuery = system._DeathEventQuery;
			((EntityQuery)(ref deathEventQuery)).CompleteDependency();
			ScanDownings(entityManager);
			foreach (Entity item in Ecs.Entities(system._DeathEventQuery))
			{
				if (observedDeaths.Contains(item))
				{
					continue;
				}
				Entity val = Ecs.Field<DeathEvent, Entity>(entityManager, item, "Died", 0);
				if (TryPlayer(entityManager, val, out var user))
				{
					Entity source = Ecs.Field<DeathEvent, Entity>(entityManager, item, "Killer", 8);
					Entity source2 = Ecs.Field<DeathEvent, Entity>(entityManager, item, "Source", 16);
					StatChangeReason val2 = Ecs.Field<DeathEvent, StatChangeReason>(entityManager, item, "StatChangeReason", 24);
					Entity val3 = Source(entityManager, source);
					if (val3 == Entity.Null)
					{
						val3 = Source(entityManager, source2);
					}
					Cause cause = Classify(entityManager, val3, val, val2, completedDeath: true);
					bool isVBlood = Ecs.Has<VBloodUnit>(entityManager, val3);
					if ((int)val2 == 46 && downingCauses.TryGetValue(val, out (Cause, bool) value))
					{
						(cause, isVBlood) = value;
					}
					downingCauses.Remove(val);
					AwardCompletedDeath(entityManager, val, user, cause, isVBlood, ((object)(*(StatChangeReason*)(&val2))/*cast due to .constrained prefix*/).ToString());
					observedDeaths.Add(item);
				}
			}
		}

		internal static void BeforeRelease(ReviveCancelEventSystem system)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (Ready(((ComponentSystemBase)system).World))
			{
				EntityQuery _query_1443162900_ = system.__query_1443162900_0;
				((EntityQuery)(ref _query_1443162900_)).CompleteDependency();
				CaptureReleases(((ComponentSystemBase)system).World, Ecs.Entities(system.__query_1443162900_0));
			}
		}

		internal static void CaptureReleases(World candidate, List<Entity> requests)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			releaseCandidates.Clear();
			if (!Ready(candidate) || requests.Count == 0)
			{
				return;
			}
			EntityManager entityManager = candidate.EntityManager;
			((EntityManager)(ref entityManager)).CompleteAllTrackedJobs();
			ScanDownings(entityManager);
			List<Entity> list = Ecs.All<Buff>(entityManager);
			destroyEventsBeforeRelease.Clear();
			foreach (Entity item in Ecs.All<DestroyTagEvent>(entityManager))
			{
				destroyEventsBeforeRelease.Add(item);
			}
			bool flag4 = default(bool);
			foreach (Entity request in requests)
			{
				if (!Ecs.Has<FromCharacter>(entityManager, request))
				{
					continue;
				}
				Entity val = Ecs.Field<FromCharacter, Entity>(entityManager, request, "Character", 8);
				if (!TryPlayer(entityManager, val, out var _))
				{
					continue;
				}
				Entity val2 = Entity.Null;
				bool flag = false;
				bool flag2 = false;
				bool flag3 = false;
				foreach (Entity item2 in list)
				{
					if (!Ecs.Has<DestroyTag>(entityManager, item2) && !(Ecs.Field<Buff, Entity>(entityManager, item2, "Target", 8) != val))
					{
						flag |= Ecs.Has<ReviveCancelBuff>(entityManager, item2);
						flag2 |= Ecs.Has<BlockFeedBuff>(entityManager, item2);
						flag3 |= Ecs.Has<DraculaSaveDeathBuff>(entityManager, item2);
						if (Ecs.Has<VampireDownedBuff>(entityManager, item2))
						{
							val2 = item2;
						}
					}
				}
				if (Plugin.Settings.Current.LogDamage)
				{
					ManualLogSource log = ((BasePlugin)Plugin.Instance).Log;
					BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(68, 6, ref flag4);
					if (flag4)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("DR RELEASE victim=");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Entity>(val);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" canRelease=");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>(flag);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" blocked=");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>(flag2);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" dracula=");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>(flag3);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" downed=");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Entity>(val2);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" attributed=");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>(downingCauses.ContainsKey(val));
					}
					log.LogInfo(val3);
				}
				if (!(!flag || flag2) && flag3 && !(val2 == Entity.Null) && !awardedDraculaDownings.Contains(val2) && downingCauses.TryGetValue(val, out (Cause, bool) value))
				{
					releaseCandidates.Add((val, val2, value.Item1, value.Item2));
				}
			}
		}

		internal static void AfterRelease(World candidate)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready(candidate))
			{
				releaseCandidates.Clear();
				return;
			}
			EntityManager em = candidate.EntityManager;
			((EntityManager)(ref em)).CompleteAllTrackedJobs();
			if (releaseCandidates.Count == 0)
			{
				return;
			}
			HashSet<Entity> hashSet = new HashSet<Entity>();
			foreach (Entity item in Ecs.All<DestroyTagEvent>(em))
			{
				if (!destroyEventsBeforeRelease.Contains(item))
				{
					hashSet.Add(Ecs.Field<DestroyTagEvent, Entity>(em, item, "Entity", 0));
				}
			}
			bool flag2 = default(bool);
			foreach (var releaseCandidate in releaseCandidates)
			{
				bool flag = hashSet.Contains(releaseCandidate.Downed) || !((EntityManager)(ref em)).Exists(releaseCandidate.Downed) || Ecs.Has<DestroyTag>(em, releaseCandidate.Downed);
				if (Plugin.Settings.Current.LogDamage)
				{
					ManualLogSource log = ((BasePlugin)Plugin.Instance).Log;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(52, 4, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("DR RELEASE outcome victim=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Entity>(releaseCandidate.Victim);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" downed=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Entity>(releaseCandidate.Downed);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" accepted=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(flag);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" queued=");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(hashSet.Contains(releaseCandidate.Downed));
					}
					log.LogInfo(val);
				}
				if (flag && TryPlayer(em, releaseCandidate.Victim, out var user) && awardedDraculaDownings.Add(releaseCandidate.Downed))
				{
					downingCauses.Remove(releaseCandidate.Victim);
					AwardCompletedDeath(em, releaseCandidate.Victim, user, releaseCandidate.Cause, releaseCandidate.VBlood, "Dracula chamber release");
				}
			}
			releaseCandidates.Clear();
			awardedDraculaDownings.RemoveWhere((Entity e) => !((EntityManager)(ref em)).Exists(e));
		}

		private static void AwardCompletedDeath(EntityManager em, Entity victim, User user, Cause cause, bool isVBlood, string reason)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			PlayerState playerState = Get(user.PlatformId);
			Settings current = Plugin.Settings.Current;
			PlayerState playerState2 = Rules.Award(playerState, current, Now, cause, downing: false, isVBlood);
			Put(user.PlatformId, playerState2);
			lethalHits.Remove(victim);
			string text = (playerState2.OptedOut ? "opted-out" : ((current.OnlyVBloodDeathsGrantStacks && (cause != Cause.Creature || !isVBlood)) ? "requires-vblood" : ((!Rules.GrantsDeath(current, cause)) ? $"excluded-{cause}" : ((playerState2.Stacks > playerState.Stacks) ? "stack-added" : "timer-refreshed"))));
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val;
			if (current.LogDamage)
			{
				ManualLogSource log = ((BasePlugin)Plugin.Instance).Log;
				val = new BepInExInfoLogInterpolatedStringHandler(113, 13, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("DR AWARD utc=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(Now);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" player=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ulong>(user.PlatformId);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" victim=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Entity>(victim);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" reason=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" cause=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Cause>(cause);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" VBlood=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(isVBlood);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" verdict=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" stacks=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(playerState.Stacks);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("->");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(playerState2.Stacks);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" expiry=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(playerState2.ExpiresUtcMs);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" sunGrants=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(current.SunDeathsGrantStacks);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" pvpGrants=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(current.PvpDeathsGrantStacks);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" vbloodOnly=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(current.OnlyVBloodDeathsGrantStacks);
				}
				log.LogInfo(val);
			}
			ManualLogSource log2 = ((BasePlugin)Plugin.Instance).Log;
			val = new BepInExInfoLogInterpolatedStringHandler(69, 7, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Player death: player=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ulong>(user.PlatformId);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", reason=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", cause=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Cause>(cause);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", VBlood=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(isVBlood);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", stacks=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(playerState.Stacks);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("->");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(playerState2.Stacks);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", optedOut=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(playerState2.OptedOut);
			}
			log2.LogInfo(val);
			if (!playerState2.OptedOut && playerState2.Stacks > 0 && Rules.GrantsDeath(current, cause) && (!current.OnlyVBloodDeathsGrantStacks || (cause == Cause.Creature && isVBlood)))
			{
				Entity userEntity = ((EntityManager)(ref em)).GetComponentData<PlayerCharacter>(victim).UserEntity;
				SendText(em, userEntity, $"Death Resistance: {Display.Value(Rules.Reduction(playerState2, current, Now))}% less eligible damage taken ({playerState2.Stacks} stack{((playerState2.Stacks == 1) ? "" : "s")}). Type {Display.Label(".dr status")} for details.");
			}
		}

		internal static void Downings(World candidate)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (Ready(candidate))
			{
				ScanDownings(candidate.EntityManager);
			}
		}

		private static void ScanDownings(EntityManager em)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_005f: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			List<Entity> list = Ecs.All<VampireDownedBuff>(em);
			HashSet<Entity> hashSet = new HashSet<Entity>();
			bool flag2 = default(bool);
			foreach (Entity item in list)
			{
				hashSet.Add(item);
				if (observedDownings.Contains(item) || !Ecs.Has<Buff>(em, item))
				{
					continue;
				}
				Entity val = Ecs.Field<Buff, Entity>(em, item, "Target", 8);
				if (!TryPlayer(em, val, out var user))
				{
					continue;
				}
				Entity val2 = Ecs.Field<VampireDownedBuff, Entity>(em, item, "Source", 0);
				Entity val3 = Source(em, val2);
				User user2;
				Cause cause = ((val3 == val || val3 == Entity.Null) ? Cause.Other : (TryPlayer(em, val3, out user2) ? Cause.Player : ((!Ecs.Has<UnitLevel>(em, val3)) ? Cause.Other : Cause.Creature)));
				bool flag = Ecs.Has<VBloodUnit>(em, val3);
				string text = "downed-source";
				(HitBatch, long) value;
				bool num = lethalHits.Remove(val, out value);
				long num2 = (num ? (Now - value.Item2) : (-1));
				if (num && num2 >= 0 && num2 <= 10000 && Ecs.Has<Health>(em, val) && Ecs.Field<Health, float>(em, val, "Value", 16) <= 0f)
				{
					cause = value.Item1.Cause;
					flag = value.Item1.VBlood;
					text = "confirmed-lethal-batch";
				}
				downingCauses[val] = (cause, flag);
				if (Plugin.Settings.Current.LogDamage)
				{
					ManualLogSource log = ((BasePlugin)Plugin.Instance).Log;
					BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(143, 13, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("DR DOWNED utc=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<long>(Now);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" player=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<ulong>(user.PlatformId);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" victim=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Entity>(val);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" buff=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Entity>(item);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" rawSource=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Entity>(val2);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" sourceExists=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>(((EntityManager)(ref em)).Exists(val2));
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" resolvedSource=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Entity>(val3);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" sourceId=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(Ecs.Field<VampireDownedBuff, int>(em, item, "SourceId", 16));
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" sourceSpellId=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(Ecs.Field<VampireDownedBuff, int>(em, item, "SourceSpellId", 20));
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" lethalAgeMs=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<long>(num2);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" attribution=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" cause=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Cause>(cause);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" VBlood=");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>(flag);
					}
					log.LogInfo(val4);
				}
				Put(user.PlatformId, Rules.Award(Get(user.PlatformId), Plugin.Settings.Current, Now, cause, downing: true));
				observedDownings.Add(item);
			}
			observedDownings.IntersectWith(hashSet);
		}

		private static bool HasDowning(EntityManager em, Entity character)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			foreach (Entity observedDowning in observedDownings)
			{
				if (Ecs.Has<Buff>(em, observedDowning) && Ecs.Field<Buff, Entity>(em, observedDowning, "Target", 8) == character)
				{
					return true;
				}
			}
			return false;
		}

		private static bool TryPlayer(EntityManager em, Entity character, out User user)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			user = default(User);
			if (!Ecs.Has<PlayerCharacter>(em, character))
			{
				return false;
			}
			Entity userEntity = ((EntityManager)(ref em)).GetComponentData<PlayerCharacter>(character).UserEntity;
			if (!Ecs.Has<User>(em, userEntity))
			{
				return false;
			}
			user = ((EntityManager)(ref em)).GetComponentData<User>(userEntity);
			return true;
		}

		private static Entity Source(EntityManager em, Entity source)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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)
			Entity result = Entity.Null;
			HashSet<Entity> hashSet = new HashSet<Entity>();
			for (int i = 0; i < 16; i++)
			{
				if (!(source != Entity.Null))
				{
					break;
				}
				if (!((EntityManager)(ref em)).Exists(source))
				{
					break;
				}
				if (!hashSet.Add(source))
				{
					return Entity.Null;
				}
				if (TryPlayer(em, source, out var _))
				{
					return source;
				}
				if (Ecs.Has<UnitLevel>(em, source))
				{
					result = source;
				}
				if (!Ecs.Has<EntityOwner>(em, source))
				{
					break;
				}
				source = Ecs.Field<EntityOwner, Entity>(em, source, "Owner", 0);
			}
			return result;
		}

		private static Cause Classify(EntityManager em, Entity source, Entity victim, StatChangeReason reason, bool completedDeath = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			if ((int)reason == 36)
			{
				return Cause.Sun;
			}
			if (source == victim || source == Entity.Null)
			{
				return Cause.Other;
			}
			if ((int)reason != 28 && (!completedDeath || (int)reason != 15))
			{
				return Cause.Other;
			}
			if (TryPlayer(em, source, out var _))
			{
				return Cause.Player;
			}
			if (!Ecs.Has<UnitLevel>(em, source))
			{
				return Cause.Other;
			}
			return Cause.Creature;
		}

		private static double Level(EntityManager em, Entity source)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (Ecs.Has<PlayerCharacter>(em, source) && Ecs.Has<Equipment>(em, source))
			{
				return Ecs.Field<Equipment, float>(em, source, "WeaponLevel", 0) + Ecs.Field<Equipment, float>(em, source, "ArmorLevel", 4) + Ecs.Field<Equipment, float>(em, source, "SpellLevel", 8);
			}
			if (Ecs.Has<UnitLevel>(em, source))
			{
				return Ecs.Field<UnitLevel, int>(em, source, "Level", 0);
			}
			return double.NaN;
		}

		internal static bool SendText(EntityManager em, Entity userEntity, string text)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!Ecs.Has<ConnectedUser>(em, userEntity))
			{
				return false;
			}
			int num = Ecs.Field<ConnectedUser, byte>(em, userEntity, "UserIndex", 0);
			if (num > 127)
			{
				return false;
			}
			FixedString512Bytes val = FixedString512Bytes.op_Implicit(text);
			NetworkId val2 = default(NetworkId);
			ServerChatUtils.SendChatMessage(em, ref num, ref val, ref val2, ref val2, (ServerChatMessageType)6, DateTimeOffset.UtcNow.ToUnixTimeSeconds());
			return true;
		}

		internal static void Guard(Action action)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				failed = true;
				if (Now >= nextError)
				{
					nextError = Now + 30000;
					((BasePlugin)Plugin.Instance).Log.LogError((object)("Death Resistance disabled for this world after an error. Fix the issue and restart the mod. " + ex));
				}
			}
		}
	}
	[HarmonyPatch(typeof(ServerBootstrapSystem), "OnUpdate")]
	internal static class TickPatch
	{
		[HarmonyPostfix]
		private static void After(ServerBootstrapSystem __instance)
		{
			Runtime.Guard(delegate
			{
				Runtime.Tick(((ComponentSystemBase)__instance).World);
			});
		}
	}
	[HarmonyPatch(typeof(StatChangeSystem), "OnUpdate")]
	internal static class DamagePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static void Before(StatChangeSystem __instance)
		{
			Runtime.Guard(delegate
			{
				Runtime.Damage(__instance);
			});
		}

		[HarmonyPostfix]
		private static void After(StatChangeSystem __instance)
		{
			Runtime.Guard(delegate
			{
				Runtime.DamageAfter(__instance);
			});
		}
	}
	[HarmonyPatch(typeof(DeathEventListenerSystem), "OnUpdate")]
	internal static class DeathPatch
	{
		[HarmonyPrefix]
		private static void Before(DeathEventListenerSystem __instance)
		{
			Runtime.Guard(delegate
			{
				Runtime.Deaths(__instance);
			});
		}
	}
	[HarmonyPatch(typeof(DownedEventSystem), "OnUpdate")]
	internal static class DownedPatch
	{
		[HarmonyPostfix]
		private static void After(DownedEventSystem __instance)
		{
			Runtime.Guard(delegate
			{
				Runtime.Downings(((ComponentSystemBase)__instance).World);
			});
		}
	}
	[HarmonyPatch(typeof(ReviveCancelEventSystem), "OnUpdate")]
	internal static class DraculaReleasePatch
	{
		[HarmonyPrefix]
		private static void Before(ReviveCancelEventSystem __instance)
		{
			Runtime.Guard(delegate
			{
				Runtime.BeforeRelease(__instance);
			});
		}

		[HarmonyPostfix]
		private static void After(ReviveCancelEventSystem __instance)
		{
			Runtime.Guard(delegate
			{
				Runtime.AfterRelease(((ComponentSystemBase)__instance).World);
			});
		}
	}
	public sealed class StateStore
	{
		private sealed record Document(int Schema, Dictionary<ulong, PlayerState> Players);

		private readonly string path;

		private Dictionary<ulong, PlayerState> players;

		public StateStore(string path)
		{
			this.path = path;
			players = new Dictionary<ulong, PlayerState>();
			if (File.Exists(path))
			{
				Document document = JsonSerializer.Deserialize<Document>(File.ReadAllText(path)) ?? throw new InvalidDataException("Empty Death Resistance state file.");
				if (document.Schema != 1 || document.Players == null)
				{
					throw new InvalidDataException("Unsupported Death Resistance state schema.");
				}
				if (document.Players.Any<KeyValuePair<ulong, PlayerState>>((KeyValuePair<ulong, PlayerState> p) => p.Value == null || p.Value.Stacks < 0 || p.Value.ExpiresUtcMs < 0))
				{
					throw new InvalidDataException("Invalid Death Resistance player state.");
				}
				players = document.Players;
			}
		}

		public PlayerState Get(ulong id)
		{
			if (!players.TryGetValue(id, out PlayerState value))
			{
				return new PlayerState();
			}
			return value;
		}

		public void Put(ulong id, PlayerState state)
		{
			if (!(Get(id) == state))
			{
				Dictionary<ulong, PlayerState> next = new Dictionary<ulong, PlayerState>(players) { [id] = state };
				Commit(next);
			}
		}

		public void NormalizeAll(Settings settings, long now)
		{
			Dictionary<ulong, PlayerState> dictionary = players.ToDictionary<KeyValuePair<ulong, PlayerState>, ulong, PlayerState>((KeyValuePair<ulong, PlayerState> p) => p.Key, (KeyValuePair<ulong, PlayerState> p) => Rules.Normalize(p.Value, settings, now));
			if (dictionary.Any((KeyValuePair<ulong, PlayerState> p) => p.Value != players[p.Key]))
			{
				Commit(dictionary);
			}
		}

		private void Commit(Dictionary<ulong, PlayerState> next)
		{
			Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path)));
			string sourceFileName = path + ".tmp";
			using (FileStream fileStream = new FileStream(sourceFileName, FileMode.Create, FileAccess.Write, FileShare.None))
			{
				JsonSerializer.Serialize(fileStream, new Document(1, next));
				fileStream.Flush(flushToDisk: true);
			}
			if (File.Exists(path))
			{
				File.Replace(sourceFileName, path, path + ".bak");
			}
			else
			{
				File.Move(sourceFileName, path);
			}
			players = next;
		}
	}
	internal static class Ecs
	{
		private static readonly HashSet<string> CheckedFields = new HashSet<string>();

		internal static List<Entity> Entities(EntityQuery query)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			NativeArray<Entity> val = ((EntityQuery)(ref query)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2));
			try
			{
				List<Entity> list = new List<Entity>(val.Length);
				for (int i = 0; i < val.Length; i++)
				{
					list.Add(val[i]);
				}
				return list;
			}
			finally
			{
				val.Dispose();
			}
		}

		internal static List<Entity> All<T>(EntityManager em)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			EntityQuery query = Query<T>(em);
			try
			{
				return Entities(query);
			}
			finally
			{
				((EntityQuery)(ref query)).Dispose();
			}
		}

		internal static ComponentType Type<T>()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return new ComponentType(Il2CppType.Of<T>(), (AccessMode)0);
		}

		internal static bool Has<T>(EntityManager em, Entity e)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (e != Entity.Null && ((EntityManager)(ref em)).Exists(e))
			{
				return ((EntityManager)(ref em)).HasComponent(e, Type<T>());
			}
			return false;
		}

		internal static EntityQuery Query<T>(EntityManager em)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			EntityQueryBuilder val = default(EntityQueryBuilder);
			((EntityQueryBuilder)(ref val))..ctor(AllocatorHandle.op_Implicit((Allocator)2));
			try
			{
				EntityQueryBuilder val2 = ((EntityQueryBuilder)(ref val)).AddAll(Type<T>());
				val = ((EntityQueryBuilder)(ref val2)).WithOptions((EntityQueryOptions)18);
				return ((EntityManager)(ref em)).CreateEntityQuery(ref val);
			}
			finally
			{
				((EntityQueryBuilder)(ref val)).Dispose();
			}
		}

		internal unsafe static TValue Field<TComponent, TValue>(EntityManager em, Entity e, string name, int offset) where TValue : unmanaged
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			string text = typeof(TComponent).FullName + "." + name;
			if (!CheckedFields.Contains(text))
			{
				IntPtr il2CppField = IL2CPP.GetIl2CppField(Il2CppClassPointerStore<TComponent>.NativeClassPtr, name);
				if (il2CppField == IntPtr.Zero)
				{
					throw new InvalidOperationException("Missing game field: " + text);
				}
				uint num = IL2CPP.il2cpp_field_get_offset(il2CppField);
				if (num != offset && num != offset + 2 * IntPtr.Size)
				{
					throw new InvalidOperationException($"Unsupported game layout for {text}: offset {num}.");
				}
				CheckedFields.Add(text);
			}
			byte* componentDataRawRO = (byte*)((EntityManager)(ref em)).GetComponentDataRawRO(e, TypeManager.GetTypeIndex(Il2CppType.Of<TComponent>()));
			if (componentDataRawRO == null)
			{
				throw new InvalidOperationException("Missing component data for " + text);
			}
			return Unsafe.ReadUnaligned<TValue>(componentDataRawRO + offset);
		}
	}
	public enum Cause
	{
		Creature,
		Player,
		Sun,
		Other
	}
	public sealed record Settings
	{
		public bool LogDamage { get; init; }

		public bool EnabledByDefault { get; init; } = true;

		public int LevelAllowance { get; init; } = 3;

		public double ReductionPerStack { get; init; } = 10.0;

		public int MaxStacks { get; init; }

		public double DurationSeconds { get; init; } = 3600.0;

		public bool ReduceSunDamage { get; init; }

		public bool SunDeathsGrantStacks { get; init; }

		public bool ReducePvpDamage { get; init; }

		public bool PvpDeathsGrantStacks { get; init; }

		public bool PvpDowningsGrantStacks { get; init; }

		public bool OnlyVBloodDeathsGrantStacks { get; init; }

		public int EffectiveCap => Math.Min((MaxStacks == 0) ? int.MaxValue : MaxStacks, (int)Math.Ceiling(100.0 / ReductionPerStack));

		public void Validate()
		{
			if (LevelAllowance < 0 || LevelAllowance > 1000)
			{
				throw new ArgumentException("LevelAllowance must be 0–1000.");
			}
			if (!double.IsFinite(ReductionPerStack) || ReductionPerStack < 0.01 || ReductionPerStack > 100.0)
			{
				throw new ArgumentException("ReductionPerStack must be 0.01–100 percent.");
			}
			if (Math.Round(ReductionPerStack, 2) != ReductionPerStack)
			{
				throw new ArgumentException("ReductionPerStack supports at most two decimal places, so the displayed percentage is exact.");
			}
			if (MaxStacks < 0 || MaxStacks > 10000)
			{
				throw new ArgumentException("MaxStacks must be 0–10000 (0 = until immunity).");
			}
			if (!double.IsFinite(DurationSeconds) || DurationSeconds < 1.0 || DurationSeconds > 31536000.0)
			{
				throw new ArgumentException("DurationSeconds must be 1–31536000.");
			}
		}
	}
	public sealed record PlayerState
	{
		public bool HasPreference { get; init; }

		public bool OptedOut { get; init; }

		public int Stacks { get; init; }

		public long ExpiresUtcMs { get; init; }

		public bool DowningAwarded { get; init; }
	}
	public static class Rules
	{
		public static PlayerState Normalize(PlayerState state, Settings settings, long now)
		{
			if (!state.HasPreference)
			{
				state = state with
				{
					OptedOut = !settings.EnabledByDefault
				};
			}
			return state with
			{
				Stacks = ((!state.OptedOut && state.ExpiresUtcMs > now) ? Math.Clamp(state.Stacks, 0, settings.EffectiveCap) : 0),
				ExpiresUtcMs = ((state.OptedOut || state.ExpiresUtcMs <= now) ? 0 : state.ExpiresUtcMs)
			};
		}

		public static double Reduction(PlayerState state, Settings settings, long now)
		{
			return Math.Min(100.0, (double)Normalize(state, settings, now).Stacks * settings.ReductionPerStack);
		}

		public static PlayerState Award(PlayerState state, Settings settings, long now, Cause cause, bool downing, bool sourceIsVBlood = false)
		{
			state = Normalize(state, settings, now);
			if (state.OptedOut)
			{
				return state;
			}
			if (settings.OnlyVBloodDeathsGrantStacks && (downing || cause != Cause.Creature || !sourceIsVBlood))
			{
				if (!downing)
				{
					return state with
					{
						DowningAwarded = false
					};
				}
				return state;
			}
			if (downing)
			{
				if (cause != Cause.Player || !settings.PvpDowningsGrantStacks || state.DowningAwarded)
				{
					return state;
				}
			}
			else
			{
				if (!GrantsDeath(settings, cause))
				{
					return state with
					{
						DowningAwarded = false
					};
				}
				if (state.DowningAwarded && state.Stacks > 0)
				{
					return state with
					{
						DowningAwarded = false,
						ExpiresUtcMs = now + (long)(settings.DurationSeconds * 1000.0)
					};
				}
			}
			return state with
			{
				Stacks = Math.Min(settings.EffectiveCap, state.Stacks + 1),
				ExpiresUtcMs = now + (long)(settings.DurationSeconds * 1000.0),
				DowningAwarded = downing
			};
		}

		public static bool GrantsDeath(Settings settings, Cause cause)
		{
			return cause switch
			{
				Cause.Creature => true, 
				Cause.Player => settings.PvpDeathsGrantStacks, 
				Cause.Sun => settings.SunDeathsGrantStacks, 
				_ => false, 
			};
		}

		public static bool Covers(Settings settings, Cause cause, double playerLevel, double sourceLevel)
		{
			if (cause == Cause.Sun)
			{
				return settings.ReduceSunDamage;
			}
			if (cause == Cause.Other || (cause == Cause.Player && !settings.ReducePvpDamage))
			{
				return false;
			}
			if (double.IsFinite(playerLevel) && double.IsFinite(sourceLevel) && playerLevel >= 0.0 && sourceLevel >= 0.0)
			{
				return sourceLevel <= playerLevel + (double)settings.LevelAllowance;
			}
			return false;
		}

		public static float Damage(float change, PlayerState state, Settings settings, long now, Cause cause, double playerLevel, double sourceLevel)
		{
			if (!float.IsFinite(change) || change >= 0f || !Covers(settings, cause, playerLevel, sourceLevel))
			{
				return change;
			}
			return (float)((double)change * (1.0 - Reduction(state, settings, now) / 100.0));
		}

		public static string Card(PlayerState state, Settings settings, long now)
		{
			state = Normalize(state, settings, now);
			TimeSpan timeSpan = TimeSpan.FromSeconds(Math.Max(0L, (long)Math.Ceiling((double)(state.ExpiresUtcMs - now) / 1000.0)));
			string text = $"{(int)timeSpan.TotalHours:00}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00}";
			string text2 = (state.OptedOut ? "Off — opted out" : ((state.Stacks == 0) ? "On — awaiting a qualifying death" : "On — protection active"));
			return $"{Display.Label("Death Resistance")} — {Display.Color(text2, state.OptedOut ? "#F28B82" : "#81C995")}\n{Display.Value(Reduction(state, settings, now))}% less eligible damage taken\nStacks: {Display.Value(state.Stacks)}/{Display.Value(settings.EffectiveCap)} | Remaining: {Display.Color(text, "#FDD663")}";
		}

		public static string SettingsCard(Settings settings)
		{
			return $"{Display.Label("Death Resistance settings")}\nDamage reduction per death: {Display.Value(settings.ReductionPerStack)}% (additive)\nDuration: {Display.Value(settings.DurationSeconds / 60.0)} min | Stack cap: {Display.Value(settings.EffectiveCap)}\nProtection from sources: your level +{Display.Value(settings.LevelAllowance)} or lower\nSun reduction: {On(settings.ReduceSunDamage)} | Sun death stacks: {On(settings.SunDeathsGrantStacks)}\nPvP reduction: {On(settings.ReducePvpDamage)} | PvP death stacks: {On(settings.PvpDeathsGrantStacks)}\nPvP downing stacks: {On(settings.PvpDowningsGrantStacks)}\nStack grants restricted to V Blood deaths: {On(settings.OnlyVBloodDeathsGrantStacks)}\nDefault participation: {On(settings.EnabledByDefault)}";
			static string On(bool enabled)
			{
				return Display.Value(enabled);
			}
		}
	}
	public static class Display
	{
		public const string Green = "#81C995";

		public const string Red = "#F28B82";

		public const string Gold = "#FDD663";

		public static string Color(string text, string color)
		{
			return $"<color={color}>{text}</color>";
		}

		public static string Label(string text)
		{
			return Color(text, "#8AB4F8");
		}

		public static string Value(object value)
		{
			if (!(value is bool flag))
			{
				return Color(Convert.ToString(value, CultureInfo.InvariantCulture) ?? "", "#FDD663");
			}
			return Color(flag ? "On" : "Off", flag ? "#81C995" : "#F28B82");
		}

		public static string Setting(string key, object value)
		{
			return Label(key) + " = " + Value(value);
		}
	}
}