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 BetterArchery v2.0.0
BetterArchery/plugins/BetterArchery.dll
Decompiled a week 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.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using Auga; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using Common; using HarmonyLib; using JetBrains.Annotations; using LitJson; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; 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: AssemblyTitle("BetterArchery")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BetterArchery")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("04f6ef99-721d-41d7-86e2-59ced874c902")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Common { [Serializable] public class RecipeRequirementConfig { public string item = ""; public int amount = 1; } [Serializable] public class RecipeConfig { public string name = ""; public string item = ""; public int amount = 1; public string craftingStation = ""; public int minStationLevel = 1; public bool enabled = true; public string repairStation = ""; public List<RecipeRequirementConfig> resources = new List<RecipeRequirementConfig>(); } [Serializable] public class RecipesConfig { public List<RecipeConfig> recipes = new List<RecipeConfig>(); } internal class CustomSlotItem : MonoBehaviour { public string m_slotName; } public static class CustomSlotCreator { public static readonly Dictionary<Humanoid, Dictionary<string, ItemData>> customSlotItemData = new Dictionary<Humanoid, Dictionary<string, ItemData>>(); public static string GetCustomSlotName(ItemData item) { if (!IsCustomSlotItem(item)) { return null; } return item.m_dropPrefab.GetComponent<CustomSlotItem>().m_slotName; } public static bool IsCustomSlotItem(ItemData item) { return item != null && Object.op_Implicit((Object)(object)item.m_dropPrefab) && Object.op_Implicit((Object)(object)item.m_dropPrefab.GetComponent<CustomSlotItem>()); } private static bool TryGetSlots(Humanoid humanoid, out Dictionary<string, ItemData> slots) { slots = null; return (Object)(object)humanoid != (Object)null && customSlotItemData.TryGetValue(humanoid, out slots) && slots != null; } public static ItemData GetPrefabItemData(Humanoid humanoid, string slotName) { if (!TryGetSlots(humanoid, out var slots) || !slots.TryGetValue(slotName, out var value) || value == null || (Object)(object)value.m_dropPrefab == (Object)null) { return null; } return value.m_dropPrefab.GetComponent<ItemDrop>()?.m_itemData; } public static ItemData GetSlotItem(Humanoid humanoid, string slotName) { Dictionary<string, ItemData> slots; ItemData value; return (TryGetSlots(humanoid, out slots) && slots.TryGetValue(slotName, out value)) ? value : null; } public static void SetSlotItem(Humanoid humanoid, string slotName, ItemData item) { if (!((Object)(object)humanoid == (Object)null)) { if (!TryGetSlots(humanoid, out var slots)) { slots = new Dictionary<string, ItemData>(); customSlotItemData[humanoid] = slots; } slots[slotName] = item; } } public static bool DoesSlotExist(Humanoid humanoid, string slotName) { Dictionary<string, ItemData> slots; return TryGetSlots(humanoid, out slots) && slots.ContainsKey(slotName); } public static bool IsSlotOccupied(Humanoid humanoid, string slotName) { Dictionary<string, ItemData> slots; ItemData value; return TryGetSlots(humanoid, out slots) && slots.TryGetValue(slotName, out value) && value != null; } public static void ApplyCustomSlotItem(GameObject prefab, string slotName) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)prefab)) { if (!Object.op_Implicit((Object)(object)prefab.GetComponent<CustomSlotItem>())) { prefab.AddComponent<CustomSlotItem>(); } prefab.GetComponent<CustomSlotItem>().m_slotName = slotName; prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_itemType = (ItemType)0; Debug.Log((object)("[CustomSlotCreator] Created " + slotName + " slot for " + ((Object)prefab).name + ".")); } } } public static class PrefabCreator { public static Dictionary<string, CraftingStation> CraftingStations; public static T RequireComponent<T>(GameObject go) where T : Component { T val = go.GetComponent<T>(); if ((Object)(object)val == (Object)null) { val = go.AddComponent<T>(); } return val; } public static void Reset() { CraftingStations = null; } private static void InitCraftingStations() { if (CraftingStations != null) { return; } CraftingStations = new Dictionary<string, CraftingStation>(); foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if ((Object)(object)recipe.m_craftingStation != (Object)null && !CraftingStations.ContainsKey(((Object)recipe.m_craftingStation).name)) { CraftingStations.Add(((Object)recipe.m_craftingStation).name, recipe.m_craftingStation); } } } public static Recipe CreateRecipe(string name, string itemId, RecipeConfig recipeConfig) { //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_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Expected O, but got Unknown InitCraftingStations(); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemId); if ((Object)(object)itemPrefab == (Object)null) { Debug.LogWarning((object)("[PrefabCreator] Could not find item prefab (" + itemId + ")")); return null; } Recipe val = ScriptableObject.CreateInstance<Recipe>(); ((Object)val).name = name; val.m_amount = recipeConfig.amount; val.m_minStationLevel = recipeConfig.minStationLevel; val.m_item = itemPrefab.GetComponent<ItemDrop>(); val.m_enabled = recipeConfig.enabled; if (!string.IsNullOrEmpty(recipeConfig.craftingStation)) { if (!CraftingStations.ContainsKey(recipeConfig.craftingStation)) { Debug.LogWarning((object)("[PrefabCreator] Could not find crafting station (" + itemId + "): " + recipeConfig.craftingStation)); string text = string.Join(", ", CraftingStations.Keys); Debug.Log((object)("[PrefabCreator] Available Stations: " + text)); } else { val.m_craftingStation = CraftingStations[recipeConfig.craftingStation]; } } if (!string.IsNullOrEmpty(recipeConfig.repairStation)) { if (!CraftingStations.ContainsKey(recipeConfig.repairStation)) { Debug.LogWarning((object)("[PrefabCreator] Could not find repair station (" + itemId + "): " + recipeConfig.repairStation)); string text2 = string.Join(", ", CraftingStations.Keys); Debug.Log((object)("[PrefabCreator] Available Stations: " + text2)); } else { val.m_repairStation = CraftingStations[recipeConfig.repairStation]; } } List<Requirement> list = new List<Requirement>(); foreach (RecipeRequirementConfig resource in recipeConfig.resources) { GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(resource.item); if ((Object)(object)itemPrefab2 == (Object)null) { Debug.LogError((object)("[PrefabCreator] Could not find requirement item (" + itemId + "): " + resource.item)); continue; } list.Add(new Requirement { m_amount = resource.amount, m_resItem = itemPrefab2.GetComponent<ItemDrop>() }); } val.m_resources = list.ToArray(); return val; } public static Recipe AddNewRecipe(string name, string itemId, RecipeConfig recipeConfig) { Recipe val = CreateRecipe(name, itemId, recipeConfig); if ((Object)(object)val == (Object)null) { Debug.LogError((object)("[PrefabCreator] Failed to create recipe (" + name + ")")); return null; } return AddNewRecipe(val); } public static Recipe AddNewRecipe(Recipe recipe) { int num = ObjectDB.instance.m_recipes.RemoveAll((Recipe x) => ((Object)x).name == ((Object)recipe).name); if (num > 0) { Debug.Log((object)$"[PrefabCreator] Removed recipe ({((Object)recipe).name}): {num}"); } ObjectDB.instance.m_recipes.Add(recipe); Debug.Log((object)("[PrefabCreator] Added recipe: " + ((Object)recipe).name)); return recipe; } } public static class Utils { private static MethodInfo _loadImageMethod; public static void PrintObject(object o) { if (o == null) { Debug.Log((object)"null"); } else { Debug.Log((object)(o?.ToString() + ":\n" + GetObjectString(o, " "))); } } public static string GetObjectString(object obj, string indent) { string text = ""; Type type = obj.GetType(); IEnumerable<FieldInfo> enumerable = from f in type.GetFields() where f.IsPublic select f; foreach (FieldInfo item in enumerable) { object value = item.GetValue(obj); string text2 = ((value == null) ? "null" : value.ToString()); text = text + "\n" + indent + item.Name + ": " + text2; } return text; } private static bool LoadImageCompat(Texture2D tex, byte[] data) { try { if (_loadImageMethod == null) { Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule"); if (type == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == "UnityEngine.ImageConversionModule") { type = assembly.GetType("UnityEngine.ImageConversion"); if (type != null) { break; } } } } if (type == null) { return false; } _loadImageMethod = type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); } if (_loadImageMethod == null) { return false; } return (bool)_loadImageMethod.Invoke(null, new object[2] { tex, data }); } catch { return false; } } public static Sprite LoadSpriteFromFile(string spritePath) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004e: 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_005b: Unknown result type (might be due to invalid IL or missing references) spritePath = Path.Combine(Paths.PluginPath, spritePath); if (File.Exists(spritePath)) { byte[] data = File.ReadAllBytes(spritePath); Texture2D val = new Texture2D(20, 20); if (LoadImageCompat(val, data)) { return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), default(Vector2), 100f); } } return null; } public static Sprite LoadSpriteFromFile(string modFolder, string iconName) { string spritePath = Path.Combine(modFolder, iconName); return LoadSpriteFromFile(spritePath); } public static bool IsServer() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 return ZNet.instance.IsServer() || ZNet.instance.IsDedicated() || (int)SystemInfo.graphicsDeviceType == 4; } } } namespace BetterArchery { public class Arrow { public string Name { get; set; } public float SpawnChance { get; set; } public string SpawnArrow { get; set; } } public enum QuiverHudOrientation { Horizontal, Vertical } [BepInPlugin("ishid4.mods.betterarchery", "Better Archery", "2.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class BetterArchery : BaseUnityPlugin { public enum ZoomState { Fixed, ZoomingIn, ZoomingOut } public const int QuiverUseSlotCount = 3; public static bool ZoomSfx; public static Dictionary<string, Dictionary<string, AudioClip>> CustomSfxDict = new Dictionary<string, Dictionary<string, AudioClip>>(); private static readonly Dictionary<string, AudioClip[]> _customSfxClipCache = new Dictionary<string, AudioClip[]>(); private static readonly Dictionary<string, AudioSource> _customSfxAudioSources = new Dictionary<string, AudioSource>(); public static bool SpeedReduction; public static bool IsContainerOpen; public static float ZoomInTimer = 0.1f; public static float ZoomOutTimer; public static float ZoomOutDelayTimer = 0f; public static float __BaseFov; public static float __LastZoomFov; public static float __NewZoomFov = 0f; public static ZoomState __ZoomState; public static int QuiverRowIndex = 0; public static ConfigEntry<KeyboardShortcut> HoldingKeyCode; public static ConfigEntry<KeyboardShortcut>[] KeyCodes = new ConfigEntry<KeyboardShortcut>[3]; public static ConfigEntry<string> ArrowRetrieveList; public static readonly Dictionary<string, Arrow> ArrowRetrieves = new Dictionary<string, Arrow>(); public static ConfigEntry<float> ArrowDisappearTime; public static ConfigEntry<bool> ArrowDisappearOnHit; public static ConfigEntry<bool> ArrowRetrieveSolidCollider; public static ConfigEntry<Vector2> InventoryQuiverSlotLocation; public static ConfigEntry<Vector2> InventoryQuiverSlotLocationWithContainer; public static ConfigEntry<bool> QuiverHudEnabled; public static ConfigEntry<float> QuiverHudScale; public static ConfigEntry<Vector2> QuiverHudPositionOffset; public static ConfigEntry<QuiverHudOrientation> QuiverHudLayout; public static ConfigEntry<Vector3> QuiverModelRotation; public static ConfigEntry<Vector3> QuiverModelScale; public static ConfigEntry<Vector3> QuiverModelPosition; public static ConfigEntry<float> ArrowVelocity; public static ConfigEntry<float> ArrowGravity; public static ConfigEntry<float> ArrowAccuracy; public static ConfigEntry<Vector3> ArrowAimDir; public static ConfigEntry<bool> ConfigQuiverEnabled; public static ConfigEntry<bool> ConfigArrowImprovementsEnabled; public static ConfigEntry<bool> ConfigRetrievableArrowsEnabled; public static ConfigEntry<bool> ConfigBowZoomEnabled; public static ConfigEntry<KeyboardShortcut> BowDrawCancelKey; public static ConfigEntry<bool> BowDrawCancelEnabled; public static ConfigEntry<string> BowDrawCancelGamepadButton; public static ConfigEntry<float> BowZoomFactor; public static ConfigEntry<bool> AutomaticBowZoom; public static ConfigEntry<KeyboardShortcut> BowZoomKey; public static ConfigEntry<float> BowZoomConstantTime; public static ConfigEntry<bool> BowZoomSFXEnabled; public static ConfigEntry<float> StayInZoomTime; public static ConfigEntry<bool> IsCrosshairVisible; public static ConfigEntry<bool> IsBowCrosshairVisible; public static ConfigEntry<bool> ShowSneakDamage; public static ConfigEntry<bool> BowDrawMovementSpeedReductionEnabled; public static ConfigEntry<bool> ConfigCrouchBowDrawEnabled; public static ConfigEntry<bool> NockedArrowEnabled; public const string CrouchBowDrawClipName = "Bow Aim Idle 01"; public const string CrouchBowDrawStateName = "staff_charge_loop"; public static readonly Vector3 NockedArrowPosition = new Vector3(-0.01f, 0f, 0f); public static readonly Vector3 NockedArrowRotation = new Vector3(-1f, 0f, 0f); public const float NockedArrowScale = 1f; public const float NockedArrowYaw = 6f; public const string NockedArrowFlipped = "ArrowCarapace,BoltCarapace"; public static ConfigEntry<int> DebugLevel; public static RecipesConfig Recipes; public static ConfigEntry<bool> WoodenArrowEverywhereEnabled; public static readonly Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>(); public static GameObject QuiverGO; public static ConfigEntry<int> NexusID; public static AudioSource PlayerAudioSource; public static BetterArchery _instance; private Harmony _harmony; public const string EquipmentAndQuickSlotsGuid = "randyknapp.mods.equipmentandquickslots"; private static int eaqsPresent = -1; public const string ExtendedPlayerInventoryGuid = "aedenthorn.ExtendedPlayerInventory"; private static int epiPresent = -1; public static bool hasAuga { get; private set; } public static bool isEquipmentAndQuickSlotsPresent { get { if (eaqsPresent < 0) { eaqsPresent = (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.equipmentandquickslots") ? 1 : 0); } return eaqsPresent == 1; } } public static bool isExtendedPlayerInventoryPresent { get { if (epiPresent < 0) { epiPresent = (Chainloader.PluginInfos.ContainsKey("aedenthorn.ExtendedPlayerInventory") ? 1 : 0); } return epiPresent == 1; } } public static bool isInventoryExpansionModPresent => isEquipmentAndQuickSlotsPresent || isExtendedPlayerInventoryPresent; private void Awake() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) _instance = this; ConfigQuiverEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Quiver", "Enable Quiver", true, "Enable the quiver. Don't change this value while in the game. If you disable this while arrows are in the quiver, you will LOSE ALL OF THEM!"); InventoryQuiverSlotLocation = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Quiver", "Change location of inventory quiver slot", new Vector2(3f, -25f), "Change quiver slot inventory location. For 'More Slots' you can use this location, 'x:3.0, y:-167.0'."); InventoryQuiverSlotLocationWithContainer = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Quiver", "Change location of inventory quiver slot when a chest opened", new Vector2(3f, -425f), "Change quiver slot inventory location when a chest opened."); QuiverModelRotation = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Quiver", "Change Quiver Model Rotation", new Vector3(270f, 90f, -10f), "Change the quiver model rotation. Default is 'x:270.0, y:90.0, z:-10.0'"); QuiverModelScale = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Quiver", "Change Quiver Model Scale", new Vector3(2f, 2f, 2f), "Change the quiver model scale. Default is 'x:2.0, y:2.0, z:2.0'"); QuiverModelPosition = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Quiver", "Change Quiver Model Position", new Vector3(0.001f, 0f, 0.003f), "Change the quiver model position. Default is 'x:0.001, y:0.0, z:0.003'"); QuiverHudEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Quiver", "Enable Quiver Hud", true, "Enable the quiver's hotbar on the screen/hud. This doesn't affect inventory."); QuiverHudScale = ((BaseUnityPlugin)this).Config.Bind<float>("Quiver", "Quiver Hud Scale", 0.7f, "Size of the quiver HUD slots."); QuiverHudPositionOffset = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Quiver", "Quiver Hud Position Offset", new Vector2(-5f, 180f), "Change the quiver HUD position. Default is 'x:-5.0, y:180'"); QuiverHudLayout = ((BaseUnityPlugin)this).Config.Bind<QuiverHudOrientation>("Quiver", "Quiver Hud Orientation", QuiverHudOrientation.Horizontal, "Layout of the quiver HUD slots: a horizontal row or a vertical column."); HoldingKeyCode = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Quiver", "Quiver slot hotkey holding key", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Change holding key. For the inputs: https://docs.unity3d.com/ScriptReference/KeyCode.html"); KeyCodes[0] = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Quiver", "Quiver slot hotkey 1", new KeyboardShortcut((KeyCode)49, Array.Empty<KeyCode>()), "Hotkey for Quiver Slot 1. For the inputs: https://docs.unity3d.com/ScriptReference/KeyCode.html"); KeyCodes[1] = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Quiver", "Quiver slot hotkey 2", new KeyboardShortcut((KeyCode)50, Array.Empty<KeyCode>()), "Hotkey for Quiver Slot 2. For the inputs: https://docs.unity3d.com/ScriptReference/KeyCode.html"); KeyCodes[2] = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Quiver", "Quiver slot hotkey 3", new KeyboardShortcut((KeyCode)51, Array.Empty<KeyCode>()), "Hotkey for Quiver Slot 3. For the inputs: https://docs.unity3d.com/ScriptReference/KeyCode.html"); ConfigArrowImprovementsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Arrow Improvements", "Enable Arrow Improvements", true, "Arrow improvements including aim problems fixes, gravity changes."); ArrowVelocity = ((BaseUnityPlugin)this).Config.Bind<float>("Arrow Improvements", "Set Arrow Velocity", 70f, "Change the arrow's velocity. Vanilla is '60'."); ArrowGravity = ((BaseUnityPlugin)this).Config.Bind<float>("Arrow Improvements", "Set Arrow Gravity", 15f, "Change the arrow's gravity. Vanilla is '5'."); ArrowAccuracy = ((BaseUnityPlugin)this).Config.Bind<float>("Arrow Improvements", "Set Arrow Accuracy", 0f, "Change the arrow's accuracy. Vanilla is '-1'."); ArrowAimDir = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Arrow Improvements", "Set Aim Direction", new Vector3(0f, 0.05f, 0f), "Change the aim direction. Vanilla is 'x:0.0, y:0.0, z: 0.0'."); ConfigBowZoomEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Bow Zoom", "Enable Bow Zoom", true, "Enable the zooming with bow."); AutomaticBowZoom = ((BaseUnityPlugin)this).Config.Bind<bool>("Bow Zoom", "Automatic Bow Zoom", false, "Zoom while drawing bow automatically."); BowZoomSFXEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Bow Zoom", "Enable Bow Zoom SFX", true, "Sound effects for zoom-in and zoom-out."); BowZoomFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Bow Zoom", "Zoom Factor", 2f, "Max zoom."); BowZoomConstantTime = ((BaseUnityPlugin)this).Config.Bind<float>("Bow Zoom", "Bow Zoom Constant Time", -1f, "Change this value to '-1' if you don't want constant time while zooming. '1' is recommended."); BowZoomKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Bow Zoom", "Bow Zoom Hotkey", new KeyboardShortcut((KeyCode)324, Array.Empty<KeyCode>()), "Mouse0: Left Click, Mouse1: Right Click, Mouse2: Middle Click. For the other inputs: https://docs.unity3d.com/ScriptReference/KeyCode.html"); BowDrawCancelKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Bow Zoom", "Bow Draw Cancel Hotkey", new KeyboardShortcut((KeyCode)101, Array.Empty<KeyCode>()), "Mouse0: Left Click, Mouse1: Right Click, Mouse2: Middle Click. For the other inputs: https://docs.unity3d.com/ScriptReference/KeyCode.html"); BowDrawCancelEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Bow Zoom", "Enable Bow Draw Cancel", true, "When enabled, the Bow Draw Cancel Hotkey cancels bow drawing. Disable to restore vanilla cancel behavior."); BowDrawCancelGamepadButton = ((BaseUnityPlugin)this).Config.Bind<string>("Bow Zoom", "Bow Draw Cancel Gamepad Button", "JoyBlock", "Gamepad button that cancels bow drawing (ZInput button name). Empty to disable gamepad cancel. Requires 'Enable Bow Draw Cancel'."); StayInZoomTime = ((BaseUnityPlugin)this).Config.Bind<float>("Bow Zoom", "Stay In-Zoom Time", 2f, "Set the max time of staying on zoom while holding RMB after releasing an arrow."); IsCrosshairVisible = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Enable Crosshair", true, "You can hide your crosshair."); IsBowCrosshairVisible = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Enable Bow Crosshair", true, "You can hide your circle bow crosshair."); ShowSneakDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Enable Sneak Damage Showing", true, "Show sneak damage at top left."); BowDrawMovementSpeedReductionEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Enable Bow Draw Movement Speed Reduction", true, "Set walk speed while drawing bow."); ConfigCrouchBowDrawEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Enable Crouch Bow Draw", true, "Keep the character crouched while drawing a bow."); NockedArrowEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Enable Nocked Arrow", true, "Show the selected arrow model nocked on the bow string while drawing."); WoodenArrowEverywhereEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Enable Crafting Wooden Arrow Everywhere", true, "Enable to crafting wooden arrows without a crafting table."); ConfigRetrievableArrowsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Retrievable Arrows", "Enable Retrievable Arrows", true, "Enable the retrievable arrows."); ArrowDisappearTime = ((BaseUnityPlugin)this).Config.Bind<float>("Retrievable Arrows", "Arrow Disappear Time", 60f, "Set arrow's disappear countdown time."); ArrowDisappearOnHit = ((BaseUnityPlugin)this).Config.Bind<bool>("Retrievable Arrows", "Arrow Disappear On Hit", false, "Make non-retrievable arrows disappear on hit."); ArrowRetrieveSolidCollider = ((BaseUnityPlugin)this).Config.Bind<bool>("Retrievable Arrows", "Retrievable Arrow Solid Collider", false, "Let players stand on retrievable arrows stuck in the ground."); ArrowRetrieveList = ((BaseUnityPlugin)this).Config.Bind<string>("Retrievable Arrows", "Arrow Retrieve List", "ArrowWood=0.2;ArrowFlint=0.3;ArrowBronze=0.5;ArrowIron=0.7;ArrowObsidian=0.7;ArrowNeedle=0.1;ArrowFire=0;ArrowPoison=0.7>ArrowObsidian;ArrowSilver=0.5;ArrowFrost=0.7>ArrowObsidian;ArrowCarapace=0.7;ArrowCharred=0.7;BoltBone=0.3;BoltIron=0.5;BoltBlackmetal=0.7;BoltCarapace=0.7;BoltCharred=0.7", "Retrievable ammo list. Format: AmmoPrefab=chance>SpawnPrefab, entries separated by ';'. The '>SpawnPrefab' part is optional and defaults to the same ammo. Example: ArrowWood=0.2;ArrowPoison=0.7>ArrowObsidian"); ArrowRetrieveList.SettingChanged += delegate { RebuildArrowRetrieves(); }; NexusID = ((BaseUnityPlugin)this).Config.Bind<int>("Other", "NexusID", 348, "Nexus mod ID for updates."); DebugLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Other", "Set Debug Log Level", 1, "0: Nothing, 1: Only Errors, 2: Errors and Warnings, 3: Everything"); RebuildArrowRetrieves(); Recipes = LoadJsonFile<RecipesConfig>("BetterArcheryRecipes.json"); if (ConfigQuiverEnabled.Value) { AssetBundle val = LoadAssetBundle("quiverassets"); if (Recipes != null && (Object)(object)val != (Object)null) { foreach (RecipeConfig recipe in Recipes.recipes) { if (val.Contains(recipe.item)) { GameObject value = val.LoadAsset<GameObject>(recipe.item); Prefabs.Add(recipe.item, value); } } } if (val != null) { val.Unload(false); } } _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); hasAuga = API.IsLoaded(); } public static void RebuildArrowRetrieves() { ArrowRetrieves.Clear(); string text = ArrowRetrieveList?.Value; if (string.IsNullOrEmpty(text)) { return; } string[] array = text.Split(new char[1] { ';' }); foreach (string text2 in array) { string text3 = text2.Trim(); if (text3.Length == 0) { continue; } string[] array2 = text3.Split(new char[1] { '=' }); if (array2.Length != 2) { Log("Invalid arrow retrieve entry (expected Ammo=chance>Spawn): '" + text3 + "'", 1); continue; } string text4 = array2[0].Trim(); string text5 = array2[1]; string text6 = text5; string text7 = text4; int num = text5.IndexOf('>'); if (num >= 0) { text6 = text5.Substring(0, num); text7 = text5.Substring(num + 1).Trim(); } if (text4.Length == 0 || text7.Length == 0 || !float.TryParse(text6.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { Log("Invalid arrow retrieve entry: '" + text3 + "'", 1); continue; } ArrowRetrieves[text4] = new Arrow { Name = text4, SpawnChance = Mathf.Clamp01(result), SpawnArrow = text7 }; } Log($"Loaded {ArrowRetrieves.Count} retrievable ammo entries.", 3); } public void Start() { hasAuga = API.IsLoaded(); if (hasAuga) { Log("Auga Loaded."); } Dictionary<string, object> dictionary = LoadTranslationJsonFile<Dictionary<string, object>>("betterarchery_translations.json"); if (dictionary.Count > 0) { LoadTranslations(dictionary); } } private void Update() { Player localPlayer = Player.m_localPlayer; CrouchBowDrawOverlay.Update(localPlayer); NockedArrow.Update(localPlayer); if (!((Object)(object)localPlayer == (Object)null) && ConfigQuiverEnabled.Value && ((Character)localPlayer).TakeInput()) { for (int i = 0; i < 3; i++) { CheckQuiverUseInput(localPlayer, i); } } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } foreach (GameObject value in Prefabs.Values) { Object.Destroy((Object)(object)value); } Prefabs.Clear(); } public static void Log(string str = "", int warningType = 2) { int num = ((DebugLevel == null) ? 1 : DebugLevel.Value); if (num == 0) { return; } if (warningType == 0) { Debug.LogError((object)("[" + typeof(BetterArchery).Namespace + "]: " + str)); } if (num > 1) { if (warningType == 1) { Debug.LogWarning((object)("[" + typeof(BetterArchery).Namespace + "]: " + str)); } if (num > 2 && warningType == 2) { Debug.Log((object)("[" + typeof(BetterArchery).Namespace + "]: " + str)); } } } private static void LoadTranslations(Dictionary<string, object> translations) { if (translations == null) { Log("Could not parse betterarchery_translations.json!", 3); return; } List<KeyValuePair<string, string>> list = Localization.instance.m_translations.Where((KeyValuePair<string, string> instanceMTranslation) => instanceMTranslation.Key.StartsWith("mod_betterarchery_")).ToList(); foreach (KeyValuePair<string, string> item in list) { Localization.instance.m_translations.Remove(item.Key); } foreach (KeyValuePair<string, object> translation in translations) { Localization.instance.AddWord(translation.Key, translation.Value.ToString()); } } public unsafe static string GetBindingLabel(int index) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) index = Mathf.Clamp(index, 0, 2); KeyCode bindingKeycode = GetBindingKeycode(index); if (((object)(*(KeyCode*)(&bindingKeycode))/*cast due to .constrained prefix*/).ToString().Contains("Alpha")) { return ((object)(*(KeyCode*)(&bindingKeycode))/*cast due to .constrained prefix*/).ToString().Replace("Alpha", ""); } return ((object)(*(KeyCode*)(&bindingKeycode))/*cast due to .constrained prefix*/).ToString().ToUpperInvariant(); } public static KeyCode GetBindingKeycode(int index) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) index = Mathf.Clamp(index, 0, 2); KeyboardShortcut value = KeyCodes[index].Value; return ((KeyboardShortcut)(ref value)).MainKey; } public static bool IsBowZoomHeld() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) int result; if (BowZoomKey != null) { KeyboardShortcut value = BowZoomKey.Value; result = (Input.GetKey(((KeyboardShortcut)(ref value)).MainKey) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } public static bool IsBowDrawCancelPressed() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (BowDrawCancelKey != null) { KeyboardShortcut value = BowDrawCancelKey.Value; if (Input.GetKey(((KeyboardShortcut)(ref value)).MainKey)) { return true; } } string text = BowDrawCancelGamepadButton?.Value; if (!string.IsNullOrEmpty(text) && ZInput.IsGamepadActive()) { try { if (ZInput.GetButton(text)) { return true; } } catch { } } return false; } public static int GetBonusInventoryRowIndex() { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && QuiverRowIndex != 0) { return QuiverRowIndex; } return 0; } public static void CheckQuiverUseInput(Player player, int index) { //IL_0002: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0051: 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) KeyCode bindingKeycode = GetBindingKeycode(index); KeyboardShortcut value = HoldingKeyCode.Value; bool flag; if (!string.IsNullOrEmpty(((KeyboardShortcut)(ref value)).Serialize())) { value = HoldingKeyCode.Value; if (((KeyboardShortcut)(ref value)).Serialize() != "None") { value = HoldingKeyCode.Value; flag = Input.GetKey(((KeyboardShortcut)(ref value)).MainKey) && Input.GetKeyDown(bindingKeycode); goto IL_0070; } } flag = Input.GetKeyDown(bindingKeycode); goto IL_0070; IL_0070: if (flag) { int bonusInventoryRowIndex = GetBonusInventoryRowIndex(); ItemData itemAt = ((Humanoid)player).GetInventory().GetItemAt(index, bonusInventoryRowIndex); if (itemAt != null) { ((Humanoid)player).UseItem((Inventory)null, itemAt, false); } } } public static bool IsQuiverSlot(Vector2i pos) { //IL_0001: 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) return IsQuiverSlot(pos.x, pos.y); } public static bool IsQuiverSlot(int x, int y) { int bonusInventoryRowIndex = GetBonusInventoryRowIndex(); return y == bonusInventoryRowIndex && x >= 0 && x < 3; } public static Vector2i GetQuiverSlotPosition(int index) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) int bonusInventoryRowIndex = GetBonusInventoryRowIndex(); return new Vector2i(index, bonusInventoryRowIndex); } public static bool IsQuiverEquipped() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } if (CustomSlotCreator.IsSlotOccupied((Humanoid)(object)localPlayer, "quiver")) { return true; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); return inventory != null && inventory.GetEquippedItems().Any((ItemData item) => CustomSlotCreator.IsCustomSlotItem(item) && CustomSlotCreator.GetCustomSlotName(item) == "quiver"); } private static T LoadJsonFile<T>(string filename) where T : class { string assetPath = GetAssetPath(filename); if (!string.IsNullOrEmpty(assetPath)) { string json = File.ReadAllText(assetPath); return JsonMapper.ToObject<T>(json); } return null; } private static Dictionary<string, object> LoadTranslationJsonFile<T>(string filename) where T : class { string assetPath = GetAssetPath(filename); if (!string.IsNullOrEmpty(assetPath)) { string json = File.ReadAllText(assetPath); return JsonMapper.ToObject<Dictionary<string, object>>(json); } return null; } public static AssetBundle LoadAssetBundle(string filename) { Assembly callingAssembly = Assembly.GetCallingAssembly(); AssetBundle result = AssetBundle.LoadFromStream(callingAssembly.GetManifestResourceStream(callingAssembly.GetName().Name + "." + filename)); Log("Loaded AssetBundle (" + filename + ").", 3); Log(callingAssembly.GetName().Name); return result; } public static string GetAssetPath(string assetName, bool isDirectory = false) { string text = Path.Combine(Paths.PluginPath, "BetterArchery", assetName); if (isDirectory) { if (!Directory.Exists(text)) { Assembly assembly = typeof(BetterArchery).Assembly; text = Path.Combine(Path.GetDirectoryName(assembly.Location), assetName); if (!Directory.Exists(text)) { Log("Could not find directory (" + assetName + ").", 1); return null; } } return text; } if (!File.Exists(text)) { Assembly assembly2 = typeof(BetterArchery).Assembly; text = Path.Combine(Path.GetDirectoryName(assembly2.Location), assetName); if (!File.Exists(text)) { Log("Could not find asset (" + assetName + ").", 1); return null; } } return text; } public static void TryCreateCustomSlot(ZNetScene zNetScene) { if (!((Object)(object)zNetScene == (Object)null) && ConfigQuiverEnabled.Value) { GameObject prefab = zNetScene.GetPrefab("LeatherQuiver"); CustomSlotCreator.ApplyCustomSlotItem(prefab, "quiver"); } } public static void TryCreateCustomSFX() { if (!ConfigBowZoomEnabled.Value || !BowZoomSFXEnabled.Value) { return; } string assetPath = GetAssetPath("SFX", isDirectory: true); if (string.IsNullOrEmpty(assetPath)) { Log("SFX folder not found."); return; } Log("path: " + assetPath); string[] directories = Directory.GetDirectories(assetPath); foreach (string path in directories) { Log("Checking folder " + Path.GetFileName(path)); CustomSfxDict[Path.GetFileName(path)] = new Dictionary<string, AudioClip>(); string[] files = Directory.GetFiles(path); foreach (string path2 in files) { if (Path.GetExtension(path2).ToLower().Equals(".wav")) { Log("Checking file " + Path.GetFileName(path2)); ((MonoBehaviour)_instance).StartCoroutine(LoadSFXCoroutine(path2, CustomSfxDict[Path.GetFileName(path)])); } } } } private static AudioSource CreateChildSfxSource(string name) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BA_SFX_" + name); val.transform.SetParent(((Component)PlayerAudioSource).transform, false); AudioSource val2 = val.AddComponent<AudioSource>(); val2.outputAudioMixerGroup = PlayerAudioSource.outputAudioMixerGroup; val2.spatialBlend = PlayerAudioSource.spatialBlend; val2.rolloffMode = PlayerAudioSource.rolloffMode; val2.minDistance = PlayerAudioSource.minDistance; val2.maxDistance = PlayerAudioSource.maxDistance; val2.dopplerLevel = PlayerAudioSource.dopplerLevel; val2.playOnAwake = false; val2.loop = false; val2.volume = PlayerAudioSource.volume; return val2; } public static void PlayCustomSFX(string name, bool checkIfPlaying = true) { if ((Object)(object)PlayerAudioSource == (Object)null || !BowZoomSFXEnabled.Value) { return; } if (!CustomSfxDict.TryGetValue(name, out var value) || value.Count == 0) { Log("SFX not found.", 0); return; } try { if (!_customSfxAudioSources.TryGetValue(name, out var value2) || (Object)(object)value2 == (Object)null) { value2 = CreateChildSfxSource(name); _customSfxAudioSources[name] = value2; } if (checkIfPlaying && value2.isPlaying) { return; } if (!_customSfxClipCache.TryGetValue(name, out var value3) || value3 == null || value3.Length != value.Count) { value3 = value.Values.Where((AudioClip c) => (Object)(object)c != (Object)null).ToArray(); _customSfxClipCache[name] = value3; if (value3.Length == 0) { return; } } AudioClip val = value3[Random.Range(0, value3.Length)]; value2.pitch = 1f; value2.PlayOneShot(val); } catch (Exception ex) { Log("Error while playing custom SFX: " + ex.Message, 0); } } public static IEnumerator LoadSFXCoroutine(string path, Dictionary<string, AudioClip> dict) { path = "file:///" + path; UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)20); try { yield return www.SendWebRequest(); if (www == null) { Log("ww error.", 0); yield break; } DownloadHandlerAudioClip dh = (DownloadHandlerAudioClip)www.downloadHandler; if (dh != null) { AudioClip ac = dh.audioClip; if ((Object)(object)ac != (Object)null) { ((Object)ac).name = Path.GetFileNameWithoutExtension(path); if (!dict.ContainsKey(((Object)ac).name)) { dict[((Object)ac).name] = ac; } Log("Added " + ((Object)ac).name + " SFX."); yield break; } } Log("Error while adding custom SFX.", 0); } finally { ((IDisposable)www)?.Dispose(); } } public static void TryRegisterPrefabs(ZNetScene zNetScene) { if ((Object)(object)zNetScene == (Object)null) { return; } foreach (GameObject value in Prefabs.Values) { if (!ConfigQuiverEnabled.Value) { Log(((Object)value).name); if (((Object)value).name.Contains("Quiver")) { Debug.Log((object)("[PrefabCreator] " + ((Object)value).name + " prefab skipped.")); continue; } } if (!zNetScene.m_prefabs.Contains(value)) { zNetScene.m_prefabs.Add(value); } } } public static bool IsObjectDBReady() { return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null; } public static void TryRegisterItems() { if (!IsObjectDBReady()) { return; } foreach (GameObject value in Prefabs.Values) { ItemDrop component = value.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null)) { if (!ConfigQuiverEnabled.Value && ((Object)component.m_itemData.m_dropPrefab).name.Contains("Quiver")) { Debug.Log((object)("[PrefabCreator] Skipped prefab: " + ((Object)component.m_itemData.m_dropPrefab).name)); } else if ((Object)(object)ObjectDB.instance.GetItemPrefab(StringExtensionMethods.GetStableHashCode(((Object)value).name)) == (Object)null) { component.m_itemData.m_dropPrefab = value; ObjectDB.instance.m_items.Add(value); } } } ObjectDB.instance.UpdateRegisters(); } public static void TryRegisterRecipes() { if (!IsObjectDBReady()) { return; } PrefabCreator.Reset(); foreach (RecipeConfig recipe in Recipes.recipes) { if (!ConfigQuiverEnabled.Value && recipe.item.Contains("Quiver")) { Debug.Log((object)("[PrefabCreator] Skipped recipe: " + recipe.name)); } else if (!WoodenArrowEverywhereEnabled.Value && recipe.name == "Recipe_ArrowWoodAnywhere") { Debug.Log((object)("[PrefabCreator] Skipped recipe: " + recipe.name)); } else { PrefabCreator.AddNewRecipe(recipe.name, recipe.item, recipe); } } } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] public static class TerminalAwake_Patch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; internal void <Postfix>b__0_0(ConsoleEventArgs args) { //IL_020c: Unknown result type (might be due to invalid IL or missing references) if (args.Length < 2) { args.Context.AddString("Syntax: ba [action]"); return; } switch (args.FullLine.Substring(args[0].Length + 1)) { case "reload": ((BaseUnityPlugin)BetterArchery._instance).Config.Reload(); BetterArchery.RebuildArrowRetrieves(); args.Context.AddString("Better Archery Reloaded."); args.Context.AddString(Localization.instance.Localize("$mod_betterarchery_test")); break; case "drop": { Inventory inventory = ((Humanoid)Player.m_localPlayer).m_inventory; for (int num = inventory.m_inventory.Count - 1; num >= 0; num--) { ItemData val = inventory.m_inventory[num]; if (val.m_gridPos.y >= 5 && !BetterArchery.IsQuiverSlot(val.m_gridPos)) { BetterArchery.Log($"Found {((Object)val.m_dropPrefab).name} x {val.m_stack} in invisible slots; attempting to drop."); ((Humanoid)Player.m_localPlayer).DropItem(inventory, val, val.m_stack); } } break; } case "god": Player.m_localPlayer.SetGodMode(!Player.m_localPlayer.m_godMode); Player.m_localPlayer.SetNoPlacementCost(!Player.m_localPlayer.m_noPlacementCost); Player.m_localPlayer.m_staminaRegenDelay = 0.05f; Player.m_localPlayer.m_staminaRegen = 999f; Player.m_localPlayer.m_runStaminaDrain = 0f; Player.m_localPlayer.SetMaxStamina(9999f, true); ((Character)Player.m_localPlayer).AddStamina(999f); break; case "clear": ((Humanoid)Player.m_localPlayer).GetInventory().RemoveAll(); break; case "sfx": BetterArchery.PlayCustomSFX("exhale"); break; case "kill": ((Character)Player.m_localPlayer).SetHealth(0f); break; case "removequivermodel": ZNetScene.instance.Destroy(BetterArchery.QuiverGO); break; case "fill": { for (int i = 0; i < 32; i++) { ((Humanoid)Player.m_localPlayer).m_inventory.AddItem(ObjectDB.instance.GetItemPrefab("Wood"), 100); } break; } default: args.Context.AddString("Syntax: ba [action]"); break; } } } public static void Postfix() { //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_0041: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { //IL_020c: Unknown result type (might be due to invalid IL or missing references) if (args.Length < 2) { args.Context.AddString("Syntax: ba [action]"); } else { switch (args.FullLine.Substring(args[0].Length + 1)) { case "reload": ((BaseUnityPlugin)BetterArchery._instance).Config.Reload(); BetterArchery.RebuildArrowRetrieves(); args.Context.AddString("Better Archery Reloaded."); args.Context.AddString(Localization.instance.Localize("$mod_betterarchery_test")); break; case "drop": { Inventory inventory = ((Humanoid)Player.m_localPlayer).m_inventory; for (int num = inventory.m_inventory.Count - 1; num >= 0; num--) { ItemData val3 = inventory.m_inventory[num]; if (val3.m_gridPos.y >= 5 && !BetterArchery.IsQuiverSlot(val3.m_gridPos)) { BetterArchery.Log($"Found {((Object)val3.m_dropPrefab).name} x {val3.m_stack} in invisible slots; attempting to drop."); ((Humanoid)Player.m_localPlayer).DropItem(inventory, val3, val3.m_stack); } } break; } case "god": Player.m_localPlayer.SetGodMode(!Player.m_localPlayer.m_godMode); Player.m_localPlayer.SetNoPlacementCost(!Player.m_localPlayer.m_noPlacementCost); Player.m_localPlayer.m_staminaRegenDelay = 0.05f; Player.m_localPlayer.m_staminaRegen = 999f; Player.m_localPlayer.m_runStaminaDrain = 0f; Player.m_localPlayer.SetMaxStamina(9999f, true); ((Character)Player.m_localPlayer).AddStamina(999f); break; case "clear": ((Humanoid)Player.m_localPlayer).GetInventory().RemoveAll(); break; case "sfx": BetterArchery.PlayCustomSFX("exhale"); break; case "kill": ((Character)Player.m_localPlayer).SetHealth(0f); break; case "removequivermodel": ZNetScene.instance.Destroy(BetterArchery.QuiverGO); break; case "fill": { for (int i = 0; i < 32; i++) { ((Humanoid)Player.m_localPlayer).m_inventory.AddItem(ObjectDB.instance.GetItemPrefab("Wood"), 100); } break; } default: args.Context.AddString("Syntax: ba [action]"); break; } } }; <>c.<>9__0_0 = val; obj = (object)val; } ConsoleCommand val2 = new ConsoleCommand("ba", "[action]", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false) { IsCheat = false }; } } public static class CrouchBowDrawOverlay { private enum Phase { Off, Drawing, Releasing } private const string SourceClipName = "Charge Staff Loop"; private const string RecoilClipName = "Bow Aim Recoil"; private const string FireTriggerName = "bow_fire"; private const int LayerIndex = 1; private const float ReleaseDuration = 0.6f; private const float MinReleaseHold = 0.2f; private static Player _installedPlayer; private static AnimatorOverrideController _overrideController; private static AnimationClip _sourceClip; private static AnimationClip _aimClip; private static AnimationClip _recoilClip; private static Phase _phase; private static float _releaseStartTime; private static bool _pendingRestore; private static bool _warned; private static int _crouchStateHash; private static int _overlayStateHash; private static int _noneStateHash; private static bool _hashesReady; public static bool IsActiveFor(Player player) { return _phase != Phase.Off && (Object)(object)_installedPlayer != (Object)null && (Object)(object)_installedPlayer == (Object)(object)player; } public static void CancelBowDraw(Player player) { ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon != null && currentWeapon.m_shared.m_attack.m_bowDraw) { ((Humanoid)player).m_attackDrawTime = -1f; if (!string.IsNullOrEmpty(currentWeapon.m_shared.m_attack.m_drawAnimationState)) { ((Character)player).m_zanim.SetBool(currentWeapon.m_shared.m_attack.m_drawAnimationState, false); } } } public static bool OnFireTrigger(ZSyncAnimation zanim, string name) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Invalid comparison between Unknown and I4 if (name != "bow_fire") { return false; } if (!BetterArchery.ConfigCrouchBowDrawEnabled.Value) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)((Character)localPlayer).m_zanim != (Object)(object)zanim) { return false; } if (!localPlayer.m_crouchToggled) { return false; } ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon(); if (currentWeapon == null || (int)currentWeapon.m_shared.m_itemType != 4) { return false; } if ((Object)(object)_overrideController == (Object)null) { return false; } _phase = Phase.Releasing; _releaseStartTime = Time.time; PlayClip(localPlayer, _recoilClip); return true; } public static void Update(Player player) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Invalid comparison between Unknown and I4 if (!BetterArchery.ConfigCrouchBowDrawEnabled.Value || (Object)(object)player == (Object)null || (Object)(object)((Character)player).m_animator == (Object)null) { Stop(); return; } if ((Object)(object)_installedPlayer != (Object)(object)player) { Stop(); Reset(); _installedPlayer = player; } EnsureController(player); if (_pendingRestore) { TryRestoreClip(player); } int num; if (player.m_crouchToggled && ((Character)player).IsDrawingBow()) { ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); num = ((currentWeapon != null && (int)currentWeapon.m_shared.m_itemType == 4) ? 1 : 0); } else { num = 0; } bool flag = (byte)num != 0; if (_phase == Phase.Releasing) { float num2 = Time.time - _releaseStartTime; if (num2 < 0.6f) { if (flag && num2 >= 0.2f) { StartAim(player); } else { KeepCrouch(player); } } else if (flag) { StartAim(player); } else { Stop(); } } else if (!flag) { Stop(); } else if (!((Object)(object)_overrideController == (Object)null)) { StartAim(player); } } private static void StartAim(Player player) { if (_phase != Phase.Drawing) { _phase = Phase.Drawing; PlayClip(player, _aimClip); } KeepCrouch(player); ((Character)player).m_animator.SetLayerWeight(OverlayLayer(((Character)player).m_animator), Mathf.Clamp01(((Humanoid)player).GetAttackDrawPercentage() * 1.5f)); } private static void KeepCrouch(Player player) { if (((Character)player).GetNextOrCurrentAnimHash() != Player.s_animatorTagCrouch) { ((Character)player).m_animator.CrossFadeInFixedTime(_crouchStateHash, 0.15f, 0); } } private static void PlayClip(Player player, AnimationClip clip) { _pendingRestore = false; _overrideController[((Object)_sourceClip).name] = clip; Animator animator = ((Character)player).m_animator; int num = OverlayLayer(animator); animator.Play(_overlayStateHash, num, 0f); animator.SetLayerWeight(num, 1f); } private static bool TryRestoreClip(Player player) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_overrideController == (Object)null || (Object)(object)_sourceClip == (Object)null) { _pendingRestore = false; return false; } Animator animator = ((Character)player).m_animator; if ((Object)(object)animator == (Object)null) { _pendingRestore = false; return false; } int num = OverlayLayer(animator); if (!animator.IsInTransition(num)) { AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(num); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash != _overlayStateHash) { _overrideController[((Object)_sourceClip).name] = _sourceClip; _pendingRestore = false; return true; } } return false; } private static int OverlayLayer(Animator animator) { return Mathf.Clamp(1, 0, animator.layerCount - 1); } private static void Stop() { if (_phase != Phase.Off) { _phase = Phase.Off; _pendingRestore = true; Animator val = (((Object)(object)_installedPlayer != (Object)null) ? ((Character)_installedPlayer).m_animator : null); if ((Object)(object)val != (Object)null && (Object)(object)val.runtimeAnimatorController == (Object)(object)_overrideController) { int num = OverlayLayer(val); val.CrossFadeInFixedTime(_noneStateHash, 0.1f, num); val.SetLayerWeight(num, 1f); } } } private static void Reset() { _installedPlayer = null; _overrideController = null; _sourceClip = null; _aimClip = null; _recoilClip = null; _phase = Phase.Off; _pendingRestore = false; _warned = false; } private static void EnsureController(Player player) { //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown if ((Object)(object)_overrideController != (Object)null) { if ((Object)(object)((Character)player).m_animator.runtimeAnimatorController != (Object)(object)_overrideController) { ((Character)player).m_animator.runtimeAnimatorController = (RuntimeAnimatorController)(object)_overrideController; } return; } RuntimeAnimatorController runtimeAnimatorController = ((Character)player).m_animator.runtimeAnimatorController; if ((Object)(object)runtimeAnimatorController == (Object)null) { return; } if (!_hashesReady) { _crouchStateHash = Animator.StringToHash("Crouch"); _overlayStateHash = Animator.StringToHash("staff_charge_loop"); _noneStateHash = Animator.StringToHash("None"); _hashesReady = true; } AnimationClip val = FindClip(runtimeAnimatorController, "Charge Staff Loop"); AnimationClip val2 = FindClip(runtimeAnimatorController, "Bow Aim Idle 01"); AnimationClip val3 = FindClip(runtimeAnimatorController, "Bow Aim Recoil"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { if (!_warned) { BetterArchery.Log("Crouch bow draw overlay disabled: clip 'Bow Aim Idle 01', 'Bow Aim Recoil' or 'Charge Staff Loop' not found.", 1); _warned = true; } return; } try { _sourceClip = val; _aimClip = val2; _recoilClip = val3; _overrideController = new AnimatorOverrideController(runtimeAnimatorController); ((Character)player).m_animator.runtimeAnimatorController = (RuntimeAnimatorController)(object)_overrideController; } catch (Exception ex) { if (!_warned) { BetterArchery.Log("Crouch bow draw overlay failed: " + ex.Message, 0); _warned = true; } } } private static AnimationClip FindClip(RuntimeAnimatorController controller, string clipName) { if ((Object)(object)controller == (Object)null || string.IsNullOrEmpty(clipName)) { return null; } AnimationClip[] animationClips = controller.animationClips; foreach (AnimationClip val in animationClips) { if ((Object)(object)val != (Object)null && ((Object)val).name == clipName) { return val; } } return null; } } [HarmonyPatch] public class Patches { private class QuiverSyncComponent : MonoBehaviour { internal Humanoid h; private int _nextFrame; private void Update() { if (Object.op_Implicit((Object)(object)h) && Object.op_Implicit((Object)(object)((Character)h).m_nview) && ((Character)h).m_nview.IsValid()) { int frameCount = Time.frameCount; if (frameCount >= _nextFrame) { _nextFrame = frameCount + 60; SyncQuiverFromZdo(h); } } } } private const string QuiverSlotName = "quiver"; private const string ZdoKeyQuiver = "BetterArchery.QuiverPrefab"; private static readonly Dictionary<Humanoid, GameObject> QuiverInstances = new Dictionary<Humanoid, GameObject>(); [HarmonyPatch(typeof(ItemData), "IsEquipable")] [HarmonyPostfix] private static void IsEquipablePostfix(ref bool __result, ref ItemData __instance) { __result = __result || CustomSlotCreator.IsCustomSlotItem(__instance); } [HarmonyPatch(typeof(Humanoid), "Awake")] [HarmonyPostfix] private static void HumanoidEntryPostfix(ref Humanoid __instance) { CustomSlotCreator.customSlotItemData[__instance] = new Dictionary<string, ItemData>(); if (!Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<QuiverSyncComponent>())) { QuiverSyncComponent quiverSyncComponent = ((Component)__instance).gameObject.AddComponent<QuiverSyncComponent>(); quiverSyncComponent.h = __instance; } } [HarmonyPatch(typeof(Player), "Load")] [HarmonyPostfix] private static void InventoryLoadPostfix(ref Player __instance) { foreach (ItemData equippedItem in ((Humanoid)__instance).m_inventory.GetEquippedItems()) { if (CustomSlotCreator.IsCustomSlotItem(equippedItem)) { string customSlotName = CustomSlotCreator.GetCustomSlotName(equippedItem); CustomSlotCreator.SetSlotItem((Humanoid)(object)__instance, customSlotName, equippedItem); } } } [HarmonyPatch(typeof(Humanoid), "EquipItem")] [HarmonyPostfix] private static void EquipItemPostfix(ref bool __result, ref Humanoid __instance, ItemData item, bool triggerEquipEffects = true) { if (CustomSlotCreator.IsCustomSlotItem(item)) { string customSlotName = CustomSlotCreator.GetCustomSlotName(item); if (CustomSlotCreator.IsSlotOccupied(__instance, customSlotName)) { __instance.UnequipItem(CustomSlotCreator.GetSlotItem(__instance, customSlotName), triggerEquipEffects); } CustomSlotCreator.SetSlotItem(__instance, customSlotName, item); if (__instance.IsItemEquiped(item)) { item.m_equipped = true; } __instance.SetupEquipment(); if (triggerEquipEffects) { __instance.TriggerEquipEffect(item); } if (customSlotName == "quiver" && Object.op_Implicit((Object)(object)item.m_dropPrefab)) { string name = ((Object)item.m_dropPrefab).name; SetQuiverZdo(__instance, name); CreateOrUpdateQuiverVisual(__instance, name); } __result = true; } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] [HarmonyPostfix] private static void UnequipItemPostfix(ref Humanoid __instance, ItemData item, bool triggerEquipEffects = true) { if (CustomSlotCreator.IsCustomSlotItem(item)) { string customSlotName = CustomSlotCreator.GetCustomSlotName(item); if (item == CustomSlotCreator.GetSlotItem(__instance, customSlotName)) { CustomSlotCreator.SetSlotItem(__instance, customSlotName, null); } if (!BetterArchery.IsQuiverEquipped()) { SetQuiverZdo(__instance, ""); RemoveQuiverVisual(__instance); } __instance.UpdateEquipmentStatusEffects(); } } [HarmonyPatch(typeof(Humanoid), "SetupEquipment")] [HarmonyPostfix] private static void SetupEquipmentPostfix(Humanoid __instance) { SyncQuiverFromZdo(__instance); } [HarmonyPatch(typeof(Humanoid), "OnDestroy")] [HarmonyPrefix] private static void HumanoidOnDestroyPrefix(Humanoid __instance) { RemoveQuiverVisual(__instance); } private static void SetQuiverZdo(Humanoid h, string prefabName) { if (Object.op_Implicit((Object)(object)h) && !((Object)(object)((Character)h).m_nview == (Object)null) && ((Character)h).m_nview.IsValid() && ((Character)h).m_nview.IsOwner()) { ZDO zDO = ((Character)h).m_nview.GetZDO(); string text = zDO.GetString("BetterArchery.QuiverPrefab", ""); if (!(text == prefabName)) { zDO.Set("BetterArchery.QuiverPrefab", prefabName); } } } private static void SyncQuiverFromZdo(Humanoid h) { if (!Object.op_Implicit((Object)(object)h) || (Object)(object)((Character)h).m_nview == (Object)null || !((Character)h).m_nview.IsValid()) { return; } ZDO zDO = ((Character)h).m_nview.GetZDO(); string text = zDO.GetString("BetterArchery.QuiverPrefab", ""); if (string.IsNullOrEmpty(text)) { RemoveQuiverVisual(h); return; } if (QuiverInstances.TryGetValue(h, out var value) && (Object)(object)value != (Object)null) { if (((Object)value).name.StartsWith(text)) { return; } RemoveQuiverVisual(h); } CreateOrUpdateQuiverVisual(h, text); } private static void CreateOrUpdateQuiverVisual(Humanoid h, string prefabName) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(prefabName) || (Object)(object)h == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return; } try { GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); if ((Object)(object)prefab == (Object)null) { BetterArchery.Log("Quiver prefab '" + prefabName + "' not found."); return; } Transform val = Utils.FindChild(prefab.transform, "attach", (IterativeSearchType)0); if ((Object)(object)val == (Object)null) { BetterArchery.Log("Quiver prefab '" + prefabName + "' missing child 'attach'."); return; } Transform val2 = Utils.FindChild(((Component)h).transform, "BackBow_attach", (IterativeSearchType)0); if ((Object)(object)val2 == (Object)null) { BetterArchery.Log("BackBow_attach not found on humanoid."); return; } GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, val2.position, val2.rotation, ((Component)val2).transform); ((Object)val3).name = prefabName + "_QuiverInstance"; val3.transform.localPosition = BetterArchery.QuiverModelPosition.Value; val3.transform.localScale = new Vector3(0.01f * BetterArchery.QuiverModelScale.Value.x, 0.01f * BetterArchery.QuiverModelScale.Value.y, 0.01f * BetterArchery.QuiverModelScale.Value.z); val3.transform.localEulerAngles = BetterArchery.QuiverModelRotation.Value; BoxCollider component = val3.GetComponent<BoxCollider>(); if (Object.op_Implicit((Object)(object)component)) { Object.DestroyImmediate((Object)(object)component); } QuiverInstances[h] = val3; } catch (Exception arg) { BetterArchery.Log($"Failed to create quiver visual: {arg}", 0); } } private static void RemoveQuiverVisual(Humanoid h) { if (!QuiverInstances.TryGetValue(h, out var value) || (Object)(object)value == (Object)null) { return; } try { if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { ZNetScene.instance.Destroy(value); } else { Object.DestroyImmediate((Object)(object)value); } } catch { Object.DestroyImmediate((Object)(object)value); } QuiverInstances.Remove(h); } [HarmonyPatch(typeof(Humanoid), "IsItemEquiped")] [HarmonyPostfix] private static void IsItemEquipedPostfix(ref bool __result, ref Humanoid __instance, ItemData item) { if (CustomSlotCreator.IsCustomSlotItem(item)) { string customSlotName = CustomSlotCreator.GetCustomSlotName(item); bool flag = CustomSlotCreator.DoesSlotExist(__instance, customSlotName) && CustomSlotCreator.GetSlotItem(__instance, customSlotName) == item; __result |= flag; } } [HarmonyPatch(typeof(Humanoid), "GetEquipmentWeight")] [HarmonyPostfix] private static void GetEquipmentWeightPostfix(ref float __result, ref Humanoid __instance) { foreach (string key in CustomSlotCreator.customSlotItemData[__instance].Keys) { if (CustomSlotCreator.IsSlotOccupied(__instance, key)) { __result += CustomSlotCreator.GetSlotItem(__instance, key).m_shared.m_weight; } } } [HarmonyPatch(typeof(Humanoid), "UnequipAllItems")] [HarmonyPostfix] private static void UnequipAllItemsPostfix(ref Humanoid __instance) { foreach (string item in CustomSlotCreator.customSlotItemData[__instance].Keys.ToList()) { if (CustomSlotCreator.IsSlotOccupied(__instance, item)) { __instance.UnequipItem(CustomSlotCreator.GetSlotItem(__instance, item), false); } } } [HarmonyPatch(typeof(Humanoid), "GetSetCount")] [HarmonyPostfix] private static void GetSetCountPostfix(ref int __result, ref Humanoid __instance, string setName) { foreach (string item in CustomSlotCreator.customSlotItemData[__instance].Keys.ToList()) { if (CustomSlotCreator.IsSlotOccupied(__instance, item) && CustomSlotCreator.GetSlotItem(__instance, item).m_shared.m_setName == setName) { __result++; } } } public static HashSet<StatusEffect> GetStatusEffectsFromCustomSlotItems(Humanoid __instance) { HashSet<StatusEffect> hashSet = new HashSet<StatusEffect>(); foreach (string key in CustomSlotCreator.customSlotItemData[__instance].Keys) { if (CustomSlotCreator.IsSlotOccupied(__instance, key)) { if (Object.op_Implicit((Object)(object)CustomSlotCreator.GetSlotItem(__instance, key).m_shared.m_equipStatusEffect)) { StatusEffect equipStatusEffect = CustomSlotCreator.GetSlotItem(__instance, key).m_shared.m_equipStatusEffect; hashSet.Add(equipStatusEffect); } if (__instance.HaveSetEffect(CustomSlotCreator.GetSlotItem(__instance, key))) { StatusEffect setStatusEffect = CustomSlotCreator.GetSlotItem(__instance, key).m_shared.m_setStatusEffect; hashSet.Add(setStatusEffect); } } } return hashSet; } } [HarmonyPatch] public static class QuiverHudInstaller { [HarmonyPatch(typeof(Hud), "Awake")] [HarmonyPostfix] private static void Install(Hud __instance) { if (BetterArchery.ConfigQuiverEnabled.Value && BetterArchery.QuiverHudEnabled.Value) { QuiverHud.TryCreate(__instance); } } [HarmonyPatch(typeof(Hud), "OnDestroy")] [HarmonyPostfix] private static void Uninstall() { QuiverHud.Destroy(); } } public class QuiverHud : MonoBehaviour { private class CachedSlot { public GameObject Go; public Image Icon; public TMP_Text Amount; public TMP_Text Binding; public GameObject Equipped; public int StackText = -1; } private static QuiverHud _instance; private RectTransform _anchorFood; private float _appliedScale = -1f; private Vector2 _appliedOffset = new Vector2(float.NaN, float.NaN); private QuiverHudOrientation _appliedOrientation; private bool _hasAppliedOrientation; private float _elementSpace = 70f; private readonly CachedSlot[] _slots = new CachedSlot[3]; private GameObject _slotsRoot; private bool _built; private bool _lastGamepad; private static void HideChild(GameObject go, string childName) { Transform val = go.transform.Find(childName); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } } public static void TryCreate(Hud hud) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: 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_01f6: Unknown result type (might be due to invalid IL or missing references) Destroy(); if ((Object)(object)hud == (Object)null) { BetterArchery.Log("[BA-HUD] TryCreate: hud is null.", 0); return; } HotkeyBar componentInChildren = ((Component)hud).GetComponentInChildren<HotkeyBar>(); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.m_elementPrefab == (Object)null || (Object)(object)((Component)componentInChildren).transform.parent == (Object)null) { BetterArchery.Log("[BA-HUD] TryCreate: no vanilla hotbar found, cannot install.", 0); return; } GameObject val = new GameObject("QuiverHotkeyBar"); float num = HudScale(); Vector2 value = BetterArchery.QuiverHudPositionOffset.Value; RectTransform val2 = val.AddComponent<RectTransform>(); RectTransform foodBarRoot = hud.m_foodBarRoot; if ((Object)(object)foodBarRoot != (Object)null && (Object)(object)((Transform)foodBarRoot).parent != (Object)null) { val.transform.SetParent(((Transform)foodBarRoot).parent, false); val2.anchorMin = foodBarRoot.anchorMin; val2.anchorMax = foodBarRoot.anchorMax; val2.pivot = new Vector2(0f, 0f); val2.anchoredPosition = HudBasePosition(foodBarRoot) + value; } else { val.transform.SetParent(((Component)componentInChildren).transform.parent, false); Transform transform = ((Component)componentInChildren).transform; RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val3 != (Object)null) { val2.anchorMin = val3.anchorMin; val2.anchorMax = val3.anchorMax; val2.pivot = new Vector2(0f, 0f); val2.anchoredPosition = val3.anchoredPosition + new Vector2(0f, 95f) + value; } } val.transform.localScale = new Vector3(num, num, 1f); _instance = val.AddComponent<QuiverHud>(); _instance._anchorFood = foodBarRoot; _instance._appliedScale = num; _instance._appliedOffset = value; } private static float HudScale() { float num = ((BetterArchery.QuiverHudScale != null) ? BetterArchery.QuiverHudScale.Value : 0.8f); return Mathf.Clamp(num, 0.3f, 2f); } private static Vector2 HudBasePosition(RectTransform food) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_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_0047: 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_0062: 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) float x = food.anchoredPosition.x; Rect rect = food.rect; float num = x - ((Rect)(ref rect)).width * food.pivot.x; float y = food.anchoredPosition.y; rect = food.rect; float num2 = y + ((Rect)(ref rect)).height * (1f - food.pivot.y); return new Vector2(num, num2 + 8f); } public static void Destroy() { if ((Object)(object)_instance != (Object)null) { Object.Destroy((Object)(object)((Component)_instance).gameObject); _instance = null; } } private void Update() { try { Refresh(); } catch (Exception arg) { BetterArchery.Log($"Quiver HUD refresh failed: {arg}", 0); ((Behaviour)this).enabled = false; } } private void Refresh() { Player localPlayer = Player.m_localPlayer; if (!BetterArchery.ConfigQuiverEnabled.Value || !BetterArchery.QuiverHudEnabled.Value || !((Object)(object)localPlayer != (Object)null) || ((Character)localPlayer).IsDead() || !BetterArchery.IsQuiverEquipped() || (!_built && !BuildSlots(localPlayer))) { SetSlotsVisible(visible: false); return; } SetSlotsVisible(visible: true); ApplyLayout(); bool flag = ZInput.IsGamepadActive(); if (flag != _lastGamepad) { _lastGamepad = flag; UpdateBindingLabels(flag); } int bonusInventoryRowIndex = BetterArchery.GetBonusInventoryRowIndex(); Inventory inventory = ((Humanoid)localPlayer).GetInventory(); ItemData ammoItem = ((Humanoid)localPlayer).GetAmmoItem(); for (int i = 0; i < _slots.Length; i++) { CachedSlot cachedSlot = _slots[i]; if (cachedSlot == null || (Object)(object)cachedSlot.Go == (Object)null || (Object)(object)cachedSlot.Icon == (Object)null) { continue; } ItemData itemAt = inventory.GetItemAt(i, bonusInventoryRowIndex); bool flag2 = itemAt != null; ((Component)cachedSlot.Icon).gameObject.SetActive(flag2); if ((Object)(object)cachedSlot.Equipped != (Object)null) { cachedSlot.Equipped.SetActive(flag2 && (itemAt.m_equipped || itemAt == ammoItem)); } if ((Object)(object)cachedSlot.Amount != (Object)null) { bool flag3 = flag2 && itemAt.m_shared.m_maxStackSize > 1; ((Component)cachedSlot.Amount).gameObject.SetActive(flag3); if (flag3 && cachedSlot.StackText != itemAt.m_stack) { cachedSlot.Amount.text = $"{itemAt.m_stack} / {itemAt.m_shared.m_maxStackSize}"; cachedSlot.StackText = itemAt.m_stack; } } if (flag2) { cachedSlot.Icon.sprite = itemAt.GetIcon(); } } } private Vector3 SlotLocalPosition(int index) { //IL_0041: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (BetterArchery.QuiverHudLayout.Value == QuiverHudOrientation.Vertical) { return new Vector3(0f, (float)(-index) * _elementSpace, 0f); } return new Vector3((float)index * _elementSpace, 0f, 0f); } private void ApplyLayout() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) float num = HudScale(); Vector2 value = BetterArchery.QuiverHudPositionOffset.Value; QuiverHudOrientation value2 = BetterArchery.QuiverHudLayout.Value; if (Mathf.Approximately(num, _appliedScale) && value == _appliedOffset && _hasAppliedOrientation && value2 == _appliedOrientation) { return; } _appliedScale = num; _appliedOffset = value; _appliedOrientation = value2; _hasAppliedOrientation = true; Transform transform = ((Component)this).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val == (Object)null) { return; } ((Transform)val).localScale = new Vector3(num, num, 1f); if ((Object)(object)_anchorFood != (Object)null) { val.anchoredPosition = HudBasePosition(_anchorFood) + value; } for (int i = 0; i < _slots.Length; i++) { CachedSlot cachedSlot = _slots[i]; if ((Object)(object)cachedSlot?.Go != (Object)null) { cachedSlot.Go.transform.localPosition = SlotLocalPosition(i); } } } private void SetSlotsVisible(bool visible) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if ((Object)(object)_slotsRoot == (Object)null) { _slotsRoot = new GameObject("Slots"); _slotsRoot.transform.SetParent(((Component)this).transform, false); } if (_slotsRoot.activeSelf != visible) { _slotsRoot.SetActive(visible); } } private bool BuildSlots(Player player) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_010d: 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_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown Hud componentInParent = ((Component)this).GetComponentInParent<Hud>(); HotkeyBar val = ((componentInParent != null) ? ((Component)componentInParent).GetComponentInChildren<HotkeyBar>() : null); if ((Object)(object)val == (Object)null || (Object)(object)val.m_elementPrefab == (Object)null) { return false; } if ((Object)(object)_slotsRoot == (Object)null) { _slotsRoot = new GameObject("Slots"); _slotsRoot.transform.SetParent(((Component)this).transform, false); } for (int i = 0; i < _slots.Length; i++) { if ((Object)(object)_slots[i]?.Go != (Object)null) { Object.Destroy((Object)(object)_slots[i].Go); } _slots[i] = null; } _elementSpace = val.m_elementSpace; for (int j = 0; j < _slots.Length; j++) { GameObject val2 = Object.Instantiate<GameObject>(val.m_elementPrefab, _slotsRoot.transform); val2.transform.localPosition = SlotLocalPosition(j); Transform obj = val2.transform.Find("icon"); Image val3 = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null); if ((Object)(object)val3 == (Object)null) { Object.Destroy((Object)(object)val2); return false; } Transform obj2 = val2.transform.Find("binding"); TMP_Text val4 = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null); if ((Object)(object)val4 != (Object)null) { ((Behaviour)val4).enabled = true; val4.overflowMode = (TextOverflowModes)0; val4.horizontalAlignment = (HorizontalAlignmentOptions)2; val4.fontSize = 11f; val4.autoSizeTextContainer = true; val4.rectTransform.anchoredPosition = new Vector2(28f, -7f); } Transform obj3 = val2.transform.Find("amount"); TMP_Text amount = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null); Transform obj4 = val2.transform.Find("equiped"); GameObject equipped = ((obj4 != null) ? ((Component)obj4).gameObject : null); HideChild(val2, "queued"); HideChild(val2, "selected"); HideChild(val2, "durability"); int slotIndex = j; Button component = val2.GetComponent<Button>(); if ((Object)(object)component != (Object)null) { ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { UseQuiverSlot(slotIndex); }); } _slots[j] = new CachedSlot { Go = val2, Icon = val3, Amount = amount, Binding = val4, Equipped = equipped }; } _appliedOrientation = BetterArchery.QuiverHudLayout.Value; _hasAppliedOrientation = true; _lastGamepad = ZInput.IsGamepadActive(); UpdateBindingLabels(_lastGamepad); _built = true; return true; } private void UpdateBindingLabels(bool gamepad) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _slots.Length; i++) { CachedSlot cachedSlot = _slots[i]; if ((Object)(object)cachedSlot?.Binding == (Object)null) { continue; } if (gamepad) { cachedSlot.Binding.text = string.Empty; continue; } KeyboardShortcut value = BetterArchery.HoldingKeyCode.Value; if (!string.IsNullOrEmpty(((KeyboardShortcut)(ref value)).Serialize())) { value = BetterArchery.HoldingKeyCode.Value; if (!(((KeyboardShortcut)(ref value)).Serialize() == "None")) { TMP_Text binding = cachedSlot.Binding; value = BetterArchery.HoldingKeyCode.Value; binding.text = ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString() + " + " + BetterArchery.GetBindingLabel(i); continue; } } cachedSlot.Binding.text = BetterArchery.GetBindingLabel(i); } } private static void UseQuiverSlot(int index) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ItemData itemAt = ((Humanoid)localPlayer).GetInventory().GetItemAt(index, BetterArchery.GetBonusInventoryRowIndex()); if (itemAt != null) { ((Humanoid)localPlayer).UseItem((Inventory)null, itemAt, false); } } } } [HarmonyPatch(typeof(InventoryGrid), "OnLeftClick")] public static class InventoryGrid_OnLeftClick_Patch { public static bool Prefix(InventoryGrid __instance, UIInputHandler clickHandler) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!BetterArchery.ConfigQuiverEnabled.Value) { return true; } GameObject gameObject = ((Component)clickHandler).gameObject; Vector2i buttonPos = __instance.GetButtonPos(gameObject); ItemData itemAt = __instance.m_inventory.GetItemAt(buttonPos.x, buttonPos.y); if ((Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) && itemAt != null && itemAt.m_equipped && ((Object)itemAt.m_dropPrefab).name.Contains("Quiver")) { MessageHud.instance.ShowMessage((MessageType)2, "$mod_betterarchery_quiver_equipped_error", 0, (Sprite)null, false, true); return false; } return true; } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui", new Type[] { typeof(Player), typeof(ItemData) })] public static class InventoryGrid_UpdateGui_Patch { public static Vector2 customLocation; private static void Postfix(InventoryGrid __instance, Player player, ItemData dragItem, List<InventoryElement> ___m_elements) { if (((Object)__instance).name != "PlayerGrid" || !BetterArchery.ConfigQuiverEnabled.Value || BetterArchery.isInventoryExpansionModPresent) { return; } try { EnsureQuiverRows(__instance); } catch (Exception arg) { BetterArchery.Log($"EnsureQuiverRows failed: {arg}", 0); } try { HideModRows(__instance, ___m_elements); } catch (Exception arg2) { BetterArchery.Log($"HideModRows failed: {arg2}", 0); } try { if (BetterArchery.IsQuiverEquipped()) { CreateQuiverSlots(__instance, ___m_elements); } else { RemoveQuiverSlots(__instance, ___m_elements); } } catch (Exception arg3) { BetterArchery.Log($"Quiver slot handling failed: {arg3}", 0); } } private static void EnsureQuiverRows(InventoryGrid __instance) { Inventory inventory = __instance.GetInventory(); if (inventory != null) { int quiverRowIndex = BetterArchery.QuiverRowIndex; if (quiverRowIndex > 0 && inventory.GetHeight() <= quiverRowIndex) { inventory.SetHeight(quiverRowIndex + 1); BetterArchery.Log($"Restored quiver rows: inventory is now {inventory.GetWidth()}x{inventory.GetHeight()} (quiver row {quiverRowIndex}).", 0); } } } private static void HideModRows(InventoryGrid __instance, List<InventoryElement> ___m_elements) { if (BetterArchery.QuiverRowIndex >= __instance.GetInventory().GetHeight()) { BetterArchery.Log($"refusing to hide rows: quiver row {BetterArchery.QuiverRowIndex} outside {__instance.GetInventory().GetWidth()}x{__instance.GetInventory().GetHeight()}.", 0); return; } if (__instance.GetInventory().GetHeight() > 5) { InventoryElement element = GetElement(___m_elements, 7, __instance.GetInventory().GetHeight() - 1); if (element == null || !((Component)element).gameObject.activeSelf) { return; } for (int i = __instance.GetInventory().GetHeight() - 2; i < __instance.GetInventory().GetHeight(); i++) { for (int j = 0; j < 8; j++) { InventoryElement element2 = GetElement(___m_elements, j, i); if (element2 != null) { ((Component)element2).gameObject.SetActive(false); } } } return; } InventoryElement element3 = GetElement(___m_elements, 7, __instance.GetInventory().GetHeight() - 1); if (element3 == null || !((Component)element3).gameObject.activeSelf) { return; } for (int k = __instance.GetInventory().GetHeight() - 1; k < __instance.GetInventory().GetHeight(); k++) { for (int l = 0; l < 8; l++) { InventoryElement element4 = GetElement(___m_elements, l, k); if (element4 != null) { ((Component)element4).gameObject.SetActive(false); } } } } public static void CreateQuiverSlots(InventoryGrid __instance, List<InventoryElement> ___m_elements) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0236: 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_0418: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0426: 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) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) Vector2 val = (BetterArchery.IsContainerOpen ? BetterArchery.InventoryQuiverSlotLocationWithContainer.Value : BetterArchery.InventoryQuiverSlotLocation.Value); int bonusInventoryRowIndex = BetterArchery.GetBonusInventoryRowIndex(); Transform val2 = ((Component)__instance).transform.parent.Find("QuiverSlotBkg"); if (Object.op_Implicit((Object)(object)val2) && customLocation == val && QuiverSlotsInPlace(__instance, ___m_elements, bonusInventoryRowIndex, val)) { return; } customLocation = (BetterArchery.IsContainerOpen ? BetterArchery.InventoryQuiverSlotLocationWithContainer.Value : BetterArchery.InventoryQuiverSlotLocation.Value); KeyboardShortcut value; if (BetterArchery.hasAuga) { Vector2 val6 = default(Vector2); for (int i = 0; i < 3; i++) { int num = i; InventoryElement element = GetElement(___m_elements, num, bonusInventoryRowIndex); if ((Object)(object)element == (Object)null) { continue; } ((Component)element).gameObject.SetActive(true); Transform val3 = ((Component)element).transform.Find("binding"); TMP_Text val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<TMP_Text>() : null); if ((Object)(object)val4 == (Object)null) { BetterArchery.Log("quiver slot has no 'binding' text child, skipping label styling.", 0); } else { ((Behaviour)val4).enabled = true; val4.overflowMode = (TextOverflowModes)0; val4.fontSize = 11f; val4.autoSizeTextContainer = true; val4.rectTransform.anchoredPosition = new Vector2(1f, 14f); } if ((Object)(object)val4 != (Object)null) { value = BetterArchery.HoldingKeyCode.Value; if (!string.IsNullOrEmpty(((KeyboardShortcut)(ref value)).Serialize())) { value = BetterArchery.HoldingKeyCode.Value; if (!(((KeyboardShortcut)(ref value)).Serialize() == "None")) { value = BetterArchery.HoldingKeyCode.Value; val4.text = ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString() + " + " + BetterArchery.GetBindingLabel(i); goto IL_01fb; } } val4.text = BetterArchery.GetBindingLabel(i); } goto IL_01fb; IL_01fb: Vector2 val5 = customLocation; ((Vector2)(ref val6))..ctor((float)num * __instance.m_elementSpace, 4f * (0f - __instance.m_elementSpace) + 30f); Transform transform = ((Component)element).transform; ((RectTransform)((transform is RectTransform) ? transform : null)).anchoredPosition = val5 + val6; } RectTransform orCreateBackground = GetOrCreateBackground(__instance, "QuiverSlotBkg"); if ((Object)(object)orCreateBackground == (Object)null) { BetterArchery.Log("quiver background unavailable, slots work without backdrop.", 0); return; } orCreateBackground.anchoredPosition = new Vector2(-174f + customLocation.x, -235f + customLocation.y); orCreateBackground.SetSizeWithCurrentAnchors((Axis)0, 235f); orCreateBackground.SetSizeWithCurrentAnchors((Axis)1, 90f); ((Transform)orCreateBackground).localScale = new Vector3(1f, 1f, 1f); return; } Vector2 val10 = default(Vector2); for (int j = 0; j < 3; j++) { int num2 = j; InventoryElement element2 = GetElement(___m_elements, num2, bonusInventoryRowIndex); if ((Object)(object)element2 == (Object)null) { continue; } ((Component)element2).gameObject.SetActive(true); Transform val7 = ((Component)element2).transform.Find("binding"); TMP_Text val8 = (((Object)(object)val7 != (Object)null) ? ((Component)val7).GetComponent<TMP_Text>() : null); if ((Object)(object)val8 == (Object)null) { BetterArchery.Log("quiver slot has no 'binding' text child, skipping label styling.", 0); } else { ((Behaviour)val8).enabled = true; val8.overflowMode = (TextOverflowModes)0; val8.horizontalAlignment = (HorizontalAlignmentOptions)2; val8.fontSize = 11f; val8.autoSizeTextContainer = true; val8.rectTransform.anchoredPosition = new Vector2(28f, -7f); value = BetterArchery.HoldingKeyCode.Value; if (!string.IsNullOrEmpty(((KeyboardShortcut)(ref value)).Serialize())) { value = BetterArchery.HoldingKeyCode.Value; if (!(((KeyboardShortcut)(ref value)).Serialize() == "None")) { value = BetterArchery.HoldingKeyCode.Value; val8.text = ((object)((KeyboardShortcut)(r