Decompiled source of KillFeed v1.1.4
BepInEx/plugins/GTFOKillFeed/GTFOKillFeed.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using AK; using Agents; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using CharacterDestruction; using Enemies; using FX_EffectSystem; using GameData; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem.Collections.Generic; using Player; using SNetwork; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("1.1.4.0")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.4.0")] [module: UnverifiableCode] namespace HawChow.GTFOKillFeed; public sealed class CorpseVisualLease : MonoBehaviour { private Renderer[] _renderers; private bool[] _enabled; private Rigidbody[] _bodies; private bool[] _kinematic; private bool[] _gravity; private float[] _drag; internal Vector3[] Origins; internal int Generation; internal int BodyCount { get { Rigidbody[] bodies = _bodies; if (bodies == null) { return 0; } return bodies.Length; } } internal Vector3 Center { get { //IL_0035: 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) if (_bodies != null && _bodies.Length != 0 && (Object)(object)_bodies[0] != (Object)null) { return _bodies[0].position; } return ((Component)this).transform.position; } } public CorpseVisualLease(IntPtr pointer) : base(pointer) { } internal void Capture() { //IL_00c6: 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) RestoreState(); _renderers = Il2CppArrayBase<Renderer>.op_Implicit(((Component)this).GetComponentsInChildren<Renderer>(true)); _enabled = new bool[_renderers.Length]; for (int i = 0; i < _renderers.Length; i++) { _enabled[i] = _renderers[i].enabled; } _bodies = Il2CppArrayBase<Rigidbody>.op_Implicit(((Component)this).GetComponentsInChildren<Rigidbody>(true)); Origins = (Vector3[])(object)new Vector3[_bodies.Length]; _kinematic = new bool[_bodies.Length]; _gravity = new bool[_bodies.Length]; _drag = new float[_bodies.Length]; for (int j = 0; j < _bodies.Length; j++) { Rigidbody val = _bodies[j]; Origins[j] = val.position; _kinematic[j] = val.isKinematic; _gravity[j] = val.useGravity; _drag[j] = val.drag; } } internal void Launch(Vector3 direction, float strength) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_0086: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00a9: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_00b7: 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_00c8: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00f0: Unknown result type (might be due to invalid IL or missing references) if (_bodies == null || _bodies.Length == 0) { return; } Vector3 center = Center; for (int i = 0; i < _bodies.Length; i++) { Rigidbody val = _bodies[i]; if (!((Object)(object)val == (Object)null)) { val.isKinematic = false; val.useGravity = true; val.drag = 0.8f; Vector3 val2 = val.position - center; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = direction; } else { val2.y = Mathf.Max(val2.y, 0.15f); Vector3 val3 = ((Vector3)(ref val2)).normalized * 0.8f + direction * 0.2f; val2 = ((Vector3)(ref val3)).normalized; } val.velocity = val2 * FeedbackPolicy.LaunchSpeed(strength) + Vector3.up * (1.6f + strength); val.angularVelocity = Vector3.Cross(val2, Vector3.up) * (1f + strength * 2f); } } } internal void Limit(float maxDistance) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_003c: 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_0089: 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_0058: 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_0063: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00ac: Unknown result type (might be due to invalid IL or missing references) if (_bodies == null) { return; } for (int i = 0; i < _bodies.Length; i++) { Rigidbody val = _bodies[i]; if (!((Object)(object)val == (Object)null)) { Vector3 val2 = val.position - Origins[i]; if (((Vector3)(ref val2)).sqrMagnitude > maxDistance * maxDistance) { val.position = Origins[i] + ((Vector3)(ref val2)).normalized * maxDistance; val.velocity = Vector3.zero; val.angularVelocity = Vector3.zero; } Vector3 velocity = val.velocity; if (((Vector3)(ref velocity)).sqrMagnitude > 81f) { velocity = val.velocity; val.velocity = ((Vector3)(ref velocity)).normalized * 9f; } } } } internal void Hide() { if (_renderers == null) { return; } Renderer[] renderers = _renderers; foreach (Renderer val in renderers) { if ((Object)(object)val != (Object)null) { val.enabled = false; } } } internal void RestoreState() { //IL_0068: 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) if (_renderers != null) { for (int i = 0; i < _renderers.Length; i++) { try { if ((Object)(object)_renderers[i] != (Object)null) { _renderers[i].enabled = _enabled[i]; } } catch { } } } if (_bodies != null) { for (int j = 0; j < _bodies.Length; j++) { try { Rigidbody val = _bodies[j]; if (!((Object)(object)val == (Object)null)) { val.velocity = Vector3.zero; val.angularVelocity = Vector3.zero; val.isKinematic = _kinematic[j]; val.useGravity = _gravity[j]; val.drag = _drag[j]; } } catch { } } } _renderers = null; _enabled = null; _bodies = null; Origins = null; Generation = ((Generation == int.MaxValue) ? 1 : (Generation + 1)); } private void OnDisable() { RestoreState(); } } internal static class CorpseFeedback { private sealed class Corpse { internal EnemyAgent Enemy; internal IntPtr Identity; internal int ModelGeneration; internal int RagdollGeneration; internal float At; internal float Strength; internal float BurstAt; internal float EndAt; internal float BodySize = 1f; internal Vector3 Direction; internal Vector3 Origin; internal bool Launched; internal bool Broken; internal bool Exploded; internal int GibDataCalls; internal int GibDataSetupMisses; internal CorpseVisualLease Model; internal CorpseVisualLease Ragdoll; internal readonly List<CD_Gib> Gibs = new List<CD_Gib>(); } private static readonly List<Corpse> Active = new List<Corpse>(16); private static readonly Dictionary<IntPtr, Corpse> Hidden = new Dictionary<IntPtr, Corpse>(); private static readonly Dictionary<IntPtr, Corpse> GibOwners = new Dictionary<IntPtr, Corpse>(); private static readonly Dictionary<IntPtr, Vector3> GibOrigins = new Dictionary<IntPtr, Vector3>(); private static readonly Dictionary<IntPtr, Vector3> GibScales = new Dictionary<IntPtr, Vector3>(); private static FX_Pool _deathPool; private static Corpse _fragmentOwner; private static int _warnings; private static float _pruneAt; private static readonly CorpseSoundThrottle ExplosionSound = new CorpseSoundThrottle(); private static Vector3 _pendingSoundPosition; private static AudioClip _customExplosionClip; private static bool _customExplosionLoadAttempted; private static void Log(string message) { Plugin instance = Plugin.Instance; if (instance != null) { ((BasePlugin)instance).Log.LogInfo((object)("[CORPSE] " + message)); } } internal static void Schedule(EnemyAgent enemy, Vector3 direction, float strength) { //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0284: 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_0206: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.Enabled.Value || !Plugin.CorpseEffects.Value) { return; } if ((Object)(object)enemy == (Object)null) { Log("schedule=skipped;reason=enemy-null"); return; } foreach (Corpse item in Active) { if (item.Identity == ((Il2CppObjectBase)enemy).Pointer) { Log($"schedule=skipped;enemyId={enemy.EnemyDataID};reason=already-active"); return; } } if (Hidden.ContainsKey(((Il2CppObjectBase)enemy).Pointer)) { Log($"schedule=skipped;enemyId={enemy.EnemyDataID};reason=already-hidden"); return; } if (Active.Count >= 16) { Log($"schedule=skipped;enemyId={enemy.EnemyDataID};reason=active-cap;active={Active.Count}"); return; } if (Hidden.Count >= 256) { Log($"schedule=skipped;enemyId={enemy.EnemyDataID};reason=hidden-cap;hidden={Hidden.Count}"); return; } if (((Vector3)(ref direction)).sqrMagnitude < 0.01f) { Camera currentCamera = CameraManager.GetCurrentCamera(); direction = (((Object)(object)currentCamera != (Object)null) ? ((Component)currentCamera).transform.forward : Vector3.forward); } direction.y = 0f; if (((Vector3)(ref direction)).sqrMagnitude < 0.01f) { direction = Vector3.forward; } float num = FeedbackPolicy.Clamp(Plugin.CorpseExplosionDelay.Value, 0.65f, 1.6f, 1.15f); float volume; float num2 = MeasureSize(enemy, out volume); Active.Add(new Corpse { Identity = ((Il2CppObjectBase)enemy).Pointer, Enemy = enemy, At = Time.unscaledTime, Strength = FeedbackPolicy.Unit(strength), BodySize = num2, Direction = ((Vector3)(ref direction)).normalized, Origin = ((Component)enemy).transform.position, BurstAt = num, EndAt = num + 0.75f }); Log($"schedule=accepted;enemyId={enemy.EnemyDataID};strength={FeedbackPolicy.Unit(strength):0.##};bodyVolume={volume:0.###}m3;sizeFactor={num2:0.##};active={Active.Count}"); } internal static void Tick(float now) { //IL_079b: Unknown result type (might be due to invalid IL or missing references) //IL_07a0: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_04f1: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Unknown result type (might be due to invalid IL or missing references) //IL_0534: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_0528: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_0532: Unknown result type (might be due to invalid IL or missing references) if (now >= _pruneAt) { _pruneAt = now + 2f; foreach (Corpse item in new List<Corpse>(Hidden.Values)) { try { if ((Object)(object)item.Enemy == (Object)null || ((Agent)item.Enemy).Alive || ((Object)(object)item.Ragdoll != (Object)null && !FeedbackPolicy.IsLeaseCurrent(item.RagdollGeneration, item.Ragdoll.Generation))) { Release(item, removeHidden: true); } } catch (Exception error) { Warn(error); Release(item, removeHidden: true); } } } for (int num = Active.Count - 1; num >= 0; num--) { Corpse corpse = Active[num]; try { if ((Object)(object)corpse.Enemy == (Object)null || ((Agent)corpse.Enemy).Alive || ((Object)(object)corpse.Ragdoll != (Object)null && !FeedbackPolicy.IsLeaseCurrent(corpse.RagdollGeneration, corpse.Ragdoll.Generation))) { Release(corpse, removeHidden: true); Active.RemoveAt(num); } else { float num2 = now - corpse.At; if (!Plugin.Enabled.Value || !Plugin.CorpseEffects.Value) { Release(corpse, removeHidden: true); Active.RemoveAt(num); } else { if (!corpse.Launched && num2 >= 0.04f) { GameObject ragdollInstance = corpse.Enemy.RagdollInstance; if ((Object)(object)ragdollInstance != (Object)null) { CorpseVisualLease corpseVisualLease = Lease(ragdollInstance); if (corpseVisualLease.BodyCount > 0) { corpse.Ragdoll = corpseVisualLease; corpse.Ragdoll.Launch(corpse.Direction, corpse.Strength); corpse.RagdollGeneration = corpse.Ragdoll.Generation; corpse.Launched = true; Log($"launch=applied;enemyId={corpse.Enemy.EnemyDataID};ragdollBodies={corpseVisualLease.BodyCount};age={num2:0.00}s;mode=radial"); } else { corpseVisualLease.RestoreState(); if (!FeedbackPolicy.ShouldWaitForRagdoll(num2, corpse.BurstAt)) { corpse.Launched = true; Log($"launch=skipped;enemyId={corpse.Enemy.EnemyDataID};reason=ragdoll-has-no-rigidbody;age={num2:0.00}s"); } } } else if (!FeedbackPolicy.ShouldWaitForRagdoll(num2, corpse.BurstAt)) { corpse.Launched = true; Log($"launch=skipped;enemyId={corpse.Enemy.EnemyDataID};reason=ragdoll-instance-unavailable;age={num2:0.00}s"); } } float travel = FeedbackPolicy.Travel(corpse.Strength, Plugin.MinLaunchDistance.Value, Plugin.MaxLaunchDistance.Value, corpse.BodySize) * FeedbackPolicy.Clamp(Plugin.CorpseTravelScale.Value, 0.5f, 1.5f, 1f); corpse.Ragdoll?.Limit(FeedbackPolicy.AppliedTravel(travel)); LimitGibs(corpse); if (!corpse.Broken && num2 >= 0.12f) { corpse.Broken = true; int value = BreakLimbs(corpse); Log($"dismemberment=complete;enemyId={corpse.Enemy.EnemyDataID};limbsBroken={value};gibDataCalls={corpse.GibDataCalls};setupIdMisses={corpse.GibDataSetupMisses};gibsCaptured={corpse.Gibs.Count};attemptBudget={FeedbackPolicy.Fragments(corpse.Strength)}"); } if (!corpse.Exploded && num2 >= corpse.BurstAt) { corpse.Exploded = true; Vector3 val = (((Object)(object)corpse.Ragdoll != (Object)null) ? corpse.Ragdoll.Center : Chest(corpse.Enemy)); int num3 = FeedbackPolicy.BurstCount(corpse.BodySize, corpse.Strength); int num4 = 0; float num5 = FeedbackPolicy.BurstSpread(corpse.Strength, corpse.BodySize); for (int i = 0; i < num3; i++) { Vector3 val2 = val; if (i > 0) { float num6 = (float)i * 2.39996f; val2 += new Vector3(Mathf.Cos(num6) * num5, 0.3f + 0.25f * (float)i, Mathf.Sin(num6) * num5); } if (Explode(val2)) { num4++; } } string value2 = RequestExplosionSound(val); Log($"burst=complete;enemyId={corpse.Enemy.EnemyDataID};fx={num4}/{num3};sound={value2};ragdollBodies={corpse.Ragdoll?.BodyCount ?? 0};dismembermentStage={(corpse.Broken ? "attempted" : "not-run")};gibDataCalls={corpse.GibDataCalls};setupIdMisses={corpse.GibDataSetupMisses};gibsCaptured={corpse.Gibs.Count};sizeFactor={corpse.BodySize:0.##}"); if ((Object)(object)corpse.Enemy.MainModelGO != (Object)null) { CorpseVisualLease component = corpse.Enemy.MainModelGO.GetComponent<CorpseVisualLease>(); corpse.Model = (((Object)(object)component != (Object)null && (Object)(object)corpse.Ragdoll != (Object)null && ((Il2CppObjectBase)component).Pointer == ((Il2CppObjectBase)corpse.Ragdoll).Pointer) ? corpse.Ragdoll : Lease(corpse.Enemy.MainModelGO)); corpse.ModelGeneration = corpse.Model.Generation; corpse.Model.Hide(); } corpse.Ragdoll?.Hide(); Hidden[corpse.Identity] = corpse; } if (num2 >= corpse.EndAt) { ReleaseGibs(corpse); Active.RemoveAt(num); } } } } catch (Exception error2) { Warn(error2); Release(corpse, removeHidden: true); Active.RemoveAt(num); } } if (!Plugin.Enabled.Value || !Plugin.CorpseEffects.Value) { ExplosionSound.Reset(); _pendingSoundPosition = Vector3.zero; } else { FlushExplosionSound(now); } } private static string RequestExplosionSound(Vector3 position) { //IL_001d: 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_0012: Unknown result type (might be due to invalid IL or missing references) if (!ExplosionSound.Request(Time.unscaledTime)) { _pendingSoundPosition = position; return "coalesced"; } return PostExplosionSound(position); } private static void FlushExplosionSound(float now) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (ExplosionSound.TryFlush(now)) { Log("sound=" + PostExplosionSound(_pendingSoundPosition) + ";coalesced=true"); } } private static string PostExplosionSound(Vector3 position) { //IL_0010: 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) AudioClip val = LoadExplosionSound(); if ((Object)(object)val != (Object)null) { try { AudioSource.PlayClipAtPoint(val, position, 0.82f); return "custom"; } catch (Exception error) { Warn(error); } } try { CellSound.Post(EVENTS.ENEMYEXPLODE, position); return "game-fallback"; } catch (Exception error2) { Warn(error2); return "failed"; } } private static AudioClip LoadExplosionSound() { if (_customExplosionLoadAttempted) { return _customExplosionClip; } _customExplosionLoadAttempted = true; try { using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("KillFeed.Audio.corpse-burst.wav"); if (stream == null) { throw new InvalidOperationException("Embedded corpse burst WAV is missing."); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); byte[] array = memoryStream.ToArray(); if (array.Length < 12 || Encoding.ASCII.GetString(array, 0, 4) != "RIFF" || Encoding.ASCII.GetString(array, 8, 4) != "WAVE") { throw new InvalidOperationException("Embedded corpse burst WAV has an invalid RIFF header."); } int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = -1; int num6 = 0; int num7 = 12; while (num7 <= array.Length - 8) { string text = Encoding.ASCII.GetString(array, num7, 4); int num8 = BitConverter.ToInt32(array, num7 + 4); int num9 = num7 + 8; if (num8 < 0 || num9 > array.Length - num8) { throw new InvalidOperationException("Embedded corpse burst WAV has a malformed chunk."); } if (text == "fmt ") { if (num8 < 16) { throw new InvalidOperationException("Embedded corpse burst WAV format chunk is incomplete."); } num = BitConverter.ToUInt16(array, num9); num2 = BitConverter.ToUInt16(array, num9 + 2); num3 = BitConverter.ToInt32(array, num9 + 4); num4 = BitConverter.ToUInt16(array, num9 + 14); } else if (text == "data") { num5 = num9; num6 = num8; } long num10 = (long)num9 + (long)num8 + (num8 & 1); if (num10 > array.Length) { throw new InvalidOperationException("Embedded corpse burst WAV chunk exceeds the file length."); } num7 = (int)num10; } if (num != 1 || num2 != 1 || num3 < 8000 || num3 > 192000 || num4 != 16 || num5 < 0 || num6 <= 0 || num6 % (num2 * (num4 / 8)) != 0) { throw new InvalidOperationException("Embedded corpse burst WAV must be mono PCM16 with a valid sample rate."); } int num11 = num6 / 2; float[] array2 = new float[num11]; for (int i = 0; i < num11; i++) { int num12 = num5 + i * 2; short num13 = (short)(array[num12] | (array[num12 + 1] << 8)); array2[i] = (float)num13 / 32768f; } AudioClip val = AudioClip.Create("KillFeed_CorpseBurst", num11, num2, num3, false); if ((Object)(object)val == (Object)null || !val.SetData(new Il2CppStructArray<float>(array2), 0)) { throw new InvalidOperationException("Unity could not load the embedded corpse burst samples."); } _customExplosionClip = val; } catch (Exception error) { Warn(error); } return _customExplosionClip; } private static CorpseVisualLease Lease(GameObject obj) { CorpseVisualLease corpseVisualLease = obj.GetComponent<CorpseVisualLease>(); if ((Object)(object)corpseVisualLease == (Object)null) { corpseVisualLease = obj.AddComponent<CorpseVisualLease>(); } corpseVisualLease.Capture(); return corpseVisualLease; } private static Vector3 Chest(EnemyAgent enemy) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) EnemyModelRefs modelRef = enemy.ModelRef; Transform val = ((modelRef != null) ? modelRef.m_chestBone : null); if (!((Object)(object)val != (Object)null)) { return ((Component)enemy).transform.position + Vector3.up; } return val.position; } private static float MeasureSize(EnemyAgent enemy, out float volume) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) volume = 0f; try { BurnableSkinnedMesh componentInChildren = ((Component)enemy).GetComponentInChildren<BurnableSkinnedMesh>(true); SkinnedMeshRenderer val = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.m_skinnedMesh : null); if ((Object)(object)val != (Object)null) { Bounds bounds = ((Renderer)val).bounds; Vector3 size = ((Bounds)(ref bounds)).size; volume = Math.Abs(size.x * size.y * size.z); } } catch (Exception error) { Warn(error); } return FeedbackPolicy.SizeFactor(volume); } private static int ActivateGibData(CD_CharacterDestructionCollider destruction, byte destructionId, Vector3 position, Vector3 force, int maxCalls, out bool setupMatched, out int setupMatches, out int dataEntries) { //IL_00ac: 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) setupMatched = false; setupMatches = 0; dataEntries = 0; if ((Object)(object)destruction == (Object)null || maxCalls <= 0) { return 0; } List<CD_DestructionSetup> allowedDestructions = destruction.m_allowedDestructions; if (allowedDestructions == null) { return 0; } int num = 0; for (int i = 0; i < allowedDestructions.Count; i++) { if (num >= maxCalls) { break; } CD_DestructionSetup val = allowedDestructions[i]; if ((Object)(object)val == (Object)null || val.m_id != destructionId) { continue; } setupMatched = true; setupMatches++; Il2CppReferenceArray<CD_GibData> gibDatas = val.m_gibDatas; if (gibDatas == null || ((Il2CppArrayBase<CD_GibData>)(object)gibDatas).Length == 0) { continue; } dataEntries += ((Il2CppArrayBase<CD_GibData>)(object)gibDatas).Length; for (int j = 0; j < ((Il2CppArrayBase<CD_GibData>)(object)gibDatas).Length; j++) { if (num >= maxCalls) { break; } CD_GibData val2 = ((Il2CppArrayBase<CD_GibData>)(object)gibDatas)[j]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.m_gibPrefab == (Object)null)) { try { val2.Activate(position, force); num++; } catch (Exception error) { Warn(error); } } } } return num; } private static int BreakLimbs(Corpse item) { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: 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: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: 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_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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) Dam_EnemyDamageBase damage = item.Enemy.Damage; Il2CppReferenceArray<Dam_EnemyDamageLimb> val = ((damage != null) ? damage.DamageLimbs : null); if (val == null) { return 0; } int num = FeedbackPolicy.Fragments(item.Strength); int num2 = 0; _fragmentOwner = item; try { int num3 = ((Il2CppArrayBase<Dam_EnemyDamageLimb>)(object)val).Length - 1; Vector3 val4 = default(Vector3); sDestructionEventData val6 = default(sDestructionEventData); while (num3 >= 0 && num2 < num) { Dam_EnemyDamageLimb val2 = ((Il2CppArrayBase<Dam_EnemyDamageLimb>)(object)val)[num3]; CD_CharacterDestructionCollider val3 = ((val2 != null) ? val2.m_destruction : null); if (!((Object)(object)val2 == (Object)null) && !val2.IsDestroyed && !((Object)(object)val3 == (Object)null) && val3.HasDestruction()) { float num4 = (float)(num2 + 1) * 2.39996f; ((Vector3)(ref val4))..ctor(Mathf.Cos(num4), 0.65f, Mathf.Sin(num4)); Vector3 val5 = ((Vector3)(ref val4)).normalized * (1.8f + 3f * item.Strength); if (val3.TryDoDestruction((ImpactDirection)1, item.Direction, Vector3.zero, val5, (CD_DestructionSeverity)((item.Strength > 0.45f) ? 3 : 2), false, ref val6)) { Vector3 position = ((Component)val2).transform.position; int value = 0; try { value = val3.m_allowedDestructions?.Count ?? 0; } catch (Exception error) { Warn(error); } CD_CharacterDestruction characterDestruction = val3.m_characterDestruction; bool value2 = false; if ((Object)(object)characterDestruction != (Object)null) { try { characterDestruction.ApplyDestruction((Agent)(object)item.Enemy, val6); value2 = true; } catch (Exception error2) { Warn(error2); } } if (item.GibDataCalls < 24) { bool setupMatched; int setupMatches; int dataEntries; int num5 = ActivateGibData(val3, val6.m_destructionID, position, ((Vector3)(ref val4)).normalized * FeedbackPolicy.GibLaunchSpeed(item.Strength), 24 - item.GibDataCalls, out setupMatched, out setupMatches, out dataEntries); item.GibDataCalls += num5; if (!setupMatched) { item.GibDataSetupMisses++; } Log($"gibdata=resolved;enemyId={item.Enemy.EnemyDataID};destructionId={val6.m_destructionID};setupMatched={setupMatched};setupMatches={setupMatches};entries={dataEntries};activateCalls={num5}"); } val2.DestroyLimb(val6); FX_Manager.PlayEffect(true, (FX_GroupName)4, position, Quaternion.identity, false); Log($"destruction=local;enemyId={item.Enemy.EnemyDataID};limb={num3};destructionId={val6.m_destructionID};meshDestroyed={value2};setups={value};gibs={item.Gibs.Count}"); num2++; } } num3--; } } finally { _fragmentOwner = null; } return num2; } internal static void GibReused(CD_Gib gib) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gib == (Object)null) { return; } if (GibOwners.TryGetValue(((Il2CppObjectBase)gib).Pointer, out var value)) { for (int num = value.Gibs.Count - 1; num >= 0; num--) { if (((Il2CppObjectBase)value.Gibs[num]).Pointer == ((Il2CppObjectBase)gib).Pointer) { value.Gibs.RemoveAt(num); } } } GibOwners.Remove(((Il2CppObjectBase)gib).Pointer); GibOrigins.Remove(((Il2CppObjectBase)gib).Pointer); if (GibScales.TryGetValue(((Il2CppObjectBase)gib).Pointer, out var value2)) { Rigidbody rigidbody = gib.m_rigidbody; if ((Object)(object)rigidbody != (Object)null && (Object)(object)((Component)rigidbody).transform != (Object)null) { ((Component)rigidbody).transform.localScale = value2; } GibScales.Remove(((Il2CppObjectBase)gib).Pointer); } } internal static void CaptureGib(CD_Gib gib) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: 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_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: 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_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (_fragmentOwner == null || (Object)(object)gib == (Object)null || _fragmentOwner.Gibs.Count >= 24) { return; } foreach (CD_Gib gib2 in _fragmentOwner.Gibs) { if (((Il2CppObjectBase)gib2).Pointer == ((Il2CppObjectBase)gib).Pointer) { return; } } _fragmentOwner.Gibs.Add(gib); GibOwners[((Il2CppObjectBase)gib).Pointer] = _fragmentOwner; Rigidbody rigidbody = gib.m_rigidbody; if (!((Object)(object)rigidbody == (Object)null)) { GibOrigins[((Il2CppObjectBase)gib).Pointer] = rigidbody.position; Transform transform = ((Component)rigidbody).transform; if ((Object)(object)transform != (Object)null && !GibScales.ContainsKey(((Il2CppObjectBase)gib).Pointer)) { GibScales[((Il2CppObjectBase)gib).Pointer] = transform.localScale; transform.localScale *= FeedbackPolicy.GibScale(_fragmentOwner.BodySize); } float num = (float)_fragmentOwner.Gibs.Count * 2.39996f; Vector3 val = new Vector3(Mathf.Cos(num), 0.7f, Mathf.Sin(num)); Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val2 = rigidbody.position - _fragmentOwner.Origin; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f) { val2.y = Mathf.Max(val2.y, 0.25f); val = ((Vector3)(ref val2)).normalized * 0.7f + normalized * 0.3f; normalized = ((Vector3)(ref val)).normalized; } rigidbody.velocity = normalized * FeedbackPolicy.GibLaunchSpeed(_fragmentOwner.Strength); } } private static void LimitGibs(Corpse owner) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_0097: 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_00ae: Unknown result type (might be due to invalid IL or missing references) float num = FeedbackPolicy.FragmentRadius(owner.Strength, owner.BodySize); foreach (CD_Gib gib in owner.Gibs) { if ((Object)(object)gib == (Object)null || !GibOwners.TryGetValue(((Il2CppObjectBase)gib).Pointer, out var value) || value != owner) { continue; } Rigidbody rigidbody = gib.m_rigidbody; if (!((Object)(object)rigidbody == (Object)null) && GibOrigins.TryGetValue(((Il2CppObjectBase)gib).Pointer, out var value2)) { Vector3 val = rigidbody.position - value2; if (((Vector3)(ref val)).sqrMagnitude > num * num) { rigidbody.position = value2 + ((Vector3)(ref val)).normalized * num; rigidbody.velocity = Vector3.zero; } } } } private static bool Explode(Vector3 position) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_deathPool == (Object)null) { GameObject val = Resources.Load<GameObject>("FXC_FlyerDeath"); if ((Object)(object)val == (Object)null) { Warn(new InvalidOperationException("FXC_FlyerDeath resource unavailable")); return false; } _deathPool = FX_Manager.CreatePool(val); } if ((Object)(object)_deathPool == (Object)null) { Warn(new InvalidOperationException("FXC_FlyerDeath pool unavailable")); return false; } FX_EffectBase_Poolable val2 = _deathPool.AquireEffect(); if ((Object)(object)val2 == (Object)null) { Warn(new InvalidOperationException("FXC_FlyerDeath pool returned no effect")); return false; } ((FX_EffectBase)val2).Play((FX_Trigger)null, position, Quaternion.identity); return true; } private static void ReleaseGibs(Corpse item) { CD_Gib[] array = item.Gibs.ToArray(); foreach (CD_Gib val in array) { try { if ((Object)(object)val != (Object)null && GibOwners.TryGetValue(((Il2CppObjectBase)val).Pointer, out var value) && value == item) { GibReused(val); val.Deactivate(); } } catch (Exception error) { Warn(error); } } item.Gibs.Clear(); } private static void Release(Corpse item, bool removeHidden) { try { ReleaseGibs(item); } catch (Exception error) { Warn(error); } try { if ((Object)(object)item.Model != (Object)null && FeedbackPolicy.IsLeaseCurrent(item.ModelGeneration, item.Model.Generation)) { item.Model.RestoreState(); } } catch (Exception error2) { Warn(error2); } try { if ((Object)(object)item.Ragdoll != (Object)null && FeedbackPolicy.IsLeaseCurrent(item.RagdollGeneration, item.Ragdoll.Generation)) { item.Ragdoll.RestoreState(); } } catch (Exception error3) { Warn(error3); } if (removeHidden) { Hidden.Remove(item.Identity); } } internal static void Restore(EnemyAgent enemy) { if ((Object)(object)enemy == (Object)null) { return; } if (Hidden.TryGetValue(((Il2CppObjectBase)enemy).Pointer, out var value)) { Release(value, removeHidden: true); } for (int num = Active.Count - 1; num >= 0; num--) { if (Active[num].Identity == ((Il2CppObjectBase)enemy).Pointer) { Release(Active[num], removeHidden: true); Active.RemoveAt(num); } } } internal static void Reset() { //IL_00b3: 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) foreach (Corpse item in Active) { Release(item, removeHidden: false); } foreach (Corpse value in Hidden.Values) { Release(value, removeHidden: false); } Active.Clear(); Hidden.Clear(); GibOwners.Clear(); GibOrigins.Clear(); GibScales.Clear(); _deathPool = null; _fragmentOwner = null; ExplosionSound.Reset(); _pendingSoundPosition = Vector3.zero; } private static void Warn(Exception error) { if (_warnings++ < 6) { Plugin instance = Plugin.Instance; if (instance != null) { ((BasePlugin)instance).Log.LogWarning((object)("[CORPSE] " + error.Message)); } } } } [HarmonyPatch(typeof(CD_Gib), "Activate", new Type[] { typeof(Vector3), typeof(Vector3) })] internal static class GibActivatePatch { [HarmonyPrefix] private static void Prefix(CD_Gib __instance) { KillTracker.GuardAction(delegate { CorpseFeedback.GibReused(__instance); }); } [HarmonyPostfix] private static void Postfix(CD_Gib __instance) { KillTracker.GuardAction(delegate { CorpseFeedback.CaptureGib(__instance); }); } } [HarmonyPatch(typeof(CD_Gib), "Activate", new Type[] { typeof(Vector3) })] internal static class GibActivateSimplePatch { [HarmonyPrefix] private static void Prefix(CD_Gib __instance) { KillTracker.GuardAction(delegate { CorpseFeedback.GibReused(__instance); }); } [HarmonyPostfix] private static void Postfix(CD_Gib __instance) { KillTracker.GuardAction(delegate { CorpseFeedback.CaptureGib(__instance); }); } } [HarmonyPatch(typeof(CD_Gib), "Deactivate")] internal static class GibDeactivatePatch { [HarmonyPrefix] private static void Prefix(CD_Gib __instance) { KillTracker.GuardAction(delegate { CorpseFeedback.GibReused(__instance); }); } } internal static class DamageNumbers { private sealed class Number { internal Vector3 World; internal float At; internal float Side; internal HitKind Kind; internal string Text; internal bool Preview; } private static readonly List<Number> Active = new List<Number>(64); private static int _sequence; private static GUIStyle _style; internal static void Add(Vector3 world, float damage, HitKind kind, bool preview = false) { //IL_0030: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ShowDamageNumbers == null || !Plugin.ShowDamageNumbers.Value || !Plugin.Enabled.Value) { return; } string text = FeedbackPolicy.DamageText(damage, kind); if (text.Length != 0 && KillPolicy.IsFinite(world.x) && KillPolicy.IsFinite(world.y) && KillPolicy.IsFinite(world.z)) { while (Active.Count >= 64) { Active.RemoveAt(0); } int num = _sequence++; Active.Add(new Number { World = world, At = Time.unscaledTime, Side = (float)(num % 7 - 3) * 11f, Kind = kind, Text = text, Preview = preview }); } } internal static void Tick(float now) { float num = ((Plugin.DamageNumberLifetime != null) ? FeedbackPolicy.Clamp(Plugin.DamageNumberLifetime.Value, 0.35f, 1.2f, 0.72f) : 0.72f); for (int num2 = Active.Count - 1; num2 >= 0; num2--) { if (now - Active[num2].At >= num) { Active.RemoveAt(num2); } } } internal static void Draw() { //IL_0360: 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_0096: 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_0035: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0164: 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_0187: 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) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0309: 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) //IL_0310: 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_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0302: 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_02ac: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ShowDamageNumbers.Value || Active.Count == 0) { return; } Camera currentCamera = CameraManager.GetCurrentCamera(); if (_style == null) { _style = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontStyle = (FontStyle)1, clipping = (TextClipping)0, richText = false }; } float num = Mathf.Clamp((float)Screen.height / 1080f, 0.75f, 1.6f); float num2 = FeedbackPolicy.Clamp(Plugin.DamageNumberLifetime.Value, 0.35f, 1.2f, 0.72f); Color color = GUI.color; try { Vector3 val = default(Vector3); Rect val2 = default(Rect); foreach (Number item in Active) { float num3 = Time.unscaledTime - item.At; if (num3 < 0f || num3 >= num2) { continue; } if (item.Preview) { ((Vector3)(ref val))..ctor((float)Screen.width * 0.5f + item.World.x * num, (float)Screen.height * 0.5f, 1f); } else { if ((Object)(object)currentCamera == (Object)null) { continue; } val = currentCamera.WorldToScreenPoint(item.World); if (val.z <= 0.05f) { continue; } val.y = (float)Screen.height - val.y; } if (val.x < 0f || val.x > (float)Screen.width || val.y < 0f || val.y > (float)Screen.height) { continue; } float num4 = FeedbackPolicy.Clamp(Plugin.DamageNumberSize.Value, 16f, 42f, 27f) * FeedbackPolicy.NumberScale(num3, item.Kind) * num; _style.fontSize = Mathf.RoundToInt(num4); float num5 = val.x + item.Side * (0.35f + num3 * 1.7f) * num; float num6 = val.y + (-95f * num3 + 105f * num3 * num3) * num; float num7 = FeedbackPolicy.Alpha(num3, num2); ((Rect)(ref val2))..ctor(num5 - 100f * num, num6 - num4, 200f * num, num4 * 2f); GUI.color = new Color(0.035f, 0.04f, 0.045f, num7); float num8 = 1.6f * num; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (i != 0 || j != 0) { GUI.Label(new Rect(((Rect)(ref val2)).x + (float)i * num8, ((Rect)(ref val2)).y + (float)j * num8, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), item.Text, _style); } } } Color val3 = (Color)((item.Kind == HitKind.Weakspot) ? KillHud.Accent : ((item.Kind == HitKind.Armor) ? new Color(0.65f, 0.72f, 0.77f) : KillHud.Ink)); GUI.color = new Color(val3.r, val3.g, val3.b, num7); GUI.Label(val2, item.Text, _style); } } finally { GUI.color = color; } } internal static void Preview() { //IL_000f: 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_0040: Unknown result type (might be due to invalid IL or missing references) Add(new Vector3(-90f, 0f, 0f), 6.75f, HitKind.Armor, preview: true); Add(Vector3.zero, 24.35f, HitKind.Normal, preview: true); Add(new Vector3(90f, 0f, 0f), 81.2f, HitKind.Weakspot, preview: true); } internal static void Clear() { Active.Clear(); } } internal static class EnemyNames { private sealed class NameFile { public string Source { get; set; } public bool UseHikariaDefaults { get; set; } = true; public List<NameGroup> Names { get; set; } public List<EnemyNameRule> Rules { get; set; } = new List<EnemyNameRule>(); } private sealed class NameGroup { public List<uint> IDs { get; set; } public string Name { get; set; } } private static List<EnemyNameRule> _rules = new List<EnemyNameRule>(); private static Dictionary<uint, string> _defaults = new Dictionary<uint, string>(); private static NameFile _bundled; private static DateTime _stamp; private static float _checkAt; private static bool _useDefaults = true; private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true, WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; internal static string FilePath => Path.Combine(Paths.ConfigPath, "HawChow.KillFeed.EnemyNames.json"); internal static void Initialize() { try { using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("KillFeed.EnemyNames.defaults.json"); if (stream == null) { throw new InvalidOperationException("Bundled Hikaria name table missing."); } _bundled = JsonSerializer.Deserialize<NameFile>(stream, JsonOptions); _defaults = BuildDefaults(_bundled.Names); if (!File.Exists(FilePath)) { File.WriteAllText(FilePath, JsonSerializer.Serialize(_bundled, JsonOptions)); } Reload(); } catch (Exception ex) { ((BasePlugin)Plugin.Instance).Log.LogWarning((object)("[NAMES] initialization failed: " + ex.Message)); } } internal static void Tick(float now) { if (now < _checkAt) { return; } _checkAt = now + 2f; try { if (File.GetLastWriteTimeUtc(FilePath) != _stamp) { Reload(); } } catch (Exception ex) { ((BasePlugin)Plugin.Instance).Log.LogWarning((object)("[NAMES] file check failed: " + ex.Message)); } } internal static string Resolve(uint id, string raw) { return EnemyNamePolicy.Resolve(id, raw, _rules, _useDefaults ? _defaults : null); } private static void Reload() { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown try { _stamp = File.GetLastWriteTimeUtc(FilePath); FileInfo fileInfo = new FileInfo(FilePath); if (!fileInfo.Exists || fileInfo.Length > 262144) { throw new FormatException("Name file missing or exceeds 256 KiB."); } NameFile nameFile = JsonSerializer.Deserialize<NameFile>(File.ReadAllText(FilePath), JsonOptions); if (nameFile?.Rules == null || nameFile.Rules.Count > 1024) { throw new FormatException("Rules must be an array with at most 1024 entries."); } foreach (EnemyNameRule rule in nameFile.Rules) { if (!EnemyNamePolicy.Valid(rule)) { throw new FormatException("Rules need RawName and a single-line DisplayName up to 96 characters."); } } Dictionary<uint, string> defaults = BuildDefaults(nameFile.Names ?? _bundled?.Names ?? new List<NameGroup>()); _rules = nameFile.Rules; _defaults = defaults; _useDefaults = nameFile.UseHikariaDefaults; ManualLogSource log = ((BasePlugin)Plugin.Instance).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(103, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[NAMES] defaults="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(_defaults.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";enabled="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(_useDefaults); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";overrides="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(_rules.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";file="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(FilePath); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";custom-rundown IDs may override defaults by exact raw name."); } log.LogInfo(val); } catch (Exception ex) { ((BasePlugin)Plugin.Instance).Log.LogWarning((object)("[NAMES] keeping previous valid mappings: " + ex.Message)); } } private static Dictionary<uint, string> BuildDefaults(List<NameGroup> groups) { if (groups == null || groups.Count > 1024) { throw new FormatException("Invalid default name groups."); } Dictionary<uint, string> dictionary = new Dictionary<uint, string>(); foreach (NameGroup group in groups) { if (group.IDs == null || group.IDs.Count > 1024 || string.IsNullOrWhiteSpace(group.Name) || group.Name.Length > 96 || group.Name.Contains('\n') || group.Name.Contains('\r')) { throw new FormatException("Invalid name group."); } foreach (uint iD in group.IDs) { if (iD != 0) { dictionary[iD] = group.Name; } } } if (dictionary.Count > 4096) { throw new FormatException("Default map exceeds 4096 IDs."); } return dictionary; } } internal enum HitKind { Normal, Armor, Weakspot } internal static class FeedbackPolicy { internal const float BurstWindow = 0.65f; internal const float NumberLifetime = 0.72f; internal const float CorpseBurstDelay = 1.15f; internal const float CorpseSoundInterval = 0.12f; internal const float CorpseCleanupDelay = 1.9f; internal const int MaxNumbers = 64; internal const int MaxCorpses = 16; internal const float SizeBaselineVolume = 1.4f; internal const float SizeFactorMin = 0.7f; internal const float SizeFactorMax = 2.4f; internal const float DefaultPanelOpacity = 0f; internal const float DefaultMinDistance = 3.8f; internal const float DefaultMaxDistance = 8.5f; internal const float AbsoluteDistanceCeiling = 40f; internal static float Clamp(float value, float min, float max, float fallback) { if (KillPolicy.IsFinite(value)) { return Math.Max(min, Math.Min(max, value)); } return fallback; } internal static bool IsLeaseCurrent(int captured, int current) { if (captured > 0) { return captured == current; } return false; } internal static float Unit(float value) { return Clamp(value, 0f, 1f, 0f); } internal static float Strength(float burstDamage, float window = 0.65f) { window = Clamp(window, 0.2f, 1.5f, 0.65f); float num = Math.Max(0f, Clamp(burstDamage, 0f, 100000f, 0f)) / window; return Unit((float)(Math.Log(1f + num / 35f) / Math.Log(23.85714340209961))); } internal static float SizeFactor(float volume) { if (KillPolicy.IsFinite(volume) && !(volume <= 0f)) { return Clamp((float)Math.Pow(volume / 1.4f, 0.3333333432674408), 0.7f, 2.4f, 1f); } return 1f; } private static float BodySize(float sizeFactor) { return Clamp(sizeFactor, 0.7f, 2.4f, 1f); } internal static float PanelAlpha(float opacity) { return Clamp(opacity, 0f, 0.9f, 0f); } internal static float RuleAlpha(float panelAlpha) { return Clamp(panelAlpha * 0.55f, 0.05f, 0.35f, 0.22f); } internal static float TravelBias(float sizeFactor) { return 0.75f + 0.25f * BodySize(sizeFactor); } internal static float LaunchBudget(float strength, float minDistance, float maxDistance) { float num = Clamp(minDistance, 0.5f, 20f, 3.8f); float num2 = Clamp(maxDistance, num, 30f, Math.Max(num, 8.5f)); return num + (num2 - num) * Unit(strength); } internal static float AppliedTravel(float travel) { return Clamp(travel, 0.5f, 40f, 3.8f); } internal static float GibScale(float sizeFactor) { return BodySize(sizeFactor); } internal static float GibScatter(float sizeFactor) { return 0.6f + 0.4f * BodySize(sizeFactor); } internal static int BurstCount(float sizeFactor, float strength = 0f) { float num = Unit((BodySize(sizeFactor) - 0.7f) / 1.7f); return 3 + (int)Math.Round(num * 2f, MidpointRounding.AwayFromZero) + (int)Math.Round(Unit(strength) * 2f, MidpointRounding.AwayFromZero); } internal static float BurstSpread(float strength, float sizeFactor) { return 0.8f * GibScatter(sizeFactor) * (0.8f + 0.4f * Unit(strength)); } internal static float GibLaunchSpeed(float strength) { return 5.5f + 6.5f * Unit(strength); } internal static bool ShouldWaitForRagdoll(float age, float burstAt) { if (KillPolicy.IsFinite(age) && KillPolicy.IsFinite(burstAt)) { return age < Math.Max(0f, burstAt); } return false; } internal static float Travel(float strength) { return LaunchBudget(strength, 3.8f, 8.5f); } internal static float Travel(float strength, float sizeFactor) { return Travel(strength) * TravelBias(sizeFactor); } internal static float Travel(float strength, float minDistance, float maxDistance, float sizeFactor) { return LaunchBudget(strength, minDistance, maxDistance) * TravelBias(sizeFactor); } internal static float LaunchSpeed(float strength) { return 4.2f + 4.4f * Unit(strength); } internal static int Fragments(float strength) { return 2 + (int)Math.Floor(4f * Unit(strength)); } internal static float FragmentRadius(float strength) { return 0.65f + 1.35f * Unit(strength); } internal static float FragmentRadius(float strength, float sizeFactor) { return FragmentRadius(strength) * GibScatter(sizeFactor); } internal static string DamageText(float value, HitKind kind) { if (!KillPolicy.IsFinite(value) || value < 0f) { return string.Empty; } string text = ((value > 0f && value < 0.01f) ? value.ToString("0.####", CultureInfo.InvariantCulture) : value.ToString("0.##", CultureInfo.InvariantCulture)); return kind switch { HitKind.Armor => "[" + text + "]", HitKind.Weakspot => text + "!", _ => text, }; } internal static float NumberScale(float age, HitKind kind) { float num = Unit(age / 0.14f); float num2 = (float)Math.Sin((double)num * Math.PI) * (1f - num); return kind switch { HitKind.Armor => 0.82f, HitKind.Weakspot => 1.18f, _ => 1f, } * (1f + 0.28f * num2); } internal static float Alpha(float age, float lifetime) { return Unit((lifetime - age) / 0.22f); } internal static float CardWidth(float iconWidth, float textWidth, float scale, float maximumWidth) { float val = Clamp(maximumWidth, 0f, 10000f, 0f); float val2 = Math.Max(0f, iconWidth) + 30f * Clamp(scale, 0.5f, 2f, 1f) + Math.Max(0f, Clamp(textWidth, 0f, 10000f, 0f)); return Math.Max(0f, Math.Min(val, val2)); } internal static float CenteredCardX(float screenWidth, float cardWidth, float offset, float margin = 12f) { float num = Clamp(screenWidth, 1f, 100000f, 1f); float num2 = Clamp(margin, 0f, num * 0.5f, 0f); float num3 = Clamp(cardWidth, 0f, Math.Max(0f, num - 2f * num2), Math.Max(0f, num - 2f * num2)); float num4 = (num - num3) * 0.5f; return Clamp(num4 + offset, num2, Math.Max(num2, num - num3 - num2), num4); } internal static string CardDetail(KillCard card, bool distance, bool health) { string text = (distance ? (card.DistanceText + " / ") : string.Empty); if (health) { text = text + card.HealthText + " / "; } return text + card.EnemyName; } } internal sealed class CorpseSoundThrottle { private float _nextAllowedAt; private bool _pending; internal bool HasPending => _pending; internal bool Request(float now) { if (!KillPolicy.IsFinite(now)) { return false; } if (_pending || now < _nextAllowedAt) { _pending = true; return false; } _pending = false; _nextAllowedAt = now + 0.12f; return true; } internal bool TryFlush(float now) { if (!_pending || !KillPolicy.IsFinite(now) || now < _nextAllowedAt) { return false; } _pending = false; _nextAllowedAt = now + 0.12f; return true; } internal void Reset() { _nextAllowedAt = 0f; _pending = false; } } internal sealed class BurstHistory { private readonly Dictionary<long, Queue<(float Time, float Damage)>> _entries = new Dictionary<long, Queue<(float, float)>>(); internal void Add(long id, float now, float damage) { if (id == 0L || !KillPolicy.IsFinite(now) || !KillPolicy.IsFinite(damage) || damage <= 0f) { return; } if (!_entries.TryGetValue(id, out Queue<(float, float)> value)) { if (_entries.Count >= 256) { Prune(now); } if (_entries.Count >= 256) { return; } value = (_entries[id] = new Queue<(float, float)>()); } while (value.Count > 0 && now - value.Peek().Item1 > 0.65f) { value.Dequeue(); } if (value.Count >= 96) { value.Dequeue(); } value.Enqueue((now, damage)); } internal float Sum(long id, float now) { if (!_entries.TryGetValue(id, out Queue<(float, float)> value)) { return 0f; } while (value.Count > 0 && now - value.Peek().Item1 > 0.65f) { value.Dequeue(); } float num = 0f; foreach (var item in value) { num += item.Item2; } return num; } internal void Prune(float now) { List<long> list = new List<long>(); foreach (KeyValuePair<long, Queue<(float, float)>> entry in _entries) { Queue<(float, float)> value = entry.Value; while (value.Count > 0 && now - value.Peek().Item1 > 0.65f) { value.Dequeue(); } if (value.Count == 0) { list.Add(entry.Key); } } foreach (long item in list) { _entries.Remove(item); } } internal void Remove(long id) { _entries.Remove(id); } internal void Clear() { _entries.Clear(); } } public sealed class EnemyNameRule { public uint DataBlockId { get; set; } public string RawName { get; set; } = string.Empty; public string DisplayName { get; set; } = string.Empty; } internal static class EnemyNamePolicy { internal static string Resolve(uint id, string rawName, IReadOnlyList<EnemyNameRule> rules, IReadOnlyDictionary<uint, string> defaults = null) { rawName = (string.IsNullOrWhiteSpace(rawName) ? "Unknown" : rawName); if (rules == null) { rules = Array.Empty<EnemyNameRule>(); } foreach (EnemyNameRule rule in rules) { if (Valid(rule) && rule.DataBlockId == id && rule.DataBlockId != 0 && string.Equals(rule.RawName, rawName, StringComparison.Ordinal)) { return rule.DisplayName; } } foreach (EnemyNameRule rule2 in rules) { if (Valid(rule2) && rule2.DataBlockId == 0 && string.Equals(rule2.RawName, rawName, StringComparison.Ordinal)) { return rule2.DisplayName; } } if (defaults == null || !defaults.TryGetValue(id, out var value) || string.IsNullOrWhiteSpace(value)) { return rawName; } return value; } internal static bool Valid(EnemyNameRule rule) { if (rule != null && !string.IsNullOrWhiteSpace(rule.RawName) && !string.IsNullOrWhiteSpace(rule.DisplayName) && rule.RawName.Length <= 256 && rule.DisplayName.Length <= 96 && !rule.DisplayName.Contains('\n')) { return !rule.DisplayName.Contains('\r'); } return false; } } public sealed class KillHud : MonoBehaviour { internal static readonly Color Ink = new Color(0.91f, 0.925f, 0.92f); internal static readonly Color Accent = new Color(0.9f, 0.67f, 0.34f); private Texture2D _normalIcon; private Texture2D _weakIcon; private GUIStyle _titleStyle; private GUIStyle _detailStyle; private bool _visible = true; private bool _triedIcons; private int _warnings; private int _layoutLogs; internal static KillHud Instance; public KillHud(IntPtr pointer) : base(pointer) { } private void Update() { //IL_0029: 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_0035: 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) try { float unscaledTime = Time.unscaledTime; EnemyNames.Tick(unscaledTime); DamageNumbers.Tick(unscaledTime); CorpseFeedback.Tick(unscaledTime); if (Plugin.Enabled.Value) { if ((int)Plugin.ToggleKey.Value != 0 && Input.GetKeyDown(Plugin.ToggleKey.Value)) { _visible = !_visible; } if ((int)Plugin.PreviewKey.Value != 0 && Input.GetKeyDown(Plugin.PreviewKey.Value)) { KillTracker.AddPreview(weakspot: false); KillTracker.AddPreview(weakspot: true); DamageNumbers.Preview(); } } } catch (Exception ex) { Warn("update", ex.Message); } } private void OnGUI() { //IL_02f6: 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_0026: Invalid comparison between Unknown and I4 //IL_0029: 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_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown if (!_visible || Plugin.Enabled == null || !Plugin.Enabled.Value || (int)Event.current.type != 7) { return; } Color color = GUI.color; try { EnsureStyles(); EnsureIcons(); DamageNumbers.Draw(); VisibleKillCard[] array = KillTracker.Snapshot(Time.unscaledTime); float num = Mathf.Clamp((float)Screen.height / 1080f, 0.75f, 1.6f); float num2 = FeedbackPolicy.Clamp(Plugin.IconSize.Value, 26f, 76f, 46f) * num; float num3 = Mathf.Max(50f * num, num2 + 10f * num); float maxWidth = Mathf.Max(0f, Mathf.Min((float)Screen.width - 32f, 430f * num)); float num4 = Mathf.Clamp((float)Screen.height * 0.78f + Plugin.VerticalOffset.Value, num3 * (float)array.Length, (float)Screen.height - num3 - 12f); bool flag = default(bool); for (int i = 0; i < array.Length; i++) { float num5 = Mathf.Max(0f, Time.unscaledTime - array[i].Card.CreatedAt); float num6 = Mathf.Pow(1f - Mathf.Clamp01(num5 / 0.16f), 3f); float num7 = num4 - (float)(array.Length - 1 - i) * (num3 + 5f * num) + num6 * 7f * num; float num8 = MeasureCardWidth(array[i], num2, num, maxWidth); float num9 = FeedbackPolicy.CenteredCardX(Screen.width, num8, Plugin.HorizontalOffset.Value); if (_layoutLogs++ < 8) { Plugin instance = Plugin.Instance; if (instance != null) { ManualLogSource log = ((BasePlugin)instance).Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(65, 7, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[HUD] card layout enemy="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(array[i].Card.EnemyName); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";x="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num9, "0.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";width="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num8, "0.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";center="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num9 + num8 * 0.5f, "0.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";screenCenter="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>((float)Screen.width * 0.5f, "0.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";screen="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Screen.width); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("x"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Screen.height); } log.LogInfo(val); } } DrawCard(array[i], new Rect(num9, num7, num8, num3), num2, num); } } catch (Exception ex) { Warn("draw", ex.Message); } finally { GUI.color = color; } } private float MeasureCardWidth(VisibleKillCard visible, float iconSize, float scale, float maxWidth) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //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_00b1: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) KillCard card = visible.Card; bool flag = card.Kind == KillKind.Weakspot; string text = ((!KillPolicy.IsChinese(Plugin.Language.Value)) ? (flag ? "WEAKPOINT KILL" : "KILL CONFIRMED") : (flag ? "弱点击杀" : "击杀确认")); string text2 = FeedbackPolicy.CardDetail(card, Plugin.ShowDistance.Value, Plugin.ShowEnemyHealth.Value); _titleStyle.fontSize = Mathf.RoundToInt(13f * scale); _detailStyle.fontSize = Mathf.RoundToInt(12f * scale); float textWidth = Mathf.Max(_titleStyle.CalcSize(new GUIContent(text)).x, _detailStyle.CalcSize(new GUIContent(text2)).x); return FeedbackPolicy.CardWidth(iconSize, textWidth, scale, maxWidth); } private void DrawCard(VisibleKillCard visible, Rect rect, float iconSize, float scale) { //IL_0048: 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_0074: 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_00ae: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Expected O, but got Unknown //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: 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) KillCard card = visible.Card; bool flag = card.Kind == KillKind.Weakspot; float alpha = visible.Alpha; float num = FeedbackPolicy.PanelAlpha((Plugin.BackgroundOpacity != null) ? Plugin.BackgroundOpacity.Value : 0f); GUI.color = new Color(0.055f, 0.064f, 0.068f, num * alpha); GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture); GUI.color = new Color(0.28f, 0.31f, 0.32f, FeedbackPolicy.RuleAlpha(num) * alpha); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, scale), (Texture)(object)Texture2D.whiteTexture); Color val = (flag ? Accent : Ink); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref rect)).x + 8f * scale, ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - iconSize) * 0.5f, iconSize, iconSize); GUI.color = new Color(1f, 1f, 1f, alpha); Texture2D val3 = (flag ? _weakIcon : _normalIcon); if ((Object)(object)val3 != (Object)null) { GUI.DrawTexture(val2, (Texture)(object)val3, (ScaleMode)2, true); } float num2 = ((Rect)(ref val2)).xMax + 10f * scale; float num3 = ((Rect)(ref rect)).xMax - num2 - 12f * scale; string text = ((!KillPolicy.IsChinese(Plugin.Language.Value)) ? (flag ? "WEAKPOINT KILL" : "KILL CONFIRMED") : (flag ? "弱点击杀" : "击杀确认")); _titleStyle.fontSize = Mathf.RoundToInt(13f * scale); Rect val4 = default(Rect); ((Rect)(ref val4))..ctor(num2, ((Rect)(ref rect)).center.y - 20f * scale, num3, 22f * scale); int num4 = Mathf.RoundToInt(8f * scale); while (_titleStyle.fontSize > num4 && _titleStyle.CalcSize(new GUIContent(text)).x > num3) { GUIStyle titleStyle = _titleStyle; int fontSize = titleStyle.fontSize; titleStyle.fontSize = fontSize - 1; } GUI.color = new Color(0f, 0f, 0f, 0.65f * alpha); GUI.Label(new Rect(((Rect)(ref val4)).x + scale, ((Rect)(ref val4)).y + scale, ((Rect)(ref val4)).width, ((Rect)(ref val4)).height), text, _titleStyle); GUI.color = new Color(val.r, val.g, val.b, alpha); GUI.Label(val4, text, _titleStyle); string text2 = FeedbackPolicy.CardDetail(card, Plugin.ShowDistance.Value, Plugin.ShowEnemyHealth.Value); _detailStyle.fontSize = Mathf.RoundToInt(12f * scale); GUIContent val5 = new GUIContent(text2); int num5 = Mathf.RoundToInt(8f * scale); while (_detailStyle.fontSize > num5 && _detailStyle.CalcSize(val5).x > num3) { GUIStyle detailStyle = _detailStyle; int fontSize = detailStyle.fontSize; detailStyle.fontSize = fontSize - 1; } Rect val6 = default(Rect); ((Rect)(ref val6))..ctor(num2, ((Rect)(ref rect)).center.y + 1f * scale, num3, 19f * scale); GUI.color = new Color(0f, 0f, 0f, 0.65f * alpha); GUI.Label(new Rect(((Rect)(ref val6)).x + scale, ((Rect)(ref val6)).y + scale, ((Rect)(ref val6)).width, ((Rect)(ref val6)).height), text2, _detailStyle); GUI.color = new Color(Ink.r, Ink.g, Ink.b, 0.96f * alpha); GUI.Label(val6, text2, _detailStyle); } private void EnsureStyles() { //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_0021: 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_002f: 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_0042: Expected O, but got Unknown //IL_004d: 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_005a: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown if (_titleStyle == null) { _titleStyle = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1, alignment = (TextAnchor)3, clipping = (TextClipping)1, richText = false }; _detailStyle = new GUIStyle(GUI.skin.label) { fontSize = 13, alignment = (TextAnchor)3, clipping = (TextClipping)1, richText = false }; } } private void EnsureIcons() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown if (!_triedIcons) { _triedIcons = true; string path = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? string.Empty, "Assets", "icons"); _normalIcon = LoadIcon(Path.Combine(path, "kill-normal.png")); _weakIcon = LoadIcon(Path.Combine(path, "kill-weakspot.png")); ManualLogSource log = ((BasePlugin)Plugin.Instance).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(72, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[HUD] icons ready normal="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>((Object)(object)_normalIcon != (Object)null); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";weakspot="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>((Object)(object)_weakIcon != (Object)null); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";layout=two-line;health-tiers=removed"); } log.LogInfo(val); } } private static Texture2D LoadIcon(string path) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown if (!File.Exists(path)) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(File.ReadAllBytes(path)))) { Object.Destroy((Object)(object)val); return null; } ((Object)val).hideFlags = (HideFlags)61; return val; } private void Warn(string stage, string detail) { if (_warnings++ < 5) { Plugin instance = Plugin.Instance; if (instance != null) { ((BasePlugin)instance).Log.LogWarning((object)("[HUD] " + stage + ": " + detail)); } } } } internal enum KillKind { Normal, Weakspot } internal enum KillTier { Minor, Elite, Boss } internal readonly struct KillDecision { internal readonly bool Credited; internal readonly KillKind Kind; internal KillDecision(bool credited, KillKind kind) { Credited = credited; Kind = kind; } } internal static class KillDefaults { internal const bool Enabled = true; internal const float IconSize = 46f; internal const float CardLifetime = 2.6f; internal const float FadeSeconds = 0.45f; internal const float MaxDistance = 999f; internal const float MinorHealthThreshold = 120f; internal const float EliteHealthThreshold = 1000f; internal const int MaxCards = 3; } internal static class KillPolicy { internal static KillDecision ClassifyLethalHit(bool localPlayerSource, float healthBefore, float healthAfter, bool limbObserved, bool limbIsWeakspot) { bool flag = IsFinite(healthBefore) && IsFinite(healthAfter) && healthBefore > 0f && healthAfter <= 0f; if (!localPlayerSource || !flag) { return new KillDecision(credited: false, KillKind.Normal); } return new KillDecision(credited: true, (limbObserved && limbIsWeakspot) ? KillKind.Weakspot : KillKind.Normal); } internal static KillTier ClassifyTier(float healthMax, float minorThreshold = 120f, float eliteThreshold = 1000f) { if (!IsFinite(minorThreshold) || minorThreshold <= 0f) { minorThreshold = 120f; } if (!IsFinite(eliteThreshold) || eliteThreshold <= minorThreshold) { eliteThreshold = Math.Max(1000f, minorThreshold + 1f); } if (!IsFinite(healthMax) || healthMax < 0f) { return KillTier.Minor; } if (healthMax < minorThreshold) { return KillTier.Minor; } if (healthMax < eliteThreshold) { return KillTier.Elite; } return KillTier.Boss; } internal static string FormatDistance(float meters, float maximum = 999f) { if (!IsFinite(meters) || meters < 0f) { return "—"; } if (!IsFinite(maximum) || maximum < 1f) { maximum = 999f; } if (meters > maximum) { return ((int)Math.Floor(maximum + 0.5f)).ToString(CultureInfo.InvariantCulture) + "m+"; } return ((int)Math.Floor(meters + 0.5f)).ToString(CultureInfo.InvariantCulture) + "m"; } internal static string FormatHealth(float healthMax) { if (!IsFinite(healthMax) || healthMax < 0f) { return "— HP"; } return healthMax.ToString("0.#", CultureInfo.InvariantCulture) + " HP"; } internal static string IconKey(KillKind kind) { if (kind != KillKind.Weakspot) { return "kill-normal.png"; } return "kill-weakspot.png"; } internal static bool IsChinese(string language) { if (!string.Equals(language, "zh", StringComparison.OrdinalIgnoreCase) && !string.Equals(language, "zh-CN", StringComparison.OrdinalIgnoreCase)) { return string.Equals(language, "cn", StringComparison.OrdinalIgnoreCase); } return true; } internal static string TierLabel(KillTier tier, string language) { if (!IsChinese(language)) { return tier switch { KillTier.Elite => "ELITE", KillTier.Minor => "MINOR", _ => "BOSS", }; } return tier switch { KillTier.Elite => "精英", KillTier.Minor => "普通", _ => "BOSS", }; } internal static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } internal sealed class KillLedger { private readonly HashSet<long> _credited = new HashSet<long>(); internal int Count => _credited.Count; internal bool TryCredit(long enemyIdentity) { if (enemyIdentity != 0L) { return _credited.Add(enemyIdentity); } return false; } internal void Reset() { _credited.Clear(); } internal void Forget(long enemyIdentity) { _credited.Remove(enemyIdentity); } } internal sealed class KillCard { internal readonly KillKind Kind; internal readonly KillTier Tier; internal readonly string EnemyName; internal readonly string DistanceText; internal readonly string HealthText; internal readonly float CreatedAt; internal KillCard(KillKind kind, KillTier tier, string enemyName, float distanceMeters, float healthMax, float createdAt, float maxDistance = 999f) { Kind = kind; Tier = tier; EnemyName = (string.IsNullOrWhiteSpace(enemyName) ? "Unknown" : enemyName.Trim()); DistanceText = KillPolicy.FormatDistance(distanceMeters, maxDistance); HealthText = KillPolicy.FormatHealth(healthMax); CreatedAt = createdAt; } } internal readonly struct VisibleKillCard { internal readonly KillCard Card; internal readonly float Alpha; internal VisibleKillCard(KillCard card, float alpha) { Card = card; Alpha = alpha; } } internal sealed class KillCardQueue { private readonly List<KillCard> _cards = new List<KillCard>(); internal int Count => _cards.Count; internal bool Enqueue(KillCard card, float now, float lifetime, float fadeSeconds, int capacity) { if (card == null || capacity <= 0 || !KillPolicy.IsFinite(now)) { return false; } lifetime = (KillPolicy.IsFinite(lifetime) ? Math.Max(0.1f, lifetime) : 2.6f); fadeSeconds = (KillPolicy.IsFinite(fadeSeconds) ? Math.Max(0f, Math.Min(fadeSeconds, lifetime)) : 0.45f); Trim(now, lifetime); while (_cards.Count >= capacity) { _cards.RemoveAt(0); } _cards.Add(card); return true; } internal VisibleKillCard[] Snapshot(float now, float lifetime, float fadeSeconds, int capacity) { if (!KillPolicy.IsFinite(now)) { return Array.Empty<VisibleKillCard>(); } lifetime = (KillPolicy.IsFinite(lifetime) ? Math.Max(0.1f, lifetime) : 2.6f); fadeSeconds = (KillPolicy.IsFinite(fadeSeconds) ? Math.Max(0f, Math.Min(fadeSeconds, lifetime)) : 0.45f); Trim(now, lifetime); int num = Math.Max(0, _cards.Count - Math.Max(0, capacity)); VisibleKillCard[] array = new VisibleKillCard[_cards.Count - num]; for (int i = num; i < _cards.Count; i++) { KillCard killCard = _cards[i]; float num2 = Math.Max(0f, now - killCard.CreatedAt); float alpha = ((fadeSeconds <= 0f || num2 <= lifetime - fadeSeconds) ? 1f : Math.Max(0f, Math.Min(1f, (lifetime - num2) / fadeSeconds))); array[i - num] = new VisibleKillCard(killCard, alpha); } return array; } internal void Clear() { _cards.Clear(); } private void Trim(float now, float lifetime) { for (int num = _cards.Count - 1; num >= 0; num--) { if (now - _cards[num].CreatedAt >= lifetime) { _cards.RemoveAt(num); } } } } internal sealed class DamageRoot { internal IntPtr EnemyPointer; internal float HealthBefore; internal bool LocalSource; internal bool LimbObserved; internal bool Weakspot; internal bool Credited; internal bool HitRecorded; internal bool HasValue; internal bool Processed; internal ulong PlayerLookup; internal HitKind Kind; internal float Damage; internal Vector3 Position; internal Vector3 Direction; } internal sealed class DamageScope { internal DamageScope Previous; internal DamageRoot Root; } internal static class KillTracker { private static readonly KillLedger Ledger = new KillLedger(); private static readonly KillCardQueue Cards = new KillCardQueue(); private static readonly BurstHistory Bursts = new BurstHistory(); [ThreadStatic] private static DamageScope _active; private static int _diagnosticBudget = 12; internal static void Reset() { Ledger.Reset(); Cards.Clear(); Bursts.Clear(); _active = null; DamageNumbers.Clear(); CorpseFeedback.Reset(); } internal static void Spawned(Dam_EnemyDamageBase enemy) { if (!((Object)(object)enemy == (Object)null)) { Ledger.Forget(((Il2CppObjectBase)enemy).Pointer.ToInt64()); Bursts.Remove(((Il2CppObjectBase)enemy).Pointer.ToInt64()); } } private static DamageScope Begin(Dam_EnemyDamageBase enemy, Agent sourceAgent, int limbId, Vector3 position, Vector3 direction) { //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_00b4: 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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Invalid comparison between Unknown and I4 //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Invalid comparison between Unknown and I4 (bool, ulong) tuple = ResolveSource(sourceAgent); IntPtr intPtr = (((Object)(object)enemy != (Object)null) ? ((Il2CppObjectBase)enemy).Pointer : IntPtr.Zero); DamageRoot damageRoot = _active?.Root; if (damageRoot == null || damageRoot.HitRecorded || damageRoot.EnemyPointer != intPtr || damageRoot.PlayerLookup != tuple.Item2 || damageRoot.LocalSource != tuple.Item1) { damageRoot = new DamageRoot { Kind = HitKind.Normal, EnemyPointer = intPtr, HealthBefore = (((Object)(object)enemy != (Object)null) ? ((Dam_SyncedDamageBase)enemy).Health : 0f), LocalSource = tuple.Item1, PlayerLookup = tuple.Item2, Position = position, Direction = direction }; } if ((Object)(object)enemy != (Object)null && limbId >= 0 && enemy.DamageLimbs != null && limbId < ((Il2CppArrayBase<Dam_EnemyDamageLimb>)(object)enemy.DamageLimbs).Length) { Dam_EnemyDamageLimb val = ((Il2CppArrayBase<Dam_EnemyDamageLimb>)(object)enemy.DamageLimbs)[limbId]; if ((Object)(object)val != (Object)null) { damageRoot.LimbObserved = true; damageRoot.Weakspot = (int)val.m_type == 1; damageRoot.Kind = (damageRoot.Weakspot ? HitKind.Weakspot : (((int)val.m_type == 2) ? HitKind.Armor : HitKind.Normal)); } } return _active = new DamageScope { Previous = _active, Root = damageRoot }; } internal static DamageScope BeginLimb(Dam_EnemyDamageLimb limb, float damage, Agent source, Vector3 position, Vector3 direction, float precision, bool behind, bool melee, float backstabber = 1f, float sleeper = 1f) { //IL_0027: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Invalid comparison between Unknown and I4 //IL_00a3: 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) Dam_EnemyDamageBase val = (((Object)(object)limb != (Object)null) ? limb.m_base : null); DamageScope damageScope = Begin(val, source, ((Object)(object)limb != (Object)null) ? limb.m_limbID : (-1), position, direction); DamageRoot root = damageScope.Root; if (!root.LocalSource || root.HealthBefore <= 0f || (Object)(object)val == (Object)null || (Object)(object)limb == (Object)null) { return damageScope; } try { float num = AgentModifierManager.ApplyModifier((Agent)(object)val.Owner, (AgentModifier)(melee ? 6 : 7), damage); if (melee && (int)val.Owner.Locomotion.CurrentStateEnum == 14) { num *= sleeper; } num = limb.ApplyWeakspotAndArmorModifiers(num, precision); if (behind) { num = limb.ApplyDamageFromBehindBonus(num, position, direction, backstabber); } root.Damage = Dam_EnemyDamageBase.RoundDamage(num); root.HasValue = KillPolicy.IsFinite(root.Damage) && root.Damage >= 0f; } catch (Exception ex) { Note("modifier capture unavailable: " + ex.GetType().Name); } return damageScope; } internal static DamageScope BeginBullet(Dam_EnemyDamageBase enemy, pBulletDamageData data) { //IL_0018: 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_0039: 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_0027: 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) Agent sourceAgent = null; try { ((pAgent)(ref data.source)).TryGet(ref sourceAgent); } catch { } return Begin(enemy, sourceAgent, data.limbID, ((Object)(object)enemy != (Object)null) ? (((Component)enemy).transform.position + Vector3.up) : Vector3.zero, Vector3.zero); } internal static DamageScope BeginProcessedDamage(Dam_EnemyDamageBase enemy, Agent source, float damage, Vector3 position, Vector3 direction, int limbId) { //IL_0004: 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_004b: 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_0059: Unknown result type (might be due to invalid IL or missing references) DamageScope damageScope = Begin(enemy, source, limbId, position, direction); damageScope.Root.Processed = true; damageScope.Root.Damage = damage; damageScope.Root.HasValue = KillPolicy.IsFinite(damage) && damage >= 0f; damageScope.Root.Position = position; damageScope.Root.Direction = direction; return damageScope; } private static void RecordHit(Dam_EnemyDamageBase enemy, DamageRoot root) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (root.HitRecorded || !root.LocalSource || root.HealthBefore <= 0f) { return; } root.HitRecorded = true; float num = (root.HasValue ? root.Damage : Math.Max(0f, root.HealthBefore - ((Dam_SyncedDamageBase)enemy).Health)); if (KillPolicy.IsFinite(num) && !(num < 0f)) { if (root.Processed && ((Dam_SyncedDamageBase)enemy).Health >= root.HealthBefore) { num = 0f; } if (num > 0f) { Bursts.Add(root.EnemyPointer.ToInt64(), Time.unscaledTime, num); } if (num > 0f || root.Kind == HitKind.Armor) { DamageNumbers.Add(root.Position, num, root.Kind); Note($"number={num:0.####};kind={root.Kind};source={(root.Processed ? "final-settlement" : (root.HasValue ? "native-modifiers" : "health-delta"))}"); } } } internal static void Complete(Dam_EnemyDamageBase enemy, DamageScope scope) { //IL_015e: 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_01a2: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null || scope?.Root == null) { return; } DamageRoot root = scope.Root; if (root.EnemyPointer != ((Il2CppObjectBase)enemy).Pointer || !root.LocalSource) { return; } RecordHit(enemy, root); KillDecision killDecision = KillPolicy.ClassifyLethalHit(root.LocalSource, root.HealthBefore, ((Dam_SyncedDamageBase)enemy).Health, root.LimbObserved, root.Weakspot); if (!killDecision.Credited || root.Credited || !Ledger.TryCredit(root.EnemyPointer.ToInt64())) { return; } root.Credited = true; EnemyAgent owner = enemy.Owner; if ((Object)(object)owner == (Object)null) { return; } float distanceMeters = float.NaN; try { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); if ((Object)(object)localPlayerAgent != (Object)null) { distanceMeters = Vector3.Distance(((Component)localPlayerAgent).transform.position, ((Component)owner).transform.position); } } catch { } string text = ResolveEnemyName(owner); string text2 = EnemyNames.Resolve(owner.EnemyDataID, text); KillCard killCard = new KillCard(killDecision.Kind, KillTier.Minor, text2, distanceMeters, ((Dam_SyncedDamageBase)enemy).HealthMax, Time.unscaledTime, Plugin.MaxDistance?.Value ?? 999f); Cards.Enqueue(killCard, Time.unscaledTime, Plugin.CardLifetime.Value, Plugin.FadeSeconds.Value, ClampCards(Plugin.MaxCards.Value)); CorpseFeedback.Schedule(owner, root.Direction, FeedbackPolicy.Strength(Bursts.Sum(root.EnemyPointer.ToInt64(), Time.unscaledTime))); ManualLogSource log = ((BasePlugin)Plugin.Instance).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(82, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[KILLFEED] classification="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((killDecision.Kind == KillKind.Weakspot) ? "WEAKSPOT" : "NORMAL"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";enemyId="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<uint>(owner.EnemyDataID); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";rawName="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";displayName="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text2); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";distance="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(killCard.DistanceText); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(";limbObserved="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(root.LimbObserved); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log.LogInfo(val); } internal static void CompleteFromAgent(EnemyAgent agent) { if ((Object)(object)((agent != null) ? agent.Damage : null) != (Object)null && _active?.Root?.EnemyPointer == ((Il2CppObjectBase)agent.Damage).Pointer) { Complete(agent.Damage, _active); } } internal static void CompleteFromActive(Dam_EnemyDamageBase enemy) { if ((Object)(object)enemy != (Object)null && _active?.Root?.EnemyPointer == ((Il2CppObjectBase)enemy).Pointer) { Complete(enemy, _active); } } internal static Exception End(Dam_EnemyDamageBase enemy, DamageScope scope, Exception error) { try { if (error == null) { Complete(enemy, scope); } } catch (Exception ex) { Note("capture skipped: " + ex.Message); } finally { if (_active == scope) { _active = scope?.Previous; } } return error; } internal static VisibleKillCard[] Snapshot(float now) { return Cards.Snapshot(now, Plugin.CardLifetime.Value, Plugin.FadeSeconds.Value, ClampCards(Plugin.MaxCards.Value)); } internal static void AddPreview(bool weakspot) { Cards.Enqueue(new KillCard(weakspot ? KillKind.Weakspot : KillKind.Normal, KillTier.Minor, weakspot ? "大壮" : "小白", weakspot ? 13f : 27f, weakspot ? 120f : 80f, Time.unscaledTime), Time.unscaledTime, Plugin.CardLifetime.Value, Plugin.FadeSeconds.Value, ClampCards(Plugin.MaxCards.Value)); } internal static void ObserveState(eGameStateName state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)state != 10) { Reset(); } } internal static void LogPatchReceipts(Harmony harmony, ManualLogSource log) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown bool flag = default(bool); foreach (MethodBase patchedMethod in harmony.GetPatchedMethods()) { Patches patchInfo = Harmony.GetPatchInfo(patchedMethod); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(33, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[DIAG] patch "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(patchedMethod.DeclaringType.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(patchedMethod.Name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": pre="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(patchInfo.Prefixes.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(",post="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(patchInfo.Postfixes.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(",final="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(patchInfo.Finalizers.Count); } log.LogInfo(val); } } private static int ClampCards(int value) { return Math.Max(1, Math.Min(6, value)); } private static (bool Local, ulong Lookup) ResolveSource(Agent source) { try { object obj; if (source == null) { obj = null; } else { PlayerAgent obj2 = ((Il2CppObjectBase)source).TryCast<PlayerAgent>(); obj = ((obj2 != null) ? obj2.Owner : null); } SNet_Player val = (SNet_Player)obj; return ((Object)(object)val != (Object)null && val.IsLocal) ? (Local: true, Lookup: val.Lookup) : (Local: false, Lookup: 0uL); } catch { return (Local: false, Lookup: 0uL); } } private static string ResolveEnemyName(EnemyAgent agent) { try { EnemyDataBlock block = GameDataBlockBase<EnemyDataBlock>.GetBlock(agent.EnemyDataID); if (block != null && !string.IsNul