Decompiled source of FunctionalCouplerRework v1.0.2

plugins/FunctionalCouplerRework.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using Microsoft.CodeAnalysis;
using On.RoR2;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FunctionalCouplerRework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FunctionalCouplerRework")]
[assembly: AssemblyTitle("FunctionalCouplerRework")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FunctionalCouplerRework
{
	public class Class1
	{
	}
	[BepInPlugin("thatguy119407.functionalcouplerrework", "Functional Coupler Rework", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "thatguy119407.functionalcouplerrework";

		public const string PluginName = "Functional Coupler Rework";

		public const string PluginVersion = "1.0.2";

		private static Plugin instance;

		private static ItemIndex functionalCouplerIndex = (ItemIndex)(-1);

		private readonly Dictionary<CharacterBody, HashSet<BuffIndex>> manuallyAppliedBuffs = new Dictionary<CharacterBody, HashSet<BuffIndex>>();

		private readonly HashSet<CharacterBody> pendingCollectiveRepairs = new HashSet<CharacterBody>();

		private readonly HashSet<CharacterBody> pendingEarthRepairs = new HashSet<CharacterBody>();

		private readonly HashSet<CharacterBody> pendingHauntedRepairs = new HashSet<CharacterBody>();

		private readonly HashSet<CharacterBody> pendingBeadRepairs = new HashSet<CharacterBody>();

		private FieldInfo itemDisplayRuleSetField;

		private MethodInfo instantiateDisplayRuleGroupMethod;

		private FieldInfo forceUpdateField;

		private FieldInfo collectiveFoundDisplaysField;

		private FieldInfo collectiveAnimatorsField;

		private FieldInfo collectiveHornPairsField;

		private bool checkedCatalog;

		private bool attemptedDisplayMethodResolution;

		private bool displayMethodsResolved;

		internal static Plugin Instance => instance;

		private void Awake()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			instance = this;
			CharacterBody.OnInventoryChanged += new hook_OnInventoryChanged(CharacterBody_OnInventoryChanged);
			CharacterBody.OnDestroy += new hook_OnDestroy(CharacterBody_OnDestroy);
			CharacterModel.OnInventoryChanged += new hook_OnInventoryChanged(CharacterModel_OnInventoryChanged);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Functional Coupler Rework v1.0.2 loaded.");
		}

		private void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			CharacterBody.OnInventoryChanged -= new hook_OnInventoryChanged(CharacterBody_OnInventoryChanged);
			CharacterBody.OnDestroy -= new hook_OnDestroy(CharacterBody_OnDestroy);
			CharacterModel.OnInventoryChanged -= new hook_OnInventoryChanged(CharacterModel_OnInventoryChanged);
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		private void CharacterBody_OnInventoryChanged(orig_OnInventoryChanged orig, CharacterBody self)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			if (Object.op_Implicit((Object)(object)self))
			{
				Inventory inventory = self.inventory;
				if (!((Object)(object)inventory == (Object)null) && (int)functionalCouplerIndex != -1 && inventory.GetItemCountEffective(functionalCouplerIndex) > 0)
				{
					ReconcileInactiveEquipmentBuffs(self);
					ScheduleCollectiveRepairIfNeeded(self);
					ScheduleEarthRepairIfNeeded(self);
					ScheduleHauntedRepairIfNeeded(self);
					ScheduleBeadRepairIfNeeded(self);
				}
			}
		}

		private void CharacterModel_OnInventoryChanged(orig_OnInventoryChanged orig, CharacterModel self)
		{
			orig.Invoke(self);
			if (Object.op_Implicit((Object)(object)self) && Object.op_Implicit((Object)(object)self.body) && !((Object)(object)self.body.inventory == (Object)null))
			{
				EnsureDisplayKeeper(self);
			}
		}

		private void EnsureDisplayKeeper(CharacterModel characterModel)
		{
			FunctionalCouplerDisplayKeeper functionalCouplerDisplayKeeper = ((Component)characterModel).GetComponent<FunctionalCouplerDisplayKeeper>();
			if (!Object.op_Implicit((Object)(object)functionalCouplerDisplayKeeper))
			{
				functionalCouplerDisplayKeeper = ((Component)characterModel).gameObject.AddComponent<FunctionalCouplerDisplayKeeper>();
			}
			functionalCouplerDisplayKeeper.Initialize(characterModel);
			functionalCouplerDisplayKeeper.ReconcileImmediately();
		}

		private void ReconcileInactiveEquipmentBuffs(CharacterBody body)
		{
			//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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = body.inventory;
			if ((Object)(object)inventory == (Object)null)
			{
				return;
			}
			EquipmentIndex currentEquipmentIndex = inventory.currentEquipmentIndex;
			HashSet<BuffIndex> hashSet = new HashSet<BuffIndex>();
			int equipmentSlotCount = inventory.GetEquipmentSlotCount();
			for (uint num = 0u; num < equipmentSlotCount; num++)
			{
				int equipmentSetCount = inventory.GetEquipmentSetCount(num);
				for (uint num2 = 0u; num2 < equipmentSetCount; num2++)
				{
					EquipmentIndex equipmentIndex = inventory.GetEquipment(num, num2).equipmentIndex;
					if ((int)equipmentIndex != -1 && equipmentIndex != currentEquipmentIndex)
					{
						BuffDef val = EquipmentCatalog.GetEquipmentDef(equipmentIndex)?.passiveBuffDef;
						if (!((Object)(object)val == (Object)null) && (int)val.buffIndex != -1)
						{
							hashSet.Add(val.buffIndex);
						}
					}
				}
			}
			if (!manuallyAppliedBuffs.TryGetValue(body, out var value))
			{
				value = new HashSet<BuffIndex>();
				manuallyAppliedBuffs[body] = value;
			}
			List<BuffIndex> list = new List<BuffIndex>();
			foreach (BuffIndex item in value)
			{
				if (!hashSet.Contains(item))
				{
					list.Add(item);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				BuffIndex val2 = list[i];
				if (body.HasBuff(val2))
				{
					body.RemoveBuff(val2);
				}
				value.Remove(val2);
			}
			foreach (BuffIndex item2 in hashSet)
			{
				if (!value.Contains(item2))
				{
					body.AddBuff(item2);
					value.Add(item2);
				}
			}
			if (value.Count == 0)
			{
				manuallyAppliedBuffs.Remove(body);
			}
		}

		private void ScheduleCollectiveRepairIfNeeded(CharacterBody body)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)body) && NetworkServer.active)
			{
				BuffIndex buffIndex = Buffs.EliteCollective.buffIndex;
				if (manuallyAppliedBuffs.TryGetValue(body, out var value) && value.Contains(buffIndex) && pendingCollectiveRepairs.Add(body))
				{
					((MonoBehaviour)this).StartCoroutine(RepairCollectiveBehaviorNextFrame(body));
				}
			}
		}

		private IEnumerator RepairCollectiveBehaviorNextFrame(CharacterBody body)
		{
			yield return null;
			pendingCollectiveRepairs.Remove(body);
			if (!Object.op_Implicit((Object)(object)body) || !NetworkServer.active)
			{
				yield break;
			}
			Inventory inventory = body.inventory;
			if ((Object)(object)inventory == (Object)null || (int)functionalCouplerIndex == -1 || inventory.GetItemCountEffective(functionalCouplerIndex) <= 0)
			{
				yield break;
			}
			BuffIndex buffIndex = Buffs.EliteCollective.buffIndex;
			if (manuallyAppliedBuffs.TryGetValue(body, out var value) && value.Contains(buffIndex) && body.HasBuff(buffIndex) && !Object.op_Implicit((Object)(object)((Component)body).GetComponent<AffixCollectiveBehavior>()))
			{
				if (Object.op_Implicit((Object)(object)body.AddItemBehavior<AffixCollectiveBehavior>(1)))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[FCR COLLECTIVE] Restored missing AffixCollectiveBehavior on " + ((Object)body).name + " after deferred destruction."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[FCR COLLECTIVE] Tried to restore AffixCollectiveBehavior on " + ((Object)body).name + ", but vanilla returned null."));
				}
			}
		}

		private void ScheduleEarthRepairIfNeeded(CharacterBody body)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)body) && NetworkServer.active)
			{
				BuffIndex buffIndex = Buffs.EliteEarth.buffIndex;
				if (manuallyAppliedBuffs.TryGetValue(body, out var value) && value.Contains(buffIndex) && pendingEarthRepairs.Add(body))
				{
					((MonoBehaviour)this).StartCoroutine(RepairEarthBehaviorNextFrame(body));
				}
			}
		}

		private IEnumerator RepairEarthBehaviorNextFrame(CharacterBody body)
		{
			yield return null;
			pendingEarthRepairs.Remove(body);
			if (!Object.op_Implicit((Object)(object)body) || !NetworkServer.active)
			{
				yield break;
			}
			Inventory inventory = body.inventory;
			if ((Object)(object)inventory == (Object)null || (int)functionalCouplerIndex == -1 || inventory.GetItemCountEffective(functionalCouplerIndex) <= 0)
			{
				yield break;
			}
			BuffIndex buffIndex = Buffs.EliteEarth.buffIndex;
			if (manuallyAppliedBuffs.TryGetValue(body, out var value) && value.Contains(buffIndex) && body.HasBuff(buffIndex) && !Object.op_Implicit((Object)(object)((Component)body).GetComponent<AffixEarthBehavior>()))
			{
				if (Object.op_Implicit((Object)(object)body.AddItemBehavior<AffixEarthBehavior>(1)))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[FCR EARTH] Restored missing AffixEarthBehavior on " + ((Object)body).name + " after deferred destruction."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[FCR EARTH] Tried to restore AffixEarthBehavior on " + ((Object)body).name + ", but vanilla returned null."));
				}
			}
		}

		private void ScheduleHauntedRepairIfNeeded(CharacterBody body)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)body) && NetworkServer.active)
			{
				BuffIndex buffIndex = Buffs.AffixHaunted.buffIndex;
				if (manuallyAppliedBuffs.TryGetValue(body, out var value) && value.Contains(buffIndex) && pendingHauntedRepairs.Add(body))
				{
					((MonoBehaviour)this).StartCoroutine(RepairHauntedBehaviorNextFrame(body));
				}
			}
		}

		private IEnumerator RepairHauntedBehaviorNextFrame(CharacterBody body)
		{
			yield return null;
			pendingHauntedRepairs.Remove(body);
			if (!Object.op_Implicit((Object)(object)body) || !NetworkServer.active)
			{
				yield break;
			}
			Inventory inventory = body.inventory;
			if ((Object)(object)inventory == (Object)null || (int)functionalCouplerIndex == -1 || inventory.GetItemCountEffective(functionalCouplerIndex) <= 0)
			{
				yield break;
			}
			BuffIndex buffIndex = Buffs.AffixHaunted.buffIndex;
			if (manuallyAppliedBuffs.TryGetValue(body, out var value) && value.Contains(buffIndex) && body.HasBuff(buffIndex) && !Object.op_Implicit((Object)(object)((Component)body).GetComponent<AffixHauntedBehavior>()))
			{
				if (Object.op_Implicit((Object)(object)body.AddItemBehavior<AffixHauntedBehavior>(1)))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[FCR HAUNTED] Restored missing AffixHauntedBehavior on " + ((Object)body).name + " after deferred destruction."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[FCR HAUNTED] Tried to restore AffixHauntedBehavior on " + ((Object)body).name + ", but vanilla returned null."));
				}
			}
		}

		private void ScheduleBeadRepairIfNeeded(CharacterBody body)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)body) && NetworkServer.active)
			{
				BuffIndex buffIndex = Buffs.EliteBead.buffIndex;
				if (manuallyAppliedBuffs.TryGetValue(body, out var value) && value.Contains(buffIndex) && pendingBeadRepairs.Add(body))
				{
					((MonoBehaviour)this).StartCoroutine(RepairBeadBehaviorNextFrame(body));
				}
			}
		}

		private IEnumerator RepairBeadBehaviorNextFrame(CharacterBody body)
		{
			yield return null;
			pendingBeadRepairs.Remove(body);
			if (!Object.op_Implicit((Object)(object)body) || !NetworkServer.active)
			{
				yield break;
			}
			Inventory inventory = body.inventory;
			if ((Object)(object)inventory == (Object)null || (int)functionalCouplerIndex == -1 || inventory.GetItemCountEffective(functionalCouplerIndex) <= 0)
			{
				yield break;
			}
			BuffIndex buffIndex = Buffs.EliteBead.buffIndex;
			if (manuallyAppliedBuffs.TryGetValue(body, out var value) && value.Contains(buffIndex) && body.HasBuff(buffIndex) && !Object.op_Implicit((Object)(object)((Component)body).GetComponent<AffixBeadBehavior>()))
			{
				if (Object.op_Implicit((Object)(object)body.AddItemBehavior<AffixBeadBehavior>(1)))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[FCR BEAD] Restored missing AffixBeadBehavior on " + ((Object)body).name + " after deferred destruction."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[FCR BEAD] Tried to restore AffixBeadBehavior on " + ((Object)body).name + ", but vanilla returned null."));
				}
			}
		}

		private void RemoveManuallyAppliedBuffs(CharacterBody body)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			if (!Object.op_Implicit((Object)(object)body) || !manuallyAppliedBuffs.TryGetValue(body, out var value))
			{
				return;
			}
			foreach (BuffIndex item in value)
			{
				if (body.HasBuff(item))
				{
					body.RemoveBuff(item);
				}
			}
			manuallyAppliedBuffs.Remove(body);
		}

		internal bool ShouldMaintainInactiveDisplays(CharacterModel model)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)model) || !Object.op_Implicit((Object)(object)model.body) || (Object)(object)model.body.inventory == (Object)null)
			{
				return false;
			}
			if ((int)functionalCouplerIndex == -1)
			{
				return false;
			}
			return model.body.inventory.GetItemCountEffective(functionalCouplerIndex) > 0;
		}

		internal void ReconcileInactiveDisplays(CharacterModel characterModel)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Invalid comparison between Unknown and I4
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldMaintainInactiveDisplays(characterModel) || !ResolveDisplayMethods())
			{
				return;
			}
			Inventory inventory = characterModel.body.inventory;
			EquipmentIndex currentEquipmentIndex = inventory.currentEquipmentIndex;
			HashSet<EquipmentIndex> hashSet = new HashSet<EquipmentIndex>();
			int equipmentSlotCount = inventory.GetEquipmentSlotCount();
			for (uint num = 0u; num < equipmentSlotCount; num++)
			{
				int equipmentSetCount = inventory.GetEquipmentSetCount(num);
				for (uint num2 = 0u; num2 < equipmentSetCount; num2++)
				{
					EquipmentIndex equipmentIndex = inventory.GetEquipment(num, num2).equipmentIndex;
					if ((int)equipmentIndex != -1 && equipmentIndex != currentEquipmentIndex && !((Object)(object)EquipmentCatalog.GetEquipmentDef(equipmentIndex)?.passiveBuffDef == (Object)null))
					{
						hashSet.Add(equipmentIndex);
					}
				}
			}
			bool flag = false;
			foreach (EquipmentIndex item in hashSet)
			{
				List<GameObject> equipmentDisplayObjects = characterModel.GetEquipmentDisplayObjects(item);
				bool flag2 = false;
				for (int i = 0; i < equipmentDisplayObjects.Count; i++)
				{
					if (Object.op_Implicit((Object)(object)equipmentDisplayObjects[i]))
					{
						flag2 = true;
						break;
					}
				}
				if (!flag2 && TryInstantiateEquipmentDisplay(characterModel, item))
				{
					flag = true;
				}
			}
			if (flag)
			{
				ResetCollectiveDisplaySearch(characterModel.body);
			}
		}

		private bool ResolveDisplayMethods()
		{
			if (attemptedDisplayMethodResolution)
			{
				return displayMethodsResolved;
			}
			attemptedDisplayMethodResolution = true;
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			itemDisplayRuleSetField = typeof(CharacterModel).GetField("itemDisplayRuleSet", bindingAttr);
			forceUpdateField = typeof(CharacterModel).GetField("forceUpdate", bindingAttr);
			instantiateDisplayRuleGroupMethod = typeof(CharacterModel).GetMethod("InstantiateDisplayRuleGroup", bindingAttr, null, new Type[3]
			{
				typeof(DisplayRuleGroup),
				typeof(ItemIndex),
				typeof(EquipmentIndex)
			}, null);
			collectiveFoundDisplaysField = typeof(AffixCollectiveDisplayBehaviour).GetField("_foundDisplays", bindingAttr);
			collectiveAnimatorsField = typeof(AffixCollectiveDisplayBehaviour).GetField("_animatorsFromRings", bindingAttr);
			collectiveHornPairsField = typeof(AffixCollectiveDisplayBehaviour).GetField("_hornPairs", bindingAttr);
			if (itemDisplayRuleSetField == null || instantiateDisplayRuleGroupMethod == null || forceUpdateField == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[FCR DISPLAY] Could not resolve CharacterModel display members.");
				return false;
			}
			displayMethodsResolved = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[FCR DISPLAY] Successfully resolved display members.");
			return true;
		}

		private bool TryInstantiateEquipmentDisplay(CharacterModel characterModel, EquipmentIndex equipmentIndex)
		{
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object? value = itemDisplayRuleSetField.GetValue(characterModel);
				ItemDisplayRuleSet val = (ItemDisplayRuleSet)((value is ItemDisplayRuleSet) ? value : null);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return false;
				}
				DisplayRuleGroup equipmentDisplayRuleGroup = val.GetEquipmentDisplayRuleGroup(equipmentIndex);
				if (((DisplayRuleGroup)(ref equipmentDisplayRuleGroup)).isEmpty)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[FCR DISPLAY] Empty display rule group for " + DescribeEquipment(equipmentIndex) + "."));
					return false;
				}
				instantiateDisplayRuleGroupMethod.Invoke(characterModel, new object[3]
				{
					equipmentDisplayRuleGroup,
					(object)(ItemIndex)(-1),
					equipmentIndex
				});
				List<GameObject> equipmentDisplayObjects = characterModel.GetEquipmentDisplayObjects(equipmentIndex);
				int num = 0;
				int num2 = 0;
				int num3 = 0;
				int num4 = 0;
				for (int i = 0; i < equipmentDisplayObjects.Count; i++)
				{
					GameObject val2 = equipmentDisplayObjects[i];
					if (!Object.op_Implicit((Object)(object)val2))
					{
						continue;
					}
					num++;
					val2.SetActive(true);
					ItemDisplay component = val2.GetComponent<ItemDisplay>();
					if (!Object.op_Implicit((Object)(object)component))
					{
						continue;
					}
					num2++;
					component.SetVisibilityLevel(characterModel.visibility);
					component.RefreshRenderers();
					if (component.rendererInfos == null)
					{
						continue;
					}
					for (int j = 0; j < component.rendererInfos.Length; j++)
					{
						Renderer renderer = component.rendererInfos[j].renderer;
						if (Object.op_Implicit((Object)(object)renderer))
						{
							num3++;
							if (renderer.enabled)
							{
								num4++;
							}
						}
					}
				}
				forceUpdateField.SetValue(characterModel, true);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[FCR DISPLAY] Added inactive display for " + DescribeEquipment(equipmentIndex) + "; " + $"objects={num}, ItemDisplays={num2}, " + $"renderers={num3}, enabledRenderers={num4}, " + $"modelVisibility={characterModel.visibility}."));
				return num > 0;
			}
			catch (TargetInvocationException ex)
			{
				Exception arg = ex.InnerException ?? ex;
				((BaseUnityPlugin)this).Logger.LogError((object)$"[FCR DISPLAY] Failed to instantiate {DescribeEquipment(equipmentIndex)}:\n{arg}");
				return false;
			}
			catch (Exception arg2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"[FCR DISPLAY] Failed to instantiate {DescribeEquipment(equipmentIndex)}:\n{arg2}");
				return false;
			}
		}

		private void ResetCollectiveDisplaySearch(CharacterBody body)
		{
			if (!Object.op_Implicit((Object)(object)body) || collectiveFoundDisplaysField == null)
			{
				return;
			}
			AffixCollectiveDisplayBehaviour[] array = Object.FindObjectsOfType<AffixCollectiveDisplayBehaviour>();
			foreach (AffixCollectiveDisplayBehaviour val in array)
			{
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.affixCollectiveAttachmentBehaviour) && Object.op_Implicit((Object)(object)val.affixCollectiveAttachmentBehaviour.attachment) && !((Object)(object)val.affixCollectiveAttachmentBehaviour.attachment.attachedBody != (Object)(object)body))
				{
					collectiveFoundDisplaysField.SetValue(val, false);
					object obj = collectiveAnimatorsField?.GetValue(val);
					obj?.GetType().GetMethod("Clear")?.Invoke(obj, null);
					object obj2 = collectiveHornPairsField?.GetValue(val);
					obj2?.GetType().GetMethod("Clear")?.Invoke(obj2, null);
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[FCR DISPLAY] Reset AffixCollectiveDisplayBehaviour so it can discover the newly added inactive displays.");
				}
			}
		}

		private string DescribeEquipment(EquipmentIndex equipmentIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(equipmentIndex);
			if (!((Object)(object)equipmentDef == (Object)null))
			{
				return $"{((Object)equipmentDef).name} [{equipmentIndex}]";
			}
			return $"UnknownEquipment({equipmentIndex})";
		}

		private void CharacterBody_OnDestroy(orig_OnDestroy orig, CharacterBody self)
		{
			manuallyAppliedBuffs.Remove(self);
			pendingCollectiveRepairs.Remove(self);
			pendingEarthRepairs.Remove(self);
			pendingHauntedRepairs.Remove(self);
			pendingBeadRepairs.Remove(self);
			orig.Invoke(self);
		}

		private void Update()
		{
			//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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!checkedCatalog && ItemCatalog.itemCount != 0)
			{
				functionalCouplerIndex = Items.ExtraEquipment.itemIndex;
				if ((int)functionalCouplerIndex != -1)
				{
					checkedCatalog = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Functional Coupler catalog index resolved: {functionalCouplerIndex}");
				}
			}
		}
	}
	internal sealed class FunctionalCouplerDisplayKeeper : MonoBehaviour
	{
		private CharacterModel characterModel;

		private float nextReconcileTime;

		internal void Initialize(CharacterModel model)
		{
			characterModel = model;
		}

		internal void ReconcileImmediately()
		{
			nextReconcileTime = 0f;
			Reconcile();
		}

		private void Update()
		{
			if (!(Time.unscaledTime < nextReconcileTime))
			{
				Reconcile();
			}
		}

		private void Reconcile()
		{
			nextReconcileTime = Time.unscaledTime + 0.5f;
			if (!Object.op_Implicit((Object)(object)characterModel))
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				Object.Destroy((Object)(object)this);
			}
			else if (!instance.ShouldMaintainInactiveDisplays(characterModel))
			{
				Object.Destroy((Object)(object)this);
			}
			else
			{
				instance.ReconcileInactiveDisplays(characterModel);
			}
		}
	}
}