Decompiled source of UESDrifter v1.1.2

plugins/UESDrifter.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using EntityStates;
using EntityStates.Drone;
using EntityStates.DroneScrapper;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using RoR2;
using RoR2.ContentManagement;
using RoR2.Modding;
using RoR2.Networking;
using RoR2.Skills;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Dermitio")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: AssemblyInformationalVersion("1.1.2")]
[assembly: AssemblyProduct("UESDrifter")]
[assembly: AssemblyTitle("UESDrifter")]
[assembly: AssemblyVersion("1.1.2.0")]
[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 DrifterUES
{
	public sealed class DeferredFabricatorSkillDef : DrifterSkillDef
	{
		public override bool IsReady([NotNull] GenericSkill skillSlot)
		{
			if (FabricationService.HasAvailableFabricationRecipe())
			{
				return ((DrifterSkillDef)this).IsReady(skillSlot);
			}
			return false;
		}

		public override bool CanExecute([NotNull] GenericSkill skillSlot)
		{
			if (FabricationService.HasAvailableFabricationRecipe())
			{
				return ((DrifterSkillDef)this).CanExecute(skillSlot);
			}
			return false;
		}

		public override void OnExecute([NotNull] GenericSkill skillSlot)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			skillSlot.stateMachine.SetInterruptState(((SkillDef)this).InstantiateNextState(skillSlot), ((SkillDef)this).interruptPriority);
			if (((SkillDef)this).cancelSprintingOnActivation)
			{
				skillSlot.characterBody.isSprinting = false;
			}
			if (((SkillDef)this).resetCooldownTimerOnUse)
			{
				skillSlot.rechargeStopwatch = 0f;
			}
			CharacterBody characterBody = skillSlot.characterBody;
			if (characterBody != null)
			{
				characterBody.OnSkillActivated(skillSlot);
			}
		}
	}
	internal sealed class DroneHealthSnapshot
	{
		private float healthFraction;

		private float shieldFraction;

		internal bool Pending { get; private set; }

		internal void Capture(float health, float fullHealth, float shield, float fullShield, bool alive)
		{
			if (!Pending && alive && !(fullHealth <= 0f) && !float.IsNaN(fullHealth) && !float.IsInfinity(fullHealth))
			{
				healthFraction = Fraction(health, fullHealth);
				shieldFraction = Fraction(shield, fullShield);
				Pending = true;
			}
		}

		internal bool Restore(float fullHealth, float fullShield, out float health, out float shield)
		{
			health = (shield = 0f);
			if (!Pending || fullHealth <= 0f || float.IsNaN(fullHealth) || float.IsInfinity(fullHealth))
			{
				return false;
			}
			health = fullHealth * healthFraction;
			shield = Math.Max(0f, fullShield) * shieldFraction;
			Clear();
			return true;
		}

		internal void Clear()
		{
			Pending = false;
		}

		private static float Fraction(float value, float maximum)
		{
			if (maximum <= 0f || float.IsNaN(value) || float.IsInfinity(value))
			{
				return 0f;
			}
			return Math.Min(1f, Math.Max(0f, value / maximum));
		}
	}
	public sealed class DynamicJunkPatchSkillDef : DrifterSkillDef
	{
		public override bool IsReady([NotNull] GenericSkill skillSlot)
		{
			if (((DrifterSkillDef)this).IsReady(skillSlot))
			{
				return JunkPatchPassiveService.CanAfford(skillSlot.characterBody);
			}
			return false;
		}

		public override bool CanExecute([NotNull] GenericSkill skillSlot)
		{
			if (((DrifterSkillDef)this).CanExecute(skillSlot))
			{
				return JunkPatchPassiveService.CanAfford(skillSlot.characterBody);
			}
			return false;
		}

		public override void OnExecute([NotNull] GenericSkill skillSlot)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!((SkillDef)this).CanExecute(skillSlot) || !skillSlot.stateMachine.SetInterruptState(((SkillDef)this).InstantiateNextState(skillSlot), ((SkillDef)this).interruptPriority))
			{
				return;
			}
			if (((SkillDef)this).cancelSprintingOnActivation)
			{
				skillSlot.characterBody.isSprinting = false;
			}
			if (!NetworkServer.active)
			{
				skillSlot.stock -= ((SkillDef)this).stockToConsume;
				if (((SkillDef)this).resetCooldownTimerOnUse)
				{
					skillSlot.rechargeStopwatch = 0f;
				}
			}
			CharacterBody characterBody = skillSlot.characterBody;
			if (characterBody != null)
			{
				characterBody.OnSkillActivated(skillSlot);
			}
		}
	}
	internal static class FabricationMenu
	{
		internal enum Mode
		{
			Fabricator,
			Nanobot
		}

		private static GameObject activeMenuRoot;

		private static bool menuOpening;

		private static int generation;

		internal static bool IsOpen => Object.op_Implicit((Object)(object)activeMenuRoot);

		internal static void Open(Mode mode, CharacterBody owner)
		{
			if (!((Object)(object)owner == (Object)null) && owner.hasEffectiveAuthority && !menuOpening && !Object.op_Implicit((Object)(object)activeMenuRoot))
			{
				menuOpening = true;
				((MonoBehaviour)Plugin.Instance).StartCoroutine(OpenWhenUiReady(mode, owner, generation));
			}
		}

		private static IEnumerator OpenWhenUiReady(Mode mode, CharacterBody owner, int openingGeneration)
		{
			LocalUser user = null;
			HUD hud = null;
			for (int frame = 0; frame < 30; frame++)
			{
				if (openingGeneration != generation)
				{
					yield break;
				}
				if ((Object)(object)owner == (Object)null || !owner.hasEffectiveAuthority || (Object)(object)owner.healthComponent == (Object)null || !owner.healthComponent.alive)
				{
					menuOpening = false;
					yield break;
				}
				user = ((IEnumerable<LocalUser>)LocalUserManager.readOnlyLocalUsersList).FirstOrDefault((Func<LocalUser, bool>)((LocalUser candidate) => (Object)(object)candidate.cachedBody == (Object)(object)owner));
				hud = ((IEnumerable<HUD>)HUD.readOnlyInstanceList).FirstOrDefault((Func<HUD, bool>)((HUD candidate) => candidate.localUserViewer == user));
				if (user != null && (Object)(object)user.eventSystem != (Object)null && (Object)(object)hud != (Object)null)
				{
					break;
				}
				yield return null;
			}
			if (openingGeneration != generation)
			{
				yield break;
			}
			menuOpening = false;
			if (!((Object)(object)owner == (Object)null) && !((Object)(object)owner.healthComponent == (Object)null) && owner.healthComponent.alive && user != null && !((Object)(object)user.eventSystem == (Object)null) && !((Object)(object)hud == (Object)null) && !Object.op_Implicit((Object)(object)activeMenuRoot))
			{
				GameObject val = (activeMenuRoot = CreateMenuRoot(user, hud, (mode == Mode.Fabricator) ? "UES FABRICATOR" : "NANOBOT UPGRADES"));
				PauseManager.ClosePauseScreen(true);
				if (mode == Mode.Fabricator)
				{
					ConfigureFabricator(val, owner);
				}
				else
				{
					ConfigureNanobots(val, owner);
				}
				AddResourceSummary(val, owner);
				val.AddComponent<FabricationMenuLifetime>().Initialize(owner);
			}
		}

		private static GameObject CreateMenuRoot(LocalUser user, HUD hud, string title)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: 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_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Expected O, but got Unknown
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Expected O, but got Unknown
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Expected O, but got Unknown
			GameObject val = new GameObject("UESDrifterSelectionMenu", new Type[7]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(GraphicRaycaster),
				typeof(MPEventSystemProvider),
				typeof(MPEventSystemLocator),
				typeof(CursorOpener)
			});
			Canvas component = val.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 100;
			val.GetComponent<CanvasScaler>().uiScaleMode = (ScaleMode)1;
			val.GetComponent<CanvasScaler>().referenceResolution = new Vector2(1920f, 1080f);
			val.GetComponent<MPEventSystemProvider>().eventSystem = user.eventSystem;
			val.GetComponent<CursorOpener>().forceCursorForGamePad = true;
			((Graphic)val.AddComponent<Image>()).color = new Color(0f, 0.02f, 0.05f, 0.88f);
			Transform obj = CreateChild(val.transform, "Panel", new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(860f, 760f));
			((Graphic)((Component)obj).gameObject.AddComponent<Image>()).color = new Color(0.06f, 0.11f, 0.16f, 0.98f);
			CreateText(obj, "Title", title, 32f, (TextAlignmentOptions)514, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -38f), new Vector2(-40f, 52f), hud);
			CreateText(obj, "Hint", "Select a target. Costs are charged only after server confirmation.", 17f, (TextAlignmentOptions)514, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -76f), new Vector2(-40f, 28f), hud);
			CreateCloseButton(obj, hud, val);
			Transform obj2 = CreateChild(obj, "SelectionScroll", new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(0f, -70f), new Vector2(-44f, -166f));
			ScrollRect val2 = ((Component)obj2).gameObject.AddComponent<ScrollRect>();
			Transform val3 = CreateChild(obj2, "Viewport", Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), Vector2.zero, Vector2.zero);
			((Graphic)((Component)val3).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.18f);
			((Component)val3).gameObject.AddComponent<Mask>().showMaskGraphic = true;
			Transform val4 = CreateChild(val3, "Content", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(0f, 0f));
			VerticalLayoutGroup obj3 = ((Component)val4).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj3).padding = new RectOffset(14, 14, 14, 14);
			((HorizontalOrVerticalLayoutGroup)obj3).spacing = 8f;
			((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false;
			((Component)val4).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			val2.viewport = (RectTransform)val3;
			val2.content = (RectTransform)val4;
			val2.horizontal = false;
			val2.vertical = true;
			val2.scrollSensitivity = 30f;
			return val;
		}

		private static void ConfigureFabricator(GameObject root, CharacterBody owner)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = root.transform.Find("Panel/SelectionScroll/Viewport/Content");
			JunkController component = ((Component)owner).GetComponent<JunkController>();
			int num = FabricationService.CountActiveFabricatedDrones(owner.master);
			bool flag = num >= 8;
			CreateText(root.transform.Find("Panel"), "FabricatedDroneCount", "Fabricated Drones: " + num + " / " + 8, 17f, (TextAlignmentOptions)514, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -128f), new Vector2(-40f, 28f), null);
			foreach (DroneRecipe recipe in UesRecipes.Fabrication)
			{
				DroneDef val = recipe.drone();
				if (!((Object)(object)val == (Object)null))
				{
					bool enabled = !flag && (Object)(object)Run.instance != (Object)null && Run.instance.IsDroneAvailable(val.droneIndex) && FabricationService.CanPay(owner.inventory, component, recipe.cost);
					string[] obj = new string[6] { recipe.displayName, "  •  Tier ", null, null, null, null };
					int fabricationTier = recipe.fabricationTier;
					obj[2] = fabricationTier.ToString();
					obj[3] = "\n";
					obj[4] = CostText(recipe.cost);
					obj[5] = (flag ? "  (8 drone limit reached)" : string.Empty);
					string label = string.Concat(obj);
					CreateSelectionButton(parent, val, label, enabled, delegate
					{
						UesNetwork.SendFabrication(recipe.id);
						Close(root);
					});
				}
			}
		}

		private static void ConfigureNanobots(GameObject root, CharacterBody owner)
		{
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = root.transform.Find("Panel/SelectionScroll/Viewport/Content");
			CharacterMaster master = owner.master;
			JunkController component = ((Component)owner).GetComponent<JunkController>();
			bool flag = NanobotUpgradeService.CountActiveNanobotUpgrades(master) >= 2;
			bool flag2 = false;
			foreach (CharacterMaster drone in GetEligibleDrones(master))
			{
				flag2 = true;
				bool flag3 = NanobotUpgradeService.IsNanobotActive(drone);
				int num = 1 + drone.inventory.GetItemCountPermanent(Items.DroneUpgradeHidden) - (flag3 ? 1 : 0);
				if (NanobotUpgradeService.TryGetCost(drone, out var cost))
				{
					bool enabled = !flag3 && !flag && FabricationService.CanPay(owner.inventory, component, cost);
					CharacterBody body = drone.GetBody();
					DroneDef droneDef = DroneCatalog.GetDroneDef(DroneCatalog.GetDroneIndexFromBodyIndex(body.bodyIndex));
					string text = (((Object)(object)droneDef != (Object)null && !Language.IsTokenInvalid(droneDef.nameToken)) ? Language.GetString(droneDef.nameToken) : body.GetDisplayName());
					string label = text + "  •  Tier " + num + " → " + (num + 1) + "\n" + CostText(cost) + (flag3 ? "  (already upgraded)" : (flag ? "  (2 upgrade limit reached)" : string.Empty));
					CreateSelectionButton(parent, droneDef, label, enabled, delegate
					{
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						UesNetwork.SendNanobot(((NetworkBehaviour)drone).netId);
						Close(root);
					});
				}
			}
			if (!flag2)
			{
				CreateText(parent, "Empty", "No eligible allied drones are currently owned by this player.", 20f, (TextAlignmentOptions)514, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(0f, 90f), null);
			}
		}

		private static IEnumerable<CharacterMaster> GetEligibleDrones(CharacterMaster owner)
		{
			MinionGroup val = (((Object)(object)owner != (Object)null) ? MinionGroup.FindGroup(((NetworkBehaviour)owner).netId) : null);
			if (val == null)
			{
				yield break;
			}
			MinionOwnership[] members = val.members;
			foreach (MinionOwnership val2 in members)
			{
				CharacterMaster val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponent<CharacterMaster>() : null);
				CharacterBody val4 = (((Object)(object)val3 != (Object)null) ? val3.GetBody() : null);
				if ((Object)(object)val4 != (Object)null && (Object)(object)val4.healthComponent != (Object)null && val4.healthComponent.alive && (NanobotUpgradeService.IsEligible(owner, val3) || NanobotUpgradeService.IsNanobotActive(val3)))
				{
					yield return val3;
				}
			}
		}

		private static void CreateSelectionButton(Transform parent, DroneDef drone, string label, bool enabled, Action onClick)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DroneOption", new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button),
				typeof(LayoutElement)
			});
			val.transform.SetParent(parent, false);
			val.GetComponent<LayoutElement>().preferredHeight = 82f;
			((Graphic)val.GetComponent<Image>()).color = (enabled ? new Color(0.12f, 0.24f, 0.31f, 1f) : new Color(0.09f, 0.09f, 0.09f, 1f));
			Button component = val.GetComponent<Button>();
			((Selectable)component).interactable = enabled;
			((UnityEvent)component.onClick).AddListener((UnityAction)delegate
			{
				onClick();
			});
			Image obj = ((Component)CreateChild(val.transform, "Icon", new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(50f, 0f), new Vector2(60f, 60f))).gameObject.AddComponent<Image>();
			DroneIconCache.Assign(obj, drone);
			obj.preserveAspect = true;
			((Graphic)obj).color = (Color)(enabled ? Color.white : new Color(0.35f, 0.35f, 0.35f, 1f));
			CreateText(val.transform, "Text", label, 19f, (TextAlignmentOptions)513, new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 0.5f), new Vector2(94f, 0f), new Vector2(-110f, -10f), null);
		}

		private static void CreateCloseButton(Transform parent, HUD hud, GameObject root)
		{
			//IL_003f: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: 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)
			GameObject val = new GameObject("Close", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(1f, 1f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(1f, 1f);
			val2.anchoredPosition = new Vector2(-16f, -14f);
			val2.sizeDelta = new Vector2(118f, 38f);
			((Graphic)val.GetComponent<Image>()).color = new Color(0.35f, 0.12f, 0.12f, 1f);
			((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				Close(root);
			});
			CreateText(val.transform, "Text", "CANCEL", 18f, (TextAlignmentOptions)514, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(-4f, -4f), hud);
		}

		private static Transform CreateChild(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 anchoredPosition, Vector2 size)
		{
			//IL_0014: 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_0026: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = anchorMin;
			val2.anchorMax = anchorMax;
			val2.pivot = pivot;
			val2.anchoredPosition = anchoredPosition;
			val2.sizeDelta = size;
			return val.transform;
		}

		private static TextMeshProUGUI CreateText(Transform parent, string name, string value, float size, TextAlignmentOptions alignment, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 anchoredPosition, Vector2 dimensions, HUD hud)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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_0008: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI obj = ((Component)CreateChild(parent, name, anchorMin, anchorMax, pivot, anchoredPosition, dimensions)).gameObject.AddComponent<TextMeshProUGUI>();
			object font;
			if (!((Object)(object)hud != (Object)null))
			{
				font = TMP_Settings.defaultFontAsset;
			}
			else
			{
				TextMeshProUGUI componentInChildren = ((Component)hud).GetComponentInChildren<TextMeshProUGUI>(true);
				font = ((componentInChildren != null) ? ((TMP_Text)componentInChildren).font : null);
			}
			((TMP_Text)obj).font = (TMP_FontAsset)font;
			((TMP_Text)obj).text = value;
			((TMP_Text)obj).fontSize = size;
			((TMP_Text)obj).alignment = alignment;
			((TMP_Text)obj).enableWordWrapping = true;
			((Graphic)obj).color = Color.white;
			return obj;
		}

		private static void Close(GameObject root)
		{
			if ((Object)(object)activeMenuRoot == (Object)(object)root)
			{
				activeMenuRoot = null;
			}
			Object.Destroy((Object)(object)root);
		}

		internal static void Reset()
		{
			generation++;
			menuOpening = false;
			if ((Object)(object)activeMenuRoot != (Object)null)
			{
				Close(activeMenuRoot);
			}
		}

		private static void AddResourceSummary(GameObject menuRoot, CharacterBody owner)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			Inventory val = (((Object)(object)owner != (Object)null) ? owner.inventory : null);
			if (!((Object)(object)val == (Object)null))
			{
				JunkController component = ((Component)owner).GetComponent<JunkController>();
				string value = "Resources: " + (((Object)(object)component != (Object)null) ? component.CurrentJunk : 0f) + " Junk  |  " + val.GetItemCountPermanent(Items.ScrapWhite.itemIndex) + " White  |  " + val.GetItemCountPermanent(Items.ScrapGreen.itemIndex) + " Green  |  " + val.GetItemCountPermanent(Items.ScrapRed.itemIndex) + " Red  |  " + val.GetItemCountPermanent(Items.RegeneratingScrap.itemIndex) + " Regenerating Scrap";
				CreateText(menuRoot.transform.Find("Panel"), "Resources", value, 17f, (TextAlignmentOptions)514, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -104f), new Vector2(-40f, 28f), null);
			}
		}

		private static string CostText(ResourceCost cost)
		{
			int junk = cost.junk;
			string text = junk + " Junk";
			if (cost.whiteScrap > 0)
			{
				string text2 = text;
				junk = cost.whiteScrap;
				text = text2 + ", " + junk + " White Scrap";
			}
			if (cost.greenScrap > 0)
			{
				string text3 = text;
				junk = cost.greenScrap;
				text = text3 + ", " + junk + " Green Scrap";
			}
			if (cost.redScrap > 0)
			{
				string text4 = text;
				junk = cost.redScrap;
				text = text4 + ", " + junk + " Red Scrap";
			}
			return text;
		}
	}
	internal sealed class FabricationMenuLifetime : MonoBehaviour
	{
		private CharacterBody owner;

		private Stage stage;

		internal void Initialize(CharacterBody body)
		{
			owner = body;
			stage = Stage.instance;
		}

		private void Update()
		{
			if ((Object)(object)owner == (Object)null || (Object)(object)owner.healthComponent == (Object)null || !owner.healthComponent.alive || !owner.hasEffectiveAuthority || (Object)(object)stage != (Object)(object)Stage.instance)
			{
				FabricationMenu.Reset();
			}
		}
	}
	internal static class UesNetwork
	{
		internal enum SelectionKind : byte
		{
			Fabricator = 1,
			Nanobot,
			JunkPatch
		}

		internal sealed class ResultMessage : MessageBase
		{
			public SelectionKind kind;

			public NetworkInstanceId bodyId;

			public bool accepted;

			public int stock;

			public float recharge;

			public override void Serialize(NetworkWriter writer)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				writer.Write((byte)kind);
				writer.Write(bodyId);
				writer.Write(accepted);
				writer.Write(stock);
				writer.Write(recharge);
			}

			public override void Deserialize(NetworkReader reader)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				kind = (SelectionKind)reader.ReadByte();
				bodyId = reader.ReadNetworkId();
				accepted = reader.ReadBoolean();
				stock = reader.ReadInt32();
				recharge = reader.ReadSingle();
			}
		}

		internal sealed class SelectionMessage : MessageBase
		{
			public SelectionKind kind;

			public byte recipeId;

			public NetworkInstanceId targetMasterId;

			public override void Serialize(NetworkWriter writer)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				writer.Write((byte)kind);
				writer.Write(recipeId);
				writer.Write(targetMasterId);
			}

			public override void Deserialize(NetworkReader reader)
			{
				//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)
				kind = (SelectionKind)reader.ReadByte();
				recipeId = reader.ReadByte();
				targetMasterId = reader.ReadNetworkId();
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static NetworkMessageDelegate <0>__HandleResult;
		}

		internal const short SelectionMessageType = 151;

		internal const short ResultMessageType = 152;

		private static NetworkClient registeredClient;

		internal static void RegisterClient(NetworkClient client)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if (registeredClient != client)
			{
				UnregisterClient();
				registeredClient = client;
				object obj = <>O.<0>__HandleResult;
				if (obj == null)
				{
					NetworkMessageDelegate val = HandleResult;
					<>O.<0>__HandleResult = val;
					obj = (object)val;
				}
				client.RegisterHandler((short)152, (NetworkMessageDelegate)obj);
			}
		}

		internal static void UnregisterClient()
		{
			NetworkClient obj = registeredClient;
			if (obj != null)
			{
				obj.UnregisterHandler((short)152);
			}
			registeredClient = null;
		}

		internal static void SendResult(CharacterMaster master, SelectionKind kind, bool accepted)
		{
			//IL_0086: 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)
			CharacterBody val = (((Object)(object)master != (Object)null) ? master.GetBody() : null);
			GenericSkill slot = GetSlot(val, kind);
			NetworkUser val2 = ((IEnumerable<NetworkUser>)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func<NetworkUser, bool>)((NetworkUser candidate) => (Object)(object)candidate.master == (Object)(object)master));
			if (!((Object)(object)val == (Object)null) && !((Object)(object)slot == (Object)null) && !((Object)(object)val2 == (Object)null) && ((NetworkBehaviour)val2).connectionToClient != null)
			{
				((NetworkBehaviour)val2).connectionToClient.Send((short)152, (MessageBase)(object)new ResultMessage
				{
					kind = kind,
					bodyId = ((NetworkBehaviour)val).netId,
					accepted = accepted,
					stock = slot.stock,
					recharge = slot.rechargeStopwatch
				});
			}
		}

		private static GenericSkill GetSlot(CharacterBody body, SelectionKind kind)
		{
			SkillLocator val = (((Object)(object)body != (Object)null) ? body.skillLocator : null);
			if (!((Object)(object)val == (Object)null))
			{
				return (GenericSkill)(kind switch
				{
					SelectionKind.JunkPatch => val.utility, 
					SelectionKind.Nanobot => val.special, 
					SelectionKind.Fabricator => val.secondary, 
					_ => null, 
				});
			}
			return null;
		}

		private static void HandleResult(NetworkMessage message)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			ResultMessage resultMessage = message.ReadMessage<ResultMessage>();
			GameObject obj = ClientScene.FindLocalObject(resultMessage.bodyId);
			CharacterBody val = ((obj != null) ? obj.GetComponent<CharacterBody>() : null);
			if ((Object)(object)val == (Object)null || !val.hasEffectiveAuthority)
			{
				return;
			}
			GenericSkill slot = GetSlot(val, resultMessage.kind);
			DrifterSkillDef val2 = ((resultMessage.kind == SelectionKind.Fabricator) ? Plugin.FabricatorSkill : ((resultMessage.kind == SelectionKind.Nanobot) ? Plugin.NanobotSkill : Plugin.JunkPatchSkill));
			if (!((Object)(object)slot == (Object)null) && !((Object)(object)slot.skillDef != (Object)(object)val2))
			{
				if (!NetworkServer.active)
				{
					slot.stock = resultMessage.stock;
					slot.rechargeStopwatch = resultMessage.recharge;
				}
				if (!resultMessage.accepted)
				{
					Chat.AddMessage("<color=#FFC080>UES Drifter: selection rejected. Check resources, target, stage restrictions, and skill readiness.</color>");
				}
			}
		}

		internal static void SendFabrication(byte recipeId)
		{
			Send(new SelectionMessage
			{
				kind = SelectionKind.Fabricator,
				recipeId = recipeId
			});
		}

		internal static void SendNanobot(NetworkInstanceId targetMasterId)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Send(new SelectionMessage
			{
				kind = SelectionKind.Nanobot,
				targetMasterId = targetMasterId
			});
		}

		private static void Send(SelectionMessage message)
		{
			NetworkClient val = (((Object)(object)NetworkManagerSystem.singleton != (Object)null) ? ((NetworkManager)NetworkManagerSystem.singleton).client : null);
			if (val != null && val.connection != null)
			{
				RegisterClient(val);
				val.connection.Send((short)151, (MessageBase)(object)message);
			}
		}

		internal static void HandleSelection(NetworkMessage netMessage)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			CharacterMaster senderMaster = GetSenderMaster(netMessage.conn);
			if ((Object)(object)senderMaster == (Object)null)
			{
				Debug.LogWarning((object)"[UES Drifter] Rejected selection: could not resolve the requesting player's CharacterMaster.");
				return;
			}
			SelectionMessage selectionMessage = netMessage.ReadMessage<SelectionMessage>();
			bool flag = false;
			switch (selectionMessage.kind)
			{
			case SelectionKind.Fabricator:
				flag = FabricationService.TryFabricate(senderMaster, selectionMessage.recipeId);
				break;
			case SelectionKind.Nanobot:
				flag = NanobotUpgradeService.TryUpgrade(senderMaster, selectionMessage.targetMasterId);
				break;
			}
			if (!flag)
			{
				Debug.LogWarning((object)("[UES Drifter] Server rejected selection kind=" + selectionMessage.kind.ToString() + ". Resources were not consumed."));
			}
			SendResult(senderMaster, selectionMessage.kind, flag);
		}

		internal static CharacterMaster GetSenderMaster(NetworkConnection connection)
		{
			if (connection == null || connection.playerControllers.Count == 0)
			{
				return null;
			}
			GameObject gameObject = connection.playerControllers[0].gameObject;
			if (!Object.op_Implicit((Object)(object)gameObject))
			{
				return null;
			}
			CharacterMaster component = gameObject.GetComponent<CharacterMaster>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			NetworkUser component2 = gameObject.GetComponent<NetworkUser>();
			if ((Object)(object)component2 != (Object)null && Object.op_Implicit((Object)(object)component2.masterObject))
			{
				return component2.masterObject.GetComponent<CharacterMaster>();
			}
			PlayerCharacterMasterController component3 = gameObject.GetComponent<PlayerCharacterMasterController>();
			if (!((Object)(object)component3 != (Object)null))
			{
				return null;
			}
			return component3.master;
		}
	}
	internal static class SelectionAuthority
	{
		internal enum Kind
		{
			Fabricator,
			Nanobot
		}

		private sealed class Window
		{
			internal Kind kind;

			internal float expiresAt;
		}

		private static readonly Dictionary<NetworkInstanceId, Window> windows = new Dictionary<NetworkInstanceId, Window>();

		internal static void Clear()
		{
			windows.Clear();
		}

		internal static void Remove(CharacterMaster master)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)master != (Object)null)
			{
				windows.Remove(((NetworkBehaviour)master).netId);
			}
		}

		internal static void Open(CharacterBody body, Kind kind)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active && !((Object)(object)body == (Object)null) && !((Object)(object)body.master == (Object)null) && IsCorrectVariant(body, kind) && (kind != Kind.Fabricator || (!((Object)(object)body.skillLocator == (Object)null) && body.skillLocator.secondary.stock >= 1)))
			{
				windows[((NetworkBehaviour)body.master).netId] = new Window
				{
					kind = kind,
					expiresAt = FixedTimeStamp.now.t + 12f
				};
			}
		}

		internal static bool Consume(CharacterMaster master, Kind kind, out CharacterBody body)
		{
			//IL_002e: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			body = (((Object)(object)master != (Object)null) ? master.GetBody() : null);
			if ((Object)(object)body == (Object)null || !IsCorrectVariant(body, kind) || !windows.TryGetValue(((NetworkBehaviour)master).netId, out var value))
			{
				return false;
			}
			if (value.kind != kind || FixedTimeStamp.now.t > value.expiresAt)
			{
				windows.Remove(((NetworkBehaviour)master).netId);
				return false;
			}
			windows.Remove(((NetworkBehaviour)master).netId);
			return true;
		}

		private static bool IsCorrectVariant(CharacterBody body, Kind kind)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body == (Object)null || (Object)(object)body.healthComponent == (Object)null || !body.healthComponent.alive || body.bodyIndex != BodyCatalog.FindBodyIndex(BodyPrefabs.DrifterBody) || (Object)(object)((Component)body).GetComponent<JunkController>() == (Object)null || (Object)(object)body.skillLocator == (Object)null)
			{
				return false;
			}
			if (kind != Kind.Fabricator)
			{
				if ((Object)(object)body.skillLocator.special != (Object)null)
				{
					return (Object)(object)body.skillLocator.special.skillDef == (Object)(object)Plugin.NanobotSkill;
				}
				return false;
			}
			if ((Object)(object)body.skillLocator.secondary != (Object)null)
			{
				return (Object)(object)body.skillLocator.secondary.skillDef == (Object)(object)Plugin.FabricatorSkill;
			}
			return false;
		}
	}
	internal static class FabricationService
	{
		internal readonly struct ScrapPayment
		{
			internal readonly int white;

			internal readonly int green;

			internal readonly int red;

			internal readonly int regenerating;

			internal ScrapPayment(int white, int green, int red, int regenerating)
			{
				this.white = white;
				this.green = green;
				this.red = red;
				this.regenerating = regenerating;
			}
		}

		internal const int MaxActiveFabricatedDrones = 8;

		internal static bool HasAvailableFabricationRecipe()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Run.instance == (Object)null || (Object)(object)VoidStageMissionController.instance != (Object)null)
			{
				return false;
			}
			SceneDef val = (((Object)(object)SceneInfo.instance != (Object)null) ? SceneInfo.instance.sceneDef : null);
			if ((Object)(object)val != (Object)null && val.suppressNpcEntry)
			{
				return false;
			}
			foreach (DroneRecipe item in UesRecipes.Fabrication)
			{
				DroneDef val2 = item.drone();
				if ((Object)(object)val2 != (Object)null && Run.instance.IsDroneAvailable(val2.droneIndex))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool TryFabricate(CharacterMaster playerMaster, byte recipeId)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !SelectionAuthority.Consume(playerMaster, SelectionAuthority.Kind.Fabricator, out var body))
			{
				return false;
			}
			if (!HasAvailableFabricationRecipe() || !UesRecipes.TryGet(recipeId, out var recipe))
			{
				return false;
			}
			DroneDef val = recipe.drone();
			JunkController component = ((Component)body).GetComponent<JunkController>();
			if ((Object)(object)val == (Object)null || (Object)(object)val.masterPrefab == (Object)null || (Object)(object)component == (Object)null)
			{
				return false;
			}
			if ((Object)(object)Run.instance == (Object)null || !Run.instance.IsDroneAvailable(val.droneIndex))
			{
				return false;
			}
			if ((Object)(object)body.skillLocator == (Object)null || body.skillLocator.secondary.stock < 1 || CountActiveFabricatedDrones(playerMaster) >= 8)
			{
				return false;
			}
			ResourceCost cost = recipe.cost;
			if (!CanPay(playerMaster.inventory, component, cost))
			{
				return false;
			}
			float currentJunk = component.CurrentJunk;
			ScrapPayment payment = Pay(playerMaster.inventory, component, cost);
			int num = Mathf.Max(0, Mathf.RoundToInt(currentJunk - component.CurrentJunk));
			GenericSkill secondary = body.skillLocator.secondary;
			int stock = secondary.stock;
			float rechargeStopwatch = secondary.rechargeStopwatch;
			CharacterMaster master = null;
			try
			{
				master = new MasterSummon
				{
					masterPrefab = val.masterPrefab,
					position = body.corePosition + ((Component)body).transform.forward * 3f,
					rotation = ((Component)body).transform.rotation,
					summonerBodyObject = ((Component)body).gameObject,
					ignoreTeamMemberLimit = true,
					useAmbientLevel = true,
					enablePrintController = true,
					preSpawnSetupCallback = delegate(CharacterMaster spawned)
					{
						//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)
						master = spawned;
						if ((Object)(object)spawned.inventory == (Object)null)
						{
							throw new InvalidOperationException("Summoned drone has no inventory.");
						}
						UESFabricatedDrone uESFabricatedDrone = ((Component)spawned).gameObject.AddComponent<UESFabricatedDrone>();
						uESFabricatedDrone.permanentTier = recipe.fabricationTier;
						uESFabricatedDrone.ownerMasterNetId = ((NetworkBehaviour)playerMaster).netId;
						uESFabricatedDrone.craftingCost = recipe.cost;
						uESFabricatedDrone.hasCraftingRecipe = true;
						if (recipe.fabricationTier > 1)
						{
							spawned.inventory.GiveItemPermanent(Items.DroneUpgradeHidden, recipe.fabricationTier - 1);
						}
					}
				}.Perform();
				if ((Object)(object)master == (Object)null || (Object)(object)master.inventory == (Object)null || (Object)(object)master.GetBody() == (Object)null)
				{
					throw new InvalidOperationException("Vanilla MasterSummon did not return a usable drone master and body.");
				}
				((Component)master).GetComponent<UESFabricatedDrone>()?.MarkBody(master.GetBody());
				StartFabricatorCooldown(body);
				return true;
			}
			catch (Exception ex)
			{
				if ((Object)(object)master != (Object)null)
				{
					master.DestroyBody();
					NetworkServer.Destroy(((Component)master).gameObject);
				}
				Refund(playerMaster.inventory, payment);
				playerMaster.inventory.GiveItemPermanent(Items.Junk, num);
				secondary.stock = stock;
				secondary.rechargeStopwatch = rechargeStopwatch;
				Debug.LogError((object)("[UES Drifter] Fabrication failed; payment refunded: " + ex));
				return false;
			}
		}

		internal static int CountActiveFabricatedDrones(CharacterMaster owner)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			MinionGroup val = (((Object)(object)owner != (Object)null) ? MinionGroup.FindGroup(((NetworkBehaviour)owner).netId) : null);
			if (val == null)
			{
				return 0;
			}
			int num = 0;
			MinionOwnership[] members = val.members;
			foreach (MinionOwnership val2 in members)
			{
				CharacterMaster val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponent<CharacterMaster>() : null);
				CharacterBody val4 = (((Object)(object)val3 != (Object)null) ? val3.GetBody() : null);
				if ((Object)(object)val4 != (Object)null && (Object)(object)val4.healthComponent != (Object)null && val4.healthComponent.alive && (Object)(object)val3.minionOwnership != (Object)null && (Object)(object)val3.minionOwnership.ownerMaster == (Object)(object)owner && JunkPatchTargeting.IsFabricatedDrone(val4))
				{
					num++;
				}
			}
			return num;
		}

		private static void StartFabricatorCooldown(CharacterBody playerBody)
		{
			GenericSkill val = (((Object)(object)playerBody != (Object)null && (Object)(object)playerBody.skillLocator != (Object)null) ? playerBody.skillLocator.secondary : null);
			if (!((Object)(object)val == (Object)null))
			{
				val.stock = 0;
				val.rechargeStopwatch = 0f;
				playerBody.OnSkillCooldown(val, 1);
			}
		}

		internal static bool CanPay(Inventory inventory, JunkController junk, ResourceCost cost)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)inventory == (Object)null || (Object)(object)junk == (Object)null || !junk.CanAfford(cost.junk))
			{
				return false;
			}
			int num = Mathf.Max(0, cost.whiteScrap - inventory.GetItemCountPermanent(Items.ScrapWhite.itemIndex));
			int num2 = Mathf.Max(0, cost.greenScrap - inventory.GetItemCountPermanent(Items.ScrapGreen.itemIndex));
			int num3 = Mathf.Max(0, cost.redScrap - inventory.GetItemCountPermanent(Items.ScrapRed.itemIndex));
			return inventory.GetItemCountPermanent(Items.RegeneratingScrap.itemIndex) >= num + num2 + num3;
		}

		internal static ScrapPayment Pay(Inventory inventory, JunkController junk, ResourceCost cost)
		{
			//IL_0018: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			junk.ConsumeJunk(cost.junk);
			int num = Mathf.Min(cost.whiteScrap, inventory.GetItemCountPermanent(Items.ScrapWhite.itemIndex));
			int num2 = Mathf.Min(cost.greenScrap, inventory.GetItemCountPermanent(Items.ScrapGreen.itemIndex));
			int num3 = Mathf.Min(cost.redScrap, inventory.GetItemCountPermanent(Items.ScrapRed.itemIndex));
			int num4 = cost.whiteScrap - num + cost.greenScrap - num2 + cost.redScrap - num3;
			if (num > 0)
			{
				inventory.RemoveItemPermanent(Items.ScrapWhite, num);
			}
			if (num2 > 0)
			{
				inventory.RemoveItemPermanent(Items.ScrapGreen, num2);
			}
			if (num3 > 0)
			{
				inventory.RemoveItemPermanent(Items.ScrapRed, num3);
			}
			if (num4 > 0)
			{
				inventory.RemoveItemPermanent(Items.RegeneratingScrap, num4);
			}
			return new ScrapPayment(num, num2, num3, num4);
		}

		internal static void Refund(Inventory inventory, ScrapPayment payment)
		{
			if (payment.white > 0)
			{
				inventory.GiveItemPermanent(Items.ScrapWhite, payment.white);
			}
			if (payment.green > 0)
			{
				inventory.GiveItemPermanent(Items.ScrapGreen, payment.green);
			}
			if (payment.red > 0)
			{
				inventory.GiveItemPermanent(Items.ScrapRed, payment.red);
			}
			if (payment.regenerating > 0)
			{
				inventory.GiveItemPermanent(Items.RegeneratingScrap, payment.regenerating);
			}
		}
	}
	public sealed class UESFabricatedDrone : MonoBehaviour
	{
		public int permanentTier = 1;

		public NetworkInstanceId ownerMasterNetId;

		public ResourceCost craftingCost;

		public bool hasCraftingRecipe;

		private float damageStopwatch;

		private readonly DroneHealthSnapshot healthSnapshot = new DroneHealthSnapshot();

		private CharacterBody snapshotBody;

		internal void CaptureHealth(HealthComponent health)
		{
			if (NetworkServer.active && !((Object)(object)health == (Object)null) && health.alive && !healthSnapshot.Pending)
			{
				healthSnapshot.Capture(health.health, health.fullHealth, health.shield, health.fullShield, health.alive);
				snapshotBody = health.body;
			}
		}

		internal void RestoreHealth(CharacterBody body)
		{
			if (!NetworkServer.active || (Object)(object)body == (Object)null || (Object)(object)body.healthComponent == (Object)null)
			{
				return;
			}
			MarkBody(body);
			if (!((Object)(object)body == (Object)(object)snapshotBody))
			{
				HealthComponent healthComponent = body.healthComponent;
				if (healthSnapshot.Restore(healthComponent.fullHealth, healthComponent.fullShield, out var health, out var shield))
				{
					healthComponent.Networkhealth = health;
					healthComponent.Networkshield = shield;
					snapshotBody = null;
				}
			}
		}

		internal void ClearSavedHealth()
		{
			healthSnapshot.Clear();
			snapshotBody = null;
		}

		internal void MarkBody(CharacterBody body)
		{
			if ((Object)(object)body != (Object)null && (Object)(object)Plugin.FabricatedDroneBuff != (Object)null && !body.HasBuff(Plugin.FabricatedDroneBuff))
			{
				body.AddBuff(Plugin.FabricatedDroneBuff);
			}
		}

		private void FixedUpdate()
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			if (!NetworkServer.active)
			{
				return;
			}
			CharacterMaster component = ((Component)this).GetComponent<CharacterMaster>();
			CharacterBody val = ((component != null) ? component.GetBody() : null);
			HealthComponent val2 = (((Object)(object)val != (Object)null) ? val.healthComponent : null);
			if (!((Object)(object)val2 == (Object)null) && val2.alive && !healthSnapshot.Pending)
			{
				damageStopwatch += Time.fixedDeltaTime;
				float fabricatedDroneDecayInterval = JunkPatchPassiveService.GetFabricatedDroneDecayInterval(this);
				if (!(damageStopwatch < fabricatedDroneDecayInterval))
				{
					damageStopwatch -= fabricatedDroneDecayInterval;
					val2.TakeDamage(new DamageInfo
					{
						damage = val2.fullCombinedHealth * JunkPatchPassiveService.GetFabricatedDroneDecayFraction(this),
						position = val.corePosition,
						inflictor = ((Component)this).gameObject,
						damageType = DamageTypeCombo.op_Implicit((DamageType)0),
						damageColorIndex = (DamageColorIndex)0,
						procCoefficient = 0f
					});
				}
			}
		}
	}
	internal static class JunkPatchPassiveService
	{
		internal const int BaseJunkCost = 12;

		private const int CostReductionPerDrone = 2;

		private const int MaxCostReductionDrones = 6;

		private const int MaxDecayTimeIncreaseDrones = 3;

		private const int MaxDecayAmountReductionDrones = 3;

		private const float BaseDecayInterval = 12f;

		private const float BaseDecayFraction = 0.02f;

		private const float DecayReductionPerDrone = 0.005f;

		internal static int GetFabricatedDroneCount(CharacterBody body)
		{
			if (!((Object)(object)body != (Object)null) || !((Object)(object)body.master != (Object)null))
			{
				return 0;
			}
			return FabricationService.CountActiveFabricatedDrones(body.master);
		}

		internal static int GetJunkCost(CharacterBody body)
		{
			return Mathf.Max(0, 12 - Mathf.Min(6, GetFabricatedDroneCount(body)) * 2);
		}

		internal static bool CanAfford(CharacterBody body)
		{
			JunkController val = (((Object)(object)body != (Object)null) ? ((Component)body).GetComponent<JunkController>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return val.CanAfford(GetJunkCost(body));
			}
			return false;
		}

		internal static float GetFabricatedDroneDecayFraction(UESFabricatedDrone fabricatedDrone)
		{
			int ownerFabricatedDroneCount = GetOwnerFabricatedDroneCount(fabricatedDrone);
			return Mathf.Max(0f, 0.02f - (float)Mathf.Clamp(ownerFabricatedDroneCount - 3, 0, 3) * 0.005f);
		}

		internal static float GetFabricatedDroneDecayInterval(UESFabricatedDrone fabricatedDrone)
		{
			return 12f + (float)Mathf.Min(3, GetOwnerFabricatedDroneCount(fabricatedDrone));
		}

		private static int GetOwnerFabricatedDroneCount(UESFabricatedDrone fabricatedDrone)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (!((Object)(object)fabricatedDrone != (Object)null))
			{
				obj = null;
			}
			else
			{
				GameObject obj2 = NetworkServer.FindLocalObject(fabricatedDrone.ownerMasterNetId);
				obj = ((obj2 != null) ? obj2.GetComponent<CharacterMaster>() : null);
			}
			CharacterMaster val = (CharacterMaster)obj;
			if (!((Object)(object)val != (Object)null))
			{
				return 0;
			}
			return FabricationService.CountActiveFabricatedDrones(val);
		}
	}
	public sealed class NanobotTemporaryUpgrade : MonoBehaviour
	{
		public int addedStacks = 1;
	}
	internal sealed class HoarderEfficiencyRemainder : MonoBehaviour
	{
		internal float extraJunkRemainder;
	}
	internal static class HoarderEfficiencyService
	{
		private const float WhiteScrapChance = 0.05f;

		private const float GreenScrapChance = 0.01f;

		private const float RedScrapChance = 0.005f;

		private const float YellowScrapChance = 0.001f;

		private const float MinimumScrapChance = 0.0001f;

		internal static bool IsActive(CharacterBody body)
		{
			if ((Object)(object)body != (Object)null && (Object)(object)body.skillLocator != (Object)null && (Object)(object)body.skillLocator.secondary != (Object)null && (Object)(object)body.skillLocator.special != (Object)null && (Object)(object)body.skillLocator.secondary.skillDef == (Object)(object)Plugin.FabricatorSkill)
			{
				return (Object)(object)body.skillLocator.special.skillDef == (Object)(object)Plugin.NanobotSkill;
			}
			return false;
		}

		internal static bool IsFabricatorActive(CharacterBody body)
		{
			if ((Object)(object)body != (Object)null && (Object)(object)body.skillLocator != (Object)null && (Object)(object)body.skillLocator.secondary != (Object)null)
			{
				return (Object)(object)body.skillLocator.secondary.skillDef == (Object)(object)Plugin.FabricatorSkill;
			}
			return false;
		}

		internal static int ProcessJunkGeneration(JunkController controller, int quantity)
		{
			if (!NetworkServer.active || (Object)(object)controller == (Object)null || quantity <= 0 || !IsActive(((Component)controller).GetComponent<CharacterBody>()))
			{
				return quantity;
			}
			CharacterBody component = ((Component)controller).GetComponent<CharacterBody>();
			int num = Mathf.Max(0, 8 - FabricationService.CountActiveFabricatedDrones(component.master)) / 2;
			float num2 = 1f + 0.25f * (float)num;
			HoarderEfficiencyRemainder hoarderEfficiencyRemainder = ((Component)controller).GetComponent<HoarderEfficiencyRemainder>() ?? ((Component)controller).gameObject.AddComponent<HoarderEfficiencyRemainder>();
			float num3 = (float)quantity * num2 + hoarderEfficiencyRemainder.extraJunkRemainder;
			int num4 = Mathf.FloorToInt(num3);
			hoarderEfficiencyRemainder.extraJunkRemainder = num3 - (float)num4;
			quantity = Mathf.Max(quantity, num4);
			if (controller.CurrentJunk < (float)controller.MaxJunk || (Object)(object)component.inventory == (Object)null)
			{
				return quantity;
			}
			for (int num5 = quantity - 1; num5 >= 0; num5--)
			{
				float num6 = AdjustedChance(component.inventory, Items.ScrapWhite, 0.05f);
				float num7 = AdjustedChance(component.inventory, Items.ScrapGreen, 0.01f);
				float num8 = AdjustedChance(component.inventory, Items.ScrapRed, 0.005f);
				float num9 = AdjustedChance(component.inventory, Items.ScrapYellow, 0.001f);
				float value = Random.value;
				ItemDef val = ((value < num6) ? Items.ScrapWhite : ((value < num6 + num7) ? Items.ScrapGreen : ((value < num6 + num7 + num8) ? Items.ScrapRed : ((value < num6 + num7 + num8 + num9) ? Items.ScrapYellow : null))));
				if ((Object)(object)val != (Object)null)
				{
					component.inventory.GiveItemPermanent(val, 1);
					quantity--;
				}
			}
			return quantity;
		}

		private static float AdjustedChance(Inventory inventory, ItemDef scrap, float baseChance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			int itemCountPermanent = inventory.GetItemCountPermanent(scrap.itemIndex);
			return Mathf.Max(0.0001f, baseChance * Mathf.Max(0.05f, 1f - (float)itemCountPermanent * (19f / 160f)));
		}

		internal static float GetFabricatedDroneCooldownMultiplier(GenericSkill skill)
		{
			CharacterBody val = (((Object)(object)skill != (Object)null) ? skill.characterBody : null);
			CharacterMaster val2 = (((Object)(object)val != (Object)null) ? val.master : null);
			if ((Object)(object)val2 == (Object)null || !JunkPatchTargeting.IsFabricatedDrone(val) || (Object)(object)val2.minionOwnership == (Object)null)
			{
				return 1f;
			}
			CharacterMaster ownerMaster = val2.minionOwnership.ownerMaster;
			CharacterBody val3 = ((ownerMaster != null) ? ownerMaster.GetBody() : null);
			JunkController val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<JunkController>() : null);
			if (!IsActive(val3) || (Object)(object)val4 == (Object)null)
			{
				return 1f;
			}
			float num = Mathf.Min(0.4f, (float)Mathf.FloorToInt(val4.CurrentJunk / 4f) * 0.1f);
			return 1f - num;
		}

		internal static bool IsFabricatedDroneSkill(GenericSkill skill)
		{
			return JunkPatchTargeting.IsFabricatedDrone(((Object)(object)skill != (Object)null) ? skill.characterBody : null);
		}
	}
	internal sealed class HoarderPassiveDisplay : MonoBehaviour
	{
		private CharacterBody characterBody;

		private JunkController junkController;

		private int originalMaxJunk;

		private int appliedMaxJunk = -1;

		private bool fabricatorActive;

		private int observedJunk = -1;

		private void Awake()
		{
			characterBody = ((Component)this).GetComponent<CharacterBody>();
			junkController = ((Component)this).GetComponent<JunkController>();
			if ((Object)(object)junkController != (Object)null)
			{
				originalMaxJunk = junkController.MaxJunk;
			}
		}

		private void Update()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			bool flag = HoarderEfficiencyService.IsActive(characterBody);
			int num = (flag ? 20 : originalMaxJunk);
			if ((Object)(object)junkController == (Object)null)
			{
				return;
			}
			if (appliedMaxJunk != num)
			{
				junkController.MaxJunk = num;
				appliedMaxJunk = num;
				CharacterBody component = ((Component)junkController).GetComponent<CharacterBody>();
				if (NetworkServer.active && (Object)(object)component != (Object)null && (Object)(object)component.inventory != (Object)null)
				{
					component.inventory.EnforceItemStackLimit(Items.Junk.itemIndex, num);
				}
			}
			int num2 = Mathf.RoundToInt(junkController.CurrentJunk);
			if (fabricatorActive != flag || observedJunk != num2)
			{
				fabricatorActive = flag;
				observedJunk = num2;
				characterBody.RecalculateStats();
			}
		}
	}
	internal static class JunkPatchTrashToTreasureService
	{
		internal static void Apply(CharacterBody source, CharacterBody target)
		{
			if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null) && !((Object)(object)source.inventory == (Object)null))
			{
				Refresh(target, Buffs.TrashToTreasureWhite, source.inventory.GetItemCountEffective(Items.ScrapWhite));
				Refresh(target, Buffs.TrashToTreasureGreen, source.inventory.GetItemCountEffective(Items.ScrapGreen) + source.inventory.GetItemCountEffective(Items.RegeneratingScrap));
				Refresh(target, Buffs.TrashToTreasureRed, source.inventory.GetItemCountEffective(Items.ScrapRed));
				Refresh(target, Buffs.TrashToTreasureYellow, source.inventory.GetItemCountEffective(Items.ScrapYellow));
			}
		}

		private static void Refresh(CharacterBody target, BuffDef buff, int count)
		{
			target.ClearTimedBuffs(buff);
			for (int i = 0; i < count; i++)
			{
				target.AddTimedBuff(buff, 10f);
			}
		}
	}
	internal sealed class JunkHudCounter : MonoBehaviour
	{
		private JunkController junkController;

		private TextMeshProUGUI text;

		private int currentJunk = -1;

		private int maxJunk = -1;

		internal void Initialize(JunkController controller)
		{
			junkController = controller;
			ChildLocator component = ((Component)this).GetComponent<ChildLocator>();
			Transform val = (((Object)(object)component != (Object)null && (Object)(object)controller != (Object)null) ? component.FindChild(controller.percentageUIString) : null);
			text = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TextMeshProUGUI>() : null);
		}

		private void Update()
		{
			if (!((Object)(object)junkController == (Object)null) && !((Object)(object)text == (Object)null))
			{
				int num = Mathf.RoundToInt(junkController.CurrentJunk);
				if (num != currentJunk || junkController.MaxJunk != maxJunk)
				{
					currentJunk = num;
					maxJunk = junkController.MaxJunk;
					((TMP_Text)text).SetText(currentJunk + " / " + maxJunk, true);
				}
			}
		}
	}
	internal static class JunkPatchIndicatorPrefab
	{
		private static GameObject prefab;

		private static Material material;

		private static Texture2D gradientTexture;

		private static Sprite gradientSprite;

		private static bool loading;

		private static GameObject cacheRoot;

		private static AsyncOperationHandle<GameObject> sourceHandle;

		private static bool failed;

		internal static void Prepare()
		{
			if (!((Object)(object)prefab != (Object)null) && !loading && !failed && !((Object)(object)Plugin.Instance == (Object)null) && !Application.isBatchMode)
			{
				loading = true;
				((MonoBehaviour)Plugin.Instance).StartCoroutine(Load());
			}
		}

		internal static GameObject Get()
		{
			Prepare();
			return prefab;
		}

		private static IEnumerator Load()
		{
			AsyncOperationHandle<GameObject> operation = (sourceHandle = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/PassiveHealing/WoodSpriteIndicator.prefab"));
			yield return operation;
			loading = false;
			if (!operation.IsValid() || (int)operation.Status != 1 || (Object)(object)operation.Result == (Object)null)
			{
				failed = true;
				Debug.LogWarning((object)"[UES Drifter] Could not load the Junk Patch indicator prefab.");
				yield break;
			}
			GameObject result = operation.Result;
			cacheRoot = new GameObject("UESJunkPatchIndicatorCache");
			cacheRoot.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)cacheRoot);
			prefab = Object.Instantiate<GameObject>(result, cacheRoot.transform);
			((Object)prefab).name = "UESJunkPatchWoodSpriteIndicator";
			InputBindingDisplayController componentInChildren = prefab.GetComponentInChildren<InputBindingDisplayController>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.actionName = "UtilitySkill";
			}
			Transform val = prefab.transform.Find("Holder");
			SpriteRenderer val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<SpriteRenderer>() : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sprite != (Object)null)
			{
				gradientSprite = CreateGradientSprite(val2.sprite);
				material = new Material(((Renderer)val2).sharedMaterial)
				{
					name = "UESJunkPatchWoodSpriteGradientMaterial"
				};
				val2.sprite = gradientSprite;
				((Renderer)val2).material = material;
				val2.color = new Color(1f, 1f, 1f, val2.color.a);
			}
		}

		internal static void Dispose()
		{
			//IL_0043: 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)
			Object.Destroy((Object)(object)cacheRoot);
			Object.Destroy((Object)(object)material);
			Object.Destroy((Object)(object)gradientSprite);
			Object.Destroy((Object)(object)gradientTexture);
			if (sourceHandle.IsValid())
			{
				Addressables.Release<GameObject>(sourceHandle);
			}
			sourceHandle = default(AsyncOperationHandle<GameObject>);
			cacheRoot = null;
			prefab = null;
			material = null;
			gradientSprite = null;
			gradientTexture = null;
			loading = false;
			failed = false;
		}

		private static Sprite CreateGradientSprite(Sprite source)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_004e: 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_0064: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: 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)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			Texture2D texture = source.texture;
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture.active = temporary;
				gradientTexture = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false)
				{
					name = "UESJunkPatchWoodSpriteGradientTexture",
					filterMode = ((Texture)texture).filterMode,
					wrapMode = (TextureWrapMode)1
				};
				gradientTexture.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0);
				gradientTexture.Apply();
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
			Color32[] pixels = gradientTexture.GetPixels32();
			Rect val = source.textureRect;
			float xMin = ((Rect)(ref val)).xMin;
			val = source.textureRect;
			float num = Mathf.Max(1f, ((Rect)(ref val)).width);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.58f, 1f, 0.12f, 1f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(1f, 0.34f, 0.04f, 1f);
			for (int i = 0; i < ((Texture)gradientTexture).height; i++)
			{
				for (int j = 0; j < ((Texture)gradientTexture).width; j++)
				{
					int num2 = i * ((Texture)gradientTexture).width + j;
					Color val4 = Color.Lerp(val2, val3, Mathf.Clamp01(((float)j - xMin) / num));
					pixels[num2] = new Color32((byte)(val4.r * 255f), (byte)(val4.g * 255f), (byte)(val4.b * 255f), pixels[num2].a);
				}
			}
			gradientTexture.SetPixels32(pixels);
			gradientTexture.Apply();
			Texture2D obj = gradientTexture;
			Rect rect = source.rect;
			float x = source.pivot.x;
			val = source.rect;
			float num3 = x / ((Rect)(ref val)).width;
			float y = source.pivot.y;
			val = source.rect;
			return Sprite.Create(obj, rect, new Vector2(num3, y / ((Rect)(ref val)).height), source.pixelsPerUnit, 0u, (SpriteMeshType)0, source.border);
		}
	}
	internal static class JunkPatchTargeting
	{
		internal const float AllyRange = 14f;

		internal const float DroneRange = 46f;

		internal static HealthComponent FindTarget(CharacterBody body, Ray aimRay)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_002e: 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_0038: 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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_0085: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body == (Object)null || (Object)(object)body.teamComponent == (Object)null)
			{
				return null;
			}
			float num = default(float);
			aimRay = CameraRigController.ModifyAimRayIfApplicable(aimRay, ((Component)body).gameObject, ref num);
			BullseyeSearch val = new BullseyeSearch
			{
				viewer = body,
				searchOrigin = ((Ray)(ref aimRay)).origin,
				searchDirection = ((Ray)(ref aimRay)).direction,
				maxDistanceFilter = 46f,
				maxAngleFilter = 10f,
				sortMode = (SortMode)2,
				filterByLoS = true,
				filterByDistinctEntity = false,
				teamMaskFilter = TeamMask.none
			};
			((TeamMask)(ref val.teamMaskFilter)).AddTeam(body.teamComponent.teamIndex);
			val.RefreshCandidates();
			val.FilterOutGameObject(((Component)body).gameObject);
			foreach (HurtBox result in val.GetResults())
			{
				if (!((Object)(object)result == (Object)null) && !((Object)(object)result.healthComponent == (Object)null) && result.healthComponent.alive)
				{
					CharacterBody body2 = result.healthComponent.body;
					float num2 = (((Object)(object)body2 != (Object)null && (body2.bodyFlags & 0x400000) != 0) ? 46f : 14f);
					Vector3 val2 = ((Component)result).transform.position - ((Ray)(ref aimRay)).origin;
					if (((Vector3)(ref val2)).sqrMagnitude <= num2 * num2)
					{
						return result.healthComponent;
					}
				}
			}
			return null;
		}

		internal static bool IsFabricatedDrone(CharacterBody body)
		{
			if ((Object)(object)body != (Object)null)
			{
				if (!((Object)(object)body.master != (Object)null) || !((Object)(object)((Component)body.master).GetComponent<UESFabricatedDrone>() != (Object)null))
				{
					if ((Object)(object)Plugin.FabricatedDroneBuff != (Object)null)
					{
						return body.HasBuff(Plugin.FabricatedDroneBuff);
					}
					return false;
				}
				return true;
			}
			return false;
		}
	}
	internal static class JunkPatchHealingService
	{
		[ThreadStatic]
		private static bool isHealing;

		internal static float Heal(HealthComponent target, float amount)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			bool flag = isHealing;
			isHealing = true;
			try
			{
				return target.Heal(amount, default(ProcChainMask), true);
			}
			finally
			{
				isHealing = flag;
			}
		}

		internal static bool CanHeal(HealthComponent target)
		{
			if (!isHealing)
			{
				return !JunkPatchTargeting.IsFabricatedDrone(((Object)(object)target != (Object)null) ? target.body : null);
			}
			return true;
		}
	}
	internal static class FabricatedDroneScrappingService
	{
		private sealed class PendingDrops
		{
			internal readonly List<PickupIndex> pickups;

			internal int nextIndex;

			internal PendingDrops(List<PickupIndex> pickups)
			{
				this.pickups = pickups;
			}
		}

		private static readonly Dictionary<DroneScrapperController, PendingDrops> pendingDrops = new Dictionary<DroneScrapperController, PendingDrops>();

		internal static void Clear()
		{
			pendingDrops.Clear();
		}

		internal static void Begin(DroneScrapperController controller, NetworkInstanceId bodyId)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			pendingDrops.Remove(controller);
			if (!NetworkServer.active)
			{
				return;
			}
			GameObject val = NetworkServer.FindLocalObject(bodyId);
			object obj;
			if (!((Object)(object)val != (Object)null))
			{
				obj = null;
			}
			else
			{
				CharacterBody component = val.GetComponent<CharacterBody>();
				if (component == null)
				{
					obj = null;
				}
				else
				{
					CharacterMaster master = component.master;
					obj = ((master != null) ? ((Component)master).GetComponent<UESFabricatedDrone>() : null);
				}
			}
			UESFabricatedDrone uESFabricatedDrone = (UESFabricatedDrone)obj;
			if (!((Object)(object)uESFabricatedDrone == (Object)null) && uESFabricatedDrone.hasCraftingRecipe)
			{
				List<PickupIndex> pickups = new List<PickupIndex>();
				AddScrap(pickups, Items.ScrapWhite, uESFabricatedDrone.craftingCost.whiteScrap);
				AddScrap(pickups, Items.ScrapGreen, uESFabricatedDrone.craftingCost.greenScrap);
				AddScrap(pickups, Items.ScrapRed, uESFabricatedDrone.craftingCost.redScrap);
				pendingDrops[controller] = new PendingDrops(pickups);
			}
		}

		internal static bool TryHandleDrop(DroneScrappingToIdle state)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			DroneScrapperController val = (((Object)(object)((EntityState)state).outer != (Object)null) ? ((Component)((EntityState)state).outer).GetComponent<DroneScrapperController>() : null);
			if ((Object)(object)val == (Object)null || !pendingDrops.TryGetValue(val, out var value))
			{
				return false;
			}
			if (NetworkServer.active && value.nextIndex < value.pickups.Count)
			{
				PickupIndex val2 = value.pickups[value.nextIndex++];
				Transform transform = ((Component)((EntityState)state).outer).transform;
				PickupDropletController.CreatePickupDroplet(new UniquePickup(val2), transform.position + transform.up, transform.up * 12f, false);
			}
			state.droppedScrap++;
			if (state.droppedScrap >= val.lastScrapDropCount)
			{
				pendingDrops.Remove(val);
			}
			return true;
		}

		internal static bool TryGetDropCount(DroneScrapperController controller, out int count)
		{
			if (pendingDrops.TryGetValue(controller, out var value))
			{
				count = value.pickups.Count;
				return true;
			}
			count = 0;
			return false;
		}

		private static void AddScrap(List<PickupIndex> pickups, ItemDef scrap, int recipeCost)
		{
			//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_0010: 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_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)
			if (recipeCost > 0)
			{
				PickupIndex val = PickupCatalog.FindPickupIndex(scrap.itemIndex);
				if (val != PickupIndex.none)
				{
					pickups.Add(val);
				}
			}
		}
	}
	internal sealed class JunkPatchTargetingIndicator : MonoBehaviour
	{
		private CharacterBody body;

		private Indicator indicator;

		private void Awake()
		{
			body = ((Component)this).GetComponent<CharacterBody>();
		}

		private void OnDisable()
		{
			if (indicator != null)
			{
				indicator.active = false;
			}
		}

		private void Update()
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			GenericSkill val = (((Object)(object)body != (Object)null && (Object)(object)body.skillLocator != (Object)null) ? body.skillLocator.utility : null);
			if ((Object)(object)body == (Object)null || !body.hasEffectiveAuthority || (Object)(object)val == (Object)null || (Object)(object)val.skillDef != (Object)(object)Plugin.JunkPatchSkill || !val.IsReady())
			{
				if (indicator != null)
				{
					indicator.active = false;
				}
				return;
			}
			GameObject val2 = JunkPatchIndicatorPrefab.Get();
			if (!((Object)(object)val2 == (Object)null))
			{
				if (indicator == null)
				{
					indicator = new Indicator(((Component)this).gameObject, val2);
				}
				Ray aimRay = (Ray)(((Object)(object)body.inputBank != (Object)null) ? body.inputBank.GetAimRay() : new Ray(body.corePosition, ((Component)body).transform.forward));
				HealthComponent val3 = JunkPatchTargeting.FindTarget(body, aimRay);
				indicator.targetTransform = (((Object)(object)val3 != (Object)null) ? ((Component)val3).transform : null);
				indicator.active = (Object)(object)val3 != (Object)null;
			}
		}
	}
	internal static class NanobotUpgradeService
	{
		internal const int MaxActiveNanobotUpgrades = 2;

		internal static bool TryUpgrade(CharacterMaster playerMaster, NetworkInstanceId targetMasterId)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !SelectionAuthority.Consume(playerMaster, SelectionAuthority.Kind.Nanobot, out var body))
			{
				return false;
			}
			GameObject val = NetworkServer.FindLocalObject(targetMasterId);
			CharacterMaster val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<CharacterMaster>() : null);
			if (!IsEligible(playerMaster, val2))
			{
				return false;
			}
			if (CountActiveNanobotUpgrades(playerMaster) >= 2)
			{
				return false;
			}
			JunkController component = ((Component)body).GetComponent<JunkController>();
			if (!TryGetCost(val2, out var cost))
			{
				return false;
			}
			if (!FabricationService.CanPay(playerMaster.inventory, component, cost))
			{
				return false;
			}
			float currentJunk = component.CurrentJunk;
			FabricationService.ScrapPayment payment = FabricationService.Pay(playerMaster.inventory, component, cost);
			int num = Mathf.Max(0, Mathf.RoundToInt(currentJunk - component.CurrentJunk));
			NanobotTemporaryUpgrade nanobotTemporaryUpgrade = null;
			bool flag = false;
			try
			{
				nanobotTemporaryUpgrade = ((Component)val2).gameObject.AddComponent<NanobotTemporaryUpgrade>();
				val2.inventory.GiveItemPermanent(Items.DroneUpgradeHidden, 1);
				flag = true;
				CharacterBody body2 = val2.GetBody();
				if (body2 != null)
				{
					body2.AddBuff(Plugin.NanobotActiveBuff);
				}
				return true;
			}
			catch (Exception ex)
			{
				if (flag)
				{
					val2.inventory.RemoveItemPermanent(Items.DroneUpgradeHidden, 1);
				}
				CharacterBody body3 = val2.GetBody();
				if (body3 != null)
				{
					body3.RemoveBuff(Plugin.NanobotActiveBuff);
				}
				if ((Object)(object)nanobotTemporaryUpgrade != (Object)null)
				{
					nanobotTemporaryUpgrade.addedStacks = 0;
					Object.Destroy((Object)(object)nanobotTemporaryUpgrade);
				}
				FabricationService.Refund(playerMaster.inventory, payment);
				playerMaster.inventory.GiveItemPermanent(Items.Junk, num);
				Debug.LogError((object)("[UES Drifter] Nanobot upgrade failed; payment refunded: " + ex));
				return false;
			}
		}

		internal static int CountActiveNanobotUpgrades(CharacterMaster owner)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			MinionGroup val = (((Object)(object)owner != (Object)null) ? MinionGroup.FindGroup(((NetworkBehaviour)owner).netId) : null);
			if (val == null)
			{
				return 0;
			}
			int num = 0;
			MinionOwnership[] members = val.members;
			foreach (MinionOwnership val2 in members)
			{
				CharacterMaster val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponent<CharacterMaster>() : null);
				CharacterBody val4 = (((Object)(object)val3 != (Object)null) ? val3.GetBody() : null);
				if ((Object)(object)val4 != (Object)null && (Object)(object)val4.healthComponent != (Object)null && val4.healthComponent.alive && IsNanobotActive(val3))
				{
					num++;
				}
			}
			return num;
		}

		internal static bool IsEligible(CharacterMaster owner, CharacterMaster droneMaster)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner == (Object)null || (Object)(object)droneMaster == (Object)null || (Object)(object)droneMaster.inventory == (Object)null || IsNanobotActive(droneMaster))
			{
				return false;
			}
			if ((Object)(object)droneMaster.minionOwnership == (Object)null || (Object)(object)droneMaster.minionOwnership.ownerMaster != (Object)(object)owner)
			{
				return false;
			}
			CharacterBody body = droneMaster.GetBody();
			if ((Object)(object)body == (Object)null || (Object)(object)body.healthComponent == (Object)null || !body.healthComponent.alive || (body.bodyFlags & 0x400000) == 0)
			{
				return false;
			}
			DroneDef droneDef = DroneCatalog.GetDroneDef(DroneCatalog.GetDroneIndexFromBodyIndex(body.bodyIndex));
			ResourceCost cost;
			if ((Object)(object)droneDef != (Object)null && droneDef.canCombine)
			{
				return UesRecipes.TryGetNanobotCost(droneDef, out cost);
			}
			return false;
		}

		internal static bool IsNanobotActive(CharacterMaster droneMaster)
		{
			if ((Object)(object)droneMaster == (Object)null)
			{
				return false;
			}
			NanobotTemporaryUpgrade component = ((Component)droneMaster).GetComponent<NanobotTemporaryUpgrade>();
			if ((Object)(object)component != (Object)null && component.addedStacks > 0)
			{
				return true;
			}
			CharacterBody body = droneMaster.GetBody();
			if ((Object)(object)body != (Object)null && (Object)(object)Plugin.NanobotActiveBuff != (Object)null)
			{
				return body.HasBuff(Plugin.NanobotActiveBuff);
			}
			return false;
		}

		internal static bool TryGetCost(CharacterMaster droneMaster, out ResourceCost cost)
		{
			//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)
			CharacterBody val = (((Object)(object)droneMaster != (Object)null) ? droneMaster.GetBody() : null);
			DroneDef val2 = (((Object)(object)val != (Object)null) ? DroneCatalog.GetDroneDef(DroneCatalog.GetDroneIndexFromBodyIndex(val.bodyIndex)) : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return UesRecipes.TryGetNanobotCost(val2, out cost);
			}
			cost = default(ResourceCost);
			return false;
		}

		internal static void RemoveStageLimitedUpgrades(Stage _)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			NanobotTemporaryUpgrade[] array = Object.FindObjectsOfType<NanobotTemporaryUpgrade>();
			foreach (NanobotTemporaryUpgrade nanobotTemporaryUpgrade in array)
			{
				CharacterMaster component = ((Component)nanobotTemporaryUpgrade).GetComponent<CharacterMaster>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.inventory != (Object)null)
				{
					component.inventory.RemoveItemPermanent(Items.DroneUpgradeHidden, nanobotTemporaryUpgrade.addedStacks);
					CharacterBody body = component.GetBody();
					if (body != null)
					{
						body.RemoveBuff(Plugin.NanobotActiveBuff);
					}
					nanobotTemporaryUpgrade.addedStacks = 0;
				}
				Object.Destroy((Object)(object)nanobotTemporaryUpgrade);
			}
		}
	}
	[HarmonyPatch(typeof(PauseManager), "TogglePauseScreen")]
	internal static class PreventPauseWhileUesMenuIsOpen
	{
		private static bool Prefix()
		{
			return !FabricationMenu.IsOpen;
		}
	}
	[HarmonyPatch(typeof(JunkController), "GenerateJunk")]
	internal static class ApplyHoarderEfficiencyToJunkGeneration
	{
		private static void Prefix(JunkController __instance, ref int quantity)
		{
			quantity = HoarderEfficiencyService.ProcessJunkGeneration(__instance, quantity);
		}
	}
	[HarmonyPatch(typeof(JunkController), "OnOverlayInstanceAdded")]
	internal static class ShowNumericalJunkCount
	{
		private static void Postfix(JunkController __instance, GameObject instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)instance == (Object)null) && !((Object)(object)instance.GetComponent<JunkHudCounter>() != (Object)null))
			{
				instance.AddComponent<JunkHudCounter>().Initialize(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(GenericSkill), "RunRecharge", new Type[]
	{
		typeof(float),
		typeof(bool)
	})]
	internal static class ApplyHoarderEfficiencyToFabricatedDroneCooldowns
	{
		private static void Prefix(GenericSkill __instance)
		{
			if (HoarderEfficiencyService.IsFabricatedDroneSkill(__instance))
			{
				__instance.RecalculateValues();
			}
		}
	}
	[HarmonyPatch(typeof(GenericSkill), "CalculateFinalRechargeInterval")]
	internal static class ApplyHoarderEfficiencyCooldownMultiplier
	{
		private static void Postfix(GenericSkill __instance, ref float __result)
		{
			__result *= HoarderEfficiencyService.GetFabricatedDroneCooldownMultiplier(__instance);
		}
	}
	[HarmonyPatch(typeof(CharacterBody), "RecalculateStats")]
	internal static class ApplyFabricatorJunkCombatStats
	{
		private static readonly FieldInfo DamageField = AccessTools.Field(typeof(CharacterBody), "<damage>k__BackingField");

		private static readonly FieldInfo AttackSpeedField = AccessTools.Field(typeof(CharacterBody), "<attackSpeed>k__BackingField");

		private static void Postfix(CharacterBody __instance)
		{
			JunkController val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<JunkController>() : null);
			if (HoarderEfficiencyService.IsFabricatorActive(__instance) && !((Object)(object)val == (Object)null) && val.MaxJunk > 0 && !(DamageField == null) && !(AttackSpeedField == null))
			{
				float num = Mathf.Clamp01(val.CurrentJunk / (float)val.MaxJunk);
				DamageField.SetValue(__instance, __instance.damage * Mathf.Lerp(1f, 2f, num));
				AttackSpeedField.SetValue(__instance, __instance.attackSpeed * Mathf.Lerp(1f, 0.5f, num));
			}
		}
	}
	[HarmonyPatch(typeof(HealthComponent), "Heal")]
	internal static class RestrictFabricatedDroneHealing
	{
		private static void Prefix(HealthComponent __instance, ref float amount)
		{
			if (!JunkPatchHealingService.CanHeal(__instance))
			{
				amount = 0f;
			}
		}
	}
	[HarmonyPatch(typeof(CharacterMaster), "DestroyBody")]
	internal static class PreserveFabricatedDroneHealthBeforeBodyDestroy
	{
		private static void Prefix(CharacterMaster __instance)
		{
			UESFabricatedDrone obj = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<UESFabricatedDrone>() : null);
			if (obj != null)
			{
				CharacterBody body = __instance.GetBody();
				obj.CaptureHealth((body != null) ? body.healthComponent : null);
			}
		}
	}
	[HarmonyPatch(typeof(CharacterBody), "OnDestroy")]
	internal static class PreserveFabricatedDroneHealthOnSceneUnload
	{
		private static void Prefix(CharacterBody __instance)
		{
			if (NetworkServer.active && (Object)(object)__instance != (Object)null && (Object)(object)__instance.master != (Object)null)
			{
				((Component)__instance.master).GetComponent<UESFabricatedDrone>()?.CaptureHealth(__instance.healthComponent);
			}
		}
	}
	[HarmonyPatch(typeof(CharacterMaster), "OnBodyDeath")]
	internal static class ClearFabricatedDroneSnapshotOnDeath
	{
		private static void Prefix(CharacterMaster __instance)
		{
			if (NetworkServer.active)
			{
				((Component)__instance).GetComponent<UESFabricatedDrone>()?.ClearSavedHealth();
				SelectionAuthority.Remove(__instance);
				JunkPatchExecution.Remove(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(NetworkManager), "ServerChangeScene")]
	internal static class CaptureFabricatedDronesBeforeSceneChange
	{
		private static void Prefix()
		{
			DroneStagePersistence.CaptureAll();
			Plugin.ResetSession();
		}
	}
	[HarmonyPatch(typeof(Stage), "RespawnAllNPCs")]
	internal static class RemoveNanobotTierBeforeNpcRespawn
	{
		private static void Prefix(Stage __instance)
		{
			NanobotUpgradeService.RemoveStageLimitedUpgrades(__instance);
		}
	}
	[HarmonyPatch(typeof(CharacterMaster), "OnBodyStart")]
	internal static class RestoreFabricatedDroneHealthAfterBodyStart
	{
		private static void Postfix(CharacterMaster __instance, CharacterBody body)
		{
			if (NetworkServer.active && __instance != null)
			{
				((Component)__instance).GetComponent<UESFabricatedDrone>()?.RestoreHealth(body);
			}
		}
	}
	[HarmonyPatch(typeof(CharacterBody), "GetDisplayName")]
	internal static class MarkFabricatedDroneNames
	{
		private static void Postfix(CharacterBody __instance, ref string __result)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)Plugin.FabricatedDroneBuff != (Object)null && __instance.HasBuff(Plugin.FabricatedDroneBuff))
			{
				__result += " [F]";
			}
		}
	}
	[HarmonyPatch(typeof(DroneScrapperController), "BeginScrapping")]
	internal static class TrackFabricatedDroneScrapping
	{
		private static readonly FieldInfo LastScrapDropCountField = AccessTools.Field(typeof(DroneScrapperController), "<lastScrapDropCount>k__BackingField");

		private static void Prefix(DroneScrapperController __instance, NetworkInstanceId id)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			FabricatedDroneScrappingService.Begin(__instance, id);
		}

		private static void Postfix(DroneScrapperController __instance)
		{
			if (LastScrapDropCountField != null && FabricatedDroneScrappingService.TryGetDropCount(__instance, out var count))
			{
				LastScrapDropCountField.SetValue(__instance, count);
			}
		}
	}
	[HarmonyPatch(typeof(DroneScrappingToIdle), "DropPickup")]
	internal static class ReplaceFabricatedDroneScrapDrops
	{
		private static bool Prefix(DroneScrappingToIdle __instance)
		{
			return !FabricatedDroneScrappingService.TryHandleDrop(__instance);
		}
	}
	[HarmonyPatch(typeof(DeathState), "OnEnter")]
	internal static class MarkFabricatedDroneDeathState
	{
		private static readonly FieldInfo IsGhostField = AccessTools.Field(typeof(DeathState), "isGhost");

		private static readonly FieldInfo UpgradeCountField = AccessTools.Field(typeof(DeathState), "droneUpgradeCount");

		private static void Prepare()
		{
			if (IsGhostField == null || UpgradeCountField == null)
			{
				throw new MissingFieldException("Drone.DeathState repair fields have changed.");
			}
		}

		private static void Postfix(DeathState __instance)
		{
			if (NetworkServer.active)
			{
				if (IsFabricatedDrone(__instance))
				{
					IsGhostField.SetValue(__instance, true);
				}
				CharacterBody val = (((Object)(object)((EntityState)__instance).outer != (Object)null) ? ((EntityState)__instance).outer.commonComponents.characterBody : null);
				if ((Object)(object)val != (Object)null && (Object)(object)Plugin.NanobotActiveBuff != (Object)null && val.HasBuff(Plugin.NanobotActiveBuff))
				{