Decompiled source of ValheimCuisine v2.2.4
ValheimCuisine.dll
Decompiled 3 days 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Timers; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CreatureManager; using HarmonyLib; using ItemManager; using JetBrains.Annotations; using LocalizationManager; using LocationManager; using Microsoft.CodeAnalysis; using PieceManager; using ServerSync; using SoftReferenceableAssets; using StatusEffectManager; using TMPro; using UnityEngine; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ValheimCuisine")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyProduct("ValheimCuisine")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("E0E2F92E-557C-4A05-9D89-AA92A0BD75C4")] [assembly: AssemblyFileVersion("2.2.4")] [assembly: AssemblyCompany("XutzBR")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.2.4.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<b13a31e8-09bd-4e5b-9371-9b1fbc4162c6>Embedded] internal sealed class <b13a31e8-09bd-4e5b-9371-9b1fbc4162c6>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<b13a31e8-09bd-4e5b-9371-9b1fbc4162c6>Embedded] [CompilerGenerated] internal sealed class <f702c462-8385-4673-b169-bde4ff02a79f>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <f702c462-8385-4673-b169-bde4ff02a79f>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <f702c462-8385-4673-b169-bde4ff02a79f>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [<b13a31e8-09bd-4e5b-9371-9b1fbc4162c6>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [CompilerGenerated] internal sealed class <275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContextAttribute : Attribute { public readonly byte Flag; public <275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace ValheimCuisine { [BepInPlugin("XutzBR.ValheimCuisine", "ValheimCuisine", "2.2.4")] [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] public class ValheimCuisinePlugin : BaseUnityPlugin { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] private class GrimpyBoxConversionData { public int RequiredAmount { get; set; } public int ProducedAmount { get; set; } public GrimpyBoxConversionData(int requiredAmount, int producedAmount) { RequiredAmount = requiredAmount; ProducedAmount = producedAmount; } } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public class ConversionData { public string ToItem { get; set; } public float CookTime { get; set; } public int ProducedItems { get; set; } public ConversionData(string toItem, float cookTime = 0f, int producedItems = 0) { ToItem = toItem; CookTime = cookTime; ProducedItems = producedItems; } } [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] public enum Toggle { On = 1, Off = 0 } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class ButcherTableCraftingStationPatch { private static void Postfix(ZNetScene __instance) { //IL_00a7: 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_00f5: Expected O, but got Unknown //IL_00ff: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown if ((Object)(object)__instance == (Object)null) { return; } GameObject prefab = __instance.GetPrefab("cauldron_ext3_butchertable"); if ((Object)(object)prefab == (Object)null) { ValheimCuisineLogger.LogWarning((object)"Could not find butcher table prefab 'cauldron_ext3_butchertable'"); return; } CraftingStation component = prefab.GetComponent<CraftingStation>(); if ((Object)(object)component != (Object)null) { ValheimCuisineLogger.LogDebug((object)"CraftingStation already exists on butcher table, skipping..."); return; } component = prefab.AddComponent<CraftingStation>(); component.m_name = "$piece_cauldron_ext3_butchertable"; component.m_discoverRange = 4f; component.m_rangeBuild = 20f; component.m_useDistance = 2f; component.m_useAnimation = 1; component.m_craftingSkill = (SkillType)105; component.m_craftRequireRoof = false; component.m_craftRequireFire = false; Piece component2 = prefab.GetComponent<Piece>(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_icon != (Object)null) { component.m_icon = component2.m_icon; } CraftingStation obj = component; EffectList val = new EffectList(); val.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { new EffectData { m_prefab = GetEffectPrefab(__instance, "VC_sfx_ChefTableCraft"), m_enabled = true, m_variant = -1 } }; obj.m_craftItemEffects = val; CraftingStation obj2 = component; val = new EffectList(); val.m_effectPrefabs = (EffectData[])(object)new EffectData[1] { new EffectData { m_prefab = GetEffectPrefab(__instance, "VC_sfx_gui_craftitem_workbench_end"), m_enabled = true, m_variant = -1 } }; obj2.m_craftItemDoneEffects = val; ValheimCuisineLogger.LogInfo((object)"Successfully added CraftingStation component to butcher table"); } private static GameObject GetEffectPrefab(ZNetScene zNetScene, string effectName) { GameObject prefab = zNetScene.GetPrefab(effectName); if ((Object)(object)prefab == (Object)null) { ValheimCuisineLogger.LogWarning((object)("Effect prefab '" + effectName + "' not found in ZNetScene")); } return prefab; } } [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] [HarmonyPatch(typeof(StationExtension), "GetHoverText")] public static class ButcherTableHoverTextPatch { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] private static void Postfix(StationExtension __instance, ref string __result) { string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); if (prefabName != "cauldron_ext3_butchertable" || (Object)(object)Player.m_localPlayer == (Object)null) { return; } CraftingStation component = ((Component)__instance).GetComponent<CraftingStation>(); if (!((Object)(object)component == (Object)null)) { if (!component.InUseDistance((Humanoid)(object)Player.m_localPlayer)) { __result = Localization.instance.Localize("<color=#888888>$piece_toofar</color>"); } else { __result = Localization.instance.Localize("$piece_cauldron_ext3_butchertable\n[<color=yellow><b>$KEY_Use</b></color>] $piece_use"); } } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] private static class ConversionsZNetScene_AwakePost_Patch { private static List<ItemConversion> vanillaCookingStationConversions; private static List<ItemConversion> vanillaCookingStationIronConversions; private static List<ItemConversion> vanillaOvenConversions; private static List<ItemConversion> vanillaFermenterConversions; private static void Postfix(ZNetScene __instance) { ReapplyConversions(__instance); } public static void ReapplyConversions(ZNetScene scene) { if ((Object)(object)scene == (Object)null) { return; } List<GameObject> prefabs = scene.m_prefabs; if (prefabs == null || prefabs.Count <= 0) { return; } try { GameObject prefab = scene.GetPrefab("piece_cookingstation"); CookingStation val = ((prefab != null) ? prefab.GetComponent<CookingStation>() : null); GameObject prefab2 = scene.GetPrefab("piece_cookingstation_iron"); CookingStation val2 = ((prefab2 != null) ? prefab2.GetComponent<CookingStation>() : null); GameObject prefab3 = scene.GetPrefab("piece_oven"); CookingStation val3 = ((prefab3 != null) ? prefab3.GetComponent<CookingStation>() : null); GameObject prefab4 = scene.GetPrefab("fermenter"); Fermenter val4 = ((prefab4 != null) ? prefab4.GetComponent<Fermenter>() : null); if (vanillaCookingStationConversions == null && (Object)(object)val != (Object)null && val.m_conversion != null) { vanillaCookingStationConversions = new List<ItemConversion>(val.m_conversion); } if (vanillaCookingStationIronConversions == null && (Object)(object)val2 != (Object)null && val2.m_conversion != null) { vanillaCookingStationIronConversions = new List<ItemConversion>(val2.m_conversion); } if (vanillaOvenConversions == null && (Object)(object)val3 != (Object)null && val3.m_conversion != null) { vanillaOvenConversions = new List<ItemConversion>(val3.m_conversion); } if (vanillaFermenterConversions == null && (Object)(object)val4 != (Object)null && val4.m_conversion != null) { vanillaFermenterConversions = new List<ItemConversion>(val4.m_conversion); } GameObject prefab5 = scene.GetPrefab("VC_SmokehouseWood"); CookingStation val5 = ((prefab5 != null) ? prefab5.GetComponent<CookingStation>() : null); GameObject prefab6 = scene.GetPrefab("VC_SmokehouseStone"); CookingStation val6 = ((prefab6 != null) ? prefab6.GetComponent<CookingStation>() : null); GameObject prefab7 = scene.GetPrefab("VC_DryingHook"); CookingStation val7 = ((prefab7 != null) ? prefab7.GetComponent<CookingStation>() : null); GameObject prefab8 = scene.GetPrefab("VC_DryingRack"); CookingStation val8 = ((prefab8 != null) ? prefab8.GetComponent<CookingStation>() : null); GameObject prefab9 = scene.GetPrefab("VC_FoodBarrel1"); Fermenter val9 = ((prefab9 != null) ? prefab9.GetComponent<Fermenter>() : null); GameObject prefab10 = scene.GetPrefab("VC_FoodBarrel2"); Fermenter val10 = ((prefab10 != null) ? prefab10.GetComponent<Fermenter>() : null); GameObject prefab11 = scene.GetPrefab("VC_LegendFermenter"); Fermenter val11 = ((prefab11 != null) ? prefab11.GetComponent<Fermenter>() : null); GameObject prefab12 = scene.GetPrefab("VC_DvergrCauldron"); Fermenter val12 = ((prefab12 != null) ? prefab12.GetComponent<Fermenter>() : null); ClearAllConversions(val, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12); if ((Object)(object)val != (Object)null) { RestoreVanillaConversions(val, vanillaCookingStationConversions); ApplyCookingStationConversions(scene, val, CookingStationConversions.Value, "Cooking Station"); } if ((Object)(object)val2 != (Object)null) { RestoreVanillaConversions(val2, vanillaCookingStationIronConversions); ApplyCookingStationConversions(scene, val2, CookingStationIronConversions.Value, "Iron Cooking Station"); } if ((Object)(object)val3 != (Object)null) { RestoreVanillaConversions(val3, vanillaOvenConversions); ApplyCookingStationConversions(scene, val3, OvenConversions.Value, "Oven"); } if ((Object)(object)val4 != (Object)null) { RestoreVanillaConversions(val4, vanillaFermenterConversions); ApplyFermenterConversions(scene, val4, FermenterConversions.Value, "Fermenter"); } if ((Object)(object)val5 != (Object)null) { ApplyCookingStationConversions(scene, val5, SmokehouseWoodConversions.Value, "Wooden Smokehouse"); } if ((Object)(object)val6 != (Object)null) { ApplyCookingStationConversions(scene, val6, SmokehouseStoneConversions.Value, "Stone Smokehouse"); } if ((Object)(object)val7 != (Object)null) { ApplyCookingStationConversions(scene, val7, DryingRack1Conversions.Value, "Drying Hook"); } if ((Object)(object)val8 != (Object)null) { ApplyCookingStationConversions(scene, val8, DryingRack2Conversions.Value, "Drying Rack"); } if ((Object)(object)val9 != (Object)null) { ApplyFermenterConversions(scene, val9, FoodBarrel1Conversions.Value, "Food Fermenter"); } if ((Object)(object)val10 != (Object)null) { ApplyFermenterConversions(scene, val10, FoodBarrel2Conversions.Value, "Ashwood Food Fermenter"); } if ((Object)(object)val11 != (Object)null) { ApplyFermenterConversions(scene, val11, LegendFermenterConversions.Value, "Great Fermenter"); } if ((Object)(object)val12 != (Object)null) { ApplyFermenterConversions(scene, val12, DvergrCauldronConversions.Value, "Dvergr Cauldron"); } UpdateAllWorldInstances(scene, val, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11, val12); ValheimCuisineLogger.LogInfo((object)"[Conversions] All conversions applied from config (prefabs and world instances updated)"); } catch (Exception arg) { ValheimCuisineLogger.LogError((object)$"Error applying conversions: {arg}"); } } private static void RestoreVanillaConversions(CookingStation station, List<ItemConversion> vanillaConversions) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_005e: Expected O, but got Unknown if ((Object)(object)station == (Object)null || vanillaConversions == null) { return; } foreach (ItemConversion vanillaConversion in vanillaConversions) { station.m_conversion.Add(new ItemConversion { m_from = vanillaConversion.m_from, m_to = vanillaConversion.m_to, m_cookTime = vanillaConversion.m_cookTime }); } } private static void RestoreVanillaConversions(Fermenter fermenter, List<ItemConversion> vanillaConversions) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_005e: Expected O, but got Unknown if ((Object)(object)fermenter == (Object)null || vanillaConversions == null) { return; } foreach (ItemConversion vanillaConversion in vanillaConversions) { fermenter.m_conversion.Add(new ItemConversion { m_from = vanillaConversion.m_from, m_to = vanillaConversion.m_to, m_producedItems = vanillaConversion.m_producedItems }); } } private static void UpdateAllWorldInstances(ZNetScene scene, CookingStation cookingStationPrefab, CookingStation cookingStationIronPrefab, CookingStation cookingStationOvenPrefab, Fermenter fermenterPrefab, CookingStation smokehouseWoodPrefab, CookingStation smokehouseStonePrefab, CookingStation dryingRack1Prefab, CookingStation dryingRack2Prefab, Fermenter foodBarrel1Prefab, Fermenter foodBarrel2Prefab, Fermenter legendFermenterPrefab, Fermenter dvergrCauldronPrefab) { int num = 0; CookingStation[] array = Object.FindObjectsOfType<CookingStation>(); foreach (CookingStation val in array) { if (!((Object)(object)val == (Object)null)) { string prefabName = Utils.GetPrefabName(((Component)val).gameObject); if (prefabName == "piece_cookingstation" && (Object)(object)cookingStationPrefab != (Object)null) { val.m_conversion = new List<ItemConversion>(cookingStationPrefab.m_conversion); num++; } else if (prefabName == "piece_cookingstation_iron" && (Object)(object)cookingStationIronPrefab != (Object)null) { val.m_conversion = new List<ItemConversion>(cookingStationIronPrefab.m_conversion); num++; } else if (prefabName == "piece_oven" && (Object)(object)cookingStationOvenPrefab != (Object)null) { val.m_conversion = new List<ItemConversion>(cookingStationOvenPrefab.m_conversion); num++; } else if (prefabName == "VC_SmokehouseWood" && (Object)(object)smokehouseWoodPrefab != (Object)null) { val.m_conversion = new List<ItemConversion>(smokehouseWoodPrefab.m_conversion); num++; } else if (prefabName == "VC_SmokehouseStone" && (Object)(object)smokehouseStonePrefab != (Object)null) { val.m_conversion = new List<ItemConversion>(smokehouseStonePrefab.m_conversion); num++; } else if (prefabName == "VC_DryingHook" && (Object)(object)dryingRack1Prefab != (Object)null) { val.m_conversion = new List<ItemConversion>(dryingRack1Prefab.m_conversion); num++; } else if (prefabName == "VC_DryingRack" && (Object)(object)dryingRack2Prefab != (Object)null) { val.m_conversion = new List<ItemConversion>(dryingRack2Prefab.m_conversion); num++; } } } Fermenter[] array2 = Object.FindObjectsOfType<Fermenter>(); foreach (Fermenter val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { string prefabName2 = Utils.GetPrefabName(((Component)val2).gameObject); if (prefabName2 == "fermenter" && (Object)(object)fermenterPrefab != (Object)null) { val2.m_conversion = new List<ItemConversion>(fermenterPrefab.m_conversion); num++; } else if (prefabName2 == "VC_FoodBarrel1" && (Object)(object)foodBarrel1Prefab != (Object)null) { val2.m_conversion = new List<ItemConversion>(foodBarrel1Prefab.m_conversion); num++; } else if (prefabName2 == "VC_FoodBarrel2" && (Object)(object)foodBarrel2Prefab != (Object)null) { val2.m_conversion = new List<ItemConversion>(foodBarrel2Prefab.m_conversion); num++; } else if (prefabName2 == "VC_LegendFermenter" && (Object)(object)legendFermenterPrefab != (Object)null) { val2.m_conversion = new List<ItemConversion>(legendFermenterPrefab.m_conversion); num++; } else if (prefabName2 == "VC_DvergrCauldron" && (Object)(object)dvergrCauldronPrefab != (Object)null) { val2.m_conversion = new List<ItemConversion>(dvergrCauldronPrefab.m_conversion); num++; } } } if (num > 0) { ValheimCuisineLogger.LogInfo((object)$"[Conversions] Updated {num} existing station instances in the world"); } } private static void ClearAllConversions(params object[] stations) { foreach (object obj in stations) { if (obj != null) { CookingStation val = (CookingStation)((obj is CookingStation) ? obj : null); if (val != null) { val.m_conversion.Clear(); } else { ((Fermenter)(((obj is Fermenter) ? obj : null)?)).m_conversion.Clear(); } } } } private static void ApplyCookingStationConversions(ZNetScene scene, CookingStation station, string configValue, string stationName) { //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(configValue)) { return; } string[] array = configValue.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); int num = 0; string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split(new char[1] { ':' }); if (array3.Length != 3) { ValheimCuisineLogger.LogWarning((object)("[Conversions] Invalid format for " + stationName + ": " + text)); continue; } string text2 = array3[0].Trim(); string text3 = array3[1].Trim(); if (!float.TryParse(array3[2].Trim(), out var result)) { ValheimCuisineLogger.LogWarning((object)("[Conversions] Invalid cook time for " + stationName + ": " + array3[2])); continue; } GameObject prefab = scene.GetPrefab(text2); GameObject prefab2 = scene.GetPrefab(text3); if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab2 == (Object)null)) { ItemDrop component = prefab.GetComponent<ItemDrop>(); ItemDrop component2 = prefab2.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null)) { station.m_conversion.Add(new ItemConversion { m_cookTime = result, m_from = component, m_to = component2 }); num++; } } } if (num > 0) { ValheimCuisineLogger.LogInfo((object)$"[Conversions] Added {num} conversions to {stationName}"); } } private static void ApplyFermenterConversions(ZNetScene scene, Fermenter fermenter, string configValue, string fermenterName) { //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(configValue)) { return; } string[] array = configValue.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); int num = 0; string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split(new char[1] { ':' }); if (array3.Length != 3) { ValheimCuisineLogger.LogWarning((object)("[Conversions] Invalid format for " + fermenterName + ": " + text)); continue; } string text2 = array3[0].Trim(); string text3 = array3[1].Trim(); if (!int.TryParse(array3[2].Trim(), out var result)) { ValheimCuisineLogger.LogWarning((object)("[Conversions] Invalid produced items for " + fermenterName + ": " + array3[2])); continue; } GameObject prefab = scene.GetPrefab(text2); GameObject prefab2 = scene.GetPrefab(text3); if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab2 == (Object)null)) { ItemDrop component = prefab.GetComponent<ItemDrop>(); ItemDrop component2 = prefab2.GetComponent<ItemDrop>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null)) { fermenter.m_conversion.Add(new ItemConversion { m_from = component, m_to = component2, m_producedItems = result }); num++; } } } if (num > 0) { ValheimCuisineLogger.LogInfo((object)$"[Conversions] Added {num} conversions to {fermenterName}"); } } } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class GullDropsPatch { public static void Postfix(ZNetScene __instance) { GameObject prefab = __instance.GetPrefab("Seagal"); if ((Object)(object)prefab == (Object)null) { Debug.LogWarning((object)"[BirdDroppings] Seagal prefab not found."); return; } DropOnDestroyed component = prefab.GetComponent<DropOnDestroyed>(); if ((Object)(object)component == (Object)null) { Debug.LogWarning((object)"[BirdDroppings] Seagal has no DropOnDestroyed component."); return; } AddDrop(component, "VC_BirdMeat", 1, 1, 1f); component.m_dropWhenDestroyed.m_dropMin = component.m_dropWhenDestroyed.m_drops.Count; component.m_dropWhenDestroyed.m_dropMax = component.m_dropWhenDestroyed.m_drops.Count; component.m_dropWhenDestroyed.m_oneOfEach = true; Debug.Log((object)$"[BirdDroppings] Seagal will now drop {component.m_dropWhenDestroyed.m_drops.Count} items every time."); } private static void AddDrop(DropOnDestroyed seagalDrop, string itemName, int min, int max, float weight) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName); if ((Object)(object)itemPrefab == (Object)null) { Debug.LogWarning((object)("[BirdDroppings] Item prefab '" + itemName + "' not found.")); return; } DropData val = default(DropData); val.m_item = itemPrefab; val.m_stackMin = min; val.m_stackMax = max; val.m_weight = weight; DropData item = val; seagalDrop.m_dropWhenDestroyed.m_drops.Add(item); Debug.Log((object)$"[BirdDroppings] Added {itemName} x{min}-{max} to Seagal drops."); } } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class CrowDropsPatch { public static void Postfix(ZNetScene __instance) { GameObject prefab = __instance.GetPrefab("Crow"); if ((Object)(object)prefab == (Object)null) { Debug.LogWarning((object)"[BirdDroppings] Crow prefab not found."); return; } DropOnDestroyed component = prefab.GetComponent<DropOnDestroyed>(); if ((Object)(object)component == (Object)null) { Debug.LogWarning((object)"[BirdDroppings] Crow has no DropOnDestroyed component."); return; } AddDrop(component, "VC_BirdMeat", 1, 1, 1f); component.m_dropWhenDestroyed.m_dropMin = component.m_dropWhenDestroyed.m_drops.Count; component.m_dropWhenDestroyed.m_dropMax = component.m_dropWhenDestroyed.m_drops.Count; component.m_dropWhenDestroyed.m_oneOfEach = true; Debug.Log((object)$"[BirdDroppings] Crow will now drop {component.m_dropWhenDestroyed.m_drops.Count} items every time."); } private static void AddDrop(DropOnDestroyed crowDrop, string itemName, int min, int max, float weight) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName); if ((Object)(object)itemPrefab == (Object)null) { Debug.LogWarning((object)("[BirdDroppings] Item prefab '" + itemName + "' not found.")); return; } DropData val = default(DropData); val.m_item = itemPrefab; val.m_stackMin = min; val.m_stackMax = max; val.m_weight = weight; DropData item = val; crowDrop.m_dropWhenDestroyed.m_drops.Add(item); Debug.Log((object)$"[BirdDroppings] Added {itemName} x{min}-{max} to Crow drops."); } } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class ashcrowDropsPatch { public static void Postfix(ZNetScene __instance) { GameObject prefab = __instance.GetPrefab("AshCrow"); if ((Object)(object)prefab == (Object)null) { Debug.LogWarning((object)"[BirdDroppings] AshCrow prefab not found."); return; } DropOnDestroyed component = prefab.GetComponent<DropOnDestroyed>(); if ((Object)(object)component == (Object)null) { Debug.LogWarning((object)"[BirdDroppings] AshCrow has no DropOnDestroyed component."); return; } AddDrop(component, "VC_BirdMeat", 1, 1, 1f); component.m_dropWhenDestroyed.m_dropMin = component.m_dropWhenDestroyed.m_drops.Count; component.m_dropWhenDestroyed.m_dropMax = component.m_dropWhenDestroyed.m_drops.Count; component.m_dropWhenDestroyed.m_oneOfEach = true; Debug.Log((object)$"[BirdDroppings] AshCrow will now drop {component.m_dropWhenDestroyed.m_drops.Count} items every time."); } private static void AddDrop(DropOnDestroyed ashcrowDrop, string itemName, int min, int max, float weight) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName); if ((Object)(object)itemPrefab == (Object)null) { Debug.LogWarning((object)("[BirdDroppings] Item prefab '" + itemName + "' not found.")); return; } DropData val = default(DropData); val.m_item = itemPrefab; val.m_stackMin = min; val.m_stackMax = max; val.m_weight = weight; DropData item = val; ashcrowDrop.m_dropWhenDestroyed.m_drops.Add(item); Debug.Log((object)$"[BirdDroppings] Added {itemName} x{min}-{max} to AshCrow drops."); } } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public class GrimpyBoxConverter : MonoBehaviour { private static readonly List<GrimpyBoxConverter> m_instances = new List<GrimpyBoxConverter>(); private Container m_container; private ZNetView m_nview; private void Awake() { m_container = ((Component)this).GetComponent<Container>(); m_nview = m_container?.m_nview; if (!((Object)(object)m_container == (Object)null) && !((Object)(object)m_nview == (Object)null) && m_nview.IsValid()) { ((MonoBehaviour)this).InvokeRepeating("UpdateConversion", 1f, GrimpyBoxConversionTime.Value); m_instances.Add(this); ValheimCuisineLogger.LogInfo((object)("[GrimpyBox] Converter initialized on " + ((Object)((Component)this).gameObject).name)); } } private void OnDestroy() { m_instances.Remove(this); } public static void UpdateConversionRate() { foreach (GrimpyBoxConverter instance in m_instances) { ((MonoBehaviour)instance).CancelInvoke("UpdateConversion"); ((MonoBehaviour)instance).InvokeRepeating("UpdateConversion", 0f, GrimpyBoxConversionTime.Value); } } private void UpdateConversion() { if ((Object)(object)m_container == (Object)null || (Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner()) { return; } Inventory inventory = m_container.GetInventory(); if (inventory == null) { return; } List<ItemData> allItems = inventory.GetAllItems(); if (!GetConversion(allItems, out var itemToConvert, out var conversionData) || itemToConvert == null || conversionData == null) { return; } string itemPrefabName = GetItemPrefabName(itemToConvert); int num = allItems.Where([<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (ItemData i) => GetItemPrefabName(i) == itemPrefabName).Sum([<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (ItemData i) => i.m_stack); if (num < conversionData.RequiredAmount) { return; } int num2 = conversionData.RequiredAmount; foreach (ItemData item in allItems.ToList()) { if (!(GetItemPrefabName(item) != itemPrefabName)) { if (item.m_stack >= num2) { inventory.RemoveItem(item, num2); break; } num2 -= item.m_stack; inventory.RemoveItem(item, item.m_stack); } } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Ectoplasm"); if ((Object)(object)itemPrefab == (Object)null) { ValheimCuisineLogger.LogError((object)"[GrimpyBox] Ectoplasm prefab not found in ObjectDB!"); return; } ItemData val = itemPrefab.GetComponent<ItemDrop>().m_itemData.Clone(); val.m_stack = conversionData.ProducedAmount; if (inventory.AddItem(val)) { ValheimCuisineLogger.LogInfo((object)$"[GrimpyBox] Converted {conversionData.RequiredAmount}x {itemPrefabName} to {conversionData.ProducedAmount}x Ectoplasm"); } else { ValheimCuisineLogger.LogError((object)"[GrimpyBox] Failed to add Ectoplasm to inventory!"); } m_container.Save(); } private bool GetConversion(List<ItemData> items, out ItemData itemToConvert, out GrimpyBoxConversionData conversionData) { itemToConvert = null; conversionData = null; foreach (ItemData item in items) { string itemPrefabName = GetItemPrefabName(item); if (grimpyBoxConversionDict.TryGetValue(itemPrefabName, out var value)) { int num = items.Where([<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (ItemData i) => GetItemPrefabName(i) == itemPrefabName).Sum([<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (ItemData i) => i.m_stack); if (num >= value.RequiredAmount) { itemToConvert = item; conversionData = value; return true; } } } return false; } } [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] [HarmonyPatch(typeof(Container), "Awake")] public static class GrimpyBox_Container_Awake_Patch { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] [HarmonyPostfix] public static void Postfix(Container __instance) { if (!(__instance.m_name != "$piece_vc_volvacauldron_ext4") && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && (Object)(object)((Component)__instance).GetComponent<GrimpyBoxConverter>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<GrimpyBoxConverter>(); } } } [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] public static class GrimpyBox_Inventory_AddItem_Patch { [HarmonyPrefix] [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] public static bool Prefix(Inventory __instance, ItemData item) { if (__instance.m_name != "$piece_vc_volvacauldron_ext4") { return true; } string itemPrefabName = GetItemPrefabName(item); if (itemPrefabName == "Ectoplasm" || item.m_shared.m_name == "$item_ectoplasm") { return true; } if (!IsGrimpyBoxConvertibleItem(itemPrefabName)) { ValheimCuisineLogger.LogWarning((object)("[GrimpyBox] BLOCKED: " + itemPrefabName + " is not convertible!")); if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize("$vc_grimpybox_only_convertible"), 0, (Sprite)null); } return false; } return true; } } [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] [HarmonyPatch(typeof(Container), "OnContainerChanged")] public static class GrimpyBox_Container_OnContainerChanged_Patch { [HarmonyPostfix] [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] public static void Postfix(Container __instance) { if (!(__instance.m_name != "$piece_vc_volvacauldron_ext4") && Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.IsValid() && __instance.IsOwner() && !__instance.m_loading) { __instance.Save(); } } } [HarmonyPatch(typeof(Container), "Interact")] [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] public static class GrimpyBox_Container_Interact_Patch { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] [HarmonyPostfix] public static void Postfix(Container __instance, bool __result) { if (__result && !(__instance.m_name != "$piece_vc_volvacauldron_ext4") && (Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid() && __instance.IsOwner()) { __instance.Save(); } } } [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] [HarmonyPatch(typeof(InventoryGui), "Hide")] public static class GrimpyBox_InventoryGui_Hide_Patch { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] [HarmonyPrefix] public static void Prefix(InventoryGui __instance) { Container currentContainer = __instance.m_currentContainer; if ((Object)(object)currentContainer != (Object)null && currentContainer.m_name == "$piece_vc_volvacauldron_ext4" && (Object)(object)currentContainer.m_nview != (Object)null && currentContainer.m_nview.IsValid() && currentContainer.IsOwner()) { currentContainer.Save(); } } } [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] [HarmonyPatch(typeof(Container), "Save")] public static class GrimpyBox_Container_Save_Patch { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] [HarmonyPostfix] public static void Postfix(Container __instance) { if (!(__instance.m_name != "$piece_vc_volvacauldron_ext4") && (Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid()) { ZDO zDO = __instance.m_nview.GetZDO(); zDO.IncreaseDataRevision(); } } } [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] [HarmonyPatch(typeof(Container), "GetHoverText")] public static class GrimpyBox_Container_GetHoverText_Patch { [HarmonyPostfix] [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] public static void Postfix(Container __instance, ref string __result) { if (__instance.m_name != "$piece_vc_volvacauldron_ext4") { return; } Inventory inventory = __instance.GetInventory(); if (inventory != null) { int num = (from i in inventory.GetAllItems() where GetItemPrefabName(i) == "Ectoplasm" || i.m_shared.m_name == "$item_ectoplasm" select i).Sum((ItemData i) => i.m_stack); if (num > 0) { __result = __result + "\n\n<color=yellow>" + Localization.instance.Localize("$vc_grimpybox_ectoplasm") + ":</color> " + num; } else if (inventory.GetAllItems().Count == 0) { __result = __result + "\n<color=yellow>" + Localization.instance.Localize("$vc_grimpybox_empty") + "</color>"; } __result = __result + "\n<color=yellow>" + Localization.instance.Localize("$vc_grimpybox_conversion_time") + ":</color> " + GrimpyBoxConversionTime.Value + "s"; } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] public static class RavenPatch { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] private static void Postfix(ZNetScene __instance) { if ((Object)(object)__instance == (Object)null) { return; } List<GameObject> prefabs = __instance.m_prefabs; if (prefabs == null || prefabs.Count <= 0) { return; } GameObject prefab = __instance.GetPrefab("VC_Freydis"); if ((Object)(object)prefab != (Object)null) { Piece componentInChildren = prefab.GetComponentInChildren<Piece>(); GameObject val = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).gameObject : prefab); if ((Object)(object)val.GetComponent<RavenInteraction>() == (Object)null) { val.AddComponent<RavenInteraction>(); ValheimCuisineLogger.LogInfo((object)("RavenInteraction component added to " + ((Object)val).name)); } if ((Object)(object)val.GetComponent<ZNetView>() == (Object)null) { val.AddComponent<ZNetView>(); ValheimCuisineLogger.LogInfo((object)("ZNetView component added to " + ((Object)val).name)); } } else { ValheimCuisineLogger.LogWarning((object)"Could not find VC_Freydis prefab"); } } } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public class RavenInteraction : MonoBehaviour, Interactable, Hoverable { private ZNetView m_nview = null; [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(new byte[] { 1, 0, 1 })] private static List<(string itemName, int minAmount, int maxAmount, float dropChance)> possibleDrops = new List<(string, int, int, float)>(); private static ConfigEntry<string> _RavenDropTable = null; private static ConfigEntry<float> _RavenInteractionCooldown = null; private static ConfigEntry<float> _RavenDoubleDropChance = null; private static ConfigEntry<float> _RavenTripleDropChance = null; public static void InitializeConfig(ConfigFile config, ConfigSync configSync) { string text = "Dandelion:3:6:100,Pukeberries:3:6:100,Thistle:3:6:80,GreydwarfEye:2:5:80,BoneFragments:2:5:80,MushroomBzerker:1:2:10,FragrantBundle:2:3:20,FreshSeaweed:2:3:20,CuredSquirrelHamstring:2:3:20,PowderedDragonEgg:2:3:15,PungentPebbles:2:3:20,Guck:2:5:60,Root:2:3:50,Bloodbag:2:5:80,Ooze:2:5:80,WolfFang:2:5:80,WolfClaw:2:5:50,FreezeGland:2:5:60,Tar:2:5:60,VC_LandvidiRoots:2:3:50,Sap:2:5:50,Bilebag:1:2:20,GiantBloodSack:2:5:50,Softtissue:2:3:20,CharcoalResin:2:5:20,SulfurStone:2:5:20,ProustitePowder:2:3:20,CharredBone:3:6:50,Charredskull:2:5:10,CelestialFeather:1:1:5"; _RavenDropTable = config.Bind<string>("Raven", "DropTable", text, "Drop table for Raven. Format: ItemName:MinAmount:MaxAmount:DropChance (separate multiple items with commas). Example: Dandelion:3:6:100,Thistle:2:4:50"); _RavenInteractionCooldown = config.Bind<float>("Raven", "Freydis Cooldown Time", 1800f, "Cooldown time in seconds between Freydis interactions."); _RavenDoubleDropChance = config.Bind<float>("Raven", "Double Drop Chance", 50f, "Chance (0-100%) to drop two different item types instead of one."); _RavenTripleDropChance = config.Bind<float>("Raven", "Triple Drop Chance", 25f, "Chance (0-100%) to drop three different item types instead of one."); configSync.AddConfigEntry<string>(_RavenDropTable); configSync.AddConfigEntry<float>(_RavenInteractionCooldown); configSync.AddConfigEntry<float>(_RavenDoubleDropChance); configSync.AddConfigEntry<float>(_RavenTripleDropChance); _RavenDropTable.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object _, EventArgs _) => { ParseDropTable(_RavenDropTable.Value); }; ParseDropTable(_RavenDropTable.Value); } private static void ParseDropTable(string dropTableString) { possibleDrops.Clear(); if (string.IsNullOrWhiteSpace(dropTableString)) { ValheimCuisineLogger.LogWarning((object)"Raven drop table is empty!"); return; } string[] array = dropTableString.Split(new char[1] { ',' }); string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Trim().Split(new char[1] { ':' }); if (array3.Length != 4) { ValheimCuisineLogger.LogWarning((object)("Invalid drop entry format: " + text + ". Expected format: ItemName:MinAmount:MaxAmount:DropChance")); continue; } string text2 = array3[0].Trim(); int result2; float result3; if (!int.TryParse(array3[1], out var result)) { ValheimCuisineLogger.LogWarning((object)("Invalid min amount for " + text2 + ": " + array3[1])); } else if (!int.TryParse(array3[2], out result2)) { ValheimCuisineLogger.LogWarning((object)("Invalid max amount for " + text2 + ": " + array3[2])); } else if (!float.TryParse(array3[3], out result3)) { ValheimCuisineLogger.LogWarning((object)("Invalid drop chance for " + text2 + ": " + array3[3])); } else { possibleDrops.Add((text2, result, result2, result3)); } } ValheimCuisineLogger.LogInfo((object)$"Loaded {possibleDrops.Count} items into Raven drop table"); } private void Awake() { m_nview = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)m_nview == (Object)null) { m_nview = ((Component)this).gameObject.AddComponent<ZNetView>(); } ValheimCuisineLogger.LogInfo((object)("RavenInteraction Awake called on " + ((Object)((Component)this).gameObject).name)); } private string GetPlayerCooldownKey(long playerID) { return $"playerCooldown_{playerID}"; } private float GetPlayerLastInteraction(long playerID) { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return 0f; } string playerCooldownKey = GetPlayerCooldownKey(playerID); return m_nview.GetZDO().GetFloat(playerCooldownKey, 0f); } private void SetPlayerLastInteraction(long playerID, float time) { if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid()) { string playerCooldownKey = GetPlayerCooldownKey(playerID); m_nview.GetZDO().Set(playerCooldownKey, time); } } public bool Interact(Humanoid user, bool hold, bool alt) { ValheimCuisineLogger.LogInfo((object)"Raven Interact called!"); if (hold) { return false; } if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { ValheimCuisineLogger.LogWarning((object)"ZNetView is invalid"); return false; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null) { ValheimCuisineLogger.LogWarning((object)"User is not a Player"); return false; } long playerID = val.GetPlayerID(); if (playerID == 0) { ValheimCuisineLogger.LogWarning((object)"Could not get player ID"); return false; } float time = Time.time; float num = _RavenInteractionCooldown?.Value ?? 1800f; float playerLastInteraction = GetPlayerLastInteraction(playerID); if (time - playerLastInteraction < num) { float num2 = num - (time - playerLastInteraction); ((Character)user).Message((MessageType)2, Localization.instance.Localize("$raven_brewing") + $" ({Mathf.CeilToInt(num2)}s)", 0, (Sprite)null); return false; } SpawnRandomItems(user); SetPlayerLastInteraction(playerID, time); return true; } private void SpawnRandomItems(Humanoid user) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: 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_0251: Unknown result type (might be due to invalid IL or missing references) if (possibleDrops.Count == 0) { ValheimCuisineLogger.LogWarning((object)"No items in drop table!"); ((Character)user).Message((MessageType)2, "No items configured!", 0, (Sprite)null); return; } Vector3 val = ((Component)this).transform.position + Vector3.up * 1.5f; int num = 1; float num2 = Random.Range(0f, 100f); float num3 = _RavenTripleDropChance?.Value ?? 25f; float num4 = _RavenDoubleDropChance?.Value ?? 50f; if (num2 <= num3) { num = 3; ValheimCuisineLogger.LogInfo((object)$"Triple drop! (roll: {num2:F1}% <= {num3}%)"); } else if (num2 <= num3 + num4) { num = 2; ValheimCuisineLogger.LogInfo((object)$"Double drop! (roll: {num2:F1}% <= {num3 + num4}%)"); } else { ValheimCuisineLogger.LogInfo((object)$"Single drop (roll: {num2:F1}% > {num3 + num4}%)"); } List<(int, float)> list = new List<(int, float)>(); for (int i = 0; i < possibleDrops.Count; i++) { list.Add((i, possibleDrops[i].dropChance)); } Vector3 val2 = default(Vector3); for (int j = 0; j < num; j++) { if (list.Count == 0) { break; } int index = SelectWeightedItem(list); (string, int, int, float) tuple = possibleDrops[list[index].Item1]; list.RemoveAt(index); string item = tuple.Item1; int num5 = Random.Range(tuple.Item2, tuple.Item3 + 1); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item); if ((Object)(object)itemPrefab == (Object)null) { ValheimCuisineLogger.LogWarning((object)("Could not find prefab for " + item)); continue; } ((Vector3)(ref val2))..ctor(Random.Range(-0.3f, 0.3f), 0f, Random.Range(-0.3f, 0.3f)); Vector3 val3 = val + val2; GameObject val4 = Object.Instantiate<GameObject>(itemPrefab, val3, Quaternion.identity); ItemDrop component = val4.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData != null) { component.m_itemData.m_stack = num5; component.Save(); } ValheimCuisineLogger.LogInfo((object)$"Spawned {num5}x {item} (weight: {tuple.Item4}%)"); } PlaySpawnEffects(val); ((Character)user).Message((MessageType)2, Localization.instance.Localize("$raven_conjures"), 0, (Sprite)null); } private int SelectWeightedItem([<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(new byte[] { 1, 0 })] List<(int index, float weight)> weightedItems) { float num = 0f; foreach (var weightedItem in weightedItems) { num += weightedItem.weight; } float num2 = Random.Range(0f, num); float num3 = 0f; for (int i = 0; i < weightedItems.Count; i++) { num3 += weightedItems[i].weight; if (num2 <= num3) { return i; } } return weightedItems.Count - 1; } private void PlaySpawnEffects(Vector3 position) { //IL_001e: 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_0048: 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) GameObject prefab = ZNetScene.instance.GetPrefab("VC_sfx_RavenSpeak"); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, position, Quaternion.identity); } GameObject prefab2 = ZNetScene.instance.GetPrefab("vfx_Place_wood_pole"); if ((Object)(object)prefab2 != (Object)null) { Object.Instantiate<GameObject>(prefab2, position, Quaternion.identity); } } public bool UseItem(Humanoid user, ItemData item) { return false; } public string GetHoverText() { string text = Localization.instance.Localize("$raven_name"); if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Localization.instance.Localize("$raven_conjure"); } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Localization.instance.Localize("$raven_conjure"); } long playerID = localPlayer.GetPlayerID(); float time = Time.time; float num = _RavenInteractionCooldown?.Value ?? 1800f; float playerLastInteraction = GetPlayerLastInteraction(playerID); float num2 = time - playerLastInteraction; if (num2 < num) { float num3 = num - num2; return string.Format("{0}\n[<color=yellow><b>$KEY_Use</b></color>] {1} ({2}s)", text, Localization.instance.Localize("$raven_brewing_short"), Mathf.CeilToInt(num3)); } return text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Localization.instance.Localize("$raven_conjure"); } public string GetHoverName() { return Localization.instance.Localize("$raven_name"); } } [HarmonyPatch(typeof(Player), "Update")] [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public static class LoxMilkingUpdatePatch { private const string BUCKET_PREFAB_NAME = "VC_MilkinBucket"; private const string MILK_PREFAB_NAME = "VC_LoxMilk"; private const string COOLDOWN_SE_NAME = "SE_LoxMilkedCooldown"; private static float m_lastMilkAttempt; private static void Postfix(Player __instance) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (MilkingKey == null || !MilkingKey.Value.IsKeyDown() || Time.time - m_lastMilkAttempt < 0.5f) { return; } m_lastMilkAttempt = Time.time; if (!HasBucketEquipped(__instance)) { return; } GameObject hoverObject = ((Humanoid)__instance).GetHoverObject(); if ((Object)(object)hoverObject == (Object)null) { return; } Tameable componentInParent = hoverObject.GetComponentInParent<Tameable>(); if ((Object)(object)componentInParent == (Object)null) { return; } Character character = componentInParent.m_character; if (!((Object)(object)character == (Object)null) && ((Object)character).name.StartsWith("Lox") && componentInParent.IsTamed() && !(Vector3.Distance(((Component)__instance).transform.position, ((Component)character).transform.position) > 3f)) { if (RequireBreeding != null && RequireBreeding.Value && !HasLoxBred(componentInParent)) { ((Character)__instance).Message((MessageType)2, Localization.instance.Localize("$lox_milking_nobaby"), 0, (Sprite)null); } else if (HasMilkCooldown(character)) { ((Character)__instance).Message((MessageType)2, Localization.instance.Localize("$lox_milking_cooldown"), 0, (Sprite)null); } else { MilkLox(__instance, character, componentInParent); } } } private static bool HasBucketEquipped(Player player) { ItemData rightItem = ((Humanoid)player).GetRightItem(); if (rightItem == null) { return false; } return (Object)(object)rightItem.m_dropPrefab != (Object)null && ((Object)rightItem.m_dropPrefab).name == "VC_MilkinBucket"; } private static bool HasLoxBred(Tameable tameable) { ZNetView nview = tameable.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } ZDO zDO = nview.GetZDO(); if (zDO == null) { return false; } int @int = zDO.GetInt("LoxBirthCount", 0); if (@int > 0) { ValheimCuisineLogger.LogInfo((object)$"Lox has birth count: {@int}"); return true; } float @float = zDO.GetFloat("pregnant", 0f); if (@float > 0f) { ValheimCuisineLogger.LogInfo((object)$"Lox is currently pregnant: {@float}"); return true; } if (zDO.GetBool("LoxHasBeenPregnant", false)) { ValheimCuisineLogger.LogInfo((object)"Lox has been pregnant before"); return true; } ValheimCuisineLogger.LogInfo((object)"Lox has never bred"); return false; } private static bool HasMilkCooldown(Character character) { return character.GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_LoxMilkedCooldown")); } private static void MilkLox(Player player, Character lox, Tameable tameable) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) ApplyCooldown(lox); GiveMilk(player); PlayMilkingEffects(((Component)lox).transform.position); ((Character)player).Message((MessageType)2, Localization.instance.Localize("$lox_milking_success"), 0, (Sprite)null); } private static void ApplyCooldown(Character lox) { StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("SE_LoxMilkedCooldown")); float ttl = CooldownDuration?.Value ?? 1800f; if ((Object)(object)statusEffect != (Object)null) { statusEffect.m_ttl = ttl; lox.GetSEMan().AddStatusEffect(statusEffect, false, 0, 0f); return; } SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val).name = "SE_LoxMilkedCooldown"; ((StatusEffect)val).m_name = "Recently Milked"; ((StatusEffect)val).m_ttl = ttl; ((StatusEffect)val).m_tooltip = "This Lox was recently milked"; lox.GetSEMan().AddStatusEffect((StatusEffect)(object)val, true, 0, 0f); } private static void GiveMilk(Player player) { //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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_00fb: Unknown result type (might be due to invalid IL or missing references) GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("VC_LoxMilk"); if ((Object)(object)itemPrefab == (Object)null) { Debug.LogError((object)"Could not find milk prefab: VC_LoxMilk"); ((Character)player).Message((MessageType)2, Localization.instance.Localize("$lox_milking_error"), 0, (Sprite)null); return; } int num = MilkAmount?.Value ?? 5; ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null) { Debug.LogError((object)"Milk prefab has no ItemDrop component"); return; } ItemData val = component.m_itemData.Clone(); val.m_stack = num; if (!((Humanoid)player).GetInventory().AddItem(val)) { ItemDrop.DropItem(val, num, ((Component)player).transform.position + ((Component)player).transform.forward * 0.5f + Vector3.up * 0.5f, ((Component)player).transform.rotation); ((Character)player).Message((MessageType)2, Localization.instance.Localize("$lox_milking_inventory_full"), 0, (Sprite)null); } } private static void PlayMilkingEffects(Vector3 position) { //IL_001e: 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_0048: 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_0053: 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) GameObject prefab = ZNetScene.instance.GetPrefab("VC_sfx_LoxMilking"); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, position, Quaternion.identity); } GameObject prefab2 = ZNetScene.instance.GetPrefab("vfx_lootspawn"); if ((Object)(object)prefab2 != (Object)null) { Object.Instantiate<GameObject>(prefab2, position + Vector3.up * 1f, Quaternion.identity); } } } [HarmonyPatch(typeof(Tameable), "GetHoverText")] [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public static class LoxMilkingHoverTextPatch { private const string BUCKET_PREFAB_NAME = "VC_MilkinBucket"; private const string COOLDOWN_SE_NAME = "SE_LoxMilkedCooldown"; private static void Postfix(Tameable __instance, ref string __result) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_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) if (MilkingKey == null) { return; } Character character = __instance.m_character; if ((Object)(object)character == (Object)null || !((Object)character).name.StartsWith("Lox") || !__instance.IsTamed()) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } ItemData rightItem = ((Humanoid)localPlayer).GetRightItem(); if (rightItem == null) { return; } GameObject dropPrefab = rightItem.m_dropPrefab; if (((dropPrefab != null) ? ((Object)dropPrefab).name : null) != "VC_MilkinBucket") { return; } KeyboardShortcut value = MilkingKey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; string text = ((object)(KeyCode)(ref mainKey)).ToString(); if (RequireBreeding != null && RequireBreeding.Value) { ZNetView nview = __instance.m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid()) { ZDO zDO = nview.GetZDO(); if (zDO != null) { int @int = zDO.GetInt("LoxBirthCount", 0); float @float = zDO.GetFloat("pregnant", 0f); bool @bool = zDO.GetBool("LoxHasBeenPregnant", false); if (@int == 0 && @float == 0f && !@bool) { __result = __result + "\n<color=orange>" + Localization.instance.Localize("$lox_milking_hover_nobaby") + "</color>"; return; } } } } if (character.GetSEMan().HaveStatusEffect(StringExtensionMethods.GetStableHashCode("SE_LoxMilkedCooldown"))) { __result = __result + "\n<color=orange>" + Localization.instance.Localize("$lox_milking_hover_cooldown") + "</color>"; return; } __result = __result + "\n[<color=yellow><b>" + text + "</b></color>] " + Localization.instance.Localize("$lox_milking_hover_action"); } } [HarmonyPatch(typeof(Procreation), "MakePregnant")] [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] public static class ProcreationPregnancyTracker { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(1)] private static void Postfix(Procreation __instance) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) Character component = ((Component)__instance).GetComponent<Character>(); if ((Object)(object)component == (Object)null || !((Object)component).name.StartsWith("Lox")) { return; } ZNetView component2 = ((Component)__instance).GetComponent<ZNetView>(); if (!((Object)(object)component2 == (Object)null) && component2.IsValid()) { ZDO zDO = component2.GetZDO(); if (zDO != null) { zDO.Set("LoxHasBeenPregnant", true); ValheimCuisineLogger.LogInfo((object)$"Lox {component.GetZDOID()} became pregnant"); } } } } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] [HarmonyPatch(typeof(CookingStation))] public static class CookingStationPatches { private static HashSet<string> noOvercookList = new HashSet<string>(); private static HashSet<string> multiFuelList = new HashSet<string>(); private static HashSet<string> passiveCookingList = new HashSet<string>(); private static Dictionary<string, List<string>> prefabFuelMap = new Dictionary<string, List<string>>(); private const string ZDO_FUEL_TYPE = "VC_CurrentFuelType"; public static void Initialize() { SmokehouseNoOvercookPrefabs.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object s, EventArgs e) => { RefreshNoOvercookList(); }; SmokehouseMultiFuelPrefabs.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object s, EventArgs e) => { RefreshMultiFuelList(); }; SmokehouseAllowedFuels.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object s, EventArgs e) => { RefreshFuelMaps(); }; PassiveCookingPrefabs.SettingChanged += [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] (object s, EventArgs e) => { RefreshPassiveCookingList(); }; RefreshNoOvercookList(); RefreshMultiFuelList(); RefreshFuelMaps(); RefreshPassiveCookingList(); } private static void RefreshNoOvercookList() { noOvercookList.Clear(); string[] array = SmokehouseNoOvercookPrefabs.Value.Split(new char[1] { ',' }); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (!string.IsNullOrEmpty(text2)) { noOvercookList.Add(text2); } } } private static void RefreshMultiFuelList() { multiFuelList.Clear(); string[] array = SmokehouseMultiFuelPrefabs.Value.Split(new char[1] { ',' }); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (!string.IsNullOrEmpty(text2)) { multiFuelList.Add(text2); } } } private static void RefreshFuelMaps() { prefabFuelMap.Clear(); List<string> value = (from f in SmokehouseAllowedFuels.Value.Split(new char[1] { ',' }) select f.Trim() into f where !string.IsNullOrEmpty(f) select f).ToList(); foreach (string multiFuel in multiFuelList) { prefabFuelMap[multiFuel] = value; } } private static void RefreshPassiveCookingList() { passiveCookingList.Clear(); string[] array = PassiveCookingPrefabs.Value.Split(new char[1] { ',' }); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (!string.IsNullOrEmpty(text2)) { passiveCookingList.Add(text2); } } } private static bool IsNoOvercookStation(CookingStation station) { if ((Object)(object)station == (Object)null) { return false; } string prefabName = Utils.GetPrefabName(((Component)station).gameObject); return noOvercookList.Contains(prefabName); } private static bool IsMultiFuelStation(CookingStation station) { if ((Object)(object)station == (Object)null) { return false; } string prefabName = Utils.GetPrefabName(((Component)station).gameObject); return multiFuelList.Contains(prefabName); } private static bool IsPassiveCookingStation(CookingStation station) { if ((Object)(object)station == (Object)null) { return false; } string prefabName = Utils.GetPrefabName(((Component)station).gameObject); return passiveCookingList.Contains(prefabName); } private static List<string> GetAllowedFuels(CookingStation station) { if ((Object)(object)station == (Object)null) { return null; } string prefabName = Utils.GetPrefabName(((Component)station).gameObject); return prefabFuelMap.ContainsKey(prefabName) ? prefabFuelMap[prefabName] : null; } private static bool IsStationFullyInitialized(CookingStation station) { if ((Object)(object)station == (Object)null) { return false; } if ((Object)(object)station.m_nview == (Object)null) { return false; } if (!station.m_nview.IsValid()) { return false; } if (station.m_slots == null) { return false; } if (station.m_conversion == null) { return false; } return true; } [HarmonyPatch("UpdateCooking")] [HarmonyPrefix] [HarmonyPriority(800)] public static void UpdateCooking_PassiveCooking_Prefix(CookingStation __instance) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Invalid comparison between Unknown and I4 //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) if (!IsPassiveCookingStation(__instance) || !IsStationFullyInitialized(__instance) || !__instance.m_nview.IsOwner()) { return; } float deltaTime = __instance.GetDeltaTime(); string text = default(string); float num = default(float); Status val = default(Status); for (int i = 0; i < __instance.m_slots.Length; i++) { __instance.GetSlot(i, ref text, ref num, ref val); if (string.IsNullOrEmpty(text) || (int)val == 2) { continue; } ItemConversion itemConversion = __instance.GetItemConversion(text); if (itemConversion == null) { __instance.SetSlot(i, "", 0f, (Status)0); } else { if ((Object)(object)itemConversion.m_from == (Object)null || (Object)(object)itemConversion.m_to == (Object)null) { continue; } num += deltaTime; if (IsNoOvercookStation(__instance)) { if (num > itemConversion.m_cookTime && text == ((Object)itemConversion.m_from).name) { __instance.m_doneEffect.Create(__instance.m_slots[i].position, Quaternion.identity, (Transform)null, 1f, -1); __instance.SetSlot(i, ((Object)itemConversion.m_to).name, itemConversion.m_cookTime, (Status)1); } else { __instance.SetSlot(i, text, num, val); } } else if (num > itemConversion.m_cookTime * 2f) { if (__instance.m_overcookedEffect != null && (Object)(object)__instance.m_overCookedItem != (Object)null) { __instance.m_overcookedEffect.Create(__instance.m_slots[i].position, Quaternion.identity, (Transform)null, 1f, -1); __instance.SetSlot(i, ((Object)__instance.m_overCookedItem).name, num, (Status)2); } } else if (num > itemConversion.m_cookTime && text == ((Object)itemConversion.m_from).name) { __instance.m_doneEffect.Create(__instance.m_slots[i].position, Quaternion.identity, (Transform)null, 1f, -1); __instance.SetSlot(i, ((Object)itemConversion.m_to).name, num, (Status)1); } else { __instance.SetSlot(i, text, num, val); } } } } [HarmonyPrefix] [HarmonyPatch("IsItemDone")] public static bool IsItemDone_Prefix(CookingStation __instance, string itemName, ref bool __result) { if ((Object)(object)__instance == (Object)null || string.IsNullOrEmpty(itemName)) { __result = false; return false; } if (__instance.m_conversion == null) { __result = false; return false; } if ((Object)(object)__instance.m_overCookedItem == (Object)null && IsNoOvercookStation(__instance)) { ItemConversion itemConversion = __instance.GetItemConversion(itemName); if (itemConversion == null) { __result = false; return false; } if ((Object)(object)itemConversion.m_to == (Object)null) { __result = false; return false; } if (itemName == ((Object)itemConversion.m_to).name) { __result = true; return false; } __result = false; return false; } return true; } [HarmonyPrefix] [HarmonyPatch("UpdateCooking")] public static void UpdateCooking_Prefix(CookingStation __instance) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Invalid comparison between Unknown and I4 if (!IsNoOvercookStation(__instance) || !IsStationFullyInitialized(__instance) || !__instance.m_nview.IsOwner()) { return; } string text = default(string); float num = default(float); Status val = default(Status); for (int i = 0; i < __instance.m_slots.Length; i++) { __instance.GetSlot(i, ref text, ref num, ref val); if (!string.IsNullOrEmpty(text) && (int)val != 2) { ItemConversion itemConversion = __instance.GetItemConversion(text); if (itemConversion != null && (int)val == 1 && num > itemConversion.m_cookTime) { __instance.SetSlot(i, text, itemConversion.m_cookTime, (Status)1); } } } } [HarmonyPrefix] [HarmonyPatch("OnAddFuelSwitch")] public static bool OnAddFuelSwitch_Prefix(CookingStation __instance, Switch sw, Humanoid user, ItemData item, ref bool __result) { if (!IsMultiFuelStation(__instance)) { return true; } List<string> allowedFuels = GetAllowedFuels(__instance); if (allowedFuels == null || allowedFuels.Count == 0) { return true; } if (__instance.GetFuel() > (float)(__instance.m_maxFuel - 1)) { ((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null); __result = false; return false; } if (item == null) { foreach (ItemData allItem in user.GetInventory().GetAllItems()) { if ((Object)(object)allItem.m_dropPrefab != (Object)null) { string name = ((Object)allItem.m_dropPrefab).name; if (allowedFuels.Contains(name)) { item = allItem; break; } } } if (item == null) { ((Character)user).Message((MessageType)2, "$msg_noprocessableitems", 0, (Sprite)null); __result = false; return false; } } string text = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : ""); if (!allowedFuels.Contains(text)) { ((Character)user).Message((MessageType)2, "$msg_wrongitem", 0, (Sprite)null); __result = false; return false; } if (!user.GetInventory().HaveItem(item.m_shared.m_name, true)) { ((Character)user).Message((MessageType)2, "$msg_donthaveany " + item.m_shared.m_name, 0, (Sprite)null); __result = false; return false; } ((Character)user).Message((MessageType)2, "$msg_added " + item.m_shared.m_name, 0, (Sprite)null); user.GetInventory().RemoveItem(item.m_shared.m_name, 1, -1, true); if ((Object)(object)__instance.m_nview != (Object)null && __instance.m_nview.IsValid()) { __instance.m_nview.GetZDO().Set("VC_CurrentFuelType", text); } __instance.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>()); __result = true; return false; } [HarmonyPostfix] [HarmonyPatch("OnHoverFuelSwitch")] public static void OnHoverFuelSwitch_Postfix(CookingStation __instance, ref string __result) { if (!IsMultiFuelStation(__instance)) { return; } List<string> allowedFuels = GetAllowedFuels(__instance); if (allowedFuels == null || allowedFuels.Count == 0) { return; } float fuel = __instance.GetFuel(); List<string> list = new List<string>(); foreach (string item in allowedFuels) { ObjectDB instance = ObjectDB.instance; GameObject val = ((instance != null) ? instance.GetItemPrefab(item) : null); if ((Object)(object)val != (Object)null) { ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { list.Add(Localization.instance.Localize(component.m_itemData.m_shared.m_name)); } } } string text = string.Join(", ", list); __result = Localization.instance.Localize($"{__instance.m_name} ($piece_fire_fuel {Mathf.Ceil(fuel)}/{__instance.m_maxFuel})\n" + "[<color=yellow><b>$KEY_Use</b></color>] $piece_smelter_add " + text); } [HarmonyPostfix] [HarmonyPatch("TryGetItems")] public static void TryGetItems_Postfix(CookingStation __instance, Switch switchRef, ref List<string> items, ref bool __result) { if (__result && IsMultiFuelStation(__instance) && (Object)(object)switchRef == (Object)(object)__instance.m_addFuelSwitch) { List<string> allowedFuels = GetAllowedFuels(__instance); if (allowedFuels != null && allowedFuels.Count > 0) { items.Clear(); items.AddRange(allowedFuels); } } } [HarmonyPrefix] [HarmonyPatch(typeof(WearNTear), "Destroy")] public static void WearNTear_Destroy_Prefix(WearNTear __instance) { if ((Object)(object)__instance == (Object)null) { return; } CookingStation component = ((Component)__instance).GetComponent<CookingStation>(); if ((Object)(object)component == (Object)null || !IsMultiFuelStation(component)) { return; } float fuel = component.GetFuel(); if (fuel <= 0f || (Object)(object)component.m_nview == (Object)null || !component.m_nview.IsValid()) { return; } string @string = component.m_nview.GetZDO().GetString("VC_CurrentFuelType", ""); if (string.IsNullOrEmpty(@string)) { return; } ObjectDB instance = ObjectDB.instance; GameObject val = ((instance != null) ? instance.GetItemPrefab(@string) : null); if (!((Object)(object)val == (Object)null)) { ItemDrop component2 = val.GetComponent<ItemDrop>(); if ((Object)(object)component2 != (Object)null) { component.m_fuelItem = component2; } } } } [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] [HarmonyPatch(typeof(Fermenter), "GetHoverText")] public static class Fermenter_GetHoverText_Patch { [HarmonyPostfix] public static void Postfix(Fermenter __instance, ref string __result) { if (IsDvergrCauldron(__instance)) { string oldValue = Localization.instance.Localize("$piece_fermenter_fermenting"); string newValue = Localization.instance.Localize("$piece_vc_dvergrcauldron_processing"); __result = __result.Replace(oldValue, newValue); } } private static bool IsDvergrCauldron(Fermenter fermenter) { if ((Object)(object)((fermenter != null) ? ((Component)fermenter).gameObject : null) == (Object)null) { return false; } string text = ((Object)((Component)fermenter).gameObject).name.Replace("(Clone)", "").Trim(); return text == "VC_DvergrCauldron"; } } [HarmonyPatch(typeof(Projectile), "SpawnOnHit")] [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public static class Projectile_CreatureBomb_SpawnOnHit_Patch { [<275a23d8-c6bd-4410-9009-04b6e77f1ea4>NullableContext(0)] private enum BombType { None, Niflheimr, Bloodmoon, Horde } [HarmonyPrefix] public static bool Prefix(Projectile __instance, GameObject go, Collider collider, Vector3 normal) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_013f: 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) ConfigEntry<bool> enableCreatureBombs = EnableCreatureBombs; if (enableCreatureBombs == null || !enableCreatureBombs.Value) { return true; } BombType bombType = GetBombType(__instance); if (bombType == BombType.None) { return true; } ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Detected {bombType} bomb, spawning creatures..."); if (__instance.m_groundHitOnly && ((Object)(object)go == (Object)null || (Object)(object)go.GetComponent<Heightmap>() == (Object)null)) { ValheimCuisineLogger.LogWarning((object)"[CreatureBomb] Ground hit only restriction failed"); return true; } if (__instance.m_staticHitOnly && (((Object)(object)collider != (Object)null && (Object)(object)collider.attachedRigidbody != (Object)null) || ((Object)(object)go != (Object)null && go.GetComponent<IDestructible>() != null))) { ValheimCuisineLogger.LogWarning((object)"[CreatureBomb] Static hit only restriction failed"); return true; } Vector3 val = ((Component)__instance).transform.position + ((Component)__instance).transform.TransformDirection(__instance.m_spawnOffset); ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Spawn center: {val}"); SpawnCreaturesForBomb(bombType, val); EffectList spawnOnHitEffects = __instance.m_spawnOnHitEffects; if (spawnOnHitEffects != null) { spawnOnHitEffects.Create(val, Quaternion.identity, (Transform)null, 1f, -1); } ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] {bombType} bomb completed!"); return false; } private static BombType GetBombType(Projectile projectile) { if ((Object)(object)projectile == (Object)null) { return BombType.None; } string text = ((Object)((Component)projectile).gameObject).name.Replace("(Clone)", "").Trim(); if (text.Equals("VC_NiflheimrBomb_projectile", StringComparison.OrdinalIgnoreCase)) { return BombType.Niflheimr; } if (text.Equals("VC_BloodmoonBomb_projectile", StringComparison.OrdinalIgnoreCase)) { return BombType.Bloodmoon; } if (text.Equals("VC_HordeBomb_projectile", StringComparison.OrdinalIgnoreCase)) { return BombType.Horde; } if ((Object)(object)projectile.m_nview != (Object)null && projectile.m_nview.IsValid()) { ZDO zDO = projectile.m_nview.GetZDO(); if (zDO != null) { int prefab = zDO.GetPrefab(); if (prefab == StringExtensionMethods.GetStableHashCode("VC_NiflheimrBomb_projectile")) { return BombType.Niflheimr; } if (prefab == StringExtensionMethods.GetStableHashCode("VC_BloodmoonBomb_projectile")) { return BombType.Bloodmoon; } if (prefab == StringExtensionMethods.GetStableHashCode("VC_HordeBomb_projectile")) { return BombType.Horde; } } } return BombType.None; } private static void SpawnCreaturesForBomb(BombType bombType, Vector3 center) { //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) if (1 == 0) { } string text = bombType switch { BombType.Niflheimr => NiflheimrBombCreatures?.Value, BombType.Bloodmoon => BloodmoonBombCreatures?.Value, BombType.Horde => HordeBombCreatures?.Value, _ => null, }; if (1 == 0) { } string text2 = text; if (1 == 0) { } bool flag = bombType switch { BombType.Niflheimr => NiflheimrBombRandomizeLevels?.Value ?? true, BombType.Bloodmoon => BloodmoonBombRandomizeLevels?.Value ?? true, BombType.Horde => HordeBombRandomizeLevels?.Value ?? true, _ => false, }; if (1 == 0) { } bool flag2 = flag; ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Config: '{text2}', Randomize: {flag2}"); if (string.IsNullOrWhiteSpace(text2)) { ValheimCuisineLogger.LogWarning((object)$"[CreatureBomb] No creatures configured for {bombType}!"); return; } if ((Object)(object)ZNetScene.instance == (Object)null) { ValheimCuisineLogger.LogError((object)"[CreatureBomb] ZNetScene.instance is null!"); return; } List<(string, int, int)> list = ParseCreatureList(text2); float radius = Mathf.Clamp(BombSpawnRadius?.Value ?? 2.5f, 0f, 10f); bool flag3 = BombSpawnRandomRotation?.Value ?? true; int num = 0; foreach (var item5 in list) { int item = item5.Item2; num += item; } ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Spawning {num} total creatures at {center}"); int num2 = 0; foreach (var item6 in list) { string item2 = item6.Item1; int item3 = item6.Item2; int item4 = item6.Item3; GameObject prefab = ZNetScene.instance.GetPrefab(item2); if ((Object)(object)prefab == (Object)null) { ValheimCuisineLogger.LogWarning((object)("[CreatureBomb] Prefab not found: " + item2)); continue; } for (int i = 0; i < item3; i++) { Vector3 val = CalculateSpawnPosition(center, radius, num2, num); Quaternion val2 = (flag3 ? Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) : Quaternion.identity); int num3 = item4; if (flag2 && item4 > 1) { num3 = Random.Range(1, item4 + 1); } GameObject val3 = Object.Instantiate<GameObject>(prefab, val, val2); if ((Object)(object)val3 != (Object)null) { ZNetView component = val3.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && num3 > 1) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.Set(ZDOVars.s_level, num3, false); } ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Spawned {item2} at {val} (Level {num3})"); } else { ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Spawned {item2} at {val}"); } } else { ValheimCuisineLogger.LogError((object)("[CreatureBomb] Failed to spawn " + item2 + "!")); } num2++; } } } [return: <f702c462-8385-4673-b169-bde4ff02a79f>Nullable(new byte[] { 1, 0, 1 })] private static List<(string prefabName, int count, int level)> ParseCreatureList(string configValue) { List<(string, int, int)> list = new List<(string, int, int)>(); if (string.IsNullOrWhiteSpace(configValue)) { ValheimCuisineLogger.LogWarning((object)"[CreatureBomb] Config value is null or empty"); return list; } ValheimCuisineLogger.LogInfo((object)("[CreatureBomb] Parsing creature list: " + configValue)); string[] array = configValue.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string[] array2 = text.Trim().Split(new char[1] { ':' }); if (array2.Length >= 2) { string text2 = array2[0].Trim(); if (!int.TryParse(array2[1].Trim(), out var result) || result <= 0) { ValheimCuisineLogger.LogWarning((object)("[CreatureBomb] Invalid count in entry: '" + text + "'")); continue; } int num = 1; if (array2.Length >= 3 && int.TryParse(array2[2].Trim(), out var result2)) { num = Mathf.Clamp(result2, 1, 3); } list.Add((text2, result, num)); ValheimCuisineLogger.LogInfo((object)$"[CreatureBomb] Parsed: {text2} x {result} (Level {num})"); } else { ValheimCuisineLogger.LogWarning((object)("[CreatureBomb] Invalid entry: '" + text + "'")); } } return list; } private static Vector3 CalculateSpawnPosition(Vector3 center, float radius, int index, int total) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) Vector3 val = center; if (radius > 0f && total > 1) { float num = 360f / (float)total * (float)index; float num2 = num * ((float)Math.PI / 180f); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Mathf.Cos(num2) * radius, 0f, Mathf.Sin(num2) * radius); val += val2; } return val; } } [HarmonyPatch(typeof(Player))] [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public static class BerserkRoar_ActivePower_Patch { private static readonly Dictionary<long, float> playerCooldowns = new Dictionary<long, float>(); [HarmonyPatch("Update")] [HarmonyPostfix] private static void Update_Postfix(Player __instance) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (((Character)__instance).IsOwner() && Input.GetKeyDown(BerserkRoarActivationKey.Value)) { TryTriggerBerserkRoar(__instance); } } private static void TryTriggerBerserkRoar(Player player) { bool flag = false; foreach (StatusEffect statusEffect in ((Character)player).GetSEMan().GetStatusEffects()) { if (statusEffect.m_name == "$item_vc_fulingberserkerelixir") { flag = true; break; } } if (!flag) { if (((Humanoid)player).GetInventory().HaveItem("$item_vc_fulingberserkerelixir", true)) { ((Character)player).Message((MessageType)2, Localization.instance.Localize("$vc_hamask_needpotion"), 0, (Sprite)null); } return; } long playerID = player.GetPlayerID(); float time = Time.time; if (playerCooldowns.TryGetValue(playerID, out var value)) { float num = time - value; float num2 = BerserkRoarCooldown.Value - num; if (num2 > 0f) { int num3 = Mathf.FloorToInt(num2 / 60f); int num4 = Mathf.FloorToInt(num2 % 60f); string text = Localization.instance.Localize("$vc_hamask_cooldown"); text = ((num3 <= 0) ? (text + $" {num4}s") : (text + $" {num3}m {num4}s")); ((Character)player).Message((MessageType)2, text, 0, (Sprite)null); return; } } playerCooldowns[playerID] = time; TriggerBerserkRoar(player); } private static void TriggerBerserkRoar(Player player) { string text = ((player.GetPlayerModel() == 0) ? "VC_sfx_BerserkergangMale" : "VC_sfx_BerserkergangFemale"); if (player.StartEmote("roar", false)) { ((Character)player).m_nview.InvokeRPC(ZNetView.Everybody, "VC_PlayBerserkRoar", new object[1] { text }); SpawnHamaskVFX(player); ApplyRoarEffects(player); } else { ApplyRoarEffects(player); ((Character)player).Message((MessageType)2, Localization.instance.Localize("$vc_hamask_noanimation"), 0, (Sprite)null); } } private static void SpawnHamaskVFX(Player player) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab("VC_vfx_Hamask"); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity); } } } private static void ApplyRoarEffects(Player player) { if (!((Object)(object)player == (Object)null)) { ApplyDamageBuff(player); StaggerNearbyEnemies(player); TauntNearbyEnemies(player); } } private static void ApplyDamageBuff(Player player) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) bool flag = false; ObjectDB instance = ObjectDB.instance; StatusEffect val = ((instance != null) ? instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("VC_FulingBerserkerElixirDamageEffect")) : null); if ((Object)(object)val != (Object)null) { SE_Stats val2 = (SE_Stats)(object)((val is SE_Stats) ? val : null); if ((Object)(object)val2 != (Object)null) { ((StatusEffect)val2).m_ttl = BerserkRoarDamageBoostDuration.Value; val2.m_damageModifier = BerserkRoarDamageBoostPercent.Value / 100f; val2.m_modifyAttackSkill = (SkillType)999; ((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)val2, false, 0, 0f); return; } } SE_Stats val3 = ScriptableObject.CreateInstance<SE_Stats>(); ((Object)val3).name = "VC_FulingBerserkerElixirDamageEffect"; string text = Localization.instance.Localize("$vc_fulinghamask_damage"); ((StatusEffect)val3).m_name = ((!text.Contains("[") && text != "$vc_fulinghamask_damage") ? text : "Hamask"); string text2 = Localization.instance.Localize("$vc_fulinghamask_damage_tooltip"); ((StatusEffect)val3).m_tooltip = ((!text2.Contains("[") && text2 != "$vc_fulinghamask_damage_tooltip") ? text2 : "Damage increased!"); ((StatusEffect)val3).m_ttl = BerserkRoarDamageBoostDuration.Value; val3.m_damageModifier = BerserkRoarDamageBoostPercent.Value / 100f; val3.m_modifyAttackSkill = (SkillType)999; StatusEffect statusEffect = ((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("GP_Eikthyr")); if ((Object)(object)statusEffect != (Object)null && (Object)(object)statusEffect.m_icon != (Object)null) { ((StatusEffect)val3).m_icon = statusEffect.m_icon; } else { StatusEffect statusEffect2 = ((Character)player).GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode("Rested")); if ((Object)(object)statusEffect2 != (Object)null && (Object)(object)statusEffect2.m_icon != (Object)null) { ((StatusEffect)val3).m_icon = statusEffect2.m_icon; } } ((Character)player).GetSEMan().AddStatusEffect((StatusEffect)(object)val3, false, 0, 0f); } private static void StaggerNearbyEnemies(Player player) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) float value = BerserkRoarStaggerRadius.Value; List<Character> list = new List<Character>(); Character.GetCharactersInRange(((Component)player).transform.position, value, list); foreach (Character item in list) { if (!((Object)(object)item == (Object)(object)player) && !item.IsDead() && BaseAI.IsEnemy((Character)(object)player, item)) { item.Stagger(((Component)player).transform.position - ((Component)item).transform.position); SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>(); ((StatusEffect)val).m_name = "Berserk Stagger"; ((StatusEffect)val).m_ttl = BerserkRoarStaggerDuration.Value; val.m_staggerModifier = 2f; item.GetSEMan().AddStatusEffect((StatusEffect)(object)val, false, 0, 0f); } } } private static void TauntNearbyEnemies(Player player) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) float value = BerserkRoarTauntRadius.Value; List<Character> list = new List<Character>(); Character.GetCharactersInRange(((Component)player).transform.position, value, list); foreach (Character item in list) { if (!((Object)(object)item == (Object)(object)player) && !item.IsDead() && BaseAI.IsEnemy((Character)(object)player, item)) { MonsterAI component = ((Component)item).GetComponent<MonsterAI>(); if ((Object)(object)component != (Object)null) { component.SetTarget((Character)(object)player); ((BaseAI)component).SetAlerted(true); } } } } } [HarmonyPatch(typeof(Player))] [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public static class BerserkRoar_Player_RPC_Patch { [HarmonyPostfix] [HarmonyPatch("Awake")] private static void Awake_Postfix(Player __instance) { if ((Object)(object)((Character)__instance).m_nview != (Object)null && ((Character)__instance).m_nview.IsValid()) { ((Character)__instance).m_nview.Register<string>("VC_PlayBerserkRoar", (Action<long, string>)delegate(long sender, string sfxName) { RPC_PlayBerserkRoar(__instance, sender, sfxName); }); } } private static void RPC_PlayBerserkRoar(Player player, long sender, string sfxName) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab(sfxName); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity); } } } } [HarmonyPatch(typeof(Attack), "GetAttackEitr")] [<f702c462-8385-4673-b169-bde4ff02a79f>Nullable(0)] public static class StaffEitrReduction_Patch { [HarmonyPostfix] private static void Postfix(At