Decompiled source of DescriptiveWeaponStatShower v2.0.1

WeaponStatShower.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
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.Json;
using System.Text.Json.Serialization;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using GTFO.API.Utilities;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Localization;
using MTFO.API;
using MTFO.Ext.PartialData;
using MTFO.Ext.PartialData.JsonConverters;
using Microsoft.CodeAnalysis;
using Player;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using WeaponStatShower.Dependencies;
using WeaponStatShower.ExtraDescription;
using WeaponStatShower.ExtraDescription.Data;
using WeaponStatShower.Json;
using WeaponStatShower.Json.Converters.Utils;
using WeaponStatShower.Patches;
using WeaponStatShower.Utils;
using WeaponStatShower.Utils.Extensions;
using WeaponStatShower.Utils.Language;
using WeaponStatShower.Utils.Language.Models;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("WeaponStatShower")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+75aa869cf995234f6c582c07759bee1e5af89b9a")]
[assembly: AssemblyProduct("WeaponStatShower")]
[assembly: AssemblyTitle("WeaponStatShower")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
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;
		}
	}
}
namespace WeaponStatShower
{
	public static class BIEExtensions
	{
		public static ConfigEntry<T> GetConfigEntry<T>(this ConfigFile configFile, ConfigDefinition definition)
		{
			ConfigEntry<T> result = default(ConfigEntry<T>);
			if (!configFile.TryGetEntry<T>(definition, ref result))
			{
				throw new InvalidOperationException("Config entry has not been added yet.");
			}
			return result;
		}
	}
	[BepInPlugin("WeaponStatShower", "Weapon Stat Shower", "2.0.1")]
	[BepInProcess("GTFO.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class WeaponStatShowerPlugin : BasePlugin
	{
		private enum ShowStatSetting
		{
			False,
			True,
			Force
		}

		public enum StatsPosition
		{
			Last,
			First,
			Combined
		}

		internal const string ModName = "Weapon Stat Shower";

		internal const string GUID = "WeaponStatShower";

		private const string SectionMain = "Config";

		private static readonly ConfigDefinition ConfigDefinition = new ConfigDefinition("Config", "Version");

		private static readonly ConfigDefinition ConfigGameVersion = new ConfigDefinition("Config", "GameVersion");

		private static Harmony? HarmonyInstance;

		private static readonly Dictionary<Type, Patch> RegisteredPatches = new Dictionary<Type, Patch>();

		private static ConfigEntry<LanguageEnum> _configLanguage = null;

		private static ConfigEntry<string> _sleepersShown = null;

		private static ConfigEntry<ShowStatSetting> _showStats = null;

		private static ConfigEntry<StatsPosition> _statsPosition = null;

		public static WeaponStatShowerPlugin Instance { get; private set; }

		internal static bool ShowStats
		{
			get
			{
				if (_showStats.Value != ShowStatSetting.Force)
				{
					if (_showStats.Value == ShowStatSetting.True)
					{
						return !DescriptionDataManager.Current.GlobalSettings.PreferHideStats;
					}
					return false;
				}
				return true;
			}
		}

		internal static string SleepersShown => _sleepersShown.Value.Trim().ToUpper();

		internal static LanguageEnum ConfigLanguage => _configLanguage.Value;

		internal static StatsPosition StatsLocation => _statsPosition.Value;

		public override void Load()
		{
			Instance = this;
			((BasePlugin)this).Config.SaveOnConfigSet = true;
			LogInfo("STARTED");
			DescriptionDataManager.Current.Init();
			RegisterPatch<DescriptionToggle>();
			BuildConfig(((BasePlugin)this).Config);
		}

		public static void RegisterPatch<T>() where T : Patch, new()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (HarmonyInstance == null)
			{
				HarmonyInstance = new Harmony("WeaponStatShower");
			}
			if (RegisteredPatches.TryGetValue(typeof(T), out Patch _))
			{
				LogDebug("Ignoring duplicate patch: " + typeof(T).Name);
				return;
			}
			T val = new T
			{
				Harmony = HarmonyInstance
			};
			val.Initialize();
			if (val.Enabled)
			{
				LogInfo("Applying patch: " + val.Name);
				val.Execute();
			}
			RegisteredPatches[typeof(T)] = val;
		}

		public static void LogDebug(object data)
		{
			((BasePlugin)Instance).Log.LogDebug(data);
		}

		public static void LogError(object data)
		{
			((BasePlugin)Instance).Log.LogError(data);
		}

		public static void LogFatal(object data)
		{
			((BasePlugin)Instance).Log.LogFatal(data);
		}

		public static void LogInfo(object data)
		{
			((BasePlugin)Instance).Log.LogInfo(data);
		}

		public static void LogMessage(object data)
		{
			((BasePlugin)Instance).Log.LogMessage(data);
		}

		public static void LogWarning(object data)
		{
			((BasePlugin)Instance).Log.LogWarning(data);
		}

		private static void BuildConfig(ConfigFile file)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			string text = "ShowStat";
			_configLanguage = file.Bind<LanguageEnum>(text, "Language", LanguageEnum.English, "Select the mod language.");
			_sleepersShown = file.Bind<string>(text, "SleepersShown", "NONE", "Select which Sleepers are shown, seperated by a comma.\nAcceptable values: ALL, NONE, STRIKER, SHOOTER, SCOUT, BIG_STRIKER, BIG_SHOOTER, CHARGER, CHARGER_SCOUT");
			_showStats = file.Bind<ShowStatSetting>(text, "ShowStats", ShowStatSetting.True, "Add a description tab with auto-generated weapon stats.\nForce will always create a tab, even if the rundown developer disables it.");
			_statsPosition = file.Bind<StatsPosition>(text, "StatsPosition", StatsPosition.Last, "Which tab to place the auto-generated weapon stats.\nCombined will combine it with the normal description, similar to older versions.");
			string? directoryName = Path.GetDirectoryName(file.ConfigFilePath);
			string fileName = Path.GetFileName(file.ConfigFilePath);
			LiveEdit.CreateListener(directoryName, fileName, false).FileChanged += (LiveEditEventHandler)delegate
			{
				file.Reload();
			};
		}
	}
}
namespace WeaponStatShower.Utils
{
	internal static class ArchetypeUtil
	{
		internal static ArchetypeDataBlock? GetArchetypeDataBlock(GearIDRange idRange, uint categoryID, GearCategoryDataBlock gearCatBlock)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			eWeaponFireMode val = (eWeaponFireMode)idRange.GetCompID((eGearComponent)1);
			if (categoryID != 12)
			{
				return GameDataBlockBase<ArchetypeDataBlock>.GetBlock(GearBuilder.GetArchetypeID(gearCatBlock, val));
			}
			return SentryGunInstance_Firing_Bullets.GetArchetypeDataForFireMode(val);
		}

		internal static ArchetypeDataBlock? GetMappedArchetypeDataBlock(GearIDRange idRange, uint categoryID, GearCategoryDataBlock gearCatBlock)
		{
			//IL_0007: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected I4, but got Unknown
			//IL_0050: 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_002d: 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_0035: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			eWeaponFireMode val = (eWeaponFireMode)idRange.GetCompID((eGearComponent)1);
			bool flag = categoryID == 12;
			if (!flag)
			{
				val = (eWeaponFireMode)((val - 10) switch
				{
					0 => 0, 
					1 => 2, 
					2 => 1, 
					3 => 0, 
					_ => val, 
				});
			}
			if (!flag)
			{
				return GameDataBlockBase<ArchetypeDataBlock>.GetBlock(GearBuilder.GetArchetypeID(gearCatBlock, val));
			}
			return SentryGunInstance_Firing_Bullets.GetArchetypeDataForFireMode(val);
		}
	}
	[JsonConverter(typeof(LocaleTextConverter))]
	public struct LocaleText : IEquatable<LocaleText>
	{
		public uint ID;

		public string RawText;

		public static readonly LocaleText Empty = new LocaleText(string.Empty);

		private readonly string TextFallback
		{
			get
			{
				if (ID != 0)
				{
					return Text.Get(ID);
				}
				return RawText;
			}
		}

		public LocaleText(LocalizedText baseText)
		{
			ID = 0u;
			RawText = string.Empty;
			RawText = LocalizedToText(baseText);
			ID = baseText.Id;
		}

		public LocaleText(string text)
		{
			ID = 0u;
			RawText = string.Empty;
			if (PartialData.TryGetGUID(text, out var guid))
			{
				RawText = string.Empty;
				ID = guid;
			}
			else
			{
				RawText = text;
				ID = 0u;
			}
		}

		public LocaleText(uint id)
		{
			ID = 0u;
			RawText = string.Empty;
			RawText = string.Empty;
			ID = id;
		}

		public readonly LocalizedText ToLocalizedText()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return new LocalizedText
			{
				Id = ID,
				UntranslatedText = TextFallback
			};
		}

		public override readonly string ToString()
		{
			return TextFallback;
		}

		public static string LocalizedToText(LocalizedText text)
		{
			if (!text.HasTranslation)
			{
				return text.UntranslatedText;
			}
			return Text.Get(text.Id);
		}

		public static explicit operator LocaleText(LocalizedText localizedText)
		{
			return new LocaleText(localizedText);
		}

		public static explicit operator LocaleText(string text)
		{
			return new LocaleText(text);
		}

		public static implicit operator LocalizedText(LocaleText localeText)
		{
			return localeText.ToLocalizedText();
		}

		public static implicit operator string(LocaleText localeText)
		{
			return localeText.ToString();
		}

		public readonly bool Equals(LocaleText other)
		{
			if (ID == other.ID)
			{
				return string.Equals(RawText, other.RawText, StringComparison.Ordinal);
			}
			return false;
		}

		public override readonly bool Equals(object? obj)
		{
			if (obj is LocaleText other)
			{
				return Equals(other);
			}
			return false;
		}

		public override readonly int GetHashCode()
		{
			return HashCode.Combine(ID, RawText);
		}

		public static bool operator ==(LocaleText left, LocaleText right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(LocaleText left, LocaleText right)
		{
			return !(left == right);
		}
	}
	internal class SleepersDatas
	{
		private readonly struct EnemyData
		{
			public readonly float Health;

			public readonly float HeadMultiplier;

			public readonly float BackMultiplier;

			public readonly bool IsArmored;

			public EnemyData(float health, float headMultiplier, float backMultiplier, bool isArmored)
			{
				Health = health;
				HeadMultiplier = headMultiplier;
				BackMultiplier = backMultiplier;
				IsArmored = isArmored;
			}
		}

		private readonly Dictionary<string, EnemyData> _enemyDatas = new Dictionary<string, EnemyData>();

		private readonly SleepersLanguageModel sleepersLanguageDatas;

		public SleepersDatas(string[] activatedSleepers, SleepersLanguageModel sleepersLanguageDatas)
		{
			this.sleepersLanguageDatas = sleepersLanguageDatas;
			for (int i = 0; i < activatedSleepers.Length; i++)
			{
				string text = activatedSleepers[i].Trim();
				switch (text)
				{
				case "DETAILS_ONLY":
				case "DESCRIPTION_ONLY":
				case "NONE":
					_enemyDatas.Clear();
					return;
				case "ALL":
					_enemyDatas.Clear();
					_enemyDatas.TryAdd(sleepersLanguageDatas.striker, new EnemyData(20f, 3f, 2f, isArmored: false));
					_enemyDatas.TryAdd(sleepersLanguageDatas.shooter, new EnemyData(30f, 5f, 2f, isArmored: false));
					_enemyDatas.TryAdd(sleepersLanguageDatas.scout, new EnemyData(42f, 3f, 2f, isArmored: false));
					_enemyDatas.TryAdd(sleepersLanguageDatas.bigStriker, new EnemyData(120f, 1.5f, 2f, isArmored: false));
					_enemyDatas.TryAdd(sleepersLanguageDatas.bigShooter, new EnemyData(150f, 2f, 2f, isArmored: false));
					_enemyDatas.TryAdd(sleepersLanguageDatas.charger, new EnemyData(30f, 1f, 2f, isArmored: true));
					_enemyDatas.TryAdd(sleepersLanguageDatas.chargerScout, new EnemyData(60f, 1f, 2f, isArmored: true));
					return;
				case "STRIKER":
					_enemyDatas.TryAdd(sleepersLanguageDatas.striker, new EnemyData(20f, 3f, 2f, isArmored: false));
					break;
				case "SHOOTER":
					_enemyDatas.TryAdd(sleepersLanguageDatas.shooter, new EnemyData(30f, 5f, 2f, isArmored: false));
					break;
				case "SCOUT":
					_enemyDatas.TryAdd(sleepersLanguageDatas.scout, new EnemyData(42f, 3f, 2f, isArmored: false));
					break;
				case "BIG_STRIKER":
					_enemyDatas.TryAdd(sleepersLanguageDatas.bigStriker, new EnemyData(120f, 1.5f, 2f, isArmored: false));
					break;
				case "BIG_SHOOTER":
					_enemyDatas.TryAdd(sleepersLanguageDatas.bigShooter, new EnemyData(150f, 2f, 2f, isArmored: false));
					break;
				case "CHARGER":
					_enemyDatas.TryAdd(sleepersLanguageDatas.charger, new EnemyData(30f, 1f, 2f, isArmored: true));
					break;
				case "CHARGER_SCOUT":
					_enemyDatas.TryAdd(sleepersLanguageDatas.chargerScout, new EnemyData(60f, 1f, 2f, isArmored: true));
					break;
				default:
					WeaponStatShowerPlugin.LogWarning("You inserted an incorrect value in the config: " + text);
					break;
				}
			}
		}

		public string VerboseKill(ArchetypeDataBlock archetypeDB)
		{
			float damage = archetypeDB.Damage * (float)((archetypeDB.ShotgunBulletCount <= 0) ? 1 : archetypeDB.ShotgunBulletCount);
			float precisionDamageMulti = archetypeDB.PrecisionDamageMulti;
			return BuildKillString(precisionDamageMulti, (string _, EnemyData __) => damage);
		}

		internal string? VerboseKill(MeleeArchetypeDataBlock meleeArchetypeDB)
		{
			float baseDamage = meleeArchetypeDB.ChargedAttackDamage * meleeArchetypeDB.ChargedSleeperMulti;
			float chargedPrecisionMulti = meleeArchetypeDB.ChargedPrecisionMulti;
			return BuildKillString(chargedPrecisionMulti, delegate(string enemyName, EnemyData _)
			{
				float num = baseDamage;
				if (enemyName.Contains("SCOUT") || enemyName.Contains("哨兵") || enemyName.Contains("黑触"))
				{
					num /= meleeArchetypeDB.ChargedSleeperMulti;
				}
				return num;
			});
		}

		private string BuildKillString(float prcnMult, Func<string, EnemyData, float> getDamage)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			int num2 = 0;
			int num3 = _enemyDatas.Count - 1;
			foreach (KeyValuePair<string, EnemyData> enemyData2 in _enemyDatas)
			{
				enemyData2.Deconstruct(out var key, out var value);
				string text = key;
				EnemyData enemyData = value;
				float damage = getDamage(text, enemyData);
				List<string> list = new List<string>(4);
				if (canKillOnOccipit(damage, prcnMult, enemyData))
				{
					list.Add(sleepersLanguageDatas.occipit);
				}
				if (canKillOnHead(damage, prcnMult, enemyData))
				{
					list.Add(sleepersLanguageDatas.head);
				}
				if (canKillOnBack(damage, enemyData))
				{
					list.Add(sleepersLanguageDatas.back);
				}
				if (canKillOnChest(damage, enemyData))
				{
					list.Add(sleepersLanguageDatas.chest);
				}
				if (list.Count > 0)
				{
					if (num % 2 == 1)
					{
						stringBuilder.Append(" | ");
					}
					list.Reverse();
					stringBuilder.Append(text + ": [" + string.Join(",", list) + "]");
					if (num++ % 2 == 1 && num2 != num3)
					{
						stringBuilder.AppendLine();
					}
				}
				num2++;
			}
			if (num > 1 && stringBuilder.Length > 0)
			{
				if (stringBuilder[stringBuilder.Length - 1] != '\n')
				{
					stringBuilder.AppendLine();
				}
			}
			return stringBuilder.ToString();
		}

		private bool canKillOnChest(float damage, EnemyData data)
		{
			return damage >= data.Health;
		}

		private bool canKillOnBack(float damage, EnemyData data)
		{
			return damage * data.BackMultiplier >= data.Health;
		}

		private bool canKillOnHead(float damage, float prcnMultiplier, EnemyData data)
		{
			if (isArmored(data))
			{
				return damage * data.HeadMultiplier >= data.Health;
			}
			return damage * prcnMultiplier * data.HeadMultiplier >= data.Health;
		}

		private bool canKillOnOccipit(float damage, float prcnMultiplier, EnemyData data)
		{
			if (isArmored(data))
			{
				return damage * data.BackMultiplier * data.HeadMultiplier >= data.Health;
			}
			return damage * prcnMultiplier * data.BackMultiplier * data.HeadMultiplier >= data.Health;
		}

		private bool isArmored(EnemyData data)
		{
			return data.IsArmored;
		}
	}
	internal class WeaponDescriptionBuilder
	{
		private PlayerDataBlock _playerDB;

		private GearIDRange _idRange;

		private uint _categoryID;

		private GearCategoryDataBlock _gearCategoryDB;

		private ItemDataBlock _itemDB;

		private LanguageDatas _languageDatas;

		private LanguageEnum _language;

		private SleepersDatas _sleepersDatas;

		private string _lastSleepersDatas;

		private readonly StringBuilder _strBuilder = new StringBuilder();

		private const string DIVIDER = " | ";

		private const string CLOSE_COLOR_TAG = "</color>";

		private const string SHOTGUN_PREFAB = "Assets/AssetPrefabs/Items/Weapons/GearSetup/ShotgunWeaponFirstPerson.prefab";

		internal void Inizialize(GearIDRange idRange, PlayerDataBlock playerDB, LanguageEnum language)
		{
			_idRange = idRange;
			_playerDB = playerDB;
			_categoryID = idRange.GetCompID((eGearComponent)2);
			_gearCategoryDB = GameDataBlockBase<GearCategoryDataBlock>.GetBlock(_categoryID);
			_itemDB = GameDataBlockBase<ItemDataBlock>.GetBlock(_gearCategoryDB.BaseItem);
			bool sleepersDatas = DeserializeLanguageJson(language);
			SetSleepersDatas(sleepersDatas);
		}

		private bool DeserializeLanguageJson(LanguageEnum language)
		{
			if (_language == language && _languageDatas != null)
			{
				return false;
			}
			LanguageDatasClass languageDatasClass = JsonSerializer.Deserialize<LanguageDatasClass>(LocalizedString.JsonString);
			_languageDatas = (language.Equals(LanguageEnum.English) ? languageDatasClass.english : languageDatasClass.chinese);
			_language = language;
			return true;
		}

		private void SetSleepersDatas(bool force)
		{
			if (!(_lastSleepersDatas == WeaponStatShowerPlugin.SleepersShown) || force)
			{
				_lastSleepersDatas = WeaponStatShowerPlugin.SleepersShown;
				string[] array = _lastSleepersDatas.Split(',');
				if (array[0].Trim().Length == 0)
				{
					WeaponStatShowerPlugin.LogWarning("Empty String in the config file, applying Default values");
					array = new string[1] { "ALL" };
				}
				_sleepersDatas = new SleepersDatas(array, _languageDatas.sleepers);
			}
		}

		public string DescriptionFormatter()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			if ((int)_itemDB.inventorySlot == 10)
			{
				MeleeArchetypeDataBlock block = GameDataBlockBase<MeleeArchetypeDataBlock>.GetBlock(GearBuilder.GetMeleeArchetypeID(_gearCategoryDB));
				return VerboseDescriptionFormatter(block) + GetFormatedWeaponStats(block, _itemDB);
			}
			var (val, flag) = GetRangedArchetype();
			if (val == null)
			{
				return string.Empty;
			}
			return string.Concat(str1: GetFormatedWeaponStats(val, (!flag) ? (_itemDB.FirstPersonPrefabs != null && _itemDB.FirstPersonPrefabs.Contains("Assets/AssetPrefabs/Items/Weapons/GearSetup/ShotgunWeaponFirstPerson.prefab")) : (_idRange.GetCompID((eGearComponent)1) == 13), flag), str0: VerboseDescriptionFormatter(val, flag));
		}

		internal string FireRateFormatter(string gearPublicName)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			if ((int)_itemDB.inventorySlot == 10)
			{
				MeleeArchetypeDataBlock block = GameDataBlockBase<MeleeArchetypeDataBlock>.GetBlock(GearBuilder.GetMeleeArchetypeID(_gearCategoryDB));
				MeleeLanguageModel melee = _languageDatas.melee;
				return ((GameDataBlockBase<MeleeArchetypeDataBlock>)(object)block).persistentID switch
				{
					1u => melee.hammer, 
					2u => melee.knife, 
					3u => melee.spear, 
					4u => melee.bat, 
					_ => gearPublicName, 
				};
			}
			ArchetypeDataBlock item = GetRangedArchetype().Item1;
			if (item == null)
			{
				return gearPublicName;
			}
			return VerbosePublicNameFireMode(item);
		}

		private (ArchetypeDataBlock?, bool) GetRangedArchetype()
		{
			bool item = _categoryID == 12;
			return (ArchetypeUtil.GetMappedArchetypeDataBlock(_idRange, _categoryID, _gearCategoryDB), item);
		}

		private string VerbosePublicNameFireMode(ArchetypeDataBlock archetypeDB)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected I4, but got Unknown
			//IL_012e: 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_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			FiremodeLanguageModel firemode = _languageDatas.firemode;
			eWeaponFireMode fireMode = archetypeDB.FireMode;
			_strBuilder.Clear();
			switch ((int)fireMode)
			{
			case 2:
			case 11:
			{
				StringBuilder strBuilder = _strBuilder;
				StringBuilder stringBuilder6 = strBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(13, 4, strBuilder);
				handler.AppendFormatted(firemode.fullA);
				handler.AppendLiteral(" (<#12FF50>");
				handler.AppendFormatted(_languageDatas.rateOfFire);
				handler.AppendLiteral(" ");
				handler.AppendFormatted(GetRateOfFire(archetypeDB, fireMode));
				handler.AppendFormatted("</color>");
				handler.AppendLiteral(")");
				stringBuilder6.Append(ref handler);
				break;
			}
			case 0:
			case 10:
			{
				StringBuilder strBuilder = _strBuilder;
				StringBuilder stringBuilder5 = strBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(13, 4, strBuilder);
				handler.AppendFormatted(firemode.semiA);
				handler.AppendLiteral(" (<#12FF50>");
				handler.AppendFormatted(_languageDatas.rateOfFire);
				handler.AppendLiteral(" ");
				handler.AppendFormatted(GetRateOfFire(archetypeDB, fireMode));
				handler.AppendFormatted("</color>");
				handler.AppendLiteral(")");
				stringBuilder5.Append(ref handler);
				break;
			}
			case 1:
			case 12:
				if (archetypeDB.BurstShotCount != 1)
				{
					StringBuilder strBuilder = _strBuilder;
					StringBuilder stringBuilder3 = strBuilder;
					StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(23, 7, strBuilder);
					handler.AppendFormatted(firemode.burst);
					handler.AppendLiteral(" (<#704dfa>#");
					handler.AppendFormatted(archetypeDB.BurstShotCount);
					handler.AppendFormatted("</color>");
					handler.AppendFormatted(" | ");
					handler.AppendLiteral("<#12FF50>");
					handler.AppendFormatted(_languageDatas.rateOfFire);
					handler.AppendLiteral(" ");
					handler.AppendFormatted(GetRateOfFire(archetypeDB, fireMode));
					handler.AppendFormatted("</color>");
					handler.AppendLiteral(")");
					stringBuilder3.Append(ref handler);
				}
				else
				{
					StringBuilder strBuilder = _strBuilder;
					StringBuilder stringBuilder4 = strBuilder;
					StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(13, 4, strBuilder);
					handler.AppendFormatted(firemode.burst);
					handler.AppendLiteral(" (<#12FF50>");
					handler.AppendFormatted(_languageDatas.rateOfFire);
					handler.AppendLiteral(" ");
					handler.AppendFormatted(GetRateOfFire(archetypeDB, (eWeaponFireMode)0));
					handler.AppendFormatted("</color>");
					handler.AppendLiteral(")");
					stringBuilder4.Append(ref handler);
				}
				break;
			case 3:
			{
				StringBuilder strBuilder = _strBuilder;
				StringBuilder stringBuilder2 = strBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(28, 3, strBuilder);
				handler.AppendLiteral("S-Burst (<#12FF50>#");
				handler.AppendFormatted(archetypeDB.BurstShotCount);
				handler.AppendLiteral(" every ");
				handler.AppendFormatted(archetypeDB.SpecialSemiBurstCountTimeout);
				handler.AppendLiteral("'");
				handler.AppendFormatted("</color>");
				handler.AppendLiteral(")");
				stringBuilder2.Append(ref handler);
				break;
			}
			case 13:
			{
				StringBuilder strBuilder = _strBuilder;
				StringBuilder stringBuilder = strBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(13, 4, strBuilder);
				handler.AppendFormatted(firemode.shotgunSentry);
				handler.AppendLiteral(" (<#12FF50>");
				handler.AppendFormatted(_languageDatas.rateOfFire);
				handler.AppendLiteral(" ");
				handler.AppendFormatted(GetRateOfFire(archetypeDB, fireMode));
				handler.AppendFormatted("</color>");
				handler.AppendLiteral(")");
				stringBuilder.Append(ref handler);
				break;
			}
			default:
				WeaponStatShowerPlugin.LogError("FireMode not found");
				break;
			}
			return _strBuilder.ToString();
		}

		private string VerboseDescriptionFormatter(ArchetypeDataBlock archetypeDB, bool isSentry)
		{
			_strBuilder.Clear();
			float specialChargetupTime = archetypeDB.SpecialChargetupTime;
			if (specialChargetupTime > 0f)
			{
				string value = (((double)specialChargetupTime > 0.4) ? _languageDatas.longChargeUp : _languageDatas.shortChargeUp);
				StringBuilder strBuilder = _strBuilder;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(3, 2, strBuilder);
				handler.AppendFormatted(value);
				handler.AppendLiteral(" (");
				handler.AppendFormatted(FormatFloat(specialChargetupTime, 2));
				handler.AppendLiteral(")");
				strBuilder.AppendLine(ref handler);
			}
			if (_strBuilder.Length != 0)
			{
				return _strBuilder.ToString() + "\n";
			}
			return string.Empty;
		}

		private string VerboseDescriptionFormatter(MeleeArchetypeDataBlock meleeArchetypeDB)
		{
			_strBuilder.Clear();
			if ((double)meleeArchetypeDB.CameraDamageRayLength < 1.76)
			{
				_strBuilder.AppendLine(_languageDatas.melee.shortRange);
			}
			else if ((double)meleeArchetypeDB.CameraDamageRayLength < 2.5)
			{
				_strBuilder.AppendLine(_languageDatas.melee.mediumRange);
			}
			else
			{
				_strBuilder.AppendLine(_languageDatas.melee.longRange);
			}
			_strBuilder.Append(meleeArchetypeDB.CanHitMultipleEnemies ? (_languageDatas.melee.canPierce + "\n") : string.Empty);
			if (_strBuilder.Length != 0)
			{
				return _strBuilder.ToString();
			}
			return string.Empty;
		}

		private string GetFormatedWeaponStats(ArchetypeDataBlock archetypeDB, bool isShotgun, bool isSentry = false)
		{
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			if (archetypeDB == null)
			{
				return string.Empty;
			}
			int count = 0;
			int dividerThreshold = ((_language != LanguageEnum.English) ? 3 : 4);
			_strBuilder.Clear();
			string value = FormatFloat(archetypeDB.Damage, 2) + (isShotgun ? $"(x{archetypeDB.ShotgunBulletCount})" : "");
			AppendStat(ref count, "<#9D2929>", _languageDatas.damage, value);
			AppendStatIf(ref count, Divider, !isSentry, "<color=orange>", _languageDatas.clip, archetypeDB.DefaultClipSize.ToString());
			Divider();
			AppendStat(ref count, "<#FFD306>", _languageDatas.maxAmmo, GetTotalAmmo(archetypeDB, _itemDB, isSentry).ToString());
			AppendStatIf(ref count, Divider, !isSentry, "<#C0FF00>", _languageDatas.reload, FormatFloat(archetypeDB.DefaultReloadTime, 2).ToString());
			AppendStatIf(ref count, Divider, archetypeDB.PrecisionDamageMulti != 1f, "<#18A4A9>", _languageDatas.precision, FormatFloat(archetypeDB.PrecisionDamageMulti, 2).ToString());
			Divider();
			AppendStat(ref count, "<#6764de>", _languageDatas.falloff, (int)archetypeDB.DamageFalloff.x + "m");
			AppendStatIf(ref count, Divider, archetypeDB.StaggerDamageMulti != 1f, "<color=green>", _languageDatas.stagger, FormatFloat(archetypeDB.StaggerDamageMulti, 2).ToString());
			AppendStatIf(ref count, Divider, archetypeDB.HipFireSpread != 0f && !isShotgun, "<#cc9347>", _languageDatas.hipSpread, FormatFloat(archetypeDB.HipFireSpread, 2).ToString());
			AppendStatIf(ref count, Divider, archetypeDB.AimSpread != 0f && !isShotgun, "<#e6583c>", _languageDatas.aimDSpread, FormatFloat(archetypeDB.AimSpread, 2).ToString());
			AppendStatIf(ref count, Divider, (float)(archetypeDB.ShotgunBulletSpread + archetypeDB.ShotgunConeSize) != 0f && isShotgun, "<#e6583c>", _languageDatas.spread, FormatFloat(archetypeDB.ShotgunBulletSpread + archetypeDB.ShotgunConeSize, 2).ToString());
			AppendStatIf(ref count, Divider, archetypeDB.PiercingBullets, "<#097345>", _languageDatas.pierceCount, archetypeDB.PiercingDamageCountLimit.ToString());
			_strBuilder.AppendLine();
			_strBuilder.Append(_sleepersDatas.VerboseKill(archetypeDB));
			return _strBuilder.ToString();
			void Divider()
			{
				if (count >= dividerThreshold)
				{
					_strBuilder.AppendLine();
					count = 0;
				}
				else if (count > 0)
				{
					_strBuilder.Append(" | ");
				}
			}
		}

		private string GetFormatedWeaponStats(MeleeArchetypeDataBlock meleeArchetypeDB, ItemDataBlock itemDB)
		{
			if (meleeArchetypeDB == null)
			{
				return string.Empty;
			}
			int count = 0;
			MeleeLanguageModel melee = _languageDatas.melee;
			_strBuilder.Clear();
			_strBuilder.AppendLine();
			AppendStat(ref count, "<#9D2929>", _languageDatas.damage + "." + melee.light, meleeArchetypeDB.LightAttackDamage.ToString());
			Divider();
			AppendStat(ref count, "<color=orange>", _languageDatas.damage + "." + melee.heavy, meleeArchetypeDB.ChargedAttackDamage.ToString());
			AppendStatIf(ref count, Divider, !meleeArchetypeDB.AllowRunningWhenCharging, "<#FFD306>", melee.canRunWhileCharging);
			AppendStatIf(ref count, Divider, meleeArchetypeDB.LightStaggerMulti != 1f, "<#C0FF00>", _languageDatas.stagger + "." + melee.light, meleeArchetypeDB.LightStaggerMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.ChargedStaggerMulti != 1f, "<color=green>", _languageDatas.stagger + "." + melee.heavy, meleeArchetypeDB.ChargedStaggerMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.LightPrecisionMulti != 1f, "<#004E2C>", _languageDatas.precision + "." + melee.light, meleeArchetypeDB.LightPrecisionMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.ChargedPrecisionMulti != 1f, "<#55022B>", _languageDatas.precision + "." + melee.heavy, meleeArchetypeDB.ChargedPrecisionMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.LightSleeperMulti != 1f, "<#A918A7>", melee.sleepingEnemiesMultiplier + "." + melee.light, meleeArchetypeDB.LightSleeperMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.ChargedSleeperMulti != 1f, "<#025531>", melee.sleepingEnemiesMultiplier + "." + melee.heavy, meleeArchetypeDB.ChargedSleeperMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.LightBackstabberMulti != 1f, "<#18A4A9>", melee.backstabMultiplier + "." + melee.light, meleeArchetypeDB.LightBackstabberMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.ChargedBackstabberMulti != 1f, "<#75A2AA>", melee.backstabMultiplier + "." + melee.heavy, meleeArchetypeDB.ChargedBackstabberMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.LightEnvironmentMulti != 1f, "<#18A4A9>", melee.environmentMultiplier + "." + melee.light, meleeArchetypeDB.LightEnvironmentMulti.ToString());
			AppendStatIf(ref count, Divider, meleeArchetypeDB.ChargedEnvironmentMulti != 1f, "<#75A2AA>", melee.environmentMultiplier + "." + melee.heavy, meleeArchetypeDB.ChargedEnvironmentMulti.ToString());
			_strBuilder.AppendLine();
			_strBuilder.Append(_sleepersDatas.VerboseKill(meleeArchetypeDB) ?? string.Empty);
			return _strBuilder.ToString();
			void Divider()
			{
				if (count >= 3)
				{
					_strBuilder.AppendLine();
					count = 0;
				}
				else if (count > 0)
				{
					_strBuilder.Append(" | ");
				}
			}
		}

		private void AppendStatIf(ref int count, Action divider, bool condition, string color, string label, string value = "")
		{
			if (condition)
			{
				divider();
				AppendStat(ref count, color, label, value);
			}
		}

		private void AppendStat(ref int count, string color, string label, string value = "")
		{
			_strBuilder.Append(color);
			_strBuilder.Append(label);
			if (!string.IsNullOrEmpty(value))
			{
				_strBuilder.Append(' ');
				_strBuilder.Append(value);
			}
			_strBuilder.Append("</color>");
			count++;
		}

		private static float FormatFloat(float value, int v)
		{
			return (float)Math.Round((decimal)value, v);
		}

		private int GetAmmoMax(ItemDataBlock itemDataBlock)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected I4, but got Unknown
			AmmoType ammoTypeFromSlot = PlayerAmmoStorage.GetAmmoTypeFromSlot(itemDataBlock.inventorySlot);
			return (int)ammoTypeFromSlot switch
			{
				0 => _playerDB.AmmoStandardMaxCap, 
				1 => _playerDB.AmmoSpecialMaxCap, 
				2 => _playerDB.AmmoClassMaxCap, 
				5 => itemDataBlock.ConsumableAmmoMax, 
				_ => -1, 
			};
		}

		private int GetTotalAmmo(ArchetypeDataBlock archetypeDB, ItemDataBlock itemDB, bool isSentry = false)
		{
			int ammoMax = GetAmmoMax(itemDB);
			float num = archetypeDB.CostOfBullet;
			if (isSentry)
			{
				num *= itemDB.ClassAmmoCostFactor;
				if ((float)archetypeDB.ShotgunBulletCount > 0f)
				{
					num *= (float)archetypeDB.ShotgunBulletCount;
				}
			}
			int num2 = (int)((float)ammoMax / num);
			if (!isSentry)
			{
				return num2 + archetypeDB.DefaultClipSize;
			}
			return num2;
		}

		private string GetRateOfFire(ArchetypeDataBlock archetypeDB, eWeaponFireMode fireMode)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected I4, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected I4, but got Unknown
			float value = -1f;
			switch ((int)fireMode)
			{
			default:
				switch (fireMode - 11)
				{
				case 0:
					break;
				case 2:
					goto IL_003e;
				case 1:
					goto IL_0054;
				default:
					goto end_IL_0007;
				}
				goto case 2;
			case 2:
				value = 1f / archetypeDB.ShotDelay;
				break;
			case 0:
				goto IL_003e;
			case 1:
				goto IL_0054;
				IL_0054:
				value = 1f / (archetypeDB.BurstDelay + archetypeDB.SpecialChargetupTime + archetypeDB.ShotDelay * (float)(archetypeDB.BurstShotCount - 1)) * (float)archetypeDB.BurstShotCount;
				break;
				IL_003e:
				value = 1f / (archetypeDB.ShotDelay + archetypeDB.SpecialChargetupTime);
				break;
				end_IL_0007:
				break;
			}
			return FormatFloat(value, 1).ToString();
		}
	}
}
namespace WeaponStatShower.Utils.Language
{
	public class LanguageDatas
	{
		public FiremodeLanguageModel firemode { get; set; } = new FiremodeLanguageModel();

		public MeleeLanguageModel melee { get; set; } = new MeleeLanguageModel();

		public SleepersLanguageModel sleepers { get; set; } = new SleepersLanguageModel();

		public string damage { get; set; } = string.Empty;

		public string clip { get; set; } = string.Empty;

		public string maxAmmo { get; set; } = string.Empty;

		public string falloff { get; set; } = string.Empty;

		public string reload { get; set; } = string.Empty;

		public string stagger { get; set; } = string.Empty;

		public string precision { get; set; } = string.Empty;

		public string pierceCount { get; set; } = string.Empty;

		public string rateOfFire { get; set; } = string.Empty;

		public string aimDSpread { get; set; } = string.Empty;

		public string hipSpread { get; set; } = string.Empty;

		public string spread { get; set; } = string.Empty;

		public string deployable { get; set; } = string.Empty;

		public string longChargeUp { get; set; } = string.Empty;

		public string shortChargeUp { get; set; } = string.Empty;
	}
	internal class LanguageDatasClass
	{
		public LanguageDatas english { get; set; } = new LanguageDatas();

		public LanguageDatas chinese { get; set; } = new LanguageDatas();
	}
	internal enum LanguageEnum
	{
		English,
		Chinese
	}
	internal class LocalizedString
	{
		public static readonly string JsonString = "{\r\n\t\t\t\"english\": {\r\n\t\t\t\t\"firemode\": {\r\n\t\t\t\t\t\"fullA\": \"Full-A\",\r\n\t\t\t\t\t\"semiA\": \"Semi-A\",\r\n\t\t\t\t\t\"burst\": \"Burst\",\r\n\t\t\t\t\t\"shotgunSentry\": \"Shotgun-S\"\r\n\t\t\t\t},\r\n\t\t\t\t\"melee\": {\r\n\t\t\t\t\t\"light\": \"Lgt\",\r\n\t\t\t\t\t\"heavy\": \"Hvy\",\r\n\t\t\t\t\t\"canRunWhileCharging\": \"Can't run\",\r\n\t\t\t\t\t\"sleepingEnemiesMultiplier\": \"Slp\",\r\n\t\t\t\t\t\"backstabMultiplier\": \"Bak\",\r\n\t\t\t\t\t\"environmentMultiplier\": \"Env\",\r\n\t\t\t\t\t\"canPierce\": \"Piercing\",\r\n\t\t\t\t\t\"shortRange\": \"Short Range\",\r\n\t\t\t\t\t\"mediumRange\": \"Medium Range\",\r\n\t\t\t\t\t\"longRange\": \"Long Range\",\r\n\t\t\t\t\t\"hammer\": \"Hammer - Balanced\",\r\n\t\t\t\t\t\"knife\": \"Knife - Fast\",\r\n\t\t\t\t\t\"bat\": \"Bat - Fast\",\r\n\t\t\t\t\t\"spear\": \"Spear - Slow\"\r\n\t\t\t\t},\r\n\t\t\t\t\"sleepers\": {\r\n\t\t\t\t\t\"striker\": \"STRK\",\r\n\t\t\t\t\t\"shooter\": \"SHTR\",\r\n\t\t\t\t\t\"scout\": \"SCOUT\",\r\n\t\t\t\t\t\"bigStriker\": \"B-STRK\",\r\n\t\t\t\t\t\"bigShooter\": \"B-SHTR\",\r\n\t\t\t\t\t\"charger\": \"CHRG\",\r\n\t\t\t\t\t\"chargerScout\": \"C-SCOUT\",\r\n\t\t\t\t\t\"occipit\": \"o\",\r\n\t\t\t\t\t\"head\": \"h\",\r\n\t\t\t\t\t\"back\": \"b\",\r\n\t\t\t\t\t\"chest\": \"c\"\r\n\t\t\t\t},\r\n\t\t\t\t\"damage\": \"Dmg\",\r\n\t\t\t\t\"clip\": \"Clp\",\r\n\t\t\t\t\"maxAmmo\": \"Max\",\r\n\t\t\t\t\"falloff\": \"Dist\",\r\n\t\t\t\t\"reload\": \"Rld\",\r\n\t\t\t\t\"stagger\": \"Stgr\",\r\n\t\t\t\t\"precision\": \"Prcn\",\r\n\t\t\t\t\"pierceCount\": \"Pierc\",\r\n\t\t\t\t\"rateOfFire\": \"RoF\",\r\n\t\t\t\t\"aimDSpread\": \"ADS\",\r\n\t\t\t\t\"hipSpread\": \"HIP\",\r\n\t\t\t\t\"spread\": \"SPRD\",\r\n\t\t\t\t\"deployable\": \"Deployable\",\r\n\t\t\t\t\"longChargeUp\": \"Long Charge-up\",\r\n\t\t\t\t\"shortChargeUp\": \"short Charge-up\"\r\n\t\t\t},\r\n\r\n\t\t\t\"chinese\": {\r\n\t\t\t\t\"firemode\": {\r\n\t\t\t\t\t\"fullA\": \"全自动\",\r\n\t\t\t\t\t\"semiA\": \"半自动\",\r\n\t\t\t\t\t\"burst\": \"连发\",\r\n\t\t\t\t\t\"shotgunSentry\": \"半自动霰弹射击\"\r\n\t\t\t\t},\r\n\t\t\t\t\"melee\": {\r\n\t\t\t\t\t\"light\": \"轻击\",\r\n\t\t\t\t\t\"heavy\": \"重击\",\r\n\t\t\t\t\t\"canRunWhileCharging\": \"不能冲刺\",\r\n\t\t\t\t\t\"sleepingEnemiesMultiplier\": \"沉睡倍率\",\r\n\t\t\t\t\t\"backstabMultiplier\": \"背后捅刀\",\r\n\t\t\t\t\t\"environmentMultiplier\": \"环境倍率\",\r\n\t\t\t\t\t\"canPierce\": \"穿刺\",\r\n\t\t\t\t\t\"shortRange\": \"短距离\",\r\n\t\t\t\t\t\"mediumRange\": \"中距离\",\r\n\t\t\t\t\t\"longRange\": \"长距离\",\r\n\t\t\t\t\t\"hammer\": \"大锤 - 均衡\",\r\n\t\t\t\t\t\"knife\": \"刀 - 快速\",\r\n\t\t\t\t\t\"bat\": \"棍棒 - 快速\",\r\n\t\t\t\t\t\"spear\": \"矛 - 慢速\"\r\n\t\t\t\t},\r\n\t\t\t\t\"sleepers\": {\r\n\t\t\t\t\t\"striker\": \"前锋\",\r\n\t\t\t\t\t\"shooter\": \"射手\",\r\n\t\t\t\t\t\"scout\": \"哨兵\",\r\n\t\t\t\t\t\"bigStriker\": \"大壮\",\r\n\t\t\t\t\t\"bigShooter\": \"大姐\",\r\n\t\t\t\t\t\"charger\": \"黑刺\",\r\n\t\t\t\t\t\"chargerScout\": \"黑触\",\r\n\t\t\t\t\t\"occipit\": \"后脑\",\r\n\t\t\t\t\t\"head\": \"头\",\r\n\t\t\t\t\t\"back\": \"背\",\r\n\t\t\t\t\t\"chest\": \"胸\"\r\n\t\t\t\t},\r\n\r\n\t\t\t\t\"damage\": \"伤害\",\r\n\t\t\t\t\"clip\": \"弹容量\",\r\n\t\t\t\t\"maxAmmo\": \"总弹量\",\r\n\t\t\t\t\"falloff\": \"衰减距离\",\r\n\t\t\t\t\"reload\": \"换弹时间\",\r\n\t\t\t\t\"stagger\": \"硬直倍率\",\r\n\t\t\t\t\"precision\": \"精准倍率\",\r\n\t\t\t\t\"pierceCount\": \"穿透\",\r\n\t\t\t\t\"rateOfFire\": \"射速\",\r\n\t\t\t\t\"aimDSpread\": \"倍镜\",\r\n\t\t\t\t\"hipSpread\": \"后坐力\",\r\n\t\t\t\t\"spread\": \"点差\",\r\n\t\t\t\t\"deployable\": \"可部署\",\r\n\t\t\t\t\"longChargeUp\": \"长蓄力\",\r\n\t\t\t\t\"shortChargeUp\": \"短蓄力\"\r\n\t\t\t}\r\n\t\t}";
	}
}
namespace WeaponStatShower.Utils.Language.Models
{
	public class FiremodeLanguageModel
	{
		public string fullA { get; set; } = string.Empty;

		public string semiA { get; set; } = string.Empty;

		public string burst { get; set; } = string.Empty;

		public string shotgunSentry { get; set; } = string.Empty;
	}
	public class MeleeLanguageModel
	{
		public string light { get; set; } = string.Empty;

		public string heavy { get; set; } = string.Empty;

		public string canRunWhileCharging { get; set; } = string.Empty;

		public string sleepingEnemiesMultiplier { get; set; } = string.Empty;

		public string backstabMultiplier { get; set; } = string.Empty;

		public string environmentMultiplier { get; set; } = string.Empty;

		public string canPierce { get; set; } = string.Empty;

		public string shortRange { get; set; } = string.Empty;

		public string mediumRange { get; set; } = string.Empty;

		public string longRange { get; set; } = string.Empty;

		public string hammer { get; set; } = string.Empty;

		public string knife { get; set; } = string.Empty;

		public string bat { get; set; } = string.Empty;

		public string spear { get; set; } = string.Empty;
	}
	public class SleepersLanguageModel
	{
		public string striker { get; set; } = string.Empty;

		public string shooter { get; set; } = string.Empty;

		public string scout { get; set; } = string.Empty;

		public string bigStriker { get; set; } = string.Empty;

		public string bigShooter { get; set; } = string.Empty;

		public string charger { get; set; } = string.Empty;

		public string chargerScout { get; set; } = string.Empty;

		public string occipit { get; set; } = string.Empty;

		public string head { get; set; } = string.Empty;

		public string back { get; set; } = string.Empty;

		public string chest { get; set; } = string.Empty;
	}
}
namespace WeaponStatShower.Utils.Extensions
{
	public static class CollectionExtensions
	{
		public static void ExpandToSize<T>(this List<T> list, int count, T defaultValue)
		{
			list.EnsureCapacity(count);
			while (list.Count < count)
			{
				list.Add(defaultValue);
			}
		}
	}
}
namespace WeaponStatShower.Patches
{
	internal class DescriptionToggle : Patch
	{
		private const string PatchName = "DescriptionToggle";

		private static DescriptionButtonHandler _button;

		public override string Name => "DescriptionToggle";

		public static Patch Instance { get; private set; }

		public override void Initialize()
		{
			Instance = this;
		}

		public override void Execute()
		{
			PatchMethod<CM_PlayerLobbyBar>("ShowWeaponSelectionPopup", PatchType.Postfix);
			PatchMethod<CM_PlayerLobbyBar>("OnWeaponSlotItemSelected", PatchType.Postfix);
		}

		public static void CM_PlayerLobbyBar__ShowWeaponSelectionPopup__Postfix(CM_PlayerLobbyBar __instance)
		{
			_button = new DescriptionButtonHandler(__instance);
			if ((Object)(object)__instance.selectedWeaponSlotItem != (Object)null)
			{
				CM_PlayerLobbyBar__OnWeaponSlotItemSelected__Postfix(__instance.selectedWeaponSlotItem);
			}
		}

		public static void CM_PlayerLobbyBar__OnWeaponSlotItemSelected__Postfix(CM_InventorySlotItem slotItem)
		{
			if (_button != null)
			{
				_button.SetData(slotItem.m_gearID);
			}
		}
	}
	public abstract class Patch
	{
		protected internal Harmony? Harmony { get; set; }

		public virtual string Name { get; }

		public virtual bool Enabled => true;

		public virtual void Initialize()
		{
		}

		public abstract void Execute();

		public void PatchConstructor<TClass>(PatchType patchType, string? prefixMethodName = null, string? postfixMethodName = null) where TClass : class
		{
			PatchConstructor<TClass>(null, patchType, prefixMethodName, postfixMethodName);
		}

		public void PatchConstructor<TClass>(Type[]? parameters, PatchType patchType, string? prefixMethodName = null, string? postfixMethodName = null) where TClass : class
		{
			ConstructorInfo methodBase = AccessTools.Constructor(typeof(TClass), parameters, false);
			PatchMethod<TClass>(methodBase, patchType, prefixMethodName, postfixMethodName);
		}

		public void PatchMethod<TClass>(string methodName, PatchType patchType, Type[] generics = null, string prefixMethodName = null, string postfixMethodName = null) where TClass : class
		{
			PatchMethod<TClass>(methodName, null, patchType, generics, prefixMethodName, postfixMethodName);
		}

		public void PatchMethod<TClass>(string methodName, Type[] parameters, PatchType patchType, Type[] generics = null, string prefixMethodName = null, string postfixMethodName = null) where TClass : class
		{
			MethodInfo methodBase = AccessTools.Method(typeof(TClass), methodName, parameters, generics);
			PatchMethod<TClass>(methodBase, patchType, prefixMethodName, postfixMethodName);
		}

		public void PatchMethod<TClass>(MethodBase methodBase, PatchType patchType, string prefixMethodName = null, string postfixMethodName = null) where TClass : class
		{
			PatchMethod(typeof(TClass), methodBase, patchType, prefixMethodName, postfixMethodName);
		}

		public void PatchMethod(Type classType, string methodName, PatchType patchType, Type[] generics = null, string prefixMethodName = null, string postfixMethodName = null)
		{
			PatchMethod(classType, methodName, null, patchType, generics, prefixMethodName, postfixMethodName);
		}

		public void PatchMethod(Type classType, string methodName, Type[] parameters, PatchType patchType, Type[] generics = null, string prefixMethodName = null, string postfixMethodName = null)
		{
			MethodInfo methodBase = AccessTools.Method(classType, methodName, parameters, generics);
			PatchMethod(classType, methodBase, patchType, prefixMethodName, postfixMethodName);
		}

		public void PatchMethod(Type classType, MethodBase methodBase, PatchType patchType, string? prefixMethodName = null, string? postfixMethodName = null)
		{
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Expected O, but got Unknown
			//IL_0134: 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_0147: Expected O, but got Unknown
			//IL_0147: Expected O, but got Unknown
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			string text = classType.Name.Replace("`", "__");
			string value = methodBase.ToString();
			string text2 = (methodBase.IsConstructor ? "ctor" : methodBase.Name);
			MethodInfo methodInfo = null;
			MethodInfo methodInfo2 = null;
			if ((patchType & PatchType.Prefix) != 0)
			{
				try
				{
					methodInfo2 = AccessTools.Method(GetType(), prefixMethodName ?? (text + "__" + text2 + "__Prefix"), (Type[])null, (Type[])null);
				}
				catch (Exception value2)
				{
					WeaponStatShowerPlugin.LogFatal($"Failed to obtain the prefix patch method for {value}): {value2}");
				}
			}
			if ((patchType & PatchType.Postfix) != 0)
			{
				try
				{
					methodInfo = AccessTools.Method(GetType(), postfixMethodName ?? (text + "__" + text2 + "__Postfix"), (Type[])null, (Type[])null);
				}
				catch (Exception value3)
				{
					WeaponStatShowerPlugin.LogFatal($"Failed to obtain the postfix patch method for {value}): {value3}");
				}
			}
			try
			{
				if (methodInfo2 != null && methodInfo != null)
				{
					Harmony.Patch(methodBase, new HarmonyMethod(methodInfo2), new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else if (methodInfo2 != null)
				{
					Harmony.Patch(methodBase, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else if (methodInfo != null)
				{
					Harmony.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception value4)
			{
				WeaponStatShowerPlugin.LogError($"Failed to patch method {value}: {value4}");
			}
		}
	}
	[Flags]
	public enum PatchType : byte
	{
		Prefix = 1,
		Postfix = 2,
		Both = 3
	}
}
namespace WeaponStatShower.Json
{
	public static class JSON
	{
		private static readonly JsonSerializerOptions _setting;

		static JSON()
		{
			_setting = new JsonSerializerOptions
			{
				ReadCommentHandling = JsonCommentHandling.Skip,
				IncludeFields = true,
				PropertyNameCaseInsensitive = true,
				WriteIndented = true,
				IgnoreReadOnlyProperties = true
			};
			_setting.Converters.Add(new JsonStringEnumConverter());
			if (PartialData.HasPData)
			{
				_setting.Converters.Add(PartialData.PDataIDConverter);
			}
		}

		public static T? Deserialize<T>(string json)
		{
			return JsonSerializer.Deserialize<T>(json, _setting);
		}

		public static T? Deserialize<T>(ref Utf8JsonReader reader)
		{
			return JsonSerializer.Deserialize<T>(ref reader, _setting);
		}

		public static bool TryDeserializeSafe<T>(string json, [MaybeNullWhen(false)] out T value)
		{
			try
			{
				value = JsonSerializer.Deserialize<T>(json, _setting);
				return value != null;
			}
			catch (JsonException ex)
			{
				WeaponStatShowerPlugin.LogError("Caught exception while reading json: " + ex.Message + "\n" + ex.StackTrace);
				value = default(T);
				return false;
			}
		}

		public static bool TryDeserialize<T>(string json, [MaybeNullWhen(false)] out T value)
		{
			value = JsonSerializer.Deserialize<T>(json, _setting);
			return value != null;
		}

		public static bool TryDeserialize<T>(ref Utf8JsonReader reader, [MaybeNullWhen(false)] out T value)
		{
			value = JsonSerializer.Deserialize<T>(ref reader, _setting);
			return value != null;
		}

		public static object? Deserialize(Type type, string json)
		{
			return JsonSerializer.Deserialize(json, type, _setting);
		}

		public static string Serialize<T>(T value)
		{
			return JsonSerializer.Serialize(value, _setting);
		}

		public static void Serialize<T>(Utf8JsonWriter writer, T value)
		{
			JsonSerializer.Serialize(writer, value, _setting);
		}

		public static void Serialize<T>(Utf8JsonWriter writer, string name, T value)
		{
			writer.WritePropertyName(name);
			JsonSerializer.Serialize(writer, value, _setting);
		}
	}
}
namespace WeaponStatShower.Json.Converters.Utils
{
	public class LocaleTextConverter : JsonConverter<LocaleText>
	{
		public override bool HandleNull => true;

		public override LocaleText Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
		{
			return reader.TokenType switch
			{
				JsonTokenType.String => new LocaleText(reader.GetString()), 
				JsonTokenType.Number => new LocaleText(reader.GetUInt32()), 
				JsonTokenType.Null => LocaleText.Empty, 
				_ => throw new JsonException($"LocaleTextJson type: {reader.TokenType} is not implemented!"), 
			};
		}

		public override void Write(Utf8JsonWriter writer, LocaleText value, JsonSerializerOptions options)
		{
			if (value.ID != 0)
			{
				writer.WriteNumberValue(value.ID);
			}
			else
			{
				writer.WriteStringValue(value.RawText);
			}
		}
	}
}
namespace WeaponStatShower.ExtraDescription
{
	public class DescriptionButtonHandler
	{
		private static readonly Vector2 Size = new Vector2(600f, 320f);

		private static readonly WeaponDescriptionBuilder DescriptionBuilder = new WeaponDescriptionBuilder();

		private readonly GameObject _gameObject;

		private readonly CM_Item _item;

		private readonly TextMeshPro _text;

		private readonly RectTransform _rectTrans;

		private readonly CM_ScrollWindowInfoBox _infoBox;

		private readonly CM_PageLoadout _pageLoadout;

		private LocaleText[] _headers;

		private LocaleText[] _descriptions;

		private int _index;

		private GearIDRange? _lastRange;

		public event Action<LocaleText>? OnDescriptionChanged;

		public DescriptionButtonHandler(CM_PlayerLobbyBar lobbyBar)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			_pageLoadout = ((Il2CppObjectBase)lobbyBar.m_parentPage).Cast<CM_PageLoadout>();
			_infoBox = lobbyBar.m_popupScrollWindow.InfoBox;
			_gameObject = Object.Instantiate<GameObject>(((Component)CM_PageLoadout.Current.m_copyLobbyIdButton).gameObject, ((Component)_infoBox).transform);
			_item = _gameObject.GetComponent<CM_Item>();
			_item.m_clickBlink = false;
			Transform child = ((Component)_item).transform.GetChild(0);
			_rectTrans = ((Component)child).GetComponent<RectTransform>();
			((Component)child).gameObject.SetActive(false);
			_item.OnBtnPressCallback = null;
			_item.OnBtnPressCallback += Action<int>.op_Implicit((Action<int>)OnBtnPress);
			GameObject val = new GameObject("PageNumber");
			val.transform.SetParent(_gameObject.transform, false);
			val.transform.localPosition = new Vector3(0f, -110f, 0f);
			val.layer = LayerManager.LAYER_UI;
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(1f, 1f, 1f, 0.2f);
			TextMeshPro val3 = ((Il2CppArrayBase<TextMeshPro>)(object)_item.m_texts)[0];
			_text = val.AddComponent<TextMeshPro>();
			((TMP_Text)_text).font = ((TMP_Text)val3).font;
			((TMP_Text)_text).fontSize = 48f;
			((Graphic)_text).color = val2;
			((TMP_Text)_text).alignment = (TextAlignmentOptions)1026;
			((Graphic)_text).raycastTarget = ((Graphic)val3).raycastTarget;
			_text.sortingLayerID = val3.sortingLayerID;
			((TMP_Text)_text).enableWordWrapping = false;
			((TMP_Text)_text).isOrthographic = true;
			((TMP_Text)_text).rectTransform.sizeDelta = new Vector2(100f, 50f);
			((Il2CppArrayBase<TextMeshPro>)(object)_item.m_texts)[0] = _text;
			Object.Destroy((Object)(object)val3);
			((Component)_item).transform.localPosition = new Vector3(-300f, -50f - Size.y / 2f, -1f);
			_item.m_collider.size = Size;
			((Il2CppArrayBase<Color>)(object)_item.m_textColorOut)[0] = val2;
			((Il2CppArrayBase<Color>)(object)_item.m_textColorOver)[0] = Color.white;
			_item.m_alphaSpriteOnHover = true;
		}

		public void SetData(GearIDRange idRange)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Invalid comparison between Unknown and I4
			if (_lastRange == idRange)
			{
				return;
			}
			_lastRange = idRange;
			uint compID = idRange.GetCompID((eGearComponent)2);
			GearCategoryDataBlock block = GameDataBlockBase<GearCategoryDataBlock>.GetBlock(compID);
			ArchetypeDataBlock mappedArchetypeDataBlock = ArchetypeUtil.GetMappedArchetypeDataBlock(idRange, compID, block);
			bool flag = WeaponStatShowerPlugin.ShowStats;
			LocaleText localeText;
			bool flag2;
			ExtraDescriptionData data;
			if (mappedArchetypeDataBlock != null)
			{
				localeText = new LocaleText(mappedArchetypeDataBlock.Description);
				flag2 = DescriptionDataManager.TryGetArchData(((GameDataBlockBase<ArchetypeDataBlock>)(object)mappedArchetypeDataBlock).persistentID, out data);
			}
			else
			{
				ItemDataBlock block2 = GameDataBlockBase<ItemDataBlock>.GetBlock(idRange.GetCompID((eGearComponent)3));
				flag = flag && (int)block2.inventorySlot == 10;
				flag2 = DescriptionDataManager.TryGetGearData(compID, out data);
				localeText = new LocaleText(block.Description);
			}
			if (!flag && (!flag2 || data.Descriptions.Length == 0))
			{
				_gameObject.SetActive(false);
				return;
			}
			List<LocaleText> list = new List<LocaleText>();
			List<LocaleText> list2 = new List<LocaleText>();
			int num = DescriptionDataManager.Current.GlobalSettings.DefaultDescriptionIndex;
			if (flag2)
			{
				if (data.DescriptionIndexOverride >= 0)
				{
					num = data.DescriptionIndexOverride;
				}
				list2.AddRange(data.Descriptions);
				list.AddRange(data.Headers);
				list.ExpandToSize(list2.Count, LocaleText.Empty);
			}
			LocaleText item = LocaleText.Empty;
			LocaleText item2 = new LocaleText((LocalizedText)localeText);
			if (flag)
			{
				var (localeText2, item3) = CreateGeneratedStats(idRange);
				switch (WeaponStatShowerPlugin.StatsLocation)
				{
				case WeaponStatShowerPlugin.StatsPosition.Last:
					list.Add(localeText2);
					list2.Add(item3);
					break;
				case WeaponStatShowerPlugin.StatsPosition.First:
					list.Insert(0, localeText2);
					list2.Insert(0, item3);
					if (num < list2.Count)
					{
						num++;
					}
					break;
				case WeaponStatShowerPlugin.StatsPosition.Combined:
					item = localeText2;
					item2 = new LocaleText(item3.ToString() + "\n" + item2);
					break;
				}
			}
			num = Math.Min(num, list2.Count);
			list2.Insert(num, item2);
			list.Insert(num, item);
			_descriptions = list2.ToArray();
			_headers = list.ToArray();
			LocaleText localeText3 = new LocaleText(idRange.PublicGearName);
			for (int i = 0; i < _headers.Length; i++)
			{
				if (_headers[i] == LocaleText.Empty)
				{
					_headers[i] = localeText3;
				}
			}
			_index = 0;
			if (num != 0 || WeaponStatShowerPlugin.StatsLocation == WeaponStatShowerPlugin.StatsPosition.Combined)
			{
				((TMP_Text)_infoBox.m_infoMainTitleText).SetText((string)_headers[0], true);
				((TMP_Text)_infoBox.m_infoDescriptionText).SetText((string)_descriptions[0], true);
			}
			if (_descriptions.Length == 1)
			{
				_gameObject.SetActive(false);
				return;
			}
			_gameObject.SetActive(true);
			((TMP_Text)_text).SetText("<< 1 >>", true);
		}

		private void OnBtnPress(int _)
		{
			//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_001a: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = RectTransformUtility.WorldToScreenPoint(CM_Camera.Current.Camera, ((CM_PageBase)_pageLoadout).CursorWorldPosition);
			Vector2 val2 = default(Vector2);
			RectTransformUtility.ScreenPointToLocalPointInRectangle(_rectTrans, val, CM_Camera.Current.Camera, ref val2);
			if (val2.x > 0f)
			{
				_index = (_index + 1) % _descriptions.Length;
			}
			else if (_index > 0)
			{
				_index--;
			}
			else
			{
				_index = _descriptions.Length - 1;
			}
			((TMP_Text)_infoBox.m_infoMainTitleText).SetText((string)_headers[_index], true);
			((TMP_Text)_infoBox.m_infoDescriptionText).SetText((string)_descriptions[_index], true);
			((TMP_Text)_text).SetText($"<< {_index + 1} >>", true);
		}

		private static (LocaleText header, LocaleText desc) CreateGeneratedStats(GearIDRange idRange)
		{
			DescriptionBuilder.Inizialize(idRange, GameDataBlockBase<PlayerDataBlock>.GetBlock(1u), WeaponStatShowerPlugin.ConfigLanguage);
			return (header: new LocaleText(DescriptionBuilder.FireRateFormatter(idRange.PublicGearName)), desc: new LocaleText(DescriptionBuilder.DescriptionFormatter()));
		}
	}
	public class DescriptionDataManager
	{
		public static readonly DescriptionDataManager Current = new DescriptionDataManager();

		private const string GlobalFile = "Global.json";

		private const string DataDir = "ExtraDescriptions";

		private readonly Dictionary<string, List<ExtraDescriptionData>> _fileData = new Dictionary<string, List<ExtraDescriptionData>>();

		private readonly Dictionary<uint, ExtraDescriptionData> _archIdDataMap = new Dictionary<uint, ExtraDescriptionData>();

		private readonly Dictionary<uint, ExtraDescriptionData> _gearIdDataMap = new Dictionary<uint, ExtraDescriptionData>();

		public GlobalData GlobalSettings { get; private set; } = new GlobalData();

		private void GlobalFileChanged(LiveEditEventArgs e)
		{
			WeaponStatShowerPlugin.LogWarning("LiveEdit Global File Changed");
			LiveEdit.TryReadFileContent(e.FullPath, (Action<string>)delegate(string content)
			{
				ReadGlobalContent(content);
			});
		}

		private void ReadGlobalContent(string content)
		{
			if (JSON.TryDeserializeSafe<GlobalData>(content, out var value))
			{
				GlobalSettings = value;
			}
		}

		private void DataFileChanged(LiveEditEventArgs e)
		{
			WeaponStatShowerPlugin.LogWarning("LiveEdit File Changed: " + e.FileName);
			LiveEdit.TryReadFileContent(e.FullPath, (Action<string>)delegate(string content)
			{
				ReadDataContent(e.FullPath, content);
			});
		}

		private void DataFileDeleted(LiveEditEventArgs e)
		{
			WeaponStatShowerPlugin.LogWarning("LiveEdit File Removed: " + e.FileName);
			if (!_fileData.Remove(e.FullPath, out List<ExtraDescriptionData> value))
			{
				return;
			}
			foreach (ExtraDescriptionData item in value)
			{
				if (item.ArchetypeID != 0)
				{
					_archIdDataMap.Remove(item.ArchetypeID);
				}
				if (item.GearCategoryID != 0)
				{
					_gearIdDataMap.Remove(item.GearCategoryID);
				}
			}
		}

		private void DataFileCreated(LiveEditEventArgs e)
		{
			WeaponStatShowerPlugin.LogWarning("LiveEdit File Created: " + e.FileName);
			LiveEdit.TryReadFileContent(e.FullPath, (Action<string>)delegate(string content)
			{
				ReadDataContent(e.FullPath, content);
			});
		}

		private void ReadDataContent(string filepath, string content)
		{
			if (_fileData.TryGetValue(filepath, out List<ExtraDescriptionData> value))
			{
				foreach (ExtraDescriptionData item in value)
				{
					if (item.ArchetypeID != 0)
					{
						_archIdDataMap.Remove(item.ArchetypeID);
					}
					if (item.GearCategoryID != 0)
					{
						_gearIdDataMap.Remove(item.GearCategoryID);
					}
				}
				value.Clear();
			}
			else
			{
				_fileData.Add(filepath, value = new List<ExtraDescriptionData>());
			}
			if (!JSON.TryDeserializeSafe<List<ExtraDescriptionData>>(content, out var value2))
			{
				return;
			}
			value.EnsureCapacity(value2.Count);
			foreach (ExtraDescriptionData item2 in value2)
			{
				if (item2.ArchetypeID != 0 || item2.GearCategoryID != 0)
				{
					if (item2.ArchetypeID != 0 && !_archIdDataMap.TryAdd(item2.ArchetypeID, item2))
					{
						WeaponStatShowerPlugin.LogWarning($"Duplicate archetype ID {item2.ArchetypeID} found. Name: {_archIdDataMap[item2.ArchetypeID].Name}, duplicate name: {item2.Name}");
					}
					if (item2.GearCategoryID != 0 && !_gearIdDataMap.TryAdd(item2.GearCategoryID, item2))
					{
						WeaponStatShowerPlugin.LogWarning($"Duplicate gear category ID {item2.GearCategoryID} found. Name: {_gearIdDataMap[item2.GearCategoryID].Name}, duplicate name: {item2.Name}");
					}
					value.Add(item2);
				}
			}
			value.TrimExcess();
		}

		public DescriptionDataManager()
		{
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			if (!MTFOWrapper.HasMTFO)
			{
				return;
			}
			string text = Path.Combine(MTFOWrapper.CustomPath, "WeaponStatShower");
			string path = Path.Combine(text, "Global.json");
			string text2 = Path.Combine(text, "ExtraDescriptions");
			if (!Directory.Exists(text))
			{
				WeaponStatShowerPlugin.LogInfo("No Weapon Stat Shower directory detected. Creating templates.");
				Directory.CreateDirectory(text2);
				StreamWriter streamWriter;
				using (streamWriter = File.CreateText(path))
				{
					streamWriter.WriteLine(JSON.Serialize(new GlobalData()));
				}
				using (streamWriter = File.CreateText(Path.Combine(text2, "Template.json")))
				{
					streamWriter.WriteLine(JSON.Serialize(ExtraDescriptionData.Template));
				}
			}
			else if (!File.Exists(path))
			{
				using StreamWriter streamWriter2 = File.CreateText(path);
				streamWriter2.WriteLine(JSON.Serialize(new GlobalData()));
			}
			ReadGlobalContent(File.ReadAllText(path));
			foreach (string item in Directory.EnumerateFiles(text2, "*.json", SearchOption.AllDirectories))
			{
				ReadDataContent(item, File.ReadAllText(item));
			}
			LiveEdit.CreateListener(text, "Global.json", false).FileChanged += new LiveEditEventHandler(GlobalFileChanged);
			LiveEditListener obj = LiveEdit.CreateListener(text2, "*.json", true);
			obj.FileCreated += new LiveEditEventHandler(DataFileCreated);
			obj.FileChanged += new LiveEditEventHandler(DataFileChanged);
			obj.FileDeleted += new LiveEditEventHandler(DataFileDeleted);
		}

		internal void Init()
		{
		}

		public static bool TryGetArchData(uint archetypeID, [MaybeNullWhen(false)] out ExtraDescriptionData data)
		{
			return Current._archIdDataMap.TryGetValue(archetypeID, out data);
		}

		public static bool TryGetGearData(uint gearCategoryID, [MaybeNullWhen(false)] out ExtraDescriptionData data)
		{
			return Current._gearIdDataMap.TryGetValue(gearCategoryID, out data);
		}
	}
}
namespace WeaponStatShower.ExtraDescription.Data
{
	public class ExtraDescriptionData
	{
		public static readonly ExtraDescriptionData[] Template = new ExtraDescriptionData[2]
		{
			new ExtraDescriptionData(),
			new ExtraDescriptionData
			{
				Headers = new LocaleText[2]
				{
					LocaleText.Empty,
					new LocaleText("Third Tab")
				},
				Descriptions = new LocaleText[2]
				{
					new LocaleText("Custom tab for testing"),
					new LocaleText("Another custom tab under the third tab")
				},
				Name = "Filled Example"
			}
		};

		public uint ArchetypeID { get; set; }

		public uint GearCategoryID { get; set; }

		public LocaleText[] Headers { get; set; } = Array.Empty<LocaleText>();

		public LocaleText[] Descriptions { get; set; } = Array.Empty<LocaleText>();

		public int DescriptionIndexOverride { get; set; } = -1;

		public string Name { get; set; } = string.Empty;
	}
	public class GlobalData
	{
		public bool PreferHideStats { get; set; }

		public int DefaultDescriptionIndex { get; set; }
	}
}
namespace WeaponStatShower.Dependencies
{
	internal static class MTFOWrapper
	{
		public const string PLUGIN_GUID = "com.dak.MTFO";

		public static readonly bool HasMTFO;

		public static string GameDataPath => MTFOPathAPI.RundownPath;

		public static string CustomPath => MTFOPathAPI.CustomPath;

		public static bool HasCustomDatablocks
		{
			get
			{
				if (HasMTFO)
				{
					return UnsafeHasCustomDatablocks();
				}
				return false;
			}
		}

		static MTFOWrapper()
		{
			HasMTFO = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("com.dak.MTFO");
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool UnsafeHasCustomDatablocks()
		{
			return MTFOPathAPI.HasRundownPath;
		}

		public static void AddOnHotReload(Action action)
		{
			if (HasMTFO)
			{
				AddOnHotReload_Unsafe(action);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void AddOnHotReload_Unsafe(Action action)
		{
			MTFOHotReloadAPI.OnHotReload += action;
		}
	}
	internal static class PartialData
	{
		public const string PLUGIN_GUID = "MTFO.Extension.PartialBlocks";

		public static readonly bool HasPData;

		public static JsonConverter PDataIDConverter;

		static PartialData()
		{
			HasPData = ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey("MTFO.Extension.PartialBlocks");
			if (HasPData)
			{
				SetConverter();
			}
		}

		public static bool TryGetGUID(string text, out uint guid)
		{
			if (!HasPData)
			{
				guid = 0u;
				return false;
			}
			return TryGetGUID_Internal(text, out guid);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool TryGetGUID_Internal(string text, out uint guid)
		{
			return PersistentIDManager.TryGetId(text, ref guid);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void SetConverter()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			PDataIDConverter = (JsonConverter)new PersistentIDConverter();
		}
	}
}