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 ElixDrax TamedCreatureXP v0.5.7
BepInEx/plugins/TamedCreatureXP.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("TamedCreatureXP")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("TamedCreatureXP")] [assembly: AssemblyTitle("TamedCreatureXP")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TamedCreatureXP { internal static class CreatureBackpack { private sealed class WispVisualState { public Character Creature; public Transform Root; public Vector3 Center; public float Radius; public float Height; public float Phase; public float Speed; } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDbAwakePatch { private static void Postfix() { Initialize(); } } [HarmonyPatch(typeof(Humanoid), "UseItem", new Type[] { typeof(Inventory), typeof(ItemData), typeof(bool) })] private static class UseBackpackItemPatch { private static bool Prefix(Humanoid __instance, Inventory __0, ItemData __1) { try { return UseBackpackItem(__instance, __0, __1); } catch (Exception ex) { Plugin.ModLog.LogError((object)("Could not equip creature backpack: " + ex)); return false; } } } [HarmonyPatch(typeof(Container), "Awake")] private static class VirtualContainerAwakePatch { private static bool Prefix(Container __instance) { return VirtualContainerAwakePrefix(__instance); } } [HarmonyPatch(typeof(Container), "GetInventory")] private static class VirtualGetInventoryPatch { private static bool Prefix(Container __instance, ref Inventory __result) { return GetInventoryPrefix(__instance, ref __result); } } [HarmonyPatch(typeof(Container), "Load")] private static class VirtualContainerLoadPatch { private static bool Prefix(Container __instance, ref bool __result) { return ContainerLoadPrefix(__instance, ref __result); } } [HarmonyPatch(typeof(Container), "Save")] private static class VirtualContainerSavePatch { private static bool Prefix(Container __instance) { return ContainerSavePrefix(__instance); } } [HarmonyPatch(typeof(Container), "SetInUse")] private static class VirtualContainerUsePatch { [HarmonyPriority(800)] private static bool Prefix(Container __instance, bool __0) { return SetInUsePrefix(__instance, __0); } } [HarmonyPatch(typeof(InventoryGui), "Hide")] private static class SaveBackpackOnGuiClosePatch { private static void Prefix() { OnGuiClosing(); } private static void Postfix() { OnGuiClosed(); HideBackpackPanelFrame(); } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] private static class KeepVirtualContainerInRangePatch { private static void Prefix(InventoryGui __instance, Player __0) { try { FollowPlayerWhileOpen(__instance, __0); } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not keep the backpack container within interaction range: " + ex.Message)); } } private static void Postfix(InventoryGui __instance) { try { UpdateBackpackInventoryStyle(__instance); } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not style the backpack inventory panel: " + ex.Message)); } } } [HarmonyPatch(typeof(InventoryGui), "CloseContainer")] private static class HideBackpackPanelFramePatch { private static void Postfix() { HideBackpackPanelFrame(); } } private const string ItemPrefabName = "TamedCreatureXP_CreatureBackpack"; private const string ItemInternalName = "$item_tamedcreaturexp_creaturebackpack"; private const string ContainerObjectName = "TamedCreatureXP_VirtualCreatureBackpack"; private const string VisualObjectName = "TamedCreatureXP_CreatureBackpackVisual_v3"; private const string LegacyVisualObjectName = "TamedCreatureXP_CreatureBackpackVisual"; private const string PreviousVisualObjectName = "TamedCreatureXP_CreatureBackpackVisual_v2"; private const string BackpackPanelFrameName = "TamedCreatureXP_CreatureBackpackPanelFrame"; private const string HasPackKey = "TamedCreatureXP.HasBackpack"; private const string ContentsKey = "TamedCreatureXP.BackpackContents"; private const int UnlockLevel = 4; private const int BackpackWidth = 5; private const int BackpackHeight = 3; private static ObjectDB _registeredObjectDb; private static GameObject _itemPrefab; private static Recipe _recipe; private static bool _recipeUnlocked; private static Container _virtualContainer; private static Inventory _virtualInventory; private static Character _openCreature; private static ZDO _openZdo; private static Sprite _backpackSprite; private static Sprite _panelFrameSprite; private static Transform _panelFrame; private static Material _violetTrailMaterial; private static readonly List<WispVisualState> WispVisuals = new List<WispVisualState>(); private static bool _saving; private static bool _closingVirtualContainer; private static float _nextPeriodicSave; private static bool _warnedRegistration; private static bool _warnedSave; private static bool _warnedVisual; private static bool _warnedJotunn; private static bool _warnedPanelStyle; private static bool _azuAutoStoreCompatibilityPatched; private static bool _warnedAzuAutoStorePatch; private static object _jotunnCustomItem; private static object _jotunnCustomRecipe; private static bool _jotunnItemAdded; internal static void Initialize() { try { EnsureObjectDbRegistration(); } catch (Exception ex) { if (!_warnedRegistration) { _warnedRegistration = true; Plugin.ModLog.LogWarning((object)("Creature backpack registration is waiting for Valheim: " + ex.Message)); } } } private static List<Character> SnapshotLoadedCharacters() { List<Character> list = new List<Character>(); FieldInfo fieldInfo = AccessTools.Field(typeof(Character), "s_characters"); IEnumerable enumerable = ((fieldInfo == null) ? null : (fieldInfo.GetValue(null) as IEnumerable)); if (enumerable == null) { return list; } try { foreach (object item in enumerable) { Character val = (Character)((item is Character) ? item : null); if ((Object)(object)val != (Object)null) { list.Add(val); } } } catch (InvalidOperationException ex) { Plugin.ModLog.LogDebug((object)("Creature list changed while being copied for backpack refresh: " + ex.Message)); } return list; } internal static void TryPatchAzuAutoStore(Harmony harmony) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown if (_azuAutoStoreCompatibilityPatched || harmony == null) { return; } Type type = AccessTools.TypeByName("AzuAutoStore.Patches.ContainerSetInUseClearWithoutOwnershipPatch"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null)); MethodInfo methodInfo2 = AccessTools.Method(typeof(CreatureBackpack), "AzuAutoStoreContainerPrefixGuard", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { return; } try { HarmonyMethod val = new HarmonyMethod(methodInfo2); val.priority = 800; harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _azuAutoStoreCompatibilityPatched = true; Plugin.ModLog.LogInfo((object)"AzuAutoStore compatibility enabled for the virtual creature backpack."); } catch (Exception ex) { if (!_warnedAzuAutoStorePatch) { _warnedAzuAutoStorePatch = true; Plugin.ModLog.LogWarning((object)("Could not isolate the virtual creature backpack from AzuAutoStore: " + ex.Message)); } } } private static bool AzuAutoStoreContainerPrefixGuard(Container __0) { return !IsVirtual(__0); } internal static void RefreshRecipeUnlock() { Initialize(); if ((Object)(object)_recipe == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return; } bool flag = Plugin.BackpackUnlocked != null && Plugin.BackpackUnlocked.Value; try { foreach (Character item in SnapshotLoadedCharacters()) { if (!Plugin.IsAllowedTamedCreature(item) || item.GetLevel() < 4) { continue; } flag = true; if (Plugin.BackpackUnlocked != null && !Plugin.BackpackUnlocked.Value) { Plugin.BackpackUnlocked.Value = true; if ((Object)(object)Plugin.Instance != (Object)null) { ((BaseUnityPlugin)Plugin.Instance).Config.Save(); } } break; } } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not inspect tamed creatures for backpack recipe unlock: " + ex.Message)); } if (_recipeUnlocked == flag && _recipe.m_enabled == flag) { return; } _recipeUnlocked = flag; _recipe.m_enabled = flag; try { AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null)?.Invoke(ObjectDB.instance, null); } catch (Exception ex2) { Plugin.ModLog.LogDebug((object)("Could not refresh backpack recipe: " + ex2.Message)); } } internal static void RefreshAttachedBackpacks() { try { foreach (Character item in SnapshotLoadedCharacters()) { if ((Object)(object)item == (Object)null || !item.IsTamed() || item.IsDead()) { continue; } ZNetView nView = Plugin.GetNView(item); ZDO val = (((Object)(object)nView != (Object)null && nView.IsValid()) ? nView.GetZDO() : null); if (val != null) { if (val.GetBool("TamedCreatureXP.HasBackpack", false)) { EnsureBackpackVisual(item); } else { RemoveBackpackVisual(item); } } } } catch (Exception ex) { if (!_warnedVisual) { _warnedVisual = true; Plugin.ModLog.LogWarning((object)("Could not refresh visible creature backpacks: " + ex)); } } } internal static void TickBackpackWisps() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) for (int num = WispVisuals.Count - 1; num >= 0; num--) { WispVisualState wispVisualState = WispVisuals[num]; if (wispVisualState == null || (Object)(object)wispVisualState.Creature == (Object)null || (Object)(object)wispVisualState.Root == (Object)null || wispVisualState.Creature.IsDead()) { WispVisuals.RemoveAt(num); } else { float num2 = Time.time * wispVisualState.Speed + wispVisualState.Phase; wispVisualState.Root.localPosition = wispVisualState.Center + new Vector3(Mathf.Cos(num2) * wispVisualState.Radius, Mathf.Sin(num2 * 2f) * wispVisualState.Height, Mathf.Sin(num2) * wispVisualState.Radius); wispVisualState.Root.localRotation = Quaternion.Euler(0f, (0f - num2) * 57.29578f, 0f); TickWispSparks(wispVisualState, num2); } } if ((Object)(object)_openCreature != (Object)null && Time.unscaledTime >= _nextPeriodicSave) { _nextPeriodicSave = Time.unscaledTime + 0.75f; SaveIfOpen(); } } internal static void EnsureAttachedBackpack(Character creature) { if (!((Object)(object)creature == (Object)null) && creature.IsTamed() && !creature.IsDead()) { ZNetView nView = Plugin.GetNView(creature); ZDO val = (((Object)(object)nView != (Object)null && nView.IsValid()) ? nView.GetZDO() : null); if (val != null && val.GetBool("TamedCreatureXP.HasBackpack", false)) { EnsureBackpackVisual(creature); } else { RemoveBackpackVisual(creature); } } } internal static bool HasBackpack(Character creature) { if ((Object)(object)creature == (Object)null) { return false; } ZNetView nView = Plugin.GetNView(creature); ZDO val = (((Object)(object)nView != (Object)null && nView.IsValid()) ? nView.GetZDO() : null); if (val != null) { return val.GetBool("TamedCreatureXP.HasBackpack", false); } return false; } private static byte[] SerializeInventory(Inventory inventory) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown if (inventory == null) { return null; } ZPackage val = new ZPackage(); inventory.Save(val); return val.GetArray(); } private static void EnsureBackpackVisual(Character creature) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) try { Transform val = FindChild(((Component)creature).transform, "TamedCreatureXP_CreatureBackpackVisual"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } Transform val2 = FindChild(((Component)creature).transform, "TamedCreatureXP_CreatureBackpackVisual_v2"); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)((Component)val2).gameObject); } Transform val3 = FindChild(((Component)creature).transform, "TamedCreatureXP_CreatureBackpackVisual_v3"); if ((Object)(object)val3 == (Object)null) { val3 = new GameObject("TamedCreatureXP_CreatureBackpackVisual_v3").transform; val3.SetParent(((Component)creature).transform, false); BuildBackpackWisp(val3, creature); } FitBackpackWisp(creature, val3); } catch (Exception ex) { if (!_warnedVisual) { _warnedVisual = true; Plugin.ModLog.LogWarning((object)("Could not create visible backpack on " + ((Object)((Component)creature).gameObject).name + ": " + ex)); } } } private static void BuildBackpackWisp(Transform root, Character creature) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindWispVisualSource(); GameObject val2 = null; if ((Object)(object)val != (Object)null) { try { val2 = Object.Instantiate<GameObject>(val, root, false); ((Object)val2).name = "VioletWispTexturedModel"; val2.SetActive(true); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; StripNonVisualComponents(val2); TintWispRenderers(val2, new Color(0.76f, 0.4f, 1f, 1f)); TuneWispEffects(val2); NormalizeWispSize(val2); PlayWispParticles(val2); } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not reuse an in-game wisp visual: " + ex.Message)); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } val2 = null; } } if ((Object)(object)val2 == (Object)null) { BuildTexturedFallbackWisp(root, creature); } AddVioletWispTrails(root); if (!HasParticleVisual(root)) { AddWispSparkMotes(root); } } private static void AddVioletWispTrails(Transform root) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)root == (Object)null) && !((Object)(object)FindChild(root, "VioletWispTrailGlow") != (Object)null)) { Material violetTrailMaterial = GetVioletTrailMaterial(); if (!((Object)(object)violetTrailMaterial == (Object)null)) { CreateWispTrail(root, "VioletWispTrailGlow", violetTrailMaterial, 0.06f, 0.38f, new Color(0.68f, 0.36f, 1f, 1f), new Color(0.42f, 0.18f, 0.82f, 1f), 0.18f); CreateWispTrail(root, "VioletWispTrailCore", violetTrailMaterial, 0.024f, 0.32f, new Color(0.91f, 0.76f, 1f, 1f), new Color(0.66f, 0.38f, 1f, 1f), 0.68f); } } } private static Material GetVioletTrailMaterial() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_violetTrailMaterial != (Object)null) { return _violetTrailMaterial; } Shader val = Shader.Find("Particles/Standard Unlit"); if ((Object)(object)val == (Object)null) { val = Shader.Find("Sprites/Default"); } if ((Object)(object)val == (Object)null) { val = Shader.Find("Legacy Shaders/Particles/Alpha Blended"); } if ((Object)(object)val == (Object)null) { if (!_warnedVisual) { _warnedVisual = true; Plugin.ModLog.LogWarning((object)"Could not find a transparent shader for the violet backpack wisp trail."); } return null; } _violetTrailMaterial = new Material(val); string[] array = new string[3] { "_Color", "_BaseColor", "_TintColor" }; foreach (string text in array) { if (_violetTrailMaterial.HasProperty(text)) { _violetTrailMaterial.SetColor(text, Color.white); } } return _violetTrailMaterial; } private static void CreateWispTrail(Transform root, string name, Material material, float width, float duration, Color startColor, Color endColor, float alpha) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0058: 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_006c: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0104: 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) GameObject val = new GameObject(name); val.transform.SetParent(root, false); TrailRenderer val2 = val.AddComponent<TrailRenderer>(); ((Renderer)val2).material = material; val2.time = duration; val2.widthMultiplier = width; val2.widthCurve = new AnimationCurve((Keyframe[])(object)new Keyframe[2] { new Keyframe(0f, 1f), new Keyframe(1f, 0.08f) }); val2.minVertexDistance = 0.012f; val2.numCornerVertices = 8; val2.numCapVertices = 8; val2.emitting = true; val2.autodestruct = false; Gradient val3 = new Gradient(); val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(startColor, 0f), new GradientColorKey(endColor, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[3] { new GradientAlphaKey(alpha, 0f), new GradientAlphaKey(alpha * 0.28f, 0.55f), new GradientAlphaKey(0f, 1f) }); val2.colorGradient = val3; } private static GameObject FindWispVisualSource() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { Transform[] componentsInChildren = ((Component)localPlayer).GetComponentsInChildren<Transform>(true); GameObject val = null; int num = 0; Transform[] array = componentsInChildren; foreach (Transform val2 in array) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)((Component)localPlayer).transform) && ((Object)val2).name.ToLowerInvariant().IndexOf("wisp", StringComparison.Ordinal) >= 0 && ((Component)val2).GetComponentsInChildren<Renderer>(true).Length != 0 && IsVisualOnlyTree(((Component)val2).gameObject)) { int num2 = ScoreWispVisualSource(val2); if (num2 > num) { num = num2; val = ((Component)val2).gameObject; } } } if ((Object)(object)val != (Object)null) { return val; } } return null; } private static int ScoreWispVisualSource(Transform candidate) { Renderer[] componentsInChildren = ((Component)candidate).GetComponentsInChildren<Renderer>(true); MeshFilter[] componentsInChildren2 = ((Component)candidate).GetComponentsInChildren<MeshFilter>(true); Component[] componentsInChildren3 = ((Component)candidate).GetComponentsInChildren<Component>(true); int num = componentsInChildren.Length * 10 + componentsInChildren2.Length * 4; Component[] array = componentsInChildren3; foreach (Component val in array) { if (!((Object)(object)val == (Object)null)) { switch (((object)val).GetType().Name) { case "ParticleSystem": num += 4; break; case "TrailRenderer": num += 5; break; case "Light": num += 3; break; } } } string text = ((Object)candidate).name.ToLowerInvariant(); if (text.Contains("wisplight")) { num += 80; } else if (text == "wisp") { num += 24; } return num; } private static bool IsVisualOnlyTree(GameObject root) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is Renderer) && !(val is MeshFilter) && !(((object)val).GetType().Name == "Animator") && !(((object)val).GetType().Name == "Animation") && !(((object)val).GetType().Name == "ParticleSystem") && !(((object)val).GetType().Name == "Light")) { return false; } } return true; } private static void StripNonVisualComponents(GameObject root) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is Renderer) && !(val is MeshFilter) && !(((object)val).GetType().Name == "Animator") && !(((object)val).GetType().Name == "Animation") && !(((object)val).GetType().Name == "ParticleSystem") && !(((object)val).GetType().Name == "Light")) { Object.Destroy((Object)(object)val); } } } private static void TintWispRenderers(GameObject root, Color tint) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Material[] materials = val.materials; Material[] array = materials; foreach (Material val2 in array) { if ((Object)(object)val2 == (Object)null) { continue; } string[] array2 = new string[3] { "_Color", "_BaseColor", "_TintColor" }; foreach (string text in array2) { if (val2.HasProperty(text)) { Color color = val2.GetColor(text); val2.SetColor(text, new Color(color.r * tint.r, color.g * tint.g, color.b * tint.b, color.a * tint.a)); } } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", tint * 1.6f); val2.EnableKeyword("_EMISSION"); } } val.materials = materials; } } private static void NormalizeWispSize(GameObject root) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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) Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); if (componentsInChildren.Length == 0) { return; } List<Renderer> list = new List<Renderer>(); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Name != "ParticleSystemRenderer" && ((object)val).GetType().Name != "TrailRenderer") { list.Add(val); } } if (list.Count != 0) { Bounds bounds = list[0].bounds; for (int j = 1; j < list.Count; j++) { ((Bounds)(ref bounds)).Encapsulate(list[j].bounds); } float num = Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z)); if (num > 0.001f) { Transform transform = root.transform; transform.localScale *= 0.82f / num; } } } private static void PlayWispParticles(GameObject root) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(((object)val).GetType().Name != "ParticleSystem")) { try { AccessTools.Method(((object)val).GetType(), "Play", new Type[1] { typeof(bool) }, (Type[])null)?.Invoke(val, new object[1] { true }); } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not start a cloned wisp particle system: " + ex.Message)); } } } } private static void TuneWispEffects(GameObject root) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); Type type = AccessTools.TypeByName("UnityEngine.TrailRenderer"); Component[] array = componentsInChildren; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } try { if (type != null && type.IsInstanceOfType(val)) { SetFloatProperty(val, "time", 0.28f, onlyReduce: true); float floatProperty = GetFloatProperty(val, "widthMultiplier", 0.1f); SetFloatProperty(val, "widthMultiplier", Mathf.Max(0.008f, floatProperty * 0.48f), onlyReduce: false); SetFloatProperty(val, "minVertexDistance", 0.025f, onlyReduce: true); SetIntProperty(val, "numCornerVertices", 5); SetIntProperty(val, "numCapVertices", 5); AccessTools.Method(((object)val).GetType(), "Clear", (Type[])null, (Type[])null)?.Invoke(val, null); } else if (((object)val).GetType().Name == "ParticleSystem") { ReduceParticleCurve(val, "startLifetime", 0.55f, 0.65f); ReduceParticleCurve(val, "startSize", 0.15f, 0.65f); } } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not tune a cloned wisp effect: " + ex.Message)); } } } private static void ReduceParticleCurve(Component particleSystem, string propertyName, float maximum, float factor) { PropertyInfo propertyInfo = AccessTools.Property(((object)particleSystem).GetType(), "main"); if (propertyInfo == null) { return; } object value = propertyInfo.GetValue(particleSystem, null); if (value == null) { return; } PropertyInfo propertyInfo2 = AccessTools.Property(value.GetType(), propertyName); if (!(propertyInfo2 == null) && propertyInfo2.CanWrite) { object value2 = propertyInfo2.GetValue(value, null); PropertyInfo propertyInfo3 = ((value2 == null) ? null : AccessTools.Property(value2.GetType(), "constantMax")); float num = ((propertyInfo3 == null) ? maximum : Convert.ToSingle(propertyInfo3.GetValue(value2, null))); float num2 = Mathf.Min(maximum, num * factor); if (!(num2 <= 0f)) { object value3 = Activator.CreateInstance(propertyInfo2.PropertyType, num2); propertyInfo2.SetValue(value, value3, null); } } } private static float GetFloatProperty(Component component, string name, float fallback) { PropertyInfo propertyInfo = AccessTools.Property(((object)component).GetType(), name); if (propertyInfo == null) { return fallback; } object value = propertyInfo.GetValue(component, null); if (value != null) { return Convert.ToSingle(value); } return fallback; } private static void SetFloatProperty(Component component, string name, float value, bool onlyReduce) { PropertyInfo propertyInfo = AccessTools.Property(((object)component).GetType(), name); if (!(propertyInfo == null) && propertyInfo.CanWrite) { float num = value; if (onlyReduce) { num = Mathf.Min(GetFloatProperty(component, name, value), value); } propertyInfo.SetValue(component, num, null); } } private static void SetIntProperty(Component component, string name, int value) { PropertyInfo propertyInfo = AccessTools.Property(((object)component).GetType(), name); if (propertyInfo != null && propertyInfo.CanWrite) { propertyInfo.SetValue(component, value, null); } } private static bool HasParticleVisual(Transform root) { Component[] componentsInChildren = ((Component)root).GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "ParticleSystem") { return true; } } return false; } private static void BuildTexturedFallbackWisp(Transform root, Character creature) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)val).name = "VioletWispFallback"; val.transform.SetParent(root, false); val.transform.localScale = Vector3.one; Renderer component = val.GetComponent<Renderer>(); Type type = AccessTools.TypeByName("UnityEngine.Collider"); Component val2 = ((type == null) ? null : val.GetComponent(type)); PropertyInfo propertyInfo = ((type == null) ? null : AccessTools.Property(type, "enabled")); if ((Object)(object)val2 != (Object)null && propertyInfo != null) { propertyInfo.SetValue(val2, false, null); } Material val3 = FindCreatureMaterial(creature); if ((Object)(object)component != (Object)null && (Object)(object)val3 != (Object)null) { component.material = new Material(val3); TintWispRenderers(val, new Color(0.76f, 0.4f, 1f, 1f)); } else { if (!((Object)(object)component != (Object)null)) { return; } Material material = component.material; if (!((Object)(object)material != (Object)null)) { return; } Color val4 = default(Color); ((Color)(ref val4))..ctor(0.76f, 0.4f, 1f, 1f); string[] array = new string[3] { "_Color", "_BaseColor", "_TintColor" }; foreach (string text in array) { if (material.HasProperty(text)) { material.SetColor(text, val4); } } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", val4 * 1.6f); material.EnableKeyword("_EMISSION"); } } } private static Material FindCreatureMaterial(Character creature) { if ((Object)(object)creature == (Object)null) { return null; } Renderer[] componentsInChildren = ((Component)creature).GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || IsChildOfNamedTransform(((Component)val).transform, "TamedCreatureXP_CreatureBackpackVisual_v3")) { continue; } Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null) { continue; } Material[] array = sharedMaterials; foreach (Material val2 in array) { if ((Object)(object)val2 != (Object)null) { return val2; } } } return null; } private static void AddWispSparkMotes(Transform root) { //IL_0038: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0170: 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_0133: 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) for (int i = 0; i < 5; i++) { GameObject val = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)val).name = "VioletWispMote_" + i; val.transform.SetParent(root, false); val.transform.localScale = Vector3.one * ((i % 2 == 0) ? 0.11f : 0.075f); val.transform.localPosition = Vector3.zero; Renderer component = val.GetComponent<Renderer>(); Type type = AccessTools.TypeByName("UnityEngine.Collider"); Component val2 = ((type == null) ? null : val.GetComponent(type)); PropertyInfo propertyInfo = ((type == null) ? null : AccessTools.Property(type, "enabled")); if ((Object)(object)val2 != (Object)null && propertyInfo != null) { propertyInfo.SetValue(val2, false, null); } if ((Object)(object)component != (Object)null) { Material material = component.material; if ((Object)(object)material != (Object)null && material.HasProperty("_Color")) { material.SetColor("_Color", (i % 2 == 0) ? new Color(0.9f, 0.72f, 1f, 1f) : new Color(0.55f, 0.18f, 0.95f, 1f)); } if ((Object)(object)material != (Object)null && material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", new Color(0.65f, 0.2f, 1f, 1f) * 1.7f); material.EnableKeyword("_EMISSION"); } } } } private static void TickWispSparks(WispVisualState state, float angle) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < state.Root.childCount; i++) { Transform child = state.Root.GetChild(i); if (!((Object)(object)child == (Object)null) && ((Object)child).name.IndexOf("VioletWispMote_", StringComparison.Ordinal) == 0) { float num = (float)i * (float)Math.PI * 0.4f; float num2 = 1f + (float)(i % 2) * 0.25f; child.localPosition = new Vector3(Mathf.Cos(angle * num2 + num) * 0.72f, Mathf.Sin(angle * 1.7f + num) * 0.55f, Mathf.Sin(angle * num2 + num) * 0.72f); } } } private static void FitBackpackWisp(Character creature, Transform visual) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) try { Renderer[] componentsInChildren = ((Component)creature).GetComponentsInChildren<Renderer>(); Bounds bounds = default(Bounds); ((Bounds)(ref bounds))..ctor(((Component)creature).transform.position + Vector3.up, Vector3.one); bool flag = false; Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null) && !IsChildOfNamedTransform(((Component)val).transform, "TamedCreatureXP_CreatureBackpackVisual_v3") && (val is SkinnedMeshRenderer || val is MeshRenderer)) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } float num = (flag ? Mathf.Max(0.5f, ((Bounds)(ref bounds)).size.y) : 1.5f); Vector3 val2 = ((Component)creature).transform.InverseTransformPoint(flag ? ((Bounds)(ref bounds)).center : (((Component)creature).transform.position + Vector3.up * num * 0.5f)); float num2 = Mathf.Max(0.1f, Mathf.Abs(((Component)creature).transform.lossyScale.y)); float num3 = num / num2; float num4 = Mathf.Clamp(num3 * 0.04f, 0.09f, 0.15f); WispVisualState wispVisualState = FindWispState(visual); if (wispVisualState == null) { wispVisualState = new WispVisualState { Creature = creature, Root = visual, Phase = (float)(((Object)creature).GetInstanceID() % 1000) * 0.013f, Speed = 2f }; WispVisuals.Add(wispVisualState); } wispVisualState.Creature = creature; wispVisualState.Root = visual; wispVisualState.Center = val2 + Vector3.up * (num3 * 0.16f); wispVisualState.Radius = Mathf.Clamp(num3 * 0.35f, 0.38f, 1.05f); wispVisualState.Height = Mathf.Clamp(num3 * 0.055f, 0.045f, 0.16f); visual.localScale = Vector3.one * num4; TickSingleWisp(wispVisualState); } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not position backpack wisp on " + ((Object)((Component)creature).gameObject).name + ": " + ex.Message)); } } private static WispVisualState FindWispState(Transform visual) { for (int i = 0; i < WispVisuals.Count; i++) { if (WispVisuals[i] != null && (Object)(object)WispVisuals[i].Root == (Object)(object)visual) { return WispVisuals[i]; } } return null; } private static void TickSingleWisp(WispVisualState state) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) float num = Time.time * state.Speed + state.Phase; state.Root.localPosition = state.Center + new Vector3(Mathf.Cos(num) * state.Radius, Mathf.Sin(num * 2f) * state.Height, Mathf.Sin(num) * state.Radius); state.Root.localRotation = Quaternion.Euler(0f, (0f - num) * 57.29578f, 0f); } private static bool IsChildOfNamedTransform(Transform transform, string name) { while ((Object)(object)transform != (Object)null) { if (((Object)transform).name == name) { return true; } transform = transform.parent; } return false; } private static Transform FindChild(Transform parent, string name) { if ((Object)(object)parent == (Object)null) { return null; } if (((Object)parent).name == name) { return parent; } for (int i = 0; i < parent.childCount; i++) { Transform val = FindChild(parent.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void RemoveBackpackVisual(Character creature) { Transform val = (((Object)(object)creature == (Object)null) ? null : FindChild(((Component)creature).transform, "TamedCreatureXP_CreatureBackpackVisual_v3")); if ((Object)(object)val != (Object)null) { for (int num = WispVisuals.Count - 1; num >= 0; num--) { if (WispVisuals[num] != null && (Object)(object)WispVisuals[num].Root == (Object)(object)val) { WispVisuals.RemoveAt(num); } } } if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } Transform val2 = (((Object)(object)creature == (Object)null) ? null : FindChild(((Component)creature).transform, "TamedCreatureXP_CreatureBackpackVisual")); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)((Component)val2).gameObject); } Transform val3 = (((Object)(object)creature == (Object)null) ? null : FindChild(((Component)creature).transform, "TamedCreatureXP_CreatureBackpackVisual_v2")); if ((Object)(object)val3 != (Object)null) { Object.Destroy((Object)(object)((Component)val3).gameObject); } } internal static void SaveForPortablePals(Character creature) { if ((Object)(object)creature != (Object)null && (Object)(object)creature == (Object)(object)_openCreature) { SaveIfOpen(); } } internal static void WritePortablePalsData(ZDO zdo, IDictionary<string, string> customData) { if (zdo != null && customData != null) { customData["TamedCreatureXP.HasBackpack"] = zdo.GetBool("TamedCreatureXP.HasBackpack", false).ToString(); byte[] byteArray = zdo.GetByteArray("TamedCreatureXP.BackpackContents", (byte[])null); customData["TamedCreatureXP.BackpackContents"] = ((byteArray == null) ? string.Empty : Convert.ToBase64String(byteArray)); } } internal static void RestoreFromPortablePals(ZDO zdo, IDictionary<string, string> customData) { if (zdo == null || customData == null) { return; } if (customData.TryGetValue("TamedCreatureXP.HasBackpack", out var value) && bool.TryParse(value, out var result)) { zdo.Set("TamedCreatureXP.HasBackpack", result); } if (!customData.TryGetValue("TamedCreatureXP.BackpackContents", out var value2)) { return; } try { zdo.Set("TamedCreatureXP.BackpackContents", string.IsNullOrEmpty(value2) ? new byte[0] : Convert.FromBase64String(value2)); } catch (Exception ex) { Plugin.ModLog.LogWarning((object)("Could not restore Pal Stone backpack contents: " + ex.Message)); } } private static void EnsureObjectDbRegistration() { //IL_0184: Unknown result type (might be due to invalid IL or missing references) ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return; } if (_registeredObjectDb == instance) { EnsureRecipe(instance); return; } _registeredObjectDb = instance; _itemPrefab = null; _recipe = null; _recipeUnlocked = false; RegisterLocalization(); GameObject itemPrefab = instance.GetItemPrefab("TamedCreatureXP_CreatureBackpack"); if ((Object)(object)itemPrefab != (Object)null) { _itemPrefab = itemPrefab; if ((Object)(object)_backpackSprite == (Object)null) { _backpackSprite = CreateBackpackSprite(instance); } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null) { component.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { _backpackSprite }; } RegisterItemWithJotunn(instance, itemPrefab); EnsureRecipe(instance); return; } GameObject itemPrefab2 = instance.GetItemPrefab("TrophyWolf"); if ((Object)(object)itemPrefab2 == (Object)null) { _registeredObjectDb = null; return; } _itemPrefab = Object.Instantiate<GameObject>(itemPrefab2); ((Object)_itemPrefab).name = "TamedCreatureXP_CreatureBackpack"; _itemPrefab.SetActive(false); ItemDrop component2 = _itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component2 == (Object)null || component2.m_itemData == null || component2.m_itemData.m_shared == null) { Object.Destroy((Object)(object)_itemPrefab); _itemPrefab = null; _registeredObjectDb = null; throw new InvalidOperationException("TrophyWolf template has no usable ItemDrop component."); } component2.m_itemData.m_dropPrefab = _itemPrefab; SharedData shared = component2.m_itemData.m_shared; shared.m_name = "$item_tamedcreaturexp_creaturebackpack"; shared.m_description = "$item_tamedcreaturexp_creaturebackpack_desc"; shared.m_itemType = (ItemType)19; shared.m_maxStackSize = 1; shared.m_weight = 1f; shared.m_teleportable = true; shared.m_useDurability = false; _backpackSprite = CreateBackpackSprite(instance); shared.m_icons = (Sprite[])(object)new Sprite[1] { _backpackSprite }; RegisterLocalization(); RegisterItemWithJotunn(instance, _itemPrefab); EnsureRecipe(instance); Plugin.ModLog.LogInfo((object)(((Object)(object)_recipe == (Object)null) ? "Registered creature backpack item; recipe is waiting for its crafting station and materials." : "Registered universal creature backpack item and Black Forge recipe.")); } internal static void RegisterLocalization() { try { Type type = AccessTools.TypeByName("Jotunn.Managers.LocalizationManager"); object obj = ((type == null) ? null : AccessTools.Property(type, "Instance")?.GetValue(null, null)); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "GetLocalization", Type.EmptyTypes, (Type[])null)); object obj2 = ((obj == null || methodInfo == null) ? null : methodInfo.Invoke(obj, null)); if (obj2 == null) { return; } MethodInfo methodInfo2 = null; MethodInfo[] methods = obj2.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo3 in methods) { if (!(methodInfo3.Name != "AddTranslation")) { ParameterInfo[] parameters = methodInfo3.GetParameters(); if (parameters.Length == 3 && IsStringParameter(parameters[0]) && IsStringParameter(parameters[1]) && IsStringParameter(parameters[2])) { methodInfo2 = methodInfo3; break; } } } if (!(methodInfo2 == null)) { methodInfo2.Invoke(obj2, new object[3] { "English", "item_tamedcreaturexp_creaturebackpack", "Creature Backpack" }); methodInfo2.Invoke(obj2, new object[3] { "French", "item_tamedcreaturexp_creaturebackpack", "Sac à dos de créature" }); methodInfo2.Invoke(obj2, new object[3] { "English", "item_tamedcreaturexp_creaturebackpack_desc", "Equip on a level 4 or higher tamed creature. Press the configured key while targeting it to open its 15-slot backpack." }); methodInfo2.Invoke(obj2, new object[3] { "French", "item_tamedcreaturexp_creaturebackpack_desc", "Équipe ce sac sur une créature apprivoisée de niveau 4 ou plus. Vise-la et appuie sur la touche configurée pour ouvrir son sac de 15 emplacements." }); } } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not register backpack translations through Jotunn: " + ex.Message)); } } private static bool IsStringParameter(ParameterInfo parameter) { if (!(parameter.ParameterType == typeof(string))) { if (parameter.ParameterType.IsByRef) { return parameter.ParameterType.GetElementType() == typeof(string); } return false; } return true; } private static void RegisterItemWithJotunn(ObjectDB database, GameObject prefab) { Type type = AccessTools.TypeByName("Jotunn.Managers.ItemManager"); object obj = ((type == null) ? null : AccessTools.Property(type, "Instance")?.GetValue(null, null)); if (obj == null) { if (!_warnedJotunn) { _warnedJotunn = true; Plugin.ModLog.LogWarning((object)"Jotunn ItemManager is unavailable; the creature backpack is disabled because it cannot be registered safely."); } return; } try { if (_jotunnCustomItem == null) { Type type2 = AccessTools.TypeByName("Jotunn.Entities.CustomItem"); ConstructorInfo constructorInfo = ((type2 == null) ? null : type2.GetConstructor(new Type[2] { typeof(GameObject), typeof(bool) })); MethodInfo methodInfo = ((type2 == null) ? null : AccessTools.Method(type, "AddItem", new Type[1] { type2 }, (Type[])null)); if (constructorInfo != null && methodInfo != null) { _jotunnCustomItem = constructorInfo.Invoke(new object[2] { prefab, false }); _jotunnItemAdded = Convert.ToBoolean(methodInfo.Invoke(obj, new object[1] { _jotunnCustomItem })); } } if (_jotunnCustomItem == null || !_jotunnItemAdded) { if (!_warnedJotunn) { _warnedJotunn = true; Plugin.ModLog.LogWarning((object)"Jotunn did not accept the creature backpack item; it will not be inserted into Valheim's prefab lists directly."); } } else if ((Object)(object)database != (Object)null) { MethodInfo methodInfo2 = AccessTools.Method(type, "RegisterItemInObjectDB", new Type[1] { typeof(GameObject) }, (Type[])null); if (methodInfo2 == null) { throw new MissingMethodException(type.FullName, "RegisterItemInObjectDB(GameObject)"); } methodInfo2.Invoke(obj, new object[1] { prefab }); } } catch (Exception ex) { if (!_warnedJotunn) { _warnedJotunn = true; Plugin.ModLog.LogWarning((object)("Could not register the creature backpack through Jotunn: " + ex)); } } } private static void EnsureRecipe(ObjectDB database) { //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Expected O, but got Unknown if ((Object)(object)_recipe != (Object)null || (Object)(object)database == (Object)null || (Object)(object)_itemPrefab == (Object)null || !(AccessTools.Field(typeof(ObjectDB), "m_recipes")?.GetValue(database) is IList list)) { return; } foreach (object item in list) { Recipe val = (Recipe)((item is Recipe) ? item : null); if ((Object)(object)val != (Object)null && (Object)(object)val.m_item != (Object)null && (Object)(object)((Component)val.m_item).gameObject != (Object)null && ((Object)((Component)val.m_item).gameObject).name == "TamedCreatureXP_CreatureBackpack") { _recipe = val; return; } } ZNetScene instance = ZNetScene.instance; GameObject val2 = (((Object)(object)instance == (Object)null) ? null : instance.GetPrefab("blackforge")); CraftingStation val3 = (((Object)(object)val2 == (Object)null) ? null : val2.GetComponent<CraftingStation>()); ItemDrop component = _itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)val3 == (Object)null || (Object)(object)component == (Object)null) { Plugin.ModLog.LogDebug((object)"Black Forge or backpack item is not registered yet; will retry."); return; } Requirement[] array = (Requirement[])(object)new Requirement[3]; string[] array2 = new string[3] { "BlackMetal", "LinenThread", "FineWood" }; int[] array3 = new int[3] { 4, 4, 4 }; for (int i = 0; i < array.Length; i++) { GameObject itemPrefab = database.GetItemPrefab(array2[i]); ItemDrop val4 = (((Object)(object)itemPrefab == (Object)null) ? null : itemPrefab.GetComponent<ItemDrop>()); if ((Object)(object)val4 == (Object)null) { Plugin.ModLog.LogWarning((object)("Black Forge backpack recipe ingredient is missing: " + array2[i])); return; } array[i] = new Requirement { m_resItem = val4, m_amount = array3[i], m_amountPerLevel = 0 }; } Recipe val5 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val5).name = "Recipe_TamedCreatureXP_CreatureBackpack"; val5.m_item = component; val5.m_amount = 1; val5.m_enabled = false; val5.m_craftingStation = val3; val5.m_resources = array; Type type = AccessTools.TypeByName("Jotunn.Managers.ItemManager"); object obj = ((type == null) ? null : AccessTools.Property(type, "Instance")?.GetValue(null, null)); Type type2 = AccessTools.TypeByName("Jotunn.Entities.CustomRecipe"); ConstructorInfo constructorInfo = ((type2 == null) ? null : type2.GetConstructor(new Type[3] { typeof(Recipe), typeof(bool), typeof(bool) })); MethodInfo methodInfo = ((type == null || type2 == null) ? null : AccessTools.Method(type, "AddRecipe", new Type[1] { type2 }, (Type[])null)); if (obj == null || constructorInfo == null || methodInfo == null) { Plugin.ModLog.LogWarning((object)"Jotunn recipe registration is unavailable; the creature backpack recipe was not added."); return; } _jotunnCustomRecipe = constructorInfo.Invoke(new object[3] { val5, false, false }); bool flag = Convert.ToBoolean(methodInfo.Invoke(obj, new object[1] { _jotunnCustomRecipe })); if (!list.Contains(val5)) { list.Add(val5); } _recipe = val5; try { MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "UpdateKnownRecipesList", (Type[])null, (Type[])null); if ((Object)(object)Player.m_localPlayer != (Object)null && methodInfo2 != null) { methodInfo2.Invoke(Player.m_localPlayer, null); } } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not refresh the local player's recipe list for the creature backpack: " + ex.Message)); } Plugin.ModLog.LogInfo((object)(flag ? "Registered creature backpack recipe at Black Forge (4 Black Metal, 4 Linen Thread, 4 Fine Wood)." : "Creature backpack recipe was already registered with Jotunn.")); } internal static bool UseBackpackItem(Humanoid user, Inventory inventory, ItemData item) { if (!IsBackpackItem(item)) { return true; } Player val = (Player)(object)((user is Player) ? user : null); Character val2 = (((Object)(object)val == (Object)null) ? null : val.GetHoverCreature()); if (!Plugin.IsAllowedTamedCreature(val2) || val2.GetLevel() < 4) { Plugin.ShowMessage(Plugin.IsFrench ? "Cible une créature apprivoisée de niveau 4 ou plus pour lui donner le sac." : "Target a level 4 or higher tamed creature to give it the backpack.", levelUp: false); return false; } ZNetView nView = Plugin.GetNView(val2); ZDO val3 = (((Object)(object)nView != (Object)null && nView.IsValid()) ? nView.GetZDO() : null); if (val3 == null || !ClaimOwnership(nView)) { Plugin.ShowMessage(Plugin.IsFrench ? "Impossible d'accéder aux données de cette créature." : "Could not access this creature's data.", levelUp: false); return false; } if (val3.GetBool("TamedCreatureXP.HasBackpack", false)) { Plugin.ShowMessage(Plugin.IsFrench ? "Cette créature a déjà un sac." : "This creature already has a backpack.", levelUp: false); return false; } val3.Set("TamedCreatureXP.HasBackpack", true); EnsureBackpackVisual(val2); if (inventory != null && item != null) { inventory.RemoveItem(item, 1); } Plugin.ShowMessage(Plugin.IsFrench ? "Sac de bât équipé. Utilise la touche configurée en ciblant la créature pour l'ouvrir." : "Backpack equipped. Use the configured key while targeting the creature to open it.", levelUp: false); Plugin.ModLog.LogInfo((object)("Backpack equipped on " + ((Object)((Component)val2).gameObject).name + ".")); return false; } private static bool IsBackpackItem(ItemData item) { if (item == null || item.m_shared == null) { return false; } if (!string.Equals(item.m_shared.m_name, "$item_tamedcreaturexp_creaturebackpack", StringComparison.Ordinal)) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name == "TamedCreatureXP_CreatureBackpack"; } return false; } return true; } internal static void TryOpenTargetedCreature() { //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)InventoryGui.instance == (Object)null) { return; } Character hoverCreature = localPlayer.GetHoverCreature(); if ((Object)(object)hoverCreature == (Object)null) { Plugin.ShowMessage(Plugin.IsFrench ? "Vise le compagnon portant le sac, puis appuie sur la touche configurée." : "Aim at the creature wearing the backpack, then press the configured key.", levelUp: false); } else { if (!Plugin.IsAllowedTamedCreature(hoverCreature)) { return; } if (hoverCreature.GetLevel() < 4) { Plugin.ShowMessage(Plugin.IsFrench ? "Le sac est disponible à partir du niveau 4." : "The backpack unlocks at level 4.", levelUp: false); return; } ZNetView nView = Plugin.GetNView(hoverCreature); ZDO val = (((Object)(object)nView != (Object)null && nView.IsValid()) ? nView.GetZDO() : null); if (val == null || !val.GetBool("TamedCreatureXP.HasBackpack", false)) { Plugin.ShowMessage(Plugin.IsFrench ? "Cette créature n'a pas de sac de bât." : "This creature has no backpack.", levelUp: false); return; } if (ClaimOwnership(nView)) { try { SaveIfOpen(); if ((Object)(object)_openCreature != (Object)null && (Object)(object)_openCreature != (Object)(object)hoverCreature && (Object)(object)_virtualContainer != (Object)null && (Object)/*isinst with value type is only supported in some contexts*/ == (Object)(object)_virtualContainer) { AccessTools.Method(typeof(InventoryGui), "CloseContainer", (Type[])null, (Type[])null)?.Invoke(InventoryGui.instance, null); } EnsureVirtualContainer(); _virtualInventory = new Inventory(Plugin.IsFrench ? "Sac de bât" : "Creature Backpack", _backpackSprite, 5, 3); SetField(_virtualContainer, "m_inventory", _virtualInventory); ((Component)_virtualContainer).transform.position = ((Component)localPlayer).transform.position; _openCreature = hoverCreature; _openZdo = val; LoadFromZdo(val); InventoryGui.instance.Show(_virtualContainer, 0); _nextPeriodicSave = Time.unscaledTime + 0.75f; object? obj = AccessTools.Field(typeof(InventoryGui), "m_currentContainer")?.GetValue(InventoryGui.instance); if ((Object)((obj is Container) ? obj : null) == (Object)(object)_virtualContainer) { Plugin.ModLog.LogInfo((object)("Opened the backpack inventory for " + Plugin.SafeName(hoverCreature) + ".")); } else { Plugin.ModLog.LogWarning((object)"Valheim's inventory window did not select the virtual creature backpack after Show()."); Plugin.ShowMessage(Plugin.IsFrench ? "Le sac ne s'est pas affiché. Ferme l'inventaire, vise le compagnon et réessaie." : "The backpack did not appear. Close the inventory, target the creature and try again.", levelUp: false); } return; } catch (Exception ex) { _openCreature = null; _openZdo = null; Plugin.ModLog.LogError((object)("Could not open creature backpack: " + ex)); Plugin.ShowMessage(Plugin.IsFrench ? "Erreur lors de l'ouverture du sac." : "Could not open the backpack.", levelUp: false); return; } } Plugin.ShowMessage(Plugin.IsFrench ? "Impossible d'ouvrir le sac pour le moment." : "Could not open the backpack right now.", levelUp: false); } } private static bool ClaimOwnership(ZNetView nview) { if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } if (!nview.IsOwner()) { try { nview.ClaimOwnership(); } catch (Exception ex) { Plugin.ModLog.LogDebug((object)("Could not claim backpack owner: " + ex.Message)); } } return nview.IsOwner(); } private static void EnsureVirtualContainer() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown if (!((Object)(object)_virtualContainer != (Object)null) || _virtualInventory == null) { GameObject val = new GameObject("TamedCreatureXP_VirtualCreatureBackpack"); Object.DontDestroyOnLoad((Object)val); _virtualContainer = val.AddComponent<Container>(); _virtualInventory = new Inventory("Creature Backpack", _backpackSprite, 5, 3); SetField(_virtualContainer, "m_name", Plugin.IsFrench ? "Sac de bât" : "Creature Backpack"); SetField(_virtualContainer, "m_width", 5); SetField(_virtualContainer, "m_height", 3); SetField(_virtualContainer, "m_inventory", _virtualInventory); ((Behaviour)_virtualContainer).enabled = false; } } private static void LoadFromZdo(ZDO zdo) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (zdo == null || _virtualInventory == null) { return; } byte[] byteArray = zdo.GetByteArray("TamedCreatureXP.BackpackContents", (byte[])null); if (byteArray == null || byteArray.Length == 0) { return; } try { ZPackage val = new ZPackage(byteArray); _virtualInventory.Load(val); } catch (Exception ex) { Plugin.ModLog.LogWarning((object)("Could not load creature backpack contents; the stored data was left untouched: " + ex.Message)); } } internal static void SaveIfOpen() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown if (_saving || (Object)(object)_virtualContainer == (Object)null || _virtualInventory == null || _openZdo == null) { return; } InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && (Object)/*isinst with value type is only supported in some contexts*/ != (Object)(object)_virtualContainer) { return; } try { _saving = true; ZPackage val = new ZPackage(); _virtualInventory.Save(val); _openZdo.Set("TamedCreatureXP.BackpackContents", val.GetArray()); } catch (Exception ex) { if (!_warnedSave) { _warnedSave = true; Plugin.ModLog.LogWarning((object)("Could not save creature backpack contents: " + ex.Message)); } } finally { _saving = false; } } private static void OnGuiClosed() { if (_closingVirtualContainer) { _closingVirtualContainer = false; _openCreature = null; _openZdo = null; } } private static void OnGuiClosing() { _closingVirtualContainer = false; if (!((Object)(object)_virtualContainer == (Object)null) && !((Object)(object)InventoryGui.instance == (Object)null) && !((Object)/*isinst with value type is only supported in some contexts*/ != (Object)(object)_virtualContainer)) { SaveIfOpen(); _closingVirtualContainer = true; } } private static bool IsVirtual(Container container) { if ((Object)(object)container != (Object)null) { return (Object)(object)container == (Object)(object)_virtualContainer; } return false; } internal static bool IsVirtualContainerName(string name) { return string.Equals(name, "TamedCreatureXP_VirtualCreatureBackpack", StringComparison.Ordinal); } internal static bool VirtualContainerAwakePrefix(Container instance) { return !IsVirtualContainerName(((Object)(object)instance != (Object)null && (Object)(object)((Component)instance).gameObject != (Object)null) ? ((Object)((Component)instance).gameObject).name : string.Empty); } internal static bool GetInventoryPrefix(Container __instance, ref Inventory __result) { if (!IsVirtual(__instance)) { return true; } __result = _virtualInventory; return false; } internal static bool ContainerLoadPrefix(Container __instance, ref bool __result) { if (!IsVirtual(__instance)) { return true; } __result = true; return false; } internal static bool ContainerSavePrefix(Container __instance) { if (!IsVirtual(__instance)) { return true; } SaveIfOpen(); return false; } internal static bool SetInUsePrefix(Container __instance, bool inUse) { if (!IsVirtual(__instance)) { return true; } SetField(__instance, "m_inUse", inUse); if (!inUse) { SaveIfOpen(); } return false; } internal static void FollowPlayerWhileOpen(InventoryGui gui, Player player) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_virtualContainer == (Object)null) && !((Object)(object)gui == (Object)null) && !((Object)/*isinst with value type is only supported in some contexts*/ != (Object)(object)_virtualContainer)) { Player val = (((Object)(object)player != (Object)null) ? player : Player.m_localPlayer); if ((Object)(object)val != (Object)null) { ((Component)_virtualContainer).transform.position = ((Component)val).transform.position; } } } private static void SetField(object instance, string name, object value) { FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), name); if (fieldInfo != null) { fieldInfo.SetValue(instance, value); } } private static void SetProperty(object instance, string name, object value) { if (instance != null) { PropertyInfo propertyInfo = AccessTools.Property(instance.GetType(), name); if (propertyInfo != null && propertyInfo.CanWrite) { propertyInfo.SetValue(instance, value, null); } } } internal static void UpdateBackpackInventoryStyle(InventoryGui gui) { if ((Object)(object)gui == (Object)null) { return; } object? obj = AccessTools.Field(typeof(InventoryGui), "m_currentContainer")?.GetValue(gui); Container val = (Container)((obj is Container) ? obj : null); object? obj2 = AccessTools.Field(typeof(InventoryGui), "m_container")?.GetValue(gui); RectTransform val2 = (RectTransform)((obj2 is RectTransform) ? obj2 : null); if ((Object)(object)val2 == (Object)null) { return; } Transform val3 = EnsureBackpackPanelFrame(val2); if ((Object)(object)val3 == (Object)null) { return; } bool flag = (Object)(object)val == (Object)(object)_virtualContainer; if (((Component)val3).gameObject.activeSelf != flag) { ((Component)val3).gameObject.SetActive(flag); } if (flag) { val3.SetAsLastSibling(); object? obj3 = AccessTools.Field(typeof(InventoryGui), "m_containerName")?.GetValue(gui); Component val4 = (Component)((obj3 is Component) ? obj3 : null); PropertyInfo propertyInfo = (((Object)(object)val4 == (Object)null) ? null : AccessTools.Property(((object)val4).GetType(), "text")); if (!(propertyInfo == null) && propertyInfo.CanWrite) { string text = (Plugin.IsFrench ? "SAC À DOS DE CRÉATURE" : "CREATURE BACKPACK"); propertyInfo.SetValue(val4, "<color=#B87BEE>★</color> <color=#F3D7FF>" + text + "</color> <color=#B87BEE>★</color>", null); } } } private static Transform EnsureBackpackPanelFrame(RectTransform panel) { //IL_00a3: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panelFrame != (Object)null && (Object)(object)_panelFrame.parent == (Object)(object)panel) { return _panelFrame; } _panelFrame = FindChild((Transform)(object)panel, "TamedCreatureXP_CreatureBackpackPanelFrame"); if ((Object)(object)_panelFrame != (Object)null) { return _panelFrame; } Type type = AccessTools.TypeByName("UnityEngine.UI.Image"); if (type == null) { if (!_warnedPanelStyle) { _warnedPanelStyle = true; Plugin.ModLog.LogWarning((object)"Could not style the backpack panel because Unity UI Image is unavailable."); } return null; } Sprite backpackPanelFrameSprite = GetBackpackPanelFrameSprite(); if ((Object)(object)backpackPanelFrameSprite == (Object)null) { return null; } GameObject val = new GameObject("TamedCreatureXP_CreatureBackpackPanelFrame", new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)panel, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; Component instance = val.AddComponent(type); SetProperty(instance, "sprite", backpackPanelFrameSprite); PropertyInfo propertyInfo = AccessTools.Property(type, "type"); if (propertyInfo != null) { SetProperty(instance, "type", Enum.ToObject(propertyInfo.PropertyType, 1)); } SetProperty(instance, "color", Color.white); SetProperty(instance, "raycastTarget", false); _panelFrame = val.transform; ((Component)_panelFrame).gameObject.SetActive(false); return _panelFrame; } private static Sprite GetBackpackPanelFrameSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: 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) //IL_01dd: 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_0216: 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_024f: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Expected O, but got Unknown if ((Object)(object)_panelFrameSprite != (Object)null) { return _panelFrameSprite; } new Color32((byte)0, (byte)0, (byte)0, (byte)0); Color32[] array = (Color32[])(object)new Color32[4096]; for (int i = 0; i < 64; i++) { SetFramePixel(array, 64, i, 0, new Color32((byte)22, (byte)16, (byte)24, (byte)250)); SetFramePixel(array, 64, i, 1, new Color32((byte)171, (byte)119, (byte)68, (byte)245)); SetFramePixel(array, 64, i, 2, new Color32((byte)74, (byte)48, (byte)48, (byte)238)); SetFramePixel(array, 64, i, 3, new Color32((byte)126, (byte)69, (byte)164, (byte)208)); SetFramePixel(array, 64, i, 4, new Color32((byte)55, (byte)38, (byte)42, (byte)155)); SetFramePixel(array, 64, i, 63, new Color32((byte)22, (byte)16, (byte)24, (byte)250)); SetFramePixel(array, 64, i, 62, new Color32((byte)171, (byte)119, (byte)68, (byte)245)); SetFramePixel(array, 64, i, 61, new Color32((byte)74, (byte)48, (byte)48, (byte)238)); SetFramePixel(array, 64, i, 60, new Color32((byte)126, (byte)69, (byte)164, (byte)208)); SetFramePixel(array, 64, i, 59, new Color32((byte)55, (byte)38, (byte)42, (byte)155)); SetFramePixel(array, 64, 0, i, new Color32((byte)22, (byte)16, (byte)24, (byte)250)); SetFramePixel(array, 64, 1, i, new Color32((byte)171, (byte)119, (byte)68, (byte)245)); SetFramePixel(array, 64, 2, i, new Color32((byte)74, (byte)48, (byte)48, (byte)238)); SetFramePixel(array, 64, 3, i, new Color32((byte)126, (byte)69, (byte)164, (byte)208)); SetFramePixel(array, 64, 4, i, new Color32((byte)55, (byte)38, (byte)42, (byte)155)); SetFramePixel(array, 64, 63, i, new Color32((byte)22, (byte)16, (byte)24, (byte)250)); SetFramePixel(array, 64, 62, i, new Color32((byte)171, (byte)119, (byte)68, (byte)245)); SetFramePixel(array, 64, 61, i, new Color32((byte)74, (byte)48, (byte)48, (byte)238)); SetFramePixel(array, 64, 60, i, new Color32((byte)126, (byte)69, (byte)164, (byte)208)); SetFramePixel(array, 64, 59, i, new Color32((byte)55, (byte)38, (byte)42, (byte)155)); } DrawBackpackFrameCorner(array, 64, right: false, top: false); DrawBackpackFrameCorner(array, 64, right: true, top: false); DrawBackpackFrameCorner(array, 64, right: false, top: true); DrawBackpackFrameCorner(array, 64, right: true, top: true); AddFrameRivet(array, 64, 9, 9); AddFrameRivet(array, 64, 54, 9); AddFrameRivet(array, 64, 9, 54); AddFrameRivet(array, 64, 54, 54); Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { filterMode = (FilterMode)0 }; val.SetPixels32(array); val.Apply(false, true); _panelFrameSprite = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f, 0u, (SpriteMeshType)0, new Vector4(18f, 18f, 18f, 18f)); return _panelFrameSprite; } private static void SetFramePixel(Color32[] pixels, int size, int x, int y, Color32 color) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (x >= 0 && y >= 0 && x < size && y < size) { pixels[y * size + x] = color; } } private static void DrawBackpackFrameCorner(Color32[] pixels, int size, bool right, bool top) { //IL_005e: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) for (int i = 4; i < 18; i++) { for (int j = 4; j < 18; j++) { if (j + i >= 12 && j + i <= 26) { SetOrientedFramePixel(pixels, size, j, i, right, top, new Color32((byte)32, (byte)22, (byte)29, (byte)178)); } } } DrawOrientedFrameLine(pixels, size, 3, 15, 15, 3, right, top, new Color32((byte)201, (byte)151, (byte)89, (byte)235)); DrawOrientedFrameLine(pixels, size, 5, 16, 16, 5, right, top, new Color32((byte)101, (byte)63, (byte)56, (byte)225)); DrawOrientedFrameLine(pixels, size, 8, 16, 16, 8, right, top, new Color32((byte)148, (byte)83, (byte)183, (byte)190)); DrawOrientedFrameLine(pixels, size, 12, 5, 16, 9, right, top, new Color32((byte)209, (byte)159, (byte)92, (byte)235)); DrawOrientedFrameLine(pixels, size, 16, 9, 13, 9, right, top, new Color32((byte)121, (byte)75, (byte)55, (byte)230)); DrawOrientedFrameLine(pixels, size, 6, 5, 8, 7, right, top, new Color32((byte)205, (byte)145, (byte)83, (byte)220)); DrawOrientedFrameLine(pixels, size, 5, 7, 7, 9, right, top, new Color32((byte)126, (byte)77, (byte)163, (byte)205)); } private static void SetOrientedFramePixel(Color32[] pixels, int size, int x, int y, bool right, bool top, Color32 color) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) int x2 = (right ? (size - 1 - x) : x); int y2 = (top ? (size - 1 - y) : y); SetFramePixel(pixels, size, x2, y2, color); } private static void DrawOrientedFrameLine(Color32[] pixels, int size, int x0, int y0, int x1, int y1, bool right, bool top, Color32 color) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) int num = Math.Abs(x1 - x0); int num2 = ((x0 < x1) ? 1 : (-1)); int num3 = -Math.Abs(y1 - y0); int num4 = ((y0 < y1) ? 1 : (-1)); int num5 = num + num3; while (true) { SetOrientedFramePixel(pixels, size, x0, y0, right, top, color); if (x0 != x1 || y0 != y1) { int num6 = 2 * num5; if (num6 >= num3) { num5 += num3; x0 += num2; } if (num6 <= num) { num5 += num; y0 += num4; } continue; } break; } } private static void AddFrameRivet(Color32[] pixels, int size, int centerX, int centerY) { //IL_005b: 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_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_0031: Unknown result type (might be due to invalid IL or missing references) for (int i = -4; i <= 4; i++) { for (int j = -4; j <= 4; j++) { int num = j * j + i * i; if (num <= 16) { Color32 color = ((num >= 10) ? new Color32((byte)38, (byte)25, (byte)31, byte.MaxValue) : ((num >= 4) ? new Color32((byte)202, (byte)148, (byte)84, byte.MaxValue) : new Color32((byte)188, (byte)122, (byte)235, byte.MaxValue))); SetFramePixel(pixels, size, centerX + j, centerY + i, color); } } } } private static void HideBackpackPanelFrame() { if ((Object)(object)_panelFrame != (Object)null && ((Component)_panelFrame).gameObject.activeSelf) { ((Component)_panelFrame).gameObject.SetActive(false); } } private static Sprite CreateBackpackSprite(ObjectDB database) { Sprite val = FindWispLightIcon(database); if ((Object)(object)val != (Object)null) { try { Sprite val2 = CreateVioletWispIcon(val); if ((Object)(object)val2 != (Object)null) { Plugin.ModLog.LogInfo((object)"Using a violet-tinted Wisplight icon for the creature backpack."); return val2; } } catch (Exception ex) { Plugin.ModLog.LogWarning((object)("Could not tint the Wisplight icon; using the original icon instead: " + ex.Message)); } return val; } Plugin.ModLog.LogWarning((object)"Could not find the vanilla Wisplight icon; using the fallback backpack icon."); return CreateDefaultBackpackSprite(); } private static Sprite FindWispLightIcon(ObjectDB database) { if ((Object)(object)database == (Object)null) { return null; } if (!(AccessTools.Field(typeof(ObjectDB), "m_items")?.GetValue(database) is IEnumerable enumerable)) { return null; } GameObject val = null; Sprite result = null; int num = 0; foreach (object item in enumerable) { GameObject val2 = (GameObject)((item is GameObject) ? item : null); ItemDrop val3 = (((Object)(object)val2 == (Object)null) ? null : val2.GetComponent<ItemDrop>()); SharedData val4 = (((Object)(object)val3 == (Object)null || val3.m_itemData == null) ? null : val3.m_itemData.m_shared); if (val4 != null && val4.m_icons != null && val4.m_icons.Length != 0 && !((Object)(object)val4.m_icons[0] == (Object)null)) { string text = ((Object)val2).name ?? string.Empty; string text2 = val4.m_name ?? string.Empty; int num2 = ((text.IndexOf("wisplight", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("wisplight", StringComparison.OrdinalIgnoreCase) >= 0) ? 2 : ((text.IndexOf("wisp", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("wisp", StringComparison.OrdinalIgnoreCase) >= 0) ? 1 : 0)); if (num2 > num) { num = num2; val = val2; result = val4.m_icons[0]; } } } if ((Object)(object)val != (Object)null) { Plugin.ModLog.LogDebug((object)("Selected wisp icon from " + ((Object)val).name + ".")); } return result; } private static Sprite CreateVioletWispIcon(Sprite source) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00e0: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_016c: 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_019c: 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_01d0: 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_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: 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) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source == (Object)null || (Object)(object)source.texture == (Object)null) { return null; } Rect textureRect = source.textureRect; int num = Mathf.RoundToInt(((Rect)(ref textureRect)).x); int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).y); int num3 = Mathf.RoundToInt(((Rect)(ref textureRect)).width); int num4 = Mathf.RoundToInt(((Rect)(ref textureRect)).height); if (num3 <= 0 || num4 <= 0) { return null; } Texture2D texture = source.texture; Color[] pixels; try { pixels = texture.GetPixels(num, num2, num3, num4); } catch (UnityException) { RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; Texture2D val = null; try { Graphics.Blit((Texture)(object)texture, temporary); RenderTexture.active = temporary; val = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0); val.Apply(false, false); pixels = val.GetPixels(num, num2, num3, num4); } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } } Texture2D val2 = new Texture2D(num3, num4, (TextureFormat)4, false); ((Texture)val2).filterMode = (FilterMode)1; for (int i = 0; i < pixels.Length; i++) { Color val3 = pixels[i]; pixels[i] = new Color(Mathf.Min(1f, val3.r * 0.55f + 0.08f), val3.g * 0.34f + 0.025f, Mathf.Min(1f, val3.b * 0.7f + 0.12f), val3.a); } val2.SetPixels(pixels); val2.Apply(false, true); float x = source.pivot.x; Rect rect = source.rect; float num5 = x / ((Rect)(ref rect)).width; float y = source.pivot.y; rect = source.rect; Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(num5, y / ((Rect)(ref rect)).height); return Sprite.Create(val2, new Rect(0f, 0f, (float)num3, (float)num4), val4, source.pixelsPerUnit); } private static Sprite CreateDefaultBackpackSprite() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)0; Color32 val2 = default(Color32); ((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0); Color32 val3 = default(Color32); ((Color32)(ref val3))..ctor((byte)112, (byte)65, (byte)35, byte.MaxValue); Color32 val4 = default(Color32); ((Color32)(ref val4))..ctor((byte)54, (byte)34, (byte)25, byte.MaxValue); Color32 val5 = default(Color32); ((Color32)(ref val5))..ctor((byte)227, (byte)167, (byte)66, byte.MaxValue); Color32[] array = (Color32[])(object)new Color32[1024]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { Color32 val6 = val2; bool flag = j >= 6 && j <= 25 && i >= 4 && i <= 24; bool flag2 = j >= 7 && j <= 24 && i >= 20 && i <= 27; bool flag3 = ((j >= 10 && j <= 12) || (j >= 19 && j <= 21)) && i >= 8 && i <= 26; bool num = j >= 14 && j <= 17 && i >= 12 && i <= 16; bool flag4 = (flag || flag2) && (j == 6 || j == 25 || i == 4 || i == 27); if (flag || flag2) { val6 = (flag4 ? val4 : (flag3 ? val4 : val3)); } if (num) { val6 = val5; } array[i * 32 + j] = val6; } } val.SetPixels32(array); val.Apply(false, true); return Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 32f); } } [BepInPlugin("ElixDrax.TamedCreatureXP", "Tamed Creature XP", "0.5.7")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private sealed class AssistDamageData { public readonly Dictionary<int, Character> Contributors = new Dictionary<int, Character>(); } private sealed class LocalizedConfigSetting { public ConfigurationManagerAttributes Attributes; public string EnglishName; public string FrenchName; public string EnglishCategory; public string FrenchCategory; public string EnglishDescription; public string FrenchDescription; } private sealed class ConfigurationManagerAttributes { public string DispName; public string Category; public string Description; public bool? Browsable; } public const string PluginGuid = "ElixDrax.TamedCreatureXP"; public const string PluginName = "Tamed Creature XP"; public const string PluginVersion = "0.5.7"; internal static Plugin Instance; internal static ManualLogSource ModLog; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<int> XPPerKill; internal static ConfigEntry<int> MaxLevel; internal static ConfigEntry<int> XPLevel2; internal static ConfigEntry<int> XPLevel3; internal static ConfigEntry<int> XPLevel4; internal static ConfigEntry<int> XPLevel5; internal static ConfigEntry<int> XPLevel6; private static ConfigEntry<int> ProgressionDefaultsVersion; private static ConfigEntry<int> LevelUpBonusDefaultsVersion; internal static ConfigEntry<string> HigherLevelThresholds; internal static ConfigEntry<bool> BossesAllowed; internal static ConfigEntry<bool> AwardXPForAssistDamage; internal static ConfigEntry<bool> ShowXPGained; internal static ConfigEntry<bool> ShowLevelUp; internal static ConfigEntry<bool> ShowProgress; internal static ConfigEntry<bool> ShowStarsAboveVanillaCap; internal static ConfigEntry<string> CreatureMultipliers; internal static ConfigEntry<string> VictimMultipliers; internal static ConfigEntry<string> VictimXPValues; internal static ConfigEntry<string> WizardryVictimXPValues; internal static ConfigEntry<bool> ShowCreatureStatusOnHover; internal static ConfigEntry<bool> FrenchInterface; internal static ConfigEntry<int> LevelUpHealAmount; internal static ConfigEntry<float> LevelUpShieldSeconds; internal static ConfigEntry<KeyboardShortcut> OpenBackpackKey; internal static ConfigEntry<bool> BackpackUnlocked; internal static bool SuppressNameDecorations; private Harmony _harmony; private bool _portablePalsPatched; private float _portablePalsRetryTimer; private float _backpackUpdateTimer; private static readonly List<LocalizedConfigSetting> LocalizedConfigSettings = new List<LocalizedConfigSetting>(); private static readonly HashSet<string> UnmappedVictimPrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static bool WizardryDetected; private static readonly ConditionalWeakTable<Character, AssistDamageData> AssistDamageByVictim = new ConditionalWeakTable<Character, AssistDamageData>(); internal static bool IsFrench { get { if (FrenchInterface != null) { return FrenchInterface.Value; } return false; } } private void Awake() { //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Expected O, but got Unknown //IL_05ad: Unknown result type (might be due to invalid IL or missing references) //IL_063b: Unknown result type (might be due to invalid IL or missing references) //IL_0645: Expected O, but got Unknown Instance = this; ModLog = Logger.CreateLogSource("TamedCreatureXP"); WizardryDetected = DetectWizardryPlugin(); Enabled = BindSetting("General", "Enabled", defaultValue: true, "Enabled", "Activé", "Enable tamed creature XP.", "Active les gains d'XP des créatures apprivoisées."); XPPerKill = BindSetting("Advanced XP", "XP Per Kill", 25, "XP Per Kill", "XP de secours par élimination", "Fallback XP for a creature without a per-creature XP entry.", "XP de secours si une créature n'a pas de valeur individuelle."); CreatureMultipliers = BindSetting("XP", "Creature Multipliers", "", "Creature Multipliers", "Multiplicateurs des créatures apprivoisées", "Optional multipliers for the tamed killer, e.g. Wolf=1.2;Lox=0.8.", "Multiplicateurs facultatifs pour la créature apprivoisée qui tue, ex. Wolf=1.2;Lox=0.8."); VictimMultipliers = BindSetting("XP", "Defeated Creature Multipliers", "", "Defeated Creature Multipliers", "Multiplicateurs des cibles vaincues", "Optional multipliers by defeated creature, e.g. Troll=2;Eikthyr=4.", "Multiplicateurs selon la créature vaincue, ex. Troll=2;Eikthyr=4."); VictimXPValues = BindSetting("XP", "Defeated Creature XP", GetDefaultVictimXPValues(), "Defeated Creature XP", "XP par créature vaincue", "Base XP awarded for each vanilla creature at level 1. Format: Prefab=XP;Prefab=XP. Other creatures use XP Per Kill.", "XP de base accordée pour chaque créature vanilla de niveau 1. Format : Préfab=XP;Préfab=XP. Les autres créatures utilisent XP par élimination."); EnsureKnownPrefabXP("TrollFrost", 50); EnsureKnownPrefabXP("Fenring_Cultist_Hildir_nochest", 300); EnsureKnownPrefabXP("Skeleton_Swamps", 18); EnsureKnownPrefabXP("Draugr_Ranged", 18); if (WizardryDetected) { WizardryVictimXPValues = BindSetting("Wizardry XP", "Defeated Wizardry Creature XP", GetDefaultWizardryXPValues(), "Defeated Wizardry Creature XP", "XP par créature Wizardry vaincue", "Base XP for Wizardry creature prefabs at level 1. Format: Prefab=XP;Prefab=XP.", "XP de base pour les prefabs de créatures Wizardry au niveau 1. Format : Préfab=XP;Préfab=XP."); } MaxLevel = BindSetting("Advanced XP", "Max Level", 100, "Max Level", "Niveau maximal", "Optional upper cap from 1 to 100. Without extra thresholds, the effective max remains level 6.", "Plafond facultatif de 1 à 100. Sans seuils supplémentaires, le niveau maximal effectif reste 6."); XPLevel2 = BindSetting("XP", "XP To Level 2", 700, "XP To Level 2", "XP pour le niveau 2", "Total XP required to reach level 2.", "Total d'XP requis pour atteindre le niveau 2."); XPLevel3 = BindSetting("XP", "XP To Level 3", 1700, "XP To Level 3", "XP pour le niveau 3", "Total XP required to reach level 3.", "Total d'XP requis pour atteindre le niveau 3."); XPLevel4 = BindSetting("XP", "XP To Level 4", 3200, "XP To Level 4", "XP pour le niveau 4", "Total XP required to reach level 4.", "Total d'XP requis pour atteindre le niveau 4."); XPLevel5 = BindSetting("XP", "XP To Level 5", 5200, "XP To Level 5", "XP pour le niveau 5", "Total XP required to reach level 5.", "Total d'XP requis pour atteindre le niveau 5."); XPLevel6 = BindSetting("XP", "XP To Level 6", 8000, "XP To Level 6", "XP pour le niveau 6", "Total XP required to reach level 6.", "Total d'XP requis pour atteindre le niveau 6."); HigherLevelThresholds = BindSetting("Advanced XP", "XP Thresholds for Levels 7+", "", "XP Thresholds for Levels 7+", "Seuils d'XP des niveaux 7 et +", "Optional cumulative XP thresholds. Example: 7=11000;8=15000;9=20000. Add consecutive levels with each total higher than the previous level. Maximum supported level: 100.", "Seuils d'XP totaux facultatifs. Exemple : 7=11000;8=15000;9=20000. Ajoute les niveaux à la suite avec un total supérieur au précédent. Niveau maximal pris en charge : 100."); ProgressionDefaultsVersion = ((BaseUnityPlugin)this).Config.Bind<int>("Internal", "Progression Defaults Version", 0, new ConfigDescription("Internal one-time migration marker.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Browsable = false } })); if (ProgressionDefaultsVersion.Value < 1) { XPLevel2.Value = 700; XPLevel3.Value = 1700; XPLevel4.Value = 3200; XPLevel5.Value = 5200; XPLevel6.Value = 8000; ProgressionDefaultsVersion.Value = 1; ((BaseUnityPlugin)this).Config.Save(); } if (ProgressionDefaultsVersion.Value < 2) { MaxLevel.Value = 100; ProgressionDefaultsVersion.Value = 2; ((BaseUnityPlugin)this).Config.Save(); } BossesAllowed = BindSetting("Rules", "Bosses Allowed",