Decompiled source of GatheringTorch v0.3.3

plugins/GatheringTorch.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GatheringTorch.AI;
using GatheringTorch.Items;
using GatheringTorch.Skills;
using GatheringTorch.Summons;
using GatheringTorch.UI;
using GatheringTorch.Util;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("GatheringTorch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GatheringTorch")]
[assembly: AssemblyTitle("GatheringTorch")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GatheringTorch
{
	[BepInPlugin("yoon.valheim.gatheringtorch", "Gathering Torch", "0.3.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "yoon.valheim.gatheringtorch";

		public const string ModName = "Gathering Torch";

		public const string ModVersion = "0.3.3";

		internal static ConfigEntry<KeyCode> MiningKey;

		internal static ConfigEntry<KeyCode> WoodKey;

		internal static ConfigEntry<KeyCode> CombatKey;

		internal static ConfigEntry<float> WorkRadius;

		internal static ConfigEntry<float> WorkDuration;

		internal static ConfigEntry<float> CombatDuration;

		internal static ConfigEntry<float> Cooldown;

		internal static ConfigEntry<float> WorkDamage;

		internal static ConfigEntry<int> GoblinLevel;

		internal static ConfigEntry<int> CombatGoblinCount;

		internal static ButtonConfig MiningButton;

		internal static ButtonConfig WoodButton;

		internal static ButtonConfig CombatButton;

		private Harmony _harmony;

		private SkillController _skills;

		private SkillHud _hud;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			RegisterInputs();
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
			_harmony = new Harmony("yoon.valheim.gatheringtorch");
			_harmony.PatchAll();
			_skills = ((Component)this).gameObject.AddComponent<SkillController>();
			_hud = ((Component)this).gameObject.AddComponent<SkillHud>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Gathering Torch 0.3.3 loaded");
		}

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

		private void OnVanillaPrefabsAvailable()
		{
			try
			{
				GatheringTorchItems.Register();
				DumpSummonFxPrefabs();
				DumpMonsterDeathEffects();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Gathering Torch items registered after vanilla prefabs became available.");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to register Gathering Torch items: {arg}");
			}
			finally
			{
				PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			}
		}

		private void DumpSummonFxPrefabs()
		{
			try
			{
				if (!(typeof(PrefabManager).GetField("Prefabs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(PrefabManager.Instance) is IDictionary dictionary))
				{
					return;
				}
				foreach (DictionaryEntry item in dictionary)
				{
					string text = item.Key?.ToString() ?? "";
					string text2 = text.ToLowerInvariant();
					if ((text2.Contains("skeleton") || text2.Contains("troll")) && (text2.Contains("vfx") || text2.Contains("sfx") || text2.Contains("death") || text2.Contains("ragdoll")))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[GT-FX] " + text));
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[GT-FX] dump failed: " + ex.Message));
			}
		}

		private void DumpMonsterDeathEffects()
		{
			string[] array = new string[2] { "Skeleton", "Troll" };
			foreach (string text in array)
			{
				try
				{
					GameObject prefab = PrefabManager.Instance.GetPrefab(text);
					if ((Object)(object)prefab == (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("[GT-DEATHFX] prefab missing: " + text));
						continue;
					}
					Character component = prefab.GetComponent<Character>();
					if ((Object)(object)component == (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("[GT-DEATHFX] Character missing: " + text));
						continue;
					}
					FieldInfo[] fields = typeof(Character).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (FieldInfo fieldInfo in fields)
					{
						string text2 = fieldInfo.Name.ToLowerInvariant();
						if (text2.Contains("death") || text2.Contains("effect"))
						{
							object value = fieldInfo.GetValue(component);
							if (value != null)
							{
								((BaseUnityPlugin)this).Logger.LogInfo((object)("[GT-DEATHFX] " + text + " | " + fieldInfo.Name + " = " + value));
							}
						}
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[GT-DEATHFX] " + text + " failed: " + ex.Message));
				}
			}
		}

		private void BindConfig()
		{
			MiningKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "Mining skill", (KeyCode)120, "채광 고블린 작업반");
			WoodKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "Woodcut skill", (KeyCode)122, "벌목 고블린 작업반");
			CombatKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "Combat skill", (KeyCode)99, "전투 고블린 10마리");
			WorkRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "Work radius", 100f, "사용 지점 기준 작업 반경(m)");
			WorkDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "Worker duration", 45f, "채광/벌목/채집 고블린 지속시간(초)");
			CombatDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "Combat duration", 30f, "전투 고블린 지속시간(초)");
			Cooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "Skill cooldown", 60f, "X/Z/C 각각의 독립 쿨타임(초)");
			WorkDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "Worker damage", 200f, "벌목 Chop / 채광 Pickaxe 피해량");
			GoblinLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Balance", "Goblin level", 16, "15성 = 기본값 16 (0성이 level 1)");
			CombatGoblinCount = ((BaseUnityPlugin)this).Config.Bind<int>("Balance", "Combat goblins", 10, "C 스킬 소환 수");
		}

		private void RegisterInputs()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_002b: Expected O, but got Unknown
			//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_003b: 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_0056: Expected O, but got Unknown
			//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_0066: 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_0081: Expected O, but got Unknown
			MiningButton = new ButtonConfig
			{
				Name = "GT_Mining",
				Config = MiningKey,
				Hint = "채광 고블린"
			};
			WoodButton = new ButtonConfig
			{
				Name = "GT_Woodcut",
				Config = WoodKey,
				Hint = "벌목 고블린"
			};
			CombatButton = new ButtonConfig
			{
				Name = "GT_Combat",
				Config = CombatKey,
				Hint = "전투 고블린"
			};
			InputManager.Instance.AddButton("yoon.valheim.gatheringtorch", MiningButton);
			InputManager.Instance.AddButton("yoon.valheim.gatheringtorch", WoodButton);
			InputManager.Instance.AddButton("yoon.valheim.gatheringtorch", CombatButton);
		}
	}
}
namespace GatheringTorch.Util
{
	internal static class PlayerItemUtil
	{
		private static readonly MethodInfo GetRightItemMethod = typeof(Humanoid).GetMethod("GetRightItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static ItemData GetRightItem(Player player)
		{
			if ((Object)(object)player == (Object)null || GetRightItemMethod == null)
			{
				return null;
			}
			try
			{
				object? obj = GetRightItemMethod.Invoke(player, null);
				return (ItemData)((obj is ItemData) ? obj : null);
			}
			catch
			{
				return null;
			}
		}
	}
}
namespace GatheringTorch.UI
{
	internal sealed class SkillHud : MonoBehaviour
	{
		private Texture2D _troll;

		private Texture2D _skeleton;

		private GUIStyle _label;

		private GUIStyle _key;

		private GUIStyle _cooldown;

		private GUIStyle _stateOn;

		private GUIStyle _stateOff;

		private GUIStyle _count;

		private static readonly Rect FlippedTexCoords = new Rect(0f, 1f, 1f, -1f);

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

		private void OnGUI()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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)
			Player localPlayer = Player.m_localPlayer;
			SkillController instance = SkillController.Instance;
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)instance == (Object)null) && instance.HasSummonStaff)
			{
				int equippedTier = instance.EquippedTier;
				EnsureIcons();
				EnsureStyles();
				float num = 176f;
				float num2 = ((float)Screen.width - num) * 0.5f;
				float num3 = (float)Screen.height - 195f;
				DrawSkill(new Rect(num2, num3, 78f, 78f), (Texture)(object)_troll, "Z", "트롤 소환", instance.RemainingTroll, instance.TrollUiOn, instance.CurrentTrolls, instance.MaxTrolls);
				DrawSkill(new Rect(num2 + 78f + 20f, num3, 78f, 78f), (Texture)(object)_skeleton, "C", "해골 소환", instance.RemainingSkeleton, instance.SkeletonUiOn, instance.CurrentSkeletons, instance.MaxSkeletons);
				GUI.Label(new Rect(num2, num3 + 78f + 25f, num, 25f), $"고블린 지팡이 {equippedTier}단계", _label);
			}
		}

		private void DrawSkill(Rect r, Texture icon, string key, string name, float cd, bool ready, int current, int max)
		{
			//IL_0000: 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_0010: 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_0029: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0133: 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_01b2: 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_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			GUI.Box(r, GUIContent.none);
			Color color = GUI.color;
			GUI.color = (Color)(ready ? Color.white : new Color(0.38f, 0.38f, 0.38f, 0.85f));
			if ((Object)(object)icon != (Object)null)
			{
				GUI.DrawTextureWithTexCoords(new Rect(((Rect)(ref r)).x + 3f, ((Rect)(ref r)).y + 3f, ((Rect)(ref r)).width - 6f, ((Rect)(ref r)).height - 6f), icon, FlippedTexCoords, true);
			}
			GUI.color = color;
			GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y - 21f, ((Rect)(ref r)).width, 19f), key, _key);
			GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + 5f, ((Rect)(ref r)).width, 24f), ready ? "ON" : "OFF", ready ? _stateOn : _stateOff);
			GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + ((Rect)(ref r)).height - 28f, ((Rect)(ref r)).width, 23f), $"{current} / {max}", _count);
			GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + ((Rect)(ref r)).height + 3f, ((Rect)(ref r)).width, 18f), name, _label);
			if (cd > 0f)
			{
				GUI.color = new Color(0f, 0f, 0f, 0.42f);
				GUI.DrawTexture(r, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color;
				GUI.Label(r, Mathf.CeilToInt(cd).ToString(), _cooldown);
			}
		}

		private void EnsureIcons()
		{
			if ((Object)(object)_troll == (Object)null)
			{
				_troll = LoadEmbeddedRgba("GatheringTorch.Resources.woodcutting.rgba");
			}
			if ((Object)(object)_skeleton == (Object)null)
			{
				_skeleton = LoadEmbeddedRgba("GatheringTorch.Resources.combat.rgba");
			}
		}

		private static Texture2D LoadEmbeddedRgba(string resourceName)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num <= 0)
				{
					break;
				}
			}
			if (array.Length != 262144)
			{
				return null;
			}
			Texture2D val = new Texture2D(256, 256, (TextureFormat)4, false)
			{
				name = resourceName,
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			val.LoadRawTextureData(array);
			val.Apply(false, false);
			return val;
		}

		private void EnsureStyles()
		{
			//IL_0014: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_003f: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0069: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_008d: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00c2: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_010b: 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_0121: 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_0135: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			if (_label == null)
			{
				_label = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = 14,
					fontStyle = (FontStyle)1
				};
				_label.normal.textColor = Color.white;
				_key = new GUIStyle(_label)
				{
					fontSize = 15
				};
				_cooldown = new GUIStyle(_label)
				{
					fontSize = 30,
					fontStyle = (FontStyle)1
				};
				_cooldown.normal.textColor = Color.white;
				_stateOn = new GUIStyle(_label)
				{
					fontSize = 20,
					fontStyle = (FontStyle)1
				};
				_stateOn.normal.textColor = Color.white;
				_stateOff = new GUIStyle(_label)
				{
					fontSize = 15,
					fontStyle = (FontStyle)1
				};
				_stateOff.normal.textColor = new Color(0.68f, 0.68f, 0.68f, 1f);
				_count = new GUIStyle(_label)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1
				};
				_count.normal.textColor = Color.white;
			}
		}
	}
}
namespace GatheringTorch.Summons
{
	internal sealed class SummonedGoblin : MonoBehaviour
	{
		private ZNetView _nview;

		internal long OwnerPlayerId { get; private set; }

		internal Vector3 WorkCenter { get; private set; }

		internal WorkerRole Role { get; private set; }

		internal float ExpiresAt { get; private set; }

		internal void Initialize(long ownerId, Vector3 center, WorkerRole role, float duration)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			OwnerPlayerId = ownerId;
			WorkCenter = center;
			Role = role;
			ExpiresAt = Time.time + duration;
			_nview = ((Component)this).GetComponent<ZNetView>();
		}

		private void Update()
		{
			if (!(Time.time < ExpiresAt) && ((Object)(object)_nview == (Object)null || !_nview.IsValid() || _nview.IsOwner()))
			{
				ZNetScene instance = ZNetScene.instance;
				if (instance != null)
				{
					instance.Destroy(((Component)this).gameObject);
				}
			}
		}

		internal Player FindOwner()
		{
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer != (Object)null && allPlayer.GetPlayerID() == OwnerPlayerId)
				{
					return allPlayer;
				}
			}
			return null;
		}

		internal bool InWorkArea(Vector3 point)
		{
			//IL_0000: 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_0011: 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_0029: 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)
			Vector3 val = new Vector3(point.x, 0f, point.z);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(WorkCenter.x, 0f, WorkCenter.z);
			return Vector3.Distance(val, val2) <= Plugin.WorkRadius.Value;
		}
	}
	internal sealed class SummonedSkeleton : MonoBehaviour
	{
		internal long OwnerPlayerId { get; private set; }

		internal int StaffTier { get; private set; }

		internal bool Ranged { get; private set; }

		internal void Initialize(long ownerId, int staffTier, bool ranged)
		{
			OwnerPlayerId = ownerId;
			StaffTier = staffTier;
			Ranged = ranged;
		}

		internal Player FindOwner()
		{
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer != (Object)null && allPlayer.GetPlayerID() == OwnerPlayerId)
				{
					return allPlayer;
				}
			}
			return null;
		}
	}
	internal static class SummonEffects
	{
		internal static void PlayTroll(Vector3 pos)
		{
			//IL_0000: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			CreateBurst(pos, new Color(1f, 0.2f, 0.05f, 1f), new Color(0.55f, 0.05f, 0.02f, 0f), 55, 1.15f, 5.5f, 0.25f, 0.85f);
		}

		internal static void PlaySkeleton(Vector3 pos)
		{
			//IL_0000: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			CreateBurst(pos, new Color(0.15f, 1f, 0.28f, 1f), new Color(0.35f, 0.05f, 0.65f, 0f), 42, 1f, 4f, 0.18f, 0.65f);
		}

		internal static void PlayDismiss(Vector3 pos)
		{
			//IL_0000: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			CreateBurst(pos, new Color(0.15f, 0.85f, 0.25f, 1f), new Color(0.08f, 0.02f, 0.12f, 0f), 25, 0.75f, 2.8f, 0.15f, 0.5f);
		}

		private static void CreateBurst(Vector3 pos, Color start, Color end, int count, float lifetime, float speed, float minSize, float maxSize)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0011: 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_001c: 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_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_0059: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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)
			//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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_00f8: 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_0114: 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)
			//IL_0125: Expected O, but got Unknown
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: 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_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_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: 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_020e: 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_0200: Expected O, but got Unknown
			GameObject val = new GameObject("GT_SummonFX");
			val.transform.position = pos + Vector3.up * 0.35f;
			ParticleSystem val2 = val.AddComponent<ParticleSystem>();
			MainModule main = val2.main;
			((MainModule)(ref main)).duration = 0.25f;
			((MainModule)(ref main)).loop = false;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(lifetime * 0.65f, lifetime);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(speed * 0.45f, speed);
			((MainModule)(ref main)).startSize = new MinMaxCurve(minSize, maxSize);
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(start);
			((MainModule)(ref main)).maxParticles = count + 10;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(-0.1f);
			EmissionModule emission = val2.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f);
			((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1]
			{
				new Burst(0f, (short)count)
			});
			ShapeModule shape = val2.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)2;
			((ShapeModule)(ref shape)).radius = 0.75f;
			ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val3 = new Gradient();
			val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[3]
			{
				new GradientColorKey(start, 0f),
				new GradientColorKey(start, 0.3f),
				new GradientColorKey(end, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[3]
			{
				new GradientAlphaKey(1f, 0f),
				new GradientAlphaKey(0.85f, 0.45f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val3);
			ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
			Shader val4 = Shader.Find("Particles/Standard Unlit");
			if ((Object)(object)val4 == (Object)null)
			{
				val4 = Shader.Find("Legacy Shaders/Particles/Additive");
			}
			if ((Object)(object)val4 != (Object)null)
			{
				((Renderer)component).material = new Material(val4);
			}
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.color = start;
			obj.range = 5f;
			obj.intensity = 2.2f;
			val2.Play();
			Object.Destroy((Object)(object)obj, 0.18f);
			Object.Destroy((Object)(object)val, lifetime + 0.5f);
		}
	}
	internal static class SummonManager
	{
		private const string TrollPrefab = "Troll";

		private const string SkeletonPrefab = "Skeleton";

		private static void PlayDeathEffect(GameObject prefab, Vector3 pos, Quaternion rot)
		{
			//IL_0022: 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)
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			Character component = prefab.GetComponent<Character>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			try
			{
				component.m_deathEffects.Create(pos, rot, (Transform)null, 1f, -1);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[GT-FX] death effect failed: " + ex.Message));
				}
			}
		}

		internal static bool CastCombatGroup(Player owner, Vector3 center, int count)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			for (int i = 0; i < count; i++)
			{
				flag |= (Object)(object)SpawnTroll(owner, center, i, 1, 1) != (Object)null;
			}
			return flag;
		}

		internal static GameObject SpawnTroll(Player owner, Vector3 center, int index, int staffTier, int quality)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0079: 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_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)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("Troll");
			if ((Object)(object)prefab == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)"Troll prefab not found.");
				}
				return null;
			}
			float num = (float)index * 47.5f + Random.Range(-15f, 15f);
			float num2 = Random.Range(4f, 7f);
			Vector3 val = Quaternion.Euler(0f, num, 0f) * Vector3.forward * num2;
			Vector3 val2 = center + val + Vector3.up * 0.3f;
			SummonEffects.PlayTroll(val2);
			PlayDeathEffect(prefab, val2, Quaternion.identity);
			SummonEffects.PlayTroll(val2);
			GameObject obj = Object.Instantiate<GameObject>(prefab, val2, Quaternion.identity);
			MonsterAI component = obj.GetComponent<MonsterAI>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_attackPlayerObjects = false;
			}
			Character component2 = obj.GetComponent<Character>();
			Vector3 localScale = obj.transform.localScale;
			if ((Object)(object)component2 != (Object)null)
			{
				component2.SetLevel(16);
				component2.m_group = $"GT_TROLL_{owner.GetPlayerID()}";
				component2.m_faction = (Faction)0;
			}
			SummonedGoblin summonedGoblin = obj.AddComponent<SummonedGoblin>();
			summonedGoblin.Initialize(owner.GetPlayerID(), center, WorkerRole.Combat, 315360000f);
			obj.AddComponent<TrollStatScaler>().Initialize(localScale, staffTier, quality);
			obj.AddComponent<CombatSummonAI>().Initialize(summonedGoblin);
			return obj;
		}

		internal static bool CastSkeletonGroup(Player owner, Vector3 center, int meleeCount, int rangedCount, int staffTier)
		{
			//IL_000a: 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)
			bool flag = false;
			int num = 0;
			for (int i = 0; i < meleeCount; i++)
			{
				flag |= (Object)(object)SpawnSkeleton(owner, center, num++, staffTier, ranged: false) != (Object)null;
			}
			for (int j = 0; j < rangedCount; j++)
			{
				flag |= (Object)(object)SpawnSkeleton(owner, center, num++, staffTier, ranged: true) != (Object)null;
			}
			return flag;
		}

		private static GameObject SpawnSkeleton(Player owner, Vector3 center, int index, int staffTier, bool ranged)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0079: 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_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)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("Skeleton");
			if ((Object)(object)prefab == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)"Skeleton prefab not found.");
				}
				return null;
			}
			float num = (float)index * 31f + Random.Range(-12f, 12f);
			float num2 = Random.Range(2.5f, 6f);
			Vector3 val = Quaternion.Euler(0f, num, 0f) * Vector3.forward * num2;
			Vector3 val2 = center + val + Vector3.up * 0.2f;
			SummonEffects.PlaySkeleton(val2);
			SummonEffects.PlaySkeleton(val2);
			PlayDeathEffect(prefab, val2, Quaternion.identity);
			SummonEffects.PlayTroll(val2);
			GameObject obj = Object.Instantiate<GameObject>(prefab, val2, Quaternion.identity);
			MonsterAI component = obj.GetComponent<MonsterAI>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_attackPlayerObjects = false;
			}
			Character component2 = obj.GetComponent<Character>();
			Humanoid component3 = obj.GetComponent<Humanoid>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.SetLevel(Mathf.Clamp(staffTier, 1, 6) + 1);
				component2.m_faction = (Faction)0;
				component2.m_group = $"GT_SKELETON_{owner.GetPlayerID()}";
			}
			if ((Object)(object)component3 != (Object)null)
			{
				string text = (ranged ? "SkeletonBow" : "SkeletonSword");
				GameObject prefab2 = PrefabManager.Instance.GetPrefab(text);
				ItemDrop val3 = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val3 != (Object)null)
				{
					ItemData val4 = val3.m_itemData.Clone();
					component3.EquipItem(val4, false);
				}
				else
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)("Skeleton weapon not found: " + text));
					}
				}
			}
			SummonedSkeleton summonedSkeleton = obj.AddComponent<SummonedSkeleton>();
			summonedSkeleton.Initialize(owner.GetPlayerID(), staffTier, ranged);
			obj.AddComponent<SkeletonStatScaler>().Initialize(summonedSkeleton);
			return obj;
		}

		internal static int DismissSkeletons(long ownerId)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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)
			int num = 0;
			SummonedSkeleton[] array = Object.FindObjectsByType<SummonedSkeleton>((FindObjectsSortMode)0);
			foreach (SummonedSkeleton summonedSkeleton in array)
			{
				if ((Object)(object)summonedSkeleton == (Object)null || summonedSkeleton.OwnerPlayerId != ownerId)
				{
					continue;
				}
				SummonEffects.PlayDismiss(((Component)summonedSkeleton).transform.position);
				ZNetView component = ((Component)summonedSkeleton).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid() && !component.IsOwner())
				{
					continue;
				}
				Character component2 = ((Component)summonedSkeleton).GetComponent<Character>();
				if ((Object)(object)component2 != (Object)null)
				{
					try
					{
						component2.m_deathEffects.Create(((Component)summonedSkeleton).transform.position, ((Component)summonedSkeleton).transform.rotation, (Transform)null, 1f, -1);
					}
					catch
					{
					}
				}
				ZNetScene instance = ZNetScene.instance;
				if (instance != null)
				{
					instance.Destroy(((Component)summonedSkeleton).gameObject);
				}
				num++;
			}
			return num;
		}

		internal static bool HasSkeletons(long ownerId)
		{
			SummonedSkeleton[] array = Object.FindObjectsByType<SummonedSkeleton>((FindObjectsSortMode)0);
			foreach (SummonedSkeleton summonedSkeleton in array)
			{
				if ((Object)(object)summonedSkeleton != (Object)null && summonedSkeleton.OwnerPlayerId == ownerId)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class SummonRuntime
	{
		internal static int TrollCount(long ownerId)
		{
			int num = 0;
			SummonedGoblin[] array = Object.FindObjectsOfType<SummonedGoblin>();
			foreach (SummonedGoblin summonedGoblin in array)
			{
				if (!((Object)(object)summonedGoblin == (Object)null) && summonedGoblin.OwnerPlayerId == ownerId && (!((Object)(object)((Component)summonedGoblin).GetComponent<TrollStatScaler>() == (Object)null) || !((Object)(object)((Component)summonedGoblin).GetComponent<CombatSummonAI>() == (Object)null)))
				{
					Character component = ((Component)summonedGoblin).GetComponent<Character>();
					if (!((Object)(object)component != (Object)null) || !component.IsDead())
					{
						num++;
					}
				}
			}
			return num;
		}

		internal static int SkeletonCount(long ownerId)
		{
			int num = 0;
			SummonedSkeleton[] array = Object.FindObjectsOfType<SummonedSkeleton>();
			foreach (SummonedSkeleton summonedSkeleton in array)
			{
				if (!((Object)(object)summonedSkeleton == (Object)null) && summonedSkeleton.OwnerPlayerId == ownerId)
				{
					Character component = ((Component)summonedSkeleton).GetComponent<Character>();
					if (!((Object)(object)component != (Object)null) || !component.IsDead())
					{
						num++;
					}
				}
			}
			return num;
		}

		internal static int DismissTrolls(long ownerId)
		{
			int num = 0;
			SummonedGoblin[] array = Object.FindObjectsOfType<SummonedGoblin>();
			foreach (SummonedGoblin summonedGoblin in array)
			{
				if ((Object)(object)summonedGoblin == (Object)null || summonedGoblin.OwnerPlayerId != ownerId || ((Object)(object)((Component)summonedGoblin).GetComponent<TrollStatScaler>() == (Object)null && (Object)(object)((Component)summonedGoblin).GetComponent<CombatSummonAI>() == (Object)null))
				{
					continue;
				}
				GameObject gameObject = ((Component)summonedGoblin).gameObject;
				ZNetView component = gameObject.GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid() || component.IsOwner())
				{
					if ((Object)(object)ZNetScene.instance != (Object)null && (Object)(object)component != (Object)null && component.IsValid())
					{
						ZNetScene.instance.Destroy(gameObject);
					}
					else
					{
						Object.Destroy((Object)(object)gameObject);
					}
					num++;
				}
			}
			return num;
		}

		internal static void CleanupTrollCorpseFx(Vector3 center, float radius)
		{
			//IL_006a: 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)
			GameObject[] array = Object.FindObjectsOfType<GameObject>();
			foreach (GameObject val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string text = ((Object)val).name.ToLowerInvariant();
				bool num = text.Contains("troll");
				bool flag = text.Contains("ragdoll") || text.Contains("corpse") || text.Contains("death");
				if (!num || !flag || Vector3.Distance(val.transform.position, center) > radius)
				{
					continue;
				}
				ZNetView component = val.GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					if (component.IsOwner() && (Object)(object)ZNetScene.instance != (Object)null)
					{
						ZNetScene.instance.Destroy(val);
					}
				}
				else
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
	}
	internal enum WorkerRole
	{
		Mining,
		Woodcutting,
		Gathering,
		Combat
	}
}
namespace GatheringTorch.Skills
{
	internal sealed class SkillController : MonoBehaviour
	{
		private const float TrollCooldown = 60f;

		private const float SkeletonCooldown = 30f;

		private const float CountRefreshInterval = 5f;

		private const float EquipRefreshInterval = 0.5f;

		private static readonly MethodInfo GetLeftItemMethod = typeof(Humanoid).GetMethod("GetLeftItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private bool _castingTroll;

		private bool _castingSkeleton;

		private int _cachedTrolls;

		private int _cachedSkeletons;

		private float _nextCountRefreshAt;

		private ItemData _cachedStaff;

		private int _cachedTier;

		private float _nextEquipRefreshAt;

		internal static SkillController Instance { get; private set; }

		internal float TrollReadyAt { get; private set; }

		internal float SkeletonReadyAt { get; private set; }

		internal bool HasSummonStaff
		{
			get
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					return false;
				}
				RefreshEquippedStaff(localPlayer, force: false);
				if (_cachedStaff != null)
				{
					return _cachedTier > 0;
				}
				return false;
			}
		}

		internal int EquippedTier => _cachedTier;

		internal ItemData EquippedStaff => _cachedStaff;

		internal bool TrollUiOn
		{
			get
			{
				if (!_castingTroll && _cachedTrolls <= 0)
				{
					return Time.time >= TrollReadyAt;
				}
				return false;
			}
		}

		internal bool SkeletonUiOn
		{
			get
			{
				if (!_castingSkeleton && _cachedSkeletons <= 0)
				{
					return Time.time >= SkeletonReadyAt;
				}
				return false;
			}
		}

		internal int CurrentTrolls => _cachedTrolls;

		internal int MaxTrolls => 1;

		internal int CurrentSkeletons => _cachedSkeletons;

		internal int MaxSkeletons
		{
			get
			{
				ItemData cachedStaff = _cachedStaff;
				if (cachedStaff == null)
				{
					return 0;
				}
				int num = Mathf.Max(1, cachedStaff.m_quality);
				return 10 + (num - 1) * 3;
			}
		}

		internal float RemainingTroll => Mathf.Max(0f, TrollReadyAt - Time.time);

		internal float RemainingSkeleton => Mathf.Max(0f, SkeletonReadyAt - Time.time);

		private void Awake()
		{
			Instance = this;
		}

		private void Update()
		{
			//IL_0036: 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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			RefreshEquippedStaff(localPlayer, force: false);
			if (_cachedStaff == null || _cachedTier <= 0)
			{
				return;
			}
			RefreshCounts(force: false);
			if (Input.GetKeyDown(Plugin.WoodKey.Value))
			{
				RefreshEquippedStaff(localPlayer, force: true);
				if (_cachedStaff != null)
				{
					TryTrollToggle(localPlayer, _cachedStaff, _cachedTier);
				}
			}
			if (Input.GetKeyDown(Plugin.CombatKey.Value))
			{
				RefreshEquippedStaff(localPlayer, force: true);
				if (_cachedStaff != null)
				{
					TrySkeletonToggle(localPlayer, _cachedStaff, _cachedTier);
				}
			}
		}

		private void RefreshEquippedStaff(Player player, bool force)
		{
			if ((Object)(object)player == (Object)null)
			{
				_cachedStaff = null;
				_cachedTier = 0;
			}
			else
			{
				if (!force && Time.time < _nextEquipRefreshAt)
				{
					return;
				}
				_nextEquipRefreshAt = Time.time + 0.5f;
				_cachedStaff = null;
				_cachedTier = 0;
				ItemData rightItem = PlayerItemUtil.GetRightItem(player);
				if (rightItem != null && GatheringTorchItems.TryGetTier(rightItem, out var tier))
				{
					_cachedStaff = rightItem;
					_cachedTier = tier;
					return;
				}
				ItemData leftItem = GetLeftItem(player);
				if (leftItem != null && GatheringTorchItems.TryGetTier(leftItem, out var tier2))
				{
					_cachedStaff = leftItem;
					_cachedTier = tier2;
				}
			}
		}

		private static ItemData GetLeftItem(Player player)
		{
			if ((Object)(object)player == (Object)null || GetLeftItemMethod == null)
			{
				return null;
			}
			try
			{
				object? obj = GetLeftItemMethod.Invoke(player, null);
				return (ItemData)((obj is ItemData) ? obj : null);
			}
			catch
			{
				return null;
			}
		}

		private void RefreshCounts(bool force)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				_cachedTrolls = 0;
				_cachedSkeletons = 0;
				_nextCountRefreshAt = Time.time + 5f;
			}
			else if (force || !(Time.time < _nextCountRefreshAt))
			{
				long playerID = localPlayer.GetPlayerID();
				_cachedTrolls = SummonRuntime.TrollCount(playerID);
				_cachedSkeletons = SummonRuntime.SkeletonCount(playerID);
				_nextCountRefreshAt = Time.time + 5f;
			}
		}

		private void TryTrollToggle(Player player, ItemData staff, int tier)
		{
			RefreshCounts(force: true);
			long playerID = player.GetPlayerID();
			if (_cachedTrolls > 0)
			{
				int num = SummonRuntime.DismissTrolls(playerID);
				_cachedTrolls = 0;
				_nextCountRefreshAt = Time.time + 5f;
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, $"트롤 소환 해제 ({num}마리)", 0, (Sprite)null, false);
				}
			}
			else if (!_castingTroll)
			{
				if (Time.time < TrollReadyAt)
				{
					ShowCooldown("트롤 소환", TrollReadyAt - Time.time);
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(CastTroll(player, staff, tier));
				}
			}
		}

		private IEnumerator CastTroll(Player player, ItemData staff, int tier)
		{
			_castingTroll = true;
			PlayCastAnimation(player, "staff_trollsummon");
			yield return (object)new WaitForSeconds(0.45f);
			if ((Object)(object)player == (Object)null)
			{
				_castingTroll = false;
				yield break;
			}
			Vector3 center = ((Component)player).transform.position;
			int quality = ((staff == null) ? 1 : Mathf.Max(1, staff.m_quality));
			GameObject troll = SummonManager.SpawnTroll(player, center, 0, tier, quality);
			SummonRuntime.CleanupTrollCorpseFx(center, 14f);
			yield return (object)new WaitForSeconds(0.25f);
			SummonRuntime.CleanupTrollCorpseFx(center, 14f);
			if ((Object)(object)troll != (Object)null)
			{
				TrollReadyAt = Time.time + 60f;
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, "트롤 소환", 0, (Sprite)null, false);
				}
			}
			_castingTroll = false;
			yield return null;
			RefreshCounts(force: true);
		}

		private void TrySkeletonToggle(Player player, ItemData staff, int tier)
		{
			RefreshCounts(force: true);
			long playerID = player.GetPlayerID();
			if (_cachedSkeletons > 0)
			{
				int num = SummonManager.DismissSkeletons(playerID);
				_cachedSkeletons = 0;
				_nextCountRefreshAt = Time.time + 5f;
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, $"해골 소환 해제 ({num}마리)", 0, (Sprite)null, false);
				}
			}
			else if (!_castingSkeleton)
			{
				if (Time.time < SkeletonReadyAt)
				{
					ShowCooldown("해골 소환", SkeletonReadyAt - Time.time);
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(CastSkeletons(player, staff, tier));
				}
			}
		}

		private IEnumerator CastSkeletons(Player player, ItemData staff, int tier)
		{
			_castingSkeleton = true;
			PlayCastAnimation(player, "staff_summon");
			yield return (object)new WaitForSeconds(0.35f);
			if ((Object)(object)player == (Object)null || staff == null)
			{
				_castingSkeleton = false;
				yield break;
			}
			int num = Mathf.Max(1, staff.m_quality);
			int num2 = 5 + (num - 1) * 2;
			int num3 = 5 + (num - 1);
			Vector3 position = ((Component)player).transform.position;
			if (SummonManager.CastSkeletonGroup(player, position, num2, num3, tier))
			{
				SkeletonReadyAt = Time.time + 30f;
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)2, $"해골 소환 ({num2 + num3}마리)", 0, (Sprite)null, false);
				}
			}
			_castingSkeleton = false;
			yield return null;
			RefreshCounts(force: true);
		}

		private static void PlayCastAnimation(Player player, string trigger)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				ZSyncAnimation component = ((Component)player).GetComponent<ZSyncAnimation>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetTrigger(trigger);
					return;
				}
			}
			catch
			{
			}
			try
			{
				Animator componentInChildren = ((Component)player).GetComponentInChildren<Animator>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.SetTrigger(trigger);
				}
			}
			catch
			{
			}
		}

		private static void ShowCooldown(string skill, float remain)
		{
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)2, $"{skill} 쿨타임 {Mathf.CeilToInt(remain)}초", 0, (Sprite)null, false);
			}
		}
	}
}
namespace GatheringTorch.Items
{
	internal static class GatheringTorchItems
	{
		private const string BasePrefab = "Torch";

		internal static readonly string[] Prefabs = new string[6] { "GT_GatheringTorch_T1", "GT_GatheringTorch_T2", "GT_GatheringTorch_T3", "GT_GatheringTorch_T4", "GT_GatheringTorch_T5", "GT_GatheringTorch_T6" };

		private static readonly int[] WorkerCounts = new int[6] { 1, 2, 3, 4, 6, 9 };

		private static readonly Dictionary<string, int> TierByPrefab = new Dictionary<string, int>();

		internal static void Register()
		{
			//IL_0001: 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_0029: 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)
			//IL_0066: 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)
			RegisterTier(1, Color.red, "AxeWood", null);
			RegisterTier(2, Color.blue, "AxeStone", Prefabs[0]);
			RegisterTier(3, Color.yellow, "AxeFlint", Prefabs[1]);
			RegisterTier(4, Color.green, "AxeBronze", Prefabs[2]);
			RegisterTier(5, new Color(1f, 0.5f, 0f), "AxeIron", Prefabs[3]);
			RegisterTier(6, new Color(0.62f, 0.2f, 1f), "AxeBlackMetal", Prefabs[4]);
		}

		private static void RegisterTier(int tier, Color flameColor, string axePrefab, string previousTier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_003d: 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_004c: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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)
			ItemConfig val = new ItemConfig
			{
				Name = $"채집의 지팡이 {tier}",
				Description = GetDescription(tier),
				CraftingStation = CraftingStations.Workbench,
				RepairStation = CraftingStations.Workbench,
				MinStationLevel = 1,
				Amount = 1
			};
			switch (tier)
			{
			case 1:
				val.AddRequirement("Torch", 1, 0);
				val.AddRequirement(axePrefab, 1, 0);
				break;
			case 6:
				val.AddRequirement(previousTier, 1, 0);
				val.AddRequirement("Stone", 10, 5);
				val.AddRequirement("Iron", 10, 5);
				val.AddRequirement("BlackMetal", 10, 5);
				val.AddRequirement("Bronze", 10, 5);
				break;
			default:
				val.AddRequirement(previousTier, 1, 0);
				val.AddRequirement(axePrefab, 1, 0);
				break;
			}
			CustomItem val2 = new CustomItem(Prefabs[tier - 1], "Torch", val);
			SharedData shared = val2.ItemDrop.m_itemData.m_shared;
			shared.m_name = $"채집의 지팡이 {tier}";
			shared.m_description = GetDescription(tier);
			shared.m_maxStackSize = 1;
			shared.m_maxQuality = 5;
			shared.m_damages = new DamageTypes
			{
				m_blunt = 1f
			};
			shared.m_damagesPerLevel = default(DamageTypes);
			shared.m_attackForce = 0f;
			shared.m_toolTier = 0;
			RecolorTorch(val2.ItemPrefab, flameColor);
			if (ItemManager.Instance.AddItem(val2))
			{
				TierByPrefab[Prefabs[tier - 1]] = tier;
				Plugin.Log.LogInfo((object)$"Registered staff T{tier}: {Prefabs[tier - 1]}");
			}
			else
			{
				Plugin.Log.LogError((object)$"Failed to register staff T{tier}");
			}
		}

		private static string GetDescription(int tier)
		{
			int num = WorkerCounts[tier - 1];
			return $"X: 채광 {num}+채집1 / Z: 벌목 {num}+채집1 / C: 전투10\n" + "작업 45초, 전투 30초, 각 쿨타임 60초, 반경 100m";
		}

		private static void RecolorTorch(GameObject prefab, Color c)
		{
			//IL_000f: 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_0017: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystem[] componentsInChildren = prefab.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				MainModule main = componentsInChildren[i].main;
				((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(c);
			}
			Light[] componentsInChildren2 = prefab.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].color = c;
			}
		}

		internal static bool TryGetTier(ItemData item, out int tier)
		{
			tier = 0;
			if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
			{
				return false;
			}
			string key = ((Object)item.m_dropPrefab).name.Replace("(Clone)", "");
			return TierByPrefab.TryGetValue(key, out tier);
		}

		internal static int WorkerCount(int tier)
		{
			if (tier < 1 || tier > WorkerCounts.Length)
			{
				return 0;
			}
			return WorkerCounts[tier - 1];
		}
	}
}
namespace GatheringTorch.Patches
{
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class CombatGoblinDamagePatch
	{
		private static void Prefix(HitData hit)
		{
			if (hit == null)
			{
				return;
			}
			Character attacker = hit.GetAttacker();
			if ((Object)(object)attacker == (Object)null)
			{
				return;
			}
			TrollStatScaler component = ((Component)attacker).GetComponent<TrollStatScaler>();
			if (!((Object)(object)component == (Object)null))
			{
				float attackMultiplier = component.AttackMultiplier;
				if (!(attackMultiplier <= 0f) && !Mathf.Approximately(attackMultiplier, 1f))
				{
					((DamageTypes)(ref hit.m_damage)).Modify(attackMultiplier);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class SkeletonSummonDamagePatch
	{
		private static void Prefix(HitData hit)
		{
			if (hit == null)
			{
				return;
			}
			Character attacker = hit.GetAttacker();
			if (!((Object)(object)attacker == (Object)null))
			{
				SummonedSkeleton component = ((Component)attacker).GetComponent<SummonedSkeleton>();
				if (!((Object)(object)component == (Object)null))
				{
					float attackMultiplier = SkeletonStatScaler.GetAttackMultiplier(component);
					hit.m_damage.m_damage *= attackMultiplier;
					hit.m_damage.m_blunt *= attackMultiplier;
					hit.m_damage.m_slash *= attackMultiplier;
					hit.m_damage.m_pierce *= attackMultiplier;
					hit.m_damage.m_chop *= attackMultiplier;
					hit.m_damage.m_pickaxe *= attackMultiplier;
					hit.m_damage.m_fire *= attackMultiplier;
					hit.m_damage.m_frost *= attackMultiplier;
					hit.m_damage.m_lightning *= attackMultiplier;
					hit.m_damage.m_poison *= attackMultiplier;
					hit.m_damage.m_spirit *= attackMultiplier;
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
	internal static class SummonNoDropPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(CharacterDrop __instance, ref List<KeyValuePair<GameObject, int>> __result)
		{
			if (!((Object)(object)__instance == (Object)null) && __result != null)
			{
				GameObject gameObject = ((Component)__instance).gameObject;
				bool num = (Object)(object)gameObject.GetComponent<SummonedSkeleton>() != (Object)null;
				bool flag = (Object)(object)gameObject.GetComponent<SummonedGoblin>() != (Object)null && ((Object)(object)gameObject.GetComponent<TrollStatScaler>() != (Object)null || (Object)(object)gameObject.GetComponent<CombatSummonAI>() != (Object)null);
				if (num || flag)
				{
					__result.Clear();
				}
			}
		}
	}
}
namespace GatheringTorch.AI
{
	internal sealed class CombatSummonAI : MonoBehaviour
	{
		private SummonedGoblin _meta;

		private MonsterAI _ai;

		private Character _character;

		private Animator _animator;

		private float _nextFollow;

		private MethodInfo _inAttackMethod;

		internal void Initialize(SummonedGoblin meta)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			_meta = meta;
			_ai = ((Component)this).GetComponent<MonsterAI>();
			_character = ((Component)this).GetComponent<Character>();
			_animator = ((Component)this).GetComponentInChildren<Animator>();
			if ((Object)(object)_character != (Object)null)
			{
				_character.m_faction = (Faction)0;
				_character.m_group = $"GT_COMBAT_{meta.OwnerPlayerId}";
				_inAttackMethod = ((object)_character).GetType().GetMethod("InAttack", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
		}

		private void Update()
		{
			if ((Object)(object)_character == (Object)null || (Object)(object)_animator == (Object)null)
			{
				return;
			}
			bool flag = false;
			if (_inAttackMethod != null)
			{
				try
				{
					if (_inAttackMethod.Invoke(_character, null) is bool flag2)
					{
						flag = flag2;
					}
				}
				catch
				{
				}
			}
			_animator.speed = (flag ? 2f : 1f);
		}

		private void FixedUpdate()
		{
			if (!((Object)(object)_meta == (Object)null) && !((Object)(object)_ai == (Object)null) && !(Time.time < _nextFollow))
			{
				_nextFollow = Time.time + 1f;
				Player val = _meta.FindOwner();
				if ((Object)(object)val != (Object)null && (Object)(object)_ai.GetFollowTarget() == (Object)null)
				{
					_ai.SetFollowTarget(((Component)val).gameObject);
				}
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_animator != (Object)null)
			{
				_animator.speed = 1f;
			}
		}
	}
	internal sealed class GatherWorkerAI : WorkerBase
	{
		protected override GameObject FindTarget()
		{
			//IL_003d: 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_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_00bd: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			GameObject result = null;
			float num = float.MaxValue;
			Pickable[] array = Object.FindObjectsByType<Pickable>((FindObjectsSortMode)0);
			foreach (Pickable val in array)
			{
				if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && Meta.InWorkArea(((Component)val).transform.position))
				{
					float num2 = Vector3.SqrMagnitude(((Component)this).transform.position - ((Component)val).transform.position);
					if (num2 < num)
					{
						num = num2;
						result = ((Component)val).gameObject;
					}
				}
			}
			PickableItem[] array2 = Object.FindObjectsByType<PickableItem>((FindObjectsSortMode)0);
			foreach (PickableItem val2 in array2)
			{
				if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeInHierarchy && Meta.InWorkArea(((Component)val2).transform.position))
				{
					float num3 = Vector3.SqrMagnitude(((Component)this).transform.position - ((Component)val2).transform.position);
					if (num3 < num)
					{
						num = num3;
						result = ((Component)val2).gameObject;
					}
				}
			}
			return result;
		}

		protected override bool IsTargetStillValid(GameObject go)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go != (Object)null && go.activeInHierarchy)
			{
				return Meta.InWorkArea(go.transform.position);
			}
			return false;
		}

		protected override void PerformWork(GameObject go)
		{
			if ((Object)(object)go == (Object)null || (Object)(object)Humanoid == (Object)null)
			{
				ClearTarget();
				return;
			}
			Pickable componentInParent = go.GetComponentInParent<Pickable>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				componentInParent.Interact(Humanoid, false, false);
				ClearTarget();
				return;
			}
			PickableItem componentInParent2 = go.GetComponentInParent<PickableItem>();
			if ((Object)(object)componentInParent2 != (Object)null)
			{
				componentInParent2.Interact(Humanoid, false, false);
				ClearTarget();
			}
			else
			{
				ClearTarget();
			}
		}
	}
	internal sealed class HarvestLootForwarder : MonoBehaviour
	{
		private SummonedGoblin _meta;

		private ZNetView _nview;

		private float _nextScan;

		private void Awake()
		{
			_meta = ((Component)this).GetComponent<SummonedGoblin>();
			_nview = ((Component)this).GetComponent<ZNetView>();
		}

		private void FixedUpdate()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_meta == (Object)null || _meta.Role == WorkerRole.Combat || Time.time < _nextScan)
			{
				return;
			}
			_nextScan = Time.time + 0.35f;
			if ((Object)(object)_nview != (Object)null && _nview.IsValid() && !_nview.IsOwner())
			{
				return;
			}
			Player val = _meta.FindOwner();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, 7f);
			HashSet<ItemDrop> hashSet = new HashSet<ItemDrop>();
			Collider[] array2 = array;
			foreach (Collider val2 in array2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					ItemDrop componentInParent = ((Component)val2).GetComponentInParent<ItemDrop>();
					if (!((Object)(object)componentInParent == (Object)null) && hashSet.Add(componentInParent))
					{
						TryTransfer(componentInParent, val);
					}
				}
			}
		}

		private static void TryTransfer(ItemDrop drop, Player owner)
		{
			if ((Object)(object)drop == (Object)null || (Object)(object)owner == (Object)null || drop.m_itemData == null)
			{
				return;
			}
			ZNetView component = ((Component)drop).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid() && !component.IsOwner())
			{
				drop.RequestOwn();
				return;
			}
			Inventory inventory = ((Humanoid)owner).GetInventory();
			ItemData val = drop.m_itemData.Clone();
			if (!inventory.CanAddItem(val, val.m_stack) || !inventory.AddItem(val))
			{
				return;
			}
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				ZNetScene instance = ZNetScene.instance;
				if (instance != null)
				{
					instance.Destroy(((Component)drop).gameObject);
				}
			}
			else
			{
				Object.Destroy((Object)(object)((Component)drop).gameObject);
			}
		}
	}
	internal sealed class LaborTrollAI : MonoBehaviour
	{
		private SummonedGoblin _meta;

		private MonsterAI _ai;

		private Character _character;

		private Animator _animator;

		private GameObject _target;

		private float _nextSearch;

		private float _nextSwing;

		private int _swingsRemaining;

		private bool _swinging;

		private const float SearchInterval = 0.75f;

		private const float WorkDistance = 4f;

		private const float SwingInterval = 0.85f;

		internal void Initialize(SummonedGoblin meta)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			_meta = meta;
			_ai = ((Component)this).GetComponent<MonsterAI>();
			_character = ((Component)this).GetComponent<Character>();
			_animator = ((Component)this).GetComponentInChildren<Animator>();
			if ((Object)(object)_character != (Object)null)
			{
				_character.m_faction = (Faction)0;
				_character.m_group = $"GT_LABOR_{meta.OwnerPlayerId}";
			}
		}

		private void Update()
		{
			//IL_007a: 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_00aa: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_meta == (Object)null || (Object)(object)_character == (Object)null)
			{
				return;
			}
			if ((Object)(object)_target == (Object)null || !_target.activeInHierarchy)
			{
				StopSwinging();
				if (Time.time >= _nextSearch)
				{
					_nextSearch = Time.time + 0.75f;
					_target = FindNearestTarget();
				}
				return;
			}
			if (!_meta.InWorkArea(_target.transform.position))
			{
				_target = null;
				StopSwinging();
				return;
			}
			if (Vector3.Distance(((Component)this).transform.position, _target.transform.position) > 4f)
			{
				StopSwinging();
				MoveToward(_target.transform.position);
				return;
			}
			FaceTarget(_target.transform.position);
			if (!_swinging)
			{
				_swinging = true;
				_swingsRemaining = 3;
				_nextSwing = Time.time;
			}
			if (_swingsRemaining > 0 && Time.time >= _nextSwing)
			{
				Swing();
				_swingsRemaining--;
				_nextSwing = Time.time + 0.85f;
			}
			if (_swingsRemaining <= 0)
			{
				StopSwinging();
				_target = null;
				_nextSearch = Time.time + 0.25f;
			}
		}

		private GameObject FindNearestTarget()
		{
			GameObject best = null;
			float bestDistance = float.MaxValue;
			TreeBase[] array = Object.FindObjectsByType<TreeBase>((FindObjectsSortMode)0);
			foreach (TreeBase val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Consider(((Component)val).gameObject, ref best, ref bestDistance);
				}
			}
			TreeLog[] array2 = Object.FindObjectsByType<TreeLog>((FindObjectsSortMode)0);
			foreach (TreeLog val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Consider(((Component)val2).gameObject, ref best, ref bestDistance);
				}
			}
			MineRock5[] array3 = Object.FindObjectsByType<MineRock5>((FindObjectsSortMode)0);
			foreach (MineRock5 val3 in array3)
			{
				if ((Object)(object)val3 != (Object)null && IsOre(((Object)((Component)val3).gameObject).name))
				{
					Consider(((Component)val3).gameObject, ref best, ref bestDistance);
				}
			}
			MineRock[] array4 = Object.FindObjectsByType<MineRock>((FindObjectsSortMode)0);
			foreach (MineRock val4 in array4)
			{
				if ((Object)(object)val4 != (Object)null && IsOre(((Object)((Component)val4).gameObject).name))
				{
					Consider(((Component)val4).gameObject, ref best, ref bestDistance);
				}
			}
			return best;
		}

		private void Consider(GameObject go, ref GameObject best, ref float bestDistance)
		{
			//IL_001e: 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_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)
			if (!((Object)(object)go == (Object)null) && go.activeInHierarchy && _meta.InWorkArea(go.transform.position))
			{
				float num = Vector3.SqrMagnitude(((Component)this).transform.position - go.transform.position);
				if (num < bestDistance)
				{
					bestDistance = num;
					best = go;
				}
			}
		}

		private static bool IsOre(string objectName)
		{
			if (string.IsNullOrEmpty(objectName))
			{
				return false;
			}
			string text = objectName.ToLowerInvariant();
			if ((text.Contains("rock") || text.Contains("stone")) && !text.Contains("copper") && !text.Contains("tin") && !text.Contains("silver") && !text.Contains("obsidian") && !text.Contains("iron") && !text.Contains("scrap") && !text.Contains("mud") && !text.Contains("marble") && !text.Contains("ancient"))
			{
				return false;
			}
			if (!text.Contains("copper") && !text.Contains("tin") && !text.Contains("silver") && !text.Contains("obsidian") && !text.Contains("iron") && !text.Contains("scrap") && !text.Contains("mudpile") && !text.Contains("mudpile") && !text.Contains("blackmarble") && !text.Contains("marble") && !text.Contains("ancientarmor"))
			{
				return text.Contains("ancientsword");
			}
			return true;
		}

		private void MoveToward(Vector3 target)
		{
			//IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target - ((Component)this).transform.position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				return;
			}
			((Vector3)(ref val)).Normalize();
			if ((Object)(object)_ai != (Object)null)
			{
				MethodInfo method = typeof(BaseAI).GetMethod("MoveTowards", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					try
					{
						method.Invoke(_ai, new object[2] { val, true });
						return;
					}
					catch
					{
					}
				}
			}
			Transform transform = ((Component)this).transform;
			transform.position += val * 3f * Time.deltaTime;
		}

		private void FaceTarget(Vector3 target)
		{
			//IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target - ((Component)this).transform.position;
			val.y = 0f;
			if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f))
			{
				((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, Quaternion.LookRotation(val), Time.deltaTime * 10f);
			}
		}

		private void Swing()
		{
			if ((Object)(object)_animator != (Object)null)
			{
				_animator.speed = 2f;
				_animator.SetTrigger("attack");
			}
			((MonoBehaviour)this).Invoke("ApplySwingHit", 0.25f);
		}

		private void ApplySwingHit()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//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_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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0127: 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_0135: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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 ((Object)(object)_target == (Object)null)
			{
				return;
			}
			HitData val = new HitData();
			val.m_point = _target.transform.position;
			val.m_dir = ((Component)this).transform.forward;
			val.m_damage.m_blunt = 250f;
			if ((Object)(object)_target.GetComponent<TreeBase>() != (Object)null || (Object)(object)_target.GetComponent<TreeLog>() != (Object)null || (Object)(object)_target.GetComponentInParent<TreeBase>() != (Object)null || (Object)(object)_target.GetComponentInParent<TreeLog>() != (Object)null)
			{
				val.m_damage.m_chop = 500f;
			}
			else
			{
				val.m_damage.m_pickaxe = 500f;
				val.m_toolTier = 99;
			}
			TryDamage(_target, val);
			Collider[] array = Physics.OverlapSphere(((Component)this).transform.position + ((Component)this).transform.forward * 2f, 3f);
			for (int i = 0; i < array.Length; i++)
			{
				Character componentInParent = ((Component)array[i]).GetComponentInParent<Character>();
				if (!((Object)(object)componentInParent == (Object)null) && !((Object)(object)componentInParent == (Object)(object)_character) && (int)componentInParent.m_faction != 0)
				{
					HitData val2 = new HitData();
					val2.m_point = ((Component)componentInParent).transform.position;
					val2.m_dir = ((Component)this).transform.forward;
					val2.m_damage.m_blunt = 500f;
					val2.SetAttacker(_character);
					componentInParent.Damage(val2);
				}
			}
		}

		private static bool TryDamage(GameObject go, HitData hit)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				MethodInfo method = ((object)val).GetType().GetMethod("Damage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(HitData) }, null);
				if (!(method == null))
				{
					try
					{
						method.Invoke(val, new object[1] { hit });
						return true;
					}
					catch
					{
					}
				}
			}
			return false;
		}

		private void StopSwinging()
		{
			_swinging = false;
			_swingsRemaining = 0;
			if ((Object)(object)_animator != (Object)null)
			{
				_animator.speed = 1f;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_animator != (Object)null)
			{
				_animator.speed = 1f;
			}
		}
	}
	internal sealed class MiningWorkerAI : WorkerBase
	{
		protected override GameObject FindTarget()
		{
			GameObject best = null;
			float bestScore = float.MaxValue;
			MineRock5[] array = Object.FindObjectsByType<MineRock5>((FindObjectsSortMode)0);
			foreach (MineRock5 val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Consider(((Component)val).gameObject, ref best, ref bestScore);
				}
			}
			MineRock[] array2 = Object.FindObjectsByType<MineRock>((FindObjectsSortMode)0);
			foreach (MineRock val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Consider(((Component)val2).gameObject, ref best, ref bestScore);
				}
			}
			Destructible[] array3 = Object.FindObjectsByType<Destructible>((FindObjectsSortMode)0);
			foreach (Destructible val3 in array3)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					string text = ((Object)((Component)val3).gameObject).name.ToLowerInvariant();
					if (text.Contains("rock") || text.Contains("stone") || text.Contains("ore") || text.Contains("copper") || text.Contains("tin") || text.Contains("silver") || text.Contains("obsidian") || text.Contains("iron") || text.Contains("scrap") || text.Contains("mud") || text.Contains("meteor"))
					{
						Consider(((Component)val3).gameObject, ref best, ref bestScore);
					}
				}
			}
			return best;
		}

		private void Consider(GameObject go, ref GameObject best, ref float bestScore)
		{
			//IL_001d: 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_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)go == (Object)null) && go.activeInHierarchy && Meta.InWorkArea(go.transform.position))
			{
				float num = Vector3.SqrMagnitude(((Component)this).transform.position - go.transform.position);
				if (num < bestScore)
				{
					bestScore = num;
					best = go;
				}
			}
		}

		protected override bool IsTargetStillValid(GameObject go)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go != (Object)null && go.activeInHierarchy)
			{
				return Meta.InWorkArea(go.transform.position);
			}
			return false;
		}

		protected override void PerformWork(GameObject go)
		{
			//IL_0030: 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_008f: 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)
			if ((Object)(object)go == (Object)null)
			{
				ClearTarget();
				return;
			}
			HitData val = MakeHit(0f, 1000f);
			val.m_toolTier = 99;
			val.m_point = go.transform.position;
			bool flag = TryApplyDamage(go, val);
			if (!flag)
			{
				Transform[] componentsInChildren = go.GetComponentsInChildren<Transform>(true);
				foreach (Transform val2 in componentsInChildren)
				{
					if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)(object)go))
					{
						HitData val3 = MakeHit(0f, 1000f);
						val3.m_toolTier = 99;
						val3.m_point = val2.position;
						if (TryApplyDamage(((Component)val2).gameObject, val3))
						{
							flag = true;
							break;
						}
					}
				}
			}
			if (!flag)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("No mining Damage(HitData) receiver found on " + ((Object)go).name));
				}
				ClearTarget();
			}
		}
	}
	internal sealed class SkeletonStatScaler : MonoBehaviour
	{
		private Character _character;

		private SummonedSkeleton _meta;

		internal void Initialize(SummonedSkeleton meta)
		{
			_meta = meta;
			_character = ((Component)this).GetComponent<Character>();
			if (!((Object)(object)_character == (Object)null) && !((Object)(object)_meta == (Object)null))
			{
				ApplyHealth();
			}
		}

		private void ApplyHealth()
		{
			float num = Mathf.Pow(2f, (float)Mathf.Max(0, _meta.StaffTier - 1));
			float num2 = 262.5f * num;
			MethodInfo method = typeof(Character).GetMethod("SetMaxHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null);
			if (method != null)
			{
				try
				{
					method.Invoke(_character, new object[1] { num2 });
				}
				catch
				{
				}
			}
			MethodInfo method2 = typeof(Character).GetMethod("SetHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null);
			if (method2 != null)
			{
				try
				{
					method2.Invoke(_character, new object[1] { num2 });
				}
				catch
				{
				}
			}
		}

		internal static float GetAttackMultiplier(SummonedSkeleton meta)
		{
			if ((Object)(object)meta == (Object)null)
			{
				return 1f;
			}
			return Mathf.Pow(2f, (float)Mathf.Max(0, meta.StaffTier - 1));
		}
	}
	internal sealed class TrollStatScaler : MonoBehaviour
	{
		private Character _character;

		internal float AttackMultiplier { get; private set; } = 1f;

		internal void Initialize(Vector3 baseScale, int staffTier, int quality)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			_character = ((Component)this).GetComponent<Character>();
			if (!((Object)(object)_character == (Object)null))
			{
				((Component)this).transform.localScale = baseScale * 1.2f;
				int num = Mathf.Clamp(staffTier, 1, 6);
				int num2 = Mathf.Clamp(quality, 1, 5);
				float tierMultiplier = GetTierMultiplier(num);
				float num3 = 1f + 0.25f * (float)(num2 - 1);
				float num4 = tierMultiplier * num3;
				float maxHealth = GetMaxHealth();
				_character.SetLevel(num + 1);
				float maxHealth2 = GetMaxHealth();
				float num5 = 1f;
				if (maxHealth > 0f && maxHealth2 > 0f)
				{
					num5 = maxHealth / maxHealth2;
				}
				if (maxHealth > 0f)
				{
					float num6 = maxHealth * num4;
					SetMaxHealth(num6);
					SetHealth(num6);
				}
				AttackMultiplier = num5 * num4;
			}
		}

		private float GetMaxHealth()
		{
			MethodInfo method = typeof(Character).GetMethod("GetMaxHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method == null)
			{
				return 0f;
			}
			try
			{
				object obj = method.Invoke(_character, null);
				if (obj is float)
				{
					return (float)obj;
				}
			}
			catch
			{
			}
			return 0f;
		}

		private void SetMaxHealth(float value)
		{
			MethodInfo method = typeof(Character).GetMethod("SetMaxHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null);
			if (method == null)
			{
				return;
			}
			try
			{
				method.Invoke(_character, new object[1] { value });
			}
			catch
			{
			}
		}

		private void SetHealth(float value)
		{
			MethodInfo method = typeof(Character).GetMethod("SetHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null);
			if (method == null)
			{
				return;
			}
			try
			{
				method.Invoke(_character, new object[1] { value });
			}
			catch
			{
			}
		}

		private static float GetTierMultiplier(int tier)
		{
			return Mathf.Clamp(tier, 1, 6) switch
			{
				1 => 2f, 
				2 => 2.9f, 
				3 => 4.2f, 
				4 => 6.1f, 
				5 => 8.84f, 
				6 => 12.8f, 
				_ => 1f, 
			};
		}
	}
	internal sealed class WoodcutWorkerAI : WorkerBase
	{
		protected override GameObject FindTarget()
		{
			GameObject best = null;
			float bestDist = float.MaxValue;
			TreeBase[] array = Object.FindObjectsByType<TreeBase>((FindObjectsSortMode)0);
			foreach (TreeBase val in array)
			{
				Consider(((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null, ref best, ref bestDist);
			}
			TreeLog[] array2 = Object.FindObjectsByType<TreeLog>((FindObjectsSortMode)0);
			foreach (TreeLog val2 in array2)
			{
				Consider(((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null, ref best, ref bestDist);
			}
			Destructible[] array3 = Object.FindObjectsByType<Destructible>((FindObjectsSortMode)0);
			foreach (Destructible val3 in array3)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					string text = ((Object)((Component)val3).gameObject).name.ToLowerInvariant();
					if (text.Contains("stump") || text.Contains("tree") || text.Contains("log"))
					{
						Consider(((Component)val3).gameObject, ref best, ref bestDist);
					}
				}
			}
			return best;
		}

		private void Consider(GameObject go, ref GameObject best, ref float bestDist)
		{
			//IL_001d: 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_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)go == (Object)null) && go.activeInHierarchy && Meta.InWorkArea(go.transform.position))
			{
				float num = Vector3.SqrMagnitude(((Component)this).transform.position - go.transform.position);
				if (num < bestDist)
				{
					bestDist = num;
					best = go;
				}
			}
		}

		protected override bool IsTargetStillValid(GameObject go)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go != (Object)null && go.activeInHierarchy)
			{
				return Meta.InWorkArea(go.transform.position);
			}
			return false;
		}

		protected override void PerformWork(GameObject go)
		{
			//IL_002d: 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)
			if ((Object)(object)go == (Object)null)
			{
				ClearTarget();
				return;
			}
			HitData val = MakeHit(Plugin.WorkDamage.Value, 0f);
			val.m_point = go.transform.position;
			if (!TryApplyDamage(go, val))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("No woodcut Damage(HitData) receiver found on " + ((Object)go).name));
				}
				ClearTarget();
			}
		}
	}
	internal abstract class WorkerBase : MonoBehaviour
	{
		protected SummonedGoblin Meta;

		protected MonsterAI AI;

		private bool _speedBoosted;

		protected Humanoid Humanoid;

		protected ZNetView NView;

		protected float NextSearch;

		protected float NextWork;

		protected GameObject Target;

		protected const float SearchInterval = 1.25f;

		protected const float WorkInterval = 1.1f;

		protected const float InteractionDistance = 2.25f;

		internal virtual void Initialize(SummonedGoblin meta)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			Meta = meta;
			AI = ((Component)this).GetComponent<MonsterAI>();
			Humanoid = ((Component)this).GetComponent<Humanoid>();
			NView = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)AI != (Object)null)
			{
				AI.m_alertRange = 0f;
				((BaseAI)AI).m_viewRange = 0f;
				((BaseAI)AI).m_hearRange = 0f;
			}
			Character component = ((Component)this).GetComponent<Character>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_group = "GT_WORKER";
				component.m_faction = (Faction)0;
			}
		}

		protected virtual void FixedUpdate()
		{
			//IL_0068: 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_009b: 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_00b9: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Meta == (Object)null || (Object)(object)AI == (Object)null || ((Object)(object)NView != (Object)null && NView.IsValid() && !NView.IsOwner()))
			{
				return;
			}
			if ((Object)(object)Target != (Object)null)
			{
				if (!Meta.InWorkArea(Target.transform.position))
				{
					ClearTarget();
				}
				else
				{
					MoveTowardTarget(Target);
					Vector3 position = Target.transform.position;
					position.y = ((Component)this).transform.position.y;
					((Component)this).transform.LookAt(position);
					if (Vector3.Distance(((Component)this).transform.position, Target.transform.position) <= 2.25f && Time.time >= NextWork)
					{
						NextWork = Time.time + 1.1f;
						PerformWork(Target);
					}
				}
			}
			if (((Object)(object)Target == (Object)null || !IsTargetStillValid(Target)) && Time.time >= NextSearch)
			{
				NextSearch = Time.time + 1.25f + Random.Range(0f, 0.35f);
				Target = FindTarget();
				MoveTowardTarget(Target);
			}
		}

		private void MoveTowardTarget(GameObject go)
		{
			//IL_001e: 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_00e1: 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)
			//IL_0099: 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)
			if ((Object)(object)go == (Object)null || (Object)(object)AI == (Object)null)
			{
				return;
			}
			Vector3 position = go.transform.position;
			MethodInfo methodInfo = AccessTools.Method(typeof(BaseAI), "MoveTo", new Type[4]
			{
				typeof(float),
				typeof(Vector3),
				typeof(float),
				typeof(bool)
			}, (Type[])null);
			if (methodInfo != null)
			{
				try
				{
					methodInfo.Invoke(AI, new object[4]
					{
						Time.fixedDeltaTime,
						position,
						1.8000001f,
						true
					});
					return;
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogError((object)("Worker MoveTo failed: " + ex.Message));
					}
				}
			}
			Vector3 val = position - ((Component)this).transform.position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
			{
				((Vector3)(ref val)).Normalize();
				((BaseAI)AI).MoveTowards(val, true);
			}
		}

		protected void ClearTarget()
		{
			Target = null;
			if ((Object)(object)AI != (Object)null)
			{
				AI.SetFollowTarget((GameObject)null);
			}
		}

		protected abstract GameObject FindTarget();

		protected abstract bool IsTargetStillValid(GameObject go);

		protected abstract void PerformWork(GameObject go);

		protected T FindClosestInRadius<T>() where T : Component
		{
			//IL_0059: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			T[] array = Object.FindObjectsByType<T>((FindObjectsSortMode)0);
			T result = default(T);
			float num = float.MaxValue;
			T[] array2 = array;
			foreach (T val in array2)
			{
				if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && Meta.InWorkArea(((Component)val).transform.position))
				{
					float num2 = Vector3.SqrMagnitude(((Component)this).transform.position - ((Component)val).transform.position);
					if (num2 < num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		protected bool TryApplyDamage(GameObject go, HitData hit)
		{
			if ((Object)(object)go == (Object)null || hit == null)
			{
				return false;
			}
			Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (TryInvokeDamage(componentsInChildren[i], hit))
				{
					return true;
				}
			}
			Transform parent = go.transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				componentsInChildren = ((Component)parent).GetComponents<Component>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if (TryInvokeDamage(componentsInChildren[i], hit))
					{
						return true;
					}
				}
				parent = parent.parent;
			}
			return false;
		}

		private static bool TryInvokeDamage(Component component, HitData hit)
		{
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			MethodInfo method = ((object)component).GetType().GetMethod("Damage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(HitData) }, null);
			if (method == null)
			{
				return false;
			}
			try
			{
				method.Invoke(component, new object[1] { hit });
				return true;
			}
			catch
			{
				return false;
			}
		}

		protected HitData MakeHit(float chop, float pickaxe)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_002d: 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)
			HitData val = new HitData();
			val.m_damage.m_chop = chop;
			val.m_damage.m_pickaxe = pickaxe;
			val.m_toolTier = 99;
			val.m_point = ((Component)this).transform.position;
			Humanoid component = ((Component)this).GetComponent<Humanoid>();
			if ((Object)(object)component != (Object)null)
			{
				val.SetAttacker((Character)(object)component);
			}
			return val;
		}
	}
}