Decompiled source of Perfect Oils v1.3.0

PerfectOils.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using PerfectRandom.Sulfur.Core;
using PerfectRandom.Sulfur.Core.CharacterStats;
using PerfectRandom.Sulfur.Core.Items;
using PerfectRandom.Sulfur.Core.Stats;
using PerfectRandom.Sulfur.Core.UI.ItemDescription;
using PerfectRandom.Sulfur.Core.Weapons;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("PerfectOils")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PerfectOils")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("fca0f276-8db3-47a4-b077-acfc5373e719")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PerfectOils
{
	internal sealed class OilTraitService
	{
		internal sealed class OilDefinitionInfo
		{
			internal readonly EnchantmentDefinition Definition;

			internal readonly bool HasMoreBulletDrop;

			internal OilDefinitionInfo(EnchantmentDefinition definition)
			{
				Definition = definition;
				HasMoreBulletDrop = NegativeTraitPolicy.HasMoreBulletDropTrait(((Object)(object)definition == (Object)null) ? null : definition.modifiersApplied);
			}
		}

		private struct ModifierSignature
		{
			internal readonly ItemAttributes Attribute;

			internal readonly StatModType ModType;

			internal readonly float Value;

			internal readonly NegativeOilTrait Traits;

			internal ModifierSignature(ItemModifierContainer modifier, NegativeOilTrait traits)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				Attribute = modifier.attribute;
				ModType = modifier.modType;
				Value = modifier.value;
				Traits = traits;
			}

			internal bool Matches(ItemAttributes attribute, StatModifier modifier)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: 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)
				return modifier != null && Attribute == attribute && ModType == modifier.Type && Math.Abs(Value - modifier.Value) <= 1E-06f;
			}
		}

		private readonly ManualLogSource _log;

		private readonly TraitConfiguration _settings;

		private readonly Dictionary<uint, List<ModifierSignature>> _classifiedBySourceId = new Dictionary<uint, List<ModifierSignature>>();

		private readonly Dictionary<ItemDefinition, OilDefinitionInfo> _oilInfoByItem = new Dictionary<ItemDefinition, OilDefinitionInfo>();

		private readonly Dictionary<EnchantmentDefinition, OilDefinitionInfo> _oilInfoByDefinition = new Dictionary<EnchantmentDefinition, OilDefinitionInfo>();

		private readonly Dictionary<EnchantmentDefinition, bool> _originalDurabilityFlags = new Dictionary<EnchantmentDefinition, bool>();

		private bool _initialized;

		private bool _loggedFirstRuntimeSuppression;

		private bool _warnedUnavailableDatabase;

		private bool _warnedEmptyDatabase;

		private bool _warnedNoOilDefinitions;

		internal bool IsInitialized => _initialized;

		internal OilTraitService(ManualLogSource log, TraitConfiguration settings)
		{
			_log = log;
			_settings = settings;
		}

		internal bool Initialize(AsyncAssetLoading assets, bool detailedLogging)
		{
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Invalid comparison between Unknown and I4
			if (_initialized)
			{
				return true;
			}
			if ((Object)(object)assets == (Object)null || (Object)(object)assets.itemDatabase == (Object)null || (Object)(object)assets.enchantmentDatabase == (Object)null)
			{
				if (!_warnedUnavailableDatabase)
				{
					_log.LogWarning((object)"[PerfectOils] Asset loading completed, but an oil database was unavailable; initialization will be retried.");
					_warnedUnavailableDatabase = true;
				}
				return false;
			}
			List<ItemDefinition> rawList = assets.itemDatabase.GetRawList();
			if (rawList == null)
			{
				if (!_warnedUnavailableDatabase)
				{
					_log.LogWarning((object)"[PerfectOils] Item database returned no raw item list; initialization will be retried.");
					_warnedUnavailableDatabase = true;
				}
				return false;
			}
			if (rawList.Count == 0)
			{
				if (!_warnedEmptyDatabase)
				{
					_log.LogWarning((object)"[PerfectOils] Item database is present but still empty; initialization will be retried.");
					_warnedEmptyDatabase = true;
				}
				return false;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			int num9 = 0;
			for (int i = 0; i < rawList.Count; i++)
			{
				ItemDefinition val = rawList[i];
				if (!IsOilItem(val))
				{
					continue;
				}
				num++;
				EnchantmentDefinition val2;
				try
				{
					val2 = assets.enchantmentDatabase[val.appliesEnchantment];
				}
				catch (Exception ex)
				{
					_log.LogWarning((object)("[PerfectOils] Could not resolve enchantment for oil '" + SafeOilName(val) + "': " + ex.Message));
					continue;
				}
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				if (!_oilInfoByDefinition.TryGetValue(val2, out var value))
				{
					value = new OilDefinitionInfo(val2);
					_oilInfoByDefinition.Add(val2, value);
					num2++;
					uint key = GlobalId.op_Implicit(((EnchantmentId)(ref val2.id)).AsGlobalId());
					List<ModifierSignature> list = new List<ModifierSignature>();
					List<ItemModifierContainer> modifiersApplied = val2.modifiersApplied;
					if (modifiersApplied != null)
					{
						for (int j = 0; j < modifiersApplied.Count; j++)
						{
							ItemModifierContainer val3 = modifiersApplied[j];
							NegativeOilTrait negativeOilTrait = NegativeTraitPolicy.Classify(val3, value.HasMoreBulletDrop);
							if (negativeOilTrait == NegativeOilTrait.None)
							{
								continue;
							}
							list.Add(new ModifierSignature(val3, negativeOilTrait));
							num3++;
							if ((negativeOilTrait & NegativeOilTrait.NegativeBulletSpeed) != NegativeOilTrait.None)
							{
								num5++;
							}
							if ((negativeOilTrait & NegativeOilTrait.NegativeDamage) != NegativeOilTrait.None)
							{
								if ((int)val3.modType == 100)
								{
									num6++;
								}
								else
								{
									num7++;
								}
							}
							if ((negativeOilTrait & NegativeOilTrait.NegativeBulletSize) != NegativeOilTrait.None)
							{
								num8++;
							}
							if ((negativeOilTrait & NegativeOilTrait.NegativeRpm) != NegativeOilTrait.None)
							{
								num9++;
							}
							if (_settings.ShouldRemove(negativeOilTrait))
							{
								num4++;
							}
							if (detailedLogging)
							{
								_log.LogInfo((object)("[PerfectOils] Classified " + NegativeTraitPolicy.Describe(negativeOilTrait) + " from '" + SafeDefinitionName(val2, val) + "' [active=" + _settings.ShouldRemove(negativeOilTrait) + ", attribute=" + ((object)Unsafe.As<ItemAttributes, ItemAttributes>(ref val3.attribute)/*cast due to .constrained prefix*/).ToString() + ", type=" + ((object)Unsafe.As<StatModType, StatModType>(ref val3.modType)/*cast due to .constrained prefix*/).ToString() + ", value=" + val3.value + "]."));
							}
						}
					}
					if (list.Count > 0)
					{
						_classifiedBySourceId[key] = list;
					}
					_originalDurabilityFlags[val2] = val2.CostsDurability;
				}
				_oilInfoByItem[val] = value;
			}
			if (num == 0 || num2 == 0)
			{
				if (!_warnedNoOilDefinitions)
				{
					_log.LogWarning((object)("[PerfectOils] Scanned " + rawList.Count + " item definitions but found no runtime enchantment oils; initialization will be retried."));
					_warnedNoOilDefinitions = true;
				}
				return false;
			}
			_initialized = true;
			_log.LogInfo((object)("[PerfectOils] Scanned " + rawList.Count + " item definitions. Indexed " + num + " oil items across " + num2 + " unique enchantments; " + num3 + " known negative modifiers were classified, and " + num4 + " are currently enabled for suppression by config. Signed-value traits: bulletSpeed=" + num5 + ", damageFlat=" + num6 + ", damagePercent=" + num7 + ", bulletSize=" + num8 + ", rpm=" + num9 + "."));
			return true;
		}

		internal unsafe bool ShouldSuppress(ItemAttributes attribute, StatModifier modifier)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if (!_initialized || modifier == null)
			{
				return false;
			}
			if (!_classifiedBySourceId.TryGetValue(modifier.SourceId, out var value))
			{
				return false;
			}
			for (int i = 0; i < value.Count; i++)
			{
				ModifierSignature modifierSignature = value[i];
				if (modifierSignature.Matches(attribute, modifier) && _settings.ShouldRemove(modifierSignature.Traits))
				{
					if (!_loggedFirstRuntimeSuppression)
					{
						_loggedFirstRuntimeSuppression = true;
						ManualLogSource log = _log;
						string[] obj = new string[7]
						{
							"[PerfectOils] Runtime suppression is active; the first configured oil modifier was blocked [trait=",
							NegativeTraitPolicy.Describe(modifierSignature.Traits),
							", attribute=",
							((object)(*(ItemAttributes*)(&attribute))/*cast due to .constrained prefix*/).ToString(),
							", sourceId=",
							null,
							null
						};
						uint sourceId = modifier.SourceId;
						obj[5] = sourceId.ToString();
						obj[6] = "].";
						log.LogInfo((object)string.Concat(obj));
					}
					return true;
				}
			}
			return false;
		}

		internal bool TryGetOilInfo(InventoryItem item, out OilDefinitionInfo info)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			info = null;
			if (!_initialized || (Object)(object)item == (Object)null || (Object)(object)item.itemDefinition == (Object)null)
			{
				return false;
			}
			ItemDefinition itemDefinition = item.itemDefinition;
			if (_oilInfoByItem.TryGetValue(itemDefinition, out info))
			{
				return true;
			}
			if (!((EnchantmentId)(ref itemDefinition.appliesEnchantment)).IsValid)
			{
				return false;
			}
			try
			{
				EnchantmentDefinition asset = AssetAccess.GetAsset(itemDefinition.appliesEnchantment);
				return (Object)(object)asset != (Object)null && _oilInfoByDefinition.TryGetValue(asset, out info);
			}
			catch
			{
				info = null;
				return false;
			}
		}

		internal void RefreshDurabilityFlags(bool pluginEnabled)
		{
			bool flag = pluginEnabled && _settings.RemoveExtraDurabilityCost.Value;
			foreach (KeyValuePair<EnchantmentDefinition, bool> originalDurabilityFlag in _originalDurabilityFlags)
			{
				if ((Object)(object)originalDurabilityFlag.Key != (Object)null)
				{
					originalDurabilityFlag.Key.CostsDurability = !flag && originalDurabilityFlag.Value;
				}
			}
		}

		internal void RestoreOriginalDefinitions()
		{
			foreach (KeyValuePair<EnchantmentDefinition, bool> originalDurabilityFlag in _originalDurabilityFlags)
			{
				if ((Object)(object)originalDurabilityFlag.Key != (Object)null)
				{
					originalDurabilityFlag.Key.CostsDurability = originalDurabilityFlag.Value;
				}
			}
			_classifiedBySourceId.Clear();
			_oilInfoByItem.Clear();
			_oilInfoByDefinition.Clear();
			_originalDurabilityFlags.Clear();
			_initialized = false;
			_loggedFirstRuntimeSuppression = false;
			_warnedUnavailableDatabase = false;
			_warnedEmptyDatabase = false;
			_warnedNoOilDefinitions = false;
		}

		private static bool IsOilItem(ItemDefinition itemDefinition)
		{
			return (Object)(object)itemDefinition != (Object)null && itemDefinition.IsEnchantment && ((EnchantmentId)(ref itemDefinition.appliesEnchantment)).IsValid;
		}

		private static string SafeOilName(ItemDefinition oilItem)
		{
			if ((Object)(object)oilItem == (Object)null)
			{
				return "<null oil>";
			}
			if (!string.IsNullOrEmpty(oilItem.displayName))
			{
				return oilItem.displayName;
			}
			return ((object)Unsafe.As<ItemId, ItemId>(ref oilItem.id)/*cast due to .constrained prefix*/).ToString();
		}

		private static string SafeDefinitionName(EnchantmentDefinition definition, ItemDefinition oilItem)
		{
			if ((Object)(object)definition != (Object)null && !string.IsNullOrEmpty(definition.enchantmentName))
			{
				return definition.enchantmentName;
			}
			return SafeOilName(oilItem);
		}
	}
	[Flags]
	internal enum NegativeOilTrait
	{
		None = 0,
		DisableAiming = 1,
		MoreBulletDrop = 2,
		MoreDrag = 4,
		ExtraAmmoConsumeChance = 8,
		DecreaseAccuracyWhenMoving = 0x10,
		DecreaseMoveSpeed = 0x20,
		DecreaseJumpPower = 0x40,
		DecreaseLootChanceMultiplier = 0x80,
		DisableMoneyDrops = 0x100,
		DisableOrganDrops = 0x200,
		NegativeBulletSpeed = 0x400,
		NegativeDamage = 0x800,
		NegativeBulletSize = 0x1000,
		NegativeRpm = 0x2000,
		ExtraDurabilityCost = 0x4000
	}
	internal static class NegativeTraitPolicy
	{
		private const float Epsilon = 1E-06f;

		internal static bool HasMoreBulletDropTrait(IList<ItemModifierContainer> modifiers)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			if (modifiers == null)
			{
				return false;
			}
			for (int i = 0; i < modifiers.Count; i++)
			{
				ItemModifierContainer val = modifiers[i];
				if (val != null && (int)val.attribute == 102 && IncreasesAttribute(val))
				{
					return true;
				}
			}
			return false;
		}

		internal static NegativeOilTrait Classify(ItemModifierContainer modifier, bool oilHasMoreBulletDrop)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Invalid comparison between Unknown and I4
			//IL_001f: 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_006b: Expected I4, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected I4, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Invalid comparison between Unknown and I4
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Invalid comparison between Unknown and I4
			if (modifier == null)
			{
				return NegativeOilTrait.None;
			}
			ItemAttributes attribute = modifier.attribute;
			ItemAttributes val = attribute;
			if ((int)val <= 52)
			{
				switch (val - 1)
				{
				default:
					if ((int)val != 41)
					{
						if ((int)val != 52)
						{
							break;
						}
						return DecreasesAttribute(modifier) ? NegativeOilTrait.NegativeBulletSize : NegativeOilTrait.None;
					}
					return (oilHasMoreBulletDrop && IncreasesAttribute(modifier)) ? NegativeOilTrait.MoreBulletDrop : NegativeOilTrait.None;
				case 7:
					return IncreasesAttribute(modifier) ? NegativeOilTrait.DisableAiming : NegativeOilTrait.None;
				case 2:
					return IncreasesAttribute(modifier) ? NegativeOilTrait.ExtraAmmoConsumeChance : NegativeOilTrait.None;
				case 0:
					return DecreasesAttribute(modifier) ? NegativeOilTrait.DecreaseAccuracyWhenMoving : NegativeOilTrait.None;
				case 16:
					return DecreasesAttribute(modifier) ? NegativeOilTrait.DecreaseMoveSpeed : NegativeOilTrait.None;
				case 14:
					return DecreasesAttribute(modifier) ? NegativeOilTrait.DecreaseJumpPower : NegativeOilTrait.None;
				case 15:
					return DecreasesAttribute(modifier) ? NegativeOilTrait.DecreaseLootChanceMultiplier : NegativeOilTrait.None;
				case 8:
					return IncreasesAttribute(modifier) ? NegativeOilTrait.DisableMoneyDrops : NegativeOilTrait.None;
				case 9:
					return IncreasesAttribute(modifier) ? NegativeOilTrait.DisableOrganDrops : NegativeOilTrait.None;
				case 5:
				case 6:
					return DecreasesAttribute(modifier) ? NegativeOilTrait.NegativeDamage : NegativeOilTrait.None;
				case 1:
				case 3:
				case 4:
				case 10:
				case 11:
				case 12:
				case 13:
					break;
				}
			}
			else
			{
				if ((int)val == 56)
				{
					return DecreasesAttribute(modifier) ? NegativeOilTrait.NegativeRpm : NegativeOilTrait.None;
				}
				switch (val - 61)
				{
				default:
					if ((int)val != 102)
					{
						break;
					}
					return IncreasesAttribute(modifier) ? NegativeOilTrait.MoreBulletDrop : NegativeOilTrait.None;
				case 4:
					return IncreasesAttribute(modifier) ? NegativeOilTrait.MoreDrag : NegativeOilTrait.None;
				case 0:
					if (!DecreasesAttribute(modifier))
					{
						return NegativeOilTrait.None;
					}
					return (NegativeOilTrait)(0x400 | (oilHasMoreBulletDrop ? 2 : 0));
				case 2:
					return IncreasesAttribute(modifier) ? NegativeOilTrait.ExtraDurabilityCost : NegativeOilTrait.None;
				case 1:
				case 3:
					break;
				}
			}
			return NegativeOilTrait.None;
		}

		internal static string Describe(NegativeOilTrait traits)
		{
			if (traits == NegativeOilTrait.None)
			{
				return "None";
			}
			List<string> list = new List<string>();
			AddName(list, traits, NegativeOilTrait.DisableAiming, "Disable Aiming");
			AddName(list, traits, NegativeOilTrait.MoreBulletDrop, "More Bullet Drop");
			AddName(list, traits, NegativeOilTrait.MoreDrag, "More Drag");
			AddName(list, traits, NegativeOilTrait.ExtraAmmoConsumeChance, "Extra Ammo Consume Chance");
			AddName(list, traits, NegativeOilTrait.DecreaseAccuracyWhenMoving, "Decrease Accuracy When Moving");
			AddName(list, traits, NegativeOilTrait.DecreaseMoveSpeed, "Decrease Move Speed");
			AddName(list, traits, NegativeOilTrait.DecreaseJumpPower, "Decrease Jump Power");
			AddName(list, traits, NegativeOilTrait.DecreaseLootChanceMultiplier, "Decrease Loot Chance Multiplier");
			AddName(list, traits, NegativeOilTrait.DisableMoneyDrops, "Disable Money Drops");
			AddName(list, traits, NegativeOilTrait.DisableOrganDrops, "Disable Organ Drops");
			AddName(list, traits, NegativeOilTrait.NegativeBulletSpeed, "Negative Bullet Speed");
			AddName(list, traits, NegativeOilTrait.NegativeDamage, "Negative Damage");
			AddName(list, traits, NegativeOilTrait.NegativeBulletSize, "Negative Bullet Size");
			AddName(list, traits, NegativeOilTrait.NegativeRpm, "Negative RPM");
			AddName(list, traits, NegativeOilTrait.ExtraDurabilityCost, "Extra Oil Durability Cost");
			return string.Join(" + ", list.ToArray());
		}

		private static bool IncreasesAttribute(ItemModifierContainer modifier)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return IsSupportedModType(modifier.modType) && modifier.value > 1E-06f;
		}

		private static bool DecreasesAttribute(ItemModifierContainer modifier)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return IsSupportedModType(modifier.modType) && modifier.value < -1E-06f;
		}

		private static bool IsSupportedModType(StatModType modType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			return (int)modType == 100 || (int)modType == 200 || (int)modType == 300;
		}

		private static void AddName(List<string> names, NegativeOilTrait traits, NegativeOilTrait flag, string name)
		{
			if ((traits & flag) != NegativeOilTrait.None)
			{
				names.Add(name);
			}
		}
	}
	[BepInPlugin("com.ryuka.sulfur.perfectoils", "Perfect Oils", "1.3.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.ryuka.sulfur.perfectoils";

		public const string PluginName = "Perfect Oils";

		public const string PluginVersion = "1.3.0";

		private const float InitializationRetryInterval = 1f;

		private Harmony _harmony;

		private AsyncAssetLoading _assetLoader;

		private float _nextInitializationAttempt;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal ConfigEntry<bool> Enabled { get; private set; }

		internal ConfigEntry<bool> ShowRemovedTraitsWithStrikethrough { get; private set; }

		internal ConfigEntry<bool> DetailedLogging { get; private set; }

		internal TraitConfiguration TraitSettings { get; private set; }

		internal OilTraitService OilTraits { get; private set; }

		internal TooltipStrikeRenderer TooltipRenderer { get; private set; }

		private void Awake()
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Perfect Oils. Individual undesirable traits can be selected in the Traits section.");
			ShowRemovedTraitsWithStrikethrough = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowRemovedTraitsWithStrikethrough", true, "Keep the original undesirable-trait text in oil tooltips and draw a strikethrough over lines currently disabled by this mod.");
			DetailedLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DetailedLogging", false, "Log each classified oil modifier and tooltip line. Keep disabled during normal play.");
			TraitSettings = new TraitConfiguration(((BaseUnityPlugin)this).Config);
			OilTraits = new OilTraitService(((BaseUnityPlugin)this).Logger, TraitSettings);
			TooltipRenderer = new TooltipStrikeRenderer(OilTraits, TraitSettings, ((BaseUnityPlugin)this).Logger);
			Enabled.SettingChanged += OnDurabilitySettingChanged;
			TraitSettings.RemoveExtraDurabilityCost.SettingChanged += OnDurabilitySettingChanged;
			_harmony = new Harmony("com.ryuka.sulfur.perfectoils");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[PerfectOils] Patches applied. Waiting for the SULFUR asset databases.");
		}

		private void Update()
		{
			if (OilTraits != null && !OilTraits.IsInitialized && !(Time.unscaledTime < _nextInitializationAttempt))
			{
				if ((Object)(object)_assetLoader == (Object)null)
				{
					_assetLoader = Object.FindFirstObjectByType<AsyncAssetLoading>();
				}
				if ((Object)(object)_assetLoader == (Object)null || !_assetLoader.loadingDone)
				{
					_nextInitializationAttempt = Time.unscaledTime + 1f;
				}
				else
				{
					TryInitializeOilTraits(_assetLoader);
				}
			}
		}

		internal void NotifyAssetsReady(AsyncAssetLoading assetLoader)
		{
			if (!((Object)(object)assetLoader == (Object)null))
			{
				_assetLoader = assetLoader;
				TryInitializeOilTraits(assetLoader);
			}
		}

		private void TryInitializeOilTraits(AsyncAssetLoading assetLoader)
		{
			if (OilTraits != null && !OilTraits.IsInitialized)
			{
				if (!OilTraits.Initialize(assetLoader, DetailedLogging.Value))
				{
					_nextInitializationAttempt = Time.unscaledTime + 1f;
				}
				else
				{
					OilTraits.RefreshDurabilityFlags(Enabled.Value);
				}
			}
		}

		private void OnDurabilitySettingChanged(object sender, EventArgs eventArgs)
		{
			if (OilTraits != null && OilTraits.IsInitialized)
			{
				OilTraits.RefreshDurabilityFlags(Enabled.Value);
			}
		}

		private void OnDestroy()
		{
			Enabled.SettingChanged -= OnDurabilitySettingChanged;
			if (TraitSettings != null)
			{
				TraitSettings.RemoveExtraDurabilityCost.SettingChanged -= OnDurabilitySettingChanged;
			}
			if (OilTraits != null)
			{
				OilTraits.RestoreOriginalDefinitions();
			}
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
			if (Instance == this)
			{
				Instance = null;
				Log = null;
			}
		}
	}
	internal sealed class TooltipStrikeRenderer
	{
		private enum LineKind
		{
			Attribute,
			Description
		}

		private sealed class LineSpec
		{
			internal readonly LineKind Kind;

			internal readonly string Key;

			internal readonly string Value;

			internal readonly bool IsRemoved;

			internal LineSpec(LineKind kind, string key, string value, bool isRemoved)
			{
				Kind = kind;
				Key = key ?? string.Empty;
				Value = value ?? string.Empty;
				IsRemoved = isRemoved;
			}
		}

		private sealed class RenderedLine
		{
			internal readonly LineKind Kind;

			internal readonly int SiblingIndex;

			internal readonly string Key;

			internal readonly string Value;

			internal readonly TMP_Text[] TextComponents;

			internal RenderedLine(LineKind kind, int siblingIndex, string key, string value, TMP_Text[] textComponents)
			{
				Kind = kind;
				SiblingIndex = siblingIndex;
				Key = key ?? string.Empty;
				Value = value ?? string.Empty;
				TextComponents = textComponents;
			}
		}

		private static class LocalizationBridge
		{
			private static readonly MethodInfo TryGetTranslationMethod = FindTryGetTranslation();

			internal static string GetTranslationOrFallback(string term, string fallback)
			{
				if (TryGetTranslationMethod != null)
				{
					try
					{
						object[] array = new object[9] { term, null, true, 0, true, false, null, null, true };
						bool flag = (bool)TryGetTranslationMethod.Invoke(null, array);
						string text = array[1] as string;
						if (flag && !string.IsNullOrEmpty(text))
						{
							return text;
						}
					}
					catch
					{
					}
				}
				return fallback ?? string.Empty;
			}

			private static MethodInfo FindTryGetTranslation()
			{
				Type type = AccessTools.TypeByName("I2.Loc.LocalizationManager");
				if (type == null)
				{
					return null;
				}
				MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!(methodInfo.Name != "TryGetTranslation"))
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (parameters.Length == 9 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string).MakeByRefType())
						{
							return methodInfo;
						}
					}
				}
				return null;
			}
		}

		private static readonly FieldInfo AttributesInUseField = AccessTools.Field(typeof(ItemDescription), "attributesInUse");

		private static readonly FieldInfo DescriptionTextInUseField = AccessTools.Field(typeof(ItemDescription), "descriptionTextInUse");

		private static readonly FieldInfo KeyTextField = AccessTools.Field(typeof(ItemDescriptionAttribute), "keyText");

		private static readonly FieldInfo ValueTextField = AccessTools.Field(typeof(ItemDescriptionAttribute), "valueText");

		private static readonly FieldInfo ModifierTextField = AccessTools.Field(typeof(ItemDescriptionAttribute), "modifierText");

		private static readonly MethodInfo FormatModifierValueMethod = AccessTools.Method(typeof(ItemDescription), "GetValueAsStringDependingOnModType", new Type[2]
		{
			typeof(ItemModifierContainer),
			typeof(ItemAttribute)
		}, (Type[])null);

		private readonly OilTraitService _oilTraits;

		private readonly TraitConfiguration _settings;

		private readonly ManualLogSource _log;

		private bool _loggedFirstStrikethrough;

		internal TooltipStrikeRenderer(OilTraitService oilTraits, TraitConfiguration settings, ManualLogSource log)
		{
			_oilTraits = oilTraits;
			_settings = settings;
			_log = log;
		}

		internal void Apply(ItemDescription description, InventoryItem item, bool detailedLogging)
		{
			if ((Object)(object)description == (Object)null || (Object)(object)item == (Object)null || !_oilTraits.TryGetOilInfo(item, out var info) || info == null || (Object)(object)info.Definition == (Object)null || info.Definition.modifiersApplied == null)
			{
				return;
			}
			List<LineSpec> list = BuildLineSpecs(description, info);
			if (list.Count == 0)
			{
				return;
			}
			List<RenderedLine> list2 = CollectRenderedLines(description);
			if (list2.Count == 0)
			{
				return;
			}
			List<int> list3 = FindBestOrderedMatch(list2, list);
			if (list3 == null)
			{
				list3 = FindRemovedLinesFallback(list2, list);
				if (detailedLogging)
				{
					_log.LogWarning((object)("[PerfectOils] Could not match the complete oil modifier block for '" + SafeItemName(item) + "'; used exact removed-line fallback matching."));
				}
			}
			if (list3 == null)
			{
				return;
			}
			int num = 0;
			for (int i = 0; i < list.Count && i < list3.Count; i++)
			{
				if (list[i].IsRemoved && list3[i] >= 0)
				{
					ApplyStrikethrough(list2[list3[i]]);
					num++;
				}
			}
			if (num > 0 && !_loggedFirstStrikethrough)
			{
				_loggedFirstStrikethrough = true;
				_log.LogInfo((object)"[PerfectOils] Tooltip integration is active; removed oil traits are being shown with strikethrough.");
			}
			if (detailedLogging && num > 0)
			{
				_log.LogInfo((object)("[PerfectOils] Marked " + num + " removed trait line(s) in the tooltip for '" + SafeItemName(item) + "'."));
			}
		}

		private List<LineSpec> BuildLineSpecs(ItemDescription description, OilTraitService.OilDefinitionInfo info)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			List<LineSpec> list = new List<LineSpec>();
			List<ItemModifierContainer> modifiersApplied = info.Definition.modifiersApplied;
			for (int i = 0; i < modifiersApplied.Count; i++)
			{
				ItemModifierContainer val = modifiersApplied[i];
				if (val == null || (int)val.attribute == 0)
				{
					continue;
				}
				ItemAttribute asset;
				try
				{
					asset = AssetAccess.GetAsset(val.attribute);
				}
				catch
				{
					continue;
				}
				if ((Object)(object)asset == (Object)null || !asset.showInItemDescription)
				{
					continue;
				}
				NegativeOilTrait traits = NegativeTraitPolicy.Classify(val, info.HasMoreBulletDrop);
				bool isRemoved = _settings.ShouldRemove(traits);
				if (asset.simplifiedModAmount)
				{
					bool flag = val.value > 0f;
					string term = string.Format(flag ? "ItemAttributes/{0}_simplifiedIncrease" : "ItemAttributes/{0}_simplifiedDecrease", val.attribute);
					string fallback = (flag ? asset.simplifiedIncreaseString : asset.simplifiedDecreaseString);
					string translationOrFallback = LocalizationBridge.GetTranslationOrFallback(term, fallback);
					if (!string.IsNullOrEmpty(translationOrFallback))
					{
						list.Add(new LineSpec(LineKind.Description, translationOrFallback, string.Empty, isRemoved));
					}
					continue;
				}
				string term2 = $"ItemAttributes/{val.attribute}_itemDescription";
				string translationOrFallback2 = LocalizationBridge.GetTranslationOrFallback(term2, asset.itemDescriptionName);
				if (asset.isBooleanAttribute)
				{
					if (!string.IsNullOrEmpty(translationOrFallback2))
					{
						list.Add(new LineSpec(LineKind.Description, translationOrFallback2, string.Empty, isRemoved));
					}
				}
				else
				{
					string value = FormatModifierValue(description, val, asset);
					string key = translationOrFallback2 + (string.IsNullOrEmpty(value) ? string.Empty : ":");
					list.Add(new LineSpec(LineKind.Attribute, key, value, isRemoved));
				}
			}
			return list;
		}

		private static string FormatModifierValue(ItemDescription description, ItemModifierContainer modifier, ItemAttribute attribute)
		{
			if (FormatModifierValueMethod == null)
			{
				return modifier.GetValueString();
			}
			try
			{
				return ((string)FormatModifierValueMethod.Invoke(description, new object[2] { modifier, attribute })) ?? string.Empty;
			}
			catch
			{
				return modifier.GetValueString() ?? string.Empty;
			}
		}

		private static List<RenderedLine> CollectRenderedLines(ItemDescription description)
		{
			List<RenderedLine> list = new List<RenderedLine>();
			List<ItemDescriptionAttribute> list2 = ((AttributesInUseField == null) ? null : (AttributesInUseField.GetValue(description) as List<ItemDescriptionAttribute>));
			if (list2 != null)
			{
				for (int i = 0; i < list2.Count; i++)
				{
					ItemDescriptionAttribute val = list2[i];
					if (!((Object)(object)val == (Object)null))
					{
						TMP_Text textField = GetTextField(KeyTextField, val);
						TMP_Text textField2 = GetTextField(ValueTextField, val);
						TMP_Text textField3 = GetTextField(ModifierTextField, val);
						list.Add(new RenderedLine(LineKind.Attribute, ((Component)val).transform.GetSiblingIndex(), GetComparableText(textField), GetComparableText(textField2), (TMP_Text[])(object)new TMP_Text[3] { textField, textField2, textField3 }));
					}
				}
			}
			List<ItemDescriptionText> list3 = ((DescriptionTextInUseField == null) ? null : (DescriptionTextInUseField.GetValue(description) as List<ItemDescriptionText>));
			if (list3 != null)
			{
				for (int j = 0; j < list3.Count; j++)
				{
					ItemDescriptionText val2 = list3[j];
					if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.textComp == (Object)null))
					{
						int siblingIndex = ((Component)val2).transform.GetSiblingIndex();
						string comparableText = GetComparableText((TMP_Text)(object)val2.textComp);
						string empty = string.Empty;
						TMP_Text[] textComponents = (TMP_Text[])(object)new TextMeshProUGUI[1] { val2.textComp };
						list.Add(new RenderedLine(LineKind.Description, siblingIndex, comparableText, empty, textComponents));
					}
				}
			}
			list.Sort(delegate(RenderedLine left, RenderedLine right)
			{
				int siblingIndex2 = left.SiblingIndex;
				return siblingIndex2.CompareTo(right.SiblingIndex);
			});
			return list;
		}

		private static TMP_Text GetTextField(FieldInfo field, object instance)
		{
			return (TMP_Text)((field == null) ? null : /*isinst with value type is only supported in some contexts*/);
		}

		private static string GetComparableText(TMP_Text text)
		{
			return ((Object)(object)text == (Object)null) ? string.Empty : RemoveOwnStrikeTags(text.text ?? string.Empty);
		}

		private static List<int> FindBestOrderedMatch(List<RenderedLine> lines, List<LineSpec> specs)
		{
			List<int> result = null;
			int num = int.MaxValue;
			for (int i = 0; i < lines.Count; i++)
			{
				if (!Matches(lines[i], specs[0]))
				{
					continue;
				}
				List<int> list = new List<int>(specs.Count) { i };
				int num2 = i + 1;
				bool flag = true;
				for (int j = 1; j < specs.Count; j++)
				{
					int num3 = -1;
					for (int k = num2; k < lines.Count; k++)
					{
						if (Matches(lines[k], specs[j]))
						{
							num3 = k;
							break;
						}
					}
					if (num3 < 0)
					{
						flag = false;
						break;
					}
					list.Add(num3);
					num2 = num3 + 1;
				}
				if (flag)
				{
					int num4 = list[list.Count - 1] - list[0];
					if (num4 < num)
					{
						result = list;
						num = num4;
					}
				}
			}
			return result;
		}

		private static List<int> FindRemovedLinesFallback(List<RenderedLine> lines, List<LineSpec> specs)
		{
			List<int> list = new List<int>(specs.Count);
			HashSet<int> hashSet = new HashSet<int>();
			bool flag = false;
			for (int i = 0; i < specs.Count; i++)
			{
				if (!specs[i].IsRemoved)
				{
					list.Add(-1);
					continue;
				}
				int item = -1;
				for (int j = 0; j < lines.Count; j++)
				{
					if (!hashSet.Contains(j) && Matches(lines[j], specs[i]))
					{
						item = j;
						hashSet.Add(j);
						flag = true;
						break;
					}
				}
				list.Add(item);
			}
			return flag ? list : null;
		}

		private static bool Matches(RenderedLine line, LineSpec spec)
		{
			return line.Kind == spec.Kind && string.Equals(line.Key, spec.Key, StringComparison.Ordinal) && string.Equals(line.Value, spec.Value, StringComparison.Ordinal);
		}

		private static void ApplyStrikethrough(RenderedLine line)
		{
			for (int i = 0; i < line.TextComponents.Length; i++)
			{
				TMP_Text val = line.TextComponents[i];
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(val.text))
				{
					string text = RemoveOwnStrikeTags(val.text);
					val.text = "<s>" + text + "</s>";
				}
			}
		}

		private static string RemoveOwnStrikeTags(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return string.Empty;
			}
			if (text.StartsWith("<s>", StringComparison.Ordinal) && text.EndsWith("</s>", StringComparison.Ordinal))
			{
				return text.Substring("<s>".Length, text.Length - "<s>".Length - "</s>".Length);
			}
			return text;
		}

		private static string SafeItemName(InventoryItem item)
		{
			if ((Object)(object)item == (Object)null || (Object)(object)item.itemDefinition == (Object)null)
			{
				return "<unknown oil>";
			}
			return string.IsNullOrEmpty(item.itemDefinition.displayName) ? ((object)item.itemDefinition).ToString() : item.itemDefinition.displayName;
		}
	}
	internal sealed class TraitConfiguration
	{
		internal ConfigEntry<bool> RemoveDisableAiming { get; private set; }

		internal ConfigEntry<bool> RemoveMoreBulletDrop { get; private set; }

		internal ConfigEntry<bool> RemoveMoreDrag { get; private set; }

		internal ConfigEntry<bool> RemoveExtraAmmoConsumeChance { get; private set; }

		internal ConfigEntry<bool> RemoveDecreaseAccuracyWhenMoving { get; private set; }

		internal ConfigEntry<bool> RemoveDecreaseMoveSpeed { get; private set; }

		internal ConfigEntry<bool> RemoveDecreaseJumpPower { get; private set; }

		internal ConfigEntry<bool> RemoveDecreaseLootChanceMultiplier { get; private set; }

		internal ConfigEntry<bool> RemoveDisableMoneyDrops { get; private set; }

		internal ConfigEntry<bool> RemoveDisableOrganDrops { get; private set; }

		internal ConfigEntry<bool> RemoveNegativeBulletSpeed { get; private set; }

		internal ConfigEntry<bool> RemoveNegativeDamage { get; private set; }

		internal ConfigEntry<bool> RemoveNegativeBulletSize { get; private set; }

		internal ConfigEntry<bool> RemoveNegativeRpm { get; private set; }

		internal ConfigEntry<bool> RemoveExtraDurabilityCost { get; private set; }

		internal TraitConfiguration(ConfigFile config)
		{
			RemoveDisableAiming = config.Bind<bool>("Traits", "RemoveDisableAiming", true, "Remove oil modifiers that disable aiming down sights.");
			RemoveMoreBulletDrop = config.Bind<bool>("Traits", "RemoveMoreBulletDrop", false, "Remove increased projectile gravity and its same-oil speed/mass companion penalties.");
			RemoveMoreDrag = config.Bind<bool>("Traits", "RemoveMoreDrag", false, "Remove oil modifiers that increase projectile drag.");
			RemoveExtraAmmoConsumeChance = config.Bind<bool>("Traits", "RemoveExtraAmmoConsumeChance", true, "Remove oil modifiers that add a chance to consume extra ammunition.");
			RemoveDecreaseAccuracyWhenMoving = config.Bind<bool>("Traits", "RemoveDecreaseAccuracyWhenMoving", true, "Remove oil modifiers that reduce accuracy while moving.");
			RemoveDecreaseMoveSpeed = config.Bind<bool>("Traits", "RemoveDecreaseMoveSpeed", true, "Remove oil modifiers that reduce movement speed while holding the weapon.");
			RemoveDecreaseJumpPower = config.Bind<bool>("Traits", "RemoveDecreaseJumpPower", true, "Remove oil modifiers that reduce jump power while holding the weapon.");
			RemoveDecreaseLootChanceMultiplier = config.Bind<bool>("Traits", "RemoveDecreaseLootChanceMultiplier", true, "Remove oil modifiers that reduce the loot chance multiplier.");
			RemoveDisableMoneyDrops = config.Bind<bool>("Traits", "RemoveDisableMoneyDrops", true, "Remove oil modifiers that disable Sulf/money drops.");
			RemoveDisableOrganDrops = config.Bind<bool>("Traits", "RemoveDisableOrganDrops", true, "Remove oil modifiers that disable organ drops.");
			RemoveNegativeBulletSpeed = config.Bind<bool>("Traits", "RemoveNegativeBulletSpeed", false, "Remove ProjectileTimeScale modifiers only when they reduce bullet speed. Positive bullet-speed modifiers remain active.");
			RemoveNegativeDamage = config.Bind<bool>("Traits", "RemoveNegativeDamage", false, "Remove flat or percentage damage modifiers only when their signed value is negative. Positive damage modifiers remain active.");
			RemoveNegativeBulletSize = config.Bind<bool>("Traits", "RemoveNegativeBulletSize", false, "Remove ProjectileScale modifiers only when they reduce bullet size. Positive bullet-size modifiers remain active.");
			RemoveNegativeRpm = config.Bind<bool>("Traits", "RemoveNegativeRpm", false, "Remove RPM modifiers only when their signed value is negative. Positive fire-rate modifiers remain active.");
			RemoveExtraDurabilityCost = config.Bind<bool>("General", "RemoveExtraDurabilityCost", false, "Remove oil-specific extra durability consumption. This setting is independent from the other undesirable traits.");
		}

		internal bool ShouldRemove(NegativeOilTrait traits)
		{
			return IsEnabled(traits, NegativeOilTrait.DisableAiming, RemoveDisableAiming) || IsEnabled(traits, NegativeOilTrait.MoreBulletDrop, RemoveMoreBulletDrop) || IsEnabled(traits, NegativeOilTrait.MoreDrag, RemoveMoreDrag) || IsEnabled(traits, NegativeOilTrait.ExtraAmmoConsumeChance, RemoveExtraAmmoConsumeChance) || IsEnabled(traits, NegativeOilTrait.DecreaseAccuracyWhenMoving, RemoveDecreaseAccuracyWhenMoving) || IsEnabled(traits, NegativeOilTrait.DecreaseMoveSpeed, RemoveDecreaseMoveSpeed) || IsEnabled(traits, NegativeOilTrait.DecreaseJumpPower, RemoveDecreaseJumpPower) || IsEnabled(traits, NegativeOilTrait.DecreaseLootChanceMultiplier, RemoveDecreaseLootChanceMultiplier) || IsEnabled(traits, NegativeOilTrait.DisableMoneyDrops, RemoveDisableMoneyDrops) || IsEnabled(traits, NegativeOilTrait.DisableOrganDrops, RemoveDisableOrganDrops) || IsEnabled(traits, NegativeOilTrait.NegativeBulletSpeed, RemoveNegativeBulletSpeed) || IsEnabled(traits, NegativeOilTrait.NegativeDamage, RemoveNegativeDamage) || IsEnabled(traits, NegativeOilTrait.NegativeBulletSize, RemoveNegativeBulletSize) || IsEnabled(traits, NegativeOilTrait.NegativeRpm, RemoveNegativeRpm) || IsEnabled(traits, NegativeOilTrait.ExtraDurabilityCost, RemoveExtraDurabilityCost);
		}

		private static bool IsEnabled(NegativeOilTrait traits, NegativeOilTrait flag, ConfigEntry<bool> setting)
		{
			return (traits & flag) != NegativeOilTrait.None && setting.Value;
		}
	}
}
namespace PerfectOils.Patches
{
	[HarmonyPatch(typeof(AsyncAssetLoading), "set_loadingDone")]
	internal static class AssetLoadingPatches
	{
		[HarmonyPostfix]
		private static void AfterLoadingDoneSet(AsyncAssetLoading __instance, bool value)
		{
			Plugin instance = Plugin.Instance;
			if (value && !((Object)(object)instance == (Object)null))
			{
				instance.NotifyAssetsReady(__instance);
			}
		}
	}
	[HarmonyPatch]
	internal static class ItemDescriptionPatches
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(ItemDescription), "Setup", new Type[1] { typeof(InventoryItem) }, (Type[])null);
		}

		[HarmonyPostfix]
		private static void AfterSetup(ItemDescription __instance, InventoryItem __0)
		{
			Plugin instance = Plugin.Instance;
			if (!((Object)(object)instance == (Object)null) && instance.Enabled.Value && instance.ShowRemovedTraitsWithStrikethrough.Value && instance.TooltipRenderer != null)
			{
				instance.TooltipRenderer.Apply(__instance, __0, instance.DetailedLogging.Value);
			}
		}
	}
	[HarmonyPatch]
	internal static class ItemStatsPatches
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(ItemStats), "AddModifier", new Type[2]
			{
				typeof(ItemAttributes),
				typeof(StatModifier)
			}, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool BeforeAddModifier(ItemAttributes __0, StatModifier __1)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null || !instance.Enabled.Value || instance.OilTraits == null)
			{
				return true;
			}
			return !instance.OilTraits.ShouldSuppress(__0, __1);
		}
	}
	[HarmonyPatch(typeof(Weapon), "SyncEnchantments")]
	internal static class WeaponPatches
	{
		[HarmonyPrefix]
		private static void ResetCachedAimingState(ref bool ___aimingDisabled)
		{
			___aimingDisabled = false;
		}
	}
}