Decompiled source of ForgeOfTruePotential v1.0.3

ForgeOfTruePotential.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ForgeOfTruePotential")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ForgeOfTruePotential")]
[assembly: AssemblyTitle("ForgeOfTruePotential")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ForgeOfTruePotential
{
	internal static class Config
	{
		public static ConfigEntry<float> SuccessChance;

		public static ConfigEntry<int> IdolCostBase;

		public static ConfigEntry<int> IdolCostIncrement;

		public static ConfigEntry<int> ReferenceMaxQuality;

		public static ConfigEntry<int> TierBandSize;

		public static ConfigEntry<float> NoConsumeChanceMax;

		public static ConfigEntry<float> IdolDropBaseChance;

		public static ConfigEntry<float> IdolDropPerStarBonus;

		public static void Bind(ConfigFile cfg)
		{
			SuccessChance = cfg.Bind<float>("Forge", "SuccessChance", 0.75f, "Chance a craft attempt succeeds (increases quality by 1). Remainder is downgrade chance.");
			IdolCostBase = cfg.Bind<int>("Forge", "IdolCostBase", 1, "Idol cost for the first upgrade attempt at the item's normal max quality.");
			IdolCostIncrement = cfg.Bind<int>("Forge", "IdolCostIncrement", 2, "Additional idols required per quality level past the item's normal max.");
			ReferenceMaxQuality = cfg.Bind<int>("Forge", "ReferenceMaxQuality", 4, "The highest normal max quality among standard items. Used to normalize the biome-tier escalation threshold across items with different normal max qualities.");
			TierBandSize = cfg.Bind<int>("Forge", "TierBandSize", 4, "How many quality levels each biome idol tier covers before the next tier is required.");
			NoConsumeChanceMax = cfg.Bind<float>("Forge", "NoConsumeChanceMax", 0.25f, "Chance at 100 Crafting skill to skip consuming idol(s) this attempt, regardless of outcome.");
			IdolDropBaseChance = cfg.Bind<float>("Drops", "IdolDropBaseChance", 0.005f, "Base per-idol-type drop chance from a non-tamed, non-boss creature kill.");
			IdolDropPerStarBonus = cfg.Bind<float>("Drops", "IdolDropPerStarBonus", 0.1f, "Additive drop chance bonus per creature star, up to MaxStars.");
		}
	}
	internal static class CraftingLuck
	{
		public static bool RollSkipIdolConsumption(Player player, SkillType skillType)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (int)skillType == 0)
			{
				return false;
			}
			float num = ((Character)player).GetSkillFactor(skillType) * Config.NoConsumeChanceMax.Value;
			return Random.value < num;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
	internal static class ForgeCraftPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(InventoryGui __instance, Player player)
		{
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: 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_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			Recipe value = Traverse.Create((object)__instance).Field("m_craftRecipe").GetValue<Recipe>();
			ItemData value2 = Traverse.Create((object)__instance).Field("m_craftUpgradeItem").GetValue<ItemData>();
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			if (!((Object)(object)value != (Object)null) || value2 == null || !((Object)(object)currentCraftingStation != (Object)null) || !currentCraftingStation.m_upgrader)
			{
				return true;
			}
			int quality = value2.m_quality;
			Requirement val = ForgeUpgradeResolver.FindNativeUpgraderRequirement(value);
			if (val == null || (Object)(object)val.m_resItem == (Object)null)
			{
				Debug.LogError((object)("Forge of Potential recipe has no upgrader resource configured: " + ((Object)value).name));
				return false;
			}
			ForgeUpgradeRequirement forgeUpgradeRequirement = ForgeUpgradeResolver.Resolve(val, quality);
			GameObject prefab = ZNetScene.instance.GetPrefab(forgeUpgradeRequirement.IdolPrefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				Debug.LogError((object)("Idol prefab '" + forgeUpgradeRequirement.IdolPrefabName + "' not found in ZNetScene."));
				return false;
			}
			string name = prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
			int idolCost = forgeUpgradeRequirement.IdolCost;
			Inventory inventory = ((Humanoid)player).GetInventory();
			bool flag = player.NoCostCheat() || ZoneSystem.instance.GetGlobalKey((GlobalKeys)25);
			if (!flag && inventory.CountItems(name, -1, true) < idolCost)
			{
				((Character)player).Message((MessageType)2, Localization.instance.Localize("$msg_missingrequirement"), 0, (Sprite)null, false);
				return false;
			}
			if (!inventory.ContainsItem(value2))
			{
				return false;
			}
			bool flag2 = Random.value < Config.SuccessChance.Value;
			int num = (flag2 ? (quality + 1) : Mathf.Max(1, quality - 1));
			Vector2i gridPos = value2.m_gridPos;
			int variant = value2.m_variant;
			long playerID = player.GetPlayerID();
			string playerName = player.GetPlayerName();
			bool flag3 = inventory.ItemCheated(value.m_resources, -1, true) || player.NoCostCheat();
			((Humanoid)player).UnequipItem(value2, true);
			inventory.RemoveItem(value2);
			inventory.AddItem(((Object)((Component)value.m_item).gameObject).name, 1, num, variant, playerID, playerName, gridPos, flag3, false, true);
			if (!flag && !CraftingLuck.RollSkipIdolConsumption(player, currentCraftingStation.m_craftingSkill))
			{
				inventory.RemoveItem(name, idolCost, -1, true);
			}
			if ((int)currentCraftingStation.m_craftingSkill != 0)
			{
				((Character)player).RaiseSkill(currentCraftingStation.m_craftingSkill, 1f);
			}
			if (flag2)
			{
				((Character)player).Message((MessageType)2, Localization.instance.Localize("$msg_upgrader_success", new string[2]
				{
					value2.m_shared.m_name,
					num.ToString()
				}), 0, (Sprite)null, true);
			}
			else
			{
				((Character)player).Message((MessageType)2, value2.m_shared.m_name + " refinement failed and downgraded to level " + num, 0, (Sprite)null, false);
			}
			EffectList obj = (flag2 ? currentCraftingStation.m_craftItemDoneEffects : currentCraftingStation.m_craftItemDoneFailEffects);
			if (obj != null)
			{
				obj.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			Traverse.Create((object)__instance).Method("UpdateCraftingPanel", new object[1] { false }).GetValue();
			IList value3 = Traverse.Create((object)__instance).Field("m_availableRecipes").GetValue<IList>();
			int num2 = -1;
			for (int i = 0; i < value3.Count; i++)
			{
				ItemData value4 = Traverse.Create(value3[i]).Property("ItemData", (object[])null).GetValue<ItemData>();
				if (value4 != null && value4.m_gridPos == gridPos && (Object)(object)value4.m_dropPrefab == (Object)(object)value2.m_dropPrefab)
				{
					num2 = i;
					break;
				}
			}
			if (num2 >= 0)
			{
				Traverse.Create((object)__instance).Method("SetRecipe", new object[2] { num2, false }).GetValue();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "AddRecipeToList")]
	internal static class ForgeListVisibilityPatch
	{
		[HarmonyPrefix]
		public static void Prefix(Player player, Recipe recipe, ItemData item, ref bool canCraft)
		{
			if (item != null)
			{
				CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
				if (!((Object)(object)currentCraftingStation == (Object)null) && currentCraftingStation.m_upgrader)
				{
					canCraft = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ForgeRecoverFlagPatch
	{
		[HarmonyPostfix]
		public static void Postfix(ObjectDB __instance)
		{
			foreach (Recipe recipe in __instance.m_recipes)
			{
				if ((Object)(object)recipe == (Object)null || recipe.m_resources == null)
				{
					continue;
				}
				bool flag = false;
				Requirement[] resources = recipe.m_resources;
				for (int i = 0; i < resources.Length; i++)
				{
					if (resources[i].m_upgraderResource)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					continue;
				}
				resources = recipe.m_resources;
				foreach (Requirement val in resources)
				{
					if (!val.m_upgraderResource)
					{
						val.m_recover = false;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
	internal static class ForgeRequirementDisplayPatch
	{
		[HarmonyPostfix]
		public static void Postfix(InventoryGui __instance, Player player)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			Traverse obj = Traverse.Create((object)__instance).Field("m_selectedRecipe");
			Recipe value = obj.Property("Recipe", (object[])null).GetValue<Recipe>();
			ItemData value2 = obj.Property("ItemData", (object[])null).GetValue<ItemData>();
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			if (!((Object)(object)value != (Object)null) || value2 == null || !((Object)(object)currentCraftingStation != (Object)null) || !currentCraftingStation.m_upgrader)
			{
				return;
			}
			Requirement val = ForgeUpgradeResolver.FindNativeUpgraderRequirement(value);
			if (val == null)
			{
				return;
			}
			ForgeUpgradeRequirement forgeUpgradeRequirement = ForgeUpgradeResolver.Resolve(val, value2.m_quality);
			GameObject prefab = ZNetScene.instance.GetPrefab(forgeUpgradeRequirement.IdolPrefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			ItemDrop component = prefab.GetComponent<ItemDrop>();
			if (__instance.m_recipeRequirementList.Length != 0)
			{
				Requirement val2 = new Requirement
				{
					m_resItem = component,
					m_amount = forgeUpgradeRequirement.IdolCost,
					m_amountPerLevel = 0,
					m_upgraderResource = true
				};
				InventoryGui.SetupRequirement(__instance.m_recipeRequirementList[0].transform, val2, player, true, 1, 1);
			}
			string name = component.m_itemData.m_shared.m_name;
			bool flag = ((Humanoid)player).GetInventory().CountItems(name, -1, true) >= forgeUpgradeRequirement.IdolCost || player.NoCostCheat() || ZoneSystem.instance.GetGlobalKey((GlobalKeys)25);
			if (!((Object)(object)__instance.m_craftButton != (Object)null))
			{
				return;
			}
			((Selectable)__instance.m_craftButton).interactable = flag;
			if (!flag)
			{
				UITooltip component2 = ((Component)__instance.m_craftButton).GetComponent<UITooltip>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.m_text = Localization.instance.Localize("$msg_missingrequirement");
				}
			}
		}
	}
	internal readonly struct ForgeUpgradeRequirement
	{
		public readonly string IdolPrefabName;

		public readonly int IdolCost;

		public ForgeUpgradeRequirement(string idolPrefabName, int idolCost)
		{
			IdolPrefabName = idolPrefabName;
			IdolCost = idolCost;
		}
	}
	internal static class ForgeUpgradeResolver
	{
		public static Requirement FindNativeUpgraderRequirement(Recipe recipe)
		{
			Requirement[] resources = recipe.m_resources;
			foreach (Requirement val in resources)
			{
				if (val.m_upgraderResource)
				{
					return val;
				}
			}
			return null;
		}

		public static ForgeUpgradeRequirement Resolve(Requirement nativeUpgraderReq, int currentQuality)
		{
			string name = ((Object)((Component)nativeUpgraderReq.m_resItem).gameObject).name;
			int idolBiomeTier = ItemBiomeData.GetIdolBiomeTier(name);
			bool num = ItemBiomeData.IdolPrefabsByTier[idolBiomeTier].weaponIdol == name;
			int tierOffset = IdolMath.GetTierOffset(currentQuality, Config.ReferenceMaxQuality.Value, Config.TierBandSize.Value);
			int num2 = ItemBiomeData.IdolPrefabsByTier.Count - 1;
			int key = Mathf.Min(idolBiomeTier + tierOffset, num2);
			string idolPrefabName = (num ? ItemBiomeData.IdolPrefabsByTier[key].weaponIdol : ItemBiomeData.IdolPrefabsByTier[key].armorIdol);
			int idolCost = IdolMath.GetIdolCost(currentQuality, Config.ReferenceMaxQuality.Value, Config.TierBandSize.Value, Config.IdolCostBase.Value, Config.IdolCostIncrement.Value);
			return new ForgeUpgradeRequirement(idolPrefabName, idolCost);
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "OnDeath")]
	internal static class IdolDropPatch
	{
		[HarmonyPrefix]
		public static void Prefix(CharacterDrop __instance)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			Character component = ((Component)__instance).GetComponent<Character>();
			if (!((Object)(object)component == (Object)null) && !component.m_boss && !component.IsTamed())
			{
				int biomeTier = GetBiomeTier(((Component)component).transform.position);
				if (biomeTier >= 0)
				{
					int num = Mathf.Max(component.GetLevel() - 1, 0);
					float chance = Config.IdolDropBaseChance.Value + Config.IdolDropPerStarBonus.Value * (float)num;
					var (prefabName, prefabName2) = ItemBiomeData.IdolPrefabsByTier[biomeTier];
					AddDropIfMissing(__instance, prefabName, chance);
					AddDropIfMissing(__instance, prefabName2, chance);
				}
			}
		}

		private static void AddDropIfMissing(CharacterDrop drop, string prefabName, float chance)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			if (!((Object)(object)prefab == (Object)null) && !drop.m_drops.Exists((Drop d) => (Object)(object)d.m_prefab == (Object)(object)prefab))
			{
				drop.m_drops.Add(new Drop
				{
					m_prefab = prefab,
					m_amountMin = 1,
					m_amountMax = 1,
					m_chance = chance,
					m_onePerPlayer = false,
					m_levelMultiplier = false,
					m_dontScale = false
				});
			}
		}

		private static int GetBiomeTier(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected I4, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			Biome val = Heightmap.FindBiome(pos);
			if ((int)val <= 16)
			{
				switch (val - 1)
				{
				default:
					if ((int)val != 8)
					{
						if ((int)val != 16)
						{
							break;
						}
						return 4;
					}
					return 1;
				case 0:
					return 0;
				case 1:
					return 2;
				case 3:
					return 3;
				case 2:
					break;
				}
			}
			else
			{
				if ((int)val == 32)
				{
					return 6;
				}
				if ((int)val == 64)
				{
					return 7;
				}
				if ((int)val == 512)
				{
					return 5;
				}
			}
			return -1;
		}
	}
	internal static class IdolMath
	{
		public static int GetIdolCost(int currentQuality, int referenceMaxQuality, int tierBandSize, int baseCost, int increment)
		{
			int num = currentQuality - referenceMaxQuality;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num % tierBandSize;
			return baseCost + increment * num2;
		}

		public static int GetTierOffset(int currentQuality, int referenceMaxQuality, int tierBandSize)
		{
			int num = currentQuality - referenceMaxQuality;
			if (num < 0)
			{
				num = 0;
			}
			return num / tierBandSize;
		}
	}
	internal static class ItemBiomeData
	{
		public static readonly IReadOnlyDictionary<int, (string armorIdol, string weaponIdol)> IdolPrefabsByTier = new Dictionary<int, (string, string)>
		{
			{
				0,
				("Upgrader0Armor", "Upgrader0Weapon")
			},
			{
				1,
				("Upgrader1Armor", "Upgrader1Weapon")
			},
			{
				2,
				("Upgrader2Armor", "Upgrader2Weapon")
			},
			{
				3,
				("Upgrader3Armor", "Upgrader3Weapon")
			},
			{
				4,
				("Upgrader4Armor", "Upgrader4Weapon")
			},
			{
				5,
				("Upgrader5Armor", "Upgrader5Weapon")
			},
			{
				6,
				("Upgrader6Armor", "Upgrader6Weapon")
			},
			{
				7,
				("Upgrader7Armor", "Upgrader7Weapon")
			}
		};

		public static int GetIdolBiomeTier(string idolPrefabName)
		{
			foreach (KeyValuePair<int, (string, string)> item in IdolPrefabsByTier)
			{
				if (item.Value.Item1 == idolPrefabName || item.Value.Item2 == idolPrefabName)
				{
					return item.Key;
				}
			}
			throw new ArgumentException("'" + idolPrefabName + "' is not a recognized idol prefab name.");
		}
	}
	[BepInPlugin("beijingcarlo.forgeoftruepotential", "Forge of True Potential", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string PluginGuid = "beijingcarlo.forgeoftruepotential";

		private const string PluginName = "Forge of True Potential";

		private const string PluginVersion = "1.0.0";

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Config.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("beijingcarlo.forgeoftruepotential");
			_harmony.PatchAll();
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}