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 ", "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 entries = new Dictionary(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(string key, T value, string description) { entries[key] = (ConfigEntryBase)(object)file.Bind("General", key, value, description); } private T Value(string key) { return (T)entries[key].BoxedValue; } private Settings Read() { return new Settings { LogDamage = Value("LogDamage"), EnabledByDefault = Value("EnabledByDefault"), LevelAllowance = Value("LevelAllowance"), ReductionPerStack = Value("ReductionPerStack"), MaxStacks = Value("MaxStacks"), DurationSeconds = Value("DurationSeconds"), ReduceSunDamage = Value("ReduceSunDamage"), SunDeathsGrantStacks = Value("SunDeathsGrantStacks"), ReducePvpDamage = Value("ReducePvpDamage"), PvpDeathsGrantStacks = Value("PvpDeathsGrantStacks"), PvpDowningsGrantStacks = Value("PvpDowningsGrantStacks"), OnlyVBloodDeathsGrantStacks = Value("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 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 observedDownings = new HashSet(); private static readonly HashSet observedDeaths = new HashSet(); private static readonly Dictionary downingCauses = new Dictionary(); private static readonly Dictionary damageHealth = new Dictionary(); private static readonly List<(Entity Victim, Entity Downed, Cause Cause, bool VBlood)> releaseCandidates = new List<(Entity, Entity, Cause, bool)>(); private static readonly HashSet awardedDraculaDownings = new HashSet(); private static readonly HashSet destroyEventsBeforeRelease = new HashSet(); private static readonly Dictionary hitBatches = new Dictionary(); private static readonly Dictionary lethalHits = new Dictionary(); 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 list = Ecs.All(entityManager); if (list.Count == 0) { return false; } string text = ((object)Ecs.Field(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(em)) { User componentData = ((EntityManager)(ref em)).GetComponentData(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(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(em, val) && Ecs.Field(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(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 list = Ecs.Entities(system._Query); Settings current = Plugin.Settings.Current; long now = Now; foreach (Entity item in list) { if (!Ecs.Has(entityManager, item)) { continue; } StatChangeEvent componentData = ((EntityManager)(ref entityManager)).GetComponentData(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(entityManager, componentData.Entity)) { HitBatch hitBatch = new HitBatch(Ecs.Field(entityManager, componentData.Entity, "Value", 16), cause, Ecs.Has(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(entityManager, componentData.Entity)) { damageHealth[componentData.Entity] = (user.PlatformId, Ecs.Field(entityManager, componentData.Entity, "Value", 16)); } } if (num3 != componentData.Change) { componentData.Change = num3; ((EntityManager)(ref entityManager)).SetComponentData(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 hitBatch in hitBatches) { if (!Ecs.Has(entityManager, hitBatch.Key)) { continue; } float num = Ecs.Field(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(Now); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" victim="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(hitBatch.Key); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" source="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(hitBatch.Value.Source); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" cause="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(hitBatch.Value.Cause); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" VBlood="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(hitBatch.Value.VBlood); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" before="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(hitBatch.Value.Before); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" after="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num); } log.LogInfo(val); } } else if (num > 0f) { lethalHits.Remove(hitBatch.Key); } } hitBatches.Clear(); foreach (KeyValuePair item in damageHealth) { if (Ecs.Has(entityManager, item.Key)) { float num2 = Ecs.Field(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(entityManager, item, "Died", 0); if (TryPlayer(entityManager, val, out var user)) { Entity source = Ecs.Field(entityManager, item, "Killer", 8); Entity source2 = Ecs.Field(entityManager, item, "Source", 16); StatChangeReason val2 = Ecs.Field(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(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 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 list = Ecs.All(entityManager); destroyEventsBeforeRelease.Clear(); foreach (Entity item in Ecs.All(entityManager)) { destroyEventsBeforeRelease.Add(item); } bool flag4 = default(bool); foreach (Entity request in requests) { if (!Ecs.Has(entityManager, request)) { continue; } Entity val = Ecs.Field(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(entityManager, item2) && !(Ecs.Field(entityManager, item2, "Target", 8) != val)) { flag |= Ecs.Has(entityManager, item2); flag2 |= Ecs.Has(entityManager, item2); flag3 |= Ecs.Has(entityManager, item2); if (Ecs.Has(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(val); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" canRelease="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(flag); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" blocked="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(flag2); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" dracula="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(flag3); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" downed="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(val2); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" attributed="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(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 hashSet = new HashSet(); foreach (Entity item in Ecs.All(em)) { if (!destroyEventsBeforeRelease.Contains(item)) { hashSet.Add(Ecs.Field(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(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(releaseCandidate.Victim); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" downed="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(releaseCandidate.Downed); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" accepted="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(flag); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" queued="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(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(Now); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" player="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(user.PlatformId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" victim="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(victim); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" reason="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" cause="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(cause); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" VBlood="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(isVBlood); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" verdict="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" stacks="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(playerState.Stacks); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("->"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(playerState2.Stacks); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" expiry="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(playerState2.ExpiresUtcMs); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" sunGrants="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(current.SunDeathsGrantStacks); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" pvpGrants="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(current.PvpDeathsGrantStacks); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" vbloodOnly="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(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(user.PlatformId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", reason="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", cause="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(cause); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", VBlood="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(isVBlood); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", stacks="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(playerState.Stacks); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("->"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(playerState2.Stacks); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", optedOut="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(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(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 list = Ecs.All(em); HashSet hashSet = new HashSet(); bool flag2 = default(bool); foreach (Entity item in list) { hashSet.Add(item); if (observedDownings.Contains(item) || !Ecs.Has(em, item)) { continue; } Entity val = Ecs.Field(em, item, "Target", 8); if (!TryPlayer(em, val, out var user)) { continue; } Entity val2 = Ecs.Field(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(em, val3)) ? Cause.Other : Cause.Creature))); bool flag = Ecs.Has(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(em, val) && Ecs.Field(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(Now); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" player="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(user.PlatformId); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" victim="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(val); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" buff="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(item); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" rawSource="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(val2); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" sourceExists="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(((EntityManager)(ref em)).Exists(val2)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" resolvedSource="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(val3); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" sourceId="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(Ecs.Field(em, item, "SourceId", 16)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" sourceSpellId="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(Ecs.Field(em, item, "SourceSpellId", 20)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" lethalAgeMs="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(num2); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" attribution="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" cause="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(cause); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" VBlood="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted(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(em, observedDowning) && Ecs.Field(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(em, character)) { return false; } Entity userEntity = ((EntityManager)(ref em)).GetComponentData(character).UserEntity; if (!Ecs.Has(em, userEntity)) { return false; } user = ((EntityManager)(ref em)).GetComponentData(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 hashSet = new HashSet(); 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(em, source)) { result = source; } if (!Ecs.Has(em, source)) { break; } source = Ecs.Field(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(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(em, source) && Ecs.Has(em, source)) { return Ecs.Field(em, source, "WeaponLevel", 0) + Ecs.Field(em, source, "ArmorLevel", 4) + Ecs.Field(em, source, "SpellLevel", 8); } if (Ecs.Has(em, source)) { return Ecs.Field(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(em, userEntity)) { return false; } int num = Ecs.Field(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 Players); private readonly string path; private Dictionary players; public StateStore(string path) { this.path = path; players = new Dictionary(); if (File.Exists(path)) { Document document = JsonSerializer.Deserialize(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 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 next = new Dictionary(players) { [id] = state }; Commit(next); } } public void NormalizeAll(Settings settings, long now) { Dictionary dictionary = players.ToDictionary, ulong, PlayerState>((KeyValuePair p) => p.Key, (KeyValuePair p) => Rules.Normalize(p.Value, settings, now)); if (dictionary.Any((KeyValuePair p) => p.Value != players[p.Key])) { Commit(dictionary); } } private void Commit(Dictionary 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 CheckedFields = new HashSet(); internal static List 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 val = ((EntityQuery)(ref query)).ToEntityArray(AllocatorHandle.op_Implicit((Allocator)2)); try { List list = new List(val.Length); for (int i = 0; i < val.Length; i++) { list.Add(val[i]); } return list; } finally { val.Dispose(); } } internal static List All(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(em); try { return Entities(query); } finally { ((EntityQuery)(ref query)).Dispose(); } } internal static ComponentType Type() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return new ComponentType(Il2CppType.Of(), (AccessMode)0); } internal static bool Has(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()); } return false; } internal static EntityQuery Query(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()); val = ((EntityQueryBuilder)(ref val2)).WithOptions((EntityQueryOptions)18); return ((EntityManager)(ref em)).CreateEntityQuery(ref val); } finally { ((EntityQueryBuilder)(ref val)).Dispose(); } } internal unsafe static TValue Field(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.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())); if (componentDataRawRO == null) { throw new InvalidOperationException("Missing component data for " + text); } return Unsafe.ReadUnaligned(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 $"{text}"; } 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); } } }