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 ReadyViking v0.1.0
ReadyViking.dll
Decompiled 21 hours agousing System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using ReadyViking.Config; using ReadyViking.Input; using ReadyViking.Models; using ReadyViking.Overlay; using ReadyViking.Runtime; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace ReadyViking.Config { internal sealed class ReadyVikingConfig { public ConfigEntry<KeyboardShortcut> ToggleOverlay { get; private set; } public ConfigEntry<float> AutoHideSeconds { get; private set; } public ConfigEntry<float> WeaponDurabilityWarningPercent { get; private set; } public ConfigEntry<float> OverlayPositionX { get; private set; } public ConfigEntry<float> OverlayPositionY { get; private set; } public ReadyVikingConfig(ConfigFile config) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown ToggleOverlay = config.Bind<KeyboardShortcut>("General", "ToggleOverlay", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Toggle the ReadyViking test overlay."); AutoHideSeconds = config.Bind<float>("General", "AutoHideSeconds", 6f, "Seconds until the overlay hides itself after opening."); WeaponDurabilityWarningPercent = config.Bind<float>("General", "WeaponDurabilityWarningPercent", 25f, new ConfigDescription("Weapon durability percentage at or below which the overlay shows a warning.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); OverlayPositionX = config.Bind<float>("Overlay", "OverlayPositionX", 24f, "Horizontal screen position of the ReadyViking overlay."); OverlayPositionY = config.Bind<float>("Overlay", "OverlayPositionY", 170f, "Vertical screen position of the ReadyViking overlay."); } } } namespace ReadyViking.Input { internal sealed class ReadyVikingInputController { private readonly ConfigEntry<KeyboardShortcut> _toggleOverlay; public ReadyVikingInputController(ConfigEntry<KeyboardShortcut> toggleOverlay) { _toggleOverlay = toggleOverlay; } public bool TogglePressed() { //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 = _toggleOverlay.Value; return ((KeyboardShortcut)(ref value)).IsDown(); } } } namespace ReadyViking.Models { internal sealed class ActiveMealSnapshot { public string Name { get; private set; } public float RemainingSeconds { get; private set; } public ActiveMealSnapshot(string name, float remainingSeconds) { Name = name; RemainingSeconds = remainingSeconds; } } internal sealed class ActiveMealsSnapshot { public CheckState State { get; private set; } public int ActiveMealCount { get; private set; } public IReadOnlyList<ActiveMealSnapshot> Meals { get; private set; } public ActiveMealsSnapshot(CheckState state, int activeMealCount, IReadOnlyList<ActiveMealSnapshot> meals) { State = state; ActiveMealCount = activeMealCount; Meals = meals; } } internal sealed class AmmoSnapshot { public CheckState State { get; private set; } public bool RequiresAmmo { get; private set; } public string AmmoType { get; private set; } public int AvailableAmmo { get; private set; } public AmmoSnapshot(CheckState state, bool requiresAmmo, string ammoType, int availableAmmo) { State = state; RequiresAmmo = requiresAmmo; AmmoType = ammoType; AvailableAmmo = availableAmmo; } } internal sealed class CheckResult { public string Title { get; private set; } public CheckState State { get; private set; } public string Detail { get; private set; } public CheckResult(string title, CheckState state, string detail) { Title = title; State = state; Detail = detail; } } internal enum CheckState { Ready, Warning, Missing, Unknown, NotApplicable } internal sealed class InventorySnapshot { public CheckState SlotsState { get; private set; } public int FreeSlots { get; private set; } public int TotalSlots { get; private set; } public CheckState WeightState { get; private set; } public float CurrentWeight { get; private set; } public float MaxWeight { get; private set; } public InventorySnapshot(CheckState slotsState, int freeSlots, int totalSlots, CheckState weightState, float currentWeight, float maxWeight) { SlotsState = slotsState; FreeSlots = freeSlots; TotalSlots = totalSlots; WeightState = weightState; CurrentWeight = currentWeight; MaxWeight = maxWeight; } } internal sealed class ReadinessReport { public string Headline { get; private set; } public IReadOnlyList<CheckResult> Checks { get; private set; } public ReadinessReport(string headline, IReadOnlyList<CheckResult> checks) { Headline = headline; Checks = checks; } } internal sealed class ReadyVikingSnapshot { public SnapshotStatus LocalPlayerStatus { get; private set; } public ActiveMealsSnapshot ActiveMeals { get; private set; } public WeaponSnapshot Weapon { get; private set; } public RestedSnapshot Rested { get; private set; } public AmmoSnapshot Ammo { get; private set; } public InventorySnapshot Inventory { get; private set; } public bool LocalPlayerAvailable => LocalPlayerStatus == SnapshotStatus.Available; public ReadyVikingSnapshot(SnapshotStatus localPlayerStatus, ActiveMealsSnapshot activeMeals, WeaponSnapshot weapon, RestedSnapshot rested, AmmoSnapshot ammo, InventorySnapshot inventory) { LocalPlayerStatus = localPlayerStatus; ActiveMeals = activeMeals; Weapon = weapon; Rested = rested; Ammo = ammo; Inventory = inventory; } } internal sealed class RestedSnapshot { public CheckState State { get; private set; } public bool IsRested { get; private set; } public float RemainingSeconds { get; private set; } public RestedSnapshot(CheckState state, bool isRested, float remainingSeconds) { State = state; IsRested = isRested; RemainingSeconds = remainingSeconds; } } internal enum SnapshotStatus { Available, Unknown, Unavailable } internal sealed class WeaponSnapshot { public CheckState State { get; private set; } public string Name { get; private set; } public float CurrentDurability { get; private set; } public float MaxDurability { get; private set; } public float DurabilityPercent { get; private set; } public WeaponSnapshot(CheckState state, string name, float currentDurability, float maxDurability, float durabilityPercent) { State = state; Name = name; CurrentDurability = currentDurability; MaxDurability = maxDurability; DurabilityPercent = durabilityPercent; } } } namespace ReadyViking.Overlay { internal sealed class ReadyVikingOverlayView { private const float PanelWidth = 360f; private const float PanelHeight = 220f; private GUIStyle _titleStyle; private GUIStyle _rowStyle; private GUIStyle _detailStyle; private GUIStyle _panelStyle; public void Draw(ReadinessReport report, float positionX, float positionY) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) EnsureStyles(); Rect val = CreateClampedPanelRect(positionX, positionY); GUILayout.BeginArea(val, _panelStyle); GUILayout.Label(report.Headline, _titleStyle, Array.Empty<GUILayoutOption>()); foreach (CheckResult check in report.Checks) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(GetPrefix(check.State), _rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(48f) }); GUILayout.Label(check.Title, _rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }); GUILayout.Label(check.Detail, _detailStyle, Array.Empty<GUILayoutOption>()); GUILayout.EndHorizontal(); } GUILayout.EndArea(); } private static Rect CreateClampedPanelRect(float positionX, float positionY) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(0f, (float)Screen.width - 360f); float num2 = Mathf.Max(0f, (float)Screen.height - 220f); float num3 = Mathf.Clamp(positionX, 0f, num); float num4 = Mathf.Clamp(positionY, 0f, num2); return new Rect(num3, num4, 360f, 220f); } private void EnsureStyles() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown if (_panelStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.box); val.padding = new RectOffset(14, 14, 12, 12); val.margin = new RectOffset(0, 0, 0, 0); _panelStyle = val; val = new GUIStyle(GUI.skin.label); val.fontSize = 18; val.fontStyle = (FontStyle)1; val.richText = true; val.alignment = (TextAnchor)3; _titleStyle = val; val = new GUIStyle(GUI.skin.label); val.fontSize = 13; val.richText = true; val.alignment = (TextAnchor)3; _rowStyle = val; val = new GUIStyle(GUI.skin.label); val.fontSize = 13; val.richText = true; val.alignment = (TextAnchor)3; _detailStyle = val; } } private static string GetPrefix(CheckState state) { return state switch { CheckState.Ready => "<color=#8BC34A>OK</color>", CheckState.Warning => "<color=#FFC107>WARN</color>", CheckState.Missing => "<color=#EF5350>MISS</color>", CheckState.Unknown => "<color=#B0BEC5>UNK</color>", CheckState.NotApplicable => "<color=#90A4AE>N/A</color>", _ => "<color=#B0BEC5>UNK</color>", }; } } } namespace ReadyViking { [BepInPlugin("com.goblinstudio.readyviking", "ReadyViking", "0.1.0")] public sealed class Plugin : BaseUnityPlugin { private ReadyVikingConfig _config; private ReadyVikingInputController _input; private ReadyVikingOverlayView _overlayView; private ReadyVikingSnapshotCollector _snapshotCollector; private ReadinessReport _currentReport; private bool _isVisible; private float _openedAt; private void Awake() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) _config = new ReadyVikingConfig(((BaseUnityPlugin)this).Config); _input = new ReadyVikingInputController(_config.ToggleOverlay); _overlayView = new ReadyVikingOverlayView(); _snapshotCollector = new ReadyVikingSnapshotCollector(); _currentReport = StaticTestReportFactory.Create(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[ReadyViking] loaded v0.1.0"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[ReadyViking] Hotkey: " + _config.ToggleOverlay.Value)); } private void Update() { if (_input != null && _config != null) { if (_input.TogglePressed()) { ToggleOverlay(); } if (_isVisible && Time.realtimeSinceStartup - _openedAt >= Mathf.Max(0.25f, _config.AutoHideSeconds.Value)) { _isVisible = false; } } } private void OnGUI() { if (_isVisible && _overlayView != null && _currentReport != null) { _overlayView.Draw(_currentReport, _config.OverlayPositionX.Value, _config.OverlayPositionY.Value); } } private void ToggleOverlay() { _isVisible = !_isVisible; _openedAt = Time.realtimeSinceStartup; if (_isVisible) { ReadyVikingSnapshot readyVikingSnapshot = _snapshotCollector.Collect(); _currentReport = StaticTestReportFactory.Create(readyVikingSnapshot.ActiveMeals, readyVikingSnapshot.Weapon, _config.WeaponDurabilityWarningPercent.Value, readyVikingSnapshot.Rested, readyVikingSnapshot.Ammo, readyVikingSnapshot.Inventory); string text = ((readyVikingSnapshot.LocalPlayerStatus != SnapshotStatus.Available) ? "Unavailable" : "Available"); string text2 = ((!readyVikingSnapshot.LocalPlayerAvailable) ? "no" : "yes"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[ReadyViking] Snapshot status: " + text + "; local player available: " + text2)); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("[ReadyViking] Weapon snapshot: state=", readyVikingSnapshot.Weapon.State, "; name=", readyVikingSnapshot.Weapon.Name, "; current=", readyVikingSnapshot.Weapon.CurrentDurability, "; max=", readyVikingSnapshot.Weapon.MaxDurability, "; percent=", readyVikingSnapshot.Weapon.DurabilityPercent)); string text3 = ((!readyVikingSnapshot.Rested.IsRested) ? "no" : "yes"); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("[ReadyViking] Rested snapshot: state=", readyVikingSnapshot.Rested.State, "; rested=", text3, "; remaining=", readyVikingSnapshot.Rested.RemainingSeconds)); string text4 = ((!readyVikingSnapshot.Ammo.RequiresAmmo) ? "no" : "yes"); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("[ReadyViking] Ammo snapshot: state=", readyVikingSnapshot.Ammo.State, "; required=", text4, "; type=", readyVikingSnapshot.Ammo.AmmoType, "; available=", readyVikingSnapshot.Ammo.AvailableAmmo)); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("[ReadyViking] Inventory snapshot: slotsState=", readyVikingSnapshot.Inventory.SlotsState, "; free=", readyVikingSnapshot.Inventory.FreeSlots, "; total=", readyVikingSnapshot.Inventory.TotalSlots, "; weightState=", readyVikingSnapshot.Inventory.WeightState, "; current=", readyVikingSnapshot.Inventory.CurrentWeight, "; max=", readyVikingSnapshot.Inventory.MaxWeight)); } } } internal static class PluginInfo { public const string Guid = "com.goblinstudio.readyviking"; public const string Name = "ReadyViking"; public const string Version = "0.1.0"; } } namespace ReadyViking.Runtime { internal sealed class ReadyVikingSnapshotCollector { public ReadyVikingSnapshot Collect() { //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_0655: Unknown result type (might be due to invalid IL or missing references) //IL_074c: Unknown result type (might be due to invalid IL or missing references) //IL_0751: Unknown result type (might be due to invalid IL or missing references) //IL_0753: Unknown result type (might be due to invalid IL or missing references) //IL_0757: Invalid comparison between Unknown and I4 //IL_075c: Unknown result type (might be due to invalid IL or missing references) //IL_0760: Invalid comparison between Unknown and I4 //IL_0765: Unknown result type (might be due to invalid IL or missing references) //IL_0768: Invalid comparison between Unknown and I4 Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return new ReadyVikingSnapshot(SnapshotStatus.Unavailable, new ActiveMealsSnapshot(CheckState.NotApplicable, 0, new List<ActiveMealSnapshot>()), new WeaponSnapshot(CheckState.NotApplicable, string.Empty, 0f, 0f, 0f), new RestedSnapshot(CheckState.NotApplicable, isRested: false, 0f), new AmmoSnapshot(CheckState.NotApplicable, requiresAmmo: false, string.Empty, 0), new InventorySnapshot(CheckState.NotApplicable, 0, 0, CheckState.NotApplicable, 0f, 0f)); } Inventory val = null; bool flag = false; try { val = ((Humanoid)localPlayer).GetInventory(); flag = true; } catch (Exception) { val = null; } InventorySnapshot inventory; if (!flag || val == null) { inventory = new InventorySnapshot(CheckState.Unknown, 0, 0, CheckState.Unknown, 0f, 0f); } else { int num = 0; int num2 = 0; CheckState slotsState; try { int emptySlots = val.GetEmptySlots(); int width = val.GetWidth(); int height = val.GetHeight(); long num3 = (long)width * (long)height; if (width < 0 || height < 0 || num3 < 0 || num3 > int.MaxValue || emptySlots < 0 || emptySlots > num3) { throw new InvalidOperationException("Invalid inventory slot data"); } slotsState = CheckState.Ready; num = emptySlots; num2 = (int)num3; } catch (Exception) { slotsState = CheckState.Unknown; num = 0; num2 = 0; } float num4 = 0f; float num5 = 0f; CheckState weightState; try { float totalWeight = val.GetTotalWeight(); float maxCarryWeight = localPlayer.GetMaxCarryWeight(); if (float.IsNaN(totalWeight) || float.IsInfinity(totalWeight) || totalWeight < 0f || float.IsNaN(maxCarryWeight) || float.IsInfinity(maxCarryWeight) || maxCarryWeight <= 0f) { throw new InvalidOperationException("Invalid inventory weight data"); } weightState = CheckState.Ready; num4 = totalWeight; num5 = maxCarryWeight; } catch (Exception) { weightState = CheckState.Unknown; num4 = 0f; num5 = 0f; } inventory = new InventorySnapshot(slotsState, num, num2, weightState, num4, num5); } ActiveMealsSnapshot activeMeals; try { List<Food> foods = localPlayer.GetFoods(); if (foods == null) { activeMeals = new ActiveMealsSnapshot(CheckState.Unknown, 0, new List<ActiveMealSnapshot>()); } else { List<ActiveMealSnapshot> list = new List<ActiveMealSnapshot>(foods.Count); bool flag2 = true; foreach (Food item in foods) { if (item == null || string.IsNullOrWhiteSpace(item.m_name) || float.IsNaN(item.m_time) || float.IsInfinity(item.m_time) || item.m_time < 0f) { flag2 = false; break; } list.Add(new ActiveMealSnapshot(item.m_name, item.m_time)); } if (!flag2) { activeMeals = new ActiveMealsSnapshot(CheckState.Unknown, 0, new List<ActiveMealSnapshot>()); } else { CheckState state = ((list.Count == 0) ? CheckState.Missing : ((list.Count < 3) ? CheckState.Warning : CheckState.Ready)); activeMeals = new ActiveMealsSnapshot(state, list.Count, list); } } } catch (Exception) { activeMeals = new ActiveMealsSnapshot(CheckState.Unknown, 0, new List<ActiveMealSnapshot>()); } ItemData val2 = null; SharedData val3 = null; bool flag3 = false; bool flag4 = false; bool flag5 = false; WeaponSnapshot weapon; try { val2 = ((Humanoid)localPlayer).GetCurrentWeapon(); flag3 = true; if (val2 == null) { weapon = new WeaponSnapshot(CheckState.NotApplicable, string.Empty, 0f, 0f, 0f); } else { val3 = val2.m_shared; if (val3 == null) { weapon = new WeaponSnapshot(CheckState.Unknown, string.Empty, 0f, 0f, 0f); } else if (string.IsNullOrWhiteSpace(val3.m_name)) { weapon = new WeaponSnapshot(CheckState.Unknown, string.Empty, 0f, 0f, 0f); } else { flag5 = val2.IsWeapon(); flag4 = true; if (!flag5) { weapon = (((int)val3.m_itemType != 0) ? new WeaponSnapshot(CheckState.Unknown, val3.m_name, 0f, 0f, 0f) : new WeaponSnapshot(CheckState.NotApplicable, val3.m_name, 0f, 0f, 0f)); } else if (!val3.m_useDurability) { weapon = new WeaponSnapshot(CheckState.NotApplicable, val3.m_name, 0f, 0f, 0f); } else { float durability = val2.m_durability; float maxDurability = val2.GetMaxDurability(); if (float.IsNaN(durability) || float.IsInfinity(durability) || durability < 0f || float.IsNaN(maxDurability) || float.IsInfinity(maxDurability) || maxDurability <= 0f || durability > maxDurability) { weapon = new WeaponSnapshot(CheckState.Unknown, val3.m_name, 0f, 0f, 0f); } else { float durabilityPercent = Mathf.Clamp(durability / maxDurability * 100f, 0f, 100f); weapon = new WeaponSnapshot(CheckState.Ready, val3.m_name, durability, maxDurability, durabilityPercent); } } } } } catch (Exception) { weapon = new WeaponSnapshot(CheckState.Unknown, string.Empty, 0f, 0f, 0f); } RestedSnapshot rested; try { SEMan sEMan = ((Character)localPlayer).GetSEMan(); if (sEMan == null) { rested = new RestedSnapshot(CheckState.Unknown, isRested: false, 0f); } else { StatusEffect statusEffect = sEMan.GetStatusEffect(SEMan.s_statusEffectRested); if ((Object)(object)statusEffect == (Object)null) { rested = new RestedSnapshot(CheckState.Missing, isRested: false, 0f); } else { float remaningTime = statusEffect.GetRemaningTime(); rested = ((!float.IsNaN(remaningTime) && !float.IsInfinity(remaningTime) && !(remaningTime <= 0f)) ? new RestedSnapshot(CheckState.Ready, isRested: true, remaningTime) : new RestedSnapshot(CheckState.Unknown, isRested: false, 0f)); } } } catch (Exception) { rested = new RestedSnapshot(CheckState.Unknown, isRested: false, 0f); } string text = string.Empty; bool requiresAmmo = false; AmmoSnapshot ammo; try { if (!flag3) { ammo = new AmmoSnapshot(CheckState.Unknown, requiresAmmo: false, string.Empty, 0); } else if (val2 == null) { ammo = new AmmoSnapshot(CheckState.NotApplicable, requiresAmmo: false, string.Empty, 0); } else if (val3 == null || !flag4) { ammo = new AmmoSnapshot(CheckState.Unknown, requiresAmmo: false, string.Empty, 0); } else if (!flag5) { ammo = (((int)val3.m_itemType != 0) ? new AmmoSnapshot(CheckState.Unknown, requiresAmmo: false, string.Empty, 0) : new AmmoSnapshot(CheckState.NotApplicable, requiresAmmo: false, string.Empty, 0)); } else { text = val3.m_ammoType; if (string.IsNullOrWhiteSpace(text)) { ammo = new AmmoSnapshot(CheckState.NotApplicable, requiresAmmo: false, string.Empty, 0); } else { requiresAmmo = true; if (!flag || val == null) { ammo = new AmmoSnapshot(CheckState.Unknown, requiresAmmo: true, text, 0); } else { List<ItemData> allItems = val.GetAllItems(); if (allItems == null) { ammo = new AmmoSnapshot(CheckState.Unknown, requiresAmmo: true, text, 0); } else { long num6 = 0L; bool flag6 = false; foreach (ItemData item2 in allItems) { if (item2 == null || item2.m_shared == null) { flag6 = true; break; } if (!string.Equals(item2.m_shared.m_ammoType, text, StringComparison.Ordinal)) { continue; } ItemType itemType = item2.m_shared.m_itemType; if ((int)itemType != 9 && (int)itemType != 23 && (int)itemType != 2) { if (item2.IsWeapon()) { continue; } flag6 = true; break; } if (item2.m_stack <= 0) { flag6 = true; break; } num6 += item2.m_stack; if (num6 <= int.MaxValue) { continue; } flag6 = true; break; } ammo = (flag6 ? new AmmoSnapshot(CheckState.Unknown, requiresAmmo: true, text, 0) : ((num6 <= 0) ? new AmmoSnapshot(CheckState.Missing, requiresAmmo: true, text, 0) : new AmmoSnapshot(CheckState.Ready, requiresAmmo: true, text, (int)num6))); } } } } } catch (Exception) { ammo = new AmmoSnapshot(CheckState.Unknown, requiresAmmo, text, 0); } return new ReadyVikingSnapshot(SnapshotStatus.Available, activeMeals, weapon, rested, ammo, inventory); } } internal static class StaticTestReportFactory { public static ReadinessReport Create() { return CreateReport(new CheckResult("Meals", CheckState.Ready, "Three active meals")); } public static ReadinessReport Create(ActiveMealsSnapshot activeMeals, WeaponSnapshot weapon, float weaponDurabilityWarningPercent, RestedSnapshot rested, AmmoSnapshot ammo, InventorySnapshot inventory) { return CreateReport(new CheckResult(string.Empty, activeMeals.State, CreateActiveMealsDetail(activeMeals)), CreateWeaponCheck(weapon, weaponDurabilityWarningPercent), CreateRestedCheck(rested), CreateAmmoCheck(ammo), CreateInventoryCheck(inventory)); } private static ReadinessReport CreateReport(CheckResult mealsCheck, CheckResult weaponCheck = null, CheckResult restedCheck = null, CheckResult ammoCheck = null, CheckResult inventoryCheck = null) { if (weaponCheck == null) { weaponCheck = new CheckResult("Weapon", CheckState.Warning, "Sword durability: 28%"); } if (restedCheck == null) { restedCheck = new CheckResult("Rested", CheckState.Ready, "14 min"); } if (ammoCheck == null) { ammoCheck = new CheckResult("Ammo", CheckState.Missing, "No matching ammunition"); } if (inventoryCheck == null) { inventoryCheck = new CheckResult("Inventory", CheckState.Unknown, "Inventory status unknown"); } return new ReadinessReport("READY TO LEAVE?", new List<CheckResult> { mealsCheck, restedCheck, weaponCheck, ammoCheck, inventoryCheck }); } private static string CreateActiveMealsDetail(ActiveMealsSnapshot activeMeals) { switch (activeMeals.State) { case CheckState.Ready: case CheckState.Warning: case CheckState.Missing: return "Active meals: " + activeMeals.ActiveMealCount; case CheckState.NotApplicable: return "Active meals unavailable"; default: return "Active meals unknown"; } } private static CheckResult CreateRestedCheck(RestedSnapshot rested) { if (rested == null) { return new CheckResult(string.Empty, CheckState.Unknown, "Rested status unknown"); } switch (rested.State) { case CheckState.Ready: { if (!rested.IsRested || float.IsNaN(rested.RemainingSeconds) || float.IsInfinity(rested.RemainingSeconds) || rested.RemainingSeconds <= 0f) { return new CheckResult(string.Empty, CheckState.Unknown, "Rested status unknown"); } int num = Mathf.Max(1, Mathf.FloorToInt(rested.RemainingSeconds / 60f)); return new CheckResult(string.Empty, CheckState.Ready, "Rested: " + num + " min"); } case CheckState.Missing: return new CheckResult(string.Empty, CheckState.Missing, "Rested not active"); case CheckState.NotApplicable: return new CheckResult(string.Empty, CheckState.NotApplicable, "Rested unavailable"); default: return new CheckResult(string.Empty, CheckState.Unknown, "Rested status unknown"); } } private static CheckResult CreateAmmoCheck(AmmoSnapshot ammo) { if (ammo == null) { return new CheckResult(string.Empty, CheckState.Unknown, "Ammo status unknown"); } switch (ammo.State) { case CheckState.Ready: if (!ammo.RequiresAmmo || string.IsNullOrWhiteSpace(ammo.AmmoType) || ammo.AvailableAmmo <= 0) { return new CheckResult(string.Empty, CheckState.Unknown, "Ammo status unknown"); } return new CheckResult(string.Empty, CheckState.Ready, "Ammo: " + ammo.AvailableAmmo); case CheckState.Missing: if (!ammo.RequiresAmmo || string.IsNullOrWhiteSpace(ammo.AmmoType) || ammo.AvailableAmmo != 0) { return new CheckResult(string.Empty, CheckState.Unknown, "Ammo status unknown"); } return new CheckResult(string.Empty, CheckState.Missing, "Ammo: none"); case CheckState.NotApplicable: if (ammo.RequiresAmmo || !string.IsNullOrWhiteSpace(ammo.AmmoType) || ammo.AvailableAmmo != 0) { return new CheckResult(string.Empty, CheckState.Unknown, "Ammo status unknown"); } return new CheckResult(string.Empty, CheckState.NotApplicable, "Ammo not applicable"); default: return new CheckResult(string.Empty, CheckState.Unknown, "Ammo status unknown"); } } private static CheckResult CreateInventoryCheck(InventorySnapshot inventory) { if (inventory == null) { return new CheckResult(string.Empty, CheckState.Unknown, "Inventory status unknown"); } bool flag = inventory.SlotsState == CheckState.Ready && inventory.FreeSlots >= 0 && inventory.TotalSlots >= 0 && inventory.FreeSlots <= inventory.TotalSlots; bool flag2 = inventory.WeightState == CheckState.Ready && !float.IsNaN(inventory.CurrentWeight) && !float.IsInfinity(inventory.CurrentWeight) && inventory.CurrentWeight >= 0f && !float.IsNaN(inventory.MaxWeight) && !float.IsInfinity(inventory.MaxWeight) && inventory.MaxWeight > 0f; bool flag3 = inventory.SlotsState == CheckState.NotApplicable && inventory.FreeSlots == 0 && inventory.TotalSlots == 0; bool flag4 = inventory.WeightState == CheckState.NotApplicable && inventory.CurrentWeight == 0f && inventory.MaxWeight == 0f; bool flag5 = inventory.SlotsState == CheckState.Unknown && inventory.FreeSlots == 0 && inventory.TotalSlots == 0; bool flag6 = inventory.WeightState == CheckState.Unknown && inventory.CurrentWeight == 0f && inventory.MaxWeight == 0f; if (flag && flag2) { CheckState state = ((inventory.FreeSlots == 0 || inventory.CurrentWeight >= inventory.MaxWeight) ? CheckState.Warning : CheckState.Ready); return new CheckResult(string.Empty, state, "Inventory: " + inventory.FreeSlots + " free | " + FormatWeight(inventory.CurrentWeight) + "/" + FormatWeight(inventory.MaxWeight)); } if (flag3 && flag4) { return new CheckResult(string.Empty, CheckState.NotApplicable, "Inventory unavailable"); } if (flag && flag6) { return new CheckResult(string.Empty, CheckState.Unknown, "Inventory: " + inventory.FreeSlots + " free | weight unknown"); } if (flag2 && flag5) { return new CheckResult(string.Empty, CheckState.Unknown, "Inventory: slots unknown | " + FormatWeight(inventory.CurrentWeight) + "/" + FormatWeight(inventory.MaxWeight)); } return new CheckResult(string.Empty, CheckState.Unknown, "Inventory status unknown"); } private static string FormatWeight(float value) { return value.ToString("0.#", CultureInfo.CurrentCulture); } private static CheckResult CreateWeaponCheck(WeaponSnapshot weapon, float warningPercent) { if (weapon == null) { return new CheckResult(string.Empty, CheckState.Unknown, "Weapon status unknown"); } string displayName = GetDisplayName(weapon.Name); switch (weapon.State) { case CheckState.Ready: { if (string.IsNullOrWhiteSpace(displayName)) { return new CheckResult(string.Empty, CheckState.Unknown, "Weapon status unknown"); } float num = Mathf.Clamp(weapon.DurabilityPercent, 0f, 100f); int num2 = Mathf.RoundToInt(num); CheckState state = ((num <= Mathf.Clamp(warningPercent, 0f, 100f)) ? CheckState.Warning : CheckState.Ready); return new CheckResult(string.Empty, state, displayName + ": " + num2 + "%"); } case CheckState.NotApplicable: if (string.IsNullOrWhiteSpace(displayName) || IsUnarmedName(weapon.Name)) { return new CheckResult(string.Empty, CheckState.NotApplicable, "No weapon equipped"); } return new CheckResult(string.Empty, CheckState.NotApplicable, displayName + ": no durability"); case CheckState.Unknown: if (string.IsNullOrWhiteSpace(displayName)) { return new CheckResult(string.Empty, CheckState.Unknown, "Weapon status unknown"); } return new CheckResult(string.Empty, CheckState.Unknown, displayName + ": durability unknown"); default: return new CheckResult(string.Empty, CheckState.Unknown, "Weapon status unknown"); } } private static string GetDisplayName(string copiedName) { if (string.IsNullOrWhiteSpace(copiedName)) { return string.Empty; } if (!copiedName.StartsWith("$")) { return copiedName; } try { if (Localization.instance != null) { string text = Localization.instance.Localize(copiedName); if (!string.IsNullOrWhiteSpace(text) && !text.StartsWith("$")) { return text; } } } catch { } return copiedName; } private static bool IsUnarmedName(string copiedName) { return string.Equals(copiedName, "Unarmed", StringComparison.OrdinalIgnoreCase); } } }