Decompiled source of ValkreamPlus v1.0.4

ValkreamPlus.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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.Bootstrap;
using HarmonyLib;
using Jewelcrafting;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using SimpleJson;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValkreamPlus")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValkreamPlus")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.0.4")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.0")]
[module: UnverifiableCode]
namespace ValkreamPlus;

internal class LagPatch
{
	internal static class NeckCache
	{
		private static readonly Dictionary<VisEquipment, ItemData> Cache = new Dictionary<VisEquipment, ItemData>();

		private static readonly HashSet<VisEquipment> Dirty = new HashSet<VisEquipment>();

		public static void MarkDirty(VisEquipment vis)
		{
			if (Object.op_Implicit((Object)(object)vis))
			{
				Dirty.Add(vis);
			}
		}

		public static bool TryGet(Player p, out ItemData neck)
		{
			neck = null;
			if (!Ready || (Object)(object)p == (Object)null)
			{
				return false;
			}
			VisEquipment visEquipment = ((Humanoid)p).m_visEquipment;
			if (!Object.op_Implicit((Object)(object)visEquipment))
			{
				return false;
			}
			if (!Dirty.Contains(visEquipment) && Cache.TryGetValue(visEquipment, out neck) && neck != null)
			{
				return true;
			}
			object[] array = new object[2] { visEquipment, null };
			if ((bool)MI_TryGetValue.Invoke(VisualsDict, array) && array[1] != null)
			{
				object obj = array[1];
				object? value = FI_EquippedNeckItem.GetValue(obj);
				neck = (ItemData)((value is ItemData) ? value : null);
				Cache[visEquipment] = neck;
			}
			else
			{
				Cache.Remove(visEquipment);
				neck = null;
			}
			Dirty.Remove(visEquipment);
			return neck != null;
		}
	}

	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	private static class Humanoid_Equip_Patch
	{
		private static void Postfix(Humanoid __instance)
		{
			NeckCache.MarkDirty(__instance?.m_visEquipment);
		}
	}

	[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
	private static class Humanoid_Unequip_Patch
	{
		private static void Postfix(Humanoid __instance)
		{
			NeckCache.MarkDirty(__instance?.m_visEquipment);
		}
	}

	public static bool Ready;

	public static object VisualsDict;

	public static MethodInfo MI_TryGetValue;

	public static FieldInfo FI_EquippedNeckItem;

	public static void Init()
	{
		try
		{
			if (!Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.jewelcrafting", out var value))
			{
				Ready = false;
				return;
			}
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			Type type = assembly.GetType("Jewelcrafting.Visual");
			if (type == null)
			{
				Ready = false;
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(type, "visuals");
			if (fieldInfo == null)
			{
				Ready = false;
				return;
			}
			VisualsDict = fieldInfo.GetValue(null);
			if (VisualsDict == null)
			{
				Ready = false;
				return;
			}
			MI_TryGetValue = VisualsDict.GetType().GetMethod("TryGetValue");
			if (MI_TryGetValue == null)
			{
				Ready = false;
				return;
			}
			Type parameterType = MI_TryGetValue.GetParameters()[1].ParameterType;
			Type type2 = (parameterType.IsByRef ? parameterType.GetElementType() : parameterType);
			FI_EquippedNeckItem = AccessTools.Field(type2, "equippedNeckItem");
			Ready = FI_EquippedNeckItem != null;
		}
		catch
		{
			Ready = false;
		}
	}
}
[BepInPlugin("com.jotunn.ValkreamPlus", "ValkreamPlus", "1.0.4")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class ValkreamPlus : BaseUnityPlugin
{
	public class SE_CollierValkream : StatusEffect
	{
		public float m_eitr;

		public float m_skillup;

		public float m_regenModifier;

		public void SetEitr(float eitr)
		{
			m_eitr = eitr;
		}

		public void SetSkill(float skill)
		{
			m_skillup = skill;
		}

		public void SetRegenModifier(float regenModifier)
		{
			m_regenModifier = regenModifier;
		}

		public override void ModifyEitrRegen(ref float regen)
		{
			regen *= m_regenModifier;
		}

		public override void ModifySkillLevel(SkillType skill, ref float value)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)skill == 10 || (int)skill == 9)
			{
				value += m_skillup;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
	public static class EitrFromItemsPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance, ref float eitr)
		{
			if (((Character)(__instance?)).m_seman == null)
			{
				return;
			}
			foreach (StatusEffect statusEffect in ((Character)__instance).m_seman.m_statusEffects)
			{
				if (statusEffect is SE_CollierValkream sE_CollierValkream && sE_CollierValkream.m_eitr != 0f)
				{
					eitr += sE_CollierValkream.m_eitr;
				}
			}
		}
	}

	[HarmonyPatch]
	public static class Patch_IsNeckItem
	{
		private static MethodBase TargetMethod()
		{
			if (!Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.jewelcrafting", out var value))
			{
				return null;
			}
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			Type type = assembly.GetType("Jewelcrafting.Visual");
			if (type == null)
			{
				return null;
			}
			return AccessTools.Method(type, "IsNeckItem", (Type[])null, (Type[])null);
		}

		private static void Postfix(ItemData item, ref bool __result)
		{
			object obj;
			if (item == null)
			{
				obj = null;
			}
			else
			{
				GameObject dropPrefab = item.m_dropPrefab;
				obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
			}
			if ((string?)obj == "JC_Necklace_Valkream")
			{
				__result = true;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "GetBodyArmor")]
	public static class AddNecklaceArmorPatch
	{
		public static void Postfix(Player __instance, ref float __result)
		{
			if (!((Object)(object)__instance == (Object)null) && LagPatch.Ready && LagPatch.NeckCache.TryGet(__instance, out var neck) && (Object)(object)neck?.m_dropPrefab != (Object)null && ((Object)neck.m_dropPrefab).name == "JC_Necklace_Valkream")
			{
				SharedData shared = neck.m_shared;
				int num = Mathf.Max(1, neck.m_quality);
				__result += shared.m_armor + shared.m_armorPerLevel * (float)(num - 1);
			}
		}
	}

	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int)
	})]
	public static class NecklaceArmorTooltipPatch
	{
		[HarmonyPostfix]
		public static void Postfix(ItemData item, int qualityLevel, float worldLevel, ref string __result)
		{
			if ((Object)(object)item?.m_dropPrefab == (Object)null || ((Object)item.m_dropPrefab).name != "JC_Necklace_Valkream")
			{
				return;
			}
			string text = Localization.instance.Localize("$item_armor");
			string value = Localization.instance.Localize("$item_quality");
			if (__result.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return;
			}
			float num = item.m_shared.m_armor + item.m_shared.m_armorPerLevel * (float)Mathf.Max(0, qualityLevel - 1);
			string text2 = $"\n{text}: <color=orange>{num:0}</color>";
			int num2 = __result.IndexOf(value, StringComparison.OrdinalIgnoreCase);
			if (num2 >= 0)
			{
				int num3 = __result.IndexOf('\n', num2);
				if (num3 < 0)
				{
					num3 = __result.Length;
				}
				__result = __result.Insert(num3, text2);
			}
			else
			{
				__result = text2 + "\n" + __result;
			}
		}
	}

	public const string PluginGUID = "com.jotunn.ValkreamPlus";

	public const string PluginName = "ValkreamPlus";

	public const string PluginVersion = "1.0.4";

	public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

	private void Awake()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		AddLocalizations();
		PrefabManager.OnVanillaPrefabsAvailable += AddCollierValkream;
		new Harmony("com.jotunn.ValkreamPlus").PatchAll();
		AddJetonsValkream();
	}

	public static Sprite LoadEmbeddedSprite(string resourcePath)
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Expected O, but got Unknown
		//IL_009d: 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)
		Assembly assembly = typeof(ValkreamPlus).Assembly;
		using Stream stream = assembly.GetManifestResourceStream(resourcePath);
		if (stream == null)
		{
			Logger.LogWarning((object)("Embedded resource '" + resourcePath + "' not found."));
			return null;
		}
		byte[] array;
		using (MemoryStream memoryStream = new MemoryStream())
		{
			stream.CopyTo(memoryStream);
			array = memoryStream.ToArray();
		}
		Texture2D val = new Texture2D(2, 2);
		if (!ImageConversion.LoadImage(val, array))
		{
			Logger.LogWarning((object)"Failed to load texture from embedded resource.");
			return null;
		}
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height);
		return Sprite.Create(val, val2, new Vector2(0.5f, 0.5f));
	}

	private void AddCollierValkream()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected O, but got Unknown
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Expected O, but got Unknown
		PrefabManager.OnVanillaPrefabsAvailable -= AddCollierValkream;
		GameObject val = API.CreateNecklaceFromTemplate("Red", Color.red);
		API.MarkJewelry(val);
		((Object)val).name = "JC_Necklace_Valkream";
		ItemConfig collierValkreamConfig = new ItemConfig();
		collierValkreamConfig.Name = "$item_colliervalkream";
		collierValkreamConfig.Description = "$item_colliervalkream_desc";
		Sprite val2 = LoadEmbeddedSprite("ValkreamPlus.Assets.CollierValkreamIcon6.png");
		collierValkreamConfig.Icon = val2;
		collierValkreamConfig.AddRequirement("ValkreamCoinsV2", 20, 10);
		collierValkreamConfig.CraftingStation = "piece_workbench";
		collierValkreamConfig.RepairStation = "piece_workbench";
		SharedData shared = val.GetComponent<ItemDrop>().m_itemData.m_shared;
		shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 };
		shared.m_armor = 1f;
		shared.m_armorPerLevel = 1f;
		RegisterAsUpgradeableJewelry(shared.m_name);
		SE_CollierValkream sE_CollierValkream = ScriptableObject.CreateInstance<SE_CollierValkream>();
		((Object)sE_CollierValkream).name = "SE_CollierValkream";
		((StatusEffect)sE_CollierValkream).m_name = "Collier Valkream";
		((StatusEffect)sE_CollierValkream).m_icon = shared.m_icons[0];
		((StatusEffect)sE_CollierValkream).m_tooltip = "Le pouvoir des dieux de Valkream vous imprègne. Cela vous offre +10 aux skills de magie, +30% de regen d'eitr et +50 d'eitr maximal.";
		sE_CollierValkream.SetEitr(50f);
		sE_CollierValkream.SetSkill(11f);
		sE_CollierValkream.SetRegenModifier(1.3f);
		shared.m_equipStatusEffect = (StatusEffect)(object)sE_CollierValkream;
		CustomItem val3 = new CustomItem(val, false, collierValkreamConfig);
		ItemManager.Instance.AddItem(val3);
		ItemManager.OnItemsRegistered += delegate
		{
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("JC_Necklace_Valkream");
			ItemDrop val4 = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val4 != (Object)null)
			{
				val4.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { collierValkreamConfig.Icon };
			}
		};
	}

	private static void RegisterAsUpgradeableJewelry(string sharedName)
	{
		try
		{
			if (!Chainloader.PluginInfos.TryGetValue("org.bepinex.plugins.jewelcrafting", out var value))
			{
				Logger.LogWarning((object)"Jewelcrafting not found; skip jewelry registration.");
				return;
			}
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				FieldInfo field = type.GetField("upgradeableJewelry", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && typeof(HashSet<string>).IsAssignableFrom(field.FieldType))
				{
					HashSet<string> hashSet = (HashSet<string>)field.GetValue(null);
					if (hashSet.Add(sharedName))
					{
						Logger.LogInfo((object)("[ValkreamPlus] Registered '" + sharedName + "' as upgradeable jewelry via " + type.FullName + ".upgradeableJewelry"));
					}
					return;
				}
			}
			Logger.LogWarning((object)"Could not find 'upgradeableJewelry' field in Jewelcrafting assembly.");
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Failed to register upgradeable jewelry: {arg}");
		}
	}

	private void AddJetonsValkream()
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		AssetBundle val = AssetUtils.LoadAssetBundleFromResources("customcoins");
		GameObject val2 = val.LoadAsset<GameObject>("assets/custombb/admincoinsv2.prefab");
		GameObject val3 = val.LoadAsset<GameObject>("assets/custombb/lordscoinsv2.prefab");
		GameObject val4 = val.LoadAsset<GameObject>("assets/custombb/valkreamcoinsv2.prefab");
		CustomItem val5 = new CustomItem(val2, true);
		ItemManager.Instance.AddItem(val5);
		CustomItem val6 = new CustomItem(val3, true);
		ItemManager.Instance.AddItem(val6);
		CustomItem val7 = new CustomItem(val4, true);
		ItemManager.Instance.AddItem(val7);
	}

	private void AddLocalizations()
	{
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string configPath = Paths.ConfigPath;
		if (!Directory.Exists(configPath))
		{
			Logger.LogWarning((object)("Config path not found: " + configPath));
			return;
		}
		List<string> list = (from x in (from dir in Directory.EnumerateDirectories(configPath, "*", SearchOption.AllDirectories)
				where string.Equals(Path.GetFileName(dir), "ValkreamPlus", StringComparison.OrdinalIgnoreCase)
				select new
				{
					Path = dir,
					Depth = dir.TrimEnd(new char[1] { Path.DirectorySeparatorChar }).Count((char c) => c == Path.DirectorySeparatorChar)
				} into x
				orderby x.Depth
				select x).ThenBy(x => x.Path, StringComparer.OrdinalIgnoreCase)
			select x.Path).ToList();
		if (list.Count == 0)
		{
			Logger.LogWarning((object)("No 'ValkreamPlus' directory for translations found anywhere under: " + configPath));
			return;
		}
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		foreach (string item in list)
		{
			foreach (string item2 in Directory.EnumerateFiles(item, "*.json", SearchOption.AllDirectories).OrderBy<string, string>((string f) => f, StringComparer.OrdinalIgnoreCase))
			{
				if (!hashSet.Add(item2))
				{
					continue;
				}
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item2);
				try
				{
					string text = File.ReadAllText(item2);
					Dictionary<string, string> dictionary = SimpleJson.DeserializeObject<Dictionary<string, string>>(text);
					if (dictionary == null)
					{
						Logger.LogWarning((object)("Empty or invalid JSON in " + item2));
						continue;
					}
					int num = 0;
					foreach (KeyValuePair<string, string> item3 in dictionary)
					{
						try
						{
							string key = item3.Key;
							localization.AddTranslation(ref fileNameWithoutExtension, ref key, item3.Value);
							num++;
						}
						catch (Exception ex)
						{
							Logger.LogWarning((object)("Could not add key '" + item3.Key + "' from " + item2 + ": " + ex.Message));
						}
					}
				}
				catch (Exception ex2)
				{
					Logger.LogError((object)("Failed to load localization from " + item2 + ": " + ex2.Message));
				}
			}
		}
	}
}