using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using OutwardGameSettings.Managers; using OutwardGameSettings.Utility.Helpers; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("OutwardEnchanter")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OutwardEnchanter")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("c5450fe0-edcf-483f-b9ea-4b1ef9d36da7")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace OutwardGameSettings { [BepInPlugin("gymmed.outwardgamesettings", "Outward Game Settings", "0.0.1")] public class OutwardGameSettings : BaseUnityPlugin { [HarmonyPatch(typeof(ResourcesPrefabManager), "Load")] public class ResourcesPrefabManager_Load { private static void Postfix(ResourcesPrefabManager __instance) { EnchantmentsHelper.FixFilterRecipe(); } } [HarmonyPatch(typeof(EnchantmentMenu), "TryEnchant")] public class Patch_TryEnchant { private static bool Prefix(EnchantmentMenu __instance) { if (!Object.op_Implicit((Object)(object)((SingleItemInventoryMenu)__instance).m_refItemInChest)) { return true; } int enchantmentID = __instance.GetEnchantmentID(); if (enchantmentID == -1 || ((SingleItemInventoryMenu)__instance).m_refItemInChest.IsEnchanted) { return true; } if ((Object)(object)ResourcesPrefabManager.Instance.GetEnchantmentPrefab(enchantmentID) == (Object)null) { return true; } if ((Object)(object)((SingleItemContainer)__instance.m_refEnchantmentStation).ContainedItem == (Object)null) { return true; } List availableEnchantmentRecipeItemsInInventory = EnchantmentsHelper.GetAvailableEnchantmentRecipeItemsInInventory(((SingleItemContainer)__instance.m_refEnchantmentStation).ContainedItem, ((UIElement)__instance).LocalCharacter.Inventory); if (RequireRecipeToAllowEnchant.Value && !EnchantmentsHelper.IsEnchantmentInList(enchantmentID, availableEnchantmentRecipeItemsInInventory)) { ((UIElement)__instance).m_characterUI.ShowInfoNotification("You need to have enchantment!"); return false; } if (UseRecipeOnEnchanting.Value) { EnchantmentRecipeItem enchantmentInTheList = EnchantmentsHelper.GetEnchantmentInTheList(enchantmentID, availableEnchantmentRecipeItemsInInventory); if (Object.op_Implicit((Object)(object)enchantmentInTheList)) { ((UIElement)__instance).m_characterUI.ShowInfoNotification(((Item)enchantmentInTheList).Name + " has been used!"); ItemManager.Instance.DestroyItem((Item)(object)enchantmentInTheList); } } return true; } } public const string GUID = "gymmed.outwardgamesettings"; public const string NAME = "Outward Game Settings"; public const string VERSION = "0.0.1"; public static string prefix = "[GymMed-Game-Settings]"; internal static ManualLogSource Log; public static ConfigEntry RequireRecipeToAllowEnchant; public static ConfigEntry UseRecipeOnEnchanting; public static ConfigEntry EnchantingSuccessChance; public static ConfigEntry PlayAudioOnEnchantingDone; internal void Awake() { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Log.LogMessage((object)"Hello world from Outward Game Settings 0.0.1!"); RequireRecipeToAllowEnchant = ((BaseUnityPlugin)this).Config.Bind("Enchanting Modifications", "RequireRecipeToAllowEnchant", true, "Allow enchanting only if enchantment is on character?"); UseRecipeOnEnchanting = ((BaseUnityPlugin)this).Config.Bind("Enchanting Modifications", "UseRecipeOnEnchanting", true, "Remove recipe after using it on enchanting?"); EnchantingSuccessChance = ((BaseUnityPlugin)this).Config.Bind("Enchanting Modifications", "EnchantingSuccessChance", 50, "What is success chance(%) of enchanting?"); PlayAudioOnEnchantingDone = ((BaseUnityPlugin)this).Config.Bind("Enchanting Modifications", "PlayAudioOnEnchantingDone", true, "Play additional audio on enchanting failed/success?"); new Harmony("gymmed.outwardgamesettings").PatchAll(); } internal void Update() { } public static void LogMessage(string message) { Log.LogMessage((object)(prefix + " " + message)); } } } namespace OutwardGameSettings.Utility.Helpers { public class ConfigsHelper { public static int GetPercentageValueFromConfig(int originalValue) { if (originalValue < 0) { return 0; } if (originalValue > 100) { return 100; } return originalValue; } } public class EnchantmentsHelper { public static List GetAvailableEnchantmentRecipeItemsInInventory(Item item, CharacterInventory inventory) { List allItemsOfType = ItemsHelper.GetAllItemsOfType(ItemsHelper.GetUniqueItemsInInventory(inventory)); List list = new List(); foreach (EnchantmentRecipeItem item2 in allItemsOfType) { EnchantmentRecipe[] recipes = item2.Recipes; for (int i = 0; i < recipes.Length; i++) { if (recipes[i].GetHasMatchingEquipment(item)) { list.Add(item2); } } } return list; } public static List GetAvailableEnchantmentRecipies(Item item) { List enchantmentRecipes = RecipeManager.Instance.GetEnchantmentRecipes(); List list = new List(); foreach (EnchantmentRecipe item2 in enchantmentRecipes) { if (item2.GetHasMatchingEquipment(item)) { list.Add(item2); } } return list; } public static List GetMissingEnchantments(List availableEnchantments, List haveEnchantments) { List list = new List(); bool flag = false; foreach (EnchantmentRecipe availableEnchantment in availableEnchantments) { foreach (EnchantmentRecipe haveEnchantment in haveEnchantments) { if (availableEnchantment.RecipeID == haveEnchantment.RecipeID) { flag = true; } } if (flag) { flag = false; } else { list.Add(availableEnchantment); } } return list; } public static bool IsEnchantmentInList(int enchantmentId, List enchantmentItems) { foreach (EnchantmentRecipeItem enchantmentItem in enchantmentItems) { EnchantmentRecipe[] recipes = enchantmentItem.Recipes; for (int i = 0; i < recipes.Length; i++) { if (recipes[i].RecipeID == enchantmentId) { return true; } } } return false; } public static EnchantmentRecipeItem GetEnchantmentInTheList(int enchantmentId, List enchantmentItems) { foreach (EnchantmentRecipeItem enchantmentItem in enchantmentItems) { EnchantmentRecipe[] recipes = enchantmentItem.Recipes; for (int i = 0; i < recipes.Length; i++) { if (recipes[i].RecipeID == enchantmentId) { return enchantmentItem; } } } return null; } public static void FixFilterRecipe() { Item itemPrefab = ResourcesPrefabManager.Instance.GetItemPrefab("5800047"); if ((Object)(object)itemPrefab == (Object)null) { return; } EnchantmentRecipeItem val = (EnchantmentRecipeItem)(object)((itemPrefab is EnchantmentRecipeItem) ? itemPrefab : null); if (Object.op_Implicit((Object)(object)val) && val.Recipes.Count() != 3) { EnchantmentRecipe enchantmentRecipeForID = RecipeManager.Instance.GetEnchantmentRecipeForID(52); EnchantmentRecipe enchantmentRecipeForID2 = RecipeManager.Instance.GetEnchantmentRecipeForID(53); EnchantmentRecipe enchantmentRecipeForID3 = RecipeManager.Instance.GetEnchantmentRecipeForID(54); if (!((Object)(object)enchantmentRecipeForID == (Object)null) && !((Object)(object)enchantmentRecipeForID2 == (Object)null) && !((Object)(object)enchantmentRecipeForID3 == (Object)null)) { EnchantmentRecipe[] recipes = (EnchantmentRecipe[])(object)new EnchantmentRecipe[3] { enchantmentRecipeForID, enchantmentRecipeForID2, enchantmentRecipeForID3 }; val.Recipes = recipes; } } } } public class ItemsHelper { public static List GetAllItemsOfType(List items) where T : Item { List list = new List(); foreach (Item item in items) { T val = (T)(object)((item is T) ? item : null); if (val != null) { list.Add(val); } } return list; } public static List GetUniqueItemsInInventory(CharacterInventory inventory) { ItemContainer pouch = inventory.Pouch; List first = ((pouch != null) ? pouch.GetContainedItems() : null); List second = new List(); if (inventory.HasABag) { second = ((ItemContainer)inventory.EquippedBag.Container).GetContainedItems(); } return first.Union(second).ToList(); } } } namespace OutwardGameSettings.Patches { [HarmonyPatch(typeof(EnchantmentTable), "DoneEnchanting")] public class Patch_DoneEnchanting { private static bool Prefix(EnchantmentTable __instance) { int percentageValueFromConfig = ConfigsHelper.GetPercentageValueFromConfig(OutwardGameSettings.EnchantingSuccessChance.Value); if (percentageValueFromConfig != 100 && new Random().Next(1, 101) > percentageValueFromConfig) { __instance.ActivateFX(false); if (!PhotonNetwork.isNonMasterClientInRoom) { __instance.LockPillars(false); } __instance.ConsumeIncenses(); __instance.m_pendingEnchantment = null; __instance.m_remainingEnchantTime = -999f; FieldInfo field = typeof(EnchantmentTable).GetField("OnDoneEnchanting", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null && field.GetValue(__instance) is EventHandler eventHandler) { eventHandler(__instance, EventArgs.Empty); } Enchantment pendingEnchantment = __instance.PendingEnchantment; if (((pendingEnchantment != null) ? pendingEnchantment.Name : null) != null && (Object)/*isinst with value type is only supported in some contexts*/ != (Object)null) { Item obj = ((ItemContainer)__instance).m_containedItems.Values[0]; Equipment val = (Equipment)(object)((obj is Equipment) ? obj : null); NotificationsManager.Instance.BroadcastGlobalSideNotification(__instance.PendingEnchantment.Name + " on " + ((Item)val).DisplayName + " failed!"); } else { NotificationsManager.Instance.BroadcastGlobalSideNotification("Enchanting failed!"); } if (OutwardGameSettings.PlayAudioOnEnchantingDone.Value) { Global.AudioManager.PlaySoundAtPosition((Sounds)11145, ((Component)__instance).transform, 0f, 1f, 1f, 1f, 1f); } return false; } Enchantment pendingEnchantment2 = __instance.PendingEnchantment; if (((pendingEnchantment2 != null) ? pendingEnchantment2.Name : null) != null && (Object)/*isinst with value type is only supported in some contexts*/ != (Object)null) { Item obj2 = ((ItemContainer)__instance).m_containedItems.Values[0]; Equipment val2 = (Equipment)(object)((obj2 is Equipment) ? obj2 : null); NotificationsManager.Instance.BroadcastGlobalSideNotification(__instance.PendingEnchantment.Name + " on " + ((Item)val2).DisplayName + " succeeded!"); } else { NotificationsManager.Instance.BroadcastGlobalSideNotification("Enchanting succeeded!"); } if (OutwardGameSettings.PlayAudioOnEnchantingDone.Value) { Global.AudioManager.PlaySoundAtPosition((Sounds)13130, ((Component)__instance).transform, 0f, 1f, 1f, 1f, 1f); } return true; } } } namespace OutwardGameSettings.Managers { public class NotificationsManager { private static NotificationsManager _instance; public static NotificationsManager Instance { get { if (_instance == null) { _instance = new NotificationsManager(); } return _instance; } } private NotificationsManager() { } public void BroadcastGlobalSideNotification(string message) { Character val = null; foreach (PlayerSystem item in Global.Lobby.PlayersInLobby) { val = item.ControlledCharacter; if ((Object)(object)val?.CharacterUI != (Object)null) { val.CharacterUI.ShowInfoNotification(message); } } } public void BroadcastGlobalTopNotification(string message) { Character val = null; foreach (PlayerSystem item in Global.Lobby.PlayersInLobby) { val = item.ControlledCharacter; object obj; if (val == null) { obj = null; } else { CharacterUI characterUI = val.CharacterUI; obj = ((characterUI != null) ? characterUI.NotificationPanel : null); } if ((Object)obj != (Object)null) { val.CharacterUI.NotificationPanel.ShowNotification(message); } } } } }