Decompiled source of LordsOfTheKnightCape SOF v1.1.0

plugins/LordsCape/LordsCape.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
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(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.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 LordsCape
{
	[BepInPlugin("com.tronn.lordscape", "LordsCape", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class LordsCapePlugin : BaseUnityPlugin
	{
		public const string GUID = "com.tronn.lordscape";

		public const string NAME = "LordsCape";

		public const string VERSION = "1.1.0";

		public const string CapeId = "CapeLongNight";

		public const string MageCapeId = "CapeLongNightMage";

		internal static LordsCapePlugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<float> EmissionIntensity;

		internal static ConfigEntry<bool> FlipBack;

		private static Texture2D _albedo;

		private static Texture2D _emission;

		private static Texture2D _mageAlbedo;

		private static Texture2D _mageEmission;

		private static Texture2D _styleWhite;

		private static int _capeHash;

		private static int _mageHash;

		private static Mesh _unfolded;

		private static readonly HashSet<int> _fixedMeshes = new HashSet<int>();

		private static readonly HashSet<int> _done = new HashSet<int>();

		internal static string PluginDir => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		private void Awake()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			EmissionIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("LordsCape", "EmissionIntensity", 4f, "Brightness of the raven's glowing eyes.");
			FlipBack = ((BaseUnityPlugin)this).Config.Bind<bool>("LordsCape", "FlipBack", false, "Flip which half of the cape unfolds - set true if the logo text appears mirrored.");
			Harmony val = new Harmony("com.tronn.lordscape");
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(VisEquipment), "SetCapeEquipped", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(LordsCapePlugin), "OnCapeEquipped", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"VisEquipment.SetCapeEquipped not found - worn-cape fix inactive");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("worn-cape hook failed: " + ex.Message));
			}
			PrefabManager.OnVanillaPrefabsAvailable += AddItems;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"LordsCape 1.1.0 loaded");
		}

		private static void AddItems()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			try
			{
				_capeHash = StringExtensionMethods.GetStableHashCode("CapeLongNight");
				_mageHash = StringExtensionMethods.GetStableHashCode("CapeLongNightMage");
				if ((Object)(object)_albedo == (Object)null)
				{
					_albedo = LoadTex("LordsCape_albedo.png");
				}
				if ((Object)(object)_emission == (Object)null)
				{
					_emission = LoadTex("LordsCape_emission.png");
				}
				if ((Object)(object)_mageAlbedo == (Object)null)
				{
					_mageAlbedo = LoadTex("LordsMage_albedo.png");
				}
				if ((Object)(object)_mageEmission == (Object)null)
				{
					_mageEmission = LoadTex("LordsMage_emission.png");
				}
				ItemConfig val = new ItemConfig();
				val.Name = "Cape of the Long Night";
				val.Description = "Black wings of the clan. The raven watches, and its eyes burn.";
				val.CraftingStation = "piece_workbench";
				val.MinStationLevel = 2;
				val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
				{
					new RequirementConfig("LinenThread", 20, 10, true),
					new RequirementConfig("Coal", 10, 5, true)
				};
				CustomItem val2 = new CustomItem("CapeLongNight", "CapeLinen", val);
				ItemManager.Instance.AddItem(val2);
				PatchClone(val2.ItemPrefab, _albedo, _emission, unfold: true);
				val = new ItemConfig();
				val.Name = "Magecloak of the Long Night";
				val.Description = "The raven's shadow, woven for the clan's spellweavers.";
				val.CraftingStation = "piece_workbench";
				val.MinStationLevel = 2;
				val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
				{
					new RequirementConfig("LinenThread", 20, 10, true),
					new RequirementConfig("Feathers", 10, 5, true)
				};
				CustomItem val3 = new CustomItem("CapeLongNightMage", "CapeDeepNorthMage", val);
				ItemManager.Instance.AddItem(val3);
				PatchClone(val3.ItemPrefab, _mageAlbedo, _mageEmission, unfold: false);
				Log.LogInfo((object)"registered CapeLongNight and CapeLongNightMage");
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex);
			}
			finally
			{
				PrefabManager.OnVanillaPrefabsAvailable -= AddItems;
			}
		}

		private static void PatchClone(GameObject prefab, Texture2D albedo, Texture2D emission, bool unfold)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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)
			//IL_0101: Expected O, but got Unknown
			if ((Object)(object)prefab == (Object)null || (Object)(object)albedo == (Object)null)
			{
				Log.LogWarning((object)"clone patch skipped (missing prefab/texture)");
				return;
			}
			if ((Object)(object)_styleWhite == (Object)null)
			{
				_styleWhite = new Texture2D(4, 4, (TextureFormat)4, false);
				Color32[] array = (Color32[])(object)new Color32[16];
				for (int i = 0; i < 16; i++)
				{
					array[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
				}
				_styleWhite.SetPixels32(array);
				_styleWhite.Apply();
			}
			int num = 0;
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
				if (unfold && (Object)(object)val2 != (Object)null && (Object)(object)val2.sharedMesh != (Object)null)
				{
					val2.sharedMesh = UnfoldMesh(val2.sharedMesh);
				}
				Material[] sharedMaterials = val.sharedMaterials;
				for (int k = 0; k < sharedMaterials.Length; k++)
				{
					if (!((Object)(object)sharedMaterials[k] == (Object)null))
					{
						sharedMaterials[k] = new Material(sharedMaterials[k]);
						Patch(sharedMaterials[k], albedo, emission);
						num++;
					}
				}
				val.sharedMaterials = sharedMaterials;
			}
			Log.LogInfo((object)$"{((Object)prefab).name}: patched {num} material instance(s)");
		}

		public static void OnCapeEquipped(VisEquipment __instance, bool __result, int hash)
		{
			if (__result && !((Object)(object)Instance == (Object)null) && hash == _capeHash)
			{
				((MonoBehaviour)Instance).StartCoroutine(FixWornCape(__instance));
			}
		}

		internal static Texture2D LoadTex(string file)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			string text = Path.Combine(PluginDir, file);
			if (!File.Exists(text))
			{
				Log.LogWarning((object)("texture missing: " + text));
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, false);
			byte[] array = File.ReadAllBytes(text);
			MethodInfo method = typeof(ImageConversion).GetMethod("LoadImage", new Type[3]
			{
				typeof(Texture2D),
				typeof(byte[]),
				typeof(bool)
			});
			if (method == null || !(bool)method.Invoke(null, new object[3] { val, array, false }))
			{
				Log.LogError((object)("LoadImage failed for " + file));
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Log.LogInfo((object)$"loaded {file}: {((Texture)val).width}x{((Texture)val).height}");
			return val;
		}

		internal static Mesh UnfoldMesh(Mesh src)
		{
			if ((Object)(object)_unfolded != (Object)null)
			{
				return _unfolded;
			}
			Mesh val = Object.Instantiate<Mesh>(src);
			((Object)val).name = ((Object)src).name + "_lords";
			_fixedMeshes.Add(((Object)val).GetInstanceID());
			if (TryUnfold(val))
			{
				_unfolded = val;
			}
			return _unfolded ?? src;
		}

		internal static bool TryUnfold(Mesh m)
		{
			//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_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] vertices = m.vertices;
			Vector2[] uv = m.uv;
			Dictionary<long, List<int>> dictionary = new Dictionary<long, List<int>>();
			for (int i = 0; i < uv.Length; i++)
			{
				if (!(uv[i].x >= 0.228f))
				{
					long key = (long)Mathf.Round(uv[i].x * 2000f) * 100000 + (long)Mathf.Round(uv[i].y * 2000f);
					if (!dictionary.TryGetValue(key, out var value))
					{
						value = (dictionary[key] = new List<int>());
					}
					value.Add(i);
				}
			}
			Vector3 val = Vector3.zero;
			List<KeyValuePair<int, int>> list2 = new List<KeyValuePair<int, int>>();
			foreach (List<int> value3 in dictionary.Values)
			{
				for (int j = 0; j < value3.Count; j++)
				{
					for (int k = j + 1; k < value3.Count; k++)
					{
						Vector3 val2 = vertices[value3[j]] - vertices[value3[k]];
						if (((Vector3)(ref val2)).sqrMagnitude > 1E-14f)
						{
							val += new Vector3(Mathf.Abs(val2.x), Mathf.Abs(val2.y), Mathf.Abs(val2.z));
							list2.Add(new KeyValuePair<int, int>(value3[j], value3[k]));
						}
					}
				}
			}
			int num = 0;
			if (val.y > val.x && val.y >= val.z)
			{
				num = 1;
			}
			else if (val.z > val.x && val.z >= val.y)
			{
				num = 2;
			}
			float num2 = 0f;
			foreach (KeyValuePair<int, int> item in list2)
			{
				num2 += (((Vector3)(ref vertices[item.Key]))[num] + ((Vector3)(ref vertices[item.Value]))[num]) * 0.5f;
			}
			if (list2.Count > 0)
			{
				num2 /= (float)list2.Count;
			}
			if (list2.Count < 4)
			{
				Log.LogInfo((object)$"mesh '{((Object)m).name}' ({uv.Length} verts): no mirrored panel found (pairs={list2.Count}) - skipping");
				return false;
			}
			bool value2 = FlipBack.Value;
			int num3 = 0;
			for (int l = 0; l < uv.Length; l++)
			{
				if (uv[l].x < 0.228f)
				{
					float num4 = ((Vector3)(ref vertices[l]))[num] - num2;
					if (value2 ? (num4 > 0f) : (num4 < 0f))
					{
						uv[l].x = 0.454f - uv[l].x;
						num3++;
					}
				}
				else
				{
					uv[l].x += 0.5f;
				}
			}
			try
			{
				m.uv = uv;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("uv write failed on '" + ((Object)m).name + "': " + ex.Message));
				return false;
			}
			Log.LogInfo((object)$"unfold '{((Object)m).name}': axis={num} spread={val} mid={num2:F5} pairs={list2.Count} reflected={num3}/{uv.Length}");
			return true;
		}

		internal static IEnumerator FixWornCape(VisEquipment ve)
		{
			FieldInfo fi = AccessTools.Field(typeof(VisEquipment), "m_capeItemInstances");
			if (fi == null)
			{
				Log.LogWarning((object)"m_capeItemInstances not found");
				yield break;
			}
			for (float t = 0f; t < 6f; t += 0.25f)
			{
				if ((Object)(object)ve == (Object)null)
				{
					break;
				}
				if (fi.GetValue(ve) is List<GameObject> list)
				{
					foreach (GameObject item in list)
					{
						if ((Object)(object)item == (Object)null)
						{
							continue;
						}
						SkinnedMeshRenderer[] componentsInChildren = item.GetComponentsInChildren<SkinnedMeshRenderer>(true);
						for (int i = 0; i < componentsInChildren.Length; i++)
						{
							Mesh sharedMesh = componentsInChildren[i].sharedMesh;
							if (!((Object)(object)sharedMesh == (Object)null) && _fixedMeshes.Add(((Object)sharedMesh).GetInstanceID()))
							{
								Log.LogInfo((object)$"worn cape mesh: '{((Object)sharedMesh).name}' id={((Object)sharedMesh).GetInstanceID()} verts={sharedMesh.vertexCount} readable={sharedMesh.isReadable}");
								TryUnfold(sharedMesh);
							}
						}
					}
				}
				yield return (object)new WaitForSeconds(0.25f);
			}
		}

		private static bool Patch(Material mat, Texture2D albedo, Texture2D emission)
		{
			//IL_004b: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mat == (Object)null)
			{
				return false;
			}
			if (!_done.Add(((Object)mat).GetInstanceID()))
			{
				return false;
			}
			if (mat.HasProperty("_MainTex"))
			{
				mat.SetTexture("_MainTex", (Texture)(object)albedo);
			}
			if (mat.HasProperty("_Color"))
			{
				mat.SetColor("_Color", Color.white);
			}
			if (mat.HasProperty("_UseStyles"))
			{
				mat.SetFloat("_UseStyles", 0f);
			}
			if (mat.HasProperty("_Style"))
			{
				mat.SetFloat("_Style", 0f);
			}
			if (mat.HasProperty("_StyleTex"))
			{
				mat.SetTexture("_StyleTex", (Texture)(object)_styleWhite);
			}
			string[] array = new string[3] { "_USESTYLES_ON", "USE_STYLES", "_STYLES" };
			foreach (string text in array)
			{
				mat.DisableKeyword(text);
			}
			if (mat.HasProperty("_Hue"))
			{
				mat.SetFloat("_Hue", 0f);
			}
			if (mat.HasProperty("_Saturation"))
			{
				mat.SetFloat("_Saturation", 0f);
			}
			if (mat.HasProperty("_Value"))
			{
				mat.SetFloat("_Value", 0f);
			}
			if ((Object)(object)emission != (Object)null)
			{
				Color val = Color.red * EmissionIntensity.Value;
				if (mat.HasProperty("_EmissionMap"))
				{
					mat.SetTexture("_EmissionMap", (Texture)(object)emission);
				}
				if (mat.HasProperty("_EmissiveTex"))
				{
					mat.SetTexture("_EmissiveTex", (Texture)(object)emission);
				}
				if (mat.HasProperty("_EmissionColor"))
				{
					mat.SetColor("_EmissionColor", val);
				}
				if (mat.HasProperty("_EmissiveColor"))
				{
					mat.SetColor("_EmissiveColor", val);
				}
				mat.EnableKeyword("_EMISSION");
			}
			return true;
		}
	}
}