Decompiled source of NazhikaCore v0.0.1

NazhikaCore.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using NazhikaCore.Bosses;
using NazhikaCore.Features.Classes;
using NazhikaCore.Features.DeathMessages;
using NazhikaCore.Patches;
using NazhikaCore.RPC;
using NazhikaCore.StatusEffects;
using NazhikaCore.UI;
using NazhikaCore.Utils;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("NazhikaCore")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NazhikaCore")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("11D23B88-B6B8-482B-9F58-4694D6AD10FC")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace NazhikaCore
{
	[BepInPlugin("com.dreams.nazhikacore", "Nazhika Core", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class MainPlugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		internal static ConfigEntry<KeyboardShortcut> ClassSkillKey;

		public static string ModPath { get; private set; }

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			_harmony = new Harmony("com.dreams.nazhikacore");
			Log.Init(((BaseUnityPlugin)this).Logger);
			ModPath = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[NazhikaCore] ModPath = " + ModPath));
			ClassSkillKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keybinds", "ClassSkillKey", new KeyboardShortcut((KeyCode)57, Array.Empty<KeyCode>()), "Tecla para activar la habilidad de clase.");
			SkillsUI.Init(_harmony);
			AdrenalinePatch.Init(_harmony);
			LoginClasses.Init(_harmony);
			OrbsUI.Init(_harmony);
			TankAi.Init(_harmony);
			FistBjornClawRecipePatch.Init(_harmony);
			SE_BleedingSetup.Init();
			SE_FatigueSetup.Init();
			SE_CurseSetup.Init();
			SE_BlindnessSetup.Init();
			SE_OrbGaugeSetup.Init();
			SE_ParryRegenSetup.Init();
			SE_PassiveAtkSpeedSetup.Init();
			SE_WarcrySetup.Init();
			SE_TankPassiveSetup.Init();
			SE_SwordLightningSetup.Init();
			SE_SwordPoisonSetup.Init();
			SE_SwordWitherSetup.Init();
			SE_SpearStacksSetup.Init();
			SE_BloodBurstSetup.Init();
			SE_BerserkfurySetup.Init();
			SE_BerserkBurstSetup.Init();
			SE_BerserkerGodSetup.Init();
			SE_BerserkerGodCooldownSetup.Init();
			SE_FocusShotSetup.Init();
			SE_LightningStormSetup.Init();
			SE_MagicRootsSetup.Init();
			SE_ToxicCloudSetup.Init();
			SE_LavaRocksSetup.Init();
			BerserkerPatches.Init(_harmony);
			BalanceConfig.Init(((BaseUnityPlugin)this).Config);
			ClassSkillsPatches.Init(_harmony);
			LightningStorm_BlockAttackPatch.Init(_harmony);
			Monk_KiPatches.Init(_harmony);
			FatiguePatch.Init(_harmony);
			ArcherCritPatches.Init(_harmony);
			SwordLightningRPC.Init(_harmony);
			SwordPoisonRPC.Init(_harmony);
			SwordWitherRPC.Init(_harmony);
			WarcryRPC.Init(_harmony);
			BerserkBurstRPC.Init(_harmony);
			MonkLeapSkill.Init(_harmony);
			MonkChiReleaseSkill.Init(_harmony);
			MonkLeapPatches.Init(_harmony);
			BleedingPopupRPC.Init(_harmony);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[NazhikaCore] ANTES de BloodBurstNet.Init");
			BloodBurstNet.Init(_harmony);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[NazhikaCore] DESPUES de BloodBurstNet.Init");
			ClearStatusEffectsRPC.Init(_harmony);
			Player_CheerEmoteRPC.Init(_harmony);
			Player_ToxicCloudRPC.Init(_harmony);
			EikthyrBoss.Init(_harmony, ((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			SelectorClass.Init();
			ClearEffects.Init();
			ShoutDeath.Init(((BaseUnityPlugin)this).Config, _harmony, ((BaseUnityPlugin)this).Logger);
			ClassSpriteLoader.ImageFolder = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Images");
			GUIManager.OnCustomGUIAvailable += ClassSelectionUI.Instance.OnGUIAvailable;
			PrefabManager.OnVanillaPrefabsAvailable += delegate
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab("Custom_Magetable_Ext_1");
				if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<MageTableInteract>() == (Object)null)
				{
					prefab.AddComponent<MageTableInteract>();
				}
			};
			((BaseUnityPlugin)this).Logger.LogInfo((object)"✅ NazhikaCore inicializado correctamente.");
		}

		private void Update()
		{
			ClassManager.Update();
			MonkLeapSkill.EnsureRpcRegistered();
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"\ud83d\uded1 NazhikaCore descargado y parches removidos.");
		}
	}
}
namespace NazhikaCore.Utils
{
	public static class EmotesNet
	{
		public static void PlayCheer(Player player)
		{
			if (!((Object)(object)((Character)(player?)).m_nview == (Object)null) && ((Character)player).m_nview.IsValid())
			{
				((Character)player).m_nview.InvokeRPC(ZNetView.Everybody, "RPC_Nazhika_PlayCheer", Array.Empty<object>());
			}
		}
	}
	public static class IconHelper
	{
		public static Sprite Load(string fileName)
		{
			string text = Path.Combine(MainPlugin.ModPath, "NazhikaCore", "Assets", "Icons");
			string text2 = Path.Combine(text, fileName);
			Debug.Log((object)("[NazhikaCore.IconHelper] Buscando ícono en: " + text));
			if (!File.Exists(text2))
			{
				return null;
			}
			Sprite val = AssetUtils.LoadSpriteFromFile(text2);
			if ((Object)(object)val != (Object)null)
			{
				Debug.Log((object)("[NazhikaCore.IconHelper] ✅ Ícono cargado: " + fileName));
			}
			else
			{
				Debug.LogWarning((object)("[NazhikaCore.IconHelper] ⚠\ufe0f Error al cargar sprite desde: " + text2));
			}
			return val;
		}
	}
	public static class Log
	{
		private static ManualLogSource _logger;

		public static void Init(ManualLogSource logger)
		{
			_logger = logger;
		}

		public static void Info(string message)
		{
			_logger.LogInfo((object)message);
		}

		public static void Warning(string message)
		{
			_logger.LogWarning((object)message);
		}

		public static void Error(string message)
		{
			_logger.LogError((object)message);
		}
	}
}
namespace NazhikaCore.StatusEffects
{
	public class SE_BerserkBurst : StatusEffect
	{
		[CompilerGenerated]
		private sealed class <GetCandidateItems>d__22 : IEnumerable<ItemData>, IEnumerable, IEnumerator<ItemData>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private ItemData <>2__current;

			private int <>l__initialThreadId;

			private Player p;

			public Player <>3__p;

			ItemData IEnumerator<ItemData>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetCandidateItems>d__22(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = ((Humanoid)p).GetCurrentWeapon();
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = ((Humanoid)p).GetRightItem();
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = ((Humanoid)p).GetLeftItem();
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<ItemData> IEnumerable<ItemData>.GetEnumerator()
			{
				<GetCandidateItems>d__22 <GetCandidateItems>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetCandidateItems>d__ = this;
				}
				else
				{
					<GetCandidateItems>d__ = new <GetCandidateItems>d__22(0);
				}
				<GetCandidateItems>d__.p = <>3__p;
				return <GetCandidateItems>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<ItemData>)this).GetEnumerator();
			}
		}

		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_BerserkBurst");

		public static float BurstDuration = 20f;

		private Character m_char;

		private const string FuryKey = "naz_fury";

		private const string BurstCooldownUntilKey = "naz_berserkburst_cd_until";

		private bool _fxApplied;

		private bool _fxTried;

		private float _waitTimeout = 3f;

		private readonly List<GameObject> _spawnedRight = new List<GameObject>();

		private readonly List<GameObject> _spawnedLeft = new List<GameObject>();

		private const string RightHandPath = "Visual/Armature/Hips/Spine/Spine1/Spine2/RightShoulder/RightArm/RightForeArm/RightHand/RightHand_Attach/attach(Clone)";

		private const string LeftHandPath = "Visual/Armature/Hips/Spine/Spine1/Spine2/LeftShoulder/LeftArm/LeftForeArm/LeftHand/LeftHand_Attach/attach(Clone)";

		public static float DamageMult => BalanceConfig.BerserkDamageMult;

		public SE_BerserkBurst()
		{
			((Object)this).name = "SE_BerserkBurst";
			base.m_name = "Berserker Burst";
			base.m_icon = IconHelper.Load("BerserkerBurst.png");
			base.m_tooltip = $"Aumento de daño temporal (x{DamageMult:0.00}).";
			base.m_ttl = BurstDuration;
		}

		public override void Setup(Character character)
		{
			((StatusEffect)this).Setup(character);
			m_char = character;
			_fxApplied = false;
			_fxTried = false;
			_waitTimeout = 3f;
			_spawnedRight.Clear();
			_spawnedLeft.Clear();
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null && (Object)(object)((Character)val).m_nview != (Object)null && ((Character)val).m_nview.IsValid())
			{
				ZDO zDO = ((Character)val).m_nview.GetZDO();
				if (zDO != null)
				{
					zDO.Set("naz_fury", 0f);
				}
			}
			Player val2 = (Player)(object)((character is Player) ? character : null);
			if (val2 != null)
			{
				BerserkBurstRPC.ApplyFromStatus(val2, active: true);
				BerserkBurstRPC.BroadcastActivated(val2);
			}
		}

		public override void UpdateStatusEffect(float dt)
		{
			((StatusEffect)this).UpdateStatusEffect(dt);
			Character @char = m_char;
			Player val = (Player)(object)((@char is Player) ? @char : null);
			if ((Object)(object)val != (Object)null && (Object)(object)((Character)val).m_nview != (Object)null && ((Character)val).m_nview.IsValid())
			{
				ZDO zDO = ((Character)val).m_nview.GetZDO();
				if (zDO != null && zDO.GetFloat("naz_fury", 0f) > 0f)
				{
					zDO.Set("naz_fury", 0f);
				}
			}
			Character char2 = m_char;
			Player val2 = (Player)(object)((char2 is Player) ? char2 : null);
			if ((Object)(object)val2 == (Object)null || (Object)(object)Player.m_localPlayer != (Object)(object)val2 || _fxApplied || (_fxTried && _waitTimeout <= 0f))
			{
				return;
			}
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				_waitTimeout -= dt;
			}
			else if (!TryApplyAxeFX(val2))
			{
				_waitTimeout -= dt;
				if (_waitTimeout <= 0f)
				{
					_fxTried = true;
				}
			}
		}

		public override void Stop()
		{
			((StatusEffect)this).Stop();
			Character @char = m_char;
			Player val = (Player)(object)((@char is Player) ? @char : null);
			if ((Object)(object)val != (Object)null)
			{
				BerserkBurstRPC.ApplyFromStatus(val, active: false);
			}
			CleanupAxeFX();
			if ((Object)(object)val != (Object)null && (Object)(object)((Character)val).m_nview != (Object)null && ((Character)val).m_nview.IsValid() && ((Character)val).m_nview.GetZDO() != null && (Object)(object)ZNet.instance != (Object)null)
			{
				ZDO zDO = ((Character)val).m_nview.GetZDO();
				zDO.Set("naz_fury", 0f);
				float num = (float)ZNet.instance.GetTimeSeconds();
				zDO.Set("naz_berserkburst_cd_until", num + 20f);
			}
			if ((Object)(object)val != (Object)null && !((Character)val).IsDead())
			{
				SEMan sEMan = ((Character)val).GetSEMan();
				if (sEMan != null && (Object)(object)sEMan.GetStatusEffect(SE_Berserkfury.NameHash) == (Object)null)
				{
					sEMan.AddStatusEffect(SE_Berserkfury.NameHash, false, 0, 0f);
				}
				if ((Object)(object)Player.m_localPlayer == (Object)(object)val)
				{
					SkillsUI.StartCooldown(20f);
				}
			}
		}

		private bool TryApplyAxeFX(Player player)
		{
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			string itemName;
			bool flag = TryFindOneHandedAxe(player, out itemName);
			string itemName2;
			bool flag2 = !flag && TryFindTwoHandedAxe(player, out itemName2);
			if (!flag && !flag2)
			{
				_fxTried = true;
				return false;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "nihoggrAxe", "Viking_Axe", "collider" };
			string text;
			bool flag3;
			bool flag4;
			if (flag)
			{
				text = "teq_nihoggr_axe";
				flag3 = true;
				flag4 = true;
			}
			else
			{
				text = "teq_skoll_battleaxe";
				flag3 = true;
				flag4 = false;
				hashSet.Add("LeviathanAxe");
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return false;
			}
			Transform val = itemPrefab.transform.Find("attach");
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Transform val2 = (flag3 ? ((Component)player).transform.Find("Visual/Armature/Hips/Spine/Spine1/Spine2/RightShoulder/RightArm/RightForeArm/RightHand/RightHand_Attach/attach(Clone)") : null);
			Transform val3 = (flag4 ? ((Component)player).transform.Find("Visual/Armature/Hips/Spine/Spine1/Spine2/LeftShoulder/LeftArm/LeftForeArm/LeftHand/LeftHand_Attach/attach(Clone)") : null);
			if (flag3 && (Object)(object)val2 == (Object)null)
			{
				return false;
			}
			if (flag4 && (Object)(object)val3 == (Object)null)
			{
				return false;
			}
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < val.childCount; i++)
			{
				Transform child = val.GetChild(i);
				if (!hashSet.Contains(((Object)child).name))
				{
					if ((Object)(object)val2 != (Object)null)
					{
						GameObject val4 = Object.Instantiate<GameObject>(((Component)child).gameObject, val2);
						((Object)val4).name = ((Object)child).name;
						val4.transform.localPosition = child.localPosition;
						val4.transform.localRotation = child.localRotation;
						val4.transform.localScale = child.localScale;
						ForceActivateHierarchy(val4);
						_spawnedRight.Add(val4);
						num++;
					}
					if ((Object)(object)val3 != (Object)null)
					{
						GameObject val5 = Object.Instantiate<GameObject>(((Component)child).gameObject, val3);
						((Object)val5).name = ((Object)child).name;
						val5.transform.localPosition = child.localPosition;
						val5.transform.localRotation = child.localRotation;
						val5.transform.localScale = child.localScale;
						ForceActivateHierarchy(val5);
						_spawnedLeft.Add(val5);
						num2++;
					}
				}
			}
			_fxApplied = num + num2 > 0;
			_fxTried = true;
			return _fxApplied;
		}

		private void CleanupAxeFX()
		{
			_fxApplied = false;
			SafeCleanup(_spawnedRight);
			SafeCleanup(_spawnedLeft);
			_spawnedRight.Clear();
			_spawnedLeft.Clear();
		}

		private static bool TryFindOneHandedAxe(Player p, out string itemName)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			itemName = null;
			foreach (ItemData candidateItem in GetCandidateItems(p))
			{
				if (candidateItem?.m_shared != null && (int)candidateItem.m_shared.m_skillType == 7 && (int)candidateItem.m_shared.m_itemType == 3)
				{
					itemName = candidateItem.m_shared.m_name;
					return true;
				}
			}
			return false;
		}

		private static bool TryFindTwoHandedAxe(Player p, out string itemName)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			itemName = null;
			foreach (ItemData candidateItem in GetCandidateItems(p))
			{
				if (candidateItem?.m_shared != null && (int)candidateItem.m_shared.m_skillType == 7 && (int)candidateItem.m_shared.m_itemType == 14)
				{
					itemName = candidateItem.m_shared.m_name;
					return true;
				}
			}
			return false;
		}

		[IteratorStateMachine(typeof(<GetCandidateItems>d__22))]
		private static IEnumerable<ItemData> GetCandidateItems(Player p)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetCandidateItems>d__22(-2)
			{
				<>3__p = p
			};
		}

		private static void ForceActivateHierarchy(GameObject root)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)root == (Object)null))
			{
				SetActiveRecursive(root.transform, active: true);
				ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val in componentsInChildren)
				{
					EmissionModule emission = val.emission;
					((EmissionModule)(ref emission)).enabled = true;
					val.Clear(true);
					val.Play(true);
				}
				TrailRenderer[] componentsInChildren2 = root.GetComponentsInChildren<TrailRenderer>(true);
				for (int j = 0; j < componentsInChildren2.Length; j++)
				{
					((Renderer)componentsInChildren2[j]).enabled = true;
					componentsInChildren2[j].Clear();
				}
				LineRenderer[] componentsInChildren3 = root.GetComponentsInChildren<LineRenderer>(true);
				for (int k = 0; k < componentsInChildren3.Length; k++)
				{
					((Renderer)componentsInChildren3[k]).enabled = true;
				}
				Light[] componentsInChildren4 = root.GetComponentsInChildren<Light>(true);
				for (int l = 0; l < componentsInChildren4.Length; l++)
				{
					((Behaviour)componentsInChildren4[l]).enabled = true;
				}
			}
		}

		private static void SetActiveRecursive(Transform t, bool active)
		{
			((Component)t).gameObject.SetActive(active);
			for (int i = 0; i < t.childCount; i++)
			{
				SetActiveRecursive(t.GetChild(i), active);
			}
		}

		private static int SafeCleanup(List<GameObject> list)
		{
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] != (Object)null)
				{
					Object.Destroy((Object)(object)list[i]);
					num++;
				}
			}
			list.Clear();
			return num;
		}
	}
	public static class SE_BerserkBurstSetup
	{
		private static bool _asmRegistered;

		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_BerserkBurst sE_BerserkBurst = ScriptableObject.CreateInstance<SE_BerserkBurst>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_BerserkBurst, true);
			ItemManager.Instance.AddStatusEffect(val);
			Log.Info("[NazhikaCore] ✅ SE_BerserkBurst registrado (usa BerserkBurstRPC para FX+SFX+Roar).");
			if (_asmRegistered)
			{
				return;
			}
			_asmRegistered = true;
			AnimationSpeedManager.Add(delegate(Character character, double speed)
			{
				Player val2 = (Player)(object)((character is Player) ? character : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return speed;
				}
				if (!ClassApi.HasClass(val2, "Berserker"))
				{
					return speed;
				}
				if (!((Character)val2).InAttack() || ((Humanoid)val2).m_currentAttack == null)
				{
					return speed;
				}
				SEMan sEMan = ((Character)val2).GetSEMan();
				return (sEMan == null || (Object)(object)sEMan.GetStatusEffect(SE_BerserkBurst.NameHash) == (Object)null) ? speed : (speed * (double)BalanceConfig.BerserkAtkSpeedMult);
			});
		}
	}
	public class SE_BerserkerGod : StatusEffect
	{
		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_BerserkerGod");

		public const string FuryBlockZdoKey = "naz_fury_block";

		public const string GodCdZdoKey = "naz_bg_cd_until";

		private const float CooldownSeconds = 60f;

		public SE_BerserkerGod()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			((Object)this).name = "SE_BerserkerGod";
			base.m_name = "Berserker God";
			base.m_icon = IconHelper.Load("BerserkerGod.png");
			base.m_tooltip = "Invulnerable por 8s";
			base.m_ttl = 8f;
			base.m_cooldown = 60f;
			base.m_startMessage = "† Berserker God activado †";
			base.m_startMessageType = (MessageType)2;
		}

		public override void Setup(Character character)
		{
			((StatusEffect)this).Setup(character);
			try
			{
				ZDO val = (((Object)(object)base.m_character != (Object)null && (Object)(object)base.m_character.m_nview != (Object)null) ? base.m_character.m_nview.GetZDO() : null);
				if (val != null)
				{
					val.Set("naz_fury_block", true);
				}
			}
			catch
			{
			}
		}

		public override void Stop()
		{
			try
			{
				ZDO val = (((Object)(object)base.m_character != (Object)null && (Object)(object)base.m_character.m_nview != (Object)null) ? base.m_character.m_nview.GetZDO() : null);
				if (val != null)
				{
					val.Set("naz_fury_block", false);
				}
				Character character = base.m_character;
				SEMan val2 = ((character != null) ? character.GetSEMan() : null);
				if (val2 != null && (Object)(object)val2.GetStatusEffect(SE_BerserkerGodCooldown.NameHash) == (Object)null)
				{
					SE_BerserkerGodCooldown sE_BerserkerGodCooldown = val2.AddStatusEffect(SE_BerserkerGodCooldown.NameHash, false, 0, 0f) as SE_BerserkerGodCooldown;
					if ((Object)(object)sE_BerserkerGodCooldown != (Object)null)
					{
						sE_BerserkerGodCooldown.SetDuration(60f);
					}
				}
				float num = (((Object)(object)EnvMan.instance != (Object)null) ? ((float)EnvMan.instance.m_totalSeconds) : Time.time);
				if (val != null)
				{
					val.Set("naz_bg_cd_until", num + 60f);
				}
			}
			catch
			{
			}
			((StatusEffect)this).Stop();
		}
	}
	public static class SE_BerserkerGodSetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_BerserkerGod sE_BerserkerGod = ScriptableObject.CreateInstance<SE_BerserkerGod>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_BerserkerGod, true);
			ItemManager.Instance.AddStatusEffect(val);
			Debug.Log((object)"[NazhikaCore] ✅ SE_BerserkerGod registrado.");
		}
	}
	public class SE_BerserkerGodCooldown : StatusEffect
	{
		public const string InternalName = "SE_BerserkerGodCooldown";

		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_BerserkerGodCooldown");

		public SE_BerserkerGodCooldown()
		{
			((Object)this).name = "SE_BerserkerGodCooldown";
			base.m_name = "God";
			base.m_tooltip = "En recarga...";
			base.m_ttl = 60f;
			base.m_cooldownIcon = true;
			base.m_icon = IconHelper.Load("BerserkerGod.png");
		}

		public void SetDuration(float seconds)
		{
			base.m_ttl = Mathf.Max(0.1f, seconds);
		}

		public override void UpdateStatusEffect(float dt)
		{
			((StatusEffect)this).UpdateStatusEffect(dt);
			float num = Mathf.Max(0f, base.m_ttl - base.m_time);
			base.m_tooltip = $"En recarga ({num:0}s)";
		}
	}
	public static class SE_BerserkerGodCooldownSetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_BerserkerGodCooldown sE_BerserkerGodCooldown = ScriptableObject.CreateInstance<SE_BerserkerGodCooldown>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_BerserkerGodCooldown, true);
			ItemManager.Instance.AddStatusEffect(val);
			Debug.Log((object)"[NazhikaCore] ✅ SE_BerserkerGodCooldown registrado.");
		}
	}
	public class SE_Berserkfury : StatusEffect
	{
		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_Berserkfury");

		private const string FuryKey = "naz_fury";

		public SE_Berserkfury()
		{
			((Object)this).name = "SE_Berserkfury";
			base.m_name = "Berserker Fury";
			base.m_icon = IconHelper.Load("BerserkerFury.png");
			base.m_tooltip = "La furia se carga al golpear.";
			base.m_ttl = 999999f;
		}

		public override string GetIconText()
		{
			Character character = base.m_character;
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				ZNetView nview = character.m_nview;
				obj = ((nview != null) ? nview.GetZDO() : null);
			}
			ZDO val = (ZDO)obj;
			if (val == null)
			{
				return "";
			}
			float @float = val.GetFloat("naz_fury", 0f);
			if (!(@float > 0f))
			{
				return "";
			}
			return ((int)@float).ToString();
		}
	}
	public static class SE_BerserkfurySetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_Berserkfury sE_Berserkfury = ScriptableObject.CreateInstance<SE_Berserkfury>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_Berserkfury, true);
			ItemManager.Instance.AddStatusEffect(val);
			Log.Info("[NazhikaCore] ✅ SE_Berserkfury registrado (marcador).");
		}
	}
	public class SE_Bleeding : StatusEffect
	{
		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_Bleeding");

		private float tickTimer;

		private float fxTimer;

		private const float BaseHpCap = 10000f;

		private const float MoveSpeedMultiplier = 0.95f;

		internal const string ZdoBleedStacksKey = "nz_bleed_stacks";

		private int _stacks = 1;

		public int Stacks => _stacks;

		public SE_Bleeding()
		{
			((Object)this).name = "SE_Bleeding";
			base.m_name = "Bleeding";
			base.m_tooltip = "Estás sangrando: pierdes vida cada segundo.";
			base.m_icon = IconHelper.Load("bleed.png");
			base.m_ttl = 5f;
		}

		public override void Setup(Character c)
		{
			((StatusEffect)this).Setup(c);
			if (_stacks <= 0)
			{
				_stacks = 1;
			}
			_stacks = Mathf.Clamp(_stacks, 1, BalanceConfig.BleedMaxStacks);
			tickTimer = 0f;
			fxTimer = 0f;
			WriteStacksToZdo(_stacks);
			ApplyBleedTick();
		}

		public override void ModifySpeed(float baseSpeed, ref float speed, Character character, Vector3 dir)
		{
			speed *= 0.95f;
		}

		public override void UpdateStatusEffect(float dt)
		{
			((StatusEffect)this).UpdateStatusEffect(dt);
			tickTimer += dt;
			fxTimer += dt;
			if (tickTimer >= BalanceConfig.BleedTickInterval)
			{
				tickTimer = 0f;
				ApplyBleedTick();
			}
			if (fxTimer >= 1f)
			{
				fxTimer = 0f;
				SpawnBloodFXSafe();
			}
			base.m_tooltip = $"Estás sangrando ({_stacks} stack(s)): el daño por tick se duplica a {BalanceConfig.BleedMaxStacks} stacks. " + "Movimiento -5% (no afecta ataque).";
		}

		public void AddBleedStack()
		{
			_stacks = Mathf.Clamp(_stacks + 1, 1, BalanceConfig.BleedMaxStacks);
			base.m_time = 0f;
			if (base.m_ttl < 4f)
			{
				base.m_ttl = 4f;
			}
			WriteStacksToZdo(_stacks);
		}

		private void ApplyBleedTick()
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)base.m_character == (Object)null || !base.m_character.IsOwner())
			{
				return;
			}
			float maxHealthSafe = GetMaxHealthSafe(base.m_character);
			if (!(maxHealthSafe <= 0f))
			{
				int tier = GetTier(maxHealthSafe);
				float num = maxHealthSafe * 0.1f;
				if (tier >= 7 && num > 10000f)
				{
					num = 10000f;
				}
				float fixedBaseByTier = GetFixedBaseByTier(tier);
				float num2 = num * BalanceConfig.BleedFractionPerStack;
				float num3 = fixedBaseByTier + num2;
				float stackMultiplier = GetStackMultiplier(_stacks);
				float num4 = Mathf.Max(0f, num3 * stackMultiplier);
				float health = base.m_character.GetHealth();
				float health2 = Mathf.Max(0f, health - num4);
				base.m_character.SetHealth(health2);
				BleedingPopupRPC.SendBleedPopup(base.m_character.GetCenterPoint(), num4, _stacks);
				Debug.Log((object)($"[NazhikaCore/Bleeding] {((Object)base.m_character).name} maxHP={maxHealthSafe:0} tier={tier} stacks={_stacks} " + $"hpBase={num:0.#} fixed={fixedBaseByTier:0.#} scaled1={num2:0.##} base1={num3:0.##} mult={stackMultiplier:0.###} dmg={num4:0.##}"));
			}
		}

		private float GetStackMultiplier(int stacks)
		{
			int bleedMaxStacks = BalanceConfig.BleedMaxStacks;
			stacks = Mathf.Clamp(stacks, 1, bleedMaxStacks);
			if (bleedMaxStacks <= 1)
			{
				return 1f;
			}
			return 1f + ((float)stacks - 1f) / ((float)bleedMaxStacks - 1f);
		}

		private static int GetTier(float hp)
		{
			if (hp < 60f)
			{
				return 0;
			}
			if (hp < 180f)
			{
				return 1;
			}
			if (hp < 450f)
			{
				return 2;
			}
			if (hp < 1500f)
			{
				return 3;
			}
			if (hp < 3000f)
			{
				return 4;
			}
			if (hp < 5000f)
			{
				return 5;
			}
			if (hp < 10000f)
			{
				return 6;
			}
			if (hp < 50000f)
			{
				return 7;
			}
			return 8;
		}

		private static float GetFixedBaseByTier(int tier)
		{
			return tier switch
			{
				0 => BalanceConfig.BleedFixedT0, 
				1 => BalanceConfig.BleedFixedT1, 
				2 => BalanceConfig.BleedFixedT2, 
				3 => BalanceConfig.BleedFixedT3, 
				4 => BalanceConfig.BleedFixedT4, 
				5 => BalanceConfig.BleedFixedT5, 
				6 => BalanceConfig.BleedFixedT6, 
				7 => BalanceConfig.BleedFixedT7, 
				8 => BalanceConfig.BleedFixedT8, 
				_ => 10f, 
			};
		}

		private static float GetMaxHealthSafe(Character ch)
		{
			try
			{
				return ch.GetMaxHealth();
			}
			catch
			{
				return Mathf.Max(1f, ch.GetHealth());
			}
		}

		private void SpawnBloodFXSafe()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)base.m_character == (Object)null) && !((Object)(object)ZNetScene.instance == (Object)null))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("vfx_BloodHit");
				if (Object.op_Implicit((Object)(object)prefab))
				{
					Object.Instantiate<GameObject>(prefab, base.m_character.GetCenterPoint(), Quaternion.identity);
				}
			}
		}

		public override void Stop()
		{
			WriteStacksToZdo(0);
			((StatusEffect)this).Stop();
		}

		private void WriteStacksToZdo(int stacks)
		{
			try
			{
				if (!((Object)(object)base.m_character == (Object)null) && !((Object)(object)base.m_character.m_nview == (Object)null) && base.m_character.m_nview.IsValid())
				{
					ZDO zDO = base.m_character.m_nview.GetZDO();
					if (zDO != null)
					{
						zDO.Set("nz_bleed_stacks", stacks);
					}
				}
			}
			catch
			{
			}
		}
	}
	public static class SE_BleedingSetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_Bleeding sE_Bleeding = ScriptableObject.CreateInstance<SE_Bleeding>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_Bleeding, true);
			ItemManager.Instance.AddStatusEffect(val);
			Debug.Log((object)"[NazhikaCore] SE_Bleeding registrado (ZDO stacks sync).");
		}
	}
	public class SE_Blindness : StatusEffect
	{
		private GameObject blackoutCanvas;

		private Image blackoutImage;

		private float fadeSpeed = 2f;

		private float targetAlpha = 0.95f;

		public SE_Blindness()
		{
			((Object)this).name = "SE_Blindness";
			base.m_name = "Blindness";
			base.m_tooltip = "Estás cegado. Tu visión se oscurece.";
			base.m_icon = IconHelper.Load("Blindness.png");
			base.m_cooldownIcon = true;
			base.m_ttl = 6f;
		}

		public override void Setup(Character character)
		{
			((StatusEffect)this).Setup(character);
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer)
			{
				CreateBlackout();
			}
		}

		public override void UpdateStatusEffect(float dt)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			((StatusEffect)this).UpdateStatusEffect(dt);
			if ((Object)(object)blackoutImage != (Object)null)
			{
				Color color = ((Graphic)blackoutImage).color;
				color.a = Mathf.MoveTowards(color.a, targetAlpha, fadeSpeed * dt);
				((Graphic)blackoutImage).color = color;
			}
		}

		public override void Stop()
		{
			RemoveBlackout();
		}

		private void CreateBlackout()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)blackoutCanvas != (Object)null))
			{
				blackoutCanvas = new GameObject("Naz_BlindnessCanvas");
				Canvas val = blackoutCanvas.AddComponent<Canvas>();
				val.renderMode = (RenderMode)0;
				val.sortingOrder = 9999;
				CanvasGroup val2 = blackoutCanvas.AddComponent<CanvasGroup>();
				val2.blocksRaycasts = false;
				val2.interactable = false;
				GameObject val3 = new GameObject("Naz_BlindnessImage");
				val3.transform.SetParent(blackoutCanvas.transform, false);
				blackoutImage = val3.AddComponent<Image>();
				((Graphic)blackoutImage).color = new Color(0f, 0f, 0f, 0f);
				RectTransform rectTransform = ((Graphic)blackoutImage).rectTransform;
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = Vector2.zero;
				rectTransform.offsetMax = Vector2.zero;
				Object.DontDestroyOnLoad((Object)(object)blackoutCanvas);
			}
		}

		private void RemoveBlackout()
		{
			if ((Object)(object)blackoutCanvas != (Object)null)
			{
				Object.Destroy((Object)(object)blackoutCanvas);
				blackoutCanvas = null;
				blackoutImage = null;
			}
		}
	}
	public static class SE_BlindnessSetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_Blindness sE_Blindness = ScriptableObject.CreateInstance<SE_Blindness>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_Blindness, true);
			ItemManager.Instance.AddStatusEffect(val);
			Debug.Log((object)"[NazhikaCore] SE_Blindness registrado correctamente.");
		}
	}
	public class SE_BloodBurst : StatusEffect
	{
		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_BloodBurst");

		private const float RadiusMeters = 60f;

		private const float InsaneDamage = 100f;

		private const bool DebugLogs = true;

		public SE_BloodBurst()
		{
			((Object)this).name = "SE_BloodBurst";
			base.m_name = "BloodBurst";
			base.m_icon = IconHelper.Load("bloodburst.png");
			base.m_tooltip = "Detona sangrados cercanos.";
			base.m_ttl = 1f;
		}

		public override void Setup(Character character)
		{
			((StatusEffect)this).Setup(character);
			BloodBurstNet.EnsureRegisteredRobust();
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				ExecuteServer(character);
			}
			else
			{
				BloodBurstNet.RequestServerExecute(character);
			}
			base.m_time = base.m_ttl;
		}

		internal static void ExecuteServer(Character caster)
		{
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)caster == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			Vector3 position = ((Component)caster).transform.position;
			List<Character> list = new List<Character>();
			Character.GetCharactersInRange(position, 60f, list);
			int num = 0;
			Debug.Log((object)$"[NazhikaCore/BloodBurst][SERVER][START] caster={((Object)caster).name} found={list.Count}");
			foreach (Character item in list)
			{
				if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)caster || item.IsDead() || (Object)(object)item.m_nview == (Object)null || !item.m_nview.IsValid())
				{
					continue;
				}
				int num2 = 0;
				try
				{
					ZDO zDO = item.m_nview.GetZDO();
					if (zDO != null)
					{
						num2 = zDO.GetInt("nz_bleed_stacks", 0);
					}
				}
				catch
				{
				}
				if (num2 <= 0)
				{
					Debug.Log((object)("[NazhikaCore/BloodBurst][SERVER][SKIP] " + ((Object)item).name + " sin nz_bleed_stacks"));
					continue;
				}
				SEMan sEMan = item.GetSEMan();
				if (sEMan == null)
				{
					continue;
				}
				float num3 = 100f;
				float health = item.GetHealth();
				float num4 = Mathf.Max(0f, health - num3);
				item.SetHealth(num4);
				try
				{
					ZDO zDO2 = item.m_nview.GetZDO();
					if (zDO2 != null)
					{
						zDO2.Set("nz_bleed_stacks", 0);
					}
				}
				catch
				{
				}
				BleedApplyRPC.RequestCancelBleed(item);
				Vector3 centerPoint = item.GetCenterPoint();
				BloodBurstNet.TryBroadcastFx(centerPoint);
				num++;
				Debug.Log((object)$"[NazhikaCore/BloodBurst][SERVER][HIT] {((Object)item).name} zdoStacks={num2} dmg={num3} hpBefore={health} hpAfter={num4}");
			}
			Debug.Log((object)$"[NazhikaCore/BloodBurst][SERVER][END] afectados={num}");
		}

		internal static void ExecuteServerAtPosition(Vector3 center)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null)
			{
				return;
			}
			int num = 0;
			List<ZDO> list = new List<ZDO>();
			Vector2i zone = ZoneSystem.GetZone(center);
			ZDOMan.instance.FindSectorObjects(zone, 2, 0, list, (List<ZDO>)null);
			Debug.Log((object)$"[BloodBurst][SERVER][START] pos={center} zdos={list.Count}");
			foreach (ZDO item in list)
			{
				if (item == null)
				{
					continue;
				}
				float num2 = Vector3.Distance(item.GetPosition(), center);
				if (num2 > 60f)
				{
					continue;
				}
				int num3 = 0;
				try
				{
					num3 = item.GetInt("nz_bleed_stacks", 0);
				}
				catch
				{
				}
				if (num3 <= 0)
				{
					continue;
				}
				float num4 = 0f;
				try
				{
					num4 = item.GetFloat(ZDOVars.s_health, 0f);
				}
				catch
				{
				}
				if (!(num4 <= 0f))
				{
					float num5 = Mathf.Max(0f, num4 - 90000f);
					try
					{
						item.Set(ZDOVars.s_health, num5);
						item.Set("nz_bleed_stacks", 0);
					}
					catch
					{
						continue;
					}
					BleedApplyRPC.RequestCancelBleedByZDO(item.m_uid);
					BloodBurstNet.TryBroadcastFx(item.GetPosition());
					num++;
					Debug.Log((object)$"[BloodBurst][SERVER][HIT] zdo={item.m_uid} stacks={num3} hpBefore={num4} hpAfter={num5}");
				}
			}
			Debug.Log((object)$"[BloodBurst][SERVER][END] afectados={num}");
		}
	}
	internal static class BloodBurstNet
	{
		private class RegRunner : MonoBehaviour
		{
			[CompilerGenerated]
			private sealed class <Loop>d__2 : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private object <>2__current;

				public RegRunner <>4__this;

				private float <t>5__2;

				object IEnumerator<object>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <Loop>d__2(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_0051: Unknown result type (might be due to invalid IL or missing references)
					//IL_005b: Expected O, but got Unknown
					int num = <>1__state;
					RegRunner regRunner = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<t>5__2 = 0f;
						break;
					case 1:
						<>1__state = -1;
						break;
					}
					if (<t>5__2 < 2f && !_registered)
					{
						if (ZRoutedRpc.instance == null)
						{
							<t>5__2 += 0.1f;
							<>2__current = (object)new WaitForSeconds(0.1f);
							<>1__state = 1;
							return true;
						}
						EnsureRegisteredNow();
					}
					regRunner._running = false;
					return false;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			private bool _running;

			public void Kick()
			{
				if (!_running)
				{
					_running = true;
					((MonoBehaviour)this).StartCoroutine(Loop());
				}
			}

			[IteratorStateMachine(typeof(<Loop>d__2))]
			private IEnumerator Loop()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <Loop>d__2(0)
				{
					<>4__this = this
				};
			}
		}

		internal const string RpcFxName = "NazhikaCore_BloodBurstFx";

		internal const string RpcRequestName = "NazhikaCore_BloodBurst_Request";

		private const bool DebugLogs = true;

		private static bool _registered;

		private static GameObject _regRunnerGo;

		private static RegRunner _regRunner;

		public static void Init(Harmony harmony)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "Start", (Type[])null, (Type[])null);
			HarmonyMethod val = new HarmonyMethod(typeof(BloodBurstNet), "ZNet_Start_Postfix", (Type[])null);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Debug.Log((object)"[NazhikaCore/BloodBurstNet] Init OK");
		}

		private static void ZNet_Start_Postfix()
		{
			EnsureRegisteredRobust();
		}

		public static void EnsureRegisteredRobust()
		{
			if (!_registered)
			{
				if (ZRoutedRpc.instance != null)
				{
					EnsureRegisteredNow();
					return;
				}
				EnsureRegRunner();
				_regRunner.Kick();
			}
		}

		private static void EnsureRegRunner()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (!((Object)(object)_regRunner != (Object)null))
			{
				_regRunnerGo = GameObject.Find("NazhikaCore_BloodBurst_RegRunner");
				if ((Object)(object)_regRunnerGo == (Object)null)
				{
					_regRunnerGo = new GameObject("NazhikaCore_BloodBurst_RegRunner");
					Object.DontDestroyOnLoad((Object)(object)_regRunnerGo);
				}
				_regRunner = _regRunnerGo.GetComponent<RegRunner>();
				if ((Object)(object)_regRunner == (Object)null)
				{
					_regRunner = _regRunnerGo.AddComponent<RegRunner>();
				}
			}
		}

		private static void EnsureRegisteredNow()
		{
			if (!_registered && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.Register<Vector3>("NazhikaCore_BloodBurstFx", (Action<long, Vector3>)RPC_SpawnFx);
				ZRoutedRpc.instance.Register<ZDOID>("NazhikaCore_BloodBurst_Request", (Action<long, ZDOID>)RPC_RequestBurst);
				_registered = true;
				Debug.Log((object)"[NazhikaCore/BloodBurstNet] RPCs registrados: FX=NazhikaCore_BloodBurstFx, REQ=NazhikaCore_BloodBurst_Request");
			}
		}

		public static void RequestServerExecute(Character caster)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			EnsureRegisteredRobust();
			if (ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			ZDOID val = ZDOID.None;
			try
			{
				if ((Object)(object)caster != (Object)null && (Object)(object)caster.m_nview != (Object)null && caster.m_nview.IsValid())
				{
					ZDO zDO = caster.m_nview.GetZDO();
					if (zDO != null)
					{
						val = zDO.m_uid;
					}
				}
			}
			catch
			{
			}
			if (val == ZDOID.None)
			{
				Debug.LogWarning((object)"[NazhikaCore/BloodBurstNet] Request abort: caster ZDOID None");
				return;
			}
			long serverPeerID = ZRoutedRpc.instance.GetServerPeerID();
			ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerID, ZDOID.None, "NazhikaCore_BloodBurst_Request", new object[1] { val });
		}

		public static bool TryBroadcastFx(Vector3 pos)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			EnsureRegisteredRobust();
			if (ZRoutedRpc.instance == null)
			{
				return false;
			}
			try
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NazhikaCore_BloodBurstFx", new object[1] { pos });
				return true;
			}
			catch (Exception arg)
			{
				Debug.LogWarning((object)$"[NazhikaCore/BloodBurstNet] BroadcastFx ex: {arg}");
				return false;
			}
		}

		private static void RPC_RequestBurst(long sender, ZDOID casterZdo)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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)
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				Debug.Log((object)$"[NazhikaCore/BloodBurstNet] Server request sender={sender} casterZdo={casterZdo}");
				ZNetPeer peer = ZNet.instance.GetPeer(sender);
				if (peer == null)
				{
					Debug.LogWarning((object)$"[NazhikaCore/BloodBurstNet] Peer {sender} no encontrado");
					return;
				}
				Vector3 refPos = peer.m_refPos;
				Debug.Log((object)$"[NazhikaCore/BloodBurstNet] Ejecutando desde pos={refPos}");
				SE_BloodBurst.ExecuteServerAtPosition(refPos);
			}
		}

		private static void RPC_SpawnFx(long sender, Vector3 pos)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated())
			{
				BloodBurstFxFactory.SpawnAtRobust(pos);
			}
		}
	}
	internal static class BloodBurstFxFactory
	{
		private class FxRunner : MonoBehaviour
		{
			[CompilerGenerated]
			private sealed class <Loop>d__3 : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private object <>2__current;

				public FxRunner <>4__this;

				object IEnumerator<object>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <Loop>d__3(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_0026: Unknown result type (might be due to invalid IL or missing references)
					//IL_002b: Unknown result type (might be due to invalid IL or missing references)
					//IL_002e: Unknown result type (might be due to invalid IL or missing references)
					int num = <>1__state;
					FxRunner fxRunner = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						break;
					case 1:
						<>1__state = -1;
						break;
					}
					if (fxRunner._queue.Count > 0)
					{
						Vector3 pos = fxRunner._queue.Dequeue();
						<>2__current = fxRunner.SpawnWithRetry(pos);
						<>1__state = 1;
						return true;
					}
					fxRunner._running = false;
					return false;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			[CompilerGenerated]
			private sealed class <SpawnWithRetry>d__4 : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private object <>2__current;

				public Vector3 pos;

				private float <t>5__2;

				object IEnumerator<object>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <SpawnWithRetry>d__4(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_0028: Unknown result type (might be due to invalid IL or missing references)
					//IL_0032: Expected O, but got Unknown
					//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
					//IL_00bd: Expected O, but got Unknown
					//IL_006d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0072: Unknown result type (might be due to invalid IL or missing references)
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>2__current = (object)new WaitForSeconds(0.05f);
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -1;
						<t>5__2 = 0f;
						break;
					case 2:
						<>1__state = -1;
						break;
					}
					if (<t>5__2 < 3f)
					{
						if ((Object)(object)ZNetScene.instance != (Object)null)
						{
							GameObject vanillaPrefab = GetVanillaPrefab();
							if ((Object)(object)vanillaPrefab != (Object)null)
							{
								GameObject val = Object.Instantiate<GameObject>(vanillaPrefab, pos, Quaternion.identity);
								if ((Object)(object)val != (Object)null)
								{
									PruneAndScaleInstance(val);
									ForceActivate(val);
									val.SetActive(true);
									return false;
								}
							}
						}
						<t>5__2 += 0.1f;
						<>2__current = (object)new WaitForSeconds(0.1f);
						<>1__state = 2;
						return true;
					}
					return false;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			private readonly Queue<Vector3> _queue = new Queue<Vector3>();

			private bool _running;

			public void Enqueue(Vector3 pos)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				_queue.Enqueue(pos);
				if (!_running)
				{
					_running = true;
					((MonoBehaviour)this).StartCoroutine(Loop());
				}
			}

			[IteratorStateMachine(typeof(<Loop>d__3))]
			private IEnumerator Loop()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <Loop>d__3(0)
				{
					<>4__this = this
				};
			}

			[IteratorStateMachine(typeof(<SpawnWithRetry>d__4))]
			private IEnumerator SpawnWithRetry(Vector3 pos)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <SpawnWithRetry>d__4(0)
				{
					pos = pos
				};
			}
		}

		private const string VanillaFxName = "fx_CharredStone_Destruction";

		private static GameObject _vanillaPrefab;

		private static readonly string[] KeepKeywords = new string[3] { "skull", "smoke", "glow" };

		private static GameObject _runnerGo;

		private static FxRunner _runner;

		public static void SpawnAtRobust(Vector3 pos)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			EnsureRunner();
			_runner.Enqueue(pos);
		}

		private static void EnsureRunner()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (!((Object)(object)_runner != (Object)null))
			{
				_runnerGo = GameObject.Find("NazhikaCore_BloodBurst_FxRunner");
				if ((Object)(object)_runnerGo == (Object)null)
				{
					_runnerGo = new GameObject("NazhikaCore_BloodBurst_FxRunner");
					Object.DontDestroyOnLoad((Object)(object)_runnerGo);
				}
				_runner = _runnerGo.GetComponent<FxRunner>();
				if ((Object)(object)_runner == (Object)null)
				{
					_runner = _runnerGo.AddComponent<FxRunner>();
				}
			}
		}

		private static GameObject GetVanillaPrefab()
		{
			if ((Object)(object)_vanillaPrefab != (Object)null)
			{
				return _vanillaPrefab;
			}
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			_vanillaPrefab = ZNetScene.instance.GetPrefab("fx_CharredStone_Destruction");
			return _vanillaPrefab;
		}

		private static void PruneAndScaleInstance(GameObject fxInstance)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)fxInstance == (Object)null)
			{
				return;
			}
			int num = 0;
			Transform[] componentsInChildren = fxInstance.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && IsKeepName(((Object)val).name))
				{
					num++;
				}
			}
			if (num <= 0)
			{
				return;
			}
			DisableNonKeepBranches(fxInstance.transform);
			Transform[] componentsInChildren2 = fxInstance.GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null && IsKeepName(((Object)val2).name))
				{
					val2.localScale *= 0.5f;
				}
			}
		}

		private static void DisableNonKeepBranches(Transform root)
		{
			for (int i = 0; i < root.childCount; i++)
			{
				Transform child = root.GetChild(i);
				if (!((Object)(object)child == (Object)null) && !BranchHasKeep(child))
				{
					((Component)child).gameObject.SetActive(false);
				}
			}
		}

		private static bool BranchHasKeep(Transform t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return false;
			}
			if (IsKeepName(((Object)t).name))
			{
				return true;
			}
			for (int i = 0; i < t.childCount; i++)
			{
				if (BranchHasKeep(t.GetChild(i)))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsKeepName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			string text = name.ToLowerInvariant();
			for (int i = 0; i < KeepKeywords.Length; i++)
			{
				if (text.Contains(KeepKeywords[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static void ForceActivate(GameObject root)
		{
			//IL_0044: 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)
			if (Object.op_Implicit((Object)(object)root))
			{
				Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
				foreach (Transform val in componentsInChildren)
				{
					((Component)val).gameObject.SetActive(true);
				}
				ParticleSystem[] componentsInChildren2 = root.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val2 in componentsInChildren2)
				{
					EmissionModule emission = val2.emission;
					((EmissionModule)(ref emission)).enabled = true;
					val2.Clear(true);
					val2.Play(true);
				}
			}
		}
	}
	public static class SE_BloodBurstSetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_BloodBurst sE_BloodBurst = ScriptableObject.CreateInstance<SE_BloodBurst>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_BloodBurst, true);
			ItemManager.Instance.AddStatusEffect(val);
			BloodBurstNet.EnsureRegisteredRobust();
			Debug.Log((object)"[NazhikaCore] SE_BloodBurst registrado (ZDO detect bleeding; client->server request; FX Everybody).");
		}
	}
	public class SE_Curse : StatusEffect
	{
		private float tickTimer;

		private float fxTimer;

		private float damagePerTick = 5f;

		private float tickInterval = 2f;

		public SE_Curse()
		{
			((Object)this).name = "SE_Curse";
			base.m_name = "Curse";
			base.m_tooltip = "Estas maldito, el daño que haga se te devolvera.";
			base.m_icon = IconHelper.Load("curse.png");
			base.m_ttl = 5f;
		}

		public override void UpdateStatusEffect(float dt)
		{
		}
	}
	public static class SE_CurseSetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_Curse sE_Curse = ScriptableObject.CreateInstance<SE_Curse>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_Curse, true);
			ItemManager.Instance.AddStatusEffect(val);
			Debug.Log((object)"[NazhikaCore] SE_Curse registrado correctamente.");
		}
	}
	public class SE_FocusShot : StatusEffect
	{
		public const string InternalName = "SE_FocusShot";

		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_FocusShot");

		public const string ZdoKeyActive = "focusshot_active";

		private Character _ch;

		public SE_FocusShot()
		{
			((Object)this).name = "SE_FocusShot";
			base.m_name = "Focus Shot";
			base.m_icon = IconHelper.Load("focusshot.png");
			base.m_ttl = 15f;
			base.m_tooltip = "Concentración del arquero: más daño al próximo disparo de arco.";
		}

		public override void Setup(Character character)
		{
			((StatusEffect)this).Setup(character);
			_ch = character;
			Player val = (Player)(object)((character is Player) ? character : null);
			if ((Object)(object)val != (Object)null)
			{
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null && component.IsOwner())
				{
					component.GetZDO().Set("focusshot_active", 1);
					Debug.Log((object)("[SE_FocusShot] ZDO flag set → focusshot_active=1 para " + val.GetPlayerName()));
				}
			}
		}

		public override void UpdateStatusEffect(float dt)
		{
			((StatusEffect)this).UpdateStatusEffect(dt);
			base.m_tooltip = "Focus Shot activo (" + Mathf.CeilToInt(GetRemainingTTL()) + "s)";
		}

		public override void Stop()
		{
			Character ch = _ch;
			Player val = (Player)(object)((ch is Player) ? ch : null);
			if ((Object)(object)val != (Object)null)
			{
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null && component.IsOwner())
				{
					component.GetZDO().Set("focusshot_active", 0);
					Debug.Log((object)("[SE_FocusShot] ZDO flag cleared → focusshot_active=0 para " + val.GetPlayerName()));
				}
				long playerID = val.GetPlayerID();
				FocusShotRuntime.RaiseFocusRemoved(playerID);
				PlayerClassBase @class = ClassManager.GetClass(val);
				if (@class != null)
				{
					@class.TryBeginCooldown(val);
					SkillsUI.StartCooldown(@class.CooldownSeconds);
					Log.Info($"[SE_FocusShot] Buff terminado → cooldown de {@class.CooldownSeconds}s iniciado para {val.GetPlayerName()}");
				}
			}
			((StatusEffect)this).Stop();
		}

		private float GetRemainingTTL()
		{
			return Mathf.Max(0f, base.m_ttl - base.m_time);
		}
	}
	public static class SE_FocusShotSetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_FocusShot sE_FocusShot = ScriptableObject.CreateInstance<SE_FocusShot>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_FocusShot, true);
			ItemManager.Instance.AddStatusEffect(val);
			Debug.Log((object)"[NazhikaCore] ✅ SE_FocusShot registrado en Jotunn");
		}
	}
	public static class FocusShotRuntime
	{
		public static event Action<long> FocusRemoved;

		public static void RaiseFocusRemoved(long playerId)
		{
			try
			{
				if (FocusShotRuntime.FocusRemoved != null)
				{
					FocusShotRuntime.FocusRemoved(playerId);
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[FocusShot] FocusRemoved event error: " + ex));
			}
		}
	}
	public class SE_LavaRocks : StatusEffect
	{
		private class NoDamageCleaner : MonoBehaviour
		{
			private GameObject _root;

			private int _frames;

			public void Run(GameObject r, int frames)
			{
				_root = r;
				_frames = frames;
			}

			private void LateUpdate()
			{
				if ((Object)(object)_root == (Object)null)
				{
					Object.Destroy((Object)(object)this);
					return;
				}
				CleanOnce(_root);
				if (--_frames <= 0)
				{
					Object.Destroy((Object)(object)this);
				}
			}
		}

		public const string InternalName = "SE_LavaRocks";

		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_LavaRocks");

		private const KeyCode ToggleKey = 57;

		private const string LavaRockPrefabName = "LavaRock";

		private const int RocksCount = 4;

		private const float CircleYOffset = 0.06f;

		private const float SymbolWorldSize = 6f;

		private static readonly Vector3 MarkerScale = Vector3.one;

		private const string MarkerTextureFile = "sealSymbol3.png";

		private const float SpawnRadius = 6f;

		private const float SpawnYOffset = 0.15f;

		private const float MinCenterDistance = 0.9f;

		private Character _ch;

		private GameObject _marker;

		private GameObject _symbol;

		private bool _spawnReadyShown;

		public SE_LavaRocks()
		{
			((Object)this).name = "SE_LavaRocks";
			base.m_name = "Lava Rocks";
			base.m_icon = IconHelper.Load("LavaRocks.png");
			base.m_tooltip = "Apunta y haz clic derecho para invocar rocas de lava. Esc: cancelar.";
			base.m_ttl = 8f;
		}

		public override void Setup(Character character)
		{
			((StatusEffect)this).Setup(character);
			_ch = character;
			Character ch = _ch;
			Player val = (Player)(object)((ch is Player) ? ch : null);
			if (val != null && (Object)(object)Player.m_localPlayer == (Object)(object)val)
			{
				EnsureMarker(val);
				_marker.SetActive(true);
				SnapMarkerToMouse();
				_spawnReadyShown = true;
			}
		}

		public override void UpdateStatusEffect(float dt)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			((StatusEffect)this).UpdateStatusEffect(dt);
			base.m_tooltip = $"Lava Rocks ({Mathf.CeilToInt(Mathf.Max(0f, base.m_ttl - base.m_time))}s) — RMB: rocas, LMB/Esc: cancelar";
			Character ch = _ch;
			Player val = (Player)(object)((ch is Player) ? ch : null);
			if (val == null || (Object)(object)Player.m_localPlayer != (Object)(object)val)
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)57))
			{
				EnsureMarker(val);
				_marker.SetActive(!_marker.activeSelf);
			}
			if ((Object)(object)_marker == (Object)null)
			{
				return;
			}
			if (_marker.activeSelf)
			{
				if (Input.GetMouseButtonDown(0) || Input.GetKeyDown((KeyCode)27))
				{
					_marker.SetActive(false);
					return;
				}
				SnapMarkerToMouse();
				if (Input.GetMouseButtonDown(1))
				{
					if ((Object)(object)((Character)val).m_nview != (Object)null && ((Character)val).m_nview.IsValid())
					{
						((Character)val).m_nview.InvokeRPC(ZNetView.Everybody, "RPC_Nazhika_PlayCheer", Array.Empty<object>());
					}
					Vector3 position = _marker.transform.position;
					SpawnLavaRocks(position, 6f, 4);
					_marker.SetActive(false);
					base.m_time = base.m_ttl;
				}
			}
			else if (!_spawnReadyShown)
			{
				EnsureMarker(val);
				_marker.SetActive(true);
				SnapMarkerToMouse();
				_spawnReadyShown = true;
			}
		}

		public override void Stop()
		{
			((StatusEffect)this).Stop();
			Character character = base.m_character;
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null)
			{
				PlayerClassBase @class = ClassManager.GetClass(val);
				if (@class != null)
				{
					@class.TryBeginCooldown(val);
					SkillsUI.StartCooldown(@class.CooldownSeconds);
				}
			}
			try
			{
				if ((Object)(object)_marker != (Object)null)
				{
					Object.Destroy((Object)(object)_marker);
				}
				_marker = null;
				_symbol = null;
			}
			catch
			{
			}
		}

		private void EnsureMarker(Player owner)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			if ((Object)(object)_marker != (Object)null)
			{
				return;
			}
			_marker = new GameObject("LavaRocksMarker_SE");
			_marker.transform.position = ((Component)owner).transform.position;
			_marker.transform.localScale = MarkerScale;
			_marker.SetActive(false);
			_symbol = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)_symbol).name = "SealSymbol3";
			_symbol.transform.SetParent(_marker.transform, false);
			_symbol.transform.localPosition = new Vector3(0f, 0.06f, 0f);
			_symbol.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f);
			_symbol.transform.localScale = Vector3.one * 6f;
			Renderer component = _symbol.GetComponent<Renderer>();
			Shader val = TryFindShader("Unlit/Transparent", "Sprites/Default", "Legacy Shaders/Transparent/Diffuse", "Particles/Standard Unlit", "Standard");
			if ((Object)(object)component != (Object)null && (Object)(object)val != (Object)null)
			{
				Material val2 = new Material(val);
				val2.mainTexture = (Texture)(object)LoadTexture_NoRef("sealSymbol3.png");
				val2.renderQueue = 3000;
				try
				{
					if (val2.HasProperty("_Cull"))
					{
						val2.SetInt("_Cull", 0);
					}
				}
				catch
				{
				}
				component.material = val2;
			}
			Collider component2 = _symbol.GetComponent<Collider>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
		}

		private void SnapMarkerToMouse()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			Camera gameCamera = GetGameCamera();
			if (!((Object)(object)gameCamera == (Object)null) && !((Object)(object)_marker == (Object)null))
			{
				Ray val = gameCamera.ScreenPointToRay(Input.mousePosition);
				RaycastHit val2 = default(RaycastHit);
				if (Physics.Raycast(val, ref val2, 500f, -1, (QueryTriggerInteraction)1))
				{
					Vector3 point = ((RaycastHit)(ref val2)).point;
					point.y += 0.06f;
					_marker.transform.position = point;
				}
			}
		}

		private static void SpawnLavaRocks(Vector3 center, float radius, int count)
		{
			//IL_0039: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0080: 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_0055: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("LavaRock");
			if ((Object)(object)prefab == (Object)null)
			{
				Debug.LogWarning((object)"[SE_LavaRocks] Prefab no encontrado: \"LavaRock\"");
				return;
			}
			Vector3 val2 = default(Vector3);
			for (int i = 0; i < count; i++)
			{
				Vector2 val = Random.insideUnitCircle * radius;
				if (((Vector2)(ref val)).magnitude < 0.9f)
				{
					val = ((Vector2)(ref val)).normalized * 0.9f;
				}
				((Vector3)(ref val2))..ctor(center.x + val.x, center.y, center.z + val.y);
				if (TrySnapToGround(val2, out var snapped))
				{
					val2 = snapped;
				}
				val2.y += 0.15f;
				Quaternion val3 = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
				GameObject root = Object.Instantiate<GameObject>(prefab, val2, val3);
				NukeDamageComponents(root);
			}
		}

		private static bool TrySnapToGround(Vector3 near, out Vector3 snapped)
		{
			//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)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			snapped = near;
			Vector3 val = near + Vector3.up * 25f;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(val, Vector3.down, ref val2, 80f, -1, (QueryTriggerInteraction)1))
			{
				snapped = ((RaycastHit)(ref val2)).point;
				return true;
			}
			return false;
		}

		private static void NukeDamageComponents(GameObject root)
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				CleanOnce(root);
				NoDamageCleaner noDamageCleaner = root.AddComponent<NoDamageCleaner>();
				noDamageCleaner.Run(root, 6);
			}
		}

		private static void CleanOnce(GameObject root)
		{
			//IL_001f: 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)
			try
			{
				Aoe[] componentsInChildren = root.GetComponentsInChildren<Aoe>(true);
				foreach (Aoe val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null))
					{
						val.m_damage = default(DamageTypes);
						((Behaviour)val).enabled = false;
					}
				}
				Projectile[] componentsInChildren2 = root.GetComponentsInChildren<Projectile>(true);
				foreach (Projectile val2 in componentsInChildren2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						val2.m_damage = default(DamageTypes);
						((Behaviour)val2).enabled = false;
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[SE_LavaRocks] CleanOnce error: " + ex.Message));
			}
		}

		private static Camera GetGameCamera()
		{
			if ((Object)(object)GameCamera.instance?.m_camera != (Object)null)
			{
				return GameCamera.instance.m_camera;
			}
			return Camera.main;
		}

		private static Shader TryFindShader(params string[] names)
		{
			foreach (string text in names)
			{
				Shader val = Shader.Find(text);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static Texture2D LoadTexture_NoRef(string fileName)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			string text = Path.Combine(Paths.PluginPath, "NazhikaCore", "Assets", "Images", fileName);
			if (!File.Exists(text))
			{
				Debug.LogWarning((object)("[SE_LavaRocks] PNG no encontrado: " + text));
				return Texture2D.whiteTexture;
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			try
			{
				MethodInfo methodInfo = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[3]
				{
					typeof(Texture2D),
					typeof(byte[]),
					typeof(bool)
				});
				if (methodInfo != null && (bool)methodInfo.Invoke(null, new object[3] { val, array, false }))
				{
					return val;
				}
			}
			catch
			{
			}
			return Texture2D.whiteTexture;
		}
	}
	public static class SE_LavaRocksSetup
	{
		public static void Init()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			SE_LavaRocks sE_LavaRocks = ScriptableObject.CreateInstance<SE_LavaRocks>();
			ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)sE_LavaRocks, true));
			Debug.Log((object)"[NazhikaCore] ✅ SE_LavaRocks registrado en Jotunn");
		}
	}
	public class SE_LightningStorm : StatusEffect
	{
		private class NoDamageCleaner : MonoBehaviour
		{
			private GameObject _root;

			private int _frames;

			public void Run(GameObject r, int frames)
			{
				_root = r;
				_frames = frames;
			}

			private void LateUpdate()
			{
				if ((Object)(object)_root == (Object)null)
				{
					Object.Destroy((Object)(object)this);
					return;
				}
				CleanOnce(_root);
				_frames--;
				if (_frames <= 0)
				{
					Object.Destroy((Object)(object)this);
				}
			}
		}

		public const string InternalName = "SE_LightningStorm";

		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_LightningStorm");

		private const KeyCode ToggleKey = 57;

		private const string LightningPrefabName = "lightningAOE";

		private const float CircleYOffset = 0.06f;

		private const float SymbolWorldSize = 3.5f;

		private static readonly Vector3 MarkerScale = Vector3.one;

		private const float ImmobilizeRadius = 5f;

		private const float ImmobilizeCenterBonus = 0f;

		private const string ImmobilizedName = "ImmobilizedLong";

		private static readonly int ImmobilizedHash = StringExtensionMethods.GetStableHashCode("ImmobilizedLong");

		private Character _ch;

		private GameObject _marker;

		private GameObject _symbol;

		private bool _spawnReadyShown;

		public SE_LightningStorm()
		{
			((Object)this).name = "SE_LightningStorm";
			base.m_name = "Lightning Storm";
			base.m_icon = IconHelper.Load("LightningStorm.png");
			base.m_tooltip = "Apunta y haz clic derecho para invocar rayos. Esc: cancelar.";
			base.m_ttl = 20f;
		}

		public override void Setup(Character character)
		{
			((StatusEffect)this).Setup(character);
			_ch = character;
			Character ch = _ch;
			Player val = (Player)(object)((ch is Player) ? ch : null);
			if (val != null && (Object)(object)Player.m_localPlayer == (Object)(object)val)
			{
				EnsureMarker(val);
				_marker.SetActive(true);
				SnapMarkerToMouse();
				_spawnReadyShown = true;
			}
		}

		public override void UpdateStatusEffect(float dt)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			((StatusEffect)this).UpdateStatusEffect(dt);
			base.m_tooltip = $"Lightning Storm ({Mathf.CeilToInt(Mathf.Max(0f, base.m_ttl - base.m_time))}s) — RMB: rayos, LMB/Esc: cancelar";
			Character ch = _ch;
			Player val = (Player)(object)((ch is Player) ? ch : null);
			if (val == null || (Object)(object)Player.m_localPlayer != (Object)(object)val)
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)57))
			{
				EnsureMarker(val);
				_marker.SetActive(!_marker.activeSelf);
			}
			if ((Object)(object)_marker == (Object)null)
			{
				return;
			}
			if (_marker.activeSelf)
			{
				if (Input.GetMouseButtonDown(0) || Input.GetKeyDown((KeyCode)27))
				{
					_marker.SetActive(false);
					return;
				}
				SnapMarkerToMouse();
				if (Input.GetMouseButtonDown(1))
				{
					if ((Object)(object)((Character)val).m_nview != (Object)null && ((Character)val).m_nview.IsValid())
					{
						((Character)val).m_nview.InvokeRPC(ZNetView.Everybody, "RPC_Nazhika_PlayCheer", Array.Empty<object>());
					}
					Vector3 position = _marker.transform.position;
					SpawnLightningBurst(position);
					_marker.SetActive(false);
					base.m_time = base.m_ttl;
				}
			}
			else if (!_spawnReadyShown)
			{
				EnsureMarker(val);
				_marker.SetActive(true);
				SnapMarkerToMouse();
				_spawnReadyShown = true;
			}
		}

		public override void Stop()
		{
			((StatusEffect)this).Stop();
			Character character = base.m_character;
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null)
			{
				PlayerClassBase @class = ClassManager.GetClass(val);
				if (@class != null)
				{
					@class.TryBeginCooldown(val);
					SkillsUI.StartCooldown(@class.CooldownSeconds);
				}
			}
			try
			{
				if ((Object)(object)_marker != (Object)null)
				{
					Object.Destroy((Object)(object)_marker);
				}
				_marker = null;
				_symbol = null;
			}
			catch
			{
			}
		}

		private void EnsureMarker(Player owner)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			if ((Object)(object)_marker != (Object)null)
			{
				return;
			}
			_marker = new GameObject("LightningMarker_SE");
			_marker.transform.position = ((Component)owner).transform.position;
			_marker.transform.localScale = MarkerScale;
			_marker.SetActive(false);
			_symbol = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)_symbol).name = "SealSymbol";
			_symbol.transform.SetParent(_marker.transform, false);
			_symbol.transform.localPosition = new Vector3(0f, 0.06f, 0f);
			_symbol.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f);
			_symbol.transform.localScale = Vector3.one * 3.5f;
			Renderer component = _symbol.GetComponent<Renderer>();
			Shader val = TryFindShader("Unlit/Transparent", "Sprites/Default", "Legacy Shaders/Transparent/Diffuse", "Legacy Shaders/Particles/Alpha Blended", "Particles/Standard Unlit", "Standard");
			Material val2 = (Material)((!((Object)(object)val != (Object)null)) ? ((object)(((Object)(object)component != (Object)null) ? (component.material ?? component.sharedMaterial) : null)) : ((object)new Material(val)));
			if ((Object)(object)val2 != (Object)null)
			{
				try
				{
					if (val2.HasProperty("_Cull"))
					{
						val2.SetInt("_Cull", 0);
					}
				}
				catch
				{
				}
				try
				{
					val2.renderQueue = 3000;
				}
				catch
				{
				}
				val2.mainTexture = (Texture)(object)LoadTexture_NoRef("sealSymbol2.png");
				component.material = val2;
			}
			Collider component2 = _symbol.GetComponent<Collider>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
		}

		private void SnapMarkerToMouse()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Camera gameCamera = GetGameCamera();
			if (!((Object)(object)gameCamera == (Object)null) && !((Object)(object)_marker == (Object)null))
			{
				Ray val = gameCamera.ScreenPointToRay(Input.mousePosition);
				RaycastHit val2 = default(RaycastHit);
				if (Physics.Raycast(val, ref val2, 500f, -1, (QueryTriggerInteraction)1))
				{
					Vector3 point = ((RaycastHit)(ref val2)).point;
					point.y = ((RaycastHit)(ref val2)).point.y + 0.06f;
					_marker.transform.position = point;
				}
			}
		}

		private void SpawnLightningBurst(Vector3 center)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//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_004e: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("lightningAOE");
			if ((Object)(object)prefab == (Object)null)
			{
				Debug.LogWarning((object)"[SE_LightningStorm] Prefab no encontrado: \"lightningAOE\"");
				return;
			}
			for (int i = 0; i < 4; i++)
			{
				Vector3 val = center + Random.insideUnitSphere * 4f;
				val.y = center.y;
				GameObject root = Object.Instantiate<GameObject>(prefab, val, Quaternion.identity);
				NukeDamageComponents(root);
				ApplyImmobilizedInRadius(val, 5f);
			}
		}

		private static void TryApplyImmobilized(Character ch)
		{
			if (!((Object)(object)ch == (Object)null) && !ch.IsDead() && !ch.IsPlayer())
			{
				SEMan sEMan = ch.GetSEMan();
				if (sEMan != null && !sEMan.HaveStatusEffect(ImmobilizedHash))
				{
					sEMan.AddStatusEffect(ImmobilizedHash, false, 0, 0f);
				}
			}
		}

		private static void ApplyImmobilizedInRadius(Vector3 center, float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(center, radius, -1, (QueryTriggerInteraction)1);
			if (array == null || array.Length == 0)
			{
				return;
			}
			Vector3 val2 = default(Vector3);
			foreach (Collider val in array)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				Character componentInParent = ((Component)val).GetComponentInParent<Character>();
				if (!((Object)(object)componentInParent == (Object)null))
				{
					Vector3 position = ((Component)componentInParent).transform.position;
					((Vector3)(ref val2))..ctor(center.x, position.y, center.z);
					if (!(Vector3.Distance(position, val2) > radius + 0.15f))
					{
						TryApplyImmobilized(componentInParent);
					}
				}
			}
		}

		private static void NukeDamageComponents(GameObject root)
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				CleanOnce(root);
				NoDamageCleaner noDamageCleaner = root.AddComponent<NoDamageCleaner>();
				noDamageCleaner.Run(root, 6);
			}
		}

		private static void CleanOnce(GameObject root)
		{
			//IL_001f: 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)
			try
			{
				Aoe[] componentsInChildren = root.GetComponentsInChildren<Aoe>(true);
				foreach (Aoe val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null))
					{
						val.m_damage = default(DamageTypes);
						((Behaviour)val).enabled = false;
					}
				}
				Projectile[] componentsInChildren2 = root.GetComponentsInChildren<Projectile>(true);
				foreach (Projectile val2 in componentsInChildren2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						val2.m_damage = default(DamageTypes);
						((Behaviour)val2).enabled = false;
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[SE_LightningStorm] CleanOnce error: " + ex.Message));
			}
		}

		private static Camera GetGameCamera()
		{
			if ((Object)(object)GameCamera.instance?.m_camera != (Object)null)
			{
				return GameCamera.instance.m_camera;
			}
			return Camera.main;
		}

		private static Shader TryFindShader(params string[] names)
		{
			foreach (string text in names)
			{
				Shader val = Shader.Find(text);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static Texture2D LoadTexture_NoRef(string fileName)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			string text = Path.Combine(Paths.PluginPath, "NazhikaCore", "Assets", "Images", fileName);
			if (!File.Exists(text))
			{
				Debug.LogWarning((object)("[SE_LightningStorm] PNG no encontrado: " + text));
				return Texture2D.whiteTexture;
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			try
			{
				MethodInfo methodInfo = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[3]
				{
					typeof(Texture2D),
					typeof(byte[]),
					typeof(bool)
				});
				if (methodInfo != null && (bool)methodInfo.Invoke(null, new object[3] { val, array, false }))
				{
					return val;
				}
			}
			catch
			{
			}
			return Texture2D.whiteTexture;
		}
	}
	public static class SE_LightningStormSetup
	{
		public static void Init()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			SE_LightningStorm sE_LightningStorm = ScriptableObject.CreateInstance<SE_LightningStorm>();
			CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)sE_LightningStorm, true);
			ItemManager.Instance.AddStatusEffect(val);
			Debug.Log((object)"[NazhikaCore] ✅ SE_LightningStorm registrado en Jotunn");
		}
	}
	public class SE_MagicRoots : StatusEffect
	{
		private class NoDamageCleaner : MonoBehaviour
		{
			private GameObject _root;

			private int _frames;

			public void Run(GameObject r, int frames)
			{
				_root = r;
				_frames = frames;
			}

			private void LateUpdate()
			{
				if ((Object)(object)_root == (Object)null)
				{
					Object.Destroy((Object)(object)this);
					return;
				}
				CleanOnce(_root);
				if (--_frames <= 0)
				{
					Object.Destroy((Object)(object)this);
				}
			}
		}

		public const string InternalName = "SE_MagicRoots";

		public static readonly int NameHash = StringExtensionMethods.GetStableHashCode("SE_MagicRoots");

		private const KeyCode ToggleKey = 57;

		private const string RootFxPrefab = "fx_RootAshlands";

		private const float CircleYOffset = 0.06f;

		private const float SymbolWorldSize = 12f;

		private static readonly Vector3 MarkerScale = Vector3.one;

		private const float ImmobilizeRadius = 8f;

		private const float ImmobilizeDuration = 10f;

		private const string ImmobilizedName = "ImmobilizedLong";

		private static readonly int ImmobilizedHash = StringExtensionMethods.GetStableHashCode("ImmobilizedLong");

		private static readonly int MagicRootsFxHash = SE_MagicRootsFX_Target.NameHash;

		private Character _ch;

		private GameObject _marker;

		private GameObject _symbol;

		private bool _spawnReadyShown;

		public SE_MagicRoots()
		{
			((Object)this).name = "SE_MagicRoots";
			base.m_name = "Magic Roots";
			base.m_icon = IconHelper.Load("MagicRoots.png");
			base.m_tooltip = "Apunta y haz clic derecho para invocar raíces. Esc: cancelar.";
			base.m_ttl = 5f;
		}

		public override void Setup(Character character)
		{
			((StatusEffect)this).Setup(character);
			_ch = character;
			Character ch = _ch;
			Player val = (Player)(object)((ch is Player) ? ch : null);
			if (val != null && (Object)(object)Player.m_localPlayer == (Object)(object)val)
			{
				EnsureMarker(val);
				_marker.SetActive(true);
				SnapMarkerToMouse();
				_spawnReadyShown = true;
			}
		}

		public override void UpdateStatusEffect(float dt)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			((StatusEffect)this).UpdateStatusEffect(dt);
			base.m_tooltip = $"Magic Roots ({Mathf.CeilToInt(Mathf.Max(0f, base.m_ttl - base.m_time))}s) — RMB: raíces, LMB/Esc: cancelar";
			Character ch = _ch;
			Player val = (Player)(object)((ch is Player) ? ch : null);
			if (val == null || (Object)(object)Player.m_localPlayer != (Object)(object)val)
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)57))
			{
				EnsureMarker(val);
				_marker.SetActive(!_marker.activeSelf);
			}
			if ((Object)(object)_marker == (Object)null)
			{
				return;
			}
			if (_marker.activeSelf)
			{
				if (Input.GetMouseButtonDown(0) || Input.GetKeyDown((KeyCode)27))
				{
					_marker.SetActive(false);
					return;
				}
				SnapMarkerToMouse();
				if (Input.GetMouseButtonDown(1))
				{
					if ((Object)(object)((Character)val).m_nview != (Object)null && ((Character)val).m_nview.IsValid())
					{
						((Character)val).m_nview.InvokeRPC(ZNetView.Everybody, "RPC_Nazhika_PlayCheer", Array.Empty<object>());
					}
					Vector3 position = _marker.transform.position;
					SpawnRoots(position);
					_marker.SetActive(false);
					base.m_time = base.m_ttl;
				}
			}
			else if (!_spawnReadyShown)
			{
				EnsureMarker(val);
				_marker.SetActive(true);
				SnapMarkerToMouse();
				_spawnReadyShown = true;
			}
		}

		public override void Stop()
		{
			((StatusEffect)this).Stop();
			Character character = base.m_character;
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null)
			{
				PlayerClassBase @class = ClassManager.GetClass(val);
				if (@class != null)
				{
					@class.TryBeginCooldown(val);
					SkillsUI.StartCooldown(@class.CooldownSeconds);
				}
			}
			try
			{
				if ((Object)(object)_marker != (Object)null)
				{
					Object.Destroy((Object)(object)_marker);
				}
				_marker = null;
				_symbol = null;
			}
			catch
			{
			}
		}

		private void EnsureMarker(Player owner)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			if (!((Object)(object)_marker != (Object)null))
			{
				_marker = new GameObject("MagicRootsMarker_SE");
				_marker.transform.position = ((Component)owner).transform.position;
				_marker.transform.localScale = MarkerScale;
				_marker.SetActive(false);
				_symbol = GameObject.CreatePrimitive((PrimitiveType)5);
				((Object)_symbol).name = "RootSymbol";
				_symbol.transform.SetParent(_marker.transform, false);
				_symbol.transform.localPosition = new Vector3(0f, 0.06f, 0f);
				_symbol.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f);
				_symbol.transform.localScale = Vector3.one * 12f;
				Renderer component = _symbol.GetComponent<Renderer>();
				Shader val = TryFindShader("Unlit/Transparent", "Sprites/Default", "Legacy Shaders/Transparent/Diffuse", "Particles/Standard Unlit", "Standard");
				if ((Object)(object)component != (Object)null && (Object)(object)val != (Object)null)
				{
					Material val2 = new Material(val);
					val2.mainTexture = (Texture)(object)LoadTexture_NoRef("sealSymbol2.png");
					val2.renderQueue = 3000;
					component.material = val2;
				}
				Collider component2 = _symbol.GetComponent<Collider>();
				if ((Object)(object)component2 != (Object)null)
				{
					Object.Destroy((Object)(object)component2);
				}
			}
		}

		private void SnapMarkerToMouse()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			Camera gameCamera = GetGameCamera();
			if (!((Object)(object)gameCamera == (Object)null) && !((Object)(object)_marker == (Object)null))
			{
				Ray val = gameCamera.ScreenPointToRay(Input.mousePosition);
				RaycastHit val2 = default(RaycastHit);
				if (Physics.Raycast(val, ref val2, 500f, -1, (QueryTriggerInteraction)1))
				{
					Vector3 point = ((RaycastHit)(ref val2)).point;
					point.y += 0.06f;
					_marker.transform.position = point;
				}
			}
		}

		private void SpawnRoots(Vector3 center)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (m

Profesiones.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Managers;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Profesiones")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Profesiones")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("50CF68F9-AA2B-4F41-B995-4C2EB29C4A19")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace EinjarheimProfessions;

[BepInPlugin("nazhi.einjarheim.professions", "Einjarheim Professions", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInProcess("valheim.exe")]
public class EinjarheimProfessionsPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "nazhi.einjarheim.professions";

	public const string PluginName = "Einjarheim Professions";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Log;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"[Einjarheim Professions] v1.0.0 – iniciando...");
		BlacksmithingSystem.RegisterSkill();
		AlchemySystem.RegisterSkill();
		_harmony = new Harmony("nazhi.einjarheim.professions");
		_harmony.PatchAll();
		Log.LogInfo((object)"[Einjarheim Professions] Profesiones cargadas:");
		Log.LogInfo((object)"[Einjarheim Professions]   · Cooking       – bonus HP/Stamina/Eitr según nivel de cocina del chef");
		Log.LogInfo((object)"[Einjarheim Professions]   · Blacksmithing – durabilidad, daño y armadura según nivel de herrería");
		Log.LogInfo((object)"[Einjarheim Professions]   · Construction  – HP de estructuras y descuento de recursos según Crafting");
		Log.LogInfo((object)"[Einjarheim Professions]   · Alchemy       – potencia, duración y fermentación según nivel de alquimia");
	}

	private void OnDestroy()
	{
		ManualLogSource log = Log;
		if (log != null)
		{
			log.LogInfo((object)"[Einjarheim Professions] OnDestroy – deshaciendo patches.");
		}
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}
}
internal static class AlchemySystem
{
	public const string SkillIdentifier = "nazhi.alchemist";

	private static SkillType s_skillType;

	private const float XP_PotionConsumed = 1f;

	private const float XP_PotionCrafted = 2f;

	private const float BasePowerBonus = 0.1f;

	private const float PowerPerLevel = 0.003f;

	private const float MaxPowerBonus = 0.4f;

	private const float BaseDurationBonus = 0.2f;

	private const float DurationPerLevel = 0.005f;

	private const float MaxDurationBonus = 0.7f;

	private const float BaseExtraChance = 0.15f;

	private const float ExtraChancePerLevel = 0.0015f;

	private const float MaxExtraChance = 0.3f;

	private const float BaseCooldownReduction = 0.1f;

	private const float CooldownReductionPerLevel = 0.002f;

	private const float MaxCooldownReduction = 0.3f;

	private const float BaseFermentReduction = 0.2f;

	private const float FermentReductionPerLevel = 0.004f;

	private const float MaxFermentReduction = 0.6f;

	private static bool _minLevelApplied;

	internal static SkillType SkillType => s_skillType;

	internal static void ResetMinLevelFlag()
	{
		_minLevelApplied = false;
	}

	internal static void RegisterSkill()
	{
		//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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: 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_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		SkillConfig val = new SkillConfig
		{
			Identifier = "nazhi.alchemist",
			Name = "Alquimista",
			Description = "$skill_alchemist_desc",
			Icon = null,
			IncreaseStep = 1f
		};
		s_skillType = SkillManager.Instance.AddSkill(val);
		EinjarheimProfessionsPlugin.Log.LogInfo((object)string.Format("[Alchemy] Skill registrada: {0} ({1})", "nazhi.alchemist", s_skillType));
	}

	internal static void AddExperience(Player player, float amount)
	{
		//IL_000a: 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)
		if (!((Object)(object)player == (Object)null) && (int)s_skillType != 0 && !(amount <= 0f) && !((Object)(object)((Character)player).m_nview == (Object)null) && ((Character)player).m_nview.IsOwner())
		{
			((Character)player).RaiseSkill(s_skillType, amount);
		}
	}

	internal static void OnPotionConsumed(Player player)
	{
		AddExperience(player, 1f);
	}

	internal static void OnPotionCrafted(Player player)
	{
		AddExperience(player, 2f);
	}

	internal static float GetLevel(Player player)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return 0f;
		}
		return ((Character)player).GetSkillLevel(s_skillType);
	}

	internal static float GetPotionPowerMultiplier(Player player)
	{
		float num = 0.1f + 0.003f * GetLevel(player);
		return 1f + Mathf.Clamp(num, 0.1f, 0.4f);
	}

	internal static float GetPotionDurationMultiplier(Player player)
	{
		float num = 0.2f + 0.005f * GetLevel(player);
		return 1f + Mathf.Clamp(num, 0.2f, 0.7f);
	}

	internal static float GetExtraPotionChance(Player player)
	{
		float num = 0.15f + 0.0015f * GetLevel(player);
		return Mathf.Clamp(num, 0.15f, 0.3f);
	}

	internal static float GetPotionCooldownMultiplier(Player player)
	{
		float num = 0.1f + 0.002f * GetLevel(player);
		return 1f - Mathf.Clamp(num, 0.1f, 0.3f);
	}

	internal static float GetFermentationReduction(Player player)
	{
		float num = 0.2f + 0.004f * GetLevel(player);
		return Mathf.Clamp(num, 0f, 0.6f);
	}

	internal static float GetFermentationTimeMultiplier(Player player)
	{
		return 1f - GetFermentationReduction(player);
	}

	internal static bool RollExtraPotion(Player player)
	{
		return Random.value <= GetExtraPotionChance(player);
	}

	internal static void EnsureMinLevel(Player player)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Invalid comparison between Unknown and I4
		//IL_0027: 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)
		if (!_minLevelApplied && !((Object)(object)player == (Object)null) && (int)s_skillType != 0)
		{
			if (((Character)player).GetSkillLevel(s_skillType) < 1f)
			{
				((Character)player).RaiseSkill(s_skillType, 0.5f);
				EinjarheimProfessionsPlugin.Log.LogInfo((object)"[Alchemy] Nivel inicial de Alquimia establecido a 1.");
			}
			_minLevelApplied = true;
		}
	}
}
internal static class AlchemyPotionUtils
{
	internal static bool IsPotion(ItemData item)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Invalid comparison between Unknown and I4
		if (item?.m_shared == null)
		{
			return false;
		}
		if ((int)item.m_shared.m_itemType != 2)
		{
			return false;
		}
		return (Object)(object)item.m_shared.m_consumeStatusEffect != (Object)null;
	}

	internal static bool IsMeadBase(ItemData item)
	{
		if (item?.m_shared == null)
		{
			return false;
		}
		string text = item.m_shared.m_name.ToLowerInvariant();
		return text.Contains("item_meadbase") || text.Contains("meadbase") || text.Contains("mead_base") || (text.Contains("ketill") && (text.Contains("mead") || text.Contains("base")));
	}

	internal static bool IsFinalMead(ItemData item)
	{
		if (item?.m_shared == null)
		{
			return false;
		}
		string text = item.m_shared.m_name.ToLowerInvariant();
		return text.Contains("item_mead_") || (text.Contains("mead") && !text.Contains("meadbase"));
	}
}
internal static class AlchemyStatsApplier
{
	internal static void ApplyPowerAndDuration(Player player, SE_Stats stats)
	{
		if (!((Object)(object)player == (Object)null) && !((Object)(object)stats == (Object)null))
		{
			float potionDurationMultiplier = AlchemySystem.GetPotionDurationMultiplier(player);
			float potionPowerMultiplier = AlchemySystem.GetPotionPowerMultiplier(player);
			if (((StatusEffect)stats).m_ttl > 0f)
			{
				((StatusEffect)stats).m_ttl = ((StatusEffect)stats).m_ttl * potionDurationMultiplier;
			}
			if (stats.m_healthOverTimeDuration > 0f)
			{
				stats.m_healthOverTimeDuration *= potionDurationMultiplier;
			}
			if (stats.m_staminaOverTimeDuration > 0f)
			{
				stats.m_staminaOverTimeDuration *= potionDurationMultiplier;
			}
			if (stats.m_eitrOverTimeDuration > 0f)
			{
				stats.m_eitrOverTimeDuration *= potionDurationMultiplier;
			}
			stats.m_healthUpFront *= potionPowerMultiplier;
			stats.m_staminaUpFront *= potionPowerMultiplier;
			stats.m_eitrUpFront *= potionPowerMultiplier;
			stats.m_healthOverTime *= potionPowerMultiplier;
			stats.m_staminaOverTime *= potionPowerMultiplier;
			stats.m_eitrOverTime *= potionPowerMultiplier;
			stats.m_healthRegenMultiplier *= potionPowerMultiplier;
			stats.m_staminaRegenMultiplier *= potionPowerMultiplier;
			stats.m_eitrRegenMultiplier *= potionPowerMultiplier;
		}
	}
}
[HarmonyPatch(typeof(Player), "Update")]
internal static class Alchemy_Patch_EnsureMinLevel
{
	private static void Postfix(Player __instance)
	{
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			AlchemySystem.EnsureMinLevel(__instance);
		}
	}
}
[HarmonyPatch(typeof(Player), "OnSpawned")]
internal static class Alchemy_Patch_OnSpawned
{
	private static void Postfix(Player __instance)
	{
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			AlchemySystem.ResetMinLevelFlag();
		}
	}
}
[HarmonyPatch(typeof(Player), "ConsumeItem")]
internal static class Alchemy_Patch_ConsumeItem
{
	private static void Prefix(Player __instance, ItemData item)
	{
		try
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && AlchemyPotionUtils.IsPotion(item))
			{
				AlchemySystem.OnPotionConsumed(__instance);
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)$"[Alchemy] Error en ConsumeItem: {arg}");
		}
	}
}
[HarmonyPatch(typeof(SE_Stats), "Setup")]
internal static class Alchemy_Patch_SE_Stats_Setup
{
	private static void Prefix(SE_Stats __instance, Character character)
	{
		try
		{
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer)
			{
				AlchemyStatsApplier.ApplyPowerAndDuration(val, __instance);
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)$"[Alchemy] Error en SE_Stats.Setup: {arg}");
		}
	}
}
[HarmonyPatch(typeof(Fermenter), "AddItem")]
internal static class Alchemy_Patch_Fermenter_AddItem
{
	private static void Postfix(Fermenter __instance, Humanoid user, ItemData item, bool __result)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (__result && item != null && AlchemyPotionUtils.IsMeadBase(item))
			{
				EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Alchemy] Mead base en fermenter {((Component)__instance).transform.position}: {item.m_shared.m_name} x{item.m_stack}");
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer)
				{
					AlchemySystem.OnPotionCrafted(val);
				}
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)$"[Alchemy] Error en Fermenter.AddItem: {arg}");
		}
	}
}
[HarmonyPatch(typeof(Fermenter), "RPC_AddItem")]
internal static class Alchemy_Patch_Fermenter_RPC_AddItem
{
	private static void Postfix(Fermenter __instance, long sender, string name)
	{
		try
		{
			if ((Object)(object)__instance?.m_nview == (Object)null || !__instance.m_nview.IsOwner())
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			float fermentationReduction = AlchemySystem.GetFermentationReduction(localPlayer);
			if (!(fermentationReduction <= 0f))
			{
				ZDO zDO = __instance.m_nview.GetZDO();
				long @long = zDO.GetLong(ZDOVars.s_startTime, 0L);
				if (@long != 0)
				{
					double num = __instance.m_fermentationDuration * fermentationReduction;
					long num2 = (long)(num * 10000000.0);
					long num3 = Math.Max(0L, @long - num2);
					zDO.Set(ZDOVars.s_startTime, num3);
					EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Alchemy] Fermentación acelerada -{fermentationReduction * 100f:0}% (~{num:0}s) para '{name}'.");
				}
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)$"[Alchemy] Error en RPC_AddItem: {arg}");
		}
	}
}
[HarmonyPatch(typeof(Fermenter), "DelayedTap")]
internal static class Alchemy_Patch_Fermenter_DelayedTap
{
	private static void Postfix(Fermenter __instance)
	{
		try
		{
			string delayedTapItem = __instance.m_delayedTapItem;
			if (string.IsNullOrEmpty(delayedTapItem))
			{
				return;
			}
			ItemConversion itemConversion = __instance.GetItemConversion(delayedTapItem);
			if (!((Object)(object)itemConversion?.m_to == (Object)null))
			{
				EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Alchemy] Fermenter produjo: {itemConversion.m_to.m_itemData?.m_shared?.m_name} x{itemConversion.m_producedItems}");
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					AlchemySystem.OnPotionCrafted(localPlayer);
				}
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)$"[Alchemy] Error en DelayedTap: {arg}");
		}
	}
}
[HarmonyPatch]
internal static class Alchemy_Patch_Tooltip
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
			where m.Name == "GetTooltip" && m.ReturnType == typeof(string)
			select m;
	}

	private static void Postfix(ItemData __instance, ref string __result)
	{
		try
		{
			if (__instance?.m_shared == null)
			{
				return;
			}
			bool flag = AlchemyPotionUtils.IsPotion(__instance);
			bool flag2 = AlchemyPotionUtils.IsMeadBase(__instance);
			bool flag3 = AlchemyPotionUtils.IsFinalMead(__instance);
			if (flag || flag2 || flag3)
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && !__result.Contains("=== Alquimia ==="))
				{
					int num = Mathf.FloorToInt(AlchemySystem.GetLevel(localPlayer));
					float num2 = (AlchemySystem.GetPotionDurationMultiplier(localPlayer) - 1f) * 100f;
					float num3 = (AlchemySystem.GetPotionPowerMultiplier(localPlayer) - 1f) * 100f;
					float num4 = AlchemySystem.GetFermentationReduction(localPlayer) * 100f;
					__result = __result + $"\n\n<color=#E9C46A><b>==== Alquimia Level <color=#FFF44F>[{num}]</color> ====</b></color>" + $"\nPotencia de poción: <color=#FF5CDF>+{num3:0}%</color>" + $"\nDuración de poción: <color=#CBA0FF>+{num2:0}%</color>" + $"\nFermentación rápida: <color=#A6FF4D>-{num4:0}%</color>";
				}
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)$"[Alchemy] Error en Tooltip: {arg}");
		}
	}
}
internal static class BlacksmithingSystem
{
	private const string DurabilityKey = "nazhi_blacksmith_durability";

	private const string LevelKey = "nazhi_blacksmith_lvl";

	private const string CrafterKey = "nazhi_blacksmith_crafter";

	private const float MaxDurabilityBonusAt100 = 0.6f;

	private const float DamageArmorMaxBonusAt100 = 1f;

	internal static SkillType BlacksmithingSkillType;

	private static bool _minLevelApplied;

	internal static void ResetMinLevelFlag()
	{
		_minLevelApplied = false;
	}

	internal static void RegisterSkill()
	{
		//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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: 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_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		SkillConfig val = new SkillConfig
		{
			Identifier = "nazhi.blacksmithing.skill",
			Name = "Herreria",
			Description = "Mejora la durabilidad y calidad del equipo forjado en fragua, fragua negra y mesa de trabajo.",
			Icon = null,
			IncreaseStep = 1f
		};
		BlacksmithingSkillType = SkillManager.Instance.AddSkill(val);
	}

	internal static float GetLevel(Player player)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null || (int)BlacksmithingSkillType == 0)
		{
			return 0f;
		}
		return Mathf.Clamp(((Character)player).GetSkillLevel(BlacksmithingSkillType), 0f, 100f);
	}

	internal static float GetDurabilityFactor(float level)
	{
		if (level <= 0f)
		{
			return 1f;
		}
		return 1f + 0.6f * Mathf.Clamp01(level / 100f);
	}

	internal static float GetDamageArmorFactor(int level)
	{
		if (level <= 0)
		{
			return 1f;
		}
		return 1f + 1f * Mathf.Clamp01((float)level / 100f);
	}

	internal static float GetDamageArmorPercent(int level)
	{
		return (GetDamageArmorFactor(level) - 1f) * 100f;
	}

	internal static void OnItemForged(Player player, ItemData item)
	{
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)player == (Object)null) && item != null && item.m_shared != null)
		{
			float level = GetLevel(player);
			float durabilityFactor = GetDurabilityFactor(level);
			int num = Mathf.RoundToInt(level);
			string playerName = player.GetPlayerName();
			if (item.m_customData == null)
			{
				item.m_customData = new Dictionary<string, string>();
			}
			item.m_customData["nazhi_blacksmith_durability"] = durabilityFactor.ToString(CultureInfo.InvariantCulture);
			item.m_customData["nazhi_blacksmith_lvl"] = num.ToString(CultureInfo.InvariantCulture);
			item.m_customData["nazhi_blacksmith_crafter"] = playerName;
			((Character)player).RaiseSkill(BlacksmithingSkillType, 1f);
		}
	}

	internal static float GetSavedDurabilityFactor(ItemData item)
	{
		if (item?.m_customData == null)
		{
			return 1f;
		}
		if (!item.m_customData.TryGetValue("nazhi_blacksmith_durability", out var value))
		{
			return 1f;
		}
		if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			return 1f;
		}
		return (result > 1f) ? result : 1f;
	}

	internal static int GetSavedLevel(ItemData item)
	{
		if (item?.m_customData == null)
		{
			return 0;
		}
		if (!item.m_customData.TryGetValue("nazhi_blacksmith_lvl", out var value))
		{
			return 0;
		}
		int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result);
		return result;
	}

	internal static string GetSavedCrafter(ItemData item)
	{
		if (item?.m_customData == null)
		{
			return null;
		}
		item.m_customData.TryGetValue("nazhi_blacksmith_crafter", out var value);
		return value;
	}

	internal static bool HasSignature(ItemData item)
	{
		if (item?.m_customData == null)
		{
			return false;
		}
		return item.m_customData.ContainsKey("nazhi_blacksmith_durability") || item.m_customData.ContainsKey("nazhi_blacksmith_lvl") || item.m_customData.ContainsKey("nazhi_blacksmith_crafter");
	}

	internal static bool IsExcludedUtility(ItemData item)
	{
		if (item == null)
		{
			return false;
		}
		string text = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : (item.m_shared?.m_name ?? ""));
		return text == "Cultivator" || text == "Hoe" || text == "Hammer";
	}

	internal static void EnsureMinLevel(Player player)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Invalid comparison between Unknown and I4
		//IL_0027: 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)
		if (!_minLevelApplied && !((Object)(object)player == (Object)null) && (int)BlacksmithingSkillType != 0)
		{
			float skillLevel = ((Character)player).GetSkillLevel(BlacksmithingSkillType);
			if (skillLevel < 1f)
			{
				((Character)player).RaiseSkill(BlacksmithingSkillType, 0.5f);
			}
			_minLevelApplied = true;
		}
	}
}
internal static class BlacksmithingCraftContext
{
	[ThreadStatic]
	private static bool _active;

	[ThreadStatic]
	private static CraftingStation _station;

	[ThreadStatic]
	private static Player _crafter;

	internal static bool Active
	{
		get
		{
			return _active;
		}
		set
		{
			_active = value;
		}
	}

	internal static CraftingStation Station
	{
		get
		{
			return _station;
		}
		set
		{
			_station = value;
		}
	}

	internal static Player Crafter
	{
		get
		{
			return _crafter;
		}
		set
		{
			_crafter = value;
		}
	}

	internal static bool IsForgeStation(CraftingStation station)
	{
		if ((Object)(object)station == (Object)null)
		{
			return false;
		}
		return station.m_name == "$piece_forge" || station.m_name == "$piece_blackforge" || station.m_name == "$piece_workbench";
	}

	internal static void Begin(Player player)
	{
		Active = true;
		Crafter = player;
		Station = ((player != null) ? player.GetCurrentCraftingStation() : null);
	}

	internal static void End()
	{
		Active = false;
		Station = null;
		Crafter = null;
	}
}
[HarmonyPatch(typeof(Player), "Update")]
internal static class Blacksmithing_Patch_EnsureMinLevel
{
	private static void Postfix(Player __instance)
	{
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			BlacksmithingSystem.EnsureMinLevel(__instance);
		}
	}
}
[HarmonyPatch(typeof(Player), "OnSpawned")]
internal static class Blacksmithing_Patch_OnSpawned
{
	private static void Postfix(Player __instance)
	{
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			BlacksmithingSystem.ResetMinLevelFlag();
		}
	}
}
[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
internal static class Blacksmithing_Patch_DoCrafting
{
	private static void Prefix(Player player)
	{
		BlacksmithingCraftContext.Begin(player);
	}

	private static void Finalizer()
	{
		BlacksmithingCraftContext.End();
	}
}
[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
{
	typeof(string),
	typeof(int),
	typeof(int),
	typeof(int),
	typeof(long),
	typeof(string),
	typeof(Vector2i),
	typeof(bool)
})]
internal static class Blacksmithing_Patch_AddItem
{
	private static void Postfix(ref ItemData __result)
	{
		if (BlacksmithingCraftContext.Active && __result != null)
		{
			CraftingStation station = BlacksmithingCraftContext.Station;
			Player crafter = BlacksmithingCraftContext.Crafter;
			bool flag = BlacksmithingCraftContext.IsForgeStation(station);
			if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && !((Object)(object)crafter == (Object)null) && flag)
			{
				BlacksmithingSystem.OnItemForged(crafter, __result);
			}
		}
	}
}
[HarmonyPatch(typeof(ItemData), "GetMaxDurability", new Type[] { })]
internal static class Blacksmithing_Patch_MaxDurability
{
	private static void Postfix(ItemData __instance, ref float __result)
	{
		if (__instance != null)
		{
			float savedDurabilityFactor = BlacksmithingSystem.GetSavedDurabilityFactor(__instance);
			if (savedDurabilityFactor > 1f)
			{
				__result *= savedDurabilityFactor;
			}
		}
	}
}
[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
{
	typeof(ItemData),
	typeof(int),
	typeof(bool),
	typeof(float),
	typeof(int)
})]
internal static class Blacksmithing_Patch_Tooltip
{
	private static void Postfix([HarmonyArgument(0)] ItemData item, ref string __result)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Invalid comparison between Unknown and I4
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Invalid comparison between Unknown and I4
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Invalid comparison between Unknown and I4
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Invalid comparison between Unknown and I4
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Invalid comparison between Unknown and I4
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Invalid comparison between Unknown and I4
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Invalid comparison between Unknown and I4
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Invalid comparison between Unknown and I4
		if (item != null && BlacksmithingSystem.HasSignature(item))
		{
			float savedDurabilityFactor = BlacksmithingSystem.GetSavedDurabilityFactor(item);
			int savedLevel = BlacksmithingSystem.GetSavedLevel(item);
			string text = BlacksmithingSystem.GetSavedCrafter(item) ?? item.m_crafterName;
			SharedData shared = item.m_shared;
			ItemType val = (ItemType)((shared != null) ? ((int)shared.m_itemType) : 0);
			bool flag = (int)val == 3 || (int)val == 14 || (int)val == 4 || (int)val == 19;
			bool flag2 = (int)val == 6 || (int)val == 7 || (int)val == 11 || (int)val == 17;
			if (flag && BlacksmithingSystem.IsExcludedUtility(item))
			{
				flag = false;
			}
			float damageArmorPercent = BlacksmithingSystem.GetDamageArmorPercent(savedLevel);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine();
			stringBuilder.AppendLine();
			if (savedDurabilityFactor > 1f)
			{
				stringBuilder.AppendLine($"<color=#00ff00>Durabilidad extra +{(savedDurabilityFactor - 1f) * 100f:0.#}%</color>");
			}
			if (flag && damageArmorPercent > 0.01f)
			{
				stringBuilder.AppendLine($"<color=#ffcc00>Daño aumentado +{damageArmorPercent:0.#}%</color>");
			}
			else if (flag2 && damageArmorPercent > 0.01f)
			{
				stringBuilder.AppendLine($"<color=#ffcc00>Armadura aumentada +{damageArmorPercent:0.#}%</color>");
			}
			string text2 = ((!string.IsNullOrEmpty(text)) ? text : "Desconocido");
			string text3 = ((savedLevel > 0) ? savedLevel.ToString() : "?");
			stringBuilder.AppendLine("<color=#cccccc>Forjado por " + text2 + " · Herrero nivel " + text3 + "</color>");
			__result += stringBuilder.ToString();
		}
	}
}
[HarmonyPatch(typeof(ItemData), "GetDamage", new Type[]
{
	typeof(int),
	typeof(float)
})]
internal static class Blacksmithing_Patch_Damage
{
	private static void Postfix(ItemData __instance, ref DamageTypes __result)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Invalid comparison between Unknown and I4
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Invalid comparison between Unknown and I4
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Invalid comparison between Unknown and I4
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Invalid comparison between Unknown and I4
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Invalid comparison between Unknown and I4
		if (__instance == null || !BlacksmithingSystem.HasSignature(__instance))
		{
			return;
		}
		SharedData shared = __instance.m_shared;
		ItemType val = (ItemType)((shared != null) ? ((int)shared.m_itemType) : 0);
		if (((int)val == 3 || (int)val == 14 || (int)val == 4 || (int)val == 19 || (int)val == 5) && !BlacksmithingSystem.IsExcludedUtility(__instance))
		{
			int savedLevel = BlacksmithingSystem.GetSavedLevel(__instance);
			float damageArmorFactor = BlacksmithingSystem.GetDamageArmorFactor(savedLevel);
			if (!(damageArmorFactor <= 1f))
			{
				__result.m_blunt *= damageArmorFactor;
				__result.m_slash *= damageArmorFactor;
				__result.m_pierce *= damageArmorFactor;
				__result.m_chop *= damageArmorFactor;
				__result.m_pickaxe *= damageArmorFactor;
				__result.m_fire *= damageArmorFactor;
				__result.m_frost *= damageArmorFactor;
				__result.m_lightning *= damageArmorFactor;
				__result.m_poison *= damageArmorFactor;
				__result.m_spirit *= damageArmorFactor;
			}
		}
	}
}
[HarmonyPatch(typeof(ItemData), "GetArmor", new Type[]
{
	typeof(int),
	typeof(float)
})]
internal static class Blacksmithing_Patch_Armor
{
	private static void Postfix(ItemData __instance, ref float __result)
	{
		//IL_0025: 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_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Invalid comparison between Unknown and I4
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Invalid comparison between Unknown and I4
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Invalid comparison between Unknown and I4
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between Unknown and I4
		if (__instance == null || !BlacksmithingSystem.HasSignature(__instance))
		{
			return;
		}
		SharedData shared = __instance.m_shared;
		ItemType val = (ItemType)((shared != null) ? ((int)shared.m_itemType) : 0);
		if ((int)val == 6 || (int)val == 7 || (int)val == 11 || (int)val == 17)
		{
			int savedLevel = BlacksmithingSystem.GetSavedLevel(__instance);
			float damageArmorFactor = BlacksmithingSystem.GetDamageArmorFactor(savedLevel);
			if (!(damageArmorFactor <= 1f))
			{
				__result *= damageArmorFactor;
			}
		}
	}
}
internal static class ConstructionSystem
{
	internal const string ZdoKeyMaxHealth = "nazhi_construction_maxhp";

	internal const string ZdoKeyPaidPrefix = "nazhi_paid_";

	internal const string RpcSetBuilderMult = "nazhi_construction_SetBuilderMult";

	private const string AcbKey = "ACB_PreventPulling";

	private static readonly Dictionary<long, float> _pendingMult = new Dictionary<long, float>();

	internal static readonly Dictionary<string, int> PendingPaid = new Dictionary<string, int>();

	internal static void RegisterRpc()
	{
		ZRoutedRpc.instance.Register<float>("nazhi_construction_SetBuilderMult", (Action<long, float>)OnRpcSetBuilderMult);
	}

	private static void OnRpcSetBuilderMult(long senderPeerID, float hpMult)
	{
		ZNet instance = ZNet.instance;
		ZNetPeer val = ((instance != null) ? instance.GetPeer(senderPeerID) : null);
		if (val != null)
		{
			long userID = ((ZDOID)(ref val.m_characterID)).UserID;
			_pendingMult[userID] = hpMult;
			EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] RPC recibido uid={userID} hpMult={hpMult:0.000}");
		}
	}

	internal static bool TryConsumePendingMult(long uid, out float hpMult)
	{
		if (_pendingMult.TryGetValue(uid, out hpMult))
		{
			_pendingMult.Remove(uid);
			return true;
		}
		hpMult = 1f;
		return false;
	}

	internal static float GetCraftingLevel(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return 0f;
		}
		return ((Character)player).GetSkillLevel((SkillType)107);
	}

	internal static float GetHealthMultiplier(Player player)
	{
		return 1f + GetCraftingLevel(player) * 0.01f;
	}

	internal static float GetCostDiscount(Player player)
	{
		return Mathf.Clamp(GetCraftingLevel(player) * 0.005f, 0f, 0.5f);
	}

	internal static int GetConsumedAmount(int baseAmount, float discount)
	{
		if (baseAmount <= 0)
		{
			return 0;
		}
		int num = Mathf.FloorToInt((float)baseAmount * discount);
		return Mathf.Max(1, baseAmount - num);
	}

	internal static int GetRequiredAmount(int baseAmount, float discount)
	{
		return GetConsumedAmount(baseAmount, discount);
	}

	internal static bool DiscountSavesAnything(Piece piece, float discount)
	{
		if ((Object)(object)piece == (Object)null || discount <= 0f)
		{
			return false;
		}
		Requirement[] resources = piece.m_resources;
		foreach (Requirement val in resources)
		{
			if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0 && Mathf.FloorToInt((float)val.m_amount * discount) >= 1)
			{
				return true;
			}
		}
		return false;
	}

	private static string ZdoPaidKey(string itemName)
	{
		return "nazhi_paid_" + Math.Abs(itemName.GetHashCode()) % 100000;
	}

	internal static void SavePaidToZDO(ZDO zdo, string itemName, int amount)
	{
		if (zdo != null)
		{
			zdo.Set(ZdoPaidKey(itemName), amount);
			EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] ZDO saved '{itemName}'={amount} key={ZdoPaidKey(itemName)}");
		}
	}

	internal static int GetPaidFromZDO(ZDO zdo, string itemName)
	{
		if (zdo == null)
		{
			return -1;
		}
		return zdo.GetInt(ZdoPaidKey(itemName), -1);
	}

	internal static bool HasPaidData(ZDO zdo, Piece piece)
	{
		if (zdo == null || (Object)(object)piece == (Object)null)
		{
			return false;
		}
		Requirement[] resources = piece.m_resources;
		foreach (Requirement val in resources)
		{
			if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0 && GetPaidFromZDO(zdo, val.m_resItem.m_itemData.m_shared.m_name) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	internal static void FlushPaidToZDO(Player player, Piece placedPiece)
	{
		//IL_00c5: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
		if (PendingPaid.Count == 0 || (Object)(object)player == (Object)null || (Object)(object)placedPiece == (Object)null)
		{
			return;
		}
		string name = ((Object)placedPiece).name;
		float num = 5f;
		ZDO val = null;
		foreach (Piece s_allPiece in Piece.s_allPieces)
		{
			if ((Object)(object)s_allPiece == (Object)null || ((Object)s_allPiece).name != name)
			{
				continue;
			}
			WearNTear component = ((Component)s_allPiece).GetComponent<WearNTear>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component.m_nview == (Object)null) && component.m_nview.IsValid())
			{
				float num2 = Vector3.Distance(((Component)s_allPiece).transform.position, ((Component)player).transform.position);
				if (num2 < num)
				{
					num = num2;
					val = component.m_nview.GetZDO();
				}
			}
		}
		if (val == null)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)"[Construction] FlushPaidToZDO: no se encontró ZDO para la pieza recién colocada");
			PendingPaid.Clear();
			return;
		}
		foreach (KeyValuePair<string, int> item in PendingPaid)
		{
			SavePaidToZDO(val, item.Key, item.Value);
		}
		EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] FlushPaidToZDO: {PendingPaid.Count} costes guardados en ZDO uid={val.m_uid}");
		PendingPaid.Clear();
	}

	internal static void SpawnRefundDrops(Piece piece, ZDO zdo, Vector3 position)
	{
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: 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_00ed: 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)
		Requirement[] resources = piece.m_resources;
		foreach (Requirement val in resources)
		{
			if ((Object)(object)val?.m_resItem == (Object)null || val.m_amount <= 0)
			{
				continue;
			}
			string name = val.m_resItem.m_itemData.m_shared.m_name;
			int num = GetPaidFromZDO(zdo, name);
			if (num < 0)
			{
				num = val.m_amount;
			}
			int num2 = Mathf.Max(1, Mathf.RoundToInt((float)num * 0.5f));
			for (int j = 0; j < num2; j++)
			{
				GameObject gameObject = ((Component)val.m_resItem).gameObject;
				if (!((Object)(object)gameObject == (Object)null))
				{
					GameObject val2 = Object.Instantiate<GameObject>(gameObject, position + Random.insideUnitSphere * 0.3f, Quaternion.identity);
					Rigidbody component = val2.GetComponent<Rigidbody>();
					if (component != null)
					{
						component.AddForce(Vector3.up * 2f + Random.insideUnitSphere, (ForceMode)2);
					}
				}
			}
			EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] Refund '{name}' pagado={num} devuelto={num2}");
		}
	}

	internal static void BlockAzuCraftyBoxes(Player player)
	{
		if (!((Object)(object)player == (Object)null))
		{
			player.m_customData["ACB_PreventPulling"] = "0";
			EinjarheimProfessionsPlugin.Log.LogInfo((object)"[Construction] AzuCraftyBoxes bloqueado (ACB_PreventPulling=0)");
		}
	}

	internal static void UnblockAzuCraftyBoxes(Player player)
	{
		if (!((Object)(object)player == (Object)null))
		{
			player.m_customData["ACB_PreventPulling"] = "1";
			EinjarheimProfessionsPlugin.Log.LogInfo((object)"[Construction] AzuCraftyBoxes restaurado (ACB_PreventPulling=1)");
		}
	}
}
internal static class ConstructionPlaceContext
{
	[ThreadStatic]
	private static float _pendingDiscount;

	internal static void Set(float discount)
	{
		_pendingDiscount = discount;
		EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] PendingDiscount set → {discount * 100f:0.0}%");
	}

	internal static float Consume()
	{
		float pendingDiscount = _pendingDiscount;
		_pendingDiscount = 0f;
		return pendingDiscount;
	}
}
[HarmonyPatch(typeof(ZNet), "Awake")]
internal static class Construction_Patch_RegisterRpc
{
	private static void Postfix()
	{
		ConstructionSystem.RegisterRpc();
	}
}
[HarmonyPatch(typeof(Player), "SetPlaceMode", new Type[] { typeof(PieceTable) })]
internal static class Construction_Patch_SetPlaceMode
{
	private static void Postfix(Player __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			float craftingLevel = ConstructionSystem.GetCraftingLevel(__instance);
			float healthMultiplier = ConstructionSystem.GetHealthMultiplier(__instance);
			float num = ConstructionSystem.GetCostDiscount(__instance) * 100f;
			EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] Modo construcción – Crafting={craftingLevel:0} HPmult={healthMultiplier:0.000} CostReduction={num:0.0}%");
		}
	}
}
[HarmonyPatch(typeof(Player), "SetSelectedPiece", new Type[] { typeof(Vector2Int) })]
internal static class Construction_Patch_SetSelectedPiece
{
	private static void Postfix(Player __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			Piece selectedPiece = __instance.GetSelectedPiece();
			if (!((Object)(object)selectedPiece == (Object)null))
			{
				WearNTear component = ((Component)selectedPiece).GetComponent<WearNTear>();
				float num = (((Object)(object)component != (Object)null) ? component.m_health : (-1f));
				float healthMultiplier = ConstructionSystem.GetHealthMultiplier(__instance);
				float craftingLevel = ConstructionSystem.GetCraftingLevel(__instance);
				string text = ((num >= 0f) ? (num * healthMultiplier).ToString("0.0") : "N/A");
				string text2 = ((num >= 0f) ? num.ToString("0.0") : "N/A");
				EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] Pieza={((Object)selectedPiece).name} BaseHP={text2} BuffedHP={text} Crafting={craftingLevel:0}");
			}
		}
	}
}
[HarmonyPatch(typeof(Player), "PlacePiece", new Type[]
{
	typeof(Piece),
	typeof(Vector3),
	typeof(Quaternion),
	typeof(bool)
})]
internal static class Construction_Patch_PlacePiece
{
	private static void Prefix(Player __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			float costDiscount = ConstructionSystem.GetCostDiscount(__instance);
			ConstructionPlaceContext.Set(costDiscount);
			ConstructionSystem.BlockAzuCraftyBoxes(__instance);
			float healthMultiplier = ConstructionSystem.GetHealthMultiplier(__instance);
			if (healthMultiplier > 1f && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "nazhi_construction_SetBuilderMult", new object[1] { healthMultiplier });
			}
		}
	}

	private static void Postfix(Player __instance, Piece piece)
	{
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)piece == (Object)null))
		{
			if (ConstructionSystem.PendingPaid.Count > 0)
			{
				ConstructionSystem.FlushPaidToZDO(__instance, piece);
			}
			float craftingLevel = ConstructionSystem.GetCraftingLevel(__instance);
			float num = ConstructionSystem.GetCostDiscount(__instance) * 100f;
			EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] PlacePiece '{((Object)piece).name}' lvl={craftingLevel:0} CostReduction={num:0.0}%");
		}
	}
}
[HarmonyPatch(typeof(Piece), "SetCreator", new Type[] { typeof(long) })]
internal static class Construction_Patch_SetCreator
{
	private static void Postfix(Piece __instance, long uid)
	{
		try
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			WearNTear component = ((Component)__instance).GetComponent<WearNTear>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.m_nview == (Object)null || !component.m_nview.IsValid())
			{
				return;
			}
			ZDO zDO = component.m_nview.GetZDO();
			if (zDO == null || zDO.GetFloat("nazhi_construction_maxhp", 0f) > 0f)
			{
				return;
			}
			float hpMult = 1f;
			if (!ConstructionSystem.TryConsumePendingMult(uid, out hpMult))
			{
				Player player = Player.GetPlayer(uid);
				if ((Object)(object)player != (Object)null)
				{
					hpMult = ConstructionSystem.GetHealthMultiplier(player);
				}
			}
			if (!(hpMult <= 1f))
			{
				float health = component.m_health;
				if (!(health <= 0f))
				{
					float num = (component.m_health = health * hpMult);
					zDO.Set("nazhi_construction_maxhp", num);
					EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] SetCreator HP buff '{((Object)__instance).name}' {health:0} → {num:0} (x{hpMult:0.000})");
				}
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogError((object)$"[Construction] Error en Piece.SetCreator: {arg}");
		}
	}
}
[HarmonyPatch(typeof(WearNTear), "Awake")]
internal static class Construction_Patch_WearNTear_Awake
{
	private static void Postfix(WearNTear __instance)
	{
		try
		{
			if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid())
			{
				return;
			}
			ZDO zDO = __instance.m_nview.GetZDO();
			if (zDO != null)
			{
				float @float = zDO.GetFloat("nazhi_construction_maxhp", 0f);
				if (!(@float <= 0f))
				{
					float health = __instance.m_health;
					__instance.m_health = @float;
					EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] WearNTear.Awake restore '{((Object)__instance).name}' {health:0} → {@float:0}");
				}
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogError((object)$"[Construction] Error en WearNTear.Awake: {arg}");
		}
	}
}
[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
{
	typeof(Piece),
	typeof(RequirementMode)
})]
internal static class Construction_Patch_HaveRequirements
{
	private static bool Prefix(Player __instance, Piece piece, RequirementMode mode, ref bool __result)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Invalid comparison between Unknown and I4
		//IL_0087: 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)
		if ((Object)(object)__instance == (Object)null || (Object)(object)piece == (Object)null)
		{
			return true;
		}
		if ((int)mode > 0)
		{
			return true;
		}
		float costDiscount = ConstructionSystem.GetCostDiscount(__instance);
		if (costDiscount <= 0f)
		{
			return true;
		}
		if (!ConstructionSystem.DiscountSavesAnything(piece, costDiscount))
		{
			return true;
		}
		if (Object.op_Implicit((Object)(object)piece.m_craftingStation) && !Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)__instance).transform.position)) && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)22))
		{
			__result = false;
			return false;
		}
		if (piece.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(piece.m_dlc))
		{
			__result = false;
			return false;
		}
		if (ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey()))
		{
			__result = true;
			return false;
		}
		Requirement[] resources = piece.m_resources;
		foreach (Requirement val in resources)
		{
			if (Object.op_Implicit((Object)(object)val.m_resItem) && val.m_amount > 0)
			{
				string name = val.m_resItem.m_itemData.m_shared.m_name;
				int requiredAmount = ConstructionSystem.GetRequiredAmount(val.m_amount, costDiscount);
				int num = ((Humanoid)__instance).m_inventory.CountItems(name, -1, true);
				if (num < requiredAmount)
				{
					EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] HaveReq falta '{name}': have={num} need={requiredAmount}");
					__result = false;
					return false;
				}
			}
		}
		__result = true;
		return false;
	}
}
[HarmonyPatch(typeof(Player), "ConsumeResources", new Type[]
{
	typeof(Requirement[]),
	typeof(int),
	typeof(int),
	typeof(int)
})]
internal static class Construction_Patch_ConsumeResources
{
	private static bool Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier)
	{
		float num = ConstructionPlaceContext.Consume();
		EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] ConsumeResources — discount={num * 100f:0.0}%");
		if (num <= 0f)
		{
			return true;
		}
		if ((Object)(object)__instance == (Object)null || requirements == null)
		{
			return true;
		}
		ConstructionSystem.PendingPaid.Clear();
		foreach (Requirement val in requirements)
		{
			if (Object.op_Implicit((Object)(object)val?.m_resItem))
			{
				int amount = val.m_amount;
				if (amount > 0)
				{
					int consumedAmount = ConstructionSystem.GetConsumedAmount(amount, num);
					string name = val.m_resItem.m_itemData.m_shared.m_name;
					((Humanoid)__instance).m_inventory.RemoveItem(name, consumedAmount, itemQuality, true);
					ConstructionSystem.PendingPaid[name] = consumedAmount;
					EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Construction] Consume '{name}' original={amount} gastado={consumedAmount} ({num * 100f:0.0}% desc)");
				}
			}
		}
		ConstructionSystem.UnblockAzuCraftyBoxes(__instance);
		return false;
	}
}
[HarmonyPatch(typeof(Piece), "DropResources")]
internal static class Construction_Patch_DropResources
{
	private static bool Prefix(Piece __instance)
	{
		//IL_0083: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			WearNTear component = ((Component)__instance).GetComponent<WearNTear>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.m_nview == (Object)null || !component.m_nview.IsValid())
			{
				return true;
			}
			ZDO zDO = component.m_nview.GetZDO();
			if (zDO == null)
			{
				return true;
			}
			if (!ConstructionSystem.HasPaidData(zDO, __instance))
			{
				return true;
			}
			ConstructionSystem.SpawnRefundDrops(__instance, zDO, ((Component)__instance).transform.position + Vector3.up * 0.5f);
			return false;
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogError((object)$"[Construction] Error en DropResources: {arg}");
			return true;
		}
	}
}
[HarmonyPatch(typeof(Hud), "SetupPieceInfo")]
internal static class Construction_Patch_HudPieceInfo
{
	private static void Postfix(Hud __instance, Piece piece)
	{
		try
		{
			if ((Object)(object)piece == (Object)null || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			TMP_Text pieceDescription = __instance.m_pieceDescription;
			if (!((Object)(object)pieceDescription == (Object)null))
			{
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null))
				{
					float craftingLevel = ConstructionSystem.GetCraftingLevel(localPlayer);
					float healthMultiplier = ConstructionSystem.GetHealthMultiplier(localPlayer);
					float costDiscount = ConstructionSystem.GetCostDiscount(localPlayer);
					WearNTear component = ((Component)piece).GetComponent<WearNTear>();
					float num = (((Object)(object)component != (Object)null) ? component.m_health : 0f);
					float num2 = num * healthMultiplier - num;
					string text = Localization.instance.Localize(piece.m_description);
					string text2 = (ConstructionSystem.DiscountSavesAnything(piece, costDiscount) ? $"\n<size=16><color=#00BFFF>Recursos: -{costDiscount * 100f:0.0}%</color></size>" : "\n<size=16><color=#888888>Recursos: sin descuento aún</color></size>");
					pieceDescription.text = text + $"\n<size=16><color=#FFD700>Crafting: Level {craftingLevel:0}</color></size>" + $"\n<size=16><color=#32CD32>Health: {num:0}</color> (+<color=#FFD700>{num2:0}</color>)</size>" + text2;
				}
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogError((object)$"[Construction] Error en HUD SetupPieceInfo: {arg}");
		}
	}
}
[HarmonyPatch(typeof(InventoryGui), "SetupRequirement", new Type[]
{
	typeof(Transform),
	typeof(Requirement),
	typeof(Player),
	typeof(bool),
	typeof(int),
	typeof(int)
})]
internal static class Construction_Patch_SetupRequirement
{
	private static void Postfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier)
	{
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)player == (Object)null || (Object)(object)req?.m_resItem == (Object)null || craft || quality != 0)
			{
				return;
			}
			float costDiscount = ConstructionSystem.GetCostDiscount(player);
			if (costDiscount <= 0f)
			{
				return;
			}
			int amount = req.m_amount;
			if (amount <= 0)
			{
				return;
			}
			int requiredAmount = ConstructionSystem.GetRequiredAmount(amount, costDiscount);
			if (requiredAmount < amount)
			{
				Transform obj = elementRoot.Find("res_amount");
				TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
				if (!((Object)(object)val == (Object)null))
				{
					val.text = requiredAmount.ToString();
					int num = ((Humanoid)player).GetInventory().CountItems(req.m_resItem.m_itemData.m_shared.m_name, -1, true);
					bool flag = (!craft && ZoneSystem.instance.GetGlobalKey((GlobalKeys)19)) || (craft && ZoneSystem.instance.GetGlobalKey((GlobalKeys)20));
					((Graphic)val).color = ((requiredAmount <= 0 || num >= requiredAmount || flag) ? Color.white : ((Mathf.Sin(Time.time * 10f) > 0f) ? Color.red : Color.white));
				}
			}
		}
		catch (Exception arg)
		{
			EinjarheimProfessionsPlugin.Log.LogError((object)$"[Construction] Error en SetupRequirement: {arg}");
		}
	}
}
internal static class CookingSystem
{
	internal struct ChefInfo
	{
		public long ChefId;

		public string ChefName;

		public int ChefLv;

		public int Count;
	}

	internal const string CD_CHEF_NAME = "nazhi_chef_name";

	internal const string CD_CHEF_ID = "nazhi_chef_id";

	internal const string CD_CHEF_LV = "nazhi_chef_cooking_lv";

	internal const string ZDO_FOOD0_NAME = "nazhi_food0_name";

	internal const string ZDO_FOOD0_LV = "nazhi_food0_chef_lv";

	internal const string ZDO_FOOD0_CHEF = "nazhi_food0_chef_name";

	internal const string ZDO_FOOD1_NAME = "nazhi_food1_name";

	internal const string ZDO_FOOD1_LV = "nazhi_food1_chef_lv";

	internal const string ZDO_FOOD1_CHEF = "nazhi_food1_chef_name";

	internal const string ZDO_FOOD2_NAME = "nazhi_food2_name";

	internal const string ZDO_FOOD2_LV = "nazhi_food2_chef_lv";

	internal const string ZDO_FOOD2_CHEF = "nazhi_food2_chef_name";

	internal const string RpcStampFood = "nazhi_cooking_StampFood";

	internal static readonly Dictionary<long, Dictionary<string, ChefInfo>> PendingByPlayer = new Dictionary<long, Dictionary<string, ChefInfo>>();

	internal static void RegisterRpc()
	{
		ZRoutedRpc.instance.Register<string, int, string>("nazhi_cooking_StampFood", (Action<long, string, int, string>)OnRpcStampFood);
	}

	private static void OnRpcStampFood(long senderPeerID, string sharedName, int chefLv, string chefName)
	{
		Player localPlayer = Player.m_localPlayer;
		if (!((Object)(object)localPlayer == (Object)null))
		{
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			ItemData val = ((inventory != null) ? ((IEnumerable<ItemData>)inventory.GetAllItems()).LastOrDefault((Func<ItemData, bool>)((ItemData i) => i?.m_shared?.m_name == sharedName && IsFood(i) && string.IsNullOrEmpty(GetChefNameRaw(i)))) : null);
			if (val == null)
			{
				SetPending(localPlayer, sharedName, chefLv, chefName);
				return;
			}
			StampChef(val, new ChefInfo
			{
				ChefId = 0L,
				ChefName = chefName,
				ChefLv = chefLv,
				Count = 1
			});
			EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Cooking] RPC stamp '{sharedName}' chef={chefName} lv={chefLv}");
		}
	}

	internal static bool IsFood(ItemData item)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Invalid comparison between Unknown and I4
		SharedData val = item?.m_shared;
		if (val == null)
		{
			return false;
		}
		if ((int)val.m_itemType != 2)
		{
			return false;
		}
		return val.m_food > 0f || val.m_foodStamina > 0f || val.m_foodEitr > 0f;
	}

	internal static int GetVanillaCookingLevel(Player p)
	{
		if ((Object)(object)p == (Object)null)
		{
			return 1;
		}
		return Mathf.Max(1, Mathf.FloorToInt(((Character)p).GetSkillLevel((SkillType)105)));
	}

	internal static int BonusFromChefLevel(int chefLv)
	{
		return Mathf.Max(1, chefLv);
	}

	internal static void CalculateBonus(ItemData item, int chefLv, out int bonusHp, out int bonusSt, out int bonusEi)
	{
		bonusHp = 0;
		bonusSt = 0;
		bonusEi = 0;
		if (item?.m_shared == null)
		{
			return;
		}
		int num = BonusFromChefLevel(chefLv);
		float food = item.m_shared.m_food;
		float foodStamina = item.m_shared.m_foodStamina;
		float foodEitr = item.m_shared.m_foodEitr;
		if (foodEitr > 0f)
		{
			if (food > 0f)
			{
				bonusHp = Mathf.RoundToInt((float)num * 0.2f);
			}
			if (foodStamina > 0f)
			{
				bonusSt = Mathf.RoundToInt((float)num * 0.2f);
			}
			bonusEi = Mathf.RoundToInt((float)num * 0.5f);
		}
		else if (food > 0f && foodStamina > 0f)
		{
			if (food >= foodStamina)
			{
				bonusHp = Mathf.RoundToInt((float)num * 0.8f);
				bonusSt = Mathf.RoundToInt((float)num * 0.2f);
			}
			else
			{
				bonusSt = Mathf.RoundToInt((float)num * 0.8f);
				bonusHp = Mathf.RoundToInt((float)num * 0.2f);
			}
		}
		else if (food > 0f)
		{
			bonusHp = num;
		}
		else if (foodStamina > 0f)
		{
			bonusSt = num;
		}
	}

	internal static void StampChef(ItemData item, ChefInfo chef)
	{
		if (item != null)
		{
			if (item.m_customData == null)
			{
				item.m_customData = new Dictionary<string, string>();
			}
			item.m_customData["nazhi_chef_name"] = chef.ChefName;
			item.m_customData["nazhi_chef_id"] = chef.ChefId.ToString();
			item.m_customData["nazhi_chef_cooking_lv"] = chef.ChefLv.ToString();
		}
	}

	internal static ChefInfo BuildChef(Player chef)
	{
		ChefInfo result = default(ChefInfo);
		result.ChefId = chef.GetPlayerID();
		result.ChefName = chef.GetPlayerName();
		result.ChefLv = GetVanillaCookingLevel(chef);
		result.Count = 1;
		return result;
	}

	internal static void SetPending(Player chef, string itemSharedName, int chefLv, string chefName)
	{
		if (!((Object)(object)chef == (Object)null) && !string.IsNullOrEmpty(itemSharedName))
		{
			long playerID = chef.GetPlayerID();
			if (!PendingByPlayer.TryGetValue(playerID, out var value) || value == null)
			{
				value = new Dictionary<string, ChefInfo>();
				PendingByPlayer[playerID] = value;
			}
			ChefInfo chefInfo = default(ChefInfo);
			chefInfo.ChefId = chef.GetPlayerID();
			chefInfo.ChefName = chefName;
			chefInfo.ChefLv = chefLv;
			chefInfo.Count = ((!value.TryGetValue(itemSharedName, out var value2)) ? 1 : (value2.Count + 1));
			ChefInfo value3 = chefInfo;
			value[itemSharedName] = value3;
		}
	}

	internal static void SetPending(Player chef, string itemSharedName)
	{
		if (!((Object)(object)chef == (Object)null) && !string.IsNullOrEmpty(itemSharedName))
		{
			long playerID = chef.GetPlayerID();
			if (!PendingByPlayer.TryGetValue(playerID, out var value) || value == null)
			{
				value = new Dictionary<string, ChefInfo>();
				PendingByPlayer[playerID] = value;
			}
			if (value.TryGetValue(itemSharedName, out var value2))
			{
				value2.Count++;
				value[itemSharedName] = value2;
			}
			else
			{
				ChefInfo value3 = BuildChef(chef);
				value3.Count = 1;
				value[itemSharedName] = value3;
			}
		}
	}

	internal static bool TryConsumePending(Player receiver, string itemSharedName, out ChefInfo chef)
	{
		chef = default(ChefInfo);
		if ((Object)(object)receiver == (Object)null || string.IsNullOrEmpty(itemSharedName))
		{
			return false;
		}
		long playerID = receiver.GetPlayerID();
		if (!PendingByPlayer.TryGetValue(playerID, out var value) || value == null)
		{
			return false;
		}
		if (!value.TryGetValue(itemSharedName, out chef))
		{
			return false;
		}
		if (chef.Count <= 1)
		{
			value.Remove(itemSharedName);
		}
		else
		{
			ChefInfo value2 = chef;
			value2.Count--;
			value[itemSharedName] = value2;
		}
		return true;
	}

	internal static void ClearPending(long playerID)
	{
		PendingByPlayer.Remove(playerID);
	}

	internal static int GetChefLevelFromItem(ItemData item)
	{
		if (item?.m_customData == null)
		{
			return 1;
		}
		if (item.m_customData.TryGetValue("nazhi_chef_cooking_lv", out var value) && int.TryParse(value, out var result))
		{
			return Mathf.Max(1, result);
		}
		return 1;
	}

	internal static string GetChefNameFromItem(ItemData item)
	{
		if (item?.m_customData == null)
		{
			return "Desconocido";
		}
		if (item.m_customData.TryGetValue("nazhi_chef_name", out var value) && !string.IsNullOrEmpty(value))
		{
			return value;
		}
		return "Desconocido";
	}

	internal static string GetChefNameRaw(ItemData item)
	{
		if (item?.m_customData == null)
		{
			return "";
		}
		item.m_customData.TryGetValue("nazhi_chef_name", out var value);
		return value ?? "";
	}

	internal static void SaveFoodSlotToProfile(Player p, int slot, string foodName, int chefLv, string chefName)
	{
		if ((Object)(object)p == (Object)null)
		{
			return;
		}
		string text = $"naz_food{slot}_name";
		string text2 = $"naz_food{slot}_lv";
		string text3 = $"naz_food{slot}_chef";
		try
		{
			MethodInfo method = typeof(Player).GetMethod("SetCustomData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				method.Invoke(p, new object[2]
				{
					text,
					foodName ?? ""
				});
				method.Invoke(p, new object[2]
				{
					text2,
					Mathf.Max(1, chefLv).ToString()
				});
				method.Invoke(p, new object[2]
				{
					text3,
					chefName ?? ""
				});
			}
			else if (typeof(Player).GetField("m_customData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(p) is Dictionary<string, string> dictionary)
			{
				dictionary[text] = foodName ?? "";
				dictionary[text2] = Mathf.Max(1, chefLv).ToString();
				dictionary[text3] = chefName ?? "";
			}
			TryInvokeGameSaveProfile();
		}
		catch (Exception ex)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)("[Cooking] SaveFoodSlotToProfile error: " + ex.Message));
		}
	}

	internal static bool LoadFoodSlotFromProfile(Player p, int slot, out string foodName, out int chefLv, out string chefName)
	{
		foodName = "";
		chefLv = 1;
		chefName = "Desconocido";
		if ((Object)(object)p == (Object)null)
		{
			return false;
		}
		string text = $"naz_food{slot}_name";
		string text2 = $"naz_food{slot}_lv";
		string text3 = $"naz_food{slot}_chef";
		try
		{
			MethodInfo method = typeof(Player).GetMethod("GetCustomData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				foodName = (method.Invoke(p, new object[1] { text }) as string) ?? "";
				string s = (method.Invoke(p, new object[1] { text2 }) as string) ?? "1";
				chefName = (method.Invoke(p, new object[1] { text3 }) as string) ?? "Desconocido";
				int.TryParse(s, out chefLv);
			}
			else if (typeof(Player).GetField("m_customData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(p) is Dictionary<string, string> dictionary)
			{
				dictionary.TryGetValue(text, out foodName);
				dictionary.TryGetValue(text3, out chefName);
				if (dictionary.TryGetValue(text2, out var value))
				{
					int.TryParse(value, out chefLv);
				}
			}
		}
		catch (Exception ex)
		{
			EinjarheimProfessionsPlugin.Log.LogWarning((object)("[Cooking] LoadFoodSlotFromProfile error: " + ex.Message));
		}
		chefLv = Mathf.Max(1, chefLv);
		if (string.IsNullOrEmpty(foodName))
		{
			return false;
		}
		if (string.IsNullOrEmpty(chefName))
		{
			chefName = "Desconocido";
		}
		return true;
	}

	private static bool TryInvokeGameSaveProfile()
	{
		try
		{
			Game instance = Game.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			Type typeFromHandle = typeof(Game);
			MethodInfo methodInfo = typeFromHandle.GetMethod("SavePlayerProfile", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeFromHandle.GetMethod("SavePlayerProfileThreadsafe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (methodInfo != null)
			{
				methodInfo.Invoke(instance, null);
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	internal static bool TryGetChefFromZDO(Player p, int slot, out string foodName, out int chefLv, out string chefName)
	{
		foodName = "";
		chefLv = 1;
		chefName = "Desconocido";
		if ((Object)(object)p == (Object)null)
		{
			return false;
		}
		ZNetView nview = ((Character)p).m_nview;
		ZDO val = ((nview != null) ? nview.GetZDO() : null);
		if (val == null)
		{
			return false;
		}
		switch (slot)
		{
		case 0:
			foodName = val.GetString("nazhi_food0_name", "");
			chefLv = Mathf.Max(1, val.GetInt("nazhi_food0_chef_lv", 1));
			chefName = val.GetString("nazhi_food0_chef_name", "Desconocido");
			break;
		case 1:
			foodName = val.GetString("nazhi_food1_name", "");
			chefLv = Mathf.Max(1, val.GetInt("nazhi_food1_chef_lv", 1));
			chefName = val.GetString("nazhi_food1_chef_name", "Desconocido");
			break;
		case 2:
			foodName = val.GetString("nazhi_food2_name", "");
			chefLv = Mathf.Max(1, val.GetInt("nazhi_food2_chef_lv", 1));
			chefName = val.GetString("nazhi_food2_chef_name", "Desconocido");
			break;
		}
		if (string.IsNullOrEmpty(foodName))
		{
			return false;
		}
		if (string.IsNullOrEmpty(chefName))
		{
			chefName = "Desconocido";
		}
		return true;
	}

	internal static void EnsureStampedFromFallback(ItemData item, int chefLv, string chefName)
	{
		if (item != null)
		{
			if (item.m_customData == null)
			{
				item.m_customData = new Dictionary<string, string>();
			}
			item.m_customData["nazhi_chef_cooking_lv"] = Mathf.Max(1, chefLv).ToString();
			item.m_customData["nazhi_chef_name"] = (string.IsNullOrEmpty(chefName) ? "Desconocido" : chefName);
		}
	}
}
[HarmonyPatch(typeof(ZNet), "Awake")]
internal static class Cooking_Patch_RegisterRpc
{
	private static void Postfix()
	{
		CookingSystem.RegisterRpc();
	}
}
[HarmonyPatch(typeof(ZNet), "Disconnect")]
internal static class Cooking_Patch_PeerDisconnect
{
	private static void Prefix(ZNetPeer peer)
	{
		if (peer != null)
		{
			long userID = ((ZDOID)(ref peer.m_characterID)).UserID;
			if (userID != 0)
			{
				CookingSystem.ClearPending(userID);
			}
		}
	}
}
[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
internal static class Cooking_Patch_Caldero_Pending
{
	private static void Prefix(InventoryGui __instance, Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		Recipe craftRecipe = __instance.m_craftRecipe;
		if (craftRecipe?.m_item?.m_itemData != null)
		{
			ItemData itemData = craftRecipe.m_item.m_itemData;
			if (CookingSystem.IsFood(itemData))
			{
				CookingSystem.SetPending(player, itemData.m_shared.m_name);
			}
		}
	}
}
[HarmonyPatch(typeof(CookingStation), "SpawnItem")]
internal static class Cooking_Patch_Station_SpawnItem
{
	private static void Prefix(CookingStation __instance, string name)
	{
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(name) || (Object)(object)ZNet.instance == (Object)null)
		{
			return;
		}
		ObjectDB instance = ObjectDB.instance;
		GameObject val = ((instance != null) ? instance.GetItemPrefab(name) : null);
		ItemData val2 = ((val == null) ? null : val.GetComponent<ItemDrop>()?.m_itemData);
		if (val2 == null || !CookingSystem.IsFood(val2))
		{
			return;
		}
		string text = val2.m_shared?.m_name;
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		Player val3 = Player.GetClosestPlayer(((Component)__instance).transform.position, 20f) ?? Player.m_localPlayer;
		if ((Object)(object)val3 == (Object)null)
		{
			return;
		}
		int vanillaCookingLevel = CookingSystem.GetVanillaCookingLevel(val3);
		string playerName = val3.GetPlayerName();
		if (ZNet.instance.IsServer() && ZNet.instance.IsDedicated())
		{
			long peerIDForPlayer = GetPeerIDForPlayer(val3);
			if (peerIDForPlayer != 0L && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(peerIDForPlayer, "nazhi_cooking_StampFood", new object[3] { text, vanillaCookingLevel, playerName });
				EinjarheimProfessionsPlugin.Log.LogInfo((object)$"[Cooking] SpawnItem RPC → peer={peerIDForPlayer} '{text}' chef={playerName} lv={vanillaCookingLevel}");
			}
		}
		else
		{
			CookingSystem.SetPending(val3, text, vanillaCookingLevel, playerName);
		}
	}

	private static long GetPeerIDForPlayer(Player player)
	{
		if ((Object)(object)player == (Object)null || (Object)(object)ZNet.instance == (Object)null)
		{
			return 0L;
		}
		long playerID = player.GetPlayerID();
		foreach (ZNetPeer peer in ZNet.instance.GetPeers())
		{
			if (peer != null && ((ZDOID)(ref peer.m_characterID)).UserID == playerID)
			{
				return peer.m_uid;
			}
		}
		return ZRoutedRpc.Everybody;
	}
}
[HarmonyPatch]
internal static class Cooking_Patch_Inventory_AddItem_Stamp
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in typeof(Inventory).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
			where m.Name == "AddItem"
			select m;
	}

	private static void Prefix(Inventory __instance, ref object __state, params object[] __args)
	{
		__state = null;
		if (__instance == null || __args == null)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || ((Humanoid)localPlayer).GetInventory() != __instance)
		{
			return;
		}
		foreach (object obj in __args)
		{
			ItemData val = (ItemData)((obj is ItemData) ? obj : null);
			if (val != null && CookingSystem.IsFood(val))
			{
				string name = val.m_shared.m_name;
				if (!CookingSystem.TryConsumePending(localPlayer, name, out var chef))
				{
					break;
				}
				CookingSystem.StampChef(val, chef);
				return;
			}
		}
		foreach (object obj2 in __args)
		{
			if (obj2 is string text && !string.IsNullOrEmpty(text))
			{
				__state = text;
				break;
			}
		}
	}

	private static void Postfix(Inventory __instance, object __state)
	{
		if (__instance == null || __state == null)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || ((Humanoid)localPlayer).GetInventory() != __instance)
		{
			return;
		}
		string text = __state as string;
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		string sharedName = text;
		if (!sharedName.StartsWith("$"))
		{
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab(sharedName) : null);
			ItemDrop val2 = ((val != null) ? val.GetComponent<ItemDrop>() : null);
			if (val2?.m_itemData?.m_shared != null)
			{
				sharedName = val2.m_itemData.m_shared.m_name;
			}
		}
		if (CookingSystem.TryConsumePending(localPlayer, sharedName, out var chef))
		{
			ItemData val3 = ((IEnumerable<ItemData>)__instance.GetAllItems()).LastOrDefault((Func<ItemData, bool>)((ItemData i) => i?.m_shared?.m_name == sharedName));
			if (val3 != null)
			{
				CookingSystem.StampChef(val3, chef);
			}
		}
	}
}
[HarmonyPatch]
internal static class Cooking_Patch_EatFood_Save
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
			where m.Name == "EatFood"
			select m;
	}

	private static void Prefix(Player __instance, ref object __state, params object[] __args)
	{
		__state = null;
		if ((Object)(object)__instance == (Object)null || __args == null)
		{
			return;
		}
		foreach (object obj in __args)
		{
			ItemData val = (ItemData)((obj is ItemData) ? obj : null);
			if (val != null && CookingSystem.IsFood(val))
			{
				__state = val;
				break;
			}
		}
	}

	private static void Postfix(Player __instance, object __state)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		ItemData val = (ItemData)((__state is ItemData) ? __state : null);
		if (val == null || !CookingSystem.IsFood(val))
		{
			return;
		}
		ZNetView nview = ((Character)__instance).m_nview;
		ZDO val2 = ((nview != null) ? nview.GetZDO() : null);
		if (val2 == null)
		{
			return;
		}
		int chefLevelFromItem = CookingSystem.GetChefLevelFromItem(val);
		string chefNameFromItem = CookingSystem.GetChefNameFromItem(val);
		string name = val.m_shared.m_name;
		IList<Food> list = (IList<Food>)AccessTools.Field(typeof(Player), "m_foods").GetValue(__instance);
		if (list == null)
		{
			return;
		}
		for (int i = 0; i < Mathf.Min(3, list.Count); i++)
		{
			if (!((list[i]?.m_item)?.m_shared?.m_name != name))
			{
				GetZdoKeys(i, out var name2, out var lv, out var chef);
				val2.Set(name2, name);
				val2.Set(lv, chefLevelFromItem);
				val2.Set(chef, chefNameFromItem);
				CookingSystem.SaveFoodSlotToProfile(__instance, i, name, chefLevelFromItem, chefNameFromItem);
				break;
			}
		}
	}

	private static void GetZdoKeys(int slot, out string name, out string lv, out string chef)
	{
		switch (slot)
		{
		case 0:
			name = "nazhi_food0_name";
			lv = "nazhi_food0_chef_lv";
			chef = "nazhi_food0_chef_name";
			break;
		case 1:
			name = "nazhi_food1_name";
			lv = "nazhi_food1_chef_lv";
			chef = "nazhi_food1_chef_name";
			break;
		default:
			name = "nazhi_food2_name";
			lv = "nazhi_food2_chef_lv";
			chef = "nazhi_food2_chef_name";
			break;
		}
	}
}
[HarmonyPatch(typeof(Player), "OnSpawned")]
internal static class Cooking_Patch_OnSpawned_Restore
{
	private static void Postfix(Player __instance)
	{
		if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
		{
			return;
		}
		ZNetView nview = ((Character)__instance).m_nview;
		ZDO val = ((nview != null) ? nview.GetZDO() : null);
		IList<Food> list = (IList<Food>)AccessTools.Field(typeof(Player), "m_foods").GetValue(__instance);
		for (int i = 0; i < 3; i++)
		{
			if (!CookingSystem.LoadFoodSlotFromProfile(__instance, i, out var foodName, out var chefLv, out var chefName))
			{
				continue;
			}
			if (val != null)
			{
				switch (i)
				{
				case 0:
					val.Set("nazhi_food0_name", foodName);
					val.Set("nazhi_food0_chef_lv", chefLv);
					val.Set("nazhi_food0_chef_name", chefName);
					break;
				case 1:
					val.Set("nazhi_food1_name", foodName);
					val.Set("nazhi_food1_chef_lv", chefLv);
					val.Set("nazhi_food1_chef_name", chefName);
					break;
				default:
					val.Set("nazhi_food2_name", foodName);
					val.Set("nazhi_food2_chef_lv", chefLv);
					val.Set("nazhi_food2_chef_name", chefName);
					break;
				}
			}
			if (list != null && i < list.Count)
			{
				ItemData val2 = list[i]?.m_item;
				if (val2?.m_shared?.m_name == foodName)
				{
					CookingSystem.EnsureStampedFromFallback(val2, chefLv, chefName);
				}
			}
		}
		if (((Character)__instance).GetSkillLevel((SkillType)105) < 1f)
		{
			((Character)__instance).RaiseSkill((SkillType)105, 0.5f);
		}
	}
}
[HarmonyPatch]
internal static class Cooking_Patch_Tooltip
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
			where m.Name == "GetTooltip" && m.ReturnType == typeof(string)
			select m;
	}

	private static void Postfix(ItemData __instance, ref string __result)
	{
		if (__instance?.m_shared != null && CookingSystem.IsFood(__instance))
		{
			int chefLevelFromItem = CookingSystem.GetChefLevelFromItem(__instance);
			string chefNameFromItem = CookingSystem.GetChefNameFromItem(__instance);
			CookingSystem.CalculateBonus(__instance, chefLevelFromItem, out var bonusHp, out var bonusSt, out var bonusEi);
			List<string> list = new List<string>();
			if (bonusHp > 0)
			{
				list.Add($"<color=#FF6666>HP +{bonusHp}</color>");
			}
			if (bonusSt > 0)
			{
				list.Add($"<color=#66FF99>Stamina +{bonusSt}</color>");
			}
			if (bonusEi > 0)
			{
				list.Add($"<color=#66CCFF>Eitr +{bonusEi}</color>");
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine();
			if (list.Count > 0)
			{
				stringBuilder.AppendLine("<color=#FFD34D>Bonus al comer:</color> " + string.Join(", ", list));
			}
			stringBuilder.AppendLine("<color=#88CCFF>Cocinado por:</color> <color=#FFFFFF>" + chefNameFromItem + "</color> " + $"<color=#FFFFAA>(Cooking Lv {chefLevelFromItem})</color>");
			if (!__result.Contains("Bonus al comer:") && !__result.Contains("Cocinado por:"))
			{
				__result += stringBuilder.ToString();
			}
		}
	}
}
[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
internal static class Cooking_Patch_TotalFoodValue
{
	private static readonly Dictionary<long, string> _lastSig = new Dictionary<long, string>();

	private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr)
	{
		if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
		{
			return;
		}
		IList<Food> list = (IList<Food>)AccessTools.Field(typeof(Player), "m_foods").GetValue(__instance);
		if (list == null || list.Count == 0)
		{
			return;
		}
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		List<string> list2 = new List<string>();
		for (int i = 0; i < list.Count; i++)
		{
			ItemData val = list[i]?.m_item;
			if (val?.m_shared != null)
			{
				string name = val.m_shared.m_name;
				int num4 = CookingSystem.GetChefLevelFromItem(val);
				string text = CookingSystem.GetChefNameFromItem(val);
				if (num4 <= 1 && text == "Desconocido" && CookingSystem.TryGetChefFromZDO(__instance, i, out var foodName, out var chefLv, out var chefName) && foodName == name)
				{
					num4 = chefLv;
					text = chefName;
					CookingSystem.EnsureStampedFromFallback(val, num4, text);
				}
				if (num4 <= 1 && text == "Desconocido" && CookingSystem.LoadFoodSlotFromProfile(__instance, i, out var foodName2, out var chefLv2, out var chefName2) && foodName2 == name)
				{
					num4 = chefLv2;
					text = chefName2;
					CookingSystem.EnsureStampedFromFallback(val, num4, text);
				}
				CookingSystem.CalculateBonus(val, num4, out var bonusHp, out var bonusSt, out var bonusEi);
				num += bonusHp;
				num2 += bonusSt;
				num3 += bonusEi;
				list2.Add($"{name}|{text}|Lv{num4}");
			}
		}
		hp += num;
		stamina += num2;
		eitr += num3;
		long playerID = __instance.GetPlayerID();
		string text2 = string.Join("##", list2);
		if (!_lastSig.TryGetValue(playerID, out var value) || value != text2)
		{
			_lastSig[playerID] = text2;
		}
	}
}
[HarmonyPatch]
internal static class Cooking_Patch_AddItem_Context
{
	[ThreadStatic]
	private static ItemData _incoming;

	internal static ItemData Incoming => _incoming;

	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in typeof(Inventory).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
			where m.Name == "AddItem" && m.GetParameters().Length != 0 && m.GetParameters()[0].ParameterType == typeof(ItemData)
			select m;
	}

	private static void Prefix(ItemData item)
	{
		_incoming = item;
	}

	private static void Finalizer()
	{
		_incoming = null;
	}
}
[HarmonyPatch(typeof(Inventory), "FindFreeStackItem")]
internal static class Cooking_Patch_FindFreeStackItem
{
	private static bool Prefix(Inventory __instance, string name, int quality, float worldLevel, ref ItemData __result)
	{
		ItemData incoming = Cooking_Patch_AddItem_Context.Incoming;
		if (incoming == null || !CookingSystem.IsFood(incoming))
		{
			return true;
		}
		int chefLevelFromItem = CookingSystem.GetChefLevelFromItem(incoming);
		foreach (ItemData item in __instance.m_inventory)
		{
			if (item?.m_shared?.m_name != name || item.m_quality != quality || item.m_stack >= item.m_shared.m_maxStackSize || (double)item.m_worldLevel != (double)worldLevel || CookingSystem.GetChefLevelFromItem(item) != chefLevelFromItem)
			{
				continue;
			}
			__result = item;
			return false;
		}
		__result = null;
		return false;
	}
}
[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
{
	typeof(ItemData),
	typeof(int)
})]
internal static class Cooking_Patch_CanAddItem
{
	private static bool Prefix(Inventory __instance, ItemData item, int stack, ref bool __result)
	{
		if (item == null || !CookingSystem.IsFood(item))
		{
			return true;
		}
		if (stack <= 0)
		{
			stack = item.m_stack;
		}
		int chefLevelFromItem = CookingSystem.GetChefLevelFromItem(item);
		int num = 0;
		foreach (ItemData item2 in __instance.m_inventory)
		{
			if (!(item2?.m_shared?.m_name != item.m_shared.m_name) && (double)item2.m_worldLevel == (double)item.m_worldLevel && (item2.m_shared.m_maxQuality <= 1 || item2.m_quality == item.m_quality) && item2.m_stack < item2.m_shared.m_maxStackSize && CookingSystem.GetChefLevelFromItem(item2) == chefLevelFromItem)
			{
				num += item2.m_shared.m_maxStackSize - item2.m_stack;
			}
		}
		int num2 = __instance.m_width * __instance.m_height - __instance.m_inventory.Count;
		int num3 = num2 * item.m_shared.m_maxStackSize;
		__result = num + num3 >= stack;
		return false;
	}
}
[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
{
	typeof(ItemData),
	typeof(int),
	typeof(int),
	typeof(int)
})]
internal static class Cooking_Patch_AddItemXY
{
	private static bool Prefix(Inventory __instance, ItemData item, int amount, int x, int y, ref bool __result)
	{
		if (item == null || !CookingSystem.IsFood(item))
		{
			return true;
		}
		ItemData itemAt = __instance.GetItemAt(x, y);
		if (itemAt == null)
		{
			return true;
		}
		if (CookingSystem.IsFood(itemAt) && itemAt.m_shared?.m_name == item.m_shared?.m_name && CookingSystem.GetChefLevelFromItem(itemAt) != CookingSystem.GetChefLevelFromItem(item))
		{
			__result = false;
			return false;
		}
		return true;
	}
}

Rarity.dll

Decompiled 3 days 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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Testing2")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Testing2")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("55CC6F29-0D48-4124-93BF-F657DE656B82")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 YourModName
{
	public enum ItemRarity
	{
		Common,
		Uncommon,
		Rare,
		Epic,
		Legendary
	}
	public static class RarityData
	{
		public static readonly Dictionary<ItemRarity, RarityInfo> Info = new Dictionary<ItemRarity, RarityInfo>
		{
			{
				ItemRarity.Common,
				new RarityInfo
				{
					Name = "Common",
					Color = new Color(1f, 1f, 1f),
					StatBonus = 0f,
					SlotCount = 0,
					Weight = 50f
				}
			},
			{
				ItemRarity.Uncommon,
				new RarityInfo
				{
					Name = "Uncommon",
					Color = new Color(0.3f, 0.85f, 0.3f),
					StatBonus = 0.05f,
					SlotCount = 1,
					Weight = 25f
				}
			},
			{
				ItemRarity.Rare,
				new RarityInfo
				{
					Name = "Rare",
					Color = new Color(0.3f, 0.5f, 1f),
					StatBonus = 0.1f,
					SlotCount = 2,
					Weight = 15f
				}
			},
			{
				ItemRarity.Epic,
				new RarityInfo
				{
					Name = "Epic",
					Color = new Color(0.7f, 0.3f, 1f),
					StatBonus = 0.15f,
					SlotCount = 3,
					Weight = 5f
				}
			},
			{
				ItemRarity.Legendary,
				new RarityInfo
				{
					Name = "Legendary",
					Color = new Color(1f, 0.85f, 0.1f),
					StatBonus = 0.2f,
					SlotCount = 4,
					Weight = 0f
				}
			}
		};

		public static ItemRarity RollRarity()
		{
			float num = 0f;
			foreach (KeyValuePair<ItemRarity, RarityInfo> item in Info)
			{
				num += item.Value.Weight;
			}
			float num2 = Random.Range(0f, num);
			float num3 = 0f;
			foreach (KeyValuePair<ItemRarity, RarityInfo> item2 in Info)
			{
				num3 += item2.Value.Weight;
				if (num2 < num3)
				{
					return item2.Key;
				}
			}
			return ItemRarity.Common;
		}
	}
	public class RarityInfo
	{
		public string Name;

		public Color Color;

		public float StatBonus;

		public int SlotCount;

		public float Weight;
	}
	public class RarityItemData
	{
		public ItemRarity Rarity;

		public int SlotCount;

		public List<string> InsertedScrollIds;

		public float BasePierce;

		public float BaseBlunt;

		public float BaseSlash;

		public float BaseFire;

		public float BaseFrost;

		public float BaseLightning;

		public float BaseSpirit;

		public float BasePoison;

		public float BaseArmor;

		public float BaseBlockPower;

		private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;

		public int FilledSlots => InsertedScrollIds.FindAll((string s) => !string.IsNullOrEmpty(s)).Count;

		public int EmptySlots => SlotCount - FilledSlots;

		public bool HasFreeSlot => EmptySlots > 0;

		public bool HasBaseDamages => BasePierce > 0f || BaseBlunt > 0f || BaseSlash > 0f || BaseFire > 0f || BaseFrost > 0f || BaseLightning > 0f || BaseSpirit > 0f || BasePoison > 0f;

		public RarityItemData()
		{
		}

		public RarityItemData(ItemRarity rarity)
		{
			Rarity = rarity;
			SlotCount = RarityData.Info[rarity].SlotCount;
			InsertedScrollIds = new List<string>();
			for (int i = 0; i < SlotCount; i++)
			{
				InsertedScrollIds.Add(string.Empty);
			}
		}

		public void SaveBaseDamages(ItemData item)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			DamageTypes damages = item.m_shared.m_damages;
			BasePierce = damages.m_pierce;
			BaseBlunt = damages.m_blunt;
			BaseSlash = damages.m_slash;
			BaseFire = damages.m_fire;
			BaseFrost = damages.m_frost;
			BaseLightning = damages.m_lightning;
			BaseSpirit = damages.m_spirit;
			BasePoison = damages.m_poison;
			BaseArmor = item.m_shared.m_armor;
			BaseBlockPower = item.m_shared.m_blockPower;
			Logger.LogInfo((object)($"[SaveBase] {item.m_shared.m_name} q={item.m_quality} " + $"BaseArmor={BaseArmor:0.##} BaseBlockPower={BaseBlockPower:0.##}"));
		}

		public void RestoreBaseDamages(ItemData item)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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)
			DamageTypes damages = item.m_shared.m_damages;
			damages.m_pierce = BasePierce;
			damages.m_blunt = BaseBlunt;
			damages.m_slash = BaseSlash;
			damages.m_fire = BaseFire;
			damages.m_frost = BaseFrost;
			damages.m_lightning = BaseLightning;
			damages.m_spirit = BaseSpirit;
			damages.m_poison = BasePoison;
			item.m_shared.m_damages = damages;
		}

		public bool InsertScroll(string scrollPerkId)
		{
			for (int i = 0; i < InsertedScrollIds.Count; i++)
			{
				if (string.IsNullOrEmpty(InsertedScrollIds[i]))
				{
					InsertedScrollIds[i] = scrollPerkId;
					return true;
				}
			}
			return false;
		}

		public string RemoveScroll(int slotIndex)
		{
			if (slotIndex < 0 || slotIndex >= InsertedScrollIds.Count)
			{
				return string.Empty;
			}
			string result = InsertedScrollIds[slotIndex];
			InsertedScrollIds[slotIndex] = string.Empty;
			return result;
		}

		public string Serialize()
		{
			string text = string.Join(",", InsertedScrollIds);
			string text2 = string.Join(";", BasePierce.ToString("F4", Inv), BaseBlunt.ToString("F4", Inv), BaseSlash.ToString("F4", Inv), BaseFire.ToString("F4", Inv), BaseFrost.ToString("F4", Inv), BaseLightning.ToString("F4", Inv), BaseSpirit.ToString("F4", Inv), BasePoison.ToString("F4", Inv), BaseArmor.ToString("F4", Inv), BaseBlockPower.ToString("F4", Inv));
			return $"{(int)Rarity}|{SlotCount}|{text}|{text2}";
		}

		public static RarityItemData Deserialize(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return null;
			}
			string[] array = raw.Split(new char[1] { '|' });
			if (array.Length < 1)
			{
				return null;
			}
			RarityItemData rarityItemData = new RarityItemData();
			if (int.TryParse(array[0], out var result))
			{
				rarityItemData.Rarity = (ItemRarity)result;
			}
			if (array.Length > 1 && int.TryParse(array[1], out var result2))
			{
				rarityItemData.SlotCount = result2;
			}
			else
			{
				rarityItemData.SlotCount = RarityData.Info[rarityItemData.Rarity].SlotCount;
			}
			rarityItemData.InsertedScrollIds = new List<string>();
			if (array.Length > 2 && !string.IsNullOrEmpty(array[2]))
			{
				string[] array2 = array[2].Split(new char[1] { ',' });
				foreach (string item in array2)
				{
					rarityItemData.InsertedScrollIds.Add(item);
				}
			}
			while (rarityItemData.InsertedScrollIds.Count < rarityItemData.SlotCount)
			{
				rarityItemData.InsertedScrollIds.Add(string.Empty);
			}
			string[] d;
			if (array.Length > 3 && !string.IsNullOrEmpty(array[3]))
			{
				d = array[3].Split(new char[1] { ';' });
				rarityItemData.BasePierce = F(0);
				rarityItemData.BaseBlunt = F(1);
				rarityItemData.BaseSlash = F(2);
				rarityItemData.BaseFire = F(3);
				rarityItemData.BaseFrost = F(4);
				rarityItemData.BaseLightning = F(5);
				rarityItemData.BaseSpirit = F(6);
				rarityItemData.BasePoison = F(7);
				rarityItemData.BaseArmor = F(8);
				rarityItemData.BaseBlockPower = F(9);
			}
			return rarityItemData;
			float F(int i)
			{
				float result3;
				return (d.Length > i && float.TryParse(d[i], NumberStyles.Float, Inv, out result3)) ? result3 : 0f;
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "RemoveObjects")]
	public static class ZNetScene_RemoveObjects_NullSafePatch
	{
		[HarmonyPrefix]
		public static void Prefix(ZNetScene __instance)
		{
			List<ZDO> list = new List<ZDO>();
			foreach (KeyValuePair<ZDO, ZNetView> instance in __instance.m_instances)
			{
				if ((Object)(object)instance.Value == (Object)null || (Object)(object)((Component)instance.Value).gameObject == (Object)null)
				{
					list.Add(instance.Key);
				}
			}
			foreach (ZDO item in list)
			{
				__instance.m_instances.Remove(item);
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Shutdown")]
	public static class ZNetScene_Shutdown_NullSafePatch
	{
		[HarmonyPrefix]
		public static void Prefix(ZNetScene __instance)
		{
			List<ZDO> list = new List<ZDO>();
			foreach (KeyValuePair<ZDO, ZNetView> instance in __instance.m_instances)
			{
				if ((Object)(object)instance.Value == (Object)null || (Object)(object)((Component)instance.Value).gameObject == (Object)null)
				{
					list.Add(instance.Key);
				}
			}
			foreach (ZDO item in list)
			{
				__instance.m_instances.Remove(item);
			}
		}
	}
	[HarmonyPatch]
	public static class RarityItemVFX
	{
		[CompilerGenerated]
		private sealed class <ApplyVFXNextFrame>d__2 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public ItemDrop drop;

			private float <timeout>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ApplyVFXNextFrame>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)drop == (Object)null || (Object)(object)((Component)drop).gameObject == (Object)null)
					{
						return false;
					}
					<timeout>5__1 = 5f;
					goto IL_00b4;
				case 2:
					<>1__state = -1;
					<timeout>5__1 -= 0.2f;
					goto IL_00b4;
				case 3:
					{
						<>1__state = -1;
						if ((Object)(object)drop == (Object)null || (Object)(object)((Component)drop).gameObject == (Object)null)
						{
							return false;
						}
						ApplyVFX(drop);
						return false;
					}
					IL_00b4:
					if (<timeout>5__1 > 0f && ((Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).IsTeleporting()))
					{
						<>2__current = (object)new WaitForSeconds(0.2f);
						<>1__state = 2;
						return true;
					}
					<>2__current = null;
					<>1__state = 3;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const string VFX_CHILD_NAME = "RarityVFX";

		[HarmonyPatch(typeof(ItemDrop), "Start")]
		[HarmonyPostfix]
		public static void ItemDrop_Start_Postfix(ItemDrop __instance)
		{
			((MonoBehaviour)__instance).StartCoroutine(ApplyVFXNextFrame(__instance));
		}

		[IteratorStateMachine(typeof(<ApplyVFXNextFrame>d__2))]
		private static IEnumerator ApplyVFXNextFrame(ItemDrop drop)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ApplyVFXNextFrame>d__2(0)
			{
				drop = drop
			};
		}

		public static void ApplyVFX(ItemDrop drop)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: 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)
			//IL_01a4: Expected O, but got Unknown
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Expected O, but got Unknown
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)drop == (Object)null)
			{
				return;
			}
			ItemData itemData = drop.m_itemData;
			if (itemData == null)
			{
				return;
			}
			Color color;
			if (ScrollItem.IsEnchantScroll(itemData))
			{
				ScrollItem.TryGetScrollTier(itemData, out var rarity);
				if (rarity == ItemRarity.Common)
				{
					return;
				}
				color = RarityData.Info[rarity].Color;
			}
			else
			{
				if (!RarityPatches.IsWeaponOrArmor(itemData))
				{
					return;
				}
				RarityItemData rarityItemData = RarityTooltip.Get(itemData);
				if (rarityItemData == null || rarityItemData.Rarity == ItemRarity.Common)
				{
					return;
				}
				color = RarityData.Info[rarityItemData.Rarity].Color;
			}
			Transform val = FindDeep(((Component)drop).transform, "fx_ItemSparkles");
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)("[Rarity VFX] No se encontró fx_ItemSparkles en " + ((Object)drop).name));
				return;
			}
			ParticleSystem[] componentsInChildren = ((Component)val).GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val2 in componentsInChildren)
			{
				MainModule main = val2.main;
				((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(color.r, color.g, color.b, 1f), new Color(color.r, color.g, color.b, 0.4f));
				((MainModule)(ref main)).maxParticles = 100;
				((MainModule)(ref main)).simulationSpeed = 1f;
				EmissionModule emission = val2.emission;
				((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(50f);
				ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
				if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled)
				{
					Gradient val3 = new Gradient();
					val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
					{
						new GradientColorKey(color, 0f),
						new GradientColorKey(color, 1f)
					}, (GradientAlphaKey[])(object)new GradientAlphaKey[2]
					{
						new GradientAlphaKey(1f, 0f),
						new GradientAlphaKey(0f, 1f)
					});
					((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val3);
				}
				ParticleSystemRenderer component = ((Component)val2).GetComponent<ParticleSystemRenderer>();
				if ((Object)(object)component != (Object)null && (Object)(object)((Renderer)component).material != (Object)null)
				{
					Material val4 = new Material(((Renderer)component).material);
					if (val4.HasProperty("_Color"))
					{
						val4.SetColor("_Color", color);
					}
					if (val4.HasProperty("_TintColor"))
					{
						val4.SetColor("_TintColor", color);
					}
					if (val4.HasProperty("_EmissionColor"))
					{
						val4.SetColor("_EmissionColor", color * 2f);
					}
					((Renderer)component).material = val4;
				}
			}
			val.localScale = new Vector3(1f, 4f, 1f);
			Logger.LogInfo((object)("[Rarity VFX] " + ((Object)drop).name + " recoloreado | color #" + ColorUtility.ToHtmlStringRGB(color)));
		}

		private static Transform FindDeep(Transform parent, string name)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			foreach (Transform item in parent)
			{
				Transform val = item;
				if (((Object)val).name == name)
				{
					return val;
				}
				Transform val2 = FindDeep(val, name);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}
	}
	[HarmonyPatch]
	public static class RarityPatches
	{
		private static ItemRarity? _pendingRarity;

		private static string _pendingItemName;

		private static List<string> _pendingScrollIds;

		private static bool _addItemProcessing;

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		[HarmonyPrefix]
		public static void DoCrafting_Prefix(InventoryGui __instance)
		{
			_pendingRarity = null;
			_pendingItemName = null;
			_pendingScrollIds = null;
			ItemData craftUpgradeItem = __instance.m_craftUpgradeItem;
			if (craftUpgradeItem != null && IsWeaponOrArmor(craftUpgradeItem))
			{
				RarityItemData rarityItemData = RarityTooltip.Get(craftUpgradeItem);
				if (rarityItemData != null)
				{
					_pendingRarity = rarityItemData.Rarity;
					_pendingItemName = craftUpgradeItem.m_shared.m_name;
					_pendingScrollIds = new List<string>(rarityItemData.InsertedScrollIds);
					Logger.LogInfo((object)("[RarityUpgrade] PREFIX capturado: " + _pendingItemName + " " + $"rarity={_pendingRarity} scrolls={_pendingScrollIds.Count}"));
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		[HarmonyPostfix]
		public static void DoCrafting_Postfix(InventoryGui __instance, Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (IsWeaponOrArmor(allItem))
				{
					if (_pendingRarity.HasValue && allItem.m_shared.m_name == _pendingItemName && allItem.m_quality > 1 && !allItem.m_customData.ContainsKey("RarityData"))
					{
						RarityItemData rarityItemData = new RarityItemData(_pendingRarity.Value);
						rarityItemData.InsertedScrollIds = new List<string>(_pendingScrollIds);
						rarityItemData.SaveBaseDamages(allItem);
						ApplyStatBonusToDamages(allItem, rarityItemData);
						ApplyStatBonusToArmor(allItem, rarityItemData);
						ApplyStatBonusToBlockPower(allItem, rarityItemData);
						EnchantBonusManager.RefreshSingleItem(allItem);
						RarityTooltip.Save(allItem, rarityItemData);
						Logger.LogInfo((object)("[RarityUpgrade] POSTFIX transferido: " + allItem.m_shared.m_name + " " + $"q={allItem.m_quality} rarity={rarityItemData.Rarity}"));
					}
					else if (!allItem.m_customData.ContainsKey("RarityData") && allItem.m_quality <= 1)
					{
						RarityItemData orCreate = RarityTooltip.GetOrCreate(allItem);
						orCreate.SaveBaseDamages(allItem);
						ApplyStatBonusToDamages(allItem, orCreate);
						ApplyStatBonusToArmor(allItem, orCreate);
						ApplyStatBonusToBlockPower(allItem, orCreate);
						RarityTooltip.Save(allItem, orCreate);
					}
				}
			}
			_pendingRarity = null;
			_pendingItemName = null;
			_pendingScrollIds = null;
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(string),
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(long),
			typeof(string),
			typeof(Vector2i),
			typeof(bool)
		})]
		[HarmonyPostfix]
		public static void AddItem_Postfix(ref ItemData __result)
		{
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			if (__result == null || !IsWeaponOrArmor(__result) || __result.m_quality <= 1)
			{
				return;
			}
			RarityItemData rarityItemData = RarityTooltip.Get(__result);
			if (rarityItemData == null || _addItemProcessing)
			{
				return;
			}
			_addItemProcessing = true;
			try
			{
				ObjectDB instance = ObjectDB.instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					GameObject dropPrefab = __result.m_dropPrefab;
					obj = instance.GetItemPrefab(((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? "");
				}
				GameObject val = (GameObject)obj;
				ItemData val2 = ((val == null) ? null : val.GetComponent<ItemDrop>()?.m_itemData);
				if (val2 == null && (Object)(object)ObjectDB.instance != (Object)null)
				{
					foreach (GameObject item in ObjectDB.instance.m_items)
					{
						ItemDrop val3 = ((item != null) ? item.GetComponent<ItemDrop>() : null);
						if (val3?.m_itemData?.m_shared?.m_name == __result.m_shared.m_name)
						{
							val2 = val3.m_itemData;
							break;
						}
					}
				}
				if (val2 != null)
				{
					float baseArmor = val2.m_shared.m_armor + val2.m_shared.m_armorPerLevel * (float)(__result.m_quality - 1);
					rarityItemData.BaseArmor = baseArmor;
					float num = val2.m_shared.m_blockPower + val2.m_shared.m_blockPowerPerLevel * (float)(__result.m_quality - 1);
					if (num > 0f)
					{
						rarityItemData.BaseBlockPower = num;
					}
					DamageTypes damages = val2.m_shared.m_damages;
					DamageTypes damagesPerLevel = val2.m_shared.m_damagesPerLevel;
					if (damages.m_pierce > 0f)
					{
						rarityItemData.BasePierce = damages.m_pierce + damagesPerLevel.m_pierce * (float)(__result.m_quality - 1);
					}
					if (damages.m_blunt > 0f)
					{
						rarityItemData.BaseBlunt = damages.m_blunt + damagesPerLevel.m_blunt * (float)(__result.m_quality - 1);
					}
					if (damages.m_slash > 0f)
					{
						rarityItemData.BaseSlash = damages.m_slash + damagesPerLevel.m_slash * (float)(__result.m_quality - 1);
					}
					if (damages.m_fire > 0f)
					{
						rarityItemData.BaseFire = damages.m_fire + damagesPerLevel.m_fire * (float)(__result.m_quality - 1);
					}
					if (damages.m_frost > 0f)
					{
						rarityItemData.BaseFrost = damages.m_frost + damagesPerLevel.m_frost * (float)(__result.m_quality - 1);
					}
					if (damages.m_lightning > 0f)
					{
						rarityItemData.BaseLightning = damages.m_lightning + damagesPerLevel.m_lightning * (float)(__result.m_quality - 1);
					}
					if (damages.m_spirit > 0f)
					{
						rarityItemData.BaseSpirit = damages.m_spirit + damagesPerLevel.m_spirit * (float)(__result.m_quality - 1);
					}
					if (damages.m_poison > 0f)
					{
						rarityItemData.BasePoison = damages.m_poison + damagesPerLevel.m_poison * (float)(__result.m_quality - 1);
					}
				}
				else
				{
					float num2 = 1f + RarityData.Info[rarityItemData.Rarity].StatBonus;
					float num3 = rarityItemData.BaseArmor * num2;
					bool flag = Mathf.Abs(__result.m_shared.m_armor - num3) < 0.2f;
					if (rarityItemData.BaseArmor > 0f && flag)
					{
						rarityItemData.BaseArmor = __result.m_shared.m_armor / num2;
					}
					else if (rarityItemData.BaseArmor <= 0f)
					{
						rarityItemData.SaveBaseDamages(__result);
					}
					float num4 = rarityItemData.BaseBlockPower * num2;
					bool flag2 = Mathf.Abs(__result.m_shared.m_blockPower - num4) < 0.2f;
					if (rarityItemData.BaseBlockPower > 0f && flag2)
					{
						rarityItemData.BaseBlockPower = __result.m_shared.m_blockPower / num2;
					}
				}
				ApplyStatBonusToDamages(__result, rarityItemData);
				ApplyStatBonusToArmor(__result, rarityItemData);
				ApplyStatBonusToBlockPower(__result, rarityItemData);
				EnchantBonusManager.RefreshSingleItem(__result);
				RarityTooltip.Save(__result, rarityItemData);
			}
			finally
			{
				_addItemProcessing = false;
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
		[HarmonyPostfix]
		public static void UpdateGui_Postfix(InventoryGrid __instance)
		{
			//IL_0046: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: 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)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = __instance.m_inventory;
			if (inventory == null)
			{
				return;
			}
			foreach (Element element in __instance.m_elements)
			{
				if (!element.m_used)
				{
					((Graphic)element.m_icon).color = Color.white;
					continue;
				}
				ItemData itemAt = inventory.GetItemAt(element.m_pos.x, element.m_pos.y);
				if (itemAt == null)
				{
					((Graphic)element.m_icon).color = Color.white;
					continue;
				}
				if (ScrollItem.IsEnchantScroll(itemAt))
				{
					ScrollItem.TryGetScrollTier(itemAt, out var rarity);
					Color color = RarityData.Info[rarity].Color;
					((Graphic)element.m_icon).color = Color.Lerp(Color.white, color, 0.45f);
					string text = ColorUtility.ToHtmlStringRGB(color);
					element.m_tooltip.m_topic = "<color=#" + text + ">" + itemAt.m_shared.m_name + "</color>";
					continue;
				}
				RarityItemData rarityItemData = RarityTooltip.Get(itemAt);
				if (rarityItemData == null || rarityItemData.Rarity == ItemRarity.Common)
				{
					((Graphic)element.m_icon).color = Color.white;
					element.m_tooltip.m_topic = itemAt.m_shared.m_name;
					continue;
				}
				Color color2 = RarityData.Info[rarityItemData.Rarity].Color;
				((Graphic)element.m_icon).color = Color.Lerp(Color.white, color2, 0.35f);
				string text2 = ColorUtility.ToHtmlStringRGB(color2);
				element.m_tooltip.m_topic = "<color=#" + text2 + ">" + itemAt.m_shared.m_name + "</color>";
			}
		}

		public static bool IsWeaponOrArmor(ItemData item)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			ItemType itemType = item.m_shared.m_itemType;
			return (int)itemType == 3 || (int)itemType == 14 || (int)itemType == 4 || (int)itemType == 5 || (int)itemType == 6 || (int)itemType == 7 || (int)itemType == 11 || (int)itemType == 17 || (int)itemType == 18;
		}

		public static void ApplyStatBonusToDamages(ItemData item, RarityItemData data)
		{
			//IL_004b: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			if (data.Rarity != 0 && data.HasBaseDamages)
			{
				float num = 1f + RarityData.Info[data.Rarity].StatBonus;
				DamageTypes damages = item.m_shared.m_damages;
				DamageTypes damagesPerLevel = item.m_shared.m_damagesPerLevel;
				float num2 = item.m_quality - 1;
				if (data.BasePierce > 0f)
				{
					damages.m_pierce = data.BasePierce * num - damagesPerLevel.m_pierce * num2;
				}
				if (data.BaseBlunt > 0f)
				{
					damages.m_blunt = data.BaseBlunt * num - damagesPerLevel.m_blunt * num2;
				}
				if (data.BaseSlash > 0f)
				{
					damages.m_slash = data.BaseSlash * num - damagesPerLevel.m_slash * num2;
				}
				if (data.BaseFire > 0f)
				{
					damages.m_fire = data.BaseFire * num - damagesPerLevel.m_fire * num2;
				}
				if (data.BaseFrost > 0f)
				{
					damages.m_frost = data.BaseFrost * num - damagesPerLevel.m_frost * num2;
				}
				if (data.BaseLightning > 0f)
				{
					damages.m_lightning = data.BaseLightning * num - damagesPerLevel.m_lightning * num2;
				}
				if (data.BaseSpirit > 0f)
				{
					damages.m_spirit = data.BaseSpirit * num - damagesPerLevel.m_spirit * num2;
				}
				if (data.BasePoison > 0f)
				{
					damages.m_poison = data.BasePoison * num - damagesPerLevel.m_poison * num2;
				}
				item.m_shared.m_damages = damages;
			}
		}

		public static void ApplyStatBonusToArmor(ItemData item, RarityItemData data)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			if (data.Rarity != 0 && !(data.BaseArmor <= 0f))
			{
				ItemType itemType = item.m_shared.m_itemType;
				if ((int)itemType == 6 || (int)itemType == 7 || (int)itemType == 11 || (int)itemType == 17)
				{
					float num = 1f + RarityData.Info[data.Rarity].StatBonus;
					float num2 = item.m_shared.m_armorPerLevel * (float)(item.m_quality - 1);
					item.m_shared.m_armor = data.BaseArmor * num - num2;
				}
			}
		}

		public static void ApplyStatBonusToBlockPower(ItemData item, RarityItemData data)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			if (data.Rarity != 0 && !(data.BaseBlockPower <= 0f) && (int)item.m_shared.m_itemType == 5)
			{
				float num = 1f + RarityData.Info[data.Rarity].StatBonus;
				float num2 = item.m_shared.m_blockPowerPerLevel * (float)(item.m_quality - 1);
				item.m_shared.m_blockPower = data.BaseBlockPower * num - num2;
			}
		}
	}
	[HarmonyPatch]
	public static class GetTooltip_Patch
	{
		private static MethodBase TargetMethod()
		{
			return typeof(ItemData).GetMethod("GetTooltip", BindingFlags.Static | BindingFlags.Public, null, new Type[5]
			{
				typeof(ItemData),
				typeof(int),
				typeof(bool),
				typeof(float),
				typeof(int)
			}, null);
		}

		[HarmonyPostfix]
		public static void Postfix(ItemData item, ref string __result)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (item == null)
			{
				return;
			}
			if (ScrollItem.IsEnchantScroll(item))
			{
				ScrollItem.TryGetScrollTier(item, out var rarity);
				RarityInfo rarityInfo = RarityData.Info[rarity];
				string text = ColorUtility.ToHtmlStringRGB(rarityInfo.Color);
				Logger.LogInfo((object)$"[TooltipPatch] IsScroll=true revealed={ScrollItem.IsRevealed(item)} rarity={rarity}");
				item.m_customData.TryGetValue("ScrollPerk", out var value);
				Logger.LogInfo((object)("[TooltipPatch] perkKey='" + value + "'"));
				string text2 = "";
				if (item.m_customData.TryGetValue("ScrollPerk", out var value2) && !string.IsNullOrEmpty(value2))
				{
					string[] array = value2.Split(new char[1] { ':' });
					ScrollPerkDef byName = ScrollPerkRegistry.GetByName(array[0]);
					if (byName != null)
					{
						string text3 = ((array.Length == 2) ? ("Perk: " + byName.DisplayName + "\n" + byName.GetDisplayText(rarity) + " vs " + array[1]) : byName.GetTooltipDescription(rarity));
						text2 = "\n<color=#aaaaaa>Equipable en: " + byName.GetEquipableLabel() + "</color>\n<color=#" + text + ">" + text3 + "</color>";
					}
				}
				__result = "<color=#" + text + "><b>Scroll: " + rarityInfo.Name + "</b></color>" + text2 + "\n" + (ScrollItem.IsRevealed(item) ? "Click derecho para encantar" : "Click derecho para desbloquear") + ".";
				return;
			}
			RarityItemData rarityItemData = RarityTooltip.Get(item);
			if (rarityItemData == null || rarityItemData.Rarity == ItemRarity.Common)
			{
				return;
			}
			string value3 = "Tier: " + RarityData.Info[rarityItemData.Rarity].Name;
			if (__result == null || !__result.Contains(value3))
			{
				__result = RarityTooltip.ColorizeHeader(__result, rarityItemData);
				__result = RarityTooltip.ReplaceDamageLines(__result, rarityItemData, item);
				__result = RarityTooltip.ReplaceArmorLine(__result, rarityItemData, item);
				__result = RarityTooltip.ReplaceBlockPowerLine(__result, rarityItemData, item);
				string text4 = RarityTooltip.BuildTooltipAddition(rarityItemData, item);
				if (!string.IsNullOrEmpty(text4))
				{
					__result = __result + "\n" + text4;
				}
			}
		}
	}
	[BepInPlugin("com.tuusuario.valheim.rarity", "ItemRaritySystem", "0.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class RarityPlugin : BaseUnityPlugin
	{
		public const string ModGUID = "com.tuusuario.valheim.rarity";

		public const string ModName = "ItemRaritySystem";

		public const string ModVersion = "0.2.0";

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			Logger.LogInfo((object)"[ItemRaritySystem] Cargando sistema de rareza v0.2.0...");
			_harmony = new Harmony("com.tuusuario.valheim.rarity");
			_harmony.PatchAll();
			ScrollItem.Register();
			GUIManager.OnCustomGUIAvailable += CreateScrollUI;
			Logger.LogInfo((object)"[ItemRaritySystem] ¡Listo! Patches aplicados.");
		}

		private void CreateScrollUI()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)ScrollEnchantUI.Instance != (Object)null))
			{
				GameObject val = new GameObject("ScrollEnchantUI");
				Object.DontDestroyOnLoad((Object)(object)val);
				val.AddComponent<ScrollEnchantUI>();
			}
		}

		private void OnDestroy()
		{
			GUIManager.OnCustomGUIAvailable -= CreateScrollUI;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class RarityTooltip
	{
		private const string CUSTOM_DATA_KEY = "RarityData";

		private const string SMITH_LEVEL_KEY = "nazhi_blacksmith_lvl";

		private const float SMITH_DAMAGE_ARMOR_MAX_100 = 1f;

		private static readonly Dictionary<ItemRarity, string> SlotFilledChar = new Dictionary<ItemRarity, string>
		{
			{
				ItemRarity.Common,
				"\ud83d\udc8e"
			},
			{
				ItemRarity.Uncommon,
				"\ud83d\udc8e"
			},
			{
				ItemRarity.Rare,
				"\ud83d\udc8e"
			},
			{
				ItemRarity.Epic,
				"\ud83d\udc8e"
			},
			{
				ItemRarity.Legendary,
				"\ud83d\udc8e"
			}
		};

		private const string SLOT_EMPTY = "\ud83d\udd28";

		private const string SEP = "━━━━━━━━━━━━━━━━";

		private static readonly string[] ItemTypeKeys = new string[14]
		{
			"$item_onehanded", "$item_twohanded", "$item_bow", "$item_shield", "$item_helmet", "$item_chest", "$item_legs", "$item_shoulder", "$item_utility", "$item_tool",
			"$item_ammo", "$item_trophy", "$item_consumable", "$item_material"
		};

		public static string ColorizeHeader(string tooltip, RarityItemData data)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(tooltip) || data == null || data.Rarity == ItemRarity.Common)
			{
				return tooltip;
			}
			RarityInfo rarityInfo = RarityData.Info[data.Rarity];
			string text = ColorUtility.ToHtmlStringRGB(rarityInfo.Color);
			string text2 = null;
			string[] itemTypeKeys = ItemTypeKeys;
			foreach (string text3 in itemTypeKeys)
			{
				if (tooltip.Contains(text3))
				{
					text2 = text3;
					break;
				}
			}
			if (text2 == null)
			{
				return tooltip;
			}
			int num = tooltip.IndexOf(text2, StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				return tooltip;
			}
			string text4 = tooltip.Substring(0, num).TrimEnd('\n', '\r');
			string text5 = tooltip.Substring(num);
			string[] array = text4.Split(new char[1] { '\n' });
			StringBuilder stringBuilder = new StringBuilder();
			string[] array2 = array;
			foreach (string text6 in array2)
			{
				string text7 = text6.TrimEnd(new char[1] { '\r' });
				if (string.IsNullOrWhiteSpace(text7))
				{
					stringBuilder.AppendLine();
					continue;
				}
				stringBuilder.AppendLine("<color=#" + text + ">" + text7 + "</color>");
			}
			stringBuilder.AppendLine("<color=#" + text + ">Tier: " + rarityInfo.Name + "</color>");
			stringBuilder.AppendLine("<color=#" + text + ">━━━━━━━━━━━━━━━━</color>");
			return stringBuilder.ToString() + text5;
		}

		public static string ReplaceDamageLines(string tooltip, RarityItemData data, ItemData item)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0066: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(tooltip) || item == null)
			{
				return tooltip;
			}
			RarityInfo rarityInfo = RarityData.Info[data.Rarity];
			string arg = ColorUtility.ToHtmlStringRGB(rarityInfo.Color);
			float smithFactor = GetSmithFactor(GetSmithLevel(item));
			DamageTypes damage = item.GetDamage(item.m_quality, (float)item.m_worldLevel);
			Dictionary<string, (float, float, string)> dictionary = new Dictionary<string, (float, float, string)>
			{
				{
					"pierce",
					(damage.m_pierce, data.BasePierce, "Perforante")
				},
				{
					"blunt",
					(damage.m_blunt, data.BaseBlunt, "Contundente")
				},
				{
					"slash",
					(damage.m_slash, data.BaseSlash, "Cortante")
				},
				{
					"fire",
					(damage.m_fire, data.BaseFire, "Fuego")
				},
				{
					"frost",
					(damage.m_frost, data.BaseFrost, "Escarcha")
				},
				{
					"lightning",
					(damage.m_lightning, data.BaseLightning, "Rayo")
				},
				{
					"spirit",
					(damage.m_spirit, data.BaseSpirit, "Espíritu")
				},
				{
					"poison",
					(damage.m_poison, data.BasePoison, "Veneno")
				}
			};
			foreach (KeyValuePair<string, (float, float, string)> item2 in dictionary)
			{
				string pattern = "^\\$inventory_" + item2.Key + "\\s*:.*$";
				var (num, num2, arg2) = item2.Value;
				if (num <= 0f)
				{
					tooltip = Regex.Replace(tooltip, pattern, string.Empty, RegexOptions.IgnoreCase | RegexOptions.Multiline);
					continue;
				}
				float num3 = num;
				float vanillaBase = num2 * smithFactor;
				string text = ((num2 > 0f) ? FormatStatDiff(num3, vanillaBase) : string.Empty);
				string replacement = $"<color=#{arg}>{arg2}: {num3:0.#}" + ((text.Length > 0) ? ("  " + text) : string.Empty) + "</color>";
				tooltip = Regex.Replace(tooltip, pattern, replacement, RegexOptions.IgnoreCase | RegexOptions.Multiline);
			}
			return tooltip;
		}

		public static string ReplaceBlockPowerLine(string tooltip, RarityItemData data, ItemData item)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(tooltip) || item == null)
			{
				return tooltip;
			}
			if ((int)item.m_shared.m_itemType != 5)
			{
				return tooltip;
			}
			RarityInfo rarityInfo = RarityData.Info[data.Rarity];
			string arg = ColorUtility.ToHtmlStringRGB(rarityInfo.Color);
			float num = item.m_shared.m_blockPowerPerLevel * (float)(item.m_quality - 1);
			float num2 = item.m_shared.m_blockPower + num;
			string text = ((data.BaseBlockPower > 0f) ? FormatStatDiff(num2, data.BaseBlockPower) : string.Empty);
			string replacement = $"<color=#{arg}>$item_blockarmor: <color=orange>{num2:0.#}</color>" + ((text.Length > 0) ? ("  " + text) : string.Empty) + "</color>";
			tooltip = Regex.Replace(tooltip, "^\\$item_blockarmor\\s*:.*$", replacement, RegexOptions.IgnoreCase | RegexOptions.Multiline);
			return tooltip;
		}

		public static string ReplaceArmorLine(string tooltip, RarityItemData data, ItemData item)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_0080: 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_0056: Invalid comparison between Unknown and I4
			if (string.IsNullOrEmpty(tooltip) || item == null)
			{
				return tooltip;
			}
			if ((int)item.m_shared.m_itemType != 6 && (int)item.m_shared.m_itemType != 7 && (int)item.m_shared.m_itemType != 11 && (int)item.m_shared.m_itemType != 17)
			{
				return tooltip;
			}
			RarityInfo rarityInfo = RarityData.Info[data.Rarity];
			string arg = ColorUtility.ToHtmlStringRGB(rarityInfo.Color);
			float smithFactor = GetSmithFactor(GetSmithLevel(item));
			float num = 0f;
			foreach (string insertedScrollId in data.InsertedScrollIds)
			{
				if (!string.IsNullOrEmpty(insertedScrollId))
				{
					ScrollPerkDef byName = ScrollPerkRegistry.GetByName(insertedScrollId.Split(new char[1] { ':' })[0]);
					if (byName != null && byName.Type == ScrollPerkType.Armadura)
					{
						num += byName.GetValue(data.Rarity);
					}
				}
			}
			float num2 = data.BaseArmor * (1f + rarityInfo.StatBonus);
			float num3 = num2 * smithFactor;
			float num4 = num3 + num;
			string text = ((data.BaseArmor > 0f) ? FormatStatDiff(num4, data.BaseArmor) : string.Empty);
			Logger.LogInfo((object)($"[ArmorDebug] base={data.BaseArmor:0.##} " + $"afterRarity={num2:0.##} " + $"afterSmith={num3:0.##} " + $"perk={num:0.##} " + $"total={num4:0.##}"));
			string replacement = $"<color=#{arg}>Armadura: {num4:0.#}" + ((text.Length > 0) ? ("  " + text) : string.Empty) + "</color>";
			tooltip = Regex.Replace(tooltip, "^\\$item_armor\\s*:.*$", replacement, RegexOptions.IgnoreCase | RegexOptions.Multiline);
			return tooltip;
		}

		public static string BuildTooltipAddition(RarityItemData data, ItemData item = null)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (data == null || data.Rarity == ItemRarity.Common)
			{
				return string.Empty;
			}
			RarityInfo rarityInfo = RarityData.Info[data.Rarity];
			string text = ColorUtility.ToHtmlStringRGB(rarityInfo.Color);
			string filledChar = SlotFilledChar[data.Rarity];
			StringBuilder stringBuilder = new StringBuilder();
			if (data.SlotCount > 0)
			{
				stringBuilder.AppendLine();
				for (int i = 0; i < data.SlotCount; i++)
				{
					string text2 = ((i < data.InsertedScrollIds.Count) ? data.InsertedScrollIds[i] : string.Empty);
					if (string.IsNullOrEmpty(text2))
					{
						stringBuilder.AppendLine("\ud83d\udd28 <color=#888888>Slot vacío</color>");
					}
					else
					{
						stringBuilder.AppendLine(BuildPerkDescription(text2, data.Rarity, text, filledChar));
					}
				}
			}
			stringBuilder.AppendLine();
			stringBuilder.Append("<color=#" + text + ">━━━━━━━━━━━━━━━━</color>");
			return stringBuilder.ToString();
		}

		public static RarityItemData GetOrCreate(ItemData itemData)
		{
			if (itemData.m_customData.TryGetValue("RarityData", out var value))
			{
				RarityItemData rarityItemData = RarityItemData.Deserialize(value);
				if (rarityItemData != null)
				{
					return rarityItemData;
				}
			}
			ItemRarity rarity = RarityData.RollRarity();
			RarityItemData rarityItemData2 = new RarityItemData(rarity);
			itemData.m_customData["RarityData"] = rarityItemData2.Serialize();
			return rarityItemData2;
		}

		public static RarityItemData Get(ItemData itemData)
		{
			if (itemData.m_customData.TryGetValue("RarityData", out var value))
			{
				return RarityItemData.Deserialize(value);
			}
			return null;
		}

		public static void Save(ItemData itemData, RarityItemData data)
		{
			itemData.m_customData["RarityData"] = data.Serialize();
		}

		public static string GetRarityHex(RarityItemData data)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (data == null)
			{
				return "ffffff";
			}
			return ColorUtility.ToHtmlStringRGB(RarityData.Info[data.Rarity].Color);
		}

		private static int GetSmithLevel(ItemData item)
		{
			if (item?.m_customData == null)
			{
				return 0;
			}
			if (!item.m_customData.TryGetValue("nazhi_blacksmith_lvl", out var value))
			{
				return 0;
			}
			int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result);
			return result;
		}

		private static float GetSmithFactor(int smithLvl)
		{
			if (smithLvl <= 0)
			{
				return 1f;
			}
			return 1f + 1f * Mathf.Clamp01((float)smithLvl / 100f);
		}

		private static string FormatStatDiff(float current, float vanillaBase)
		{
			if (vanillaBase <= 0f)
			{
				return string.Empty;
			}
			float num = current - vanillaBase;
			float num2 = num / vanillaBase * 100f;
			if (Mathf.Abs(num) < 0.05f)
			{
				return string.Empty;
			}
			bool flag = num >= 0f;
			string text = (flag ? "↑" : "↓");
			string text2 = (flag ? "00e676" : "ff5252");
			string arg = (flag ? "+" : "");
			string text3 = $"{arg}{num:0.#}";
			string text4 = $"{arg}{num2:0.#}%";
			return "<color=#" + text2 + ">" + text + " " + text3 + " (" + text4 + ")</color>";
		}

		private static string BuildPerkDescription(string scrollId, ItemRarity rarity, string hex, string filledChar)
		{
			string[] array = scrollId.Split(new char[1] { ':' });
			string displayName = array[0];
			string text = ((array.Length == 2) ? array[1] : null);
			ScrollPerkDef byName = ScrollPerkRegistry.GetByName(displayName);
			if (byName == null)
			{
				return filledChar + " <color=#" + hex + ">" + scrollId + "</color>";
			}
			float value = byName.GetValue(rarity);
			string text2 = ((byName.Type == ScrollPerkType.Vida || byName.Type == ScrollPerkType.Armadura || byName.Type == ScrollPerkType.Durabilidad || byName.Type == ScrollPerkType.WeapSkill || byName.Type == ScrollPerkType.Weight) ? $"{value:0}" : $"{value:0.##}%");
			if (byName.Type == ScrollPerkType.NoMovPen)
			{
				text2 = "";
			}
			ScrollPerkType type = byName.Type;
			if (1 == 0)
			{
			}
			string text3 = type switch
			{
				ScrollPerkType.Pierce => "Perforante: Aumenta en +" + text2 + " el daño perforante", 
				ScrollPerkType.Blunt => "Contundente: Aumenta en +" + text2 + " el daño contundente", 
				ScrollPerkType.Slash => "Cortante: Aumenta en +" + text2 + " el daño cortante", 
				ScrollPerkType.DmgMagico => "Dominio Elemental: Aumenta en +" + text2 + " el daño mágico", 
				ScrollPerkType.VelocidadAtk => "Frenesí: Aumenta en +" + text2 + " la velocidad de ataque", 
				ScrollPerkType.DmgFaccion => "Oportunista: Aumenta en +" + text2 + " el daño vs " + TranslateFaction(text ?? "enemigos"), 
				ScrollPerkType.ReduccionDmg => "Piel de Hierro: Reduce en " + text2 + " el daño recibido", 
				ScrollPerkType.Armadura => "Bastión: Aumenta en +" + text2 + " la armadura", 
				ScrollPerkType.Vida => "Vitalidad: Aumenta en +" + text2 + " el HP máximo", 
				ScrollPerkType.RegHP => "Vitalis: Aumenta en +" + text2 + " la regeneración de HP", 
				ScrollPerkType.RegStamina => "Segundo Aliento: Aumenta en +" + text2 + " la regen. de Stamina", 
				ScrollPerkType.RegEitr => "Eco de Eitr: Aumenta en +" + text2 + " la regeneración de Eitr", 
				ScrollPerkType.Durabilidad => "Temple Reforjado: Aumenta en +" + text2 + " la durabilidad", 
				ScrollPerkType.Healing => "Sagrado: Aumenta en +" + text2 + " el poder de curación", 
				ScrollPerkType.ResistPierce => "Protección Perforante: Reduce en " + text2 + " el daño perforante recibido", 
				ScrollPerkType.ResistBlunt => "Protección Contundente: Reduce en " + text2 + " el daño contundente recibido", 
				ScrollPerkType.ResistSlash => "Protección Cortante: Reduce en " + text2 + " el daño cortante recibido", 
				ScrollPerkType.Bloqueo => "Aegis: Aumenta en +" + text2 + " el poder de bloqueo del escudo", 
				ScrollPerkType.Parry => "Contraataque: Aumenta en +" + text2 + " el multiplicador de parry", 
				ScrollPerkType.NoMovPen => "Sin Límites: Elimina la penalización de movimiento de la armadura", 
				ScrollPerkType.WeapSkill => "Destreza: Aumenta en +" + text2 + " la habilidad del arma equipada", 
				ScrollPerkType.Weight => "Sobrecarga: Aumenta en +" + text2 + " el peso máximo que puedes cargar", 
				_ => byName.DisplayName + ": +" + text2, 
			};
			if (1 == 0)
			{
			}
			string text4 = text3;
			return filledChar + " <color=#" + hex + ">" + text4 + "</color>";
		}

		private static string TranslateFaction(string faction)
		{
			if (1 == 0)
			{
			}
			string result = faction switch
			{
				"AnimalsVeg" => "Animales", 
				"ForestMonsters" => "Monstruos del Bosque", 
				"Undead" => "No Muertos", 
				"Demon" => "Demonios", 
				"MountainMonsters" => "Monstruos de Montaña", 
				"SeaMonsters" => "Monstruos del Mar", 
				"PlainsMonsters" => "Monstruos de Llanos", 
				"Boss" => "Jefes", 
				"MistlandsMonsters" => "Monstruos de Niebla", 
				"Dverger" => "Dverger", 
				_ => faction, 
			};
			if (1 == 0)
			{
			}
			return result;
		}
	}
	[HarmonyPatch]
	public static class ScrollDropPatch
	{
		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		[HarmonyPrefix]
		public static bool UseItem_Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
		{
			if (item == null)
			{
				return true;
			}
			if (!ScrollItem.IsEnchantScroll(item))
			{
				return true;
			}
			return false;
		}
	}
	public class ScrollEnchantUI : MonoBehaviour
	{
		private ItemData _scrollItem;

		private ItemData _targetItem;

		private bool _isOpen;

		private GameObject _titlePanel;

		private GameObject _leftPanel;

		private GameObject _rightPanel;

		private GameObject _bottomPanel;

		private Image _weaponIcon;

		private Text _weaponHint;

		private Text _weaponLabelText;

		private Image _scrollIcon;

		private Text _scrollPerkText;

		private Text _statusText;

		private Text _itemNameText;

		private Text _slotsAvailText;

		private Text _perksCurrentText;

		private Text _perksNewText;

		private Text _smithLevelText;

		private Button _acceptBtn;

		private Image _coinIcon;

		private Text _coinCostText;

		private const float LeftW = 300f;

		private const float RightW = 460f;

		private const float BodyH = 540f;

		private const float Gap = 10f;

		private const float TotalW = 770f;

		private const float BottomH = 80f;

		private const string COIN_PREFAB_NAME = "Coins";

		private Text _titleText;

		public static ScrollEnchantUI Instance { get; private set; }

		private static int GetSmithLevelRequired(ItemRarity rarity)
		{
			if (1 == 0)
			{
			}
			int result = rarity switch
			{
				ItemRarity.Common => 0, 
				ItemRarity.Uncommon => 10, 
				ItemRarity.Rare => 25, 
				ItemRarity.Epic => 50, 
				ItemRarity.Legendary => 75, 
				_ => 0, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		private static int GetCoinCost(ItemRarity rarity)
		{
			if (1 == 0)
			{
			}
			int result = rarity switch
			{
				ItemRarity.Common => 0, 
				ItemRarity.Uncommon => 250, 
				ItemRarity.Rare => 350, 
				ItemRarity.Epic => 1000, 
				ItemRarity.Legendary => 2500, 
				_ => 0, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		private void Awake()
		{
			Instance = this;
			GUIManager.OnCustomGUIAvailable += OnGUIAvailable;
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			GUIManager.OnCustomGUIAvailable -= OnGUIAvailable;
		}

		private void OnGUIAvailable()
		{
			Object.Destroy((Object)(object)_titlePanel);
			_titlePanel = null;
			Object.Destroy((Object)(object)_leftPanel);
			_leftPanel = null;
			Object.Destroy((Object)(object)_rightPanel);
			_rightPanel = null;
			Object.Destroy((Object)(object)_bottomPanel);
			_bottomPanel = null;
			EnsurePanel();
		}

		private void Update()
		{
		}

		public void Open(ItemData scrollItem)
		{
			if (scrollItem != null)
			{
				_scrollItem = scrollItem;
				_targetItem = null;
				EnsurePanel();
				if (!((Object)(object)_titlePanel == (Object)null))
				{
					RefreshUI();
					_titlePanel.SetActive(true);
					_leftPanel.SetActive(true);
					_rightPanel.SetActive(true);
					_bottomPanel.SetActive(true);
					_isOpen = true;
				}
			}
		}

		public void Close()
		{
			((MonoBehaviour)this).CancelInvoke("Close");
			_isOpen = false;
			GameObject titlePanel = _titlePanel;
			if (titlePanel != null)
			{
				titlePanel.SetActive(false);
			}
			GameObject leftPanel = _leftPanel;
			if (leftPanel != null)
			{
				leftPanel.SetActive(false);
			}
			GameObject rightPanel = _rightPanel;
			if (rightPanel != null)
			{
				rightPanel.SetActive(false);
			}
			GameObject bottomPanel = _bottomPanel;
			if (bottomPanel != null)
			{
				bottomPanel.SetActive(false);
			}
			_scrollItem = null;
			_targetItem = null;
		}

		public void TrySetTarget(ItemData item)
		{
			if (_isOpen && item != null && RarityPatches.IsWeaponOrArmor(item))
			{
				_targetItem = item;
				RefreshUI();
			}
		}

		private void EnsurePanel()
		{
			//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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0527: Unknown result type (might be due to invalid IL or missing references)
			//IL_0566: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0632: Unknown result type (might be due to invalid IL or missing references)
			//IL_0658: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06de: Unknown result type (might be due to invalid IL or missing references)
			//IL_070b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0718: Unknown result type (might be due to invalid IL or missing references)
			//IL_071f: Expected O, but got Unknown
			//IL_0756: Unknown result type (might be due to invalid IL or missing references)
			//IL_075e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0772: Unknown result type (might be due to invalid IL or missing references)
			//IL_0789: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fe: Expected O, but got Unknown
			//IL_0828: Unknown result type (might be due to invalid IL or missing references)
			//IL_083f: Unknown result type (might be due to invalid IL or missing references)
			//IL_084e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0853: Unknown result type (might be due to invalid IL or missing references)
			//IL_0854: Unknown result type (might be due to invalid IL or missing references)
			//IL_085c: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0907: Unknown result type (might be due to invalid IL or missing references)
			//IL_093c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0946: Expected O, but got Unknown
			//IL_0966: Unknown result type (might be due to invalid IL or missing references)
			//IL_0975: Unknown result type (might be due to invalid IL or missing references)
			//IL_0984: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b7: Expected O, but got Unknown
			if (!((Object)(object)_titlePanel != (Object)null) && GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null))
			{
				float num = -235f;
				float num2 = 155f;
				float num3 = 302f;
				float num4 = -316f;
				Color color = default(Color);
				((Color)(ref color))..ctor(0.08f, 0.06f, 0.06f, 0.97f);
				_titlePanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, num3), 770f, 58f, true);
				_titlePanel.SetActive(false);
				DarkenPanel(_titlePanel, color);
				GameObject val = GUIManager.Instance.CreateText("Encantamiento", _titlePanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, GUIManager.Instance.AveriaSerifBold, 27, GUIManager.Instance.ValheimOrange, true, Color.black, 750f, 35f, false);
				_titleText = val.GetComponent<Text>();
				_titleText.alignment = (TextAnchor)4;
				_leftPanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(num, 0f), 300f, 540f, false);
				_leftPanel.SetActive(false);
				DarkenPanel(_leftPanel, color);
				float num5 = 170f;
				float num6 = -60f;
				GameObject val2 = GUIManager.Instance.CreateText("Arma / Armadura", _leftPanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, num5 + 68f), GUIManager.Instance.AveriaSerifBold, 17, GUIManager.Instance.ValheimOrange, true, Color.black, 260f, 25f, false);
				_weaponLabelText = val2.GetComponent<Text>();
				_weaponLabelText.alignment = (TextAnchor)4;
				GameObject val3 = CreateSlot(_leftPanel.transform, new Vector2(0f, num5));
				_weaponIcon = ((Component)val3.transform.Find("Icon")).GetComponent<Image>();
				_weaponHint = MakeText(_leftPanel.transform, new Vector2(0f, num5), 105f, 105f, 14);
				_weaponHint.text = "Click\nizquierdo";
				((Graphic)_weaponHint).color = new Color(0.5f, 0.5f, 0.5f);
				_weaponHint.alignment = (TextAnchor)4;
				MakeSep(_leftPanel.transform, new Vector2(0f, num5 - 78f));
				MakeLabel(_leftPanel.transform, "Pergamino", new Vector2(0f, num6 + 68f), 260f, 17, orange: true);
				GameObject val4 = CreateSlot(_leftPanel.transform, new Vector2(0f, num6));
				_scrollIcon = ((Component)val4.transform.Find("Icon")).GetComponent<Image>();
				_scrollPerkText = MakeText(_leftPanel.transform, new Vector2(0f, num6 - 68f), 270f, 27f, 14);
				_scrollPerkText.alignment = (TextAnchor)4;
				_rightPanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(num2, 0f), 460f, 540f, false);
				_rightPanel.SetActive(false);
				DarkenPanel(_rightPanel, color);
				_itemNameText = MakeText(_rightPanel.transform, new Vector2(0f, 228f), 420f, 30f, 25);
				_itemNameText.alignment = (TextAnchor)4;
				((Graphic)_itemNameText).color = GUIManager.Instance.ValheimOrange;
				_slotsAvailText = MakeText(_rightPanel.transform, new Vector2(0f, 198f), 420f, 22f, 19);
				_slotsAvailText.alignment = (TextAnchor)4;
				((Graphic)_slotsAvailText).color = new Color(0.75f, 0.75f, 0.75f);
				MakeSep(_rightPanel.transform, new Vector2(0f, 172f));
				_statusText = MakeText(_rightPanel.transform, new Vector2(0f, 138f), 420f, 28f, 20);
				_statusText.alignment = (TextAnchor)4;
				_smithLevelText = MakeText(_rightPanel.transform, new Vector2(0f, 110f), 420f, 24f, 17);
				_smithLevelText.alignment = (TextAnchor)4;
				MakeSep(_rightPanel.transform, new Vector2(0f, 86f));
				MakeLabel(_rightPanel.transform, "Perks actuales:", new Vector2(0f, 64f), 420f, 21);
				_perksCurrentText = MakeText(_rightPanel.transform, new Vector2(0f, -2f), 420f, 80f, 22);
				_perksCurrentText.alignment = (TextAnchor)1;
				MakeSep(_rightPanel.transform, new Vector2(0f, -50f));
				MakeLabel(_rightPanel.transform, "Con este encanto:", new Vector2(0f, -72f), 420f, 21);
				_perksNewText = MakeText(_rightPanel.transform, new Vector2(0f, -138f), 420f, 80f, 22);
				_perksNewText.alignment = (TextAnchor)1;
				_bottomPanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, num4), 770f, 80f, false);
				_bottomPanel.SetActive(false);
				DarkenPanel(_bottomPanel, color);
				GameObject val5 = new GameObject("CoinSlot");
				val5.transform.SetParent(_bottomPanel.transform, false);
				RectTransform val6 = val5.AddComponent<RectTransform>();
				Vector2 val7 = default(Vector2);
				((Vector2)(ref val7))..ctor(0.5f, 0.5f);
				val6.anchorMax = val7;
				val6.anchorMin = val7;
				val6.anchoredPosition = new Vector2(-345f, 0f);
				val6.sizeDelta = new Vector2(40f, 40f);
				Image val8 = val5.AddComponent<Image>();
				Sprite sprite = GUIManager.Instance.GetSprite("item_background");
				if ((Object)(object)sprite != (Object)null)
				{
					val8.sprite = sprite;
					val8.type = (Type)1;
				}
				((Graphic)val8).color = new Color(0.1f, 0.1f, 0.1f, 0.6f);
				GameObject val9 = new GameObject("CoinIcon");
				val9.transform.SetParent(val5.transform, false);
				RectTransform val10 = val9.AddComponent<RectTransform>();
				val10.anchorMin = new Vector2(0.1f, 0.1f);
				val10.anchorMax = new Vector2(0.9f, 0.9f);
				val7 = (val10.offsetMin = (val10.offsetMax = Vector2.zero));
				_coinIcon = val9.AddComponent<Image>();
				((Behaviour)_coinIcon).enabled = false;
				((Graphic)_coinIcon).raycastTarget = false;
				_coinCostText = MakeText(_bottomPanel.transform, new Vector2(-270f, 0f), 100f, 36f, 17);
				_coinCostText.alignment = (TextAnchor)3;
				GameObject val12 = GUIManager.Instance.CreateButton("ENCANTAR", _bottomPanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-110f, 0f), 180f, 50f);
				_acceptBtn = val12.GetComponent<Button>();
				((UnityEvent)_acceptBtn.onClick).AddListener(new UnityAction(OnAccept));
				GameObject val13 = GUIManager.Instance.CreateButton("CANCELAR", _bottomPanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(110f, 0f), 180f, 50f);
				((UnityEvent)val13.GetComponent<Button>().onClick).AddListener(new UnityAction(Close));
			}
		}

		private static void DarkenPanel(GameObject panel, Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0033: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DarkBG");
			val.transform.SetParent(panel.transform, false);
			val.transform.SetAsFirstSibling();
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
			val2.offsetMin = offsetMin;
			((Graphic)val.AddComponent<Image>()).color = color;
		}

		private void RefreshUI()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Unknown result type (might be due to invalid IL or missing references)
			//IL_0654: Unknown result type (might be due to invalid IL or missing references)
			if (_scrollItem == null || (Object)(object)_scrollIcon == (Object)null)
			{
				return;
			}
			ScrollItem.TryGetScrollTier(_scrollItem, out var rarity);
			ScrollItem.TryGetScrollPerk(_scrollItem, out var perk);
			RarityInfo rarityInfo = RarityData.Info[rarity];
			string text = ColorUtility.ToHtmlStringRGB(rarityInfo.Color);
			_scrollIcon.sprite = _scrollItem.GetIcon();
			((Behaviour)_scrollIcon).enabled = true;
			_scrollPerkText.text = ((perk != null) ? ("<color=#" + text + ">" + perk.GetTooltipDescription(rarity) + "</color>") : ("<color=#" + text + ">" + rarityInfo.Name + "</color>"));
			if ((Object)(object)_titleText != (Object)null)
			{
				((Graphic)_titleText).color = rarityInfo.Color;
			}
			int coinCost = GetCoinCost(rarity);
			RefreshCoinSlot(rarity, coinCost);
			bool flag = _targetItem != null;
			((Component)_weaponHint).gameObject.SetActive(!flag);
			_weaponIcon.sprite = (flag ? _targetItem.GetIcon() : null);
			((Behaviour)_weaponIcon).enabled = flag;
			if ((Object)(object)_weaponLabelText != (Object)null)
			{
				if (!flag)
				{
					_weaponLabelText.text = "Arma / Armadura";
				}
				else
				{
					_weaponLabelText.text = GetItemCategoryLabel(_targetItem);
				}
			}
			if (!flag)
			{
				_statusText.text = "<color=#aaaaaa>Encanto: En espera</color>";
				_itemNameText.text = "—";
				_slotsAvailText.text = "";
				_smithLevelText.text = "";
				_perksCurrentText.text = "";
				_perksNewText.text = "";
				((Selectable)_acceptBtn).interactable = false;
				return;
			}
			string text2 = ((Localization.instance != null) ? Localization.instance.Localize(_targetItem.m_shared.m_name) : _targetItem.m_shared.m_name);
			_itemNameText.text = text2;
			RarityItemData rarityItemData = RarityTooltip.Get(_targetItem);
			if (rarityItemData != null)
			{
				_slotsAvailText.text = $"Slots disponibles: {rarityItemData.EmptySlots}";
			}
			else
			{
				_slotsAvailText.text = "";
			}
			int smithLevelRequired = GetSmithLevelRequired(rarity);
			bool flag2 = CheckSmithLevel(smithLevelRequired);
			int currentSmithLevel = GetCurrentSmithLevel();
			if (smithLevelRequired > 0)
			{
				string text3 = (flag2 ? "88ff88" : "ff4444");
				string text4 = (flag2 ? "✔" : "✘");
				_smithLevelText.text = $"<color=#{text3}>{text4} Herrería requerida: {smithLevelRequired}  (Actual: {currentSmithLevel})</color>";
			}
			else
			{
				_smithLevelText.text = "<color=#88ff88>✔ Sin requisito de Herrería</color>";
			}
			bool flag3 = CheckCoins(coinCost);
			string text5;
			if (rarityItemData == null)
			{
				text5 = "<color=#ff4444>Sin rareza asignada</color>";
				((Selectable)_acceptBtn).interactable = false;
			}
			else if (rarityItemData.Rarity != rarity)
			{
				string name = RarityData.Info[rarity].Name;
				text5 = "<color=#ff4444>El item debe ser " + name + "</color>";
				((Selectable)_acceptBtn).interactable = false;
			}
			else if (!rarityItemData.HasFreeSlot)
			{
				text5 = "<color=#ff4444>Sin slots libres</color>";
				((Selectable)_acceptBtn).interactable = false;
			}
			else if (!flag3)
			{
				text5 = $"<color=#ff4444>Necesitas {coinCost} monedas</color>";
				((Selectable)_acceptBtn).interactable = false;
			}
			else
			{
				ScrollItem.TryGetScrollPerk(_scrollItem, out var perk2);
				string text6 = ((perk2 != null) ? CheckPerkItemRestriction(perk2, _targetItem) : null);
				string text7 = ((text6 == null && perk2 != null) ? CheckPerkCompatibility(rarityItemData, perk2) : null);
				if (text6 != null)
				{
					text5 = "<color=#ff4444>" + text6 + "</color>";
					((Selectable)_acceptBtn).interactable = false;
				}
				else if (text7 != null)
				{
					text5 = "<color=#ff4444>" + text7 + "</color>";
					((Selectable)_acceptBtn).interactable = false;
				}
				else if (!flag2)
				{
					text5 = $"<color=#ff4444>Necesitas nivel {smithLevelRequired} de Herrería</color>";
					((Selectable)_acceptBtn).interactable = false;
				}
				else
				{
					text5 = "<color=#88ff88>Encanto: Posible ✔</color>";
					((Selectable)_acceptBtn).interactable = true;
				}
			}
			_statusText.text = text5;
			if (rarityItemData != null && rarityItemData.FilledSlots > 0)
			{
				string text8 = ColorUtility.ToHtmlStringRGB(RarityData.Info[rarityItemData.Rarity].Color);
				string text9 = "";
				foreach (string insertedScrollId in rarityItemData.InsertedScrollIds)
				{
					if (!string.IsNullOrEmpty(insertedScrollId))
					{
						text9 = text9 + "<color=#" + text8 + ">• " + FormatPerkId(insertedScrollId, rarityItemData.Rarity) + "</color>\n";
					}
				}
				_perksCurrentText.text = text9.TrimEnd(Array.Empty<char>());
			}
			else
			{
				_perksCurrentText.text = "<color=#888888>Sin perks</color>";
			}
			if (rarityItemData != null && rarityItemData.Rarity == rarity && rarityItemData.HasFreeSlot && perk != null)
			{
				string text10 = ColorUtility.ToHtmlStringRGB(RarityData.Info[rarityItemData.Rarity].Color);
				string text11 = "";
				foreach (string insertedScrollId2 in rarityItemData.InsertedScrollIds)
				{
					if (!string.IsNullOrEmpty(insertedScrollId2))
					{
						text11 = text11 + "<color=#" + text10 + ">• " + insertedScrollId2 + "</color>\n";
					}
				}
				text11 = text11 + "<color=#" + text + ">+ " + perk.GetDisplayText(rarity) + "</color>";
				_perksNewText.text = text11;
			}
			else if (rarityItemData != null && !rarityItemData.HasFreeSlot)
			{
				_perksNewText.text = "<color=#ff6666>Sin slots disponibles</color>";
			}
			else
			{
				_perksNewText.text = "<color=#888888>—</color>";
			}
		}

		private static int GetCurrentSmithLevel()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return 0;
			}
			SkillType val = (SkillType)StringExtensionMethods.GetStableHashCode("nazhi.blacksmithing.skill");
			return Mathf.FloorToInt(((Character)localPlayer).GetSkillLevel(val));
		}

		private static bool CheckSmithLevel(int required)
		{
			if (required <= 0)
			{
				return true;
			}
			return GetCurrentSmithLevel() >= required;
		}

		private static int GetPlayerCoinCount()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return 0;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			if (inventory == null)
			{
				return 0;
			}
			return inventory.CountItems("$item_coins", -1, true);
		}

		private static bool CheckCoins(int required)
		{
			if (required <= 0)
			{
				return true;
			}
			return GetPlayerCoinCount() >= required;
		}

		private void RefreshCoinSlot(ItemRarity rarity, int cost)
		{
			if ((Object)(object)_coinCostText == (Object)null)
			{
				return;
			}
			if ((Object)(object)_coinIcon != (Object)null && (Object)(object)ZNetScene.instance != (Object)null && !((Behaviour)_coinIcon).enabled)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("Coins");
				if ((Object)(object)prefab != (Object)null)
				{
					ItemDrop component = prefab.GetComponent<ItemDrop>();
					if (component?.m_itemData != null)
					{
						_coinIcon.sprite = component.m_itemData.GetIcon();
						((Behaviour)_coinIcon).enabled = (Object)(object)_coinIcon.sprite != (Object)null;
					}
				}
			}
			if (cost <= 0)
			{
				_coinCostText.text = "<color=#888888>Gratis</color>";
				return;
			}
			bool flag = CheckCoins(cost);
			int playerCoinCount = GetPlayerCoinCount();
			string arg = (flag ? "f0c040" : "ff4444");
			_coinCostText.text = $"<color=#{arg}>{playerCoinCount}/{cost}\n<size=13>monedas</size></color>";
		}

		private void OnAccept()
		{
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			if (_scrollItem == null || _targetItem == null)
			{
				return;
			}
			ScrollItem.TryGetScrollTier(_scrollItem, out var rarity);
			ScrollItem.TryGetScrollPerk(_scrollItem, out var perk);
			RarityItemData rarityItemData = RarityTooltip.Get(_targetItem);
			if (rarityItemData == null || !rarityItemData.HasFreeSlot || rarityItemData.Rarity != rarity)
			{
				return;
			}
			int smithLevelRequired = GetSmithLevelRequired(rarity);
			if (!CheckSmithLevel(smithLevelRequired))
			{
				_statusText.text = $"<color=#ff4444>Necesitas nivel {smithLevelRequired} de Herrería</color>";
				return;
			}
			int coinCost = GetCoinCost(rarity);
			if (!CheckCoins(coinCost))
			{
				_statusText.text = $"<color=#ff4444>Necesitas {coinCost} monedas</color>";
				return;
			}
			string text = ((perk != null) ? CheckPerkItemRestriction(perk, _targetItem) : null);
			if (text != null)
			{
				_statusText.text = "<color=#ff4444>Encanto: No es Posible  <size=16>· " + text + "</size></color>";
				return;
			}
			string text2 = ((perk != null) ? CheckPerkCompatibility(rarityItemData, perk) : null);
			if (text2 != null)
			{
				_statusText.text = "<color=#ff6666>Encanto: " + text2 + "</color>";
				return;
			}
			if (coinCost > 0)
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Humanoid)localPlayer).GetInventory().RemoveItem("Coins", coinCost, -1, true);
				}
			}
			string scrollPerkId = perk?.DisplayName ?? "???";
			if (perk != null && perk.Type == ScrollPerkType.DmgFaccion)
			{
				Faction[] array = new Faction[10];
				RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
				Faction[] array2 = (Faction[])(object)array;
				Faction val = array2[Random.Range(0, array2.Length)];
				scrollPerkId = $"Daño a Faccion:{val}";
			}
			rarityItemData.InsertScroll(scrollPerkId);
			RarityTooltip.Save(_targetItem, rarityItemData);
			Player localPlayer2 = Player.m_localPlayer;
			if (localPlayer2 != null)
			{
				((Humanoid)localPlayer2).GetInventory().RemoveOneItem(_scrollItem);
			}
			EnchantBonusManager.RefreshSingleItem(_targetItem);
			EnchantBonusManager.Refresh(Player.m_localPlayer);
			_statusText.text = "<color=#88ff88>✔ ¡Encantamiento aplicado!</color>";
			((Selectable)_acceptBtn).interactable = false;
			((MonoBehaviour)this).Invoke("Close", 1.2f);
		}

		private GameObject CreateSlot(Transform parent, Vector2 pos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0034: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Slot");
			val.transform.SetParent(parent, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.anchoredPosition = pos;
			val2.sizeDelta = new Vector2(108f, 108f);
			Image val4 = val.AddComponent<Image>();
			Sprite sprite = GUIManager.Instance.GetSprite("item_background");
			if ((Object)(object)sprite != (Object)null)
			{
				val4.sprite = sprite;
				val4.type = (Type)1;
			}
			((Graphic)val4).color = Color.white;
			Button val5 = val.AddComponent<Button>();
			((Selectable)val5).targetGraphic = (Graphic)(object)val4;
			ColorBlock val6 = default(ColorBlock);
			((ColorBlock)(ref val6)).normalColor = new Color(0.1324f, 0.1324f, 0.1324f, 0.502f);
			((ColorBlock)(ref val6)).highlightedColor = new Color(0.3897f, 0.4012f, 0.4012f, 0.502f);
			((ColorBlock)(ref val6)).pressedColor = new Color(0.2794f, 0.2794f, 0.2794f, 1f);
			((ColorBlock)(ref val6)).selectedColor = new Color(0.3897f, 0.4012f, 0.4012f, 0.502f);
			((ColorBlock)(ref val6)).disabledColor = new Color(0f, 0f, 0f, 0.502f);
			((ColorBlock)(ref val6)).colorMultiplier = 1f;
			((ColorBlock)(ref val6)).fadeDuration = 0.1f;
			ColorBlock colors = val6;
			((Selectable)val5).colors = colors;
			GameObject val7 = new GameObject("Icon");
			val7.transform.SetParent(val.transform, false);
			RectTransform val8 = val7.AddComponent<RectTransform>();
			val8.anchorMin = new Vector2(0.1f, 0.1f);
			val8.anchorMax = new Vector2(0.9f, 0.9f);
			val3 = (val8.offsetMin = (val8.offsetMax = Vector2.zero));
			Image val10 = val7.AddComponent<Image>();
			((Behaviour)val10).enabled = false;
			((Graphic)val10).raycastTarget = false;
			return val;
		}

		private void MakeLabel(Transform parent, string text, Vector2 pos, float width, int fontSize, bool orange = false)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GUIManager.Instance.CreateText(text, parent, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), pos, GUIManager.Instance.AveriaSerifBold, fontSize, (Color)(orange ? GUIManager.Instance.ValheimOrange : new Color(0.75f, 0.75f, 0.75f)), orange, Color.black, width, (float)fontSize + 8f, false);
			val.GetComponent<Text>().alignment = (TextAnchor)4;
		}

		private static string GetItemCategoryLabel(ItemData item)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_001f: Invalid comparison between Unknown and I4
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			if (item == null)
			{
				return "Arma / Armadura";
			}
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType == 5)
			{
				return "Escudo";
			}
			if ((int)itemType == 3 || (int)itemType == 14 || (int)itemType == 4)
			{
				return "Arma";
			}
			return "Armadura";
		}

		private static bool IsWeaponType(ItemData item)
		{
			//IL_0013: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			if (item == null)
			{
				return false;
			}
			ItemType itemType = item.m_shared.m_itemType;
			return (int)itemType == 3 || (int)itemType == 14 || (int)itemType == 4;
		}

		private static bool IsArmorType(ItemData item)
		{
			//IL_0013: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			if (item == null)
			{
				return false;
			}
			ItemType itemType = item.m_shared.m_itemType;
			return (int)itemType == 6 || (int)itemType == 7 || (int)itemType == 11 || (int)itemType == 17;
		}

		private static bool IsShieldType(ItemData item)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if (item == null)
			{
				return false;
			}
			return (int)item.m_shared.m_itemType == 5;
		}

		private static string CheckPerkItemRestriction(ScrollPerkDef perk, ItemData item)
		{
			if (perk == null || item == null)
			{
				return null;
			}
			bool flag = IsWeaponType(item);
			bool flag2 = IsArmorType(item);
			bool flag3 = IsShieldType(item);
			switch (perk.Type)
			{
			case ScrollPerkType.Pierce:
			case ScrollPerkType.Blunt:
			case ScrollPerkType.Slash:
			case ScrollPerkType.DmgFaccion:
			case ScrollPerkType.VelocidadAtk:
			case ScrollPerkType.DmgMagico:
				if (!flag)
				{
					return "Solo se puede aplicar a armas";
				}
				break;
			case ScrollPerkType.WeapSkill:
				if (!flag && !flag3)
				{
					return "Solo se puede aplicar a armas o escudos";
				}
				break;
			case ScrollPerkType.ReduccionDmg:
			case ScrollPerkType.Vida:
			case ScrollPerkType.Armadura:
			case ScrollPerkType.RegHP:
			case ScrollPerkType.RegStamina:
			case ScrollPerkType.RegEitr:
			case ScrollPerkType.ResistPierce:
			case ScrollPerkType.ResistBlunt:
			case ScrollPerkType.ResistSlash:
				if (!flag2)
				{
					return "Solo se puede aplicar a armaduras";
				}
				break;
			case ScrollPerkType.NoMovPen:
				if (!flag2 && !flag3)
				{
					return "Solo se puede aplicar a armaduras o escudos";
				}
				break;
			}
			return null;
		}

		private static string CheckPerkCompatibility(RarityItemData rd, ScrollPerkDef perk)
		{
			foreach (string insertedScrollId in rd.InsertedScrollIds)
			{
				if (string.IsNullOrEmpty(insertedScrollId))
				{
					continue;
				}
				string displayName = insertedScrollId.Split(new char[1] { ':' })[0];
				ScrollPerkDef byName = ScrollPerkRegistry.GetByName(displayName);
				if (byName != null)
				{
					bool flag = perk.Type == ScrollPerkType.Armadura;
					bool flag2 = perk.Type == ScrollPerkType.Vida;
					bool flag3 = byName.Type == ScrollPerkType.Armadura;
					bool flag4 = byName.Type == ScrollPerkType.Vida;
					if (flag && flag4)
					{
						return "Incompatible con Vida";
					}
					if (flag2 && flag3)
					{
						return "Incompatible con Armadura";
					}
					if (isRegen(perk.Type) && isRegen(byName.Type) && perk.Type != byName.Type)
					{
						return "Incompatible con " + byName.DisplayName;
					}
				}
			}
			return null;
			static bool isRegen(ScrollPerkType t)
			{
				return t == ScrollPerkType.RegHP || t == ScrollPerkType.RegStamina || t == ScrollPerkType.RegEitr;
			}
		}

		private static string FormatPerkId(string id, ItemRarity rarity)
		{
			string[] array = id.Split(new char[1] { ':' });
			if (array.Length == 2)
			{
				ScrollPerkDef byName = ScrollPerkRegistry.GetByName(array[0]);
				if (byName != null)
				{
					return byName.GetDisplayText(rarity) + " vs " + array[1];
				}
			}
			ScrollPerkDef byName2 = ScrollPerkRegistry.GetByName(id);
			return (byName2 != null) ? byName2.GetDisplayText(rarity) : id;
		}

		private Text MakeText(Transform parent, Vector2 pos, float w, float h, int fontSize)
		{
			//IL_0016: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GUIManager.Instance.CreateText("", parent, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), pos, GUIManager.Instance.AveriaSerifBold, fontSize, Color.white, false, Color.black, w, h, false);
			return val.GetComponent<Text>();
		}

		private void MakeSep(Transform parent, Vector2 pos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0055: 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)
			GameObject val = new GameObject("Sep");
			val.transform.SetParent(parent, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.anchoredPosition = pos;
			val2.sizeDelta = new Vector2(310f, 1f);
			((Graphic)val.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.12f);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")]
	public static class ScrollUIPatch
	{
		private static int _revealedFrame = -1;

		[HarmonyPrefix]
		public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item)
		{
			if (item == null || !ScrollItem.IsEnchantScroll(item))
			{
				return true;
			}
			if (item.m_customData == null || !item.m_customData.TryGetValue("ScrollRevealed", out var value) || !(value == "1"))
			{
				ScrollItem.TryGetScrollTier(item, out var rarity);
				ScrollItem.RollPerk(rarity, out var perkKey, out var perkDisplay);
				if (item.m_customData == null)
				{
					item.m_customData = new Dictionary<string, string>();
				}
				item.m_customData["ScrollPerk"] = perkKey;
				item.m_customData["ScrollRevealed"] = "1";
				item.m_shared.m_description = ScrollItem.BuildRevealedDescription(rarity, perkDisplay);
				_revealedFrame = Time.frameCount;
				Logger.LogInfo((object)$"[Scroll] Revelado: {perkKey} | {perkDisplay} ({rarity})");
				return false;
			}
			if (Time.frameCount == _revealedFrame)
			{
				return false;
			}
			if ((Object)(object)ScrollEnchantUI.Instance == (Object)null)
			{
				return true;
			}
			ScrollEnchantUI.Instance.Open(item);
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	public static class ScrollEnchantInventoryHidePatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			if (!((Object)(object)ScrollEnchantUI.Instance == (Object)null))
			{
				FieldInfo field = typeof(ScrollEnchantUI).GetField("_isOpen", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null && (bool)field.GetValue(ScrollEnchantUI.Instance))
				{
					ScrollEnchantUI.Instance.Close();
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	public static class ScrollTargetPickPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod)
		{
			if ((Object)(object)ScrollEnchantUI.Instance == (Object)null)
			{
				return true;
			}
			FieldInfo field = typeof(ScrollEnchantUI).GetField("_isOpen", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null || !(bool)field.GetValue(ScrollEnchantUI.Instance))
			{
				return true;
			}
			if (item == nul

AichoGuardian.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AichoGuardian")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AichoGuardian")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("D28110A9-E229-4700-AD4D-DCD37486A82B")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace NazhiMods.AichoGuardian;

[BepInPlugin("nazhi.aicho.guardian", "Aicho Guardian", "1.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class AichoGuardianPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "nazhi.aicho.guardian";

	public const string PluginName = "Aicho Guardian";

	public const string PluginVersion = "1.3.0";

	internal const string GuardianPrefabName = "Aicho_Guardian";

	internal const string WallSourcePrefabName = "piece_dvergr_metal_wall_2x2";

	internal const string WallClonePrefabName = "AichoDverg_Wall";

	public static ConfigEntry<float> CFG_SearchRadius;

	public static ConfigEntry<float> CFG_ResetSeconds;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Expected O, but got Unknown
		CFG_SearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("AichoGuardian", "SearchRadius", 5f, new ConfigDescription("Radio máximo para buscar muros AichoDverg_Wall.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
		CFG_ResetSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("AichoGuardian", "ResetSeconds", 5f, new ConfigDescription("Segundos para que el tótem vuelva a su estado visual activo tras usarse.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 600f), Array.Empty<object>()));
		PrefabManager.OnVanillaPrefabsAvailable += RegisterAichoGuardianAndWall;
		_harmony = new Harmony("nazhi.aicho.guardian");
		_harmony.PatchAll(typeof(AichoGuardianPlugin).Assembly);
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"Aicho Guardian cargado con SearchRadius={CFG_SearchRadius.Value}, ResetSeconds={CFG_ResetSeconds.Value}");
	}

	private void OnDestroy()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterAichoGuardianAndWall;
		try
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
		catch
		{
		}
	}

	private void RegisterAichoGuardianAndWall()
	{
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Expected O, but got Unknown
		//IL_00b7: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Expected O, but got Unknown
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_0250: Expected O, but got Unknown
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Expected O, but got Unknown
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Expected O, but got Unknown
		try
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_dvergr_metal_wall_2x2");
			if ((Object)(object)prefab == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"No se encontró el prefab 'piece_dvergr_metal_wall_2x2'.");
				return;
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("AichoDverg_Wall", prefab);
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"No se pudo clonar 'piece_dvergr_metal_wall_2x2' a 'AichoDverg_Wall'.");
				return;
			}
			EnsureAdminOnlyPlacement(val, "AichoDverg_Wall");
			Piece component = val.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "$piece_aicho_dverg_wall";
				component.m_description = "$piece_aicho_dverg_wall_desc";
			}
			PieceConfig val2 = new PieceConfig();
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "Misc";
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
			{
				new RequirementConfig
				{
					Item = "Stone",
					Amount = 10
				}
			};
			PieceConfig val3 = val2;
			PieceManager.Instance.AddPiece(new CustomPiece(val, true, val3));
			LocalizationManager.Instance.AddToken("piece_aicho_dverg_wall", "Aicho Dvergr Wall", false);
			LocalizationManager.Instance.AddToken("piece_aicho_dverg_wall_desc", "Muro especial (solo admins).", false);
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("guard_stone");
			if ((Object)(object)prefab2 == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"No se encontró el prefab base del tótem (guard_stone / dverger_guardstone).");
				return;
			}
			GameObject val4 = PrefabManager.Instance.CreateClonedPrefab("Aicho_Guardian", prefab2);
			if ((Object)(object)val4 == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"No se pudo clonar el prefab base del tótem.");
				return;
			}
			PrivateArea component2 = val4.GetComponent<PrivateArea>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
			Transform val5 = val4.transform.Find("AreaMarker");
			if ((Object)(object)val5 != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val5).gameObject);
			}
			CircleProjector[] componentsInChildren = val4.GetComponentsInChildren<CircleProjector>(true);
			foreach (CircleProjector val6 in componentsInChildren)
			{
				Object.Destroy((Object)(object)((Component)val6).gameObject);
			}
			EnsureAdminOnlyPlacement(val4, "Aicho_Guardian");
			Piece component3 = val4.GetComponent<Piece>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.m_name = "$piece_aicho_guardian";
				component3.m_description = "$piece_aicho_guardian_desc";
			}
			AichoGuardianBehaviour aichoGuardianBehaviour = val4.GetComponent<AichoGuardianBehaviour>();
			if ((Object)(object)aichoGuardianBehaviour == (Object)null)
			{
				aichoGuardianBehaviour = val4.AddComponent<AichoGuardianBehaviour>();
			}
			aichoGuardianBehaviour.TargetPrefabName = "AichoDverg_Wall";
			val2 = new PieceConfig();
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "Misc";
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
			{
				new RequirementConfig
				{
					Item = "Stone",
					Amount = 10
				}
			};
			PieceConfig val7 = val2;
			PieceManager.Instance.AddPiece(new CustomPiece(val4, true, val7));
			LocalizationManager.Instance.AddToken("piece_aicho_guardian", "Aicho Guardian", false);
			LocalizationManager.Instance.AddToken("piece_aicho_guardian_desc", "Una piedra guardiana que destruye muros Aicho cercanos al activarse.", false);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registrado OK: Aicho_Guardian + AichoDverg_Wall (admin-only wall + admin-only guardian).");
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"Error registrando Aicho Guardian/Wall: {arg}");
		}
	}

	private static void EnsureAdminOnlyPlacement(GameObject go, string targetPrefabName)
	{
		AichoAdminOnlyPlacement aichoAdminOnlyPlacement = go.GetComponent<AichoAdminOnlyPlacement>();
		if ((Object)(object)aichoAdminOnlyPlacement == (Object)null)
		{
			aichoAdminOnlyPlacement = go.AddComponent<AichoAdminOnlyPlacement>();
		}
		aichoAdminOnlyPlacement.TargetPrefabName = targetPrefabName;
	}

	internal static bool IsSinglePlayerHost()
	{
		try
		{
			return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetConnectedPeers().Count == 0;
		}
		catch
		{
			return false;
		}
	}

	internal static long GetPlayerIdSafe(Player p)
	{
		try
		{
			return ((Object)(object)p != (Object)null) ? p.GetPlayerID() : 0;
		}
		catch
		{
			return 0L;
		}
	}

	internal static bool IsAdminLocal()
	{
		try
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (IsSinglePlayerHost())
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			long playerIdSafe = GetPlayerIdSafe(localPlayer);
			return playerIdSafe != 0L && ZNetExtension.IsAdmin(ZNet.instance, playerIdSafe);
		}
		catch
		{
			return false;
		}
	}

	internal static bool IsAdminId(long playerId)
	{
		try
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (IsSinglePlayerHost())
			{
				return true;
			}
			return playerId != 0L && ZNetExtension.IsAdmin(ZNet.instance, playerId);
		}
		catch
		{
			return false;
		}
	}
}
public class AichoGuardianBehaviour : MonoBehaviour, Interactable
{
	[CompilerGenerated]
	private sealed class <ResetVisualAfterDelay>d__10 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public float seconds;

		public AichoGuardianBehaviour <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <ResetVisualAfterDelay>d__10(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			int num = <>1__state;
			AichoGuardianBehaviour aichoGuardianBehaviour = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(seconds);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				aichoGuardianBehaviour.SetActiveVisual(active: true);
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public float SearchRadius = 5f;

	public string TargetPrefabName = "AichoDverg_Wall";

	private Coroutine _resetCoroutine;

	private void Start()
	{
		SetActiveVisual(active: true);
	}

	public string GetHoverText()
	{
		string text = Localization.instance.Localize("$piece_aicho_guardian");
		return Localization.instance.Localize(text + "\n[<color=yellow><b>$KEY_Use</b></color>] Romper muros Aicho cercanos");
	}

	public string GetHoverName()
	{
		return Localization.instance.Localize("$piece_aicho_guardian");
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		if (hold)
		{
			return false;
		}
		if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
		{
			return false;
		}
		if (!IsAdminUser(user))
		{
			return false;
		}
		float radius = ((AichoGuardianPlugin.CFG_SearchRadius != null) ? AichoGuardianPlugin.CFG_SearchRadius.Value : SearchRadius);
		float seconds = ((AichoGuardianPlugin.CFG_ResetSeconds != null) ? Mathf.Max(0.01f, AichoGuardianPlugin.CFG_ResetSeconds.Value) : 5f);
		int num = DestroyNearbyWalls(radius);
		Logger.LogInfo((object)$"[AichoGuardian] Muros destruidos: {num}");
		SetActiveVisual(active: false);
		if (_resetCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(_resetCoroutine);
		}
		_resetCoroutine = ((MonoBehaviour)this).StartCoroutine(ResetVisualAfterDelay(seconds));
		return true;
	}

	private static bool IsAdminUser(Humanoid user)
	{
		if (AichoGuardianPlugin.IsSinglePlayerHost())
		{
			return true;
		}
		Player val = (Player)(object)((user is Player) ? user : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		long playerIdSafe = AichoGuardianPlugin.GetPlayerIdSafe(val);
		return AichoGuardianPlugin.IsAdminId(playerIdSafe);
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	private int DestroyNearbyWalls(float radius)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		Vector3 position = ((Component)this).transform.position;
		List<Piece> list = new List<Piece>();
		Piece.GetAllPiecesInRadius(position, radius, list);
		foreach (Piece item in list)
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			string prefabName = Utils.GetPrefabName(((Component)item).gameObject);
			if (string.Equals(prefabName, TargetPrefabName, StringComparison.Ordinal))
			{
				WearNTear component = ((Component)item).GetComponent<WearNTear>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.m_nview == (Object)null) && component.m_nview.IsValid())
				{
					component.m_nview.ClaimOwnership();
					ZNetScene.instance.Destroy(((Component)component).gameObject);
					num++;
				}
			}
		}
		return num;
	}

	[IteratorStateMachine(typeof(<ResetVisualAfterDelay>d__10))]
	private IEnumerator ResetVisualAfterDelay(float seconds)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ResetVisualAfterDelay>d__10(0)
		{
			<>4__this = this,
			seconds = seconds
		};
	}

	private void SetActiveVisual(bool active)
	{
		//IL_0051: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!((Object)(object)MaterialMan.instance == (Object)null))
			{
				if (active)
				{
					MaterialMan.instance.ResetValue(((Component)this).gameObject, ShaderProps._Color);
					MaterialMan.instance.ResetValue(((Component)this).gameObject, ShaderProps._EmissionColor);
				}
				else
				{
					MaterialMan.instance.SetValue<Color>(((Component)this).gameObject, ShaderProps._Color, Color.grey);
					MaterialMan.instance.SetValue<Color>(((Component)this).gameObject, ShaderProps._EmissionColor, Color.grey * 0.1f);
				}
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("[AichoGuardian] Error en SetActiveVisual: " + ex.Message));
		}
	}
}
public class AichoAdminOnlyPlacement : MonoBehaviour
{
	[CompilerGenerated]
	private sealed class <Start>d__2 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AichoAdminOnlyPlacement <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <Start>d__2(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			int num = <>1__state;
			AichoAdminOnlyPlacement aichoAdminOnlyPlacement = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
				{
					return false;
				}
				<>2__current = (object)new WaitForSeconds(0.15f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				try
				{
					if (string.IsNullOrEmpty(aichoAdminOnlyPlacement.TargetPrefabName))
					{
						return false;
					}
					string prefabName = Utils.GetPrefabName(((Component)aichoAdminOnlyPlacement).gameObject);
					if (!string.Equals(prefabName, aichoAdminOnlyPlacement.TargetPrefabName, StringComparison.Ordinal))
					{
						return false;
					}
					if (AichoGuardianPlugin.IsSinglePlayerHost())
					{
						return false;
					}
					Piece component = ((Component)aichoAdminOnlyPlacement).GetComponent<Piece>();
					if ((Object)(object)component == (Object)null)
					{
						return false;
					}
					long creatorIdBestEffort = GetCreatorIdBestEffort(component);
					Player localPlayer = Player.m_localPlayer;
					long num2 = (((Object)(object)localPlayer != (Object)null) ? AichoGuardianPlugin.GetPlayerIdSafe(localPlayer) : 0);
					if (creatorIdBestEffort != 0L && creatorIdBestEffort == num2)
					{
						return false;
					}
					if (creatorIdBestEffort != 0L && !AichoGuardianPlugin.IsAdminId(creatorIdBestEffort))
					{
						Logger.LogWarning((object)$"[AichoGuardian] Bloqueada colocación de {prefabName} por no-admin (creator={creatorIdBestEffort}).");
						WearNTear component2 = ((Component)aichoAdminOnlyPlacement).GetComponent<WearNTear>();
						if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_nview != (Object)null && component2.m_nview.IsValid())
						{
							component2.m_nview.ClaimOwnership();
						}
						if ((Object)(object)ZNetScene.instance != (Object)null)
						{
							ZNetScene.instance.Destroy(((Component)aichoAdminOnlyPlacement).gameObject);
						}
						else
						{
							Object.Destroy((Object)(object)((Component)aichoAdminOnlyPlacement).gameObject);
						}
					}
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)("[AichoGuardian] Error en AichoAdminOnlyPlacement: " + ex.Message));
				}
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public string TargetPrefabName = "";

	private const float CheckDelay = 0.15f;

	[IteratorStateMachine(typeof(<Start>d__2))]
	private IEnumerator Start()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <Start>d__2(0)
		{
			<>4__this = this
		};
	}

	private static long GetCreatorIdBestEffort(Piece piece)
	{
		try
		{
			MethodInfo method = typeof(Piece).GetMethod("GetCreator", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null && method.ReturnType == typeof(long))
			{
				return (long)method.Invoke(piece, null);
			}
			FieldInfo field = typeof(Piece).GetField("m_creator", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field.FieldType == typeof(long))
			{
				return (long)field.GetValue(piece);
			}
		}
		catch
		{
		}
		return 0L;
	}
}
[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
public static class AichoHammerVisibilityPatches
{
	[HarmonyPostfix]
	private static void PieceTable_UpdateAvailable_Postfix(PieceTable __instance, HashSet<string> knownRecipies, Player player, bool hideUnavailable, bool noPlacementCost)
	{
		try
		{
			if ((Object)(object)__instance == (Object)null || AichoGuardianPlugin.IsAdminLocal() || __instance.m_availablePieces == null || __instance.m_availablePieces.Count == 0)
			{
				return;
			}
			for (int i = 0; i < __instance.m_availablePieces.Count; i++)
			{
				List<Piece> list = __instance.m_availablePieces[i];
				if (list == null || list.Count == 0)
				{
					continue;
				}
				list.RemoveAll(delegate(Piece piece)
				{
					if ((Object)(object)piece == (Object)null)
					{
						return false;
					}
					string prefabName = Utils.GetPrefabName(((Component)piece).gameObject);
					return string.Equals(prefabName, "AichoDverg_Wall", StringComparison.Ordinal) || string.Equals(prefabName, "Aicho_Guardian", StringComparison.Ordinal);
				});
			}
		}
		catch
		{
		}
	}
}

Barquero.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AichoGuardian")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AichoGuardian")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("D28110A9-E229-4700-AD4D-DCD37486A82B")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace BoatLoanMod;

[BepInPlugin("com.nazhi.boatloanmod", "Boat Loan Mod", "2.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class BoatLoanPlugin : BaseUnityPlugin
{
	public const string ModGuid = "com.nazhi.boatloanmod";

	public const string ModName = "Boat Loan Mod";

	public const string ModVersion = "2.0.0";

	public static BoatLoanPlugin Instance;

	private Harmony _harmony;

	private LoanNpcPanel _panel;

	private GameObject _boatPrefab;

	private GameObject _jaroldPrefab;

	private ConfigEntry<float> _boatLifetime;

	private ConfigEntry<float> _waterSearchRadius;

	private bool _prefabsReady;

	public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;

	private void Awake()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		Instance = this;
		_harmony = new Harmony("com.nazhi.boatloanmod");
		_harmony.PatchAll();
		_boatLifetime = ((BaseUnityPlugin)this).Config.Bind<float>("Barco", "BoatLifetime", 30f, "Segundos que dura el barco prestado antes de desaparecer.");
		_waterSearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Barco", "WaterSearchRadius", 60f, "Radio máximo (en metros) en el que se busca agua para spawnear el barco.");
		PrefabManager.OnVanillaPrefabsAvailable += RegisterJarold;
		GUIManager.OnCustomGUIAvailable += OnCustomGUIAvailable;
		Logger.LogInfo((object)"Boat Loan Mod v2.0.0 loaded");
	}

	private void OnDestroy()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterJarold;
		GUIManager.OnCustomGUIAvailable -= OnCustomGUIAvailable;
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	private void RegisterJarold()
	{
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Expected O, but got Unknown
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Expected O, but got Unknown
		try
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("MLNPC_Male0");
			if ((Object)(object)prefab == (Object)null)
			{
				Logger.LogError((object)"No se encontró MLNPC_Male0.");
				return;
			}
			_boatPrefab = PrefabManager.Instance.GetPrefab("Karve");
			if ((Object)(object)_boatPrefab == (Object)null)
			{
				Logger.LogError((object)"No se encontró el prefab Karve.");
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("Jarold_BLM", prefab);
			Character component = val.GetComponent<Character>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_speed = 0f;
				component.m_walkSpeed = 0f;
				component.m_crouchSpeed = 0f;
				component.m_runSpeed = 0f;
				component.m_swimSpeed = 0f;
				component.m_turnSpeed = 0f;
				component.m_runTurnSpeed = 0f;
				component.m_flySlowSpeed = 0f;
				component.m_flyFastSpeed = 0f;
				component.m_flyTurnSpeed = 0f;
				component.m_acceleration = 0f;
				component.m_jumpForce = 0f;
				component.m_swimTurnSpeed = 0f;
			}
			BaseAI component2 = val.GetComponent<BaseAI>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Behaviour)component2).enabled = false;
			}
			MonsterAI component3 = val.GetComponent<MonsterAI>();
			if ((Object)(object)component3 != (Object)null)
			{
				((Behaviour)component3).enabled = false;
			}
			CustomCreature val2 = new CustomCreature(val, true, new CreatureConfig
			{
				Faction = (Faction)10
			});
			CreatureManager.Instance.AddCreature(val2);
			_jaroldPrefab = val;
			_prefabsReady = true;
			Logger.LogInfo((object)"Jarold_BLM registrado como CustomCreature estático.");
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"RegisterJarold: {arg}");
		}
		finally
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterJarold;
		}
	}

	private void Update()
	{
		if (!((Object)(object)Player.m_localPlayer == (Object)null) && _panel != null && _panel.IsVisible && Input.GetKeyDown((KeyCode)27))
		{
			_panel.HideAndResetCurrentNpc();
		}
	}

	private void TrySpawnJarold()
	{
		//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_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_006d: 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_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)
		//IL_009e: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: 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)
		if ((Object)(object)_jaroldPrefab == (Object)null)
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "Prefab de Jarold no disponible aún.", 0, (Sprite)null);
			return;
		}
		if (JaroldExistsInWorld())
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "Jarold ya está en el mundo.", 0, (Sprite)null);
			return;
		}
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		Vector3 forward = ((Component)Player.m_localPlayer).transform.forward;
		Vector3 val = position + forward * 3f;
		if ((Object)(object)ZoneSystem.instance != (Object)null)
		{
			val.y = ZoneSystem.instance.GetGroundHeight(val) + 0.1f;
		}
		Quaternion val2 = Quaternion.LookRotation(-forward);
		ZNetScene.instance.SpawnObject(val, val2, _jaroldPrefab);
		((Character)Player.m_localPlayer).Message((MessageType)2, "Jarold El Mercante ha aparecido.", 0, (Sprite)null);
		Logger.LogInfo((object)$"Jarold spawneado en {val}");
	}

	private void TryDespawnJarold()
	{
		_panel?.HideAndResetCurrentNpc();
		int num = 0;
		foreach (Character item in Character.GetAllCharacters().ToList())
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			ZNetView component = ((Component)item).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid() && component.GetZDO().GetPrefab() == StringExtensionMethods.GetStableHashCode("Jarold_BLM"))
			{
				try
				{
					((Component)item).gameObject.SetActive(false);
					ZNetScene.instance.Destroy(((Component)item).gameObject);
					num++;
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)("TryDespawnJarold (scene): " + ex.Message));
				}
			}
		}
		List<ZDO> list = new List<ZDO>();
		int num2 = 0;
		while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative("Jarold_BLM", list, ref num2))
		{
		}
		foreach (ZDO item2 in list)
		{
			try
			{
				item2.SetOwner(ZDOMan.GetSessionID());
				ZDOMan.instance.DestroyZDO(item2);
				num++;
			}
			catch (Exception ex2)
			{
				Logger.LogWarning((object)("TryDespawnJarold (ZDO): " + ex2.Message));
			}
		}
		string text = ((num > 0) ? $"Jarold eliminado ({num})." : "No se encontró a Jarold en el mundo.");
		((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
		Logger.LogInfo((object)text);
	}

	private bool JaroldExistsInWorld()
	{
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if (!((Object)(object)allCharacter == (Object)null))
			{
				ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetPrefab() == StringExtensionMethods.GetStableHashCode("Jarold_BLM"))
				{
					return true;
				}
			}
		}
		List<ZDO> list = new List<ZDO>();
		int num = 0;
		while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative("Jarold_BLM", list, ref num))
		{
		}
		return list.Count > 0;
	}

	private void OnCustomGUIAvailable()
	{
		RebuildPanel();
	}

	private void RebuildPanel()
	{
		if (GUIManager.Instance == null || (Object)(object)GUIManager.CustomGUIFront == (Object)null)
		{
			return;
		}
		try
		{
			_panel?.Destroy();
			_panel = null;
			_panel = new LoanNpcPanel(this, Logger);
			_panel.Build();
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"Error construyendo LoanNpcPanel: {arg}");
		}
	}

	private void EnsurePanelReady()
	{
		if (_panel == null || !_panel.IsValid)
		{
			RebuildPanel();
		}
	}

	public void OpenLoanUI(LoanNpcBehaviour npc)
	{
		EnsurePanelReady();
		if (_panel != null && _panel.IsValid)
		{
			_panel.Show(npc);
		}
	}

	public void CloseLoanUI()
	{
		_panel?.Hide();
	}

	public void RequestBoat(LoanNpcBehaviour npc)
	{
		//IL_004b: 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_007d: 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_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_00b0: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			CloseLoanUI();
			npc.ResetInteraction();
			return;
		}
		if ((Object)(object)_boatPrefab == (Object)null)
		{
			((Character)localPlayer).Message((MessageType)2, "No pude encontrar el prefab del barco.", 0, (Sprite)null);
			CloseLoanUI();
			npc.ResetInteraction();
			return;
		}
		if (WaterSpawnHelper.TryFindNearbyWaterPosition(((Component)localPlayer).transform.position, 12f, _waterSearchRadius.Value, out var result, ((Component)npc).transform.forward))
		{
			GameObject val = Object.Instantiate<GameObject>(_boatPrefab, result, Quaternion.LookRotation(((Component)localPlayer).transform.forward));
			Rigidbody component = val.GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.linearVelocity = Vector3.zero;
				component.angularVelocity = Vector3.zero;
			}
			TemporaryBoat temporaryBoat = val.AddComponent<TemporaryBoat>();
			temporaryBoat.Setup(_boatLifetime.Value, Logger);
			((Character)localPlayer).Message((MessageType)2, $"¡Tienes {_boatLifetime.Value:F0} segundos con el barco!", 0, (Sprite)null);
		}
		else
		{
			((Character)localPlayer).Message((MessageType)2, "No encontré agua cercana para dejarte un barco.", 0, (Sprite)null);
		}
		CloseLoanUI();
		npc.ResetInteraction();
	}
}
public class LoanNpcBehaviour : MonoBehaviour, Interactable, Hoverable
{
	private BoatLoanPlugin _plugin;

	private bool _busy;

	public void Setup(BoatLoanPlugin plugin)
	{
		_plugin = plugin;
	}

	public string GetHoverName()
	{
		return "Jarold El Mercante";
	}

	public string GetHoverText()
	{
		return "<color=#E7C07A>Jarold El Mercante</color>\n[E] Hablar";
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		if (hold)
		{
			return false;
		}
		if ((Object)(object)_plugin == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer || _busy)
		{
			return false;
		}
		_busy = true;
		_plugin.OpenLoanUI(this);
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	public void ResetInteraction()
	{
		_busy = false;
	}
}
public static class NpcArmorApplier
{
	private static readonly string[] ChestKeywords = new string[4] { "chest", "body", "torso", "armor" };

	private static readonly string[] LegKeywords = new string[5] { "leg", "legs", "pants", "legitem", "legsitem" };

	public static bool ApplyArmor(GameObject npc, ManualLogSource logger)
	{
		if ((Object)(object)npc == (Object)null)
		{
			return false;
		}
		Humanoid val = npc.GetComponent<Humanoid>() ?? npc.GetComponentInChildren<Humanoid>();
		Component componentInChildren = npc.GetComponentInChildren(typeof(VisEquipment));
		PrefabManager instance = PrefabManager.Instance;
		GameObject val2 = ((instance != null) ? instance.GetPrefab("ArmorHarvester1") : null);
		ItemDrop itemDrop = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<ItemDrop>() : null);
		List<string> candidates = BuildCandidates("ArmorHarvester1", val2, itemDrop);
		bool flag = false;
		bool flag2 = false;
		if ((Object)(object)val != (Object)null)
		{
			flag = TryApplyOnTarget(val, ChestKeywords, candidates, itemDrop, logger, "Humanoid");
			TryInvokeRefresh(val, logger);
		}
		if ((Object)(object)componentInChildren != (Object)null)
		{
			flag2 = TryApplyOnTarget(componentInChildren, ChestKeywords, candidates, itemDrop, logger, "VisEquipment");
			TryClearOnTarget(componentInChildren, LegKeywords, logger);
			TryInvokeRefresh(componentInChildren, logger);
		}
		return flag || flag2;
	}

	private static bool TryApplyOnTarget(object target, string[] keywords, List<string> candidates, ItemDrop itemDrop, ManualLogSource logger, string tag)
	{
		Type type = target.GetType();
		foreach (string value in keywords)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!methodInfo.Name.ToLowerInvariant().Contains(value))
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length != 1)
				{
					continue;
				}
				try
				{
					Type parameterType = parameters[0].ParameterType;
					if (parameterType == typeof(string))
					{
						using List<string>.Enumerator enumerator = candidates.GetEnumerator();
						if (enumerator.MoveNext())
						{
							string current = enumerator.Current;
							methodInfo.Invoke(target, new object[1] { current });
							return true;
						}
					}
					if (parameterType == typeof(int))
					{
						using List<string>.Enumerator enumerator2 = candidates.GetEnumerator();
						if (enumerator2.MoveNext())
						{
							string current2 = enumerator2.Current;
							methodInfo.Invoke(target, new object[1] { StringExtensionMethods.GetStableHashCode(current2) });
							return true;
						}
					}
					if (typeof(ItemData).IsAssignableFrom(parameterType) && (Object)(object)itemDrop != (Object)null)
					{
						methodInfo.Invoke(target, new object[1] { itemDrop.m_itemData });
						return true;
					}
					if (typeof(GameObject).IsAssignableFrom(parameterType) && (Object)(object)itemDrop != (Object)null)
					{
						methodInfo.Invoke(target, new object[1] { ((Component)itemDrop).gameObject });
						return true;
					}
				}
				catch (Exception ex)
				{
					logger.LogWarning((object)("[" + tag + "] " + methodInfo.Name + ": " + ex.Message));
				}
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!fieldInfo.Name.ToLowerInvariant().Contains(value))
				{
					continue;
				}
				try
				{
					if (fieldInfo.FieldType == typeof(string))
					{
						fieldInfo.SetValue(target, candidates[0]);
						return true;
					}
					if (fieldInfo.FieldType == typeof(int))
					{
						fieldInfo.SetValue(target, StringExtensionMethods.GetStableHashCode(candidates[0]));
						return true;
					}
					if (typeof(ItemData).IsAssignableFrom(fieldInfo.FieldType) && (Object)(object)itemDrop != (Object)null)
					{
						fieldInfo.SetValue(target, itemDrop.m_itemData);
						return true;
					}
					if (typeof(GameObject).IsAssignableFrom(fieldInfo.FieldType) && (Object)(object)itemDrop != (Object)null)
					{
						fieldInfo.SetValue(target, ((Component)itemDrop).gameObject);
						return true;
					}
				}
				catch (Exception ex2)
				{
					logger.LogWarning((object)("[" + tag + "] field " + fieldInfo.Name + ": " + ex2.Message));
				}
			}
		}
		return false;
	}

	private static void TryClearOnTarget(object target, string[] keywords, ManualLogSource logger)
	{
		Type type = target.GetType();
		foreach (string value in keywords)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!methodInfo.Name.ToLowerInvariant().Contains(value))
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length != 1)
				{
					continue;
				}
				try
				{
					Type parameterType = parameters[0].ParameterType;
					if (parameterType == typeof(string))
					{
						methodInfo.Invoke(target, new object[1] { "" });
						return;
					}
					if (parameterType == typeof(int))
					{
						methodInfo.Invoke(target, new object[1] { 0 });
						return;
					}
					if (!parameterType.IsValueType)
					{
						methodInfo.Invoke(target, new object[1]);
						return;
					}
				}
				catch
				{
				}
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!fieldInfo.Name.ToLowerInvariant().Contains(value))
				{
					continue;
				}
				try
				{
					if (fieldInfo.FieldType == typeof(string))
					{
						fieldInfo.SetValue(target, "");
						return;
					}
					if (fieldInfo.FieldType == typeof(int))
					{
						fieldInfo.SetValue(target, 0);
						return;
					}
					if (!fieldInfo.FieldType.IsValueType)
					{
						fieldInfo.SetValue(target, null);
						return;
					}
				}
				catch
				{
				}
			}
		}
	}

	private static void TryInvokeRefresh(object target, ManualLogSource logger)
	{
		string[] array = new string[6] { "SetupVisEquipment", "SetupEquipment", "UpdateEquipment", "UpdateEquipmentVisuals", "UpdateVisuals", "ResetCloth" };
		Type type = target.GetType();
		string[] array2 = array;
		foreach (string text in array2)
		{
			MethodInfo methodInfo = AccessTools.Method(type, text, (Type[])null, (Type[])null);
			if (!(methodInfo == null) && methodInfo.GetParameters().Length == 0)
			{
				try
				{
					methodInfo.Invoke(target, null);
				}
				catch
				{
				}
			}
		}
	}

	private static List<string> BuildCandidates(string raw, GameObject prefab, ItemDrop itemDrop)
	{
		List<string> list = new List<string>();
		if (!string.IsNullOrEmpty(raw))
		{
			list.Add(raw);
		}
		if ((Object)(object)prefab != (Object)null)
		{
			list.Add(((Object)prefab).name);
		}
		if (itemDrop?.m_itemData?.m_shared != null && !string.IsNullOrEmpty(itemDrop.m_itemData.m_shared.m_name))
		{
			list.Add(itemDrop.m_itemData.m_shared.m_name);
		}
		return list.Where((string x) => !string.IsNullOrEmpty(x)).Distinct().ToList();
	}
}
public class LoanNpcPanel
{
	private readonly BoatLoanPlugin _plugin;

	private readonly ManualLogSource _logger;

	private GameObject _panelRoot;

	private LoanNpcBehaviour _currentNpc;

	public bool IsVisible
	{
		get
		{
			if ((Object)(object)_panelRoot != (Object)null)
			{
				return _panelRoot.activeSelf;
			}
			return false;
		}
	}

	public bool IsValid => (Object)(object)_panelRoot != (Object)null;

	public LoanNpcPanel(BoatLoanPlugin plugin, ManualLogSource logger)
	{
		_plugin = plugin;
		_logger = logger;
	}

	public void Build()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		//IL_0074: 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_009e: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: 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_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_027a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_030d: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		//IL_032b: Unknown result type (might be due to invalid IL or missing references)
		//IL_036c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0385: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c7: Expected O, but got Unknown
		//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0440: Unknown result type (might be due to invalid IL or missing references)
		//IL_0459: Unknown result type (might be due to invalid IL or missing references)
		//IL_0465: Unknown result type (might be due to invalid IL or missing references)
		//IL_047d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0487: Expected O, but got Unknown
		if (GUIManager.Instance == null || (Object)(object)GUIManager.CustomGUIFront == (Object)null)
		{
			throw new Exception("GUIManager no disponible.");
		}
		_panelRoot = new GameObject("BoatLoanPanelRoot", new Type[1] { typeof(RectTransform) });
		_panelRoot.transform.SetParent(GUIManager.CustomGUIFront.transform, false);
		RectTransform component = _panelRoot.GetComponent<RectTransform>();
		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(760f, 580f);
		((Transform)component).localPosition = new Vector3(570f, 0f, 0f);
		GameObject val = GUIManager.Instance.CreateWoodpanel(_panelRoot.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 250f), 690f, 95f, false);
		((Object)val).name = "TopWoodPanel";
		SetWoodVisible(val);
		CreateOverlay(val.transform, "TopOverlay", new Color(0f, 0f, 0f, 0.85f));
		GUIManager.Instance.CreateText("Jarold El Mercante", val.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, GUIManager.Instance.NorseBold, 30, new Color(1f, 0.79f, 0.22f, 1f), true, Color.black, 560f, 42f, false).GetComponent<Text>().alignment = (TextAnchor)4;
		GameObject val2 = GUIManager.Instance.CreateWoodpanel(_panelRoot.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -40f), 690f, 400f, false);
		((Object)val2).name = "BottomWoodPanel";
		SetWoodVisible(val2);
		CreateOverlay(val2.transform, "BottomOverlay", new Color(0f, 0f, 0f, 0.85f));
		Text component2 = GUIManager.Instance.CreateText("Hola ! Soy Jarold , ¿Cómo te puedo ayudar?", val2.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -60f), GUIManager.Instance.AveriaSerifBold, 22, new Color(0.96f, 0.93f, 0.86f, 1f), true, Color.black, 580f, 60f, false).GetComponent<Text>();
		component2.alignment = (TextAnchor)1;
		component2.horizontalOverflow = (HorizontalWrapMode)0;
		component2.verticalOverflow = (VerticalWrapMode)1;
		GameObject val3 = GUIManager.Instance.CreateButton("Necesito un Barco", val2.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 30f), 470f, 60f);
		((Object)val3).name = "RentButton";
		Button component3 = val3.GetComponent<Button>();
		ApplyColors(component3, new Color(0.35f, 1f, 0.35f, 1f), new Color(0.18f, 0.82f, 0.18f, 1f));
		StyleText(val3, new Color(1f, 0.9f, 0.45f, 1f));
		((UnityEvent)component3.onClick).AddListener((UnityAction)delegate
		{
			if ((Object)(object)_currentNpc != (Object)null)
			{
				_plugin.RequestBoat(_currentNpc);
			}
		});
		GameObject val4 = GUIManager.Instance.CreateButton("Nada, lo siento", val2.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -40f), 470f, 56f);
		((Object)val4).name = "CloseButton";
		Button component4 = val4.GetComponent<Button>();
		ApplyColors(component4, new Color(1f, 0.3f, 0.3f, 1f), new Color(0.82f, 0.12f, 0.12f, 1f));
		StyleText(val4, Color.white);
		((UnityEvent)component4.onClick).AddListener(new UnityAction(HideAndResetCurrentNpc));
		_panelRoot.SetActive(false);
	}

	private static void SetWoodVisible(GameObject obj)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		Image component = obj.GetComponent<Image>();
		if ((Object)(object)component != (Object)null)
		{
			((Graphic)component).color = Color.white;
		}
	}

	private static void CreateOverlay(Transform parent, string name, Color color)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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_0083: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name, new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		val.transform.SetParent(parent, false);
		RectTransform component = val.GetComponent<RectTransform>();
		component.anchorMin = Vector2.zero;
		component.anchorMax = Vector2.one;
		component.offsetMin = new Vector2(10f, 10f);
		component.offsetMax = new Vector2(-10f, -10f);
		Image component2 = val.GetComponent<Image>();
		((Graphic)component2).color = color;
		((Graphic)component2).raycastTarget = false;
		val.transform.SetAsFirstSibling();
	}

	private static void ApplyColors(Button btn, Color hover, Color pressed)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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)
		ColorBlock valheimButtonColorBlock = GUIManager.Instance.ValheimButtonColorBlock;
		((ColorBlock)(ref valheimButtonColorBlock)).normalColor = Color.white;
		((ColorBlock)(ref valheimButtonColorBlock)).highlightedColor = hover;
		((ColorBlock)(ref valheimButtonColorBlock)).pressedColor = pressed;
		((ColorBlock)(ref valheimButtonColorBlock)).selectedColor = hover;
		((ColorBlock)(ref valheimButtonColorBlock)).disabledColor = new Color(0.6f, 0.6f, 0.6f, 1f);
		((ColorBlock)(ref valheimButtonColorBlock)).colorMultiplier = 1f;
		((ColorBlock)(ref valheimButtonColorBlock)).fadeDuration = 0.08f;
		((Selectable)btn).colors = valheimButtonColorBlock;
	}

	private static void StyleText(GameObject btn, Color color)
	{
		//IL_0013: 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)
		Text componentInChildren = btn.GetComponentInChildren<Text>(true);
		if (!((Object)(object)componentInChildren == (Object)null))
		{
			((Graphic)componentInChildren).color = color;
			componentInChildren.font = GUIManager.Instance.AveriaSerifBold;
			componentInChildren.fontSize = 24;
			componentInChildren.alignment = (TextAnchor)4;
			Outline val = ((Component)componentInChildren).GetComponent<Outline>() ?? ((Component)componentInChildren).gameObject.AddComponent<Outline>();
			((Shadow)val).effectColor = Color.black;
			((Shadow)val).effectDistance = new Vector2(1f, -1f);
		}
	}

	public void Show(LoanNpcBehaviour npc)
	{
		if (!((Object)(object)_panelRoot == (Object)null))
		{
			_currentNpc = npc;
			_panelRoot.SetActive(true);
			GUIManager.BlockInput(true);
		}
	}

	public void Hide()
	{
		if (!((Object)(object)_panelRoot == (Object)null))
		{
			_panelRoot.SetActive(false);
			GUIManager.BlockInput(false);
			_currentNpc = null;
		}
	}

	public void HideAndResetCurrentNpc()
	{
		_currentNpc?.ResetInteraction();
		Hide();
	}

	public void Destroy()
	{
		if ((Object)(object)_panelRoot != (Object)null)
		{
			Object.Destroy((Object)(object)_panelRoot);
			_panelRoot = null;
		}
	}
}
public class TemporaryBoat : MonoBehaviour
{
	private float _lifetime;

	private float _elapsed;

	private ManualLogSource _logger;

	private bool _destroyed;

	public void Setup(float lifetime, ManualLogSource logger)
	{
		_lifetime = lifetime;
		_logger = logger;
		WearNTear component = ((Component)this).GetComponent<WearNTear>();
		if ((Object)(object)component != (Object)null)
		{
			component.m_health = 1E+09f;
			((Behaviour)component).enabled = false;
		}
	}

	private void Update()
	{
		if (_destroyed)
		{
			return;
		}
		_elapsed += Time.deltaTime;
		if (_elapsed >= _lifetime - 5f && _elapsed - Time.deltaTime < _lifetime - 5f)
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, "¡El barco desaparecerá en 5 segundos!", 0, (Sprite)null);
			}
		}
		if (_elapsed >= _lifetime)
		{
			_destroyed = true;
			DestroyBoatNoDrops();
		}
	}

	private void DestroyBoatNoDrops()
	{
		try
		{
			DropOnDestroyed[] componentsInChildren = ((Component)this).GetComponentsInChildren<DropOnDestroyed>(true);
			foreach (DropOnDestroyed val in componentsInChildren)
			{
				((Behaviour)val).enabled = false;
			}
			Container[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Container>(true);
			foreach (Container val2 in componentsInChildren2)
			{
				((Behaviour)val2).enabled = false;
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, "El barco prestado ha desaparecido.", 0, (Sprite)null);
			}
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
				return;
			}
			((Component)this).gameObject.SetActive(false);
			Object.Destroy((Object)(object)((Component)this).gameObject, 0.1f);
		}
		catch (Exception arg)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogError((object)$"TemporaryBoat: {arg}");
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
}
public static class WaterSpawnHelper
{
	public static bool TryFindNearbyWaterPosition(Vector3 center, float minRadius, float maxRadius, out Vector3 result, Vector3 preferredDirection = default(Vector3))
	{
		//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_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: 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_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		result = Vector3.zero;
		if ((Object)(object)ZoneSystem.instance == (Object)null)
		{
			return false;
		}
		if (preferredDirection != Vector3.zero)
		{
			preferredDirection.y = 0f;
			((Vector3)(ref preferredDirection)).Normalize();
			for (int i = 0; i < 20; i++)
			{
				float num = Mathf.Lerp(minRadius, maxRadius, (float)i / 19f);
				Vector3 val = center + preferredDirection * num;
				float groundHeight = ZoneSystem.instance.GetGroundHeight(val);
				float liquidLevel = Floating.GetLiquidLevel(val, 1f, (LiquidType)0);
				if (!(liquidLevel <= -9999f) && !(liquidLevel - groundHeight < 2.5f))
				{
					result = new Vector3(val.x, liquidLevel + 0.35f, val.z);
					return true;
				}
			}
			return false;
		}
		for (int j = 0; j < 10; j++)
		{
			float num2 = Mathf.Lerp(minRadius, maxRadius, (float)j / 9f);
			for (int k = 0; k < 36; k++)
			{
				Vector3 val2 = center + Quaternion.Euler(0f, 10f * (float)k, 0f) * Vector3.forward * num2;
				float groundHeight2 = ZoneSystem.instance.GetGroundHeight(val2);
				float liquidLevel2 = Floating.GetLiquidLevel(val2, 1f, (LiquidType)0);
				if (!(liquidLevel2 <= -9999f) && !(liquidLevel2 - groundHeight2 < 2.5f))
				{
					result = new Vector3(val2.x, liquidLevel2 + 0.35f, val2.z);
					return true;
				}
			}
		}
		return false;
	}
}
[HarmonyPatch(typeof(Humanoid), "Awake")]
public static class Humanoid_Awake_Patch
{
	[CompilerGenerated]
	private sealed class <InitJaroldDelayed>d__1 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Humanoid humanoid;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <InitJaroldDelayed>d__1(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = null;
				<>1__state = 1;
				return true;
			case 1:
			{
				<>1__state = -1;
				if ((Object)(object)humanoid == (Object)null)
				{
					return false;
				}
				ZNetView component = ((Component)humanoid).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid())
				{
					return false;
				}
				if (component.GetZDO().GetPrefab() != StringExtensionMethods.GetStableHashCode("Jarold_BLM"))
				{
					return false;
				}
				GameObject gameObject = ((Component)humanoid).gameObject;
				LoanNpcBehaviour loanNpcBehaviour = gameObject.GetComponent<LoanNpcBehaviour>() ?? gameObject.AddComponent<LoanNpcBehaviour>();
				loanNpcBehaviour.Setup(BoatLoanPlugin.Instance);
				Character component2 = gameObject.GetComponent<Character>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.m_speed = 0f;
					component2.m_walkSpeed = 0f;
					component2.m_crouchSpeed = 0f;
					component2.m_runSpeed = 0f;
					component2.m_swimSpeed = 0f;
					component2.m_turnSpeed = 0f;
					component2.m_runTurnSpeed = 0f;
					component2.m_flySlowSpeed = 0f;
					component2.m_flyFastSpeed = 0f;
					component2.m_flyTurnSpeed = 0f;
					component2.m_acceleration = 0f;
					component2.m_jumpForce = 0f;
					component2.m_swimTurnSpeed = 0f;
				}
				BaseAI component3 = gameObject.GetComponent<BaseAI>();
				if ((Object)(object)component3 != (Object)null)
				{
					((Behaviour)component3).enabled = false;
				}
				MonsterAI component4 = gameObject.GetComponent<MonsterAI>();
				if ((Object)(object)component4 != (Object)null)
				{
					((Behaviour)component4).enabled = false;
				}
				NpcArmorApplier.ApplyArmor(gameObject, BoatLoanPlugin.Instance.Logger);
				BoatLoanPlugin.Instance.Logger.LogInfo((object)"Jarold inicializado en escena.");
				return false;
			}
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private static void Postfix(Humanoid __instance)
	{
		if (!((Object)(object)__instance == (Object)null) && !((Object)(object)BoatLoanPlugin.Instance == (Object)null))
		{
			((MonoBehaviour)BoatLoanPlugin.Instance).StartCoroutine(InitJaroldDelayed(__instance));
		}
	}

	[IteratorStateMachine(typeof(<InitJaroldDelayed>d__1))]
	private static IEnumerator InitJaroldDelayed(Humanoid humanoid)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <InitJaroldDelayed>d__1(0)
		{
			humanoid = humanoid
		};
	}
}

Ghosts.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Knuckles")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Knuckles")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("97A069E8-5AAB-4E2A-BAE4-B6E2E251C03E")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Knuckles.GhostShip
{
	public class SkellyEventCommand : ConsoleCommand
	{
		public override string Name => "skellyevent";

		public override string Help => "skellyevent <playerName> — inicia el evento de invasión";

		public override void Run(string[] args)
		{
			if (args.Length < 1)
			{
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print("Uso: skellyevent <playerName>");
				}
				return;
			}
			string name = args[0];
			Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => p.GetPlayerName().Equals(name, StringComparison.OrdinalIgnoreCase)));
			if ((Object)(object)val == (Object)null)
			{
				Console instance2 = Console.instance;
				if (instance2 != null)
				{
					instance2.Print("Jugador '" + name + "' no encontrado.");
				}
				ManualLogSource log = SpawnGhostLongshipAndSkels.Log;
				if (log != null)
				{
					log.LogWarning((object)("skellyevent: '" + name + "' no encontrado."));
				}
			}
			else
			{
				Console instance3 = Console.instance;
				if (instance3 != null)
				{
					instance3.Print("Iniciando invasión en " + val.GetPlayerName() + "...");
				}
				SpawnGhostLongshipAndSkels.StartEventForTarget(val);
			}
		}
	}
	[BepInPlugin("nazhi.spawnlongshipghostandskels", "Spawn Ghost Longship + Waves", "2.6.0")]
	public class SpawnGhostLongshipAndSkels : BaseUnityPlugin
	{
		private class BoatGodMode : MonoBehaviour
		{
			private WearNTear _wt;

			private void Awake()
			{
				_wt = ((Component)this).GetComponentInChildren<WearNTear>();
				if ((Object)(object)_wt == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)"BoatGodMode: WearNTear no encontrado en el Longship.");
					}
				}
			}

			private void LateUpdate()
			{
				if ((Object)(object)_wt == (Object)null)
				{
					return;
				}
				try
				{
					_wt.Repair();
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"BoatGodMode: error en Repair(): {arg}");
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "Awake")]
		private static class ZNetPatch
		{
			[CompilerGenerated]
			private sealed class <WaitAndRegister>d__1 : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private object <>2__current;

				private float <t>5__1;

				object IEnumerator<object>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <WaitAndRegister>d__1(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_0034: Unknown result type (might be due to invalid IL or missing references)
					//IL_003e: Expected O, but got Unknown
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<t>5__1 = 0f;
						break;
					case 1:
						<>1__state = -1;
						<t>5__1 += 0.1f;
						break;
					}
					if (ZRoutedRpc.instance == null && <t>5__1 < 10f)
					{
						<>2__current = (object)new WaitForSeconds(0.1f);
						<>1__state = 1;
						return true;
					}
					if (ZRoutedRpc.instance != null)
					{
						Log.LogInfo((object)$"ZRoutedRpc encontrado tras {<t>5__1:F1}s — registrando RPCs.");
						RegisterAllRpcs();
					}
					else
					{
						Log.LogError((object)"ZRoutedRpc nunca se inicializó tras 10s.");
					}
					return false;
				}

				bool IEnumerator.MoveNext()
				{
					//ILSpy generated this explicit interface implementation from .override directive in MoveNext
					return this.MoveNext();
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			[HarmonyPostfix]
			private static void Postfix()
			{
				if ((Object)(object)Instance != (Object)null)
				{
					((MonoBehaviour)Instance).StartCoroutine(WaitAndRegister());
				}
			}

			[IteratorStateMachine(typeof(<WaitAndRegister>d__1))]
			private static IEnumerator WaitAndRegister()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <WaitAndRegister>d__1(0);
			}
		}

		internal struct InvasionContext
		{
			public Vector3 ShorePoint;

			public Vector3 WaterPoint;

			public Vector3 ShoreDir;

			public float WaterLevel;

			public Vector3 BoatPos;

			public Quaternion BoatRot;
		}

		private class WaveSkeleton : MonoBehaviour
		{
			private void OnDestroy()
			{
				if (_currentWaveAlive > 0)
				{
					_currentWaveAlive--;
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)$"WaveSkeleton destruido. Restantes en wave: {_currentWaveAlive}");
					}
				}
			}
		}

		private class GhostEnforcer : MonoBehaviour
		{
			private float _nextTime;

			private const float Interval = 0.5f;

			private void Update()
			{
				if ((Object)(object)this == (Object)null || (Object)(object)((Component)this).gameObject == (Object)null || Time.time < _nextTime)
				{
					return;
				}
				_nextTime = Time.time + 0.5f;
				try
				{
					ApplyGhostMaterial(((Component)this).gameObject);
				}
				catch (Exception arg)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)$"GhostEnforcer error en {((Object)((Component)this).gameObject).name}: {arg}");
					}
				}
			}
		}

		[CompilerGenerated]
		private sealed class <RetreatCoroutine>d__18 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Vector3 shoreDir;

			public SpawnGhostLongshipAndSkels <>4__this;

			private GameObject <boatGO>5__1;

			private Vector3 <seaDirFlat>5__2;

			private Quaternion <startRot>5__3;

			private Quaternion <targetRot>5__4;

			private float <t>5__5;

			private ZNetView <nv>5__6;

			private ZDO <zdo>5__7;

			private ZDO <zdo>5__8;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RetreatCoroutine>d__18(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<boatGO>5__1 = null;
				<nv>5__6 = null;
				<zdo>5__7 = null;
				<zdo>5__8 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Expected O, but got Unknown
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0101: Unknown result type (might be due to invalid IL or missing references)
				//IL_0191: Unknown result type (might be due to invalid IL or missing references)
				//IL_0197: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_0232: Unknown result type (might be due to invalid IL or missing references)
				//IL_0242: Unknown result type (might be due to invalid IL or missing references)
				//IL_024c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0256: Unknown result type (might be due to invalid IL or missing references)
				//IL_025b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0145: Unknown result type (might be due to invalid IL or missing references)
				//IL_014a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0151: Unknown result type (might be due to invalid IL or missing references)
				//IL_0156: Unknown result type (might be due to invalid IL or missing references)
				//IL_015b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0160: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0134: Unknown result type (might be due to invalid IL or missing references)
				ManualLogSource log2;
				Vector3 val;
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<boatGO>5__1 = FindBoatInScene();
					if ((Object)(object)<boatGO>5__1 == (Object)null)
					{
						<>2__current = (object)new WaitForSeconds(0.5f);
						<>1__state = 1;
						return true;
					}
					goto IL_007f;
				case 1:
					<>1__state = -1;
					<boatGO>5__1 = FindBoatInScene();
					goto IL_007f;
				case 2:
					<>1__state = -1;
					goto IL_01d0;
				case 3:
					{
						<>1__state = -1;
						break;
					}
					IL_007f:
					if ((Object)(object)<boatGO>5__1 == (Object)null)
					{
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogWarning((object)"RetreatCoroutine: barco no encontrado.");
						}
						return false;
					}
					log2 = Log;
					if (log2 != null)
					{
						log2.LogInfo((object)("RetreatCoroutine: moviendo '" + ((Object)<boatGO>5__1).name + "'."));
					}
					val = new Vector3(shoreDir.x, 0f, shoreDir.z);
					<seaDirFlat>5__2 = -((Vector3)(ref val)).normalized;
					if (((Vector3)(ref <seaDirFlat>5__2)).sqrMagnitude < 0.001f)
					{
						<seaDirFlat>5__2 = -<boatGO>5__1.transform.forward;
					}
					<startRot>5__3 = <boatGO>5__1.transform.rotation;
					<targetRot>5__4 = Quaternion.LookRotation(<seaDirFlat>5__2, Vector3.up);
					<t>5__5 = 0f;
					goto IL_01d0;
					IL_01d0:
					if (<t>5__5 < 5f && (Object)(object)<boatGO>5__1 != (Object)null)
					{
						<t>5__5 += Time.deltaTime;
						<boatGO>5__1.transform.rotation = Quaternion.Slerp(<startRot>5__3, <targetRot>5__4, Mathf.Clamp01(<t>5__5 / 5f));
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					if ((Object)(object)<boatGO>5__1 == (Object)null)
					{
						return false;
					}
					<t>5__5 = 0f;
					break;
				}
				if (<t>5__5 < 8f && (Object)(object)<boatGO>5__1 != (Object)null)
				{
					<t>5__5 += Time.deltaTime;
					Transform transform = <boatGO>5__1.transform;
					transform.position += <boatGO>5__1.transform.forward * 3f * Time.deltaTime;
					<>2__current = null;
					<>1__state = 3;
					return true;
				}
				if ((Object)(object)<boatGO>5__1 == (Object)null)
				{
					return false;
				}
				<nv>5__6 = <boatGO>5__1.GetComponent<ZNetView>();
				if ((Object)(object)<nv>5__6 != (Object)null && <nv>5__6.IsOwner())
				{
					<zdo>5__7 = <nv>5__6.GetZDO();
					if (<zdo>5__7 != null && ZDOMan.instance != null)
					{
						ZDOMan.instance.DestroyZDO(<zdo>5__7);
					}
					<zdo>5__7 = null;
				}
				else if ((Object)(object)<nv>5__6 != (Object)null)
				{
					<nv>5__6.ClaimOwnership();
					<zdo>5__8 = <nv>5__6.GetZDO();
					if (<zdo>5__8 != null && ZDOMan.instance != null)
					{
						ZDOMan.instance.DestroyZDO(<zdo>5__8);
					}
					<zdo>5__8 = null;
				}
				else
				{
					Object.Destroy((Object)(object)<boatGO>5__1);
				}
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogInfo((object)"RetreatCoroutine: barco destruido.");
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <RunSingleWave>d__22 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public InvasionContext ctx;

			public int waveIndex;

			public int skeletonCount;

			public int ghostCount;

			public bool includeRancid;

			public SpawnGhostLongshipAndSkels <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RunSingleWave>d__22(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c6: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					_currentWaveAlive = 0;
					BroadcastHud(showTimer: true, <>4__this._eventTimeRemaining, showTitle: true, (waveIndex == 1) ? "Los enemigos desembarcan cerca..." : "Más enemigos se acercan");
					<>4__this.SpawnSkeletonWave(ctx, skeletonCount, ghostCount, includeRancid, waveIndex);
					if (_currentWaveAlive <= 0)
					{
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogWarning((object)$"Wave {waveIndex}: no se spawneó ningún enemigo.");
						}
						return false;
					}
					break;
				case 1:
					<>1__state = -1;
					<>4__this._eventTimeRemaining -= 1f;
					BroadcastHud(<>4__this._eventTimeRemaining > 0f, <>4__this._eventTimeRemaining, showTitle: true);
					break;
				}
				if (<>4__this._eventTimeRemaining > 0f && _currentWaveAlive > 0)
				{
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				}
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"Wave {waveIndex}: finalizada.");
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <RunWaves>d__20 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public InvasionContext ctx;

			public SpawnGhostLongshipAndSkels <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RunWaves>d__20(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = <>4__this.RunSingleWave(ctx, 1, 2, 1, includeRancid: false);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (<>4__this._eventTimeRemaining <= 0f)
					{
						return false;
					}
					<>2__current = <>4__this.WaveBreak();
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = <>4__this.RunSingleWave(ctx, 2, 4, 0, includeRancid: false);
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					if (<>4__this._eventTimeRemaining <= 0f)
					{
						return false;
					}
					<>2__current = <>4__this.WaveBreak();
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					<>2__current = <>4__this.RunSingleWave(ctx, 3, 5, 2, includeRancid: false);
					<>1__state = 5;
					return true;
				case 5:
					<>1__state = -1;
					if (<>4__this._eventTimeRemaining <= 0f)
					{
						return false;
					}
					<>2__current = <>4__this.WaveBreak();
					<>1__state = 6;
					return true;
				case 6:
					<>1__state = -1;
					<>2__current = <>4__this.RunSingleWave(ctx, 4, 6, 0, includeRancid: false);
					<>1__state = 7;
					return true;
				case 7:
					<>1__state = -1;
					if (<>4__this._eventTimeRemaining <= 0f)
					{
						return false;
					}
					<>2__current = <>4__this.WaveBreak();
					<>1__state = 8;
					return true;
				case 8:
					<>1__state = -1;
					<>2__current = <>4__this.RunSingleWave(ctx, 5, 6, 2, includeRancid: true);
					<>1__state = 9;
					return true;
				case 9:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <TriggerEventFlow>d__16 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Player targetPlayer;

			public SpawnGhostLongshipAndSkels <>4__this;

			private InvasionContext <ctx>5__1;

			private GameObject <boat>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <TriggerEventFlow>d__16(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<boat>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Expected O, but got Unknown
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Expected O, but got Unknown
				//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0202: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>4__this._eventRunning = true;
					BroadcastHud(showTimer: false, 0f, showTitle: true, "El enemigo ha encontrado tu base");
					<>2__current = (object)new WaitForSeconds(10f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					BroadcastHud(showTimer: false, 0f, showTitle: true, "Los enemigos desembarcan cerca tuyo");
					<>2__current = (object)new WaitForSeconds(1.5f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					if (!<>4__this.PrepareInvasionContext(targetPlayer, out <ctx>5__1))
					{
						BroadcastHud(showTimer: false, 0f, showTitle: false, "No se pudo encontrar una orilla cercana.");
						<>4__this._eventRunning = false;
						return false;
					}
					<boat>5__2 = <>4__this.SpawnBoat(<ctx>5__1);
					<>4__this._currentBoat = <boat>5__2;
					if ((Object)(object)<boat>5__2 == (Object)null)
					{
						BroadcastHud(showTimer: false, 0f, showTitle: false, "Falló el spawn del Longship.");
						<>4__this._eventRunning = false;
						return false;
					}
					<>4__this._eventTimeRemaining = 150f;
					<>4__this._showTimer = true;
					BroadcastHud(showTimer: true, <>4__this._eventTimeRemaining, showTitle: true);
					<>2__current = <>4__this.RunWaves(<ctx>5__1);
					<>1__state = 3;
					return true;
				case 3:
				{
					<>1__state = -1;
					<>4__this._showTimer = false;
					BroadcastHud(showTimer: false, 0f, showTitle: true);
					ZRoutedRpc instance = ZRoutedRpc.instance;
					if (instance != null)
					{
						instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "Nazhi_RPC_StartRetreat", new object[1] { <ctx>5__1.ShoreDir });
					}
					<>2__current = (object)new WaitForSeconds(14f);
					<>1__state = 4;
					return true;
				}
				case 4:
				{
					<>1__state = -1;
					BroadcastHud(showTimer: false, 0f, showTitle: false);
					<>4__this._eventRunning = false;
					<>4__this._currentBoat = null;
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)"Evento finalizado.");
					}
					return false;
				}
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <VerifyWaveGhostMaterials>d__60 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public SpawnGhostLongshipAndSkels <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <VerifyWaveGhostMaterials>d__60(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Expected O, but got Unknown
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>4__this.CheckAllWaveSkeletonGhosts("[GhostFix-0.2]");
					<>2__current = (object)new WaitForSeconds(0.8f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>4__this.CheckAllWaveSkeletonGhosts("[GhostFix-1.0]");
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaveBreak>d__21 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public SpawnGhostLongshipAndSkels <>4__this;

			private float <breakRemaining>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaveBreak>d__21(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<breakRemaining>5__1 = 3f;
					break;
				case 1:
					<>1__state = -1;
					<breakRemaining>5__1 -= 1f;
					<>4__this._eventTimeRemaining -= 1f;
					BroadcastHud(showTimer: true, <>4__this._eventTimeRemaining, showTitle: true);
					break;
				}
				if (<breakRemaining>5__1 > 0f && <>4__this._eventTimeRemaining > 0f)
				{
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		internal const string BoatPrefab = "VikingShip";

		internal const string SkelPrefab = "Skeleton";

		internal const string RancidPrefab = "Skeleton_Poison";

		internal const int TotalWaves = 5;

		internal const int FirstWaveSkels = 3;

		internal const int SkelsPerWaveIncrement = 2;

		internal const float TotalEventDurationSeconds = 150f;

		internal const float BreakBetweenWaves = 3f;

		private bool _eventRunning = false;

		internal static int _currentWaveAlive;

		internal float _eventTimeRemaining = 0f;

		internal bool _showTimer = false;

		internal GameObject _currentBoat;

		internal const string RpcStartRetreat = "Nazhi_RPC_StartRetreat";

		internal static Material GhostMaterial;

		internal static bool _hudShowTimer;

		internal static float _hudTimeRemaining;

		internal static bool _hudShowTitle;

		private static GUIStyle _timerStyle;

		private static GUIStyle _titleStyle;

		private static GUIStyle _titleShadow;

		internal const string RpcEventHud = "Nazhi_RPC_EventHud";

		internal static ManualLogSource Log;

		internal static SpawnGhostLongshipAndSkels Instance;

		internal const string RpcApplyGhost = "Nazhi_RPC_ApplyGhost";

		internal const string ZdoGhostKey = "nazhi_ghost";

		private Harmony _harmony;

		public static void StartEventForTarget(Player target)
		{
			if ((Object)(object)target == (Object)null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)"StartEventForTarget: target es null.");
				}
			}
			else if ((Object)(object)Instance == (Object)null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogError((object)"StartEventForTarget: Instance es null (plugin no inicializado).");
				}
			}
			else
			{
				Instance.StartEventForTargetInternal(target);
			}
		}

		private void StartEventForTargetInternal(Player target)
		{
			if ((Object)(object)target == (Object)null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)"StartEventForTargetInternal: target es null.");
				}
				return;
			}
			if (_eventRunning)
			{
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, "La invasión ya está en curso...", 0, (Sprite)null, false);
				}
				return;
			}
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Iniciando evento de invasión para: " + target.GetPlayerName()));
			}
			((MonoBehaviour)this).StartCoroutine(TriggerEventFlow(target));
		}

		[IteratorStateMachine(typeof(<TriggerEventFlow>d__16))]
		private IEnumerator TriggerEventFlow(Player targetPlayer)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TriggerEventFlow>d__16(0)
			{
				<>4__this = this,
				targetPlayer = targetPlayer
			};
		}

		internal static void OnRpcStartRetreat(long sender, Vector3 shoreDir)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Instance == (Object)null))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"OnRpcStartRetreat: iniciando retirada local.");
				}
				((MonoBehaviour)Instance).StartCoroutine(Instance.RetreatCoroutine(shoreDir));
			}
		}

		[IteratorStateMachine(typeof(<RetreatCoroutine>d__18))]
		private IEnumerator RetreatCoroutine(Vector3 shoreDir)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RetreatCoroutine>d__18(0)
			{
				<>4__this = this,
				shoreDir = shoreDir
			};
		}

		private static GameObject FindBoatInScene()
		{
			if ((Object)(object)Instance?._currentBoat != (Object)null)
			{
				return Instance._currentBoat;
			}
			GameObject[] array = Object.FindObjectsOfType<GameObject>();
			ZNetView val2 = default(ZNetView);
			foreach (GameObject val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string name = ((Object)val).name;
				if ((name.IndexOf("VikingShip", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Longship", StringComparison.OrdinalIgnoreCase) >= 0) && val.TryGetComponent<ZNetView>(ref val2))
				{
					ZDO zDO = val2.GetZDO();
					if (zDO != null && zDO.GetBool("nazhi_ghost", false))
					{
						return val;
					}
				}
			}
			return null;
		}

		[IteratorStateMachine(typeof(<RunWaves>d__20))]
		private IEnumerator RunWaves(InvasionContext ctx)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RunWaves>d__20(0)
			{
				<>4__this = this,
				ctx = ctx
			};
		}

		[IteratorStateMachine(typeof(<WaveBreak>d__21))]
		private IEnumerator WaveBreak()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaveBreak>d__21(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<RunSingleWave>d__22))]
		private IEnumerator RunSingleWave(InvasionContext ctx, int waveIndex, int skeletonCount, int ghostCount, bool includeRancid)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RunSingleWave>d__22(0)
			{
				<>4__this = this,
				ctx = ctx,
				waveIndex = waveIndex,
				skeletonCount = skeletonCount,
				ghostCount = ghostCount,
				includeRancid = includeRancid
			};
		}

		internal static void TryCacheGhostMaterial()
		{
			if ((Object)(object)GhostMaterial != (Object)null)
			{
				return;
			}
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			GameObject prefab = instance.GetPrefab("Ghost");
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return;
			}
			SkinnedMeshRenderer componentInChildren = prefab.GetComponentInChildren<SkinnedMeshRenderer>();
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				GhostMaterial = ((Renderer)componentInChildren).material;
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"GhostMaterial cacheado.");
				}
			}
		}

		private void OnGUI()
		{
			if (_hudShowTitle)
			{
				DrawEventTitle();
			}
			if (_hudShowTimer && _hudTimeRemaining > 0f)
			{
				DrawTimer();
			}
		}

		private static void DrawEventTitle()
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (_titleStyle == null)
			{
				_titleStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 20,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)1
				};
				_titleStyle.normal.textColor = new Color(0.55f, 0.85f, 1f);
				_titleShadow = new GUIStyle(_titleStyle);
				_titleShadow.normal.textColor = new Color(0f, 0f, 0f, 0.55f);
			}
			float num = ((float)Screen.width - 340f) * 0.5f;
			GUI.Label(new Rect(num + 2f, 22f, 340f, 32f), "Invasión Espectral", _titleShadow);
			GUI.Label(new Rect(num, 20f, 340f, 32f), "Invasión Espectral", _titleStyle);
		}

		private static void DrawTimer()
		{
			//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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0054: 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)
			if (_timerStyle == null)
			{
				_timerStyle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 24,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)1
				};
				_timerStyle.normal.textColor = new Color(1f, 0.84f, 0f);
			}
			float num = ((float)Screen.width - 200f) * 0.5f;
			float num2 = (_hudShowTitle ? 54f : 20f);
			GUI.Label(new Rect(num, num2, 200f, 40f), FormatTime(_hudTimeRemaining), _timerStyle);
		}

		private static string FormatTime(float seconds)
		{
			if (seconds < 0f)
			{
				seconds = 0f;
			}
			int num = Mathf.RoundToInt(seconds);
			return $"{num / 60:00}:{num % 60:00}";
		}

		internal static void BroadcastHud(bool showTimer, float timeRemaining, bool showTitle, string centerMsg = "")
		{
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "Nazhi_RPC_EventHud", new object[4]
				{
					showTimer ? 1 : 0,
					timeRemaining,
					showTitle ? 1 : 0,
					centerMsg ?? ""
				});
			}
		}

		internal static void OnRpcEventHud(long sender, int showTimerI, float timeRemaining, int showTitleI, string centerMsg)
		{
			_hudShowTimer = showTimerI != 0;
			_hudTimeRemaining = timeRemaining;
			_hudShowTitle = showTitleI != 0;
			if (!string.IsNullOrEmpty(centerMsg))
			{
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, centerMsg, 0, (Sprite)null, false);
				}
			}
		}

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			((Component)this).gameObject.AddComponent<GhostSyncMonitor>();
			Log.LogInfo((object)"Knuckles GhostShip cargado (Main.cs)");
		}

		private static void OnRpcApplyGhost(long sender, ZDOID zdoid)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			ZDOMan instance = ZDOMan.instance;
			ZDO val = ((instance != null) ? instance.GetZDO(zdoid) : null);
			if (val == null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)$"RPC_ApplyGhost: no se encontró ZDO para ZDOID={zdoid}");
				}
				return;
			}
			ZNetView val2 = ZNetScene.instance.FindInstance(val);
			if ((Object)(object)val2 == (Object)null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)$"RPC_ApplyGhost: no se encontró ZNetView para ZDOID={zdoid}");
				}
				return;
			}
			GameObject gameObject = ((Component)val2).gameObject;
			if (!((Object)(object)gameObject == (Object)null))
			{
				TryCacheGhostMaterial();
				if (((Object)gameObject).name.IndexOf("VikingShip", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)gameObject).name.IndexOf("Longship", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					DisableWaterEffects(gameObject);
					ApplyGhostMaterial_Filtered(gameObject);
				}
				else
				{
					ApplyGhostMaterial(gameObject);
				}
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogInfo((object)$"RPC_ApplyGhost: ghost aplicado a {((Object)gameObject).name} (ZDOID={zdoid})");
				}
			}
		}

		internal static void SendGhostRpc(GameObject go)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = default(ZNetView);
			if ((Object)(object)go == (Object)null || !go.TryGetComponent<ZNetView>(ref val))
			{
				return;
			}
			ZDO zDO = val.GetZDO();
			if (zDO != null)
			{
				ZDOID uid = zDO.m_uid;
				ZRoutedRpc instance = ZRoutedRpc.instance;
				if (instance != null)
				{
					instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "Nazhi_RPC_ApplyGhost", new object[1] { uid });
				}
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)$"SendGhostRpc enviado para {((Object)go).name} (ZDOID={uid})");
				}
			}
		}

		internal static GameObject InstantiateNet(string prefabName, Vector3 pos, Quaternion rot, bool markAsGhost = false)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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)
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			GameObject prefab = instance.GetPrefab(prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(prefab, pos, rot);
			ZNetView val2 = default(ZNetView);
			if (val.TryGetComponent<ZNetView>(ref val2))
			{
				ZDO zDO = val2.GetZDO();
				if (zDO != null)
				{
					zDO.SetPosition(pos);
					zDO.SetRotation(rot);
					if (markAsGhost)
					{
						zDO.Set("nazhi_ghost", true);
					}
				}
			}
			return val;
		}

		private void Start()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			RegisterConsoleCommand();
			CacheGhostMaterialStartup();
			_harmony = new Harmony("nazhi.ghostship");
			_harmony.PatchAll(typeof(ZNetPatch));
			Log.LogInfo((object)"Harmony patch aplicado.");
		}

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

		private void RegisterConsoleCommand()
		{
			try
			{
				CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SkellyEventCommand());
				Log.LogInfo((object)"Comando 'skellyevent' registrado.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Error registrando comando 'skellyevent': {arg}");
			}
		}

		private void CacheGhostMaterialStartup()
		{
			try
			{
				TryCacheGhostMaterial();
				Log.LogInfo((object)"GhostMaterial cacheado en Startup.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Error cacheando GhostMaterial: {arg}");
			}
		}

		internal static void RegisterAllRpcs()
		{
			if (ZRoutedRpc.instance == null)
			{
				Log.LogWarning((object)"RegisterAllRpcs: ZRoutedRpc.instance sigue null.");
				return;
			}
			try
			{
				ZRoutedRpc.instance.Register<ZDOID>("Nazhi_RPC_ApplyGhost", (Action<long, ZDOID>)OnRpcApplyGhost);
			}
			catch
			{
			}
			try
			{
				ZRoutedRpc.instance.Register<int, float, int, string>("Nazhi_RPC_EventHud", (Method<int, float, int, string>)OnRpcEventHud);
			}
			catch
			{
			}
			try
			{
				ZRoutedRpc.instance.Register<Vector3>("Nazhi_RPC_StartRetreat", (Action<long, Vector3>)OnRpcStartRetreat);
			}
			catch
			{
			}
			Log.LogInfo((object)"RPCs registrados correctamente.");
		}

		private bool PrepareInvasionContext(Player target, out InvasionContext ctx)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: 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)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			ctx = default(InvasionContext);
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)"PrepareInvasionContext: ZNetScene.instance es null.");
				}
				return false;
			}
			if ((Object)(object)instance.GetPrefab("VikingShip") == (Object)null || (Object)(object)instance.GetPrefab("Skeleton") == (Object)null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogError((object)"PrepareInvasionContext: prefabs no encontrados Boat=VikingShip, Skel=Skeleton");
				}
				return false;
			}
			if ((Object)(object)target == (Object)null)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogError((object)"PrepareInvasionContext: target es null.");
				}
				return false;
			}
			Vector3 position = ((Component)target).transform.position;
			if (!FindNearestShore(position, 80f, out var shorePoint, out var waterPoint, out var shoreDir))
			{
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogWarning((object)("PrepareInvasionContext: no se encontró orilla (<= 80m) para " + target.GetPlayerName() + "."));
				}
				return false;
			}
			float waterLevel = GetWaterLevel();
			Vector3 val = -((Vector3)(ref shoreDir)).normalized;
			Vector3 start = waterPoint + val * 8f;
			Vector3 val2 = PushToDeeperWater(start, shoreDir, 3f, 15f, 1.5f);
			Vector3 boatPos = val2;
			boatPos.y = waterLevel + 0.25f;
			Vector3 val3 = new Vector3(shoreDir.x, 0f, shoreDir.z);
			Vector3 val4 = ((Vector3)(ref val3)).normalized;
			if (((Vector3)(ref val4)).sqrMagnitude < 0.001f)
			{
				val4 = Vector3.forward;
			}
			Quaternion boatRot = Quaternion.LookRotation(val4, Vector3.up);
			ctx = new InvasionContext
			{
				ShorePoint = shorePoint,
				WaterPoint = waterPoint,
				ShoreDir = shoreDir,
				WaterLevel = waterLevel,
				BoatPos = boatPos,
				BoatRot = boatRot
			};
			ManualLogSource log5 = Log;
			if (log5 != null)
			{
				log5.LogInfo((object)$"PrepareInvasionContext OK para {target.GetPlayerName()} en {position}.");
			}
			return true;
		}

		private GameObject SpawnBoat(InvasionContext ctx)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = InstantiateNet("VikingShip", ctx.BoatPos, ctx.BoatRot, markAsGhost: true);
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)"SpawnBoat: falló InstantiateNet del Longship.");
				}
				return null;
			}
			val.AddComponent<BoatGodMode>();
			DisableWaterEffects(val);
			ApplyGhostMaterial_Filtered(val);
			SendGhostRpc(val);
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"SpawnBoat: Longship ghost inmortal spawneado correctamente.");
			}
			return val;
		}

		private void SpawnSkeletonWave(InvasionContext ctx, int skeletonCount, int ghostCount, bool includeRancid, int waveIndex)
		{
			//IL_0020: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_0084: 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_00c4: 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_00ce: 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)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: 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)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Vector3 normalized = ((Vector3)(ref ctx.ShoreDir)).normalized;
			Vector3 val = Vector3.Cross(Vector3.up, normalized);
			Vector3 normalized2 = ((Vector3)(ref val)).normalized;
			Vector3 val2 = ctx.ShorePoint + normalized * 2.5f;
			int num = 0;
			for (int i = 0; i < skeletonCount; i++)
			{
				float num2 = (float)i - (float)(skeletonCount - 1) * 0.5f;
				Vector3 xz = val2 + normalized2 * (num2 * 3f);
				if (!PlaceOnGround(xz, out var placed))
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)$"Wave {waveIndex}: no se encontró suelo para un skeleton.");
					}
					continue;
				}
				Quaternion rot = Quaternion.LookRotation(-ctx.ShoreDir, Vector3.up);
				GameObject val3 = InstantiateNet("Skeleton", placed, rot, markAsGhost: true);
				if ((Object)(object)val3 != (Object)null)
				{
					Character component = val3.GetComponent<Character>();
					if (component != null)
					{
						component.m_level = Mathf.Max(1, waveIndex);
					}
					ApplyGhostMaterial(val3);
					val3.AddComponent<GhostEnforcer>();
					AggroNearestPlayer(val3);
					val3.AddComponent<WaveSkeleton>();
					SendGhostRpc(val3);
					_currentWaveAlive++;
					num++;
				}
			}
			for (int j = 0; j < ghostCount; j++)
			{
				float num3 = (float)j - (float)(ghostCount - 1) * 0.5f;
				Vector3 xz2 = val2 + normalized2 * (num3 * 3f * 0.7f);
				if (!PlaceOnGround(xz2, out var placed2))
				{
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogWarning((object)$"Wave {waveIndex}: no se encontró suelo para un Ghost.");
					}
					continue;
				}
				Quaternion rot2 = Quaternion.LookRotation(-ctx.ShoreDir, Vector3.up);
				GameObject val4 = InstantiateNet("Ghost", placed2, rot2);
				if ((Object)(object)val4 != (Object)null)
				{
					Character component2 = val4.GetComponent<Character>();
					if (component2 != null)
					{
						component2.m_level = Mathf.Max(1, waveIndex);
					}
					AggroNearestPlayer(val4);
					val4.AddComponent<WaveSkeleton>();
					_currentWaveAlive++;
					num++;
				}
			}
			if (includeRancid)
			{
				GameObject prefab = instance.GetPrefab("Skeleton_Poison");
				if ((Object)(object)prefab != (Object)null)
				{
					Vector3 xz3 = val2;
					if (PlaceOnGround(xz3, out var placed3))
					{
						Quaternion rot3 = Quaternion.LookRotation(-ctx.ShoreDir, Vector3.up);
						GameObject val5 = InstantiateNet("Skeleton_Poison", placed3, rot3, markAsGhost: true);
						if ((Object)(object)val5 != (Object)null)
						{
							Character component3 = val5.GetComponent<Character>();
							if (component3 != null)
							{
								component3.m_level = Mathf.Max(1, waveIndex + 1);
							}
							ApplyGhostMaterial(val5);
							val5.AddComponent<GhostEnforcer>();
							AggroNearestPlayer(val5);
							val5.AddComponent<WaveSkeleton>();
							SendGhostRpc(val5);
							_currentWaveAlive++;
							num++;
							ManualLogSource log3 = Log;
							if (log3 != null)
							{
								log3.LogInfo((object)"Wave final: Rancid Remains añadido.");
							}
						}
					}
				}
				else
				{
					ManualLogSource log4 = Log;
					if (log4 != null)
					{
						log4.LogWarning((object)"SpawnSkeletonWave: prefab RancidPrefab no encontrado.");
					}
				}
			}
			ManualLogSource log5 = Log;
			if (log5 != null)
			{
				log5.LogInfo((object)$"Wave {waveIndex}: {num} enemigos generados.");
			}
			((MonoBehaviour)this).StartCoroutine(VerifyWaveGhostMaterials());
		}

		[IteratorStateMachine(typeof(<VerifyWaveGhostMaterials>d__60))]
		private IEnumerator VerifyWaveGhostMaterials()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <VerifyWaveGhostMaterials>d__60(0)
			{
				<>4__this = this
			};
		}

		private void CheckAllWaveSkeletonGhosts(string tag)
		{
			WaveSkeleton[] array = Object.FindObjectsOfType<WaveSkeleton>();
			WaveSkeleton[] array2 = array;
			foreach (WaveSkeleton waveSkeleton in array2)
			{
				GameObject gameObject = ((Component)waveSkeleton).gameObject;
				if (!((Object)(object)gameObject == (Object)null) && ((Object)gameObject).name.IndexOf("Ghost", StringComparison.OrdinalIgnoreCase) < 0)
				{
					ApplyGhostMaterial(gameObject);
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)(tag + " Enemy forzado a ghost. Obj=" + ((Object)gameObject).name));
					}
				}
			}
		}

		private static bool FindNearestShore(Vector3 origin, float maxRadius, out Vector3 shorePoint, out Vector3 waterPoint, out Vector3 shoreDir)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_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_0092: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (shoreDir = Vector3.zero);
			val = (shorePoint = (waterPoint = val));
			float waterLevel = GetWaterLevel();
			float num = waterLevel - 0.3f;
			float num2 = float.MaxValue;
			bool result = false;
			Vector3 val2 = default(Vector3);
			for (int i = 0; i < 36; i++)
			{
				float num3 = (float)Math.PI * 2f * ((float)i / 36f);
				((Vector3)(ref val2))..ctor(Mathf.Cos(num3), 0f, Mathf.Sin(num3));
				bool flag = false;
				bool flag2 = false;
				Vector3 val3 = origin;
				for (float num4 = 1f; num4 <= maxRadius; num4 += 1f)
				{
					Vector3 val4 = origin + val2 * num4;
					if (!TryGetGroundHeight(val4, out var height))
					{
						continue;
					}
					bool flag3 = height >= num;
					if (!flag2)
					{
						flag2 = true;
						flag = flag3;
						val3 = val4;
						continue;
					}
					if (flag3 != flag)
					{
						Vector3 val5 = val3;
						Vector3 val6 = val4;
						for (int j = 0; j < 10; j++)
						{
							Vector3 val7 = (val5 + val6) * 0.5f;
							TryGetGroundHeight(val7, out var height2);
							bool flag4 = height2 >= num;
							if (flag4 == flag)
							{
								val5 = val7;
							}
							else
							{
								val6 = val7;
							}
						}
						Vector3 val8 = (flag ? val5 : val6);
						Vector3 val9 = (flag ? val6 : val5);
						float num5 = Vector3.Distance(origin, val8);
						if (num5 < num2)
						{
							num2 = num5;
							shorePoint = val8;
							waterPoint = val9;
							val = val8 - val9;
							shoreDir = ((Vector3)(ref val)).normalized;
							result = true;
						}
						break;
					}
					flag = flag3;
					val3 = val4;
				}
			}
			return result;
		}

		private static bool TryGetGroundHeight(Vector3 pos, out float height)
		{
			//IL_0045: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			height = 0f;
			if ((Object)(object)ZoneSystem.instance != (Object)null)
			{
				try
				{
					float num = default(float);
					if (ZoneSystem.instance.GetSolidHeight(pos, ref num, 1000))
					{
						height = num;
						return true;
					}
				}
				catch
				{
				}
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(pos.x, 2000f, pos.z);
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(val, Vector3.down, ref val2, 5000f, -1, (QueryTriggerInteraction)1))
			{
				height = ((RaycastHit)(ref val2)).point.y;
				return true;
			}
			return false;
		}

		private static float GetHeightSafe(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			float height;
			return TryGetGroundHeight(pos, out height) ? height : GetWaterLevel();
		}

		private static float GetWaterLevel()
		{
			return ((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f;
		}

		private static float GetDepthAt(Vector3 pos)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			float waterLevel = GetWaterLevel();
			float heightSafe = GetHeightSafe(pos);
			return waterLevel - heightSafe;
		}

		private static Vector3 PushToDeeperWater(Vector3 start, Vector3 shoreDir, float minDepth, float maxPush, float step)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//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_0029: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = -((Vector3)(ref shoreDir)).normalized;
			Vector3 val2 = start;
			for (float num = 0f; num <= maxPush; num += step)
			{
				if (GetDepthAt(val2) >= minDepth)
				{
					return val2;
				}
				val2 += val * step;
			}
			return start;
		}

		private static bool PlaceOnGround(Vector3 xz, out Vector3 placed)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			placed = xz;
			if (TryGetGroundHeight(xz, out var height))
			{
				placed.y = height;
				return true;
			}
			return false;
		}

		internal static void ApplyGhostMaterial(GameObject go)
		{
			if ((Object)(object)GhostMaterial == (Object)null)
			{
				TryCacheGhostMaterial();
				if ((Object)(object)GhostMaterial == (Object)null)
				{
					return;
				}
			}
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				val.material = GhostMaterial;
			}
		}

		internal static void ApplyGhostOverlay(GameObject go)
		{
			if ((Object)(object)GhostMaterial == (Object)null)
			{
				TryCacheGhostMaterial();
				if ((Object)(object)GhostMaterial == (Object)null)
				{
					return;
				}
			}
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] materials = val.materials;
				Material[] array = (Material[])(object)new Material[materials.Length + 1];
				for (int j = 0; j < materials.Length; j++)
				{
					array[j] = materials[j];
				}
				array[materials.Length] = GhostMaterial;
				val.materials = array;
			}
		}

		internal static void ApplyGhostMaterial_Filtered(GameObject go)
		{
			if ((Object)(object)GhostMaterial == (Object)null)
			{
				TryCacheGhostMaterial();
				if ((Object)(object)GhostMaterial == (Object)null)
				{
					return;
				}
			}
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant();
				if (!text.Contains("watereffects") && !text.Contains("watermask"))
				{
					val.material = GhostMaterial;
				}
			}
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Ghost aplicado al Longship (filtrado).");
			}
		}

		internal static void DisableWaterEffects(GameObject boat)
		{
			try
			{
				Transform val = FindChildRecursiveByNameContains(boat.transform, "watereffects");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(false);
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)"watereffects desactivados en el Longship.");
					}
				}
				else
				{
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogWarning((object)"watereffects no encontrados en el Longship.");
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogError((object)$"DisableWaterEffects error: {arg}");
				}
			}
		}

		private static Transform FindChildRecursiveByNameContains(Transform root, string substring)
		{
			if ((Object)(object)root == (Object)null || substring == null)
			{
				return null;
			}
			string value = substring.ToLowerInvariant();
			if (((Object)root).name != null && ((Object)root).name.ToLowerInvariant().Contains(value))
			{
				return root;
			}
			for (int i = 0; i < root.childCount; i++)
			{
				Transform val = FindChildRecursiveByNameContains(root.GetChild(i), substring);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		internal static void AggroNearestPlayer(GameObject skel)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Character component = skel.GetComponent<Character>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				Player closestPlayer = Player.GetClosestPlayer(skel.transform.position, 60f);
				if ((Object)(object)closestPlayer == (Object)null)
				{
					return;
				}
				MonsterAI component2 = skel.GetComponent<MonsterAI>();
				if ((Object)(object)component2 != (Object)null)
				{
					((BaseAI)component2).m_alerted = true;
					((BaseAI)component2).SetHuntPlayer(true);
					component2.SetTarget((Character)(object)closestPlayer);
					((BaseAI)component2).SetAggravated(true, (AggravatedReason)0);
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)("Aggro → " + closestPlayer.GetPlayerName() + " (MonsterAI)"));
					}
					return;
				}
				BaseAI component3 = skel.GetComponent<BaseAI>();
				if ((Object)(object)component3 != (Object)null)
				{
					component3.m_alerted = true;
					component3.SetHuntPlayer(true);
					component3.SetAggravated(true, (AggravatedReason)0);
					component3.Alert();
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogInfo((object)("Aggro → " + closestPlayer.GetPlayerName() + " (BaseAI fallback)"));
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogError((object)$"AggroNearestPlayer error: {arg}");
				}
			}
		}
	}
	public class GhostSyncMonitor : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <ScanLoop>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public GhostSyncMonitor <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ScanLoop>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					if (!((Object)(object)ZNetScene.instance == (Object)null))
					{
						SpawnGhostLongshipAndSkels.TryCacheGhostMaterial();
						if (!((Object)(object)SpawnGhostLongshipAndSkels.GhostMaterial == (Object)null))
						{
							<>4__this.ScanAllNetViews();
						}
					}
					break;
				}
				<>2__current = (object)new WaitForSeconds(1.5f);
				<>1__state = 1;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const float ScanInterval = 1.5f;

		private readonly HashSet<ZDOID> _processed = new HashSet<ZDOID>();

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(ScanLoop());
		}

		[IteratorStateMachine(typeof(<ScanLoop>d__3))]
		private IEnumerator ScanLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ScanLoop>d__3(0)
			{
				<>4__this = this
			};
		}

		private void ScanAllNetViews()
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			ZNetView[] array = Object.FindObjectsOfType<ZNetView>();
			foreach (ZNetView val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				ZDO zDO = val.GetZDO();
				if (zDO == null || !zDO.GetBool("nazhi_ghost", false))
				{
					continue;
				}
				GameObject gameObject = ((Component)val).gameObject;
				if ((Object)(object)gameObject == (Object)null)
				{
					continue;
				}
				if (((Object)gameObject).name.IndexOf("VikingShip", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)gameObject).name.IndexOf("Longship", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					SpawnGhostLongshipAndSkels.DisableWaterEffects(gameObject);
					SpawnGhostLongshipAndSkels.ApplyGhostMaterial_Filtered(gameObject);
				}
				else
				{
					SpawnGhostLongshipAndSkels.ApplyGhostMaterial(gameObject);
				}
				ZDOID uid = zDO.m_uid;
				if (_processed.Add(uid))
				{
					ManualLogSource log = SpawnGhostLongshipAndSkels.Log;
					if (log != null)
					{
						log.LogInfo((object)$"GhostSyncMonitor: ghost aplicado a {((Object)gameObject).name} (ZDOID={uid})");
					}
				}
			}
		}
	}
}

HideTempleITems.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AichoGuardian")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AichoGuardian")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("D28110A9-E229-4700-AD4D-DCD37486A82B")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace HideTMPieces;

[BepInPlugin("com.yourname.hidetmpieces", "HideTMPieces", "1.0.0")]
public class HideTMPiecesPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "com.yourname.hidetmpieces";

	public const string PluginName = "HideTMPieces";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Log;

	private readonly Harmony _harmony = new Harmony("com.yourname.hidetmpieces");

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		_harmony.PatchAll();
		Log.LogInfo((object)"HideTMPieces v1.0.0 cargado — ocultando piezas _TM del martillo.");
	}

	private void OnDestroy()
	{
		_harmony.UnpatchSelf();
	}
}
[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
public static class PieceTable_UpdateAvailable_Patch
{
	private static void Postfix(PieceTable __instance)
	{
		if (__instance.m_availablePieces == null)
		{
			return;
		}
		int num = 0;
		foreach (List<Piece> availablePiece in __instance.m_availablePieces)
		{
			int count = availablePiece.Count;
			availablePiece.RemoveAll((Piece p) => (Object)(object)p != (Object)null && IsTMPiece(p));
			num += count - availablePiece.Count;
		}
		if (num > 0)
		{
			HideTMPiecesPlugin.Log.LogDebug((object)$"[UpdateAvailable] Ocultadas {num} pieza(s) _TM.");
		}
	}

	private static bool IsTMPiece(Piece piece)
	{
		if ((Object)(object)((Component)piece).gameObject == (Object)null)
		{
			return false;
		}
		string prefabName = Utils.GetPrefabName(((Component)piece).gameObject);
		return prefabName.EndsWith("_TM", StringComparison.OrdinalIgnoreCase);
	}
}