Decompiled source of AdagasCruzadas v0.3.0

plugins\AdagasCruzadas\AdagasCruzadas.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using AdagasCruzadas.Combat.StatusEffects;
using AdagasCruzadas.Items;
using BepInEx;
using BepInEx.Logging;
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.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Mayhem")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Adagas duplas (uma em cada mao) para cada adaga do Valheim.")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+fa1f3fbf230f2cc540ea136e6c16526c1dd6cb5f")]
[assembly: AssemblyProduct("AdagasCruzadas")]
[assembly: AssemblyTitle("AdagasCruzadas")]
[assembly: AssemblyVersion("0.2.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 AdagasCruzadas
{
	[BepInPlugin("com.mayhem.adagascruzadas", "AdagasCruzadas", "0.3.0")]
	internal class AdagasCruzadasPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.mayhem.adagascruzadas";

		public const string PluginName = "AdagasCruzadas";

		public const string PluginVersion = "0.3.0";

		internal static ManualLogSource Log;

		private readonly Harmony _harmony = new Harmony("com.mayhem.adagascruzadas");

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			_harmony.PatchAll();
			Log.LogInfo((object)"AdagasCruzadas 0.3.0 carregado.");
		}

		private void OnDestroy()
		{
			_harmony.UnpatchSelf();
		}
	}
}
namespace AdagasCruzadas.Network
{
	[HarmonyPatch(typeof(ZNet))]
	internal static class VersionCheckPatch
	{
		private const string RpcName = "AdagasCruzadas_Version";

		private const int ErrorVersion = 3;

		private static readonly HashSet<ZRpc> VerifiedPeers = new HashSet<ZRpc>();

		private static bool _serverVerified;

		private static readonly FieldInfo ConnectionStatusField = AccessTools.Field(typeof(ZNet), "m_connectionStatus");

		[HarmonyPostfix]
		[HarmonyPatch("OnNewConnection")]
		private static void OnNewConnectionPostfix(ZNet __instance, ZNetPeer peer)
		{
			VerifiedPeers.RemoveWhere((ZRpc rpc) => rpc == null || !rpc.IsConnected());
			peer.m_rpc.Register<string>("AdagasCruzadas_Version", (Action<ZRpc, string>)OnVersionRpc);
			if (!__instance.IsServer())
			{
				_serverVerified = false;
				peer.m_rpc.Invoke("AdagasCruzadas_Version", new object[1] { "0.3.0" });
			}
		}

		private static void OnVersionRpc(ZRpc rpc, string remoteVersion)
		{
			string text = "0.3.0";
			bool flag = remoteVersion == text;
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				if (flag)
				{
					VerifiedPeers.Add(rpc);
					rpc.Invoke("AdagasCruzadas_Version", new object[1] { text });
					return;
				}
				AdagasCruzadasPlugin.Log.LogWarning((object)("Cliente recusado: AdagasCruzadas " + remoteVersion + " (servidor: " + text + ")."));
				rpc.Invoke("Error", new object[1] { 3 });
			}
			else if (flag)
			{
				_serverVerified = true;
			}
			else
			{
				AdagasCruzadasPlugin.Log.LogWarning((object)("Servidor com AdagasCruzadas " + remoteVersion + ", este cliente tem " + text + ". Desconectando."));
				SetClientError();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("RPC_PeerInfo")]
		private static bool PeerInfoPrefix(ZNet __instance, ZRpc rpc)
		{
			if (__instance.IsServer())
			{
				if (VerifiedPeers.Contains(rpc))
				{
					return true;
				}
				AdagasCruzadasPlugin.Log.LogWarning((object)"Cliente sem AdagasCruzadas tentou conectar; recusado.");
				rpc.Invoke("Error", new object[1] { 3 });
				return false;
			}
			if (_serverVerified)
			{
				return true;
			}
			AdagasCruzadasPlugin.Log.LogWarning((object)"Servidor sem AdagasCruzadas (não respondeu à checagem de versão). Desconectando.");
			SetClientError();
			return false;
		}

		private static void SetClientError()
		{
			ConnectionStatusField.SetValue(null, (object)(ConnectionStatus)3);
		}
	}
}
namespace AdagasCruzadas.Localization
{
	[HarmonyPatch(typeof(Localization), "SetupLanguage")]
	internal static class DualDaggerLocalization
	{
		private const string PortugueseBrazilian = "Portuguese_Brazilian";

		private static void Postfix(Localization __instance, string language)
		{
			bool flag = language == "Portuguese_Brazilian";
			DualDaggerDefinition[] all = DualDaggerDefinition.All;
			foreach (DualDaggerDefinition dualDaggerDefinition in all)
			{
				LocalizationHelper.Add(__instance, dualDaggerDefinition.NameKey, flag ? dualDaggerDefinition.NamePt : dualDaggerDefinition.NameEn);
				LocalizationHelper.Add(__instance, dualDaggerDefinition.DescriptionKey, flag ? dualDaggerDefinition.DescriptionPt : dualDaggerDefinition.DescriptionEn);
			}
		}
	}
	[HarmonyPatch(typeof(Localization), "SetupLanguage")]
	internal static class InfusionLocalization
	{
		private const string PortugueseBrazilian = "Portuguese_Brazilian";

		private static void Postfix(Localization __instance, string language)
		{
			bool flag = language == "Portuguese_Brazilian";
			InfusionDefinition[] all = InfusionDefinition.All;
			foreach (InfusionDefinition infusionDefinition in all)
			{
				LocalizationHelper.Add(__instance, infusionDefinition.NameKey, flag ? infusionDefinition.NamePt : infusionDefinition.NameEn);
				LocalizationHelper.Add(__instance, infusionDefinition.DescriptionKey, flag ? infusionDefinition.DescriptionPt : infusionDefinition.DescriptionEn);
			}
			LocalizationHelper.Add(__instance, "adagascruzadas_infusion_needweapon", flag ? "É preciso estar com uma adaga, espada, lança, machado, arco ou besta de uma mão equipada." : "You need a one-handed knife, sword, spear, axe, bow or crossbow equipped.");
			LocalizationHelper.Add(__instance, "adagascruzadas_infusion_conflict", flag ? "Esta arma já causa esse efeito por conta própria" : "This weapon already deals that effect on its own");
		}
	}
	internal static class LocalizationHelper
	{
		private static readonly MethodInfo AddWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null);

		public static void Add(Localization loc, string key, string text)
		{
			AddWord.Invoke(loc, new object[2] { key, text });
		}
	}
}
namespace AdagasCruzadas.Items
{
	internal static class CraftingStationLookup
	{
		public static CraftingStation Find(string prefabName)
		{
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefabName) : null);
			if ((Object)(object)val != (Object)null)
			{
				CraftingStation component = val.GetComponent<CraftingStation>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
			return ((IEnumerable<CraftingStation>)Resources.FindObjectsOfTypeAll<CraftingStation>()).FirstOrDefault((Func<CraftingStation, bool>)((CraftingStation c) => ((Object)((Component)c).gameObject).name == prefabName));
		}
	}
	internal class RequirementDef
	{
		public string Item;

		public int Amount;

		public int AmountPerLevel;

		public RequirementDef(string item, int amount, int amountPerLevel = 0)
		{
			Item = item;
			Amount = amount;
			AmountPerLevel = amountPerLevel;
		}
	}
	internal class DualDaggerDefinition
	{
		public string BasePrefabName;

		public string DualPrefabName;

		public string NamePt;

		public string NameEn;

		public string DescriptionPt;

		public string DescriptionEn;

		public string CraftingStation;

		public int MinStationLevel;

		public RequirementDef[] Requirements;

		public bool KeepBaseAnimationState;

		public static readonly DualDaggerDefinition[] All = new DualDaggerDefinition[8]
		{
			new DualDaggerDefinition
			{
				BasePrefabName = "KnifeFlint",
				DualPrefabName = "AdagasCruzadas_KnifeFlint_Dual",
				NamePt = "Adagas Cruzadas de Sílex",
				NameEn = "Flint Crossed Daggers",
				DescriptionPt = "Um par de facas de sílex lascado, uma para cada mão. O primeiro passo de quem aprende o ofício das Adagas Cruzadas.",
				DescriptionEn = "A pair of knapped flint knives, one for each hand. The first step of anyone learning the craft of the Crossed Daggers.",
				CraftingStation = "piece_workbench",
				MinStationLevel = 1,
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("Wood", 4),
					new RequirementDef("Flint", 8, 4),
					new RequirementDef("LeatherScraps", 4)
				},
				KeepBaseAnimationState = true
			},
			new DualDaggerDefinition
			{
				BasePrefabName = "KnifeCopper",
				DualPrefabName = "AdagasCruzadas_KnifeCopper_Dual",
				NamePt = "Adagas Cruzadas de Cobre",
				NameEn = "Copper Crossed Daggers",
				DescriptionPt = "Duas lâminas de cobre gêmeas. Leves, rápidas e feitas para golpear em par.",
				DescriptionEn = "Twin copper blades. Light, quick, and made to strike as a pair.",
				CraftingStation = "forge",
				MinStationLevel = 1,
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("Wood", 4),
					new RequirementDef("Copper", 16, 8),
					new RequirementDef("GreydwarfEye", 0, 16)
				},
				KeepBaseAnimationState = true
			},
			new DualDaggerDefinition
			{
				BasePrefabName = "KnifeChitin",
				DualPrefabName = "AdagasCruzadas_KnifeChitin_Dual",
				NamePt = "Adagas Cruzadas Abissais",
				NameEn = "Abyssal Crossed Daggers",
				DescriptionPt = "Duas navalhas arrancadas das profundezas. Cortam como se ainda lembrassem do mar.",
				DescriptionEn = "Two razors torn from the depths. They cut as if they still remembered the sea.",
				CraftingStation = "piece_workbench",
				MinStationLevel = 2,
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("FineWood", 8),
					new RequirementDef("Chitin", 40, 20),
					new RequirementDef("LeatherScraps", 4)
				}
			},
			new DualDaggerDefinition
			{
				BasePrefabName = "KnifeSilver",
				DualPrefabName = "AdagasCruzadas_KnifeSilver_Dual",
				NamePt = "Adagas Cruzadas de Prata",
				NameEn = "Silver Crossed Daggers",
				DescriptionPt = "Um par de adagas de prata. O que uma não termina, a outra termina — e o que é da noite, ambas afastam.",
				DescriptionEn = "A pair of silver daggers. What one does not finish, the other does — and what belongs to the night, both drive away.",
				CraftingStation = "forge",
				MinStationLevel = 3,
				Requirements = new RequirementDef[4]
				{
					new RequirementDef("Wood", 4, 2),
					new RequirementDef("Silver", 20, 10),
					new RequirementDef("LeatherScraps", 6, 2),
					new RequirementDef("Iron", 4, 2)
				}
			},
			new DualDaggerDefinition
			{
				BasePrefabName = "KnifeBlackMetal",
				DualPrefabName = "AdagasCruzadas_KnifeBlackMetal_Dual",
				NamePt = "Adagas Cruzadas de Metal Negro",
				NameEn = "Black Metal Crossed Daggers",
				DescriptionPt = "Duas lâminas de metal negro, afiadas até o silêncio. A marca de um assassino das Adagas Cruzadas.",
				DescriptionEn = "Two black metal blades, sharpened into silence. The mark of a Crossed Daggers assassin.",
				CraftingStation = "forge",
				MinStationLevel = 4,
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("FineWood", 8),
					new RequirementDef("BlackMetal", 20, 8),
					new RequirementDef("LinenThread", 10, 10)
				}
			},
			new DualDaggerDefinition
			{
				BasePrefabName = "KnifeGold",
				DualPrefabName = "AdagasCruzadas_KnifeGold_Dual",
				NamePt = "Adagas Cruzadas Nórdicas",
				NameEn = "Nord Crossed Daggers",
				DescriptionPt = "Um par de adagas nórdicas fundidas em ouro das Terras de Cinza. Pesam pouco na mão e muito na consciência de quem as enfrenta.",
				DescriptionEn = "A pair of Nord daggers cast from Ashlands gold. Light in the hand, heavy on the conscience of those who face them.",
				CraftingStation = "blackforge",
				MinStationLevel = 4,
				Requirements = new RequirementDef[4]
				{
					new RequirementDef("Gold", 40, 20),
					new RequirementDef("MoldKnife", 1),
					new RequirementDef("Frostwood", 20, 10),
					new RequirementDef("Upgrader7Weapon", 1)
				}
			},
			new DualDaggerDefinition
			{
				BasePrefabName = "KnifeGold_BloodLightning",
				DualPrefabName = "AdagasCruzadas_KnifeGold_BloodLightning_Dual",
				NamePt = "Adagas Cruzadas de Trovossangue",
				NameEn = "Thunderblood Crossed Daggers",
				DescriptionPt = "Duas adagas nórdicas banhadas em trovossangue. Cada corte deixa o ar cheirando a tempestade.",
				DescriptionEn = "Two Nord daggers steeped in thunderblood. Every cut leaves the air smelling of storm.",
				CraftingStation = "blackforge",
				MinStationLevel = 4,
				Requirements = new RequirementDef[4]
				{
					new RequirementDef("KnifeGold", 2),
					new RequirementDef("Gold", 40, 20),
					new RequirementDef("OrbThunderBlood", 2, 2),
					new RequirementDef("Upgrader7Weapon", 1)
				}
			},
			new DualDaggerDefinition
			{
				BasePrefabName = "KnifeGold_FrostFire",
				DualPrefabName = "AdagasCruzadas_KnifeGold_FrostFire_Dual",
				NamePt = "Adagas Cruzadas de Fogogelo",
				NameEn = "Frostfire Crossed Daggers",
				DescriptionPt = "Duas adagas nórdicas temperadas em fogogelo. Uma lâmina queima, a outra congela; nenhuma perdoa.",
				DescriptionEn = "Two Nord daggers tempered in frostfire. One blade burns, the other freezes; neither forgives.",
				CraftingStation = "blackforge",
				MinStationLevel = 4,
				Requirements = new RequirementDef[4]
				{
					new RequirementDef("KnifeGold", 2),
					new RequirementDef("Gold", 40, 20),
					new RequirementDef("OrbFrostFire", 2, 2),
					new RequirementDef("Upgrader7Weapon", 1)
				}
			}
		};

		public string NameKey => "adagascruzadas_" + BasePrefabName.ToLowerInvariant() + "_dual";

		public string DescriptionKey => NameKey + "_desc";

		public string NameToken => "$" + NameKey;

		public string DescriptionToken => "$" + DescriptionKey;
	}
	internal static class DualDaggerFactory
	{
		private const float WeightMultiplier = 2f;

		private const float StaminaMultiplier = 1.5f;

		private const float TimedBlockBonus = 6f;

		internal const string OffhandGroupName = "offhand";

		private static GameObject _container;

		private static readonly Dictionary<string, GameObject> Clones = new Dictionary<string, GameObject>();

		private static readonly Dictionary<string, Recipe> Recipes = new Dictionary<string, Recipe>();

		private static readonly MethodInfo UpdateRegisters = AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null);

		private static readonly FieldInfo NamedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

		private static readonly Vector3 OffhandLocalOffset = new Vector3(0.06f, -0.02f, 0f);

		private static readonly Vector3 OffhandLocalEuler = new Vector3(0f, 25f, 0f);

		private static readonly MethodInfo MemberwiseCloneMethod = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

		public static void EnsureRegistered(ObjectDB db)
		{
			if ((Object)(object)db == (Object)null || (Object)(object)db.GetItemPrefab("KnifeSkollAndHati") == (Object)null)
			{
				return;
			}
			EnsureClones(db);
			bool flag = false;
			foreach (GameObject value2 in Clones.Values)
			{
				if (!db.m_items.Contains(value2))
				{
					db.m_items.Add(value2);
					flag = true;
				}
			}
			DualDaggerDefinition[] all = DualDaggerDefinition.All;
			foreach (DualDaggerDefinition dualDaggerDefinition in all)
			{
				if (!Recipes.TryGetValue(dualDaggerDefinition.DualPrefabName, out var value))
				{
					value = BuildRecipe(dualDaggerDefinition, db);
					if ((Object)(object)value == (Object)null)
					{
						continue;
					}
					Recipes[dualDaggerDefinition.DualPrefabName] = value;
				}
				if (!db.m_recipes.Contains(value))
				{
					db.m_recipes.Add(value);
					flag = true;
				}
			}
			if (flag)
			{
				UpdateRegisters.Invoke(db, null);
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				EnsureRegisteredInScene(ZNetScene.instance);
			}
		}

		public static void EnsureRegisteredInScene(ZNetScene scene)
		{
			if ((Object)(object)scene == (Object)null || Clones.Count == 0)
			{
				return;
			}
			Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)NamedPrefabs.GetValue(scene);
			foreach (GameObject value in Clones.Values)
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)value).name);
				if (!dictionary.ContainsKey(stableHashCode))
				{
					dictionary[stableHashCode] = value;
					if (!scene.m_prefabs.Contains(value))
					{
						scene.m_prefabs.Add(value);
					}
				}
			}
		}

		private static void EnsureClones(ObjectDB db)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (Clones.Count == DualDaggerDefinition.All.Length)
			{
				return;
			}
			if ((Object)(object)_container == (Object)null)
			{
				_container = new GameObject("AdagasCruzadas_Prefabs");
				_container.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_container);
			}
			SharedData shared = db.GetItemPrefab("KnifeSkollAndHati").GetComponent<ItemDrop>().m_itemData.m_shared;
			DualDaggerDefinition[] all = DualDaggerDefinition.All;
			foreach (DualDaggerDefinition dualDaggerDefinition in all)
			{
				if (!Clones.ContainsKey(dualDaggerDefinition.DualPrefabName))
				{
					GameObject itemPrefab = db.GetItemPrefab(dualDaggerDefinition.BasePrefabName);
					if ((Object)(object)itemPrefab == (Object)null)
					{
						AdagasCruzadasPlugin.Log.LogError((object)("Prefab base '" + dualDaggerDefinition.BasePrefabName + "' não encontrado, pulando '" + dualDaggerDefinition.DualPrefabName + "'."));
					}
					else
					{
						GameObject val = Object.Instantiate<GameObject>(itemPrefab, _container.transform);
						((Object)val).name = dualDaggerDefinition.DualPrefabName;
						Configure(val, dualDaggerDefinition, shared);
						Clones[dualDaggerDefinition.DualPrefabName] = val;
						AdagasCruzadasPlugin.Log.LogInfo((object)("Item criado: " + dualDaggerDefinition.DualPrefabName));
					}
				}
			}
		}

		private static void Configure(GameObject clone, DualDaggerDefinition def, SharedData skollShared)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			ItemDrop component = clone.GetComponent<ItemDrop>();
			SharedData shared = component.m_itemData.m_shared;
			component.m_itemData.m_dropPrefab = clone;
			float attackStamina = shared.m_attack.m_attackStamina;
			Attack val = CloneAttack(skollShared.m_attack);
			val.m_attackStamina = attackStamina * 1.5f;
			shared.m_attack = val;
			shared.m_name = def.NameToken;
			shared.m_description = def.DescriptionToken;
			shared.m_weight *= 2f;
			shared.m_timedBlockBonus = 6f;
			shared.m_itemType = skollShared.m_itemType;
			if (!def.KeepBaseAnimationState)
			{
				shared.m_animationState = skollShared.m_animationState;
			}
			BuildOffhandGroup(clone, def.DualPrefabName);
		}

		private static Recipe BuildRecipe(DualDaggerDefinition def, ObjectDB db)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			if (!Clones.TryGetValue(def.DualPrefabName, out var value))
			{
				return null;
			}
			CraftingStation val = CraftingStationLookup.Find(def.CraftingStation);
			if ((Object)(object)val == (Object)null)
			{
				AdagasCruzadasPlugin.Log.LogWarning((object)("Estação '" + def.CraftingStation + "' não encontrada ainda para '" + def.DualPrefabName + "'; tentando de novo no próximo registro."));
				return null;
			}
			List<Requirement> list = new List<Requirement>();
			RequirementDef[] requirements = def.Requirements;
			foreach (RequirementDef requirementDef in requirements)
			{
				GameObject itemPrefab = db.GetItemPrefab(requirementDef.Item);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					AdagasCruzadasPlugin.Log.LogError((object)("Recurso '" + requirementDef.Item + "' da receita de '" + def.DualPrefabName + "' não encontrado."));
					return null;
				}
				list.Add(new Requirement
				{
					m_resItem = itemPrefab.GetComponent<ItemDrop>(),
					m_amount = requirementDef.Amount,
					m_amountPerLevel = requirementDef.AmountPerLevel,
					m_recover = true
				});
			}
			Recipe obj = ScriptableObject.CreateInstance<Recipe>();
			((Object)obj).name = "Recipe_" + def.DualPrefabName;
			obj.m_item = value.GetComponent<ItemDrop>();
			obj.m_amount = 1;
			obj.m_enabled = true;
			obj.m_craftingStation = val;
			obj.m_repairStation = val;
			obj.m_minStationLevel = def.MinStationLevel;
			obj.m_resources = list.ToArray();
			return obj;
		}

		private static void BuildOffhandGroup(GameObject clone, string dualPrefabName)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			Transform val = clone.transform.Find("attach");
			if ((Object)(object)val == (Object)null)
			{
				AdagasCruzadasPlugin.Log.LogWarning((object)("'" + dualPrefabName + "': sem filho 'attach', não foi possível criar a segunda lâmina."));
				return;
			}
			List<Transform> list = new List<Transform>();
			foreach (Transform item in val)
			{
				Transform val2 = item;
				if (!(((Object)val2).name == "equiped") && !(((Object)val2).name == "collider") && !(((Object)val2).name == "offhand"))
				{
					list.Add(val2);
				}
			}
			if (!list.Any((Transform t) => (Object)(object)((Component)t).GetComponent<MeshRenderer>() != (Object)null))
			{
				AdagasCruzadasPlugin.Log.LogWarning((object)("'" + dualPrefabName + "': não encontrei a malha da lâmina em 'attach'."));
				return;
			}
			GameObject val3 = new GameObject("offhand");
			val3.transform.SetParent(val, false);
			val3.transform.localPosition = OffhandLocalOffset;
			val3.transform.localRotation = Quaternion.Euler(OffhandLocalEuler);
			val3.transform.localScale = Vector3.one;
			foreach (Transform item2 in list)
			{
				GameObject obj = Object.Instantiate<GameObject>(((Component)item2).gameObject, val3.transform, false);
				((Object)obj).name = ((Object)item2).name;
				obj.transform.localPosition = item2.localPosition;
				obj.transform.localRotation = item2.localRotation;
				obj.transform.localScale = item2.localScale;
			}
		}

		private static Attack CloneAttack(Attack source)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			return (Attack)MemberwiseCloneMethod.Invoke(source, null);
		}
	}
	internal enum InfusionId
	{
		Fire,
		Frost,
		Lightning,
		Spirit,
		Poison,
		Vampirism,
		Slow,
		Bleed
	}
	internal enum InfusionFamily
	{
		DirectDamage,
		Status,
		Vampirism
	}
	internal enum ElementalDamageType
	{
		Fire,
		Frost,
		Lightning,
		Spirit,
		Poison
	}
	internal class InfusionDefinition
	{
		public const float DurationSeconds = 300f;

		public InfusionId Id;

		public string SourcePrefabName;

		public string NamePt;

		public string NameEn;

		public string DescriptionPt;

		public string DescriptionEn;

		public RequirementDef[] Requirements;

		public InfusionFamily Family;

		public ElementalDamageType DamageType;

		public float BaseDamage = 10f;

		public string TargetStatusEffectName;

		public float Chance = 0.5f;

		public float HealPercent = 0.15f;

		public float SlowPercent = 0.3f;

		public const string CraftingStation = "piece_workbench";

		public const int MinStationLevel = 2;

		public static readonly InfusionDefinition[] All = new InfusionDefinition[8]
		{
			new InfusionDefinition
			{
				Id = InfusionId.Fire,
				SourcePrefabName = "BarleyWine",
				NamePt = "Resina Incendiária",
				NameEn = "Blazing Resin",
				DescriptionPt = "Um óleo espesso que guarda fogo represado em cada gota. Os seguidores do mago Nocthar o destilavam em fogueiras que nunca se apagavam — oferenda e arma a um só tempo.",
				DescriptionEn = "A thick oil that holds fire trapped in every drop. Followers of the mage Nocthar distilled it over bonfires that never died out — offering and weapon at once.",
				Requirements = new RequirementDef[2]
				{
					new RequirementDef("Resin", 3),
					new RequirementDef("SurtlingCore", 1)
				},
				Family = InfusionFamily.DirectDamage,
				DamageType = ElementalDamageType.Fire
			},
			new InfusionDefinition
			{
				Id = InfusionId.Frost,
				SourcePrefabName = "MeadFrostResist",
				NamePt = "Resina Congelante",
				NameEn = "Freezing Resin",
				DescriptionPt = "Um óleo que nunca aquece, nem sob o sol mais cruel. Os povos da montanha o passavam nas lâminas para que suas presas parassem de fugir — e, por fim, de sentir.",
				DescriptionEn = "An oil that never warms, not even under the cruelest sun. Mountain folk coated their blades with it so their prey would stop fleeing — and, at last, stop feeling.",
				Requirements = new RequirementDef[2]
				{
					new RequirementDef("Resin", 3),
					new RequirementDef("FreezeGland", 2)
				},
				Family = InfusionFamily.DirectDamage,
				DamageType = ElementalDamageType.Frost
			},
			new InfusionDefinition
			{
				Id = InfusionId.Lightning,
				SourcePrefabName = "MeadLightfoot",
				NamePt = "Resina Fulminante",
				NameEn = "Fulminating Resin",
				DescriptionPt = "Presa no vidro, uma tempestade que nunca se cansa de estourar. Tarkir, o Corta-Relâmpagos, jurou a Tyr que nenhum inimigo ficaria de pé diante dela.",
				DescriptionEn = "Trapped in glass, a storm that never tires of breaking. Tarkir, the Lightning-Cutter, swore to Tyr that no enemy would remain standing before it.",
				Requirements = new RequirementDef[2]
				{
					new RequirementDef("Resin", 3),
					new RequirementDef("Thunderstone", 1)
				},
				Family = InfusionFamily.DirectDamage,
				DamageType = ElementalDamageType.Lightning
			},
			new InfusionDefinition
			{
				Id = InfusionId.Spirit,
				SourcePrefabName = "MeadEitrLingering",
				NamePt = "Resina do Banimento",
				NameEn = "Banishment Resin",
				DescriptionPt = "Forjada para subjugar o que não deveria caminhar entre os vivos. Fórmula tão antiga quanto os primeiros homens, usada para banir o mal que espreita nas noites sem fim.",
				DescriptionEn = "Forged to subdue what should not walk among the living. A formula as old as the first men, used to banish the evil that lurks in the endless nights.",
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("Resin", 3),
					new RequirementDef("BoneFragments", 5),
					new RequirementDef("Ectoplasm", 2)
				},
				Family = InfusionFamily.DirectDamage,
				DamageType = ElementalDamageType.Spirit
			},
			new InfusionDefinition
			{
				Id = InfusionId.Poison,
				SourcePrefabName = "MeadPoisonResist",
				NamePt = "Resina Pestilenta",
				NameEn = "Pestilent Resin",
				DescriptionPt = "Um extrato nauseante, colhido onde nada cresce limpo. O povo de Brak o untava nas lâminas para que a morte chegasse muito antes do grito.",
				DescriptionEn = "A nauseating extract, gathered where nothing grows clean. The people of Brak smeared it on their blades so death would arrive long before the scream.",
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("Resin", 3),
					new RequirementDef("Guck", 2),
					new RequirementDef("Ooze", 2)
				},
				Family = InfusionFamily.DirectDamage,
				DamageType = ElementalDamageType.Poison
			},
			new InfusionDefinition
			{
				Id = InfusionId.Vampirism,
				SourcePrefabName = "MeadBzerker",
				NamePt = "Resina do Pacto Sanguíneo",
				NameEn = "Blood Pact Resin",
				DescriptionPt = "Selada com sangue ainda quente, firma um laço breve e cruel entre lâmina e vítima. Ravok, vampiro da linhagem de Azatoth, jamais soube compartilhar — só tomar.",
				DescriptionEn = "Sealed with still-warm blood, it forges a brief and cruel bond between blade and victim. Ravok, vampire of Azatoth's bloodline, never learned to share — only to take.",
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("Resin", 3),
					new RequirementDef("Bloodbag", 1),
					new RequirementDef("Ectoplasm", 2)
				},
				Family = InfusionFamily.Vampirism
			},
			new InfusionDefinition
			{
				Id = InfusionId.Slow,
				SourcePrefabName = "MeadTrollPheromones",
				NamePt = "Resina do Arruinado",
				NameEn = "Ruined One's Resin",
				DescriptionPt = "Um extrato espesso que entorpece os músculos do alvo. Técnica do Arruinado, caçador que perdeu tudo perseguindo as harpias da névoa — menos a paciência de esperar a presa cair.",
				DescriptionEn = "A thick extract that numbs the target's muscles. A technique of the Ruined One, a hunter who lost everything chasing the mist harpies — except the patience to wait for prey to fall.",
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("Resin", 3),
					new RequirementDef("Tar", 2),
					new RequirementDef("Root", 2)
				},
				Family = InfusionFamily.Status,
				TargetStatusEffectName = "AC_SE_Slowed"
			},
			new InfusionDefinition
			{
				Id = InfusionId.Bleed,
				SourcePrefabName = "MeadHealthMedium",
				NamePt = "Resina Corta Sangue",
				NameEn = "Bloodcut Resin",
				DescriptionPt = "Um óleo avermelhado que impede feridas de fechar. Diz a lenda que suas primeiras gotas caíram sobre um dente-de-leão, num campo ainda quente de sangue — e, desde então, nunca mais estancaram.",
				DescriptionEn = "A reddish oil that keeps wounds from closing. Legend says its first drops fell on a dandelion, in a field still warm with blood — and, ever since, they never stopped flowing.",
				Requirements = new RequirementDef[3]
				{
					new RequirementDef("Resin", 3),
					new RequirementDef("Bloodbag", 1),
					new RequirementDef("Dandelion", 3)
				},
				Family = InfusionFamily.Status,
				TargetStatusEffectName = "AC_SE_Bleed"
			}
		};

		public string NameKey => "adagascruzadas_infusion_" + Id.ToString().ToLowerInvariant();

		public string DescriptionKey => NameKey + "_desc";

		public string NameToken => "$" + NameKey;

		public string DescriptionToken => "$" + DescriptionKey;

		public string ClonePrefabName => "AdagasCruzadas_Infusion" + Id;
	}
	internal static class InfusionFactory
	{
		private static GameObject _container;

		private static readonly Dictionary<string, GameObject> Clones = new Dictionary<string, GameObject>();

		private static readonly Dictionary<string, Recipe> Recipes = new Dictionary<string, Recipe>();

		private static readonly MethodInfo UpdateRegisters = AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null);

		private static readonly FieldInfo NamedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

		public static void EnsureRegistered(ObjectDB db)
		{
			if ((Object)(object)db == (Object)null || (Object)(object)db.GetItemPrefab("Resin") == (Object)null)
			{
				return;
			}
			EnsureClones(db);
			bool flag = false;
			foreach (GameObject value2 in Clones.Values)
			{
				if (!db.m_items.Contains(value2))
				{
					db.m_items.Add(value2);
					flag = true;
				}
			}
			InfusionDefinition[] all = InfusionDefinition.All;
			foreach (InfusionDefinition infusionDefinition in all)
			{
				if (!Recipes.TryGetValue(infusionDefinition.ClonePrefabName, out var value))
				{
					value = BuildRecipe(infusionDefinition, db);
					if ((Object)(object)value == (Object)null)
					{
						continue;
					}
					Recipes[infusionDefinition.ClonePrefabName] = value;
				}
				if (!db.m_recipes.Contains(value))
				{
					db.m_recipes.Add(value);
					flag = true;
				}
			}
			if (flag)
			{
				UpdateRegisters.Invoke(db, null);
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				EnsureRegisteredInScene(ZNetScene.instance);
			}
		}

		public static GameObject GetClone(string clonePrefabName)
		{
			if (!Clones.TryGetValue(clonePrefabName, out var value))
			{
				return null;
			}
			return value;
		}

		public static void EnsureRegisteredInScene(ZNetScene scene)
		{
			if ((Object)(object)scene == (Object)null || Clones.Count == 0)
			{
				return;
			}
			Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)NamedPrefabs.GetValue(scene);
			foreach (GameObject value in Clones.Values)
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)value).name);
				if (!dictionary.ContainsKey(stableHashCode))
				{
					dictionary[stableHashCode] = value;
					if (!scene.m_prefabs.Contains(value))
					{
						scene.m_prefabs.Add(value);
					}
				}
			}
		}

		private static void EnsureClones(ObjectDB db)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (Clones.Count == InfusionDefinition.All.Length)
			{
				return;
			}
			if ((Object)(object)_container == (Object)null)
			{
				_container = new GameObject("AdagasCruzadas_InfusionPrefabs");
				_container.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_container);
			}
			InfusionDefinition[] all = InfusionDefinition.All;
			foreach (InfusionDefinition infusionDefinition in all)
			{
				if (!Clones.ContainsKey(infusionDefinition.ClonePrefabName))
				{
					GameObject itemPrefab = db.GetItemPrefab(infusionDefinition.SourcePrefabName);
					if ((Object)(object)itemPrefab == (Object)null)
					{
						AdagasCruzadasPlugin.Log.LogError((object)("Prefab base '" + infusionDefinition.SourcePrefabName + "' não encontrado, pulando '" + infusionDefinition.ClonePrefabName + "'."));
					}
					else
					{
						GameObject val = Object.Instantiate<GameObject>(itemPrefab, _container.transform);
						((Object)val).name = infusionDefinition.ClonePrefabName;
						Configure(val, infusionDefinition, db);
						Clones[infusionDefinition.ClonePrefabName] = val;
						AdagasCruzadasPlugin.Log.LogInfo((object)("Item criado: " + infusionDefinition.ClonePrefabName));
					}
				}
			}
		}

		private static void Configure(GameObject clone, InfusionDefinition def, ObjectDB db)
		{
			ItemDrop component = clone.GetComponent<ItemDrop>();
			SharedData shared = component.m_itemData.m_shared;
			component.m_itemData.m_dropPrefab = clone;
			shared.m_name = def.NameToken;
			shared.m_description = def.DescriptionToken;
			Sprite val = InfusionIconFactory.Get(db, def.Id);
			if ((Object)(object)val != (Object)null)
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { val };
			}
			else
			{
				AdagasCruzadasPlugin.Log.LogWarning((object)("Ícone colorido de '" + def.ClonePrefabName + "' não pôde ser gerado; mantendo o do frasco."));
			}
			shared.m_food = 0f;
			shared.m_foodStamina = 0f;
			shared.m_foodEitr = 0f;
			shared.m_foodBurnTime = 0f;
			shared.m_foodRegen = 0f;
			shared.m_consumeStatusEffect = null;
		}

		private static Recipe BuildRecipe(InfusionDefinition def, ObjectDB db)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			if (!Clones.TryGetValue(def.ClonePrefabName, out var value))
			{
				return null;
			}
			CraftingStation val = CraftingStationLookup.Find("piece_workbench");
			if ((Object)(object)val == (Object)null)
			{
				AdagasCruzadasPlugin.Log.LogWarning((object)("Estação 'piece_workbench' não encontrada ainda para '" + def.ClonePrefabName + "'; tentando de novo no próximo registro."));
				return null;
			}
			List<Requirement> list = new List<Requirement>();
			RequirementDef[] requirements = def.Requirements;
			foreach (RequirementDef requirementDef in requirements)
			{
				GameObject itemPrefab = db.GetItemPrefab(requirementDef.Item);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					AdagasCruzadasPlugin.Log.LogError((object)("Recurso '" + requirementDef.Item + "' da receita de '" + def.ClonePrefabName + "' não encontrado."));
					return null;
				}
				list.Add(new Requirement
				{
					m_resItem = itemPrefab.GetComponent<ItemDrop>(),
					m_amount = requirementDef.Amount,
					m_amountPerLevel = requirementDef.AmountPerLevel,
					m_recover = true
				});
			}
			Recipe obj = ScriptableObject.CreateInstance<Recipe>();
			((Object)obj).name = "Recipe_" + def.ClonePrefabName;
			obj.m_item = value.GetComponent<ItemDrop>();
			obj.m_amount = 1;
			obj.m_enabled = true;
			obj.m_craftingStation = val;
			obj.m_repairStation = val;
			obj.m_minStationLevel = 2;
			obj.m_resources = list.ToArray();
			return obj;
		}
	}
	internal static class InfusionHudEffectFactory
	{
		private static readonly Dictionary<InfusionId, StatusEffect> HudEffects = new Dictionary<InfusionId, StatusEffect>();

		public static void EnsureRegistered(ObjectDB db)
		{
			if ((Object)(object)db == (Object)null)
			{
				return;
			}
			InfusionDefinition[] all = InfusionDefinition.All;
			foreach (InfusionDefinition infusionDefinition in all)
			{
				if (!HudEffects.ContainsKey(infusionDefinition.Id))
				{
					GameObject clone = InfusionFactory.GetClone(infusionDefinition.ClonePrefabName);
					if (!((Object)(object)clone == (Object)null))
					{
						StatusEffect val = ScriptableObject.CreateInstance<StatusEffect>();
						((Object)val).name = "AC_SE_Hud_" + infusionDefinition.Id;
						val.m_name = infusionDefinition.NameToken;
						val.m_icon = clone.GetComponent<ItemDrop>().m_itemData.GetIcon();
						val.m_ttl = 300f;
						HudEffects[infusionDefinition.Id] = val;
					}
				}
			}
			foreach (StatusEffect value in HudEffects.Values)
			{
				if (!db.m_StatusEffects.Contains(value))
				{
					db.m_StatusEffects.Add(value);
				}
			}
		}

		public static StatusEffect Get(InfusionId id)
		{
			if (!HudEffects.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		public static void Sync(SEMan seMan, InfusionId? active, float remainingSeconds)
		{
			if (seMan == null)
			{
				return;
			}
			foreach (KeyValuePair<InfusionId, StatusEffect> hudEffect in HudEffects)
			{
				StatusEffect value = hudEffect.Value;
				bool flag = active.HasValue && hudEffect.Key == active.Value && remainingSeconds > 0f;
				bool flag2 = seMan.HaveStatusEffect(value.NameHash());
				if (flag && !flag2)
				{
					value.m_ttl = remainingSeconds;
					seMan.AddStatusEffect(value, true, 0, 0f, (short)(-1));
				}
				else if (!flag && flag2)
				{
					seMan.RemoveStatusEffect(value, true);
				}
			}
		}
	}
	internal static class InfusionIconFactory
	{
		private const string SourceItem = "Resin";

		private const float LuminanceGain = 1.15f;

		private static readonly Dictionary<InfusionId, Sprite> Cache = new Dictionary<InfusionId, Sprite>();

		public static Sprite Get(ObjectDB db, InfusionId id)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (Cache.TryGetValue(id, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Sprite sourceIcon = GetSourceIcon(db);
			if ((Object)(object)sourceIcon == (Object)null)
			{
				return null;
			}
			Texture2D val = ReadableCopy(sourceIcon);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Texture2D val2 = Tint(val, ColorFor(id));
			Object.Destroy((Object)(object)val);
			Sprite val3 = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), sourceIcon.pixelsPerUnit);
			((Object)val3).name = "AC_Icon_" + id;
			((Object)val3).hideFlags = (HideFlags)61;
			Cache[id] = val3;
			return val3;
		}

		private static Sprite GetSourceIcon(ObjectDB db)
		{
			GameObject val = (((Object)(object)db != (Object)null) ? db.GetItemPrefab("Resin") : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if (!((Object)(object)val2 != (Object)null))
			{
				return null;
			}
			return val2.m_itemData.GetIcon();
		}

		private static Texture2D ReadableCopy(Sprite sprite)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			Texture2D texture = sprite.texture;
			if ((Object)(object)texture == (Object)null)
			{
				return null;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			RenderTexture active = RenderTexture.active;
			Graphics.Blit((Texture)(object)texture, temporary);
			RenderTexture.active = temporary;
			Rect val = (sprite.packed ? sprite.textureRect : sprite.rect);
			Texture2D val2 = new Texture2D((int)((Rect)(ref val)).width, (int)((Rect)(ref val)).height, (TextureFormat)4, false);
			val2.ReadPixels(val, 0, 0);
			val2.Apply();
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			return val2;
		}

		private static Texture2D Tint(Texture2D src, Color color)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			Color[] pixels = src.GetPixels();
			for (int i = 0; i < pixels.Length; i++)
			{
				Color val = pixels[i];
				float num = Mathf.Clamp01((val.r * 0.299f + val.g * 0.587f + val.b * 0.114f) * 1.15f);
				pixels[i] = new Color(num * color.r, num * color.g, num * color.b, val.a);
			}
			Texture2D val2 = new Texture2D(((Texture)src).width, ((Texture)src).height, (TextureFormat)4, false);
			val2.SetPixels(pixels);
			val2.Apply();
			((Object)val2).hideFlags = (HideFlags)61;
			return val2;
		}

		private static Color ColorFor(InfusionId id)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(id switch
			{
				InfusionId.Fire => new Color(1f, 0.45f, 0.05f), 
				InfusionId.Frost => new Color(0.45f, 0.85f, 1f), 
				InfusionId.Lightning => new Color(0.35f, 0.45f, 1f), 
				InfusionId.Spirit => new Color(0.75f, 0.45f, 1f), 
				InfusionId.Poison => new Color(0.35f, 1f, 0.25f), 
				InfusionId.Vampirism => new Color(0.55f, 0f, 0.15f), 
				InfusionId.Slow => new Color(0.45f, 0.3f, 0.15f), 
				InfusionId.Bleed => new Color(1f, 0.15f, 0.1f), 
				_ => Color.white, 
			});
		}
	}
	[HarmonyPatch(typeof(ObjectDB))]
	internal static class ObjectDbRegistrationPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void AwakePostfix(ObjectDB __instance)
		{
			DualDaggerFactory.EnsureRegistered(__instance);
			InfusionFactory.EnsureRegistered(__instance);
			InfusionHudEffectFactory.EnsureRegistered(__instance);
			InfusionStatusEffectFactory.EnsureRegistered(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("CopyOtherDB")]
		private static void CopyOtherDbPostfix(ObjectDB __instance)
		{
			DualDaggerFactory.EnsureRegistered(__instance);
			InfusionFactory.EnsureRegistered(__instance);
			InfusionHudEffectFactory.EnsureRegistered(__instance);
			InfusionStatusEffectFactory.EnsureRegistered(__instance);
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetSceneRegistrationPatch
	{
		private static void Postfix(ZNetScene __instance)
		{
			DualDaggerFactory.EnsureRegisteredInScene(__instance);
			InfusionFactory.EnsureRegisteredInScene(__instance);
		}
	}
}
namespace AdagasCruzadas.Combat
{
	[HarmonyPatch(typeof(Attack), "ModifyDamage")]
	internal static class DualDaggerComboDamagePatch
	{
		private static readonly float[] ChainMultipliers = new float[3] { 1.3f, 2f, 1.5f };

		private static void Postfix(HitData hitData, int ___m_currentAttackCainLevel, ItemData ___m_weapon)
		{
			if (DualDaggerRegistry.IsDualDagger(___m_weapon))
			{
				int num = Mathf.Clamp(___m_currentAttackCainLevel, 0, ChainMultipliers.Length - 1);
				((DamageTypes)(ref hitData.m_damage)).Modify(ChainMultipliers[num]);
			}
		}
	}
	[HarmonyPatch(typeof(VisEquipment), "SetRightHandEquipped")]
	internal static class DualDaggerOffhandVisualPatch
	{
		private class OffhandHolder : MonoBehaviour
		{
			public GameObject Offhand;

			private void OnDestroy()
			{
				if ((Object)(object)Offhand != (Object)null)
				{
					Object.Destroy((Object)(object)Offhand);
				}
			}
		}

		private static readonly Vector3 LeftHandEulerOffset = Vector3.zero;

		private static readonly Vector3 LeftHandPositionOffset = Vector3.zero;

		private static void Postfix(VisEquipment __instance, bool __result, int hash, GameObject ___m_rightItemInstance)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (!__result)
			{
				return;
			}
			OffhandHolder offhandHolder = ((Component)__instance).GetComponent<OffhandHolder>();
			if ((Object)(object)offhandHolder != (Object)null && (Object)(object)offhandHolder.Offhand != (Object)null)
			{
				Object.Destroy((Object)(object)offhandHolder.Offhand);
				offhandHolder.Offhand = null;
			}
			if ((Object)(object)___m_rightItemInstance == (Object)null || (Object)(object)__instance.m_leftHand == (Object)null || !DualDaggerRegistry.IsDualDaggerHash(hash))
			{
				return;
			}
			Transform val = ___m_rightItemInstance.transform.Find("offhand");
			if (!((Object)(object)val == (Object)null))
			{
				val.SetParent(__instance.m_leftHand, false);
				val.localPosition = LeftHandPositionOffset;
				val.localRotation = Quaternion.Euler(LeftHandEulerOffset);
				val.localScale = Vector3.one;
				if ((Object)(object)offhandHolder == (Object)null)
				{
					offhandHolder = ((Component)__instance).gameObject.AddComponent<OffhandHolder>();
				}
				offhandHolder.Offhand = ((Component)val).gameObject;
			}
		}
	}
	internal static class DualDaggerRegistry
	{
		private static readonly HashSet<string> DualPrefabNames = new HashSet<string>(DualDaggerDefinition.All.Select((DualDaggerDefinition d) => d.DualPrefabName));

		private static readonly HashSet<int> DualPrefabHashes = new HashSet<int>(DualDaggerDefinition.All.Select((DualDaggerDefinition d) => StringExtensionMethods.GetStableHashCode(d.DualPrefabName)));

		public static bool IsDualDagger(ItemData weapon)
		{
			string text = (((Object)(object)weapon?.m_dropPrefab != (Object)null) ? ((Object)weapon.m_dropPrefab).name : null);
			if (text != null)
			{
				return DualPrefabNames.Contains(text);
			}
			return false;
		}

		public static bool IsDualDaggerHash(int prefabHash)
		{
			return DualPrefabHashes.Contains(prefabHash);
		}
	}
	internal static class InfusableWeapons
	{
		private static readonly HashSet<SkillType> AllowedSkills = new HashSet<SkillType>
		{
			(SkillType)2,
			(SkillType)1,
			(SkillType)5,
			(SkillType)7,
			(SkillType)8,
			(SkillType)14
		};

		private static readonly HashSet<AnimationState> TwoHandedPoses = new HashSet<AnimationState>
		{
			(AnimationState)13,
			(AnimationState)8,
			(AnimationState)2,
			(AnimationState)7
		};

		private static readonly FieldInfo HiddenRightItemField = AccessTools.Field(typeof(Humanoid), "m_hiddenRightItem");

		private static readonly FieldInfo HiddenLeftItemField = AccessTools.Field(typeof(Humanoid), "m_hiddenLeftItem");

		public static bool IsInfusable(ItemData weapon)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			SharedData val = weapon?.m_shared;
			if (val == null)
			{
				return false;
			}
			if (AllowedSkills.Contains(val.m_skillType))
			{
				return !TwoHandedPoses.Contains(val.m_animationState);
			}
			return false;
		}

		public static bool IsInfusableHash(int prefabHash)
		{
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefabHash) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return IsInfusable(val2.m_itemData);
			}
			return false;
		}

		public static ItemData GetEquipped(Humanoid humanoid, bool includeSheathed)
		{
			if ((Object)(object)humanoid == (Object)null)
			{
				return null;
			}
			if (IsInfusable(humanoid.RightItem))
			{
				return humanoid.RightItem;
			}
			if (IsInfusable(humanoid.LeftItem))
			{
				return humanoid.LeftItem;
			}
			if (!includeSheathed)
			{
				return null;
			}
			object? obj = HiddenRightItemField?.GetValue(humanoid);
			ItemData val = (ItemData)((obj is ItemData) ? obj : null);
			if (IsInfusable(val))
			{
				return val;
			}
			object? obj2 = HiddenLeftItemField?.GetValue(humanoid);
			ItemData val2 = (ItemData)((obj2 is ItemData) ? obj2 : null);
			if (!IsInfusable(val2))
			{
				return null;
			}
			return val2;
		}
	}
	internal class InfusionAuraPulse : MonoBehaviour
	{
		private const float PeriodSeconds = 1.8f;

		private const float MinDensity = 0.3f;

		private const float MinAlpha = 0.45f;

		private const float MinBrightness = 0.5f;

		private ParticleSystem[] _systems;

		private float[] _baseRate;

		private Color[] _baseColor;

		private void Awake()
		{
			//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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			_systems = ((Component)this).GetComponentsInChildren<ParticleSystem>(true);
			_baseRate = new float[_systems.Length];
			_baseColor = (Color[])(object)new Color[_systems.Length];
			for (int i = 0; i < _systems.Length; i++)
			{
				float[] baseRate = _baseRate;
				int num = i;
				EmissionModule emission = _systems[i].emission;
				baseRate[num] = ((EmissionModule)(ref emission)).rateOverTimeMultiplier;
				Color[] baseColor = _baseColor;
				int num2 = i;
				MainModule main = _systems[i].main;
				MinMaxGradient startColor = ((MainModule)(ref main)).startColor;
				baseColor[num2] = ((MinMaxGradient)(ref startColor)).color;
			}
			AdagasCruzadasPlugin.Log.LogInfo((object)string.Format("[Infusao Visual] pulso ligado em {0} sistema(s), taxas base: {1}.", _systems.Length, string.Join(", ", Array.ConvertAll(_baseRate, (float r) => r.ToString("0.##")))));
		}

		private void Update()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			if (_systems == null)
			{
				return;
			}
			float num = (Mathf.Sin(Time.time * (float)Math.PI * 2f / 1.8f) + 1f) * 0.5f;
			float num2 = Mathf.Lerp(0.3f, 1f, num);
			float num3 = Mathf.Lerp(0.45f, 1f, num);
			float num4 = Mathf.Lerp(0.5f, 1f, num);
			for (int i = 0; i < _systems.Length; i++)
			{
				ParticleSystem val = _systems[i];
				if (!((Object)(object)val == (Object)null))
				{
					EmissionModule emission = val.emission;
					((EmissionModule)(ref emission)).rateOverTimeMultiplier = _baseRate[i] * num2;
					Color val2 = _baseColor[i];
					MainModule main = val.main;
					((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(val2.r * num4, val2.g * num4, val2.b * num4, val2.a * num3));
				}
			}
		}
	}
	internal static class InfusionConflict
	{
		public static string Find(ItemData weapon, InfusionDefinition def)
		{
			if (weapon?.m_shared == null || def == null)
			{
				return null;
			}
			switch (def.Family)
			{
			case InfusionFamily.DirectDamage:
				return FindElemental(weapon, def);
			case InfusionFamily.Status:
				if (!((Object)(object)weapon.m_shared.m_attackStatusEffect != (Object)null))
				{
					return null;
				}
				return weapon.m_shared.m_attackStatusEffect.m_name;
			case InfusionFamily.Vampirism:
			{
				Attack attack = weapon.m_shared.m_attack;
				if (attack == null || !(attack.m_attackHealthReturnHit > 0f))
				{
					return null;
				}
				return "$item_healthhitreturn";
			}
			default:
				return null;
			}
		}

		private static string FindElemental(ItemData weapon, InfusionDefinition def)
		{
			//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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			DamageTypes damage = weapon.GetDamage();
			switch (def.DamageType)
			{
			case ElementalDamageType.Fire:
				if (!(damage.m_fire > 0f))
				{
					return null;
				}
				return "$inventory_fire";
			case ElementalDamageType.Frost:
				if (!(damage.m_frost > 0f))
				{
					return null;
				}
				return "$inventory_frost";
			case ElementalDamageType.Lightning:
				if (!(damage.m_lightning > 0f))
				{
					return null;
				}
				return "$inventory_lightning";
			case ElementalDamageType.Spirit:
				if (!(damage.m_spirit > 0f))
				{
					return null;
				}
				return "$inventory_spirit";
			case ElementalDamageType.Poison:
				if (!(damage.m_poison > 0f))
				{
					return null;
				}
				return "$inventory_poison";
			default:
				return null;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Update")]
	internal static class InfusionHudSyncPatch
	{
		private const float Interval = 0.5f;

		private static float _timer;

		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				_timer -= Time.deltaTime;
				if (!(_timer > 0f))
				{
					_timer = 0.5f;
					ActiveInfusion active = WeaponInfusionState.GetActive(InfusableWeapons.GetEquipped((Humanoid)(object)__instance, includeSheathed: false));
					InfusionHudEffectFactory.Sync(((Character)__instance).GetSEMan(), active?.Definition.Id, (active != null) ? WeaponInfusionState.GetRemainingSeconds(active) : 0f);
				}
			}
		}
	}
	internal static class InfusionParticleFactory
	{
		private const string SourceItem = "BowDraugrFang";

		private const string SourceChildPath = "attach/DraugrFangBow";

		private const float SurfaceOffset = 0.01f;

		private const float MeshSpawnSpeed = 1.5f;

		public static GameObject Create(InfusionId id, Renderer bladeRenderer)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)bladeRenderer == (Object)null)
			{
				return null;
			}
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("BowDraugrFang") : null);
			Transform val2 = (((Object)(object)val != (Object)null) ? val.transform.Find("attach/DraugrFangBow") : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)bladeRenderer).transform);
			((Object)val3).name = "AC_InfusionFx";
			val3.transform.localPosition = Vector3.zero;
			val3.transform.localRotation = Quaternion.identity;
			val3.transform.localScale = Vector3.one;
			MeshFilter[] componentsInChildren = val3.GetComponentsInChildren<MeshFilter>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
			MeshRenderer[] componentsInChildren2 = val3.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren2[i]);
			}
			Collider[] componentsInChildren3 = val3.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren3[i]);
			}
			Light[] componentsInChildren4 = val3.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.Destroy((Object)(object)((Component)componentsInChildren4[i]).gameObject);
			}
			Color color = ColorFor(id);
			ParticleSystem[] componentsInChildren5 = val3.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem ps in componentsInChildren5)
			{
				EmitFromBlade(ps, bladeRenderer);
				Recolor(ps, color);
			}
			val3.AddComponent<InfusionAuraPulse>();
			return val3;
		}

		private static void EmitFromBlade(ParticleSystem ps, Renderer bladeRenderer)
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			MainModule main = ps.main;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
			((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)1;
			ShapeModule shape = ps.shape;
			((ShapeModule)(ref shape)).enabled = true;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)14;
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((bladeRenderer is SkinnedMeshRenderer) ? bladeRenderer : null);
			if (val != null)
			{
				((ShapeModule)(ref shape)).skinnedMeshRenderer = val;
			}
			else
			{
				((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)13;
				((ShapeModule)(ref shape)).meshRenderer = (MeshRenderer)(object)((bladeRenderer is MeshRenderer) ? bladeRenderer : null);
			}
			((ShapeModule)(ref shape)).meshShapeType = (ParticleSystemMeshShapeType)2;
			((ShapeModule)(ref shape)).normalOffset = 0.01f;
			((ShapeModule)(ref shape)).meshSpawnMode = (ParticleSystemShapeMultiModeValue)1;
			((ShapeModule)(ref shape)).meshSpawnSpeed = MinMaxCurve.op_Implicit(1.5f);
			((ShapeModule)(ref shape)).meshSpawnSpread = 0f;
			((ShapeModule)(ref shape)).scale = Vector3.one;
			((ShapeModule)(ref shape)).position = Vector3.zero;
			((ShapeModule)(ref shape)).rotation = Vector3.zero;
		}

		private static void Recolor(ParticleSystem ps, Color color)
		{
			//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_0009: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_005e: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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)
			MainModule main = ps.main;
			MinMaxGradient startColor = ((MainModule)(ref main)).startColor;
			((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(color.r, color.g, color.b, ((MinMaxGradient)(ref startColor)).color.a));
			Color val = Color.Lerp(color, Color.white, 0.5f);
			Gradient val2 = new Gradient();
			val2.SetKeys((GradientColorKey[])(object)new GradientColorKey[3]
			{
				new GradientColorKey(val, 0f),
				new GradientColorKey(color, 0.4f),
				new GradientColorKey(color, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[3]
			{
				new GradientAlphaKey(1f, 0f),
				new GradientAlphaKey(1f, 0.6f),
				new GradientAlphaKey(0f, 1f)
			});
			ColorOverLifetimeModule colorOverLifetime = ps.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val2);
		}

		private static Color ColorFor(InfusionId id)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(id switch
			{
				InfusionId.Fire => new Color(1f, 0.4f, 0.1f), 
				InfusionId.Frost => new Color(0.5f, 0.85f, 1f), 
				InfusionId.Lightning => new Color(0.6f, 0.7f, 1f), 
				InfusionId.Spirit => new Color(0.75f, 0.6f, 1f), 
				InfusionId.Poison => new Color(0.4f, 1f, 0.3f), 
				InfusionId.Vampirism => new Color(0.8f, 0f, 0.1f), 
				InfusionId.Slow => new Color(0.5f, 0.35f, 0.2f), 
				InfusionId.Bleed => new Color(0.7f, 0f, 0f), 
				_ => Color.white, 
			});
		}
	}
	internal static class InfusionRegistry
	{
		private static readonly Dictionary<string, InfusionDefinition> ByPrefabName = InfusionDefinition.All.ToDictionary((InfusionDefinition d) => d.ClonePrefabName);

		public static InfusionDefinition Find(ItemData item)
		{
			string text = (((Object)(object)item?.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : null);
			if (text == null)
			{
				return null;
			}
			if (!ByPrefabName.TryGetValue(text, out var value))
			{
				return null;
			}
			return value;
		}
	}
	internal static class InfusionSoundFactory
	{
		private class SoundCleanup : MonoBehaviour
		{
			private const float StartGrace = 0.75f;

			private const float MaxLifetime = 5f;

			private AudioSource[] _sources;

			private float _age;

			private bool _started;

			private void Awake()
			{
				_sources = ((Component)this).GetComponentsInChildren<AudioSource>(true);
			}

			private void Update()
			{
				_age += Time.deltaTime;
				if (_age >= 5f)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
					return;
				}
				AudioSource[] sources = _sources;
				foreach (AudioSource val in sources)
				{
					if ((Object)(object)val != (Object)null && val.isPlaying)
					{
						_started = true;
						return;
					}
				}
				if (_started || !(_age < 0.75f))
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
			}
		}

		public static void PlayApplySound(InfusionDefinition definition, Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!TryPlayNamed(definition, position) && !TryPlay(GetElementalStatusSfx(definition), position))
			{
				TryPlay(GetSourceMeadSfx(definition), position);
			}
		}

		private static string GetNamedSound(InfusionDefinition definition)
		{
			if (definition.Id == InfusionId.Spirit)
			{
				return "sfx_staffspiritcaller_summon";
			}
			return null;
		}

		private static EffectList GetElementalStatusSfx(InfusionDefinition definition)
		{
			int num;
			switch (definition.Id)
			{
			case InfusionId.Fire:
				num = SEMan.s_statusEffectBurning;
				break;
			case InfusionId.Frost:
				num = SEMan.s_statusEffectFrost;
				break;
			case InfusionId.Lightning:
				num = SEMan.s_statusEffectLightning;
				break;
			case InfusionId.Poison:
				num = SEMan.s_statusEffectPoison;
				break;
			case InfusionId.Slow:
				num = SEMan.s_statusEffectPoison;
				break;
			default:
				return null;
			}
			StatusEffect val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetStatusEffect(num) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.m_startEffects;
		}

		private static EffectList GetSourceMeadSfx(InfusionDefinition definition)
		{
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(definition.SourcePrefabName) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			StatusEffect val3 = (((Object)(object)val2 != (Object)null) ? val2.m_itemData.m_shared.m_consumeStatusEffect : null);
			if (!((Object)(object)val3 != (Object)null))
			{
				return null;
			}
			return val3.m_startEffects;
		}

		private static bool TryPlayNamed(InfusionDefinition definition, Vector3 position)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			string namedSound = GetNamedSound(definition);
			if (namedSound == null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return false;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(namedSound);
			if ((Object)(object)prefab == (Object)null || !HasAudio(prefab))
			{
				return false;
			}
			SpawnAudioOnly(prefab, position);
			return true;
		}

		private static bool TryPlay(EffectList list, Vector3 position)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (list?.m_effectPrefabs == null)
			{
				return false;
			}
			EffectData[] effectPrefabs = list.m_effectPrefabs;
			foreach (EffectData val in effectPrefabs)
			{
				if (!((Object)(object)val?.m_prefab == (Object)null) && val.m_enabled && HasAudio(val.m_prefab))
				{
					SpawnAudioOnly(val.m_prefab, position);
					return true;
				}
			}
			return false;
		}

		private static bool HasAudio(GameObject prefab)
		{
			if (!((Object)(object)prefab.GetComponentInChildren<ZSFX>(true) != (Object)null))
			{
				return (Object)(object)prefab.GetComponentInChildren<AudioSource>(true) != (Object)null;
			}
			return true;
		}

		private static void SpawnAudioOnly(GameObject prefab, Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
			ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
			Renderer[] componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren2[i]);
			}
			Light[] componentsInChildren3 = val.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Behaviour)componentsInChildren3[i]).enabled = false;
			}
			MonoBehaviour[] componentsInChildren4 = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren4)
			{
				string name = ((object)val2).GetType().Name;
				if (name == "LightLod" || name == "LightFlicker")
				{
					((Behaviour)val2).enabled = false;
				}
			}
			AudioSource[] componentsInChildren5 = val.GetComponentsInChildren<AudioSource>(true);
			for (int i = 0; i < componentsInChildren5.Length; i++)
			{
				componentsInChildren5[i].loop = false;
			}
			val.AddComponent<SoundCleanup>();
		}
	}
	internal class InfusionVisualController : MonoBehaviour
	{
		private const float TickInterval = 1f;

		private ZNetView _nview;

		private Humanoid _humanoid;

		private Renderer[] _blades;

		private GameObject[] _particles;

		private int _currentShownId = -1;

		public void Bind(ZNetView nview, Humanoid humanoid, Renderer[] blades)
		{
			_nview = nview;
			_humanoid = humanoid;
			_blades = blades;
			((MonoBehaviour)this).CancelInvoke("Tick");
			((MonoBehaviour)this).InvokeRepeating("Tick", 0f, 1f);
		}

		private void Tick()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				ClearParticles();
				return;
			}
			ZDO zDO = _nview.GetZDO();
			if (zDO == null)
			{
				ClearParticles();
				return;
			}
			ActiveInfusion activeInfusion = null;
			if (_nview.IsOwner() && (Object)(object)_humanoid != (Object)null)
			{
				int num = (int)(WeaponInfusionState.GetActive(InfusableWeapons.GetEquipped(_humanoid, includeSheathed: true))?.Definition.Id ?? ((InfusionId)(-1)));
				zDO.Set("ac_infusion_r", num);
			}
			int num2 = zDO.GetInt("ac_infusion_r", -1);
			if (num2 != _currentShownId)
			{
				_currentShownId = num2;
				ApplyVisual(num2);
			}
		}

		private void ApplyVisual(int id)
		{
			ClearParticles();
			if (id < 0 || _blades == null)
			{
				return;
			}
			InfusionDefinition infusionDefinition = InfusionDefinition.All.FirstOrDefault((InfusionDefinition d) => d.Id == (InfusionId)id);
			if (infusionDefinition != null)
			{
				_particles = (GameObject[])(object)new GameObject[_blades.Length];
				for (int num = 0; num < _blades.Length; num++)
				{
					_particles[num] = InfusionParticleFactory.Create(infusionDefinition.Id, _blades[num]);
				}
				AdagasCruzadasPlugin.Log.LogInfo((object)$"[Infusao Visual] efeito de {infusionDefinition.Id} em {_blades.Length} lamina(s) de {((Object)this).name}.");
			}
		}

		private void ClearParticles()
		{
			if (_particles == null)
			{
				return;
			}
			GameObject[] particles = _particles;
			foreach (GameObject val in particles)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
			_particles = null;
		}

		private void OnDestroy()
		{
			ClearParticles();
		}
	}
	internal static class KnifeSkillBonus
	{
		private const float PerLevel = 0.0045f;

		public static float Multiplier(SkillType weaponSkill, float skillLevel)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)weaponSkill != 2)
			{
				return 1f;
			}
			return 1f + skillLevel * 0.0045f;
		}

		public static float Multiplier(float knifeSkillLevel)
		{
			return 1f + knifeSkillLevel * 0.0045f;
		}
	}
	[HarmonyPatch(typeof(Player), "ConsumeItem")]
	internal static class WeaponInfusionApplyPatch
	{
		private static bool Prefix(Player __instance, Inventory inventory, ItemData item, ref bool __result)
		{
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			InfusionDefinition infusionDefinition = InfusionRegistry.Find(item);
			if (infusionDefinition == null)
			{
				return true;
			}
			ItemData equipped = InfusableWeapons.GetEquipped((Humanoid)(object)__instance, includeSheathed: false);
			if (equipped == null)
			{
				((Character)__instance).Message((MessageType)2, "$adagascruzadas_infusion_needweapon", 0, (Sprite)null, false);
				__result = false;
				return false;
			}
			string text = InfusionConflict.Find(equipped, infusionDefinition);
			if (text != null)
			{
				Localization instance = Localization.instance;
				((Character)__instance).Message((MessageType)2, instance.Localize("$adagascruzadas_infusion_conflict") + " (" + instance.Localize(text) + ")", 0, (Sprite)null, false);
				__result = false;
				return false;
			}
			ActiveInfusion active = WeaponInfusionState.GetActive(equipped);
			if (active != null && active.Definition.Id != infusionDefinition.Id)
			{
				StatusEffect val = InfusionHudEffectFactory.Get(active.Definition.Id);
				if ((Object)(object)val != (Object)null)
				{
					((Character)__instance).GetSEMan().RemoveStatusEffect(val, true);
				}
			}
			WeaponInfusionState.Apply(equipped, infusionDefinition);
			inventory.RemoveOneItem(item);
			StatusEffect val2 = InfusionHudEffectFactory.Get(infusionDefinition.Id);
			if ((Object)(object)val2 != (Object)null)
			{
				((Character)__instance).GetSEMan().AddStatusEffect(val2, true, 0, 0f, (short)(-1));
			}
			InfusionSoundFactory.PlayApplySound(infusionDefinition, ((Component)__instance).transform.position);
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Attack), "ModifyDamage")]
	internal static class WeaponInfusionDamagePatch
	{
		private static readonly float[] ChainMultipliers = new float[3] { 1.3f, 2f, 1.5f };

		internal const string ZdoAttackInfusionKey = "ac_infusion_hit";

		internal const string ZdoAttackSkillKey = "ac_infusion_hit_skill";

		private static void Postfix(HitData hitData, int ___m_currentAttackCainLevel, ItemData ___m_weapon, Humanoid ___m_character)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			ActiveInfusion activeInfusion = (InfusableWeapons.IsInfusable(___m_weapon) ? WeaponInfusionState.GetActive(___m_weapon) : null);
			PublishAttackingInfusion(___m_character, activeInfusion, ___m_weapon);
			if (activeInfusion != null)
			{
				int num = Mathf.Clamp(___m_currentAttackCainLevel, 0, ChainMultipliers.Length - 1);
				float skillBonus = KnifeSkillBonus.Multiplier(___m_weapon.m_shared.m_skillType, hitData.m_skillLevel);
				switch (activeInfusion.Definition.Family)
				{
				case InfusionFamily.DirectDamage:
					ApplyDirectDamage(hitData, activeInfusion.Definition, ChainMultipliers[num], skillBonus);
					break;
				case InfusionFamily.Status:
					ApplyStatus(hitData, activeInfusion.Definition, skillBonus);
					break;
				case InfusionFamily.Vampirism:
					ApplyVampirism(hitData, activeInfusion.Definition, num, ___m_character, skillBonus);
					break;
				}
			}
		}

		private static void PublishAttackingInfusion(Humanoid attacker, ActiveInfusion active, ItemData weapon)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)attacker == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)attacker).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (zDO != null)
			{
				int num = (int)(active?.Definition.Id ?? ((InfusionId)(-1)));
				if (zDO.GetInt("ac_infusion_hit", -1) != num)
				{
					zDO.Set("ac_infusion_hit", num);
					zDO.Set("ac_infusion_hit_skill", (active != null && weapon?.m_shared != null) ? ((int)weapon.m_shared.m_skillType) : 0);
				}
			}
		}

		private static void ApplyDirectDamage(HitData hitData, InfusionDefinition def, float multiplier, float skillBonus)
		{
			if (hitData.m_variant < 0)
			{
				hitData.m_variant = 0;
			}
			float num = def.BaseDamage * multiplier * skillBonus;
			switch (def.DamageType)
			{
			case ElementalDamageType.Fire:
				hitData.m_damage.m_fire += num;
				break;
			case ElementalDamageType.Frost:
				hitData.m_damage.m_frost += num;
				break;
			case ElementalDamageType.Lightning:
				hitData.m_damage.m_lightning += num;
				break;
			case ElementalDamageType.Spirit:
				hitData.m_damage.m_spirit += num;
				break;
			case ElementalDamageType.Poison:
				hitData.m_damage.m_poison += num;
				break;
			}
		}

		private static void ApplyStatus(HitData hitData, InfusionDefinition def, float skillBonus)
		{
			if (Random.value >= def.Chance)
			{
				return;
			}
			ObjectDB instance = ObjectDB.instance;
			StatusEffect val = ((instance != null) ? instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode(def.TargetStatusEffectName)) : null);
			if (!((Object)(object)val == (Object)null))
			{
				hitData.m_statusEffectHash = val.NameHash();
				if (skillBonus <= 1f)
				{
					hitData.m_skillLevel = 0f;
				}
			}
		}

		private static void ApplyVampirism(HitData hitData, InfusionDefinition def, int level, Humanoid attacker, float skillBonus)
		{
			if (!((Object)(object)attacker == (Object)null))
			{
				float num = ((DamageTypes)(ref hitData.m_damage)).GetTotalDamage();
				if (level == ChainMultipliers.Length - 1)
				{
					num *= 2f;
				}
				((Character)attacker).Heal(num * def.HealPercent * skillBonus, true);
			}
		}
	}
	internal class ActiveInfusion
	{
		public InfusionDefinition Definition;

		public double EndTime;
	}
	internal static class WeaponInfusionState
	{
		private const string InfusionKey = "ac_infusion";

		private const string EndKey = "ac_infusion_end";

		public static ActiveInfusion GetActive(ItemData weapon)
		{
			if (weapon == null)
			{
				return null;
			}
			if (!weapon.m_customData.TryGetValue("ac_infusion", out var value))
			{
				return null;
			}
			if (!weapon.m_customData.TryGetValue("ac_infusion_end", out var value2))
			{
				return null;
			}
			if (!double.TryParse(value2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				Clear(weapon);
				return null;
			}
			if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.GetTimeSeconds() >= result)
			{
				Clear(weapon);
				return null;
			}
			if (!Enum.TryParse<InfusionId>(value, out var id))
			{
				Clear(weapon);
				return null;
			}
			InfusionDefinition infusionDefinition = InfusionDefinition.All.FirstOrDefault((InfusionDefinition d) => d.Id == id);
			if (infusionDefinition == null)
			{
				Clear(weapon);
				return null;
			}
			return new ActiveInfusion
			{
				Definition = infusionDefinition,
				EndTime = result
			};
		}

		public static void Apply(ItemData weapon, InfusionDefinition definition)
		{
			double num = ZNet.instance.GetTimeSeconds() + 300.0;
			weapon.m_customData["ac_infusion"] = definition.Id.ToString();
			weapon.m_customData["ac_infusion_end"] = num.ToString(CultureInfo.InvariantCulture);
		}

		public static void Clear(ItemData weapon)
		{
			weapon.m_customData.Remove("ac_infusion");
			weapon.m_customData.Remove("ac_infusion_end");
		}

		public static float GetRemainingSeconds(ActiveInfusion active)
		{
			if (active == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return 0f;
			}
			return (float)(active.EndTime - ZNet.instance.GetTimeSeconds());
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int),
		typeof(bool)
	})]
	internal static class WeaponInfusionTooltipPatch
	{
		private static void Postfix(ItemData item, ref string __result)
		{
			if (InfusableWeapons.IsInfusable(item))
			{
				ActiveInfusion active = WeaponInfusionState.GetActive(item);
				if (active != null)
				{
					float remainingSeconds = WeaponInfusionState.GetRemainingSeconds(active);
					int num = (int)(remainingSeconds / 60f);
					int num2 = (int)(remainingSeconds % 60f);
					string arg = Localization.instance.Localize(active.Definition.NameToken);
					__result += $"\n<color=orange>Infundida: {arg} ({num:00}:{num2:00})</color>";
				}
			}
		}
	}
	[HarmonyPatch(typeof(VisEquipment), "AttachItem")]
	internal static class WeaponInfusionVisualPatch
	{
		internal const string ZdoInfusionKey = "ac_infusion_r";

		private static void Postfix(VisEquipment __instance, GameObject __result, int itemHash, bool backAttach)
		{
			if ((Object)(object)__result == (Object)null || !InfusableWeapons.IsInfusableHash(itemHash))
			{
				return;
			}
			Renderer[] array = (from r in __result.GetComponentsInChildren<Renderer>(true)
				where EmitsAlongTheBlade(r, __result.transform)
				select r).ToArray();
			if (array.Length == 0)
			{
				AdagasCruzadasPlugin.Log.LogInfo((object)("[Infusao Visual] " + ((Object)__result).name + " nao tem malha propria pra emitir a aura; arma fica sem efeito visual. Renderers: " + DescribeRenderers(__result)));
				return;
			}
			InfusionVisualController infusionVisualController = __result.GetComponent<InfusionVisualController>();
			if ((Object)(object)infusionVisualController == (Object)null)
			{
				infusionVisualController = __result.AddComponent<InfusionVisualController>();
			}
			infusionVisualController.Bind(((Component)__instance).GetComponent<ZNetView>(), ((Component)__instance).GetComponent<Humanoid>(), array);
			AdagasCruzadasPlugin.Log.LogInfo((object)$"[Infusao Visual] controller ligado em {((Object)__result).name} (embainhada={backAttach}, laminas={array.Length}).");
		}

		private static bool EmitsAlongTheBlade(Renderer renderer, Transform attachRoot)
		{
			if (renderer is MeshRenderer)
			{
				return true;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if (val == null)
			{
				return false;
			}
			Transform rootBone = val.rootBone;
			if (!((Object)(object)rootBone == (Object)null))
			{
				return rootBone.IsChildOf(attachRoot);
			}
			return true;
		}

		private static string DescribeRenderers(GameObject root)
		{
			IEnumerable<string> source = root.GetComponentsInChildren<Renderer>(true).Select(delegate(Renderer r)
			{
				SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((r is SkinnedMeshRenderer) ? r : null);
				return (val == null) ? (((Object)r).name + ":" + ((object)r).GetType().Name) : (((Object)r).name + ":Skinned(root=" + (((Object)(object)val.rootBone != (Object)null) ? ((Object)val.rootBone).name : "null") + ")");
			});
			return string.Join(", ", source.ToArray());
		}
	}
}
namespace AdagasCruzadas.Combat.Ui
{
	internal class EnemyStatusIcons : MonoBehaviour
	{
		private const float IconSize = 26f;

		private const float Spacing = 4f;

		private const float VerticalOffset = -18f;

		private const string ZdoStatusKey = "ac_target_status";

		private const float SyncInterval = 0.25f;

		private Character _character;

		private ZNetView _nview;

		private RectTransform _row;

		private readonly List<Image> _pool = new List<Image>();

		private readonly List<StatusEffect> _visible = new List<StatusEffect>();

		private readonly List<int> _sources = new List<int>();

		private float _syncTimer;

		private string _lastPublished;

		private static readonly int[] InfusionStatusHashes = new int[5]
		{
			SEMan.s_statusEffectBurning,
			SEMan.s_statusEffectFrost,
			SEMan.s_statusEffectPoison,
			SEMan.s_statusEffectSpirit,
			SEMan.s_statusEffectLightning
		};

		public void Setup(Character character, RectTransform reference)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_00dd: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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)
			_character = character;
			_nview = (((Object)(object)character != (Object)null) ? ((Component)character).GetComponent<ZNetView>() : null);
			if (!((Object)(object)_row != (Object)null))
			{
				GameObject val = new GameObject("AC_StatusIcons", new Type[1] { typeof(RectTransform) });
				_row = val.GetComponent<RectTransform>();
				((Transform)_row).SetParent(((Component)this).transform, false);
				if ((Object)(object)reference != (Object)null)
				{
					_row.anchorMin = reference.anchorMin;
					_row.anchorMax = reference.anchorMax;
					_row.pivot = reference.pivot;
					_row.anchoredPosition = reference.anchoredPosition + new Vector2(0f, -18f);
				}
				else
				{
					_row.anchoredPosition = new Vector2(0f, -18f);
				}
				_row.sizeDelta = new Vector2(0f, 26f);
			}
		}

		private void LateUpdate()
		{
			if (!((Object)(object)_character == (Object)null) && !((Object)(object)_row == (Object)null))
			{
				if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner())
				{
					CollectFromStatusManager();
					PublishToZdo();
				}
				else
				{
					CollectFromZdo();
				}
				Layout();
			}
		}

		private void CollectFromStatusManager()
		{
			_visible.Clear();
			_sources.Clear();
			SEMan sEMan = _character.GetSEMan();
			if (sEMan == null)
			{
				return;
			}
			InfusionStatusSource component = ((Component)_character).GetComponent<InfusionStatusSource>();
			foreach (StatusEffect statusEffect in sEMan.GetStatusEffects())
			{
				if (!((Object)(object)statusEffect == (Object)null) && !statusEffect.m_hidden)
				{
					int num = -1;
					if ((Object)(object)component != (Object)null && component.TryGet(statusEffect.NameHash(), out var infusion))
					{
						num = (int)infusion;
					}
					if (!((Object)(object)ResolveIcon(statusEffect, num) == (Object)null))
					{
						_visible.Add(statusEffect);
						_sources.Add(num);
					}
				}
			}
			ForgetExpiredSources(component, sEMan);
		}

		private void ForgetExpiredSources(InfusionStatusSource source, SEMan seMan)
		{
			if ((Object)(object)source == (Object)null || !source.HasAny)
			{
				return;
			}
			int[] infusionStatusHashes = InfusionStatusHashes;
			foreach (int num in infusionStatusHashes)
			{
				if (!seMan.HaveStatusEffect(num))
				{
					source.Forget(num);
				}
			}
		}

		private void PublishToZdo()
		{
			_syncTimer -= Time.deltaTime;
			if (_syncTimer > 0f)
			{
				return;
			}
			_syncTimer = 0.25f;
			ZDO zDO = _nview.GetZDO();
			if (zDO == null)
			{
				return;
			}
			string text = string.Empty;
			if (_visible.Count > 0)
			{
				string[] array = new string[_visible.Count];
				for (int i = 0; i < _visible.Count; i++)
				{
					array[i] = _visible[i].NameHash() + ":" + _sources[i];
				}
				text = string.Join(",", array);
			}
			if (!(text == _lastPublished))
			{
				_lastPublished = text;
				zDO.Set("ac_target_status", text);
			}
		}

		private void CollectFromZdo()
		{
			_visible.Clear();
			_sources.Clear();
			ZDO val = (((Object)(object)_nview != (Object)null && _nview.IsValid()) ? _nview.GetZDO() : null);
			if (val == null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			string text = val.GetString("ac_target_status", string.Empty);
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			string[] array = text.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (int.TryParse(array2[0], out var result))
				{
					int result2 = -1;
					if (array2.Length > 1)
					{
						int.TryParse(array2[1], out result2);
					}
					StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(result);
					if (!((Object)(object)statusEffect == (Object)null) && !statusEffect.m_hidden && !((Object)(object)ResolveIcon(statusEffect, result2) == (Object)null))
					{
						_visible.Add(statusEffect);
						_sources.Add(result2);
					}
				}
			}
		}

		private static Sprite ResolveIcon(StatusEffect se, int infusionId)
		{
			if (infusionId < 0)
			{
				return se.m_icon;
			}
			Sprite val = InfusionIconFactory.Get(ObjectDB.instance, (InfusionId)infusionId);
			if (!((Object)(object)val != (Object)null))
			{
				return se.m_icon;
			}
			return val;
		}

		private void Layout()
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			EnsurePool(_visible.Count);
			float num = (0f - ((float)_visible.Count * 26f + (float)Mathf.Max(0, _visible.Count - 1) * 4f)) / 2f + 13f;
			for (int i = 0; i < _pool.Count; i++)
			{
				Image val = _pool[i];
				if (i >= _visible.Count)
				{
					if (((Component)val).gameObject.activeSelf)
					{
						((Component)val).gameObject.SetActive(false);
					}
					continue;
				}
				if (!((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(true);
				}
				val.sprite = ResolveIcon(_visible[i], _sources[i]);
				((Graphic)val).rectTransform.anchoredPosition = new Vector2(num, 0f);
				num += 30f;
			}
		}

		private void EnsurePool(int count)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			while (_pool.Count < count)
			{
				GameObject val = new GameObject("AC_StatusIcon", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				RectTransform component = val.GetComponent<RectTransform>();
				((Transform)component).SetParent((Transform)(object)_row, false);
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.pivot = new Vector2(0.5f, 0.5f);
				component.sizeDelta = new Vector2(26f, 26f);
				Image component2 = val.GetComponent<Image>();
				((Graphic)component2).raycastTarget = false;
				_pool.Add(component2);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHud), "UpdateHuds")]
	internal static class EnemyStatusIconsPatch
	{
		private static readonly FieldInfo HudsField = AccessTools.Field(typeof(EnemyHud), "m_huds");

		private static readonly Type HudDataType = AccessTools.Inner(typeof(EnemyHud), "HudData");

		private static readonly FieldInfo GuiField = ((HudDataType != null) ? AccessTools.Field(HudDataType, "m_gui") : null);

		private static readonly FieldInfo HealthFastField = ((HudDataType != null) ? AccessTools.Field(HudDataType, "m_healthFast") : null);

		private static void Postfix(EnemyHud __instance)
		{
			if (HudsField == null || GuiField == null || !(HudsField.GetValue(__instance) is IDictionary dictionary))
			{
				return;
			}
			foreach (DictionaryEntry item in dictionary)
			{
				object key = item.Key;
				Character val = (Character)((key is Character) ? key : null);
				if (!((Object)(object)val == (Object)null) && item.Value != null)
				{
					object? value = GuiField.GetValue(item.Value);
					GameObject val2 = (GameObject)((value is GameObject) ? value : null);
					if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.GetComponent<EnemyStatusIcons>() != (Object)null))
					{
						val2.AddComponent<EnemyStatusIcons>().Setup(val, GetHealthBarRect(item.Value));
					}
				}
			}
		}

		private static RectTransform GetHealthBarRect(object hudData)
		{
			object? obj = HealthFastField?.GetValue(hudData);
			GuiBar val = (GuiBar)((obj is GuiBar) ? obj : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			Transform transform = ((Component)val).transform;
			return (RectTransform)(object)((transform is RectTransform) ? transform : null);
		}
	}
	internal class InfusionStatusSource : MonoBehaviour
	{
		private readonly Dictionary<int, InfusionId> _byStatusHash = new Dictionary<int, InfusionId>();

		public bool HasAny => _byStatusHash.Count > 0;

		public static InfusionStatusSource GetOrAdd(GameObject target)
		{
			InfusionStatusSource component = target.GetComponent<InfusionStatusSource>();
			if (!((Object)(object)component != (Object)null))
			{
				return target.AddComponent<InfusionStatusSource>();
			}
			return component;
		}

		public void Mark(int statusHash, InfusionId infusion)
		{
			_byStatusHash[statusHash] = infusion;
		}

		public bool TryGet(int statusHash, out InfusionId infusion)
		{
			return _byStatusHash.TryGetValue(statusHash, out infusion);
		}

		public void Forget(int statusHash)
		{
			_byStatusHash.Remove(statusHash);
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	internal static class InfusionStatusSourcePatch
	{
		private static readonly Dictionary<InfusionId, int> StatusByInfusion = new Dictionary<InfusionId, int>
		{
			{
				InfusionId.Fire,
				SEMan.s_statusEffectBurning
			},
			{
				InfusionId.Frost,
				SEMan.s_statusEffectFrost
			},
			{
				InfusionId.Poison,
				SEMan.s_statusEffectPoison
			},
			{
				InfusionId.Spirit,
				SEMan.s_statusEffectSpirit
			},
			{
				InfusionId.Lightning,
				SEMan.s_statusEffectLightning
			}
		};

		private static void Postfix(Character __instance, HitData hit)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Invalid comparison between I4 and Unknown
			if ((Object)(object)__instance == (Object)null || hit == null)
			{
				return;
			}
			Character attacker = hit.GetAttacker();
			if ((Object)(object)attacker == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)attacker).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (zDO == null)
			{
				return;
			}
			int num = zDO.GetInt("ac_infusion_hit", -1);
			if (num >= 0 && zDO.GetInt("ac_infusion_hit_skill", 0) == (int)hit.m_skill && StatusByInfusion.TryGetValue((InfusionId)num, out var value))
			{
				SEMan sEMan = __instance.GetSEMan();
				if (sEMan != null && sEMan.HaveStatusEffect(value))
				{
					InfusionStatusSo