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 SakeysPocketDvergr v1.0.0
BepInEx/plugins/Sakey's Pocket Dvergr/Sakey's Pocket Dvergr.dll
Decompiled 3 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Sakey's Pocket Dvergr")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Sakey's Pocket Dvergr")] [assembly: AssemblyTitle("Sakey's Pocket Dvergr")] [assembly: AssemblyVersion("1.0.0.0")] namespace SakeysPocketDverger; [BepInPlugin("com.sakey.pocketdverger", "Sakey's Pocket Dvergr", "0.1.35")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGUID = "com.sakey.pocketdverger"; public const string PluginName = "Sakey's Pocket Dvergr"; public const string PluginVersion = "0.1.35"; private const string ASSET_BUNDLE_NAME = "pocketdvergr"; private const float STAND_DOLL_MODEL_SCALE = 1.5f; private const float STAND_SUPPORT_MODEL_SCALE = 0.25f; private const float STAND_DOLL_MODEL_Y_OFFSET = 0.25f; private const float STAND_SUPPORT_MODEL_Y_OFFSET = 0.18f; private const float WORLD_DOLL_MODEL_SCALE = 1.5f; private const float WORLD_SUPPORT_MODEL_SCALE = 0.25f; public const string ROGUE_DOLL_MODEL = "PokeDve_Rogue"; public const string SUPPORT_DOLL_MODEL = "PokeDve_Support"; public const string MAGE_DOLL_MODEL = "PokeDve_Mage"; private const string ROGUE_ICON = "icon_pokedverogue"; private const string SUPPORT_ICON = "icon_pokedvesupport"; private const string MAGE_ICON = "icon_pokedvemage"; public const string ROGUE_ITEM = "PokeDve_RogueContract"; public const string SUPPORT_ITEM = "PokeDve_SupportContract"; public const string MAGE_ITEM = "PokeDve_MageContract"; public const string ROGUE_BROKEN_ITEM = "PokeDve_RogueBroken"; public const string SUPPORT_BROKEN_ITEM = "PokeDve_SupportBroken"; public const string MAGE_BROKEN_ITEM = "PokeDve_MageBroken"; public const string DVERGR_FAVORITE_ITEM = "PokeDve_DvergrFavorite"; public const string ROGUE_SOURCE = "Dverger"; public const string SUPPORT_SOURCE = "DvergerMageSupport"; public const string MAGE_SOURCE = "DvergerMageIce"; internal static ConfigEntry<KeyboardShortcut> CommandKey; internal static ConfigEntry<int> RoguePrice; internal static ConfigEntry<int> SupportPrice; internal static ConfigEntry<int> MagePrice; internal static ConfigEntry<int> FavoritePrice; internal static ConfigEntry<float> FollowLeashDistance; internal static ConfigEntry<float> FollowTargetDistance; internal static ConfigEntry<float> FollowViewRangeMultiplier; internal static ConfigEntry<float> FollowHearRangeMultiplier; internal static ConfigEntry<bool> EmergencyRecallOnHostility; internal static ItemDrop DvergrFavoriteItem; private AssetBundle pocketBundle; private readonly Dictionary<PocketDvergerType, ItemDrop> activeItems = new Dictionary<PocketDvergerType, ItemDrop>(); private readonly Dictionary<PocketDvergerType, ItemDrop> brokenItems = new Dictionary<PocketDvergerType, ItemDrop>(); private void Awake() { //IL_0005: 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) new Harmony("com.sakey.pocketdverger").PatchAll(); CommandKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "CommandKey", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), "Pocket Dvergr command selection key. F3 cycles Follow/Stay -> Retrieve."); RoguePrice = ((BaseUnityPlugin)this).Config.Bind<int>("Shop - Haldor", "RoguePrice", 1000, "Price of the Dvergr Rogue friend."); SupportPrice = ((BaseUnityPlugin)this).Config.Bind<int>("Shop - Haldor", "SupportPrice", 1000, "Price of the Dvergr Supporter friend."); MagePrice = ((BaseUnityPlugin)this).Config.Bind<int>("Shop - Haldor", "MagePrice", 1000, "Price of the Dvergr Mage friend."); FavoritePrice = ((BaseUnityPlugin)this).Config.Bind<int>("Shop - Haldor", "FavoritePrice", 10, "Price of the Dvergr Favorite."); RoguePrice.SettingChanged += delegate { RefreshHaldorPrice(PocketDvergerType.Rogue, RoguePrice.Value); }; SupportPrice.SettingChanged += delegate { RefreshHaldorPrice(PocketDvergerType.Support, SupportPrice.Value); }; MagePrice.SettingChanged += delegate { RefreshHaldorPrice(PocketDvergerType.Mage, MagePrice.Value); }; FavoritePrice.SettingChanged += delegate { RefreshDvergrFavoritePrice(FavoritePrice.Value); }; FollowLeashDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Follow AI", "MaxFollowLeash", 20f, "Maximum distance in meters from the owner before the companion drops its enemy target and returns. This only applies while Follow is active."); FollowTargetDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Follow AI", "MaxEnemyDistanceFromOwner", 10f, "Maximum distance in meters an enemy may be from the owner while the companion is following. Targets farther away are ignored/dropped."); FollowViewRangeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Follow AI", "ViewRangeMultiplier", 0.65f, "Multiplier for Dvergr sight range while Follow is active. Lower values reduce unnecessary enemy detection."); FollowHearRangeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Follow AI", "HearRangeMultiplier", 0.65f, "Multiplier for Dvergr hearing range while Follow is active. Lower values reduce unnecessary enemy detection."); EmergencyRecallOnHostility = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "EmergencyRecallOnHostility", true, "If a Pocket Dvergr is attacked by its owner or becomes hostile toward its owner, immediately return all active Pocket Dvergrs to their 0-durability dolls."); SetupLocalization(); PrefabManager.OnVanillaPrefabsAvailable += RegisterAll; } private void RegisterAll() { try { LoadAssetBundle(); RegisterActiveItem(PocketDvergerType.Rogue, "PokeDve_RogueContract", "PokeDve_Rogue", "icon_pokedverogue"); RegisterActiveItem(PocketDvergerType.Support, "PokeDve_SupportContract", "PokeDve_Support", "icon_pokedvesupport"); RegisterActiveItem(PocketDvergerType.Mage, "PokeDve_MageContract", "PokeDve_Mage", "icon_pokedvemage"); RegisterBrokenItem(PocketDvergerType.Rogue, "PokeDve_RogueBroken", "PokeDve_Rogue", "icon_pokedverogue"); RegisterBrokenItem(PocketDvergerType.Support, "PokeDve_SupportBroken", "PokeDve_Support", "icon_pokedvesupport"); RegisterBrokenItem(PocketDvergerType.Mage, "PokeDve_MageBroken", "PokeDve_Mage", "icon_pokedvemage"); RegisterDvergrFavorite(); RegisterRepairRecipe(PocketDvergerType.Rogue, "PokeDve_RogueBroken", "PokeDve_RogueContract", "PokeDve_DvergrFavorite"); RegisterRepairRecipe(PocketDvergerType.Support, "PokeDve_SupportBroken", "PokeDve_SupportContract", "PokeDve_DvergrFavorite"); RegisterRepairRecipe(PocketDvergerType.Mage, "PokeDve_MageBroken", "PokeDve_MageContract", "PokeDve_DvergrFavorite"); RegisterCompanionSafe("PokeDve_RogueCompanion", "Dverger", PocketDvergerType.Rogue); RegisterCompanionSafe("PokeDve_SupportCompanion", "DvergerMageSupport", PocketDvergerType.Support); RegisterCompanionSafe("PokeDve_MageCompanion", "DvergerMageIce", PocketDvergerType.Mage); AddActiveItemsToHaldor(); AddDvergrFavoriteToHaldor(); Logger.LogInfo((object)"Pocket Dverger: registration completed."); } catch (Exception arg) { Logger.LogError((object)$"Pocket Dverger registration failed: {arg}"); } finally { PrefabManager.OnVanillaPrefabsAvailable -= RegisterAll; } } private void LoadAssetBundle() { string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty, "pocketdvergr"); pocketBundle = AssetBundle.LoadFromFile(text); if ((Object)(object)pocketBundle == (Object)null) { throw new InvalidOperationException("Pocket Dverger AssetBundle could not be loaded: " + text); } Logger.LogInfo((object)("Pocket Dverger: AssetBundle loaded: " + text)); } private GameObject LoadDollModel(string assetName) { if ((Object)(object)pocketBundle == (Object)null) { throw new InvalidOperationException("Pocket Dverger AssetBundle is not loaded."); } GameObject obj = pocketBundle.LoadAsset<GameObject>(assetName); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("Pocket Dverger model not found in AssetBundle: " + assetName); } return obj; } private Sprite LoadIcon(string assetName) { if ((Object)(object)pocketBundle == (Object)null) { throw new InvalidOperationException("Pocket Dverger AssetBundle is not loaded."); } Sprite obj = pocketBundle.LoadAsset<Sprite>(assetName); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("Pocket Dverger icon not found in AssetBundle: " + assetName); } return obj; } private void AddDollVisual(GameObject itemPrefab, string modelName, string iconName) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) Sprite val = LoadIcon(iconName); GameObject obj = LoadDollModel(modelName); Transform val2 = itemPrefab.transform.Find("attach"); if ((Object)(object)val2 == (Object)null) { val2 = new GameObject("attach").transform; val2.SetParent(itemPrefab.transform, false); } GameObject val3 = Object.Instantiate<GameObject>(obj, val2); ((Object)val3).name = modelName; val3.transform.localRotation = Quaternion.Euler(0f, 180f, 0f); float num = ((modelName == "PokeDve_Support") ? 0.25f : 1.5f); val3.transform.localScale = Vector3.one * num; float num2 = ((modelName == "PokeDve_Support") ? 0.18f : 0.25f); val3.transform.localPosition = new Vector3(0f, num2, 0f); PrepareDollRenderers(val3); GameObject val4 = Object.Instantiate<GameObject>(obj, itemPrefab.transform); ((Object)val4).name = "worldVisual"; val4.transform.localRotation = Quaternion.Euler(0f, 180f, 0f); float num3 = ((modelName == "PokeDve_Support") ? 0.25f : 1.5f); val4.transform.localScale = Vector3.one * num3; val4.transform.localPosition = Vector3.zero; PrepareDollRenderers(val4); val4.SetActive(false); PocketDvergerWorldVisual pocketDvergerWorldVisual = itemPrefab.GetComponent<PocketDvergerWorldVisual>(); if ((Object)(object)pocketDvergerWorldVisual == (Object)null) { pocketDvergerWorldVisual = itemPrefab.AddComponent<PocketDvergerWorldVisual>(); } pocketDvergerWorldVisual.AttachRoot = ((Component)val2).gameObject; pocketDvergerWorldVisual.WorldVisual = val4; ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { throw new InvalidOperationException("ItemDrop/SharedData missing on " + ((Object)itemPrefab).name); } component.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val }; component.m_itemData.m_variant = 0; } private void PrepareDollRenderers(GameObject model) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Custom/Creature"); Shader val2 = Shader.Find("Standard"); Renderer[] componentsInChildren = model.GetComponentsInChildren<Renderer>(true); Collider[] componentsInChildren2; foreach (Renderer val3 in componentsInChildren) { if (val3 is ParticleSystemRenderer) { val3.enabled = false; continue; } Collider component = ((Component)val3).GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { component.enabled = false; } componentsInChildren2 = ((Component)val3).GetComponentsInChildren<Collider>(true); for (int j = 0; j < componentsInChildren2.Length; j++) { componentsInChildren2[j].enabled = false; } Material[] sharedMaterials = val3.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int k = 0; k < sharedMaterials.Length; k++) { Material val4 = sharedMaterials[k]; if ((Object)(object)val4 == (Object)null) { array[k] = null; continue; } Shader val5 = (((Object)(object)val != (Object)null) ? val : val2); if ((Object)(object)val5 == (Object)null) { array[k] = val4; continue; } Material val6 = new Material(val5); ((Object)val6).name = ((Object)val4).name + "_PocketDvergrRuntime"; Texture val7 = null; if (val4.HasProperty("_MainTex")) { val7 = val4.GetTexture("_MainTex"); } else if (val4.HasProperty("_BaseMap")) { val7 = val4.GetTexture("_BaseMap"); } if ((Object)(object)val7 != (Object)null && val6.HasProperty("_MainTex")) { val6.SetTexture("_MainTex", val7); } if (val4.HasProperty("_Color") && val6.HasProperty("_Color")) { val6.SetColor("_Color", val4.GetColor("_Color")); } if (val4.HasProperty("_EmissionColor") && val6.HasProperty("_EmissionColor")) { val6.SetColor("_EmissionColor", val4.GetColor("_EmissionColor")); } array[k] = val6; } val3.sharedMaterials = array; } componentsInChildren2 = model.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = false; } } private CustomItem CreateEmptyItem(string prefabName) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) CustomItem val = new CustomItem(prefabName, true); if ((Object)(object)val.ItemDrop == (Object)null) { throw new InvalidOperationException("CustomItem created without ItemDrop: " + prefabName); } GameObject itemPrefab = val.ItemPrefab; Renderer[] components = itemPrefab.GetComponents<Renderer>(); for (int i = 0; i < components.Length; i++) { components[i].enabled = false; } if ((Object)(object)itemPrefab.GetComponent<Rigidbody>() == (Object)null) { Rigidbody obj = itemPrefab.AddComponent<Rigidbody>(); obj.mass = 0.1f; obj.useGravity = true; obj.isKinematic = false; obj.detectCollisions = true; obj.interpolation = (RigidbodyInterpolation)1; obj.collisionDetectionMode = (CollisionDetectionMode)2; } if ((Object)(object)itemPrefab.GetComponent<ZNetView>() == (Object)null) { itemPrefab.AddComponent<ZNetView>().m_persistent = true; } if ((Object)(object)itemPrefab.GetComponent<ZSyncTransform>() == (Object)null) { itemPrefab.AddComponent<ZSyncTransform>(); } if ((Object)(object)itemPrefab.GetComponent<Collider>() == (Object)null) { SphereCollider obj2 = itemPrefab.AddComponent<SphereCollider>(); obj2.radius = 0.15f; obj2.center = new Vector3(0f, 0.05f, 0f); } int num = LayerMask.NameToLayer("item"); if (num >= 0) { itemPrefab.layer = num; } return val; } private void RegisterActiveItem(PocketDvergerType type, string prefabName, string modelName, string iconName) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) CustomItem val = CreateEmptyItem(prefabName); ItemDrop itemDrop = val.ItemDrop; SharedData shared = itemDrop.m_itemData.m_shared; shared.m_name = GetActiveName(type); shared.m_description = GetActiveDescription(type); shared.m_itemType = (ItemType)16; shared.m_maxStackSize = 1; shared.m_weight = 1f; shared.m_questItem = false; shared.m_trophyPos = Vector2Int.zero; shared.m_useDurability = false; shared.m_maxDurability = 0f; shared.m_durabilityPerLevel = 0f; shared.m_destroyBroken = false; shared.m_canBeReparied = false; shared.m_movementModifier = 0f; AddDollVisual(val.ItemPrefab, modelName, iconName); itemDrop.m_itemData.m_dropPrefab = val.ItemPrefab; if (!ItemManager.Instance.AddItem(val)) { throw new InvalidOperationException("Failed to register active item: " + prefabName); } activeItems[type] = itemDrop; Logger.LogInfo((object)("Pocket Dverger: active item registered: " + prefabName)); } private void RegisterBrokenItem(PocketDvergerType type, string prefabName, string modelName, string iconName) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) CustomItem val = CreateEmptyItem(prefabName); ItemDrop itemDrop = val.ItemDrop; SharedData shared = itemDrop.m_itemData.m_shared; shared.m_name = GetBrokenName(type); shared.m_description = GetBrokenDescription(type); shared.m_itemType = (ItemType)16; shared.m_maxStackSize = 20; shared.m_weight = 1f; shared.m_questItem = false; shared.m_trophyPos = Vector2Int.zero; shared.m_useDurability = true; shared.m_maxDurability = 100f; shared.m_durabilityPerLevel = 0f; shared.m_destroyBroken = false; shared.m_canBeReparied = false; shared.m_movementModifier = 0f; AddDollVisual(val.ItemPrefab, modelName, iconName); itemDrop.m_itemData.m_durability = 0f; itemDrop.m_itemData.m_dropPrefab = val.ItemPrefab; if (!ItemManager.Instance.AddItem(val)) { throw new InvalidOperationException("Failed to register broken item: " + prefabName); } brokenItems[type] = itemDrop; Logger.LogInfo((object)("Pocket Dverger: broken item registered: " + prefabName)); } private void RegisterDvergrFavorite() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) CustomItem val = new CustomItem("PokeDve_DvergrFavorite", "Sausages"); ItemDrop itemDrop = val.ItemDrop; if ((Object)(object)itemDrop == (Object)null || itemDrop.m_itemData == null || itemDrop.m_itemData.m_shared == null) { throw new InvalidOperationException("Dvergr favorite item could not be cloned from Sausages."); } SharedData shared = itemDrop.m_itemData.m_shared; shared.m_name = "$SakeysPocketDverger_FavoriteName"; shared.m_description = "$SakeysPocketDverger_FavoriteDesc"; shared.m_itemType = (ItemType)2; shared.m_maxStackSize = 20; shared.m_consumeStatusEffect = null; shared.m_attackStatusEffect = null; shared.m_equipStatusEffect = null; shared.m_setStatusEffect = null; itemDrop.m_itemData.m_dropPrefab = val.ItemPrefab; if (!ItemManager.Instance.AddItem(val)) { throw new InvalidOperationException("Failed to register Dvergr favorite item."); } DvergrFavoriteItem = itemDrop; } private void AddActiveItemsToHaldor() { GameObject prefab = PrefabManager.Instance.GetPrefab("Haldor"); Trader val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Trader>() : null); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("Haldor Trader not found."); } if (val.m_items == null) { val.m_items = new List<TradeItem>(); } if (val.m_useItems == null) { val.m_useItems = new List<TraderUseItem>(); } AddTraderItem(val, PocketDvergerType.Rogue, RoguePrice.Value); AddTraderItem(val, PocketDvergerType.Support, SupportPrice.Value); AddTraderItem(val, PocketDvergerType.Mage, MagePrice.Value); SanitizeTraderItems(val); } private void AddTraderItem(Trader trader, PocketDvergerType type, int price) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown if (!((Object)(object)trader == (Object)null) && trader.m_items != null) { if (!activeItems.TryGetValue(type, out var item) || (Object)(object)item == (Object)null) { throw new InvalidOperationException($"Active item missing for {type}"); } if (!trader.m_items.Any((TradeItem x) => x != null && (Object)(object)x.m_prefab == (Object)(object)item)) { Sprite safeIcon = GetSafeIcon(item); trader.m_items.Add(new TradeItem { m_prefab = item, m_stack = 1, m_price = Mathf.Max(0, price), m_requiredGlobalKey = string.Empty, m_levelUpEffect = false, m_buyPlayerEffects = new EffectList(), m_icon = safeIcon, m_name = (item.m_itemData.m_shared.m_name ?? string.Empty), m_tooltip = (item.m_itemData.m_shared.m_description ?? string.Empty), m_buyKey = string.Empty, m_incrementKey = string.Empty, m_incrementAmount = 0 }); } } } private void RefreshHaldorPrice(PocketDvergerType type, int price) { GameObject val = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("Haldor") : null); Trader val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Trader>() : null); if ((Object)(object)val2 == (Object)null) { return; } EnsureHaldorRuntimeLists(val2); if (activeItems.TryGetValue(type, out var item) && !((Object)(object)item == (Object)null)) { TradeItem val3 = ((IEnumerable<TradeItem>)val2.m_items).FirstOrDefault((Func<TradeItem, bool>)((TradeItem x) => x != null && (Object)(object)x.m_prefab == (Object)(object)item)); if (val3 != null) { val3.m_price = Mathf.Max(0, price); } SanitizeTraderItems(val2); } } private static Sprite GetSafeIcon(ItemDrop item) { if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_shared == null) { return null; } Sprite[] icons = item.m_itemData.m_shared.m_icons; if (icons == null || icons.Length == 0) { return null; } int num = item.m_itemData.m_variant; if (num < 0 || num >= icons.Length) { num = 0; } return icons[num]; } internal static void EnsureHaldorRuntimeListsForHarmony(Trader trader) { if (!((Object)(object)trader == (Object)null)) { if (trader.m_items == null) { trader.m_items = new List<TradeItem>(); } if (trader.m_useItems == null) { trader.m_useItems = new List<TraderUseItem>(); } } } internal static void SanitizeTraderItems(Trader trader) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown if ((Object)(object)trader == (Object)null || trader.m_items == null) { return; } foreach (TradeItem item in trader.m_items) { if (item == null) { continue; } if (item.m_requiredGlobalKey == null) { item.m_requiredGlobalKey = string.Empty; } if (item.m_buyPlayerEffects == null) { item.m_buyPlayerEffects = new EffectList(); } if (item.m_buyKey == null) { item.m_buyKey = string.Empty; } if (item.m_incrementKey == null) { item.m_incrementKey = string.Empty; } if ((Object)(object)item.m_prefab != (Object)null && item.m_prefab.m_itemData != null && item.m_prefab.m_itemData.m_shared != null) { if (item.m_name == null) { item.m_name = item.m_prefab.m_itemData.m_shared.m_name ?? string.Empty; } if (item.m_tooltip == null) { item.m_tooltip = item.m_prefab.m_itemData.m_shared.m_description ?? string.Empty; } if ((Object)(object)item.m_icon == (Object)null) { item.m_icon = GetSafeIcon(item.m_prefab); } } else { if (item.m_name == null) { item.m_name = string.Empty; } if (item.m_tooltip == null) { item.m_tooltip = string.Empty; } } } } private void AddDvergrFavoriteToHaldor() { //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Expected O, but got Unknown GameObject prefab = PrefabManager.Instance.GetPrefab("Haldor"); Trader val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Trader>() : null); if ((Object)(object)val == (Object)null) { Logger.LogError((object)"Pocket Dvergr: Haldor Trader component not found."); return; } EnsureHaldorRuntimeLists(val); ItemDrop item = DvergrFavoriteItem; if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_shared == null) { Logger.LogError((object)"Pocket Dvergr: Dvergr Favorite ItemDrop is missing."); return; } TradeItem val2 = ((IEnumerable<TradeItem>)val.m_items).FirstOrDefault((Func<TradeItem, bool>)((TradeItem x) => x != null && (Object)(object)x.m_prefab == (Object)(object)item)); if (val2 != null) { val2.m_price = Mathf.Max(0, FavoritePrice.Value); val2.m_stack = 1; val2.m_requiredGlobalKey = string.Empty; val2.m_levelUpEffect = false; val2.m_buyPlayerEffects = (EffectList)(((object)val2.m_buyPlayerEffects) ?? ((object)new EffectList())); val2.m_icon = GetSafeIcon(item); val2.m_name = item.m_itemData.m_shared.m_name ?? string.Empty; val2.m_tooltip = item.m_itemData.m_shared.m_description ?? string.Empty; val2.m_buyKey = val2.m_buyKey ?? string.Empty; val2.m_incrementKey = val2.m_incrementKey ?? string.Empty; val2.m_incrementAmount = 0; SanitizeTraderItems(val); } else { val.m_items.Add(new TradeItem { m_prefab = item, m_stack = 1, m_price = Mathf.Max(0, FavoritePrice.Value), m_requiredGlobalKey = string.Empty, m_levelUpEffect = false, m_buyPlayerEffects = new EffectList(), m_icon = GetSafeIcon(item), m_name = (item.m_itemData.m_shared.m_name ?? string.Empty), m_tooltip = (item.m_itemData.m_shared.m_description ?? string.Empty), m_buyKey = string.Empty, m_incrementKey = string.Empty, m_incrementAmount = 0 }); SanitizeTraderItems(val); Logger.LogInfo((object)$"Pocket Dvergr: Dvergr Favorite added to Haldor for {FavoritePrice.Value} coins."); } } private void RefreshDvergrFavoritePrice(int price) { GameObject val = ((PrefabManager.Instance != null) ? PrefabManager.Instance.GetPrefab("Haldor") : null); Trader val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Trader>() : null); if (!((Object)(object)val2 == (Object)null) && val2.m_items != null && !((Object)(object)DvergrFavoriteItem == (Object)null)) { TradeItem val3 = ((IEnumerable<TradeItem>)val2.m_items).FirstOrDefault((Func<TradeItem, bool>)((TradeItem x) => x != null && (Object)(object)x.m_prefab == (Object)(object)DvergrFavoriteItem)); if (val3 != null) { val3.m_price = Mathf.Max(0, price); } EnsureHaldorRuntimeLists(val2); SanitizeTraderItems(val2); } } private static void EnsureHaldorRuntimeLists(Trader trader) { if (!((Object)(object)trader == (Object)null)) { if (trader.m_items == null) { trader.m_items = new List<TradeItem>(); } if (trader.m_useItems == null) { trader.m_useItems = new List<TraderUseItem>(); } } } private void RegisterRepairRecipe(PocketDvergerType type, string brokenPrefab, string repairedPrefab, string materialPrefab) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_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_003c: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown RecipeConfig val = new RecipeConfig { Name = $"SakeysPocketDverger_Repair_{type}", Item = repairedPrefab, Amount = 1, CraftingStation = "piece_workbench", MinStationLevel = 1 }; val.AddRequirement(brokenPrefab, 1, 0); val.AddRequirement(materialPrefab, 1, 0); if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val))) { throw new InvalidOperationException($"Failed to register repair recipe for {type}"); } Logger.LogInfo((object)$"Pocket Dverger: repair recipe registered: {type} + {materialPrefab}"); } private void RegisterCompanionSafe(string newPrefabName, string sourcePrefabName, PocketDvergerType type) { try { RegisterCompanion(newPrefabName, sourcePrefabName, type); } catch (Exception arg) { Logger.LogError((object)$"Pocket Dverger: companion registration failed: {newPrefabName}: {arg}"); } } private void RegisterCompanion(string newPrefabName, string sourcePrefabName, PocketDvergerType type) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_0119: Expected O, but got Unknown if (!((Object)(object)PrefabManager.Instance.GetPrefab(newPrefabName) != (Object)null)) { if ((Object)(object)PrefabManager.Instance.GetPrefab(sourcePrefabName) == (Object)null) { throw new InvalidOperationException("Source companion prefab not found: " + sourcePrefabName); } GameObject val = PrefabManager.Instance.CreateClonedPrefab(newPrefabName, sourcePrefabName); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("Failed to clone " + sourcePrefabName); } Humanoid component = val.GetComponent<Humanoid>(); if ((Object)(object)component != (Object)null) { ((Character)component).m_faction = (Faction)0; ((Character)component).m_name = GetCompanionName(type); } Character component2 = val.GetComponent<Character>(); if ((Object)(object)component2 != (Object)null) { component2.m_faction = (Faction)0; } Tameable component3 = val.GetComponent<Tameable>(); if ((Object)(object)component3 != (Object)null) { Object.DestroyImmediate((Object)(object)component3); } CharacterDrop component4 = val.GetComponent<CharacterDrop>(); if ((Object)(object)component4 != (Object)null) { component4.m_drops.Clear(); } NpcTalk component5 = val.GetComponent<NpcTalk>(); if ((Object)(object)component5 != (Object)null) { Object.DestroyImmediate((Object)(object)component5); } PocketDvergerCompanion pocketDvergerCompanion = val.GetComponent<PocketDvergerCompanion>(); if ((Object)(object)pocketDvergerCompanion == (Object)null) { pocketDvergerCompanion = val.AddComponent<PocketDvergerCompanion>(); } pocketDvergerCompanion.CompanionType = type; PrefabManager.Instance.AddPrefab(new CustomPrefab(val, true)); PrefabManager.Instance.RegisterToZNetScene(val); Logger.LogInfo((object)("Pocket Dverger: companion registered: " + newPrefabName + " from " + sourcePrefabName)); } } private void SetupLocalization() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "Japanese"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "SakeysPocketDverger_RogueName", "お友達のドヴェルグ" }, { "SakeysPocketDverger_SupportName", "お友達のサポーター" }, { "SakeysPocketDverger_MageName", "お友達のメイジ" }, { "SakeysPocketDverger_RogueDollName", "ドヴェルグのならず者の人形" }, { "SakeysPocketDverger_SupportDollName", "ドヴェルグのサポートの人形" }, { "SakeysPocketDverger_MageDollName", "ドヴェルグの魔術師の人形" }, { "SakeysPocketDverger_ModeFollow", "追従/待機" }, { "SakeysPocketDverger_ModeRetrieve", "回収" }, { "SakeysPocketDverger_RogueDesc", "ドヴェルグが封印されてる人形。お友達が出てくる。怒らせてはいけない。" }, { "SakeysPocketDverger_SupportDesc", "ドヴェルグが封印されてる人形。お友達が出てくる。怒らせてはいけない。" }, { "SakeysPocketDverger_MageDesc", "ドヴェルグが封印されてる人形。お友達が出てくる。怒らせてはいけない。" }, { "SakeysPocketDverger_RogueBrokenName", "ドヴェルグのならず者の人形" }, { "SakeysPocketDverger_SupportBrokenName", "ドヴェルグのサポートの人形" }, { "SakeysPocketDverger_MageBrokenName", "ドヴェルグの魔術師の人形" }, { "SakeysPocketDverger_RogueBrokenDesc", "ドヴェルグが人形になって戻ってこないときは、作業台でドヴェルグの好物をあげてみよう。きっと帰ってくる。" }, { "SakeysPocketDverger_SupportBrokenDesc", "ドヴェルグが人形になって戻ってこないときは、作業台でドヴェルグの好物をあげてみよう。きっと帰ってくる。" }, { "SakeysPocketDverger_MageBrokenDesc", "ドヴェルグが人形になって戻ってこないときは、作業台でドヴェルグの好物をあげてみよう。きっと帰ってくる。" }, { "SakeysPocketDverger_FavoriteName", "ドヴェルグの好物" }, { "SakeysPocketDverger_FavoriteDesc", "ドヴェルグの好物。人形になって戻ってこないときは、作業台でこれをあげてみよう。きっと帰ってくる。" }, { "SakeysPocketDverger_EmergencyRecall", "ドヴェルグが敵対したため、人形に戻った。" }, { "SakeysPocketDverger_AlreadyOut", "このお友達はすでに一緒に旅をしている。" }, { "SakeysPocketDverger_Follow", "ドヴェルグがついてくる。" }, { "SakeysPocketDverger_Stay", "ドヴェルグがここで待機する。" }, { "SakeysPocketDverger_Retrieved", "ドヴェルグを人形に戻した。" }, { "SakeysPocketDverger_RogueFollow", "ドヴェルグがついてくる。" }, { "SakeysPocketDverger_RogueStay", "ドヴェルグがここで待機する。" }, { "SakeysPocketDverger_RogueRetrieved", "ドヴェルグを人形に戻した。" }, { "SakeysPocketDverger_SupportFollow", "サポートドヴェルグがついてくる。" }, { "SakeysPocketDverger_SupportStay", "サポートドヴェルグがここで待機する。" }, { "SakeysPocketDverger_SupportRetrieved", "サポートドヴェルグを人形に戻した。" }, { "SakeysPocketDverger_MageFollow", "メイジドヴェルグがついてくる。" }, { "SakeysPocketDverger_MageStay", "メイジドヴェルグがここで待機する。" }, { "SakeysPocketDverger_MageRetrieved", "メイジドヴェルグを人形に戻した。" }, { "SakeysPocketDverger_Hover", "<color=yellow>$SakeysPocketDverger_DisplayName</color>" }, { "SakeysPocketDverger_DisplayName", "お友達" } }); text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "SakeysPocketDverger_RogueName", "Your Dvergr Friend" }, { "SakeysPocketDverger_SupportName", "Your Supporter Friend" }, { "SakeysPocketDverger_MageName", "Your Mage Friend" }, { "SakeysPocketDverger_RogueDollName", "Dvergr Rogue Doll" }, { "SakeysPocketDverger_SupportDollName", "Dvergr Support Doll" }, { "SakeysPocketDverger_MageDollName", "Dvergr Mage Doll" }, { "SakeysPocketDverger_ModeFollow", "Follow / Stay" }, { "SakeysPocketDverger_ModeRetrieve", "Retrieve" }, { "SakeysPocketDverger_RogueDesc", "A Dvergr is sealed inside. Your friend will come out. Don't make them angry." }, { "SakeysPocketDverger_SupportDesc", "A Dvergr is sealed inside. Your friend will come out. Don't make them angry." }, { "SakeysPocketDverger_MageDesc", "A Dvergr is sealed inside. Your friend will come out. Don't make them angry." }, { "SakeysPocketDverger_RogueBrokenName", "Dvergr Rogue Doll" }, { "SakeysPocketDverger_SupportBrokenName", "Dvergr Support Doll" }, { "SakeysPocketDverger_MageBrokenName", "Dvergr Mage Doll" }, { "SakeysPocketDverger_RogueBrokenDesc", "If your Dvergr has returned to its doll and will not come back, try giving it a Dvergr Favorite at a workbench. It will surely return." }, { "SakeysPocketDverger_SupportBrokenDesc", "If your Dvergr has returned to its doll and will not come back, try giving it a Dvergr Favorite at a workbench. It will surely return." }, { "SakeysPocketDverger_MageBrokenDesc", "If your Dvergr has returned to its doll and will not come back, try giving it a Dvergr Favorite at a workbench. It will surely return." }, { "SakeysPocketDverger_FavoriteName", "Dvergr Favorite" }, { "SakeysPocketDverger_FavoriteDesc", "A Dvergr favorite. If your doll does not come back, give this to it at a workbench. It will surely return." }, { "SakeysPocketDverger_EmergencyRecall", "The Dvergr became hostile, so they returned to their dolls." }, { "SakeysPocketDverger_AlreadyOut", "This friend is already traveling with you." }, { "SakeysPocketDverger_Follow", "The Dvergr will follow you." }, { "SakeysPocketDverger_Stay", "The Dvergr will stay here." }, { "SakeysPocketDverger_Retrieved", "The Dvergr has been returned to the doll." }, { "SakeysPocketDverger_RogueFollow", "The Dvergr will follow you." }, { "SakeysPocketDverger_RogueStay", "The Dvergr will stay here." }, { "SakeysPocketDverger_RogueRetrieved", "The Dvergr has been returned to the doll." }, { "SakeysPocketDverger_SupportFollow", "The Support Dvergr will follow you." }, { "SakeysPocketDverger_SupportStay", "The Support Dvergr will stay here." }, { "SakeysPocketDverger_SupportRetrieved", "The Support Dvergr has been returned to the doll." }, { "SakeysPocketDverger_MageFollow", "The Mage Dvergr will follow you." }, { "SakeysPocketDverger_MageStay", "The Mage Dvergr will stay here." }, { "SakeysPocketDverger_MageRetrieved", "The Mage Dvergr has been returned to the doll." }, { "SakeysPocketDverger_Hover", "<color=yellow>$SakeysPocketDverger_DisplayName</color>" }, { "SakeysPocketDverger_DisplayName", "Friend" } }); } internal static string GetCompanionName(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "$SakeysPocketDverger_RogueName", PocketDvergerType.Support => "$SakeysPocketDverger_SupportName", _ => "$SakeysPocketDverger_MageName", }; } internal static string GetFollowMessage(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "$SakeysPocketDverger_RogueFollow", PocketDvergerType.Support => "$SakeysPocketDverger_SupportFollow", _ => "$SakeysPocketDverger_MageFollow", }; } internal static string GetStayMessage(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "$SakeysPocketDverger_RogueStay", PocketDvergerType.Support => "$SakeysPocketDverger_SupportStay", _ => "$SakeysPocketDverger_MageStay", }; } internal static string GetRetrievedMessage(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "$SakeysPocketDverger_RogueRetrieved", PocketDvergerType.Support => "$SakeysPocketDverger_SupportRetrieved", _ => "$SakeysPocketDverger_MageRetrieved", }; } internal static string GetActiveName(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "$SakeysPocketDverger_RogueDollName", PocketDvergerType.Support => "$SakeysPocketDverger_SupportDollName", _ => "$SakeysPocketDverger_MageDollName", }; } internal static string GetActiveDescription(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "$SakeysPocketDverger_RogueDesc", PocketDvergerType.Support => "$SakeysPocketDverger_SupportDesc", _ => "$SakeysPocketDverger_MageDesc", }; } internal static string GetBrokenName(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "$SakeysPocketDverger_RogueBrokenName", PocketDvergerType.Support => "$SakeysPocketDverger_SupportBrokenName", _ => "$SakeysPocketDverger_MageBrokenName", }; } internal static string GetBrokenDescription(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "$SakeysPocketDverger_RogueBrokenDesc", PocketDvergerType.Support => "$SakeysPocketDverger_SupportBrokenDesc", _ => "$SakeysPocketDverger_MageBrokenDesc", }; } internal static string GetActivePrefab(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "PokeDve_RogueContract", PocketDvergerType.Support => "PokeDve_SupportContract", _ => "PokeDve_MageContract", }; } internal static string GetBrokenPrefab(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "PokeDve_RogueBroken", PocketDvergerType.Support => "PokeDve_SupportBroken", _ => "PokeDve_MageBroken", }; } internal static string GetCompanionPrefab(PocketDvergerType type) { return type switch { PocketDvergerType.Rogue => "PokeDve_RogueCompanion", PocketDvergerType.Support => "PokeDve_SupportCompanion", _ => "PokeDve_MageCompanion", }; } private static IEnumerable<ZDO> GetLoadedZDOs() { if (ZDOMan.instance == null) { yield break; } FieldInfo field = typeof(ZDOMan).GetField("m_objectsByID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || !(field.GetValue(ZDOMan.instance) is IDictionary dictionary)) { yield break; } foreach (DictionaryEntry item in dictionary) { object? value = item.Value; ZDO val = (ZDO)((value is ZDO) ? value : null); if (val != null) { yield return val; } } } internal static bool TryGetActive(long ownerId, PocketDvergerType type, out PocketDvergerCompanion found) { found = null; PocketDvergerCompanion[] array = Object.FindObjectsOfType<PocketDvergerCompanion>(); foreach (PocketDvergerCompanion pocketDvergerCompanion in array) { if (!((Object)(object)pocketDvergerCompanion == (Object)null) && pocketDvergerCompanion.GetOwnerID() == ownerId && pocketDvergerCompanion.CompanionType == type) { found = pocketDvergerCompanion; return true; } } return false; } } internal class PocketDvergerWorldVisual : MonoBehaviour { public GameObject AttachRoot; public GameObject WorldVisual; private void Start() { if ((Object)(object)AttachRoot != (Object)null) { AttachRoot.SetActive(false); } if ((Object)(object)WorldVisual != (Object)null) { WorldVisual.SetActive(true); } } } public enum PocketDvergerType { Rogue, Support, Mage } public static class PocketDvergerContractUse { public static bool TrySummon(Player owner, PocketDvergerType contractType, ItemData item, out PocketDvergerCompanion spawnedCompanion) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) spawnedCompanion = null; if ((Object)(object)owner == (Object)null || item == null) { return false; } if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return false; } GameObject prefab = PrefabManager.Instance.GetPrefab(Plugin.GetCompanionPrefab(contractType)); if ((Object)(object)prefab == (Object)null) { Logger.LogError((object)$"Pocket Dvergr companion prefab missing: {contractType}"); return false; } Vector3 val = ((Component)owner).transform.position + ((Component)owner).transform.forward * 1.2f + Vector3.up * 0.1f; GameObject val2 = Object.Instantiate<GameObject>(prefab, val, ((Component)owner).transform.rotation); if ((Object)(object)val2 == (Object)null) { return false; } ZNetView component = val2.GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { Object.Destroy((Object)(object)val2); return false; } ZDO zDO = component.GetZDO(); if (zDO == null) { Object.Destroy((Object)(object)val2); return false; } zDO.Set("SakeysPocketDverger_Owner", owner.GetPlayerID()); zDO.Set("SakeysPocketDverger_Type", (int)contractType); zDO.Set("SakeysPocketDverger_Contract", Plugin.GetActivePrefab(contractType)); PocketDvergerCompanion pocketDvergerCompanion = val2.GetComponent<PocketDvergerCompanion>(); if ((Object)(object)pocketDvergerCompanion == (Object)null) { pocketDvergerCompanion = val2.AddComponent<PocketDvergerCompanion>(); } pocketDvergerCompanion.CompanionType = contractType; pocketDvergerCompanion.Initialize(owner.GetPlayerID()); spawnedCompanion = pocketDvergerCompanion; return true; } } internal static class PocketDvergerUseHelper { public enum InventorySummonResult { NotPocketDvergr, Summoned, Failed } public static bool TryGetContractType(ItemData item, out PocketDvergerType type) { type = PocketDvergerType.Rogue; if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return false; } switch (((Object)item.m_dropPrefab).name) { case "PokeDve_RogueContract": type = PocketDvergerType.Rogue; return true; case "PokeDve_SupportContract": type = PocketDvergerType.Support; return true; case "PokeDve_MageContract": type = PocketDvergerType.Mage; return true; default: return false; } } public static bool IsOnItemStand(Player player) { if ((Object)(object)player == (Object)null) { return false; } GameObject hoverObject = ((Humanoid)player).GetHoverObject(); if ((Object)(object)hoverObject != (Object)null) { return (Object)(object)hoverObject.GetComponentInParent<ItemStand>() != (Object)null; } return false; } public static InventorySummonResult TrySummonFromInventory(Player player, Inventory inventory, ItemData item) { if ((Object)(object)player == (Object)null || item == null) { return InventorySummonResult.Failed; } if (!TryGetContractType(item, out var type)) { return InventorySummonResult.NotPocketDvergr; } Inventory val = inventory ?? ((Humanoid)player).GetInventory(); if (val == null || !val.ContainsItem(item)) { return InventorySummonResult.Failed; } if (!PocketDvergerContractUse.TrySummon(player, type, item, out var spawnedCompanion)) { return InventorySummonResult.Failed; } if (!val.RemoveOneItem(item)) { Logger.LogError((object)"Pocket Dvergr: companion summoned but contract item could not be removed."); if ((Object)(object)spawnedCompanion != (Object)null) { if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)spawnedCompanion).gameObject); } else { Object.Destroy((Object)(object)((Component)spawnedCompanion).gameObject); } } return InventorySummonResult.Failed; } return InventorySummonResult.Summoned; } } [HarmonyPatch(typeof(Humanoid), "DropItem", new Type[] { typeof(Inventory), typeof(ItemData), typeof(int) })] internal static class PocketDvergerHumanoidDropItemPatch { private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, int amount) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null || item == null || inventory == null) { return true; } if (amount != 1) { return true; } if (!PocketDvergerUseHelper.TryGetContractType(item, out var _)) { return true; } return PocketDvergerUseHelper.TrySummonFromInventory(val, inventory, item) != PocketDvergerUseHelper.InventorySummonResult.Summoned; } } [HarmonyPatch(typeof(Trader), "OnBought")] internal static class PocketDvergerHaldorOnBoughtPatch { private static void Prefix(Trader __instance) { if (!((Object)(object)__instance == (Object)null) && string.Equals(((Object)((Component)__instance).gameObject).name.Replace("(Clone)", "").Trim(), "Haldor", StringComparison.OrdinalIgnoreCase)) { Plugin.EnsureHaldorRuntimeListsForHarmony(__instance); Plugin.SanitizeTraderItems(__instance); } } } [HarmonyPatch(typeof(StoreGui), "FillList")] internal static class PocketDvergerStoreGuiFillListPatch { private static void Prefix(StoreGui __instance) { if ((Object)(object)__instance == (Object)null) { return; } try { Trader value = Traverse.Create((object)__instance).Field("m_trader").GetValue<Trader>(); if ((Object)(object)value != (Object)null && string.Equals(((Object)((Component)value).gameObject).name.Replace("(Clone)", "").Trim(), "Haldor", StringComparison.OrdinalIgnoreCase)) { Plugin.EnsureHaldorRuntimeListsForHarmony(value); Plugin.SanitizeTraderItems(value); } } catch (Exception ex) { Logger.LogDebug((object)("Pocket Dvergr: Haldor TradeItem sanitization skipped: " + ex.Message)); } } } internal static class PocketDvergerEmergencyRecall { private static bool running; public static void Trigger(Player owner, string reason) { if (running || (Object)(object)owner == (Object)null || !Plugin.EmergencyRecallOnHostility.Value || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } running = true; try { PocketDvergerCompanion[] array = Object.FindObjectsOfType<PocketDvergerCompanion>(); foreach (PocketDvergerCompanion pocketDvergerCompanion in array) { if (!((Object)(object)pocketDvergerCompanion == (Object)null) && pocketDvergerCompanion.GetOwnerID() == owner.GetPlayerID()) { DropBrokenDoll(pocketDvergerCompanion); } } ((Character)owner).Message((MessageType)2, "$SakeysPocketDverger_EmergencyRecall", 0, (Sprite)null, false); } finally { running = false; } } internal static void DropNaturalDeathDoll(PocketDvergerCompanion companion) { if (!((Object)(object)companion == (Object)null)) { DropBrokenDoll(companion); } } private static void DropBrokenDoll(PocketDvergerCompanion companion) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) companion.MarkEmergencyHandled(); GameObject prefab = PrefabManager.Instance.GetPrefab(Plugin.GetBrokenPrefab(companion.CompanionType)); if ((Object)(object)prefab == (Object)null) { Logger.LogError((object)$"Pocket Dvergr: emergency broken doll prefab missing for {companion.CompanionType}."); return; } ItemDrop component = prefab.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && component.m_itemData != null) { ItemData obj = component.m_itemData.Clone(); obj.m_dropPrefab = prefab; obj.m_stack = 1; obj.m_durability = 0f; ItemDrop val = ItemDrop.DropItem(obj, 1, ((Component)companion).transform.position + Vector3.up * 0.25f, Quaternion.identity); if ((Object)(object)val != (Object)null) { val.OnPlayerDrop(); } if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)companion).gameObject); } else { Object.Destroy((Object)(object)((Component)companion).gameObject); } } } } [HarmonyPatch(typeof(Character), "Damage", new Type[] { typeof(HitData) })] internal static class PocketDvergerFriendlyFirePatch { private static bool Prefix(Character __instance, HitData hit) { if (!Plugin.EmergencyRecallOnHostility.Value || (Object)(object)__instance == (Object)null || hit == null) { return true; } PocketDvergerCompanion component = ((Component)__instance).GetComponent<PocketDvergerCompanion>(); if ((Object)(object)component == (Object)null) { return true; } Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val == (Object)null || component.GetOwnerID() != val.GetPlayerID()) { return true; } PocketDvergerEmergencyRecall.Trigger(val, "friendly fire"); return false; } } [HarmonyPatch(typeof(Character), "OnDeath")] internal static class PocketDvergerDeathDropPatch { private static void Prefix(Character __instance) { PocketDvergerCompanion pocketDvergerCompanion = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<PocketDvergerCompanion>() : null); if (!((Object)(object)pocketDvergerCompanion == (Object)null) && !pocketDvergerCompanion.IsEmergencyHandled) { PocketDvergerEmergencyRecall.DropNaturalDeathDoll(pocketDvergerCompanion); } } } public enum PocketDvergerCommandMode { FollowStay, Retrieve } internal static class PocketDvergerCommandMenu { private static PocketDvergerCommandMode selectedMode; public static void Cycle(PocketDvergerCompanion companion) { if (!((Object)(object)companion == (Object)null)) { selectedMode = ((selectedMode == PocketDvergerCommandMode.FollowStay) ? PocketDvergerCommandMode.Retrieve : PocketDvergerCommandMode.FollowStay); ShowSelectedMessage(companion); } } public static bool Execute(PocketDvergerCompanion companion, Player player) { if ((Object)(object)companion == (Object)null || (Object)(object)player == (Object)null) { return false; } if (selectedMode == PocketDvergerCommandMode.Retrieve) { companion.Retrieve(player); } else { companion.ToggleFollowStay(player); } return true; } public static string GetModeDisplayKey() { if (selectedMode != PocketDvergerCommandMode.Retrieve) { return "$SakeysPocketDverger_ModeFollow"; } return "$SakeysPocketDverger_ModeRetrieve"; } public static void ShowSelectedMessage(PocketDvergerCompanion companion) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)companion == (Object)null)) { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = localization.TryTranslate(Plugin.GetCompanionName(companion.CompanionType)); string text2 = localization.TryTranslate(GetModeDisplayKey()); ((Character)localPlayer).Message((MessageType)2, text + ":" + text2, 0, (Sprite)null, false); } } } internal class PocketDvergerInputController : MonoBehaviour { private static int suppressInteractFrame = -1; public static bool SuppressInteractThisFrame() { if (suppressInteractFrame == Time.frameCount) { suppressInteractFrame = -1; return true; } return false; } private void Update() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || Console.IsVisible() || Menu.IsVisible()) { return; } if (ZInput.GetButton("JoyLBumper") && ZInput.GetButtonDown("JoyUse")) { Character hoverCreature = localPlayer.GetHoverCreature(); PocketDvergerCompanion pocketDvergerCompanion = (((Object)(object)hoverCreature != (Object)null) ? ((Component)hoverCreature).GetComponent<PocketDvergerCompanion>() : null); if ((Object)(object)pocketDvergerCompanion != (Object)null && pocketDvergerCompanion.GetOwnerID() == localPlayer.GetPlayerID()) { PocketDvergerCommandMenu.Cycle(pocketDvergerCompanion); suppressInteractFrame = Time.frameCount; } } if (CommandKeyPressed()) { Character hoverCreature2 = localPlayer.GetHoverCreature(); PocketDvergerCompanion pocketDvergerCompanion2 = (((Object)(object)hoverCreature2 != (Object)null) ? ((Component)hoverCreature2).GetComponent<PocketDvergerCompanion>() : null); if ((Object)(object)pocketDvergerCompanion2 != (Object)null && pocketDvergerCompanion2.GetOwnerID() == localPlayer.GetPlayerID()) { PocketDvergerCommandMenu.Cycle(pocketDvergerCompanion2); } } } private static bool CommandKeyPressed() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Plugin.CommandKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!Input.GetKey(modifier)) { return false; } } return true; } } [HarmonyPatch(typeof(PocketDvergerCompanion), "Interact")] internal static class PocketDvergerControllerCyclePatch { private static bool Prefix(Humanoid character) { if ((Object)(object)character == (Object)null || (Object)(object)character != (Object)(object)Player.m_localPlayer) { return true; } return !PocketDvergerInputController.SuppressInteractThisFrame(); } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class PocketDvergerPlayerSpawnPatch { private static void Postfix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (Object)(object)((Component)__instance).GetComponent<PocketDvergerInputController>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<PocketDvergerInputController>(); } } } public class PocketDvergerCompanion : MonoBehaviour, Interactable { private static readonly FieldInfo TargetCreatureField = AccessTools.Field(typeof(MonsterAI), "m_targetCreature"); private static readonly FieldInfo TargetStaticField = AccessTools.Field(typeof(MonsterAI), "m_targetStatic"); private static readonly MethodInfo SetAlertedMethod = AccessTools.Method(typeof(BaseAI), "SetAlerted", new Type[1] { typeof(bool) }, (Type[])null); private static readonly MethodInfo SetTargetInfoMethod = AccessTools.Method(typeof(BaseAI), "SetTargetInfo", new Type[1] { typeof(ZDOID) }, (Type[])null); private ZNetView nview; private MonsterAI monsterAI; private Humanoid humanoid; private bool initialized; private bool following; private float originalViewRange = -1f; private float originalHearRange = -1f; private int followAiCheckFrame; private bool emergencyHandled; public PocketDvergerType CompanionType; internal bool IsEmergencyHandled => emergencyHandled; private static void ClearCombatTarget(MonsterAI ai) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ai == (Object)null) { return; } try { TargetCreatureField?.SetValue(ai, null); TargetStaticField?.SetValue(ai, null); if (SetAlertedMethod != null) { SetAlertedMethod.Invoke(ai, new object[1] { false }); } if (SetTargetInfoMethod != null) { SetTargetInfoMethod.Invoke(ai, new object[1] { ZDOID.None }); } } catch (Exception ex) { Debug.LogWarning((object)("[Sakey's Pocket Dvergr] Failed to clear combat target: " + ex.Message)); } } private void Awake() { nview = ((Component)this).GetComponent<ZNetView>(); monsterAI = ((Component)this).GetComponent<MonsterAI>(); humanoid = ((Component)this).GetComponent<Humanoid>(); LoadType(); ApplyDisplayName(); Character component = ((Component)this).GetComponent<Character>(); if ((Object)(object)component != (Object)null) { try { component.SetLevel(3); } catch (Exception arg) { Logger.LogError((object)$"Pocket Dverger: SetLevel failed: {arg}"); } } initialized = true; } public void Initialize(long ownerId) { nview = ((Component)this).GetComponent<ZNetView>(); monsterAI = ((Component)this).GetComponent<MonsterAI>(); humanoid = ((Component)this).GetComponent<Humanoid>(); initialized = true; if ((Object)(object)nview != (Object)null && nview.IsValid() && nview.IsOwner()) { ZDO zDO = nview.GetZDO(); zDO.Set("SakeysPocketDverger_Owner", ownerId); zDO.Set("SakeysPocketDverger_Type", (int)CompanionType); zDO.Set("SakeysPocketDverger_Contract", Plugin.GetActivePrefab(CompanionType)); } ApplyDisplayName(); Character component = ((Component)this).GetComponent<Character>(); if ((Object)(object)component != (Object)null) { try { component.SetLevel(3); } catch (Exception arg) { Logger.LogError((object)$"Pocket Dverger: Initialize SetLevel failed: {arg}"); } } } private void LateUpdate() { ApplyDisplayName(); } private void ApplyDisplayName() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)humanoid == (Object)null) { humanoid = ((Component)this).GetComponent<Humanoid>(); } if ((Object)(object)humanoid != (Object)null) { ((Character)humanoid).m_faction = (Faction)0; ((Character)humanoid).m_name = Plugin.GetCompanionName(CompanionType); } } private void LoadType() { if (!((Object)(object)nview == (Object)null) && nview.IsValid()) { ZDO zDO = nview.GetZDO(); if (zDO != null) { CompanionType = (PocketDvergerType)zDO.GetInt("SakeysPocketDverger_Type", (int)CompanionType); } } } private void FixedUpdate() { if (!initialized || (Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return; } Player val = FindOwner(); if (!((Object)(object)val == (Object)null) && !((Object)(object)monsterAI == (Object)null)) { if (following) { monsterAI.SetFollowTarget(((Component)val).gameObject); } ApplyFollowBehavior(); } } private void CacheOriginalAiRanges() { if (!((Object)(object)monsterAI == (Object)null)) { BaseAI val = (BaseAI)(object)monsterAI; if (originalViewRange < 0f) { originalViewRange = val.m_viewRange; } if (originalHearRange < 0f) { originalHearRange = val.m_hearRange; } } } private void ApplyFollowBehavior() { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)monsterAI == (Object)null) { return; } CacheOriginalAiRanges(); BaseAI val = (BaseAI)(object)monsterAI; if (!following) { if (originalViewRange >= 0f) { val.m_viewRange = originalViewRange; } if (originalHearRange >= 0f) { val.m_hearRange = originalHearRange; } return; } val.m_viewRange = originalViewRange * Mathf.Clamp(Plugin.FollowViewRangeMultiplier.Value, 0.05f, 1f); val.m_hearRange = originalHearRange * Mathf.Clamp(Plugin.FollowHearRangeMultiplier.Value, 0.05f, 1f); followAiCheckFrame++; if (followAiCheckFrame < 10) { return; } followAiCheckFrame = 0; Player val2 = FindOwner(); if ((Object)(object)val2 == (Object)null) { return; } Character targetCreature = val.GetTargetCreature(); if ((Object)(object)targetCreature == (Object)(object)val2) { PocketDvergerEmergencyRecall.Trigger(val2, "hostility"); } else if (!((Object)(object)targetCreature == (Object)null) && !targetCreature.IsDead()) { float num = Vector3.Distance(((Component)this).transform.position, ((Component)val2).transform.position); float num2 = Vector3.Distance(((Component)targetCreature).transform.position, ((Component)val2).transform.position); if (num > Mathf.Max(1f, Plugin.FollowLeashDistance.Value)) { ClearCombatTarget(monsterAI); } else if (num2 > Mathf.Max(1f, Plugin.FollowTargetDistance.Value)) { ClearCombatTarget(monsterAI); } } } private Player FindOwner() { long id = GetOwnerID(); if (id == 0L) { return null; } return ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && p.GetPlayerID() == id)); } public long GetOwnerID() { if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return 0L; } ZDO zDO = nview.GetZDO(); if (zDO != null) { return zDO.GetLong("SakeysPocketDverger_Owner", 0L); } return 0L; } public bool Interact(Humanoid character, bool hold, bool alt) { if (hold) { return false; } Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null || GetOwnerID() != val.GetPlayerID()) { return false; } if (StoreGui.IsVisible() || InventoryGui.IsVisible() || Menu.IsVisible()) { return false; } return PocketDvergerCommandMenu.Execute(this, val); } public bool IsFollowing() { return following; } public void ToggleFollowStay(Player player) { following = !following; if ((Object)(object)monsterAI != (Object)null) { BaseAI val = (BaseAI)(object)monsterAI; if (following) { val.ResetPatrolPoint(); monsterAI.SetFollowTarget(((Component)player).gameObject); } else { monsterAI.SetFollowTarget((GameObject)null); val.SetPatrolPoint(); } ApplyFollowBehavior(); } ((Character)player).Message((MessageType)2, following ? Plugin.GetFollowMessage(CompanionType) : Plugin.GetStayMessage(CompanionType), 0, (Sprite)null, false); } public bool Retrieve(Player player) { if ((Object)(object)player == (Object)null || ((Humanoid)player).GetInventory() == null) { return false; } if ((Object)(object)monsterAI != (Object)null) { monsterAI.SetFollowTarget((GameObject)null); ClearCombatTarget(monsterAI); ((BaseAI)monsterAI).ResetPatrolPoint(); } GameObject prefab = PrefabManager.Instance.GetPrefab(Plugin.GetActivePrefab(CompanionType)); if ((Object)(object)prefab == (Object)null || !((Humanoid)player).GetInventory().AddItem(prefab, 1)) { return false; } ((Character)player).Message((MessageType)2, Plugin.GetRetrievedMessage(CompanionType), 0, (Sprite)null, false); if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)this).gameObject); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } return true; } internal void MarkEmergencyHandled() { emergencyHandled = true; } public bool UseItem(Humanoid user, ItemData item) { return false; } public string GetHoverText() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = localization.TryTranslate(Plugin.GetCompanionName(CompanionType)); string text2 = localization.TryTranslate(PocketDvergerCommandMenu.GetModeDisplayKey()); return text + "\n[F3 / L1+決定] " + text2; } public string GetHoverName() { return Plugin.GetCompanionName(CompanionType); } }