Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of UESDrifter v1.1.1
plugins/UESDrifter.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
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 BepInEx; using EntityStates; using EntityStates.Drone; using EntityStates.DroneScrapper; using HarmonyLib; using JetBrains.Annotations; 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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyVersion("0.0.0.0")] namespace DrifterUES; public sealed class DeferredFabricatorSkillDef : DrifterSkillDef { public override bool IsReady([NotNull] GenericSkill skillSlot) { return FabricationService.HasAvailableFabricationRecipe() && ((DrifterSkillDef)this).IsReady(skillSlot); } public override bool CanExecute([NotNull] GenericSkill skillSlot) { return FabricationService.HasAvailableFabricationRecipe() && ((DrifterSkillDef)this).CanExecute(skillSlot); } public override void OnExecute([NotNull] GenericSkill skillSlot) { //IL_000f: 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); } } } public sealed class DynamicJunkPatchSkillDef : DrifterSkillDef { public override bool IsReady([NotNull] GenericSkill skillSlot) { return ((DrifterSkillDef)this).IsReady(skillSlot) && JunkPatchPassiveService.CanAfford(skillSlot.characterBody); } public override bool CanExecute([NotNull] GenericSkill skillSlot) { return ((DrifterSkillDef)this).CanExecute(skillSlot) && JunkPatchPassiveService.CanAfford(skillSlot.characterBody); } public override void OnExecute([NotNull] GenericSkill skillSlot) { //IL_000f: 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; } JunkController component = ((Component)skillSlot).GetComponent<JunkController>(); int junkCost = JunkPatchPassiveService.GetJunkCost(skillSlot.characterBody); if ((Object)(object)component != (Object)null && component.CanAfford(junkCost)) { component.ConsumeJunk(junkCost); } 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; 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)); } } private static IEnumerator OpenWhenUiReady(Mode mode, CharacterBody owner) { LocalUser user = null; HUD hud = null; for (int frame = 0; frame < 30; frame++) { if ((Object)(object)owner == (Object)null || !owner.hasEffectiveAuthority) { 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; } menuOpening = false; if (user != null && !((Object)(object)user.eventSystem == (Object)null) && !((Object)(object)hud == (Object)null) && !Object.op_Implicit((Object)(object)activeMenuRoot)) { GameObject root = (activeMenuRoot = CreateMenuRoot(user, hud, (mode == Mode.Fabricator) ? "UES FABRICATOR" : "NANOBOT UPGRADES")); PauseManager.ClosePauseScreen(true); if (mode == Mode.Fabricator) { ConfigureFabricator(root, owner); } else { ConfigureNanobots(root, owner); } AddResourceSummary(root, owner); } } private static GameObject CreateMenuRoot(LocalUser user, HUD hud, string title) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_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) //IL_0168: 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) //IL_01f5: 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_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Expected O, but got Unknown //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Expected O, but got Unknown //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: 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; Image val2 = val.AddComponent<Image>(); ((Graphic)val2).color = new Color(0f, 0.02f, 0.05f, 0.88f); Transform val3 = 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)); Image val4 = ((Component)val3).gameObject.AddComponent<Image>(); ((Graphic)val4).color = new Color(0.06f, 0.11f, 0.16f, 0.98f); CreateText(val3, "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(val3, "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(val3, hud, val); Transform val5 = CreateChild(val3, "SelectionScroll", new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0.5f, 0.5f), new Vector2(0f, -70f), new Vector2(-44f, -166f)); ScrollRect val6 = ((Component)val5).gameObject.AddComponent<ScrollRect>(); Transform val7 = CreateChild(val5, "Viewport", Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f), Vector2.zero, Vector2.zero); ((Graphic)((Component)val7).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.18f); ((Component)val7).gameObject.AddComponent<Mask>().showMaskGraphic = true; Transform val8 = CreateChild(val7, "Content", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), Vector2.zero, new Vector2(0f, 0f)); VerticalLayoutGroup val9 = ((Component)val8).gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)val9).padding = new RectOffset(14, 14, 14, 14); ((HorizontalOrVerticalLayoutGroup)val9).spacing = 8f; ((HorizontalOrVerticalLayoutGroup)val9).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val9).childForceExpandHeight = false; ((Component)val8).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; val6.viewport = (RectTransform)val7; val6.content = (RectTransform)val8; val6.horizontal = false; val6.vertical = true; val6.scrollSensitivity = 30f; return val; } private static void ConfigureFabricator(GameObject root, CharacterBody owner) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00bb: 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) 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 && FabricationService.CanPay(owner.inventory, component, recipe.cost); string label = recipe.displayName + " • Tier " + recipe.fabricationTier + "\n" + CostText(recipe.cost) + (flag ? " (8 drone limit reached)" : string.Empty); CreateSelectionButton(parent, val.iconSprite, label, enabled, delegate { UesNetwork.SendFabrication(recipe.id); Close(root); }); } } } private static void ConfigureNanobots(GameObject root, CharacterBody owner) { //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_022b: 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_00f4: 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, ((Object)(object)droneDef != (Object)null) ? droneDef.iconSprite : null, label, enabled, delegate { //IL_0007: 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 group = (((Object)(object)owner != (Object)null) ? MinionGroup.FindGroup(((NetworkBehaviour)owner).netId) : null); if (group == null) { yield break; } MinionOwnership[] members = group.members; foreach (MinionOwnership member in members) { CharacterMaster master = (Object.op_Implicit((Object)(object)member) ? ((Component)member).GetComponent<CharacterMaster>() : null); if ((Object)(object)master != (Object)null && (NanobotUpgradeService.IsEligible(owner, master) || NanobotUpgradeService.IsNanobotActive(master))) { yield return master; } } } private static void CreateSelectionButton(Transform parent, Sprite icon, string label, bool enabled, Action onClick) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: 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) 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; Image component = val.GetComponent<Image>(); ((Graphic)component).color = (enabled ? new Color(0.12f, 0.24f, 0.31f, 1f) : new Color(0.09f, 0.09f, 0.09f, 1f)); Button component2 = val.GetComponent<Button>(); ((Selectable)component2).interactable = enabled; ((UnityEvent)component2.onClick).AddListener((UnityAction)delegate { onClick(); }); Transform val2 = 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)); Image val3 = ((Component)val2).gameObject.AddComponent<Image>(); val3.sprite = icon; val3.preserveAspect = true; ((Graphic)val3).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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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) 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0058: 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_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) Transform val = CreateChild(parent, name, anchorMin, anchorMax, pivot, anchoredPosition, dimensions); TextMeshProUGUI val2 = ((Component)val).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)val2).font = (TMP_FontAsset)font; ((TMP_Text)val2).text = value; ((TMP_Text)val2).fontSize = size; ((TMP_Text)val2).alignment = alignment; ((TMP_Text)val2).enableWordWrapping = true; ((Graphic)val2).color = Color.white; return val2; } private static void Close(GameObject root) { if ((Object)(object)activeMenuRoot == (Object)(object)root) { activeMenuRoot = null; } Object.Destroy((Object)(object)root); } private static void AddResourceSummary(GameObject menuRoot, CharacterBody owner) { //IL_006c: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_0135: 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_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0162: 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) { string text = cost.junk + " Junk"; if (cost.whiteScrap > 0) { text = text + ", " + cost.whiteScrap + " White Scrap"; } if (cost.greenScrap > 0) { text = text + ", " + cost.greenScrap + " Green Scrap"; } if (cost.redScrap > 0) { text = text + ", " + cost.redScrap + " Red Scrap"; } return text; } } internal static class UesNetwork { internal enum SelectionKind : byte { Fabricator = 1, Nanobot } internal sealed class SelectionMessage : MessageBase { public SelectionKind kind; public byte recipeId; public NetworkInstanceId targetMasterId; public override void Serialize(NetworkWriter writer) { //IL_001d: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) kind = (SelectionKind)reader.ReadByte(); recipeId = reader.ReadByte(); targetMasterId = reader.ReadNetworkId(); } } internal const short SelectionMessageType = 151; internal static void SendFabrication(byte recipeId) { Send(new SelectionMessage { kind = SelectionKind.Fabricator, recipeId = recipeId }); } internal static void SendNanobot(NetworkInstanceId targetMasterId) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) 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) { val.connection.Send((short)151, (MessageBase)(object)message); } } internal static void HandleSelection(NetworkMessage netMessage) { //IL_006d: 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.")); } } private 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>(); return ((Object)(object)component3 != (Object)null) ? component3.master : null; } } 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 Open(CharacterBody body, Kind kind) { //IL_006d: 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) 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_002f: 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_0087: 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) { if ((Object)(object)body == (Object)null || (Object)(object)((Component)body).GetComponent<JunkController>() == (Object)null || (Object)(object)body.skillLocator == (Object)null) { return false; } return (kind == Kind.Fabricator) ? ((Object)(object)body.skillLocator.secondary.skillDef == (Object)(object)Plugin.FabricatorSkill) : ((Object)(object)body.skillLocator.special.skillDef == (Object)(object)Plugin.NanobotSkill); } } 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_0094: 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_009d: 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) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0184: 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_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: 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; } ScrapPayment payment = Pay(playerMaster.inventory, component, cost); CharacterMaster val2 = 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 }.Perform(); if ((Object)(object)val2 == (Object)null) { Refund(playerMaster.inventory, payment); playerMaster.inventory.GiveItemPermanent(Items.Junk, cost.junk); return false; } if (recipe.fabricationTier > 1 && (Object)(object)val2.inventory != (Object)null) { val2.inventory.GiveItemPermanent(Items.DroneUpgradeHidden, recipe.fabricationTier - 1); } UESFabricatedDrone uESFabricatedDrone = ((Component)val2).gameObject.AddComponent<UESFabricatedDrone>(); uESFabricatedDrone.permanentTier = recipe.fabricationTier; uESFabricatedDrone.ownerMasterNetId = ((NetworkBehaviour)playerMaster).netId; uESFabricatedDrone.craftingCost = recipe.cost; uESFabricatedDrone.hasCraftingRecipe = true; uESFabricatedDrone.MarkBody(val2.GetBody()); StartFabricatorCooldown(body); return true; } internal static int CountActiveFabricatedDrones(CharacterMaster owner) { //IL_000e: 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_0096: 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); UESFabricatedDrone uESFabricatedDrone = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<UESFabricatedDrone>() : null); if ((Object)(object)val3 != (Object)null && (Object)(object)val3.GetBody() != (Object)null && (Object)(object)uESFabricatedDrone != (Object)null && uESFabricatedDrone.ownerMasterNetId == ((NetworkBehaviour)owner).netId) { 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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)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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) 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); } private 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 bool hasSavedHealth; private float savedHealthFraction; private float savedShieldFraction; internal void CaptureHealth(HealthComponent health) { if (!((Object)(object)health == (Object)null) && health.alive) { hasSavedHealth = true; savedHealthFraction = ((health.fullHealth > 0f) ? Mathf.Clamp01(health.health / health.fullHealth) : 1f); savedShieldFraction = ((health.fullShield > 0f) ? Mathf.Clamp01(health.shield / health.fullShield) : 0f); } } internal void RestoreHealth(CharacterBody body) { if (!((Object)(object)body == (Object)null) && !((Object)(object)body.healthComponent == (Object)null)) { MarkBody(body); if (hasSavedHealth) { HealthComponent healthComponent = body.healthComponent; healthComponent.Networkhealth = healthComponent.fullHealth * savedHealthFraction; healthComponent.Networkshield = healthComponent.fullShield * savedShieldFraction; hasSavedHealth = false; } } } 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown if (!NetworkServer.active) { return; } damageStopwatch += Time.fixedDeltaTime; float fabricatedDroneDecayInterval = JunkPatchPassiveService.GetFabricatedDroneDecayInterval(this); if (!(damageStopwatch < fabricatedDroneDecayInterval)) { damageStopwatch -= fabricatedDroneDecayInterval; 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) { 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) { return ((Object)(object)body != (Object)null && (Object)(object)body.master != (Object)null) ? FabricationService.CountActiveFabricatedDrones(body.master) : 0; } 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); return (Object)(object)val != (Object)null && val.CanAfford(GetJunkCost(body)); } 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_000e: 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; return ((Object)(object)val != (Object)null) ? FabricationService.CountActiveFabricatedDrones(val) : 0; } } 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) { return (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 && (Object)(object)body.skillLocator.special.skillDef == (Object)(object)Plugin.NanobotSkill; } internal static bool IsFabricatorActive(CharacterBody body) { return (Object)(object)body != (Object)null && (Object)(object)body.skillLocator != (Object)null && (Object)(object)body.skillLocator.secondary != (Object)null && (Object)(object)body.skillLocator.secondary.skillDef == (Object)(object)Plugin.FabricatorSkill; } 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_0003: 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 || (Object)(object)((Component)val2).GetComponent<UESFabricatedDrone>() == (Object)null || (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) { CharacterBody val = (((Object)(object)skill != (Object)null) ? skill.characterBody : null); return (Object)(object)val != (Object)null && (Object)(object)val.master != (Object)null && (Object)(object)((Component)val.master).GetComponent<UESFabricatedDrone>() != (Object)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_0096: 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; internal static void Prepare() { if (!((Object)(object)prefab != (Object)null) && !loading && !((Object)(object)Plugin.Instance == (Object)null)) { loading = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(Load()); } } internal static GameObject Get() { Prepare(); return prefab; } private static IEnumerator Load() { AsyncOperationHandle<GameObject> operation = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/PassiveHealing/WoodSpriteIndicator.prefab"); yield return operation; loading = false; GameObject vanillaPrefab = operation.Result; if (!((Object)(object)vanillaPrefab == (Object)null)) { cacheRoot = new GameObject("UESJunkPatchIndicatorCache"); cacheRoot.SetActive(false); Object.DontDestroyOnLoad((Object)(object)cacheRoot); prefab = Object.Instantiate<GameObject>(vanillaPrefab, cacheRoot.transform); ((Object)prefab).name = "UESJunkPatchWoodSpriteIndicator"; InputBindingDisplayController binding = prefab.GetComponentInChildren<InputBindingDisplayController>(true); if ((Object)(object)binding != (Object)null) { binding.actionName = "UtilitySkill"; } Transform holder = prefab.transform.Find("Holder"); SpriteRenderer renderer = (((Object)(object)holder != (Object)null) ? ((Component)holder).GetComponent<SpriteRenderer>() : null); if ((Object)(object)renderer != (Object)null && (Object)(object)renderer.sprite != (Object)null) { gradientSprite = CreateGradientSprite(renderer.sprite); material = new Material(((Renderer)renderer).sharedMaterial) { name = "UESJunkPatchWoodSpriteGradientMaterial" }; renderer.sprite = gradientSprite; ((Renderer)renderer).material = material; } } } private static Sprite CreateGradientSprite(Sprite source) { //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_0050: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0087: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: 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_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: 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_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: 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; 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(); 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 = 12f; internal const float DroneRange = 46f; internal static HealthComponent FindTarget(CharacterBody body, Ray aimRay) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0039: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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) //IL_0055: 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_0071: 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_0078: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_0092: Expected O, but got Unknown //IL_009e: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013f: 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) 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)) { CharacterBody body2 = result.healthComponent.body; float num2 = (((Object)(object)body2 != (Object)null && (body2.bodyFlags & 0x400000) != 0) ? 46f : 12f); 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) { return (Object)(object)body != (Object)null && (Object)(object)body.master != (Object)null && (Object)(object)((Component)body.master).GetComponent<UESFabricatedDrone>() != (Object)null; } } internal static class JunkPatchHealingService { [ThreadStatic] private static bool isHealing; internal static float Heal(HealthComponent target, float amount) { //IL_000c: 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) isHealing = true; try { return target.Heal(amount, default(ProcChainMask), true); } finally { isHealing = false; } } internal static bool CanHeal(HealthComponent target) { return isHealing || !JunkPatchTargeting.IsFabricatedDrone(((Object)(object)target != (Object)null) ? target.body : null); } } 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 Begin(DroneScrapperController controller, NetworkInstanceId bodyId) { //IL_001e: 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_0083: 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_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_00a0: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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) 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0102: 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_011e: 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) 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_0025: 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; } FabricationService.Pay(playerMaster.inventory, component, cost); val2.inventory.GiveItemPermanent(Items.DroneUpgradeHidden, 1); ((Component)val2).gameObject.AddComponent<NanobotTemporaryUpgrade>(); CharacterBody body2 = val2.GetBody(); if (body2 != null) { body2.AddBuff(Plugin.NanobotActiveBuff); } return true; } internal static int CountActiveNanobotUpgrades(CharacterMaster owner) { //IL_000e: 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); if ((Object)(object)val3 != (Object)null && (Object)(object)val3.GetBody() != (Object)null && (Object)(object)((Component)val3).GetComponent<NanobotTemporaryUpgrade>() != (Object)null) { num++; } } return num; } internal static bool IsEligible(CharacterMaster owner, CharacterMaster droneMaster) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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 || (body.bodyFlags & 0x400000) == 0) { return false; } DroneDef droneDef = DroneCatalog.GetDroneDef(DroneCatalog.GetDroneIndexFromBodyIndex(body.bodyIndex)); ResourceCost cost; return (Object)(object)droneDef != (Object)null && droneDef.canCombine && UesRecipes.TryGetNanobotCost(droneDef, out cost); } internal static bool IsNanobotActive(CharacterMaster droneMaster) { if ((Object)(object)droneMaster == (Object)null) { return false; } if ((Object)(object)((Component)droneMaster).GetComponent<NanobotTemporaryUpgrade>() != (Object)null) { return true; } CharacterBody body = droneMaster.GetBody(); return (Object)(object)body != (Object)null && (Object)(object)Plugin.NanobotActiveBuff != (Object)null && body.HasBuff(Plugin.NanobotActiveBuff); } internal static bool TryGetCost(CharacterMaster droneMaster, out ResourceCost cost) { //IL_0021: 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) 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); } } 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")] 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 uESFabricatedDrone = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<UESFabricatedDrone>() : null); if (uESFabricatedDrone != null) { CharacterBody body = __instance.GetBody(); uESFabricatedDrone.CaptureHealth((body != null) ? body.healthComponent : null); } } } [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_0002: 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 void Postfix(DeathState __instance) { if (NetworkServer.active && IsFabricatedDrone(__instance)) { IsGhostField?.SetValue(__instance, true); } } internal static bool IsFabricatedDrone(DeathState state) { CharacterBody val = ((state != null && (Object)(object)((EntityState)state).outer != (Object)null) ? ((EntityState)state).outer.commonComponents.characterBody : null); return (Object)(object)val != (Object)null && (((Object)(object)val.master != (Object)null && (Object)(object)((Component)val.master).GetComponent<UESFabricatedDrone>() != (Object)null) || ((Object)(object)Plugin.FabricatedDroneBuff != (Object)null && val.HasBuff(Plugin.FabricatedDroneBuff))); } } [HarmonyPatch(typeof(DeathState), "OnImpactServer")] internal static class SuppressFabricatedDroneRepairSpawn { private static bool Prefix(DeathState __instance) { return !MarkFabricatedDroneDeathState.IsFabricatedDrone(__instance); } } [HarmonyPatch(typeof(DroneCombinerController), "GetInteractability")] internal static class PreventCombiningTemporaryNanobotTier { private static void Postfix(Interactor activator, ref Interactability __result) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if ((int)__result == 0 || (Object)(object)activator == (Object)null) { return; } CharacterBody component = ((Component)activator).GetComponent<CharacterBody>(); CharacterMaster val = ((component != null) ? component.master : null); MinionGroup val2 = (((Object)(object)val != (Object)null) ? MinionGroup.FindGroup(((NetworkBehaviour)val).netId) : null); if (val2 == null) { return; } MinionOwnership[] members = val2.members; foreach (MinionOwnership val3 in members) { if ((Object)(object)val3 != (Object)null && (Object)(object)((Component)val3).GetComponent<NanobotTemporaryUpgrade>() != (Object)null) { __result = (Interactability)1; break; } } } } [BepInPlugin("com.dermitio.uesdrifter", "UES Drifter", "1.0.3")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.dermitio.uesdrifter"; public const string PluginName = "UES Drifter"; public const string PluginVersion = "1.0.3"; internal static Plugin Instance; internal static DrifterSkillDef FabricatorSkill; internal static DrifterSkillDef NanobotSkill; internal static DrifterSkillDef JunkPatchSkill; internal static BuffDef NanobotActiveBuff; internal static BuffDef FabricatedDroneBuff; private static Texture2D fabricatorTexture; private static Texture2D nanobotTexture; private static Sprite fabricatorIcon; private static Sprite nanobotIcon; private static Texture2D junkPatchTexture; private static Sprite junkPatchIcon; private static Texture2D hoarderTexture; internal static Sprite HoarderIcon; private static string trashToTreasureDescriptionToken; private bool networkHandlerRegistered; private void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) Instance = this; new Harmony("com.dermitio.uesdrifter").PatchAll(); CreateAndRegisterSkillDefs(); RegisterEntityStates(); Language.onCurrentLanguageChanged += RegisterLanguageTokens; RoR2Application.onLoadFinished = (Action)Delegate.Combine(RoR2Application.onLoadFinished, new Action(InstallSkillVariants)); NetworkManagerSystem.onStartServerGlobal += RegisterServerNetworkHandler; NetworkManagerSystem.onStopServerGlobal += ResetServerNetworkHandler; Stage.onStageStartGlobal += NanobotUpgradeService.RemoveStageLimitedUpgrades; } private void OnDestroy() { NetworkManagerSystem.onStartServerGlobal -= RegisterServerNetworkHandler; NetworkManagerSystem.onStopServerGlobal -= ResetServerNetworkHandler; Stage.onStageStartGlobal -= NanobotUpgradeService.RemoveStageLimitedUpgrades; Language.onCurrentLanguageChanged -= RegisterLanguageTokens; RoR2Application.onLoadFinished = (Action)Delegate.Remove(RoR2Application.onLoadFinished, new Action(InstallSkillVariants)); } private void RegisterServerNetworkHandler() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (!networkHandlerRegistered) { NetworkServer.RegisterHandler((short)151, new NetworkMessageDelegate(UesNetwork.HandleSelection)); networkHandlerRegistered = true; } } private void ResetServerNetworkHandler() { networkHandlerRegistered = false; } private static void InstallSkillVariants() { CharacterBody drifterBody = BodyPrefabs.DrifterBody; SkillLocator locator = (Object.op_Implicit((Object)(object)drifterBody) ? ((Component)drifterBody).GetComponent<SkillLocator>() : null); if ((Object)(object)locator == (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogError((object)"Could not find Drifter's SkillLocator; UES variants were not installed."); return; } FabricatorSkill.minimumJunkCost = 4f; NanobotSkill.minimumJunkCost = 4f; JunkPatchSkill.minimumJunkCost = 4f; AddVariant(locator.secondary.skillFamily, (SkillDef)(object)FabricatorSkill); AddVariant(locator.utility.skillFamily, (SkillDef)(object)JunkPatchSkill); AddVariant(locator.special.skillFamily, (SkillDef)(object)NanobotSkill); GenericSkill val = ((IEnumerable<GenericSkill>)((Component)drifterBody).GetComponents<GenericSkill>()).FirstOrDefault((Func<GenericSkill, bool>)((GenericSkill skill) => (int)locator.FindSkillSlot(skill) == -1)); if ((Object)(object)val == (Object)null || (Object)(object)val.skillFamily == (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogError((object)"Could not find Drifter's Trash To Treasure SkillFamily; Hoarder Efficiency details were not installed."); } else { SkillDef defaultSkillDef = val.skillFamily.defaultSkillDef; if ((Object)(object)defaultSkillDef != (Object)null && defaultSkillDef.skillDescriptionToken != "DRIFTER_TRASH_TO_TREASURE_WITH_HOARDER_DESCRIPTION") { trashToTreasureDescriptionToken = defaultSkillDef.skillDescriptionToken; defaultSkillDef.skillDescriptionToken = "DRIFTER_TRASH_TO_TREASURE_WITH_HOARDER_DESCRIPTION"; } } RegisterLanguageTokens(); JunkPatchIndicatorPrefab.Prepare(); if ((Object)(object)((Component)drifterBody).GetComponent<HoarderPassiveDisplay>() == (Object)null) { ((Component)drifterBody).gameObject.AddComponent<HoarderPassiveDisplay>(); } if ((Object)(object)((Component)drifterBody).GetComponent<JunkPatchTargetingIndicator>() == (Object)null) { ((Component)drifterBody).gameObject.AddComponent<JunkPatchTargetingIndicator>(); } } private static void CreateAndRegisterSkillDefs() { if ((Object)(object)FabricatorSkill != (Object)null || (Object)(object)NanobotSkill != (Object)null || (Object)(object)JunkPatchSkill != (Object)null) { return; } fabricatorIcon = LoadEmbeddedSprite("DrifterUES.Assets.Fabricator.png", out fabricatorTexture); nanobotIcon = LoadEmbeddedSprite("DrifterUES.Assets.Nanobot.png", out nanobotTexture); HoarderIcon = LoadEmbeddedSprite("DrifterUES.Assets.HoarderEfficiency.png", out hoarderTexture); NanobotActiveBuff = ScriptableObject.CreateInstance<BuffDef>(); ((Object)NanobotActiveBuff).name = "UESNanobotUpgradeActive"; NanobotActiveBuff.iconSprite = nanobotIcon; NanobotActiveBuff.isHidden = true; NanobotActiveBuff.canStack = false; FabricatedDroneBuff = ScriptableObject.CreateInstance<BuffDef>(); ((Object)FabricatedDroneBuff).name = "UESFabricatedDrone"; FabricatedDroneBuff.isHidden = true; FabricatedDroneBuff.canStack = false; LegacyModContentPackProvider.instance.registrationContentPack.buffDefs.Add((BuffDef[])(object)new BuffDef[2] { NanobotActiveBuff, FabricatedDroneBuff }); FabricatorSkill = CreateSkill("UESFabricator", "DRIFTER_UES_FABRICATOR_NAME", "DRIFTER_UES_FABRICATOR_DESCRIPTION", fabricatorIcon, typeof(OpenFabricatorMenu), 1f); ((SkillDef)FabricatorSkill).stockToConsume = 1; NanobotSkill = CreateSkill("NanobotUpgrades", "DRIFTER_NANOBOT_UPGRADES_NAME", "DRIFTER_NANOBOT_UPGRADES_DESCRIPTION", nanobotIcon, typeof(OpenNanobotMenu), 1f); junkPatchIcon = LoadEmbeddedSprite("DrifterUES.Assets.JunkPatch.png", out junkPatchTexture); JunkPatchSkill = CreateSkill("JunkPatch", "DRIFTER_JUNK_PATCH_NAME", "DRIFTER_JUNK_PATCH_DESCRIPTION", junkPatchIcon, typeof(JunkPatch), 0f); ((SkillDef)JunkPatchSkill).baseRechargeInterval = 7f; ((SkillDef)JunkPatchSkill).stockToConsume = 1; JunkPatchSkill.requireJunkForActivation = true; ((SkillDef)JunkPatchSkill).hideCooldown = false; ((SkillDef)JunkPatchSkill).hideStockCount = false; SkillCatalog.getAdditionalSkillDefs += delegate(List<SkillDef> skillDefs) { if (!skillDefs.Contains((SkillDef)(object)FabricatorSkill)) { skillDefs.Add((SkillDef)(object)FabricatorSkill); } if (!skillDefs.Contains((SkillDef)(object)NanobotSkill)) { skillDefs.Add((SkillDef)(object)NanobotSkill); } if (!skillDefs.Contains((SkillDef)(object)JunkPatchSkill)) { skillDefs.Add((SkillDef)(object)JunkPatchSkill); } }; } private static void RegisterEntityStates() { NamedAssetCollection<Type> entityStateTypes = LegacyModContentPackProvider.instance.registrationContentPack.entityStateTypes; if (!entityStateTypes.Contains(typeof(OpenFabricatorMenu))) { entityStateTypes.Add(new Type[1] { typeof(OpenFabricatorMenu) }); } if (!entityStateTypes.Contains(typeof(OpenNanobotMenu))) { entityStateTypes.Add(new Type[1] { typeof(OpenNanobotMenu) }); } if (!entityStateTypes.Contains(typeof(JunkPatch))) { entityStateTypes.Add(new Type[1] { typeof(JunkPatch) }); } } private static DrifterSkillDef CreateSkill(string name, string skillNameToken, string descriptionToken, Sprite icon, Type stateType, float minimumJunk) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) DrifterSkillDef val = (DrifterSkillDef)((name == "UESFabricator") ? ((object)ScriptableObject.CreateInstance<DeferredFabricatorSkillDef>()) : ((object)((name == "JunkPatch") ? ScriptableObject.CreateInstance<DynamicJunkPatchSkillDef>() : ((DynamicJunkPatchSkillDef)(object)ScriptableObject.CreateInstance<DrifterSkillDef>())))); ((Object)val).name = name; ((SkillDef)val).skillName = name; ((SkillDef)val).skillNameToken = skillNameToken; ((SkillDef)val).skillDescriptionToken = descriptionToken; ((SkillDef)val).icon = icon; ((SkillDef)val).activationState = new SerializableEntityStateType(stateType); ((SkillDef)val).activationStateMachineName = "Weapon"; ((SkillDef)val).interruptPriority = (InterruptPriority)1; ((SkillDef)val).baseMaxStock = 1; ((SkillDef)val).baseRechargeInterval = ((name == "UESFabricator") ? 20f : 0f); ((SkillDef)val).stockToConsume = 0; val.minimumJunkCost = minimumJunk; val.requireJunkForActivation = false; val.bypassCooldown = false; ((SkillDef)val).cancelSprintingOnActivation = false; ((SkillDef)val).mustKeyPress = true; ((SkillDef)val).hideCooldown = name != "UESFabricator"; ((SkillDef)val).hideStockCount = name != "UESFabricator"; return val; } private static void AddVariant(SkillFamily family, SkillDef skill) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)family) && !family.variants.Any((Variant v) => (Object)(object)v.skillDef == (Object)(object)skill || ((Object)(object)v.skillDef != (Object)null && v.skillDef.skillName == skill.skillName))) { List<Variant> list = family.variants.ToList(); Variant item = new Variant { skillDef = skill, unlockableDef = null }; ((Variant)(ref item)).viewableNode = CreateVariantViewableNode(family, skill); list.Add(item); family.variants = list.ToArray(); } } private static Node CreateVariantViewableNode(SkillFamily family, SkillDef skill) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown CharacterBody drifterBody = BodyPrefabs.DrifterBody; string text = (Object.op_Implicit((Object)(object)drifterBody) ? ((Object)drifterBody).name : null); if (string.IsNullOrEmpty(text)) { return null; } Node val = ViewablesCatalog.FindNode("/Loadout/Bodies/" + text + "/"); if (val == null) { return null; } string skillFamilyName = SkillCatalog.GetSkillFamilyName(family.catalogIndex); Node node = new Node(skillFamilyName + "." + ((Object)skill).name, false, val); node.shouldShowUnviewed = (UserProfile profile) => !profile.HasViewedViewable(node.fullName); return node; } private static Sprite LoadEmbeddedSprite(string resourceName, out Texture2D texture) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0057: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); if (stream == null) { throw new InvalidOperationException("Missing embedded icon resource: " + resourceName); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); texture = new Texture2D(2, 2, (TextureFormat)4, false) { name = resourceName, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; if (!ImageConversion.LoadImage(texture, memoryStream.ToArray(), false)) { throw new InvalidOperationException("Could not decode icon resource: " + resourceName); } return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), 100f); } private static void RegisterLanguageTokens() { SetLanguageTokens(Language.english); if (Language.currentLanguage != null && Language.currentLanguage != Language.english) { SetLanguageTokens(Language.currentLanguage); } } private static void SetLanguageTokens(Language language) { if (language != null) { language.SetStringByToken("DRIFTER_UES_FABRICATOR_NAME", "UES Fabricator"); language.SetStringByToken("DRIFTER_UES_FABRICATOR_DESCRIPTION", "Open the UES fabrication menu. Select a drone to fabricate using collected Junk and Scrap. Carried Junk linearly raises damage to 2x and lowers attack speed to 0.5x at full Junk."); language.SetStringByToken("DRIFTER_NANOBOT_UPGRADES_NAME", "Nanobot Upgrades"); language.SetStringByToken("DRIFTER_NANOBOT_UPGRADES_DESCRIPTION", "Open the Nanobot menu. Upgrade one compatible owned drone for the current stage. Each drone uses its highest-rarity Scrap recipe, with one of each required Scrap type."); language.SetStringByToken("DRIFTER_JUNK_PATCH_NAME", "Junk Patch"); language.SetStringByToken("DRIFTER_JUNK_PATCH_DESCRIPTION", "Spend 12 Junk to heal yourself or an aimed ally within 12m for 35% of missing health. Drones can be targeted within 46m and heal for 40% of full combined health. Fabricated drones only accept healing from Junk Patch and convert overheal into a temporary barrier at 30% efficiency. Each fabricated drone reduces this skill's Junk cost by 2, up to six drones. The first three fabricated drones each increase decay time by 1 second; the next three each reduce decay by 0.5% per tick. The target receives your Trash To Treasure buffs for 10 seconds; another Junk Patch refreshes them."); language.SetStringByToken("DRIFTER_HOARDER_EFFICIENCY_NAME", "Hoarder Efficiency"); language.SetStringByToken("DRIFTER_HOARDER_EFFICIENCY_DESCRIPTION", "This passive is only active when both UES Fabricator and Nanobot Upgrades are selected.\nRaises Junk capacity to 20.\nFor every two fabricated drones below the 8-drone limit, generate 25% more Junk.\nAt 20 Junk, each would-be Junk can become Scrap; owned matching Scrap lowers its chance.\nFabricated drones gain 10% cooldown reduction per 4 Junk, up to 40%."); string text = (string.IsNullOrEmpty(trashToTreasureDescriptionToken) ? string.Empty : language.GetLocalizedStringByToken(trashToTreasureDescriptionToken)); language.SetStringByToken("DRIFTER_TRASH_TO_TREASURE_WITH_HOARDER_DESCRIPTION", string.IsNullOrEmpty(text) ? "Hoarder Efficiency: This passive is only active when both UES Fabricator and Nanobot Upgrades are selected. Raises Junk capacity to 20. For every two fabricated drones below the 8-drone limit, generate 25% more Junk. At 20 Junk, each would-be Junk can become Scrap; owned matching Scrap lowers its chance. Fabricated drones gain 10% cooldown reduction per 4 Junk, up to 40%." : (text + "\n\nHoarder Efficiency: This passive is only active when both UES Fabricator and Nanobot Upgrades are selected. Raises Junk capacity to 20. For every two fabricated drones below the 8-drone limit, generate 25% more Junk. At 20 Junk, each would-be Junk can become Scrap; owned matching Scrap lowers its chance. Fabricated drones gain 10% cooldown reduction per 4 Junk, up to 40%.")); } } } public readonly struct ResourceCost { public readonly int junk; public readonly int whiteScrap; public readonly int greenScrap; public readonly int redScrap; public ResourceCost(int junk, int whiteScrap, int greenScrap, int redScrap) { this.junk = junk; this.whiteScrap = whiteScrap; this.greenScrap = greenScrap; this.redScrap = redScrap; } } public sealed class DroneRecipe { public readonly byte id; public readonly string displayName; public readonly int fabricationTier; public readonly Func<DroneDef> drone; public readonly ResourceCost cost; public DroneRecipe(byte id, string displayName, int fabricationTier, Func<DroneDef> drone, ResourceCost cost) { this.id = id; this.displayName = displayName; this.fabricationTier = fabricationTier; this.drone = drone; this.cost = cost; } } public sealed class DroneUpgradeRecipe { public readonly Func<DroneDef> drone; public readonly ResourceCost cost; public DroneUpgradeRecipe(Func<DroneDef> drone, ResourceCost cost) { this.drone = drone; this.cost = cost; } }