Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of EndGameStats v0.4.0
BepInEx/plugins/EndGameStats/EndGameStats.Core.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EndGameStats.Core")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("EndGameStats.Core")] [assembly: AssemblyTitle("EndGameStats.Core")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EndGameStats.Core { public sealed class PlayerRunStats { public string PlayerId { get; } public string DisplayName { get; private set; } public int Deaths { get; private set; } public int TeammatesRescued { get; private set; } public int EnemyKills { get; private set; } public double HaulWork { get; private set; } public double ExtractedValue { get; private set; } public double ValuableDamage { get; private set; } public PlayerRunStats(string playerId, string displayName) { if (string.IsNullOrWhiteSpace(playerId)) { throw new ArgumentException("A stable player ID is required.", "playerId"); } PlayerId = playerId; DisplayName = displayName ?? string.Empty; } public void Rename(string displayName) { DisplayName = displayName ?? string.Empty; } public void RecordDeath() { Deaths++; } public void RecordRescue() { TeammatesRescued++; } public void RecordEnemyKill() { EnemyKills++; } public void AddHaulWork(double currentValue, double distanceMetres, int grabberCount = 1) { if (!IsFiniteNonNegative(currentValue)) { throw new ArgumentOutOfRangeException("currentValue"); } if (!IsFiniteNonNegative(distanceMetres)) { throw new ArgumentOutOfRangeException("distanceMetres"); } if (grabberCount < 1) { throw new ArgumentOutOfRangeException("grabberCount"); } HaulWork += currentValue * distanceMetres / (double)grabberCount; } public void AddValuableDamage(double valueLost) { if (!IsFiniteNonNegative(valueLost)) { throw new ArgumentOutOfRangeException("valueLost"); } ValuableDamage += valueLost; } public void AddExtractedValue(double value) { if (!IsFiniteNonNegative(value)) { throw new ArgumentOutOfRangeException("value"); } ExtractedValue += value; } private static bool IsFiniteNonNegative(double value) { if (!double.IsNaN(value) && !double.IsInfinity(value)) { return value >= 0.0; } return false; } } public sealed class RunStatsBoard { private readonly Dictionary<string, PlayerRunStats> _players = new Dictionary<string, PlayerRunStats>(StringComparer.Ordinal); public IReadOnlyCollection<PlayerRunStats> Players => _players.Values; public double UnattributedValuableDamage { get; private set; } public double UnattributedExtractedValue { get; private set; } public PlayerRunStats GetOrAddPlayer(string playerId, string displayName) { if (_players.TryGetValue(playerId, out PlayerRunStats value)) { value.Rename(displayName); return value; } value = new PlayerRunStats(playerId, displayName); _players.Add(playerId, value); return value; } public void AddUnattributedDamage(double valueLost) { if (double.IsNaN(valueLost) || double.IsInfinity(valueLost) || valueLost < 0.0) { throw new ArgumentOutOfRangeException("valueLost"); } UnattributedValuableDamage += valueLost; } public void AddUnattributedExtractedValue(double value) { if (double.IsNaN(value) || double.IsInfinity(value) || value < 0.0) { throw new ArgumentOutOfRangeException("value"); } UnattributedExtractedValue += value; } public IReadOnlyList<PlayerRunStats> Leaders(Func<PlayerRunStats, double> value, bool lowerIsBetter = false, Func<PlayerRunStats, bool>? eligible = null) { PlayerRunStats[] array = _players.Values.Where(eligible ?? ((Func<PlayerRunStats, bool>)((PlayerRunStats _) => true))).ToArray(); if (array.Length == 0) { return Array.Empty<PlayerRunStats>(); } double best = (lowerIsBetter ? array.Min(value) : array.Max(value)); return array.Where((PlayerRunStats player) => NearlyEqual(value(player), best)).OrderBy<PlayerRunStats, string>((PlayerRunStats player) => player.DisplayName, StringComparer.OrdinalIgnoreCase).ToArray(); } private static bool NearlyEqual(double left, double right) { double num = Math.Max(1.0, Math.Max(Math.Abs(left), Math.Abs(right))); return Math.Abs(left - right) <= 1E-09 * num; } } }
BepInEx/plugins/EndGameStats/EndGameStats.dll
Decompiled 7 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using EndGameStats.Core; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EndGameStats")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("EndGameStats")] [assembly: AssemblyTitle("EndGameStats")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EndGameStats { [HarmonyPatch(typeof(ValuableObject), "Start")] internal static class ValuableRegistrationPatch { private static void Postfix(ValuableObject __instance) { Plugin.Instance.RegisterValuable(__instance); } } [HarmonyPatch(typeof(PhysGrabObject), "GrabPlayerAddRPC")] internal static class GrabStartedPatch { private static void Postfix(PhysGrabObject __instance, int photonViewID) { Plugin.Instance.RecordGrab(__instance, photonViewID, released: false); } } [HarmonyPatch(typeof(PhysGrabObject), "GrabPlayerRemoveRPC")] internal static class GrabEndedPatch { private static void Prefix(PhysGrabObject __instance, int photonViewID) { Plugin.Instance.RecordGrab(__instance, photonViewID, released: true); } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")] internal static class PlayerDeathPatch { private static void Postfix(PlayerAvatar __instance) { Plugin.Instance.RecordDeath(__instance); } } [HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")] internal static class PlayerRevivePatch { private static void Prefix(PlayerAvatar __instance, bool _revivedByTruck, out PlayerAvatar? __state) { __state = Plugin.Instance.CaptureRescuer(__instance, _revivedByTruck); } private static void Postfix(PlayerAvatar? __state) { Plugin.Instance.RecordRescue(__state); } } [HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "BreakRPC")] internal static class ValuableDamagePatch { private static void Prefix(PhysGrabObjectImpactDetector __instance, float valueLost, bool _loseValue) { Plugin.Instance.RecordDamage(__instance, valueLost, _loseValue); } } [HarmonyPatch(typeof(ExtractionPoint), "ExtractionPointSurplus")] internal static class SuccessfulExtractionPatch { private static void Prefix() { Plugin.Instance.RecordSuccessfulExtraction(); } } [HarmonyPatch(typeof(HurtCollider), "EnemyHurt")] internal static class WeaponEnemyHitPatch { private static void Prefix(HurtCollider __instance, Enemy _enemy) { Plugin.Instance.RecordWeaponEnemyHit(__instance, _enemy); } } [HarmonyPatch(typeof(EnemyHealth), "DeathImpulseRPC")] internal static class EnemyDeathPatch { private static void Postfix(EnemyHealth __instance) { Plugin.Instance.RecordEnemyDeath(__instance); } } [BepInPlugin("chaun.repo.endgamestats", "End Game Stats", "0.4.0")] public sealed class Plugin : BaseUnityPlugin { private sealed class ValuableSample { public PlayerAvatar? LastCarrier; public float LastCarriedAt = float.NegativeInfinity; public ValuableObject Valuable { get; } public HashSet<string> Participants { get; } = new HashSet<string>(StringComparer.Ordinal); public ValuableSample(ValuableObject valuable) { Valuable = valuable; } } private sealed class EnemyAttribution { public PlayerAvatar Player { get; } public float At { get; } public EnemyAttribution(PlayerAvatar player, float at) { Player = player; At = at; } } public const string PluginGuid = "chaun.repo.endgamestats"; public const string PluginName = "End Game Stats"; public const string PluginVersion = "0.4.0"; private readonly Dictionary<int, ValuableSample> _valuables = new Dictionary<int, ValuableSample>(); private readonly HashSet<int> _creditedExtractions = new HashSet<int>(); private readonly HashSet<string> _deadPlayers = new HashSet<string>(StringComparer.Ordinal); private readonly Dictionary<int, EnemyAttribution> _enemyAttribution = new Dictionary<int, EnemyAttribution>(); private readonly HashSet<int> _creditedEnemyKills = new HashSet<int>(); private ConfigEntry<KeyboardShortcut> _toggleKey; private ConfigEntry<float> _cartSampleInterval; private ConfigEntry<float> _releaseAttributionSeconds; private ConfigEntry<float> _enemyKillAttributionSeconds; private ConfigEntry<string> _language; private bool _visible; private bool _wasInLevel; private float _nextSample; private Rect _window = new Rect(40f, 60f, 1110f, 420f); private Texture2D _panelTexture; private Texture2D _screenTexture; private Texture2D _borderTexture; private Texture2D _rowTexture; private Texture2D _scanlineTexture; private GUIStyle _windowStyle; private Font? _terminalFont; internal static Plugin Instance { get; private set; } internal RunStatsBoard Board { get; private set; } = new RunStatsBoard(); private void Awake() { //IL_0021: 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) Instance = this; _toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Display", "ToggleKey", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), "Open or close the live stats board."); _language = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "Language", "Auto", "UI language: Auto, English, or SimplifiedChinese."); _cartSampleInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Tracking", "CartSampleIntervalSeconds", 1f, "Low-frequency fallback interval for valuables transported inside carts."); _releaseAttributionSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Tracking", "DamageAttributionSeconds", 3f, "Attribute damage to the most recent carrier for this long after release."); _enemyKillAttributionSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Tracking", "EnemyKillAttributionSeconds", 10f, "Credit an enemy kill to its most recent player interaction within this many seconds."); new Harmony("chaun.repo.endgamestats").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"End Game Stats 0.4.0 loaded"); } private void Update() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = _toggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { _visible = !_visible; } bool flag = SafeRunIsLevel(); if (flag && !_wasInLevel) { BeginLevel(); } else if (!flag && _wasInLevel) { _visible = true; } _wasInLevel = flag; if (flag && !(Time.unscaledTime < _nextSample)) { _nextSample = Time.unscaledTime + Mathf.Max(0.25f, _cartSampleInterval.Value); SampleCartParticipants(); } } private void BeginLevel() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown Board = new RunStatsBoard(); _valuables.Clear(); _creditedExtractions.Clear(); _deadPlayers.Clear(); _enemyAttribution.Clear(); _creditedEnemyKills.Clear(); _visible = false; RegisterExistingValuables(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Started a new level stats snapshot"); } private void RegisterExistingValuables() { if (!Object.op_Implicit((Object)(object)ValuableDirector.instance)) { return; } foreach (ValuableObject valuable in ValuableDirector.instance.valuableList) { RegisterValuable(valuable); } } internal void RegisterValuable(ValuableObject? valuable) { if (valuable != null && Object.op_Implicit((Object)(object)valuable) && !_valuables.ContainsKey(((Object)valuable).GetInstanceID())) { _valuables.Add(((Object)valuable).GetInstanceID(), new ValuableSample(valuable)); } } private void SampleCartParticipants() { RegisterExistingValuables(); if (Object.op_Implicit((Object)(object)GameDirector.instance)) { foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { GetPlayer(player); } } KeyValuePair<int, ValuableSample>[] array = _valuables.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair<int, ValuableSample> keyValuePair = array[i]; ValuableObject valuable = keyValuePair.Value.Valuable; if (!Object.op_Implicit((Object)(object)valuable)) { _valuables.Remove(keyValuePair.Key); continue; } PhysGrabObjectImpactDetector component = ((Component)valuable).GetComponent<PhysGrabObjectImpactDetector>(); if (Object.op_Implicit((Object)(object)component) && component.inCart) { PhysGrabCart value = Traverse.Create((object)component).Field("currentCart").GetValue<PhysGrabCart>(); if (Object.op_Implicit((Object)(object)value)) { AddParticipants(keyValuePair.Value, GetGrabbers(((Component)value).GetComponent<PhysGrabObject>())); } } } } internal void RecordGrab(PhysGrabObject grabObject, int grabberPhotonViewId, bool released) { PhotonView val = PhotonView.Find(grabberPhotonViewId); PhysGrabber val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<PhysGrabber>() : null); if (val2 == null || !Object.op_Implicit((Object)(object)val2) || val2.playerAvatar == null || !Object.op_Implicit((Object)(object)val2.playerAvatar)) { return; } ValuableObject component = ((Component)grabObject).GetComponent<ValuableObject>(); if (Object.op_Implicit((Object)(object)component)) { RegisterValuable(component); ValuableSample valuableSample = _valuables[((Object)component).GetInstanceID()]; PlayerRunStats player = GetPlayer(val2.playerAvatar); if (player != null) { valuableSample.Participants.Add(player.PlayerId); } valuableSample.LastCarrier = val2.playerAvatar; if (released) { valuableSample.LastCarriedAt = Time.unscaledTime; } return; } PhysGrabCart component2 = ((Component)grabObject).GetComponent<PhysGrabCart>(); if (!Object.op_Implicit((Object)(object)component2)) { EnemyRigidbody val3 = ((Component)grabObject).GetComponent<EnemyRigidbody>() ?? ((Component)grabObject).GetComponentInParent<EnemyRigidbody>(); EnemyHealth val4 = (Object.op_Implicit((Object)(object)val3) ? ((Component)val3).GetComponent<EnemyHealth>() : null); if (Object.op_Implicit((Object)(object)val4)) { RememberEnemyInteractor(val4, val2.playerAvatar); } } else { if (released) { return; } foreach (KeyValuePair<int, ValuableSample> valuable2 in _valuables) { ValuableObject valuable = valuable2.Value.Valuable; if (Object.op_Implicit((Object)(object)valuable)) { PhysGrabObjectImpactDetector component3 = ((Component)valuable).GetComponent<PhysGrabObjectImpactDetector>(); if ((Object)(object)(Object.op_Implicit((Object)(object)component3) ? Traverse.Create((object)component3).Field("currentCart").GetValue<PhysGrabCart>() : null) == (Object)(object)component2) { AddParticipants(valuable2.Value, (IEnumerable<PhysGrabber>)(object)new PhysGrabber[1] { val2 }); } } } } } internal void RecordDeath(PlayerAvatar avatar) { PlayerRunStats player = GetPlayer(avatar); if (player != null && _deadPlayers.Add(player.PlayerId)) { player.RecordDeath(); } } internal PlayerAvatar? CaptureRescuer(PlayerAvatar revived, bool revivedByTruck) { PlayerRunStats player = GetPlayer(revived); if (player == null || !_deadPlayers.Remove(player.PlayerId)) { return null; } if (revivedByTruck) { return null; } PlayerDeathHead value = Traverse.Create((object)revived).Field("playerDeathHead").GetValue<PlayerDeathHead>(); if (!Object.op_Implicit((Object)(object)value)) { return null; } return (from grabber in GetGrabbers(Traverse.Create((object)value).Field("physGrabObject").GetValue<PhysGrabObject>()) select grabber.playerAvatar).FirstOrDefault((Func<PlayerAvatar, bool>)((PlayerAvatar val) => Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)revived)); } internal void RecordRescue(PlayerAvatar? rescuer) { if (Object.op_Implicit((Object)(object)rescuer)) { PlayerRunStats? player = GetPlayer(rescuer); if (player != null) { player.RecordRescue(); } } } internal void RecordDamage(PhysGrabObjectImpactDetector detector, float valueLost, bool loseValue) { if (!loseValue || valueLost <= 0f) { return; } ValuableObject component = ((Component)detector).GetComponent<ValuableObject>(); if (!Object.op_Implicit((Object)(object)component)) { return; } PlayerAvatar val = null; List<PhysGrabber> grabbers = GetGrabbers(((Component)component).GetComponent<PhysGrabObject>()); ValuableSample value; if (grabbers.Count > 0) { val = grabbers[0].playerAvatar; } else if (_valuables.TryGetValue(((Object)component).GetInstanceID(), out value) && Time.unscaledTime - value.LastCarriedAt <= _releaseAttributionSeconds.Value) { val = value.LastCarrier; } if (Object.op_Implicit((Object)(object)val)) { PlayerRunStats? player = GetPlayer(val); if (player != null) { player.AddValuableDamage((double)valueLost); } } else { Board.AddUnattributedDamage((double)valueLost); } } internal void RecordSuccessfulExtraction() { if (!Object.op_Implicit((Object)(object)RoundDirector.instance)) { return; } GameObject[] array = RoundDirector.instance.dollarHaulList.ToArray(); foreach (GameObject val in array) { if (!Object.op_Implicit((Object)(object)val)) { continue; } ValuableObject component = val.GetComponent<ValuableObject>(); if (!Object.op_Implicit((Object)(object)component) || !_creditedExtractions.Add(((Object)component).GetInstanceID())) { continue; } float num = ReadFloat(component, "dollarValueCurrent"); if (!_valuables.TryGetValue(((Object)component).GetInstanceID(), out ValuableSample value) || value.Participants.Count == 0) { Board.AddUnattributedExtractedValue((double)num); continue; } float num2 = num / (float)value.Participants.Count; foreach (string playerId in value.Participants) { PlayerRunStats val2 = ((IEnumerable<PlayerRunStats>)Board.Players).FirstOrDefault((Func<PlayerRunStats, bool>)((PlayerRunStats candidate) => candidate.PlayerId == playerId)); if (val2 != null) { val2.AddExtractedValue((double)num2); } else { Board.AddUnattributedExtractedValue((double)num2); } } } } internal void RecordWeaponEnemyHit(HurtCollider hurtCollider, Enemy enemy) { if (!Object.op_Implicit((Object)(object)enemy) || hurtCollider.deathPit) { return; } EnemyHealth component = ((Component)enemy).GetComponent<EnemyHealth>(); if (Object.op_Implicit((Object)(object)component)) { PhysGrabObject componentInParent = ((Component)hurtCollider).GetComponentInParent<PhysGrabObject>(); if (Object.op_Implicit((Object)(object)componentInParent)) { PlayerAvatar value = Traverse.Create((object)componentInParent).Field("lastPlayerGrabbing").GetValue<PlayerAvatar>(); RememberEnemyInteractor(component, value); } } } internal void RecordEnemyDeath(EnemyHealth enemyHealth) { if (!Object.op_Implicit((Object)(object)enemyHealth) || !_creditedEnemyKills.Add(((Object)enemyHealth).GetInstanceID())) { return; } PlayerAvatar val = null; if (_enemyAttribution.TryGetValue(((Object)enemyHealth).GetInstanceID(), out EnemyAttribution value) && Time.unscaledTime - value.At <= Mathf.Max(0f, _enemyKillAttributionSeconds.Value)) { val = value.Player; } if (val == null) { val = Traverse.Create((object)enemyHealth).Field("onObjectHurtPlayer").GetValue<PlayerAvatar>(); } if (Object.op_Implicit((Object)(object)val)) { PlayerRunStats? player = GetPlayer(val); if (player != null) { player.RecordEnemyKill(); } } } private void RememberEnemyInteractor(EnemyHealth enemyHealth, PlayerAvatar? player) { if (Object.op_Implicit((Object)(object)enemyHealth) && Object.op_Implicit((Object)(object)player)) { _enemyAttribution[((Object)enemyHealth).GetInstanceID()] = new EnemyAttribution(player, Time.unscaledTime); } } private void AddParticipants(ValuableSample sample, IEnumerable<PhysGrabber> grabbers) { foreach (PhysGrabber grabber in grabbers) { PlayerRunStats player = GetPlayer(grabber.playerAvatar); if (player != null) { sample.Participants.Add(player.PlayerId); } } } private PlayerRunStats? GetPlayer(PlayerAvatar? avatar) { if (!Object.op_Implicit((Object)(object)avatar)) { return null; } string value = Traverse.Create((object)avatar).Field("playerName").GetValue<string>(); string text = (Object.op_Implicit((Object)(object)avatar.photonView) ? ("photon:" + avatar.photonView.OwnerActorNr.ToString(CultureInfo.InvariantCulture)) : "local"); return Board.GetOrAddPlayer(text, string.IsNullOrWhiteSpace(value) ? "Semibot" : value); } private static List<PhysGrabber> GetGrabbers(PhysGrabObject? grabObject) { List<PhysGrabber> list = new List<PhysGrabber>(); if (!Object.op_Implicit((Object)(object)grabObject)) { return list; } if (!(Traverse.Create((object)grabObject).Field("playerGrabbing").GetValue() is IEnumerable enumerable)) { return list; } foreach (object item in enumerable) { PhysGrabber val = (PhysGrabber)((item is PhysGrabber) ? item : null); if (val != null && Object.op_Implicit((Object)(object)val)) { list.Add(val); } } return list; } private static float ReadFloat(object instance, string field) { return Traverse.Create(instance).Field(field).GetValue<float>(); } private static bool SafeRunIsLevel() { try { return SemiFunc.RunIsLevel(); } catch { return false; } } private void OnGUI() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //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) if (_visible) { if (_windowStyle == null) { BuildVisualTheme(); } _window = GUI.Window(948210, _window, new WindowFunction(DrawWindow), string.Empty, _windowStyle); } } private void DrawWindow(int id) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Expected O, but got Unknown //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0411: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) DrawTerminalFrame(); GUIStyle val = new GUIStyle(GUI.skin.label) { font = _terminalFont, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; val.normal.textColor = new Color(0.52f, 1f, 0.52f); GUIStyle val2 = val; GUI.Label(new Rect(20f, 5f, ((Rect)(ref _window)).width - 40f, 24f), T("[ CRT-03 // SALVAGE TELEMETRY ]", "[ CRT-03 // 回收作业终端 ]"), val2); GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, alignment = (TextAnchor)4, font = _terminalFont }; val3.normal.textColor = new Color(0.52f, 1f, 0.52f); GUIStyle val4 = val3; GUIStyle val5 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, font = _terminalFont }; val5.normal.textColor = new Color(0.38f, 0.86f, 0.42f); GUIStyle val6 = val5; GUIStyle style = new GUIStyle(val6); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.Label(T("SYS.READOUT / STATUS: ONLINE", "系统读数 / 状态:在线"), val4, Array.Empty<GUILayoutOption>()); GUILayout.Space(3f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Column(T("PLAYER", "玩家"), 190f, val4); Column(T("DEATHS", "死亡"), 70f, val4); Column(T("RESCUES", "救援"), 70f, val4); Column(T("KILLS", "击杀"), 70f, val4); Column(T("RECOVERED VALUE", "回收贡献"), 140f, val4); Column(T("GOODS DAMAGED", "物品损失"), 140f, val4); Column(T("TITLES", "称号"), 360f, val4); GUILayout.EndHorizontal(); GUILayout.Space(6f); foreach (PlayerRunStats item in Board.Players.OrderByDescending((PlayerRunStats p) => p.ExtractedValue)) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Column(Truncate(item.DisplayName, 20), 190f, val6); Column(item.Deaths.ToString(CultureInfo.InvariantCulture), 70f, style); Column(item.TeammatesRescued.ToString(CultureInfo.InvariantCulture), 70f, style); Column(item.EnemyKills.ToString(CultureInfo.InvariantCulture), 70f, style); Column(Dollars(item.ExtractedValue), 140f, style); Column(Dollars(item.ValuableDamage), 140f, style); GUIStyle val7 = new GUIStyle(val6) { fontStyle = (FontStyle)1 }; val7.normal.textColor = new Color(0.7f, 1f, 0.5f); Column(GetTitles(item), 360f, val7); GUILayout.EndHorizontal(); } GUILayout.FlexibleSpace(); GUILayout.Label(T("Unattributed goods damage: " + Dollars(Board.UnattributedValuableDamage), "未归属的物品损失:" + Dollars(Board.UnattributedValuableDamage)), Array.Empty<GUILayoutOption>()); GUILayout.Label(T("Unattributed recovered value: " + Dollars(Board.UnattributedExtractedValue), "未归属的回收价值:" + Dollars(Board.UnattributedExtractedValue)), Array.Empty<GUILayoutOption>()); KeyboardShortcut value = _toggleKey.Value; string english = $"Press {((KeyboardShortcut)(ref value)).MainKey} to close"; value = _toggleKey.Value; GUILayout.Label(T(english, $"按 {((KeyboardShortcut)(ref value)).MainKey} 关闭"), Array.Empty<GUILayoutOption>()); GUILayout.EndVertical(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 28f)); } private static string Truncate(string value, int max) { if (value.Length > max) { return value.Substring(0, max - 1) + "…"; } return value; } private static string Dollars(double value) { return "$" + value.ToString("N0", CultureInfo.InvariantCulture); } private string GetTitles(PlayerRunStats player) { List<string> list = new List<string>(); AddTitle(list, player, "Defective Unit", "残次品", (PlayerRunStats p) => p.Deaths); AddTitle(list, player, "Guardian Angel", "再生父母", (PlayerRunStats p) => p.TeammatesRescued); AddTitle(list, player, "Physics Exorcist", "物理超度师", (PlayerRunStats p) => p.EnemyKills); AddTitle(list, player, "Born to Grind", "天生牛马", (PlayerRunStats p) => p.ExtractedValue); AddTitle(list, player, "Financial Liability", "负资产", (PlayerRunStats p) => p.ValuableDamage); return string.Join(" / ", list); } private void AddTitle(List<string> titles, PlayerRunStats player, string englishTitle, string chineseTitle, Func<PlayerRunStats, double> value) { IReadOnlyList<PlayerRunStats> readOnlyList = Board.Leaders(value, false, (Func<PlayerRunStats, bool>)null); if (readOnlyList.Count != 0 && !(value(readOnlyList[0]) <= 0.0) && readOnlyList.Any((PlayerRunStats leader) => leader.PlayerId == player.PlayerId)) { titles.Add(T(englishTitle, chineseTitle)); } } private static void Column(string text, float width, GUIStyle style) { GUILayout.Label(text, style, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(width) }); } private void BuildVisualTheme() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: 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_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_0179: Expected O, but got Unknown _terminalFont = Font.CreateDynamicFontFromOSFont((!UseChinese()) ? new string[3] { "Consolas", "Courier New", "Arial" } : new string[3] { "SimSun", "Microsoft YaHei", "Arial" }, 16); _panelTexture = SolidTexture(new Color(0.025f, 0.027f, 0.023f, 0.99f)); _screenTexture = SolidTexture(new Color(0.005f, 0.055f, 0.018f, 0.98f)); _borderTexture = SolidTexture(new Color(0.12f, 0.16f, 0.11f, 1f)); _rowTexture = SolidTexture(new Color(0.1f, 0.3f, 0.12f, 0.18f)); _scanlineTexture = SolidTexture(new Color(0f, 0f, 0f, 0.24f)); GUIStyle val = new GUIStyle(GUI.skin.window); val.normal.background = _panelTexture; val.normal.textColor = new Color(0.52f, 1f, 0.52f); val.font = _terminalFont; val.fontStyle = (FontStyle)1; val.alignment = (TextAnchor)1; val.padding = new RectOffset(22, 22, 48, 22); _windowStyle = val; } private void DrawTerminalFrame() { //IL_002c: 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_0098: 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_0108: Unknown result type (might be due to invalid IL or missing references) GUI.DrawTexture(new Rect(10f, 27f, ((Rect)(ref _window)).width - 20f, ((Rect)(ref _window)).height - 37f), (Texture)(object)_borderTexture); GUI.DrawTexture(new Rect(17f, 34f, ((Rect)(ref _window)).width - 34f, ((Rect)(ref _window)).height - 51f), (Texture)(object)_screenTexture); GUI.DrawTexture(new Rect(17f, 34f, ((Rect)(ref _window)).width - 34f, 2f), (Texture)(object)_borderTexture); GUI.DrawTexture(new Rect(17f, ((Rect)(ref _window)).height - 19f, ((Rect)(ref _window)).width - 34f, 2f), (Texture)(object)_borderTexture); for (float num = 36f; num < ((Rect)(ref _window)).height - 20f; num += 3f) { GUI.DrawTexture(new Rect(18f, num, ((Rect)(ref _window)).width - 36f, 1f), (Texture)(object)_scanlineTexture); } } private static Texture2D SolidTexture(Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1); val.SetPixel(0, 0, color); val.Apply(); return val; } private bool UseChinese() { //IL_0064: 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) if (_language.Value.Equals("SimplifiedChinese", StringComparison.OrdinalIgnoreCase) || _language.Value.Equals("Chinese", StringComparison.OrdinalIgnoreCase) || _language.Value.Equals("简体中文", StringComparison.OrdinalIgnoreCase)) { return true; } if (_language.Value.Equals("English", StringComparison.OrdinalIgnoreCase)) { return false; } return ((object)Application.systemLanguage/*cast due to .constrained prefix*/).ToString().IndexOf("Chinese", StringComparison.OrdinalIgnoreCase) >= 0; } private string T(string english, string chinese) { if (!UseChinese()) { return english; } return chinese; } } }