Decompiled source of EarlyAxesReforged v0.1.3

plugins\EarlyAxesReforged.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EarlyAxesReforged")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.3.0")]
[assembly: AssemblyInformationalVersion("0.1.3")]
[assembly: AssemblyProduct("EarlyAxesReforged")]
[assembly: AssemblyTitle("EarlyAxesReforged")]
[assembly: AssemblyVersion("0.1.3.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 EarlyAxesReforged
{
	[BepInPlugin("com.earlyaxesreforged", "Early Axes Reforged", "0.1.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class Requirement
		{
			public readonly string Prefab;

			public readonly int Amount;

			public readonly int AmountPerLevel;

			public Requirement(string prefab, int amount, int amountPerLevel)
			{
				Prefab = prefab;
				Amount = amount;
				AmountPerLevel = amountPerLevel;
			}
		}

		public const string PluginGuid = "com.earlyaxesreforged";

		public const string PluginName = "Early Axes Reforged";

		public const string PluginVersion = "0.1.3";

		private const string EarlyAxePrefabName = "AxeEarly";

		private const string BerserkirAxePrefabName = "AxeBerzerkr";

		private static readonly Dictionary<string, string> WeaponIcons = new Dictionary<string, string>
		{
			{ "CastAxeEarly", "CastAxeEarly.png" },
			{ "ForgedAxeEarly", "ForgedAxeEarly.png" },
			{ "TemperedAxeEarly", "TemperedAxeEarly.png" }
		};

		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Early Axes Reforged 0.1.3 is loading.");
			PrefabManager.OnVanillaPrefabsAvailable += RegisterWeapons;
		}

		private void RegisterWeapons()
		{
			try
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab("AxeEarly");
				GameObject prefab2 = PrefabManager.Instance.GetPrefab("AxeBerzerkr");
				if ((Object)(object)prefab == (Object)null || (Object)(object)prefab2 == (Object)null)
				{
					throw new InvalidOperationException($"Source prefab lookup failed. AxeEarly={(Object)(object)prefab != (Object)null}; AxeBerzerkr={(Object)(object)prefab2 != (Object)null}.");
				}
				RegisterWeapon("CastAxeEarly", "AxeEarly", "Cast Early Axes", prefab, copyEarlyAxeStats: false, 50f, 45f, 12f, 6f, 8f, 16f);
				RegisterWeapon("ForgedAxeEarly", "AxeBerzerkr", "Forged Early Axes", prefab, copyEarlyAxeStats: true, 70f, 55f, 21f, 10.5f, 10f, 20f);
				RegisterWeapon("TemperedAxeEarly", "AxeBerzerkr", "Tempered Early Axes", prefab, copyEarlyAxeStats: true, 110f, 65f, 39f, 19.5f, 14f, 28f);
				RegisterRecipes();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Weapon and recipe registration pass completed.");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Registration failed: {arg}");
			}
			finally
			{
				PrefabManager.OnVanillaPrefabsAvailable -= RegisterWeapons;
			}
		}

		private void RegisterWeapon(string prefabName, string sourcePrefabName, string displayName, GameObject earlyAxeSource, bool copyEarlyAxeStats, float slash, float chop, float blockPower, float blockPowerPerLevel, float primaryStamina, float secondaryStamina)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			try
			{
				CustomItem val = new CustomItem(prefabName, sourcePrefabName);
				GameObject itemPrefab = val.ItemPrefab;
				if ((Object)(object)itemPrefab == (Object)null)
				{
					throw new InvalidOperationException("Jötunn did not create '" + prefabName + "'.");
				}
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				ItemDrop component2 = earlyAxeSource.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData?.m_shared == null)
				{
					throw new InvalidOperationException("'" + prefabName + "' has no valid ItemDrop shared data.");
				}
				if (copyEarlyAxeStats)
				{
					if (component2?.m_itemData?.m_shared == null)
					{
						throw new InvalidOperationException("AxeEarly source has no valid shared data.");
					}
					CopySharedData(component2.m_itemData.m_shared, component.m_itemData.m_shared);
				}
				SharedData shared = component.m_itemData.m_shared;
				shared.m_name = displayName;
				shared.m_description = "An upgraded Early Axe.";
				shared.m_icons = (Sprite[])(object)new Sprite[1] { LoadIcon(WeaponIcons[prefabName]) };
				ApplyDamageProgression(shared, slash, chop);
				SetMember(shared, "m_blockPower", blockPower);
				SetMember(shared, "m_blockPowerPerLevel", blockPowerPerLevel);
				SetAttackStamina(shared, primaryStamina, secondaryStamina);
				ApplyWeaponColorization(itemPrefab, prefabName);
				if (!ItemManager.Instance.AddItem(val))
				{
					throw new InvalidOperationException("Jötunn rejected '" + prefabName + "'.");
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered " + prefabName + " (" + displayName + ")."));
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Could not register {prefabName}: {arg}");
			}
		}

		private void ApplyWeaponColorization(GameObject prefab, string prefabName)
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			switch (prefabName)
			{
			default:
				return;
			case "CastAxeEarly":
				((Color)(ref val))..ctor(0.80784315f, 0.5372549f, 14f / 51f, 1f);
				break;
			case "ForgedAxeEarly":
				((Color)(ref val))..ctor(0.62f, 0.78f, 0.96f, 1f);
				break;
			case "TemperedAxeEarly":
				((Color)(ref val))..ctor(29f / 51f, 0.8745098f, 0.6431373f, 1f);
				break;
			}
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			int num = 0;
			int num2 = 0;
			Renderer[] array = componentsInChildren;
			foreach (Renderer val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Material[] sharedMaterials = val2.sharedMaterials;
				if (sharedMaterials == null || sharedMaterials.Length == 0)
				{
					continue;
				}
				Material[] array2 = (Material[])(object)new Material[sharedMaterials.Length];
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Material val3 = sharedMaterials[j];
					if (!((Object)(object)val3 == (Object)null))
					{
						Material val4 = new Material(val3);
						((Object)val4).name = ((Object)val3).name + "_" + prefabName;
						array2[j] = val4;
						if (val4.HasProperty("_Color"))
						{
							val4.SetColor("_Color", val);
							num++;
							continue;
						}
						if (val4.HasProperty("_BaseColor"))
						{
							val4.SetColor("_BaseColor", val);
							num++;
							continue;
						}
						num2++;
						((BaseUnityPlugin)this).Logger.LogDebug((object)("Colorization skipped material '" + ((Object)val3).name + "' on '" + ((Object)val2).name + "': no _Color or _BaseColor property."));
					}
				}
				val2.sharedMaterials = array2;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Colorization for {prefabName}: tinted {num} material(s); skipped {num2} unsupported material(s); found {componentsInChildren.Length} renderer(s).");
		}

		private void ApplyDamageProgression(SharedData shared, float slash, float chop)
		{
			object member = GetMember(shared, "m_damages");
			object member2 = GetMember(shared, "m_damagesPerLevel");
			if (member == null || member2 == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not locate damage or per-level damage data; cloned damage values were retained.");
				return;
			}
			bool num = SetMember(member, "m_slash", slash);
			bool flag = SetMember(member, "m_chop", chop);
			bool flag2 = SetMember(member2, "m_slash", 5f);
			bool flag3 = SetMember(member2, "m_chop", 3f);
			bool flag4 = SetMember(shared, "m_damages", member);
			bool flag5 = SetMember(shared, "m_damagesPerLevel", member2);
			if (num && flag && flag2 && flag3 && flag4 && flag5)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Applied damage progression: Slash {slash}, Chop {chop}, per quality +5 Slash/+3 Chop.");
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"One or more damage values could not be applied; inspect the preceding member warnings.");
			}
		}

		private void SetAttackStamina(SharedData shared, float primary, float secondary)
		{
			object member = GetMember(shared, "m_attack");
			if (member == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not locate primary attack data; stamina values were retained from source prefab.");
				return;
			}
			SetMember(member, "m_attackStamina", primary);
			object member2 = GetMember(shared, "m_secondaryAttack");
			if (member2 != null)
			{
				SetMember(member2, "m_attackStamina", secondary);
			}
		}

		private void RegisterRecipes()
		{
			AddRecipe("CastAxeEarly", "forge", 1, new Requirement("AxeEarly", 1, 0), new Requirement("Bronze", 8, 4), new Requirement("DeerHide", 2, 1));
			AddRecipe("ForgedAxeEarly", "forge", 3, new Requirement("CastAxeEarly", 1, 0), new Requirement("Iron", 20, 10), new Requirement("BjornHide", 2, 1));
			AddRecipe("TemperedAxeEarly", "blackforge", 1, new Requirement("ForgedAxeEarly", 1, 0), new Requirement("BlackMetal", 20, 10), new Requirement("LinenThread", 6, 1));
			AddRecipe("AxeHead1", "forge", 1, new Requirement("Copper", 8, 0), new Requirement("AncientSeed", 1, 0));
			AddRecipe("AxeHead2", "forge", 1, new Requirement("Tin", 8, 0), new Requirement("GreydwarfEye", 1, 0));
		}

		private void AddRecipe(string item, string station, int stationLevel, params Requirement[] requirements)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			try
			{
				RecipeConfig val = new RecipeConfig
				{
					Item = item,
					CraftingStation = station,
					MinStationLevel = stationLevel
				};
				foreach (Requirement requirement in requirements)
				{
					val.AddRequirement(requirement.Prefab, requirement.Amount, requirement.AmountPerLevel);
				}
				ItemManager.Instance.AddRecipe(new CustomRecipe(val));
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Submitted recipe for {item} at {station} level {stationLevel}.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Could not register recipe for {item} at {station} level {stationLevel}: {ex}");
			}
		}

		private void CopySharedData(SharedData source, SharedData destination)
		{
			FieldInfo[] fields = typeof(SharedData).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!fieldInfo.IsInitOnly && !(fieldInfo.Name == "m_name") && !(fieldInfo.Name == "m_icons"))
				{
					try
					{
						fieldInfo.SetValue(destination, fieldInfo.GetValue(source));
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not copy SharedData field '" + fieldInfo.Name + "': " + ex.Message));
					}
				}
			}
		}

		private object GetMember(object target, string name)
		{
			if (target == null)
			{
				return null;
			}
			Type type = target.GetType();
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(target);
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(property != null) || !property.CanRead)
			{
				return null;
			}
			return property.GetValue(target, null);
		}

		private bool SetMember(object target, string name, object value)
		{
			if (target == null)
			{
				return false;
			}
			Type type = target.GetType();
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && !field.IsInitOnly)
			{
				field.SetValue(target, Convert.ChangeType(value, field.FieldType));
				return true;
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanWrite)
			{
				property.SetValue(target, Convert.ChangeType(value, property.PropertyType), null);
				return true;
			}
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not set '" + type.Name + "." + name + "'."));
			return false;
		}

		private Sprite LoadIcon(string fileName)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Assets", fileName);
			if (!File.Exists(text))
			{
				throw new FileNotFoundException("Required icon not deployed: " + text, text);
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				Object.Destroy((Object)(object)val);
				throw new InvalidDataException("Unity could not load '" + text + "'.");
			}
			((Object)val).name = Path.GetFileNameWithoutExtension(fileName);
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}
	}
}