Decompiled source of SparkleEngineerTweaks v1.11.0

plugins/SparkleEngineerTweaks.dll

Decompiled 10 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Engi.EngiMissilePainter;
using EntityStates.Engi.Mine;
using EntityStates.EngiTurret.EngiTurretWeapon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using R2API;
using RoR2;
using RoR2.CharacterAI;
using RoR2.Projectile;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SparkleEngineerTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SparkleEngineerTweaks")]
[assembly: AssemblyTitle("SparkleEngineerTweaks")]
[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 SparkleEngineerTweaks
{
	internal static class EngineerBubbleShieldArmor
	{
		private sealed class Shield
		{
			public GameObject gameObject;

			public float radius = -1f;

			public Transform center;
		}

		private static readonly string[] DeployedTypeNames = new string[2] { "EntityStates.Engi.EngiBubbleShield.Deployed", "EntityStates.Engi.EngiBubbleShield+Deployed" };

		private const string BubbleChildName = "Bubble";

		private const string CollisionChildName = "Collision";

		private const float FallbackRadius = 10f;

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _radius;

		private static ConfigEntry<float> _duration;

		private static ConfigEntry<float> _interval;

		private static readonly List<Shield> _shields = new List<Shield>();

		private static Type _deployedType;

		private static float _nextTick;

		private static bool _radiusLogged;

		private static bool _buffLogged;

		private static bool _registered;

		private static bool _errorLogged;

		private static bool Enabled
		{
			get
			{
				if (_enabled != null)
				{
					return _enabled.Value;
				}
				return true;
			}
		}

		private static float Radius
		{
			get
			{
				if (_radius == null)
				{
					return 0f;
				}
				return _radius.Value;
			}
		}

		private static float Duration
		{
			get
			{
				if (_duration == null)
				{
					return 0.5f;
				}
				return Mathf.Max(0.1f, _duration.Value);
			}
		}

		private static float Interval
		{
			get
			{
				if (_interval == null)
				{
					return 0.2f;
				}
				return Mathf.Clamp(_interval.Value, 0.05f, 2f);
			}
		}

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("位移技能.泡泡护盾", "BubbleShieldArmor", true, "是否给处在泡泡护盾里的友军(含工程师自己)+200 点护甲。用的是原版 ArmorBoost buff,走出护盾后短暂失效。");
			_radius = config.Bind<float>("位移技能.泡泡护盾", "Radius", 0f, "护盾判定半径(米):0 = 自动按护盾模型算(推荐)。");
			_duration = config.Bind<float>("位移技能.泡泡护盾", "BuffDuration", 0.5f, "每次续上的护甲 buff 时长(秒):走出护盾后大约这么多秒失效。");
			_interval = config.Bind<float>("位移技能.泡泡护盾", "CheckInterval", 0.2f, "多久检查一次谁在护盾里(秒)。");
		}

		internal static string Summary()
		{
			if (!Enabled)
			{
				return "";
			}
			return " [泡泡护盾:+200护甲]";
		}

		internal static void Patch(Harmony harmony)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			if (!Enabled)
			{
				Log((LogLevel)16, "泡泡护盾护甲:按配置保持原版,不挂补丁。");
				return;
			}
			Type type = null;
			for (int i = 0; i < DeployedTypeNames.Length; i++)
			{
				if (!(type == null))
				{
					break;
				}
				type = AccessTools.TypeByName(DeployedTypeNames[i]);
			}
			if (type == null)
			{
				Log((LogLevel)2, "泡泡护盾护甲补丁失败:找不到 " + string.Join(" / ", DeployedTypeNames) + "。");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "OnEnter", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log((LogLevel)2, "泡泡护盾护甲补丁失败:取不到 " + type.FullName + ".OnEnter。");
				return;
			}
			_deployedType = type;
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(EngineerBubbleShieldArmor), "DeployedOnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log((LogLevel)16, "补丁已挂载:" + type.FullName + ".OnEnter <- EngineerBubbleShieldArmor.DeployedOnEnterPostfix(护盾内友军 +200 护甲)");
		}

		private static void DeployedOnEnterPostfix(EntityState __instance)
		{
			try
			{
				if (__instance == null || (Object)(object)__instance.outer == (Object)null || (_deployedType != null && ((object)__instance).GetType() != _deployedType))
				{
					return;
				}
				GameObject gameObject = ((Component)__instance.outer).gameObject;
				if ((Object)(object)gameObject == (Object)null)
				{
					return;
				}
				for (int i = 0; i < _shields.Count; i++)
				{
					if (_shields[i].gameObject == gameObject)
					{
						return;
					}
				}
				_shields.Add(new Shield
				{
					gameObject = gameObject
				});
				if (!_registered)
				{
					_registered = true;
					Log((LogLevel)16, "泡泡护盾护甲:已登记一面护盾(" + ((Object)gameObject).name + "),开始给范围内的同队角色续 +200 护甲 buff。");
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "泡泡护盾护甲:登记护盾时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		internal static void Tick()
		{
			//IL_00b4: 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_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_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled || !NetworkServer.active)
			{
				return;
			}
			float time = Time.time;
			if (time < _nextTick)
			{
				return;
			}
			_nextTick = time + Interval;
			try
			{
				for (int num = _shields.Count - 1; num >= 0; num--)
				{
					if ((Object)(object)_shields[num].gameObject == (Object)null)
					{
						_shields.RemoveAt(num);
					}
				}
				if (_shields.Count == 0)
				{
					return;
				}
				BuffDef armorBoost = Buffs.ArmorBoost;
				if ((Object)(object)armorBoost == (Object)null)
				{
					return;
				}
				IList<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList;
				if (readOnlyInstancesList == null)
				{
					return;
				}
				for (int i = 0; i < _shields.Count; i++)
				{
					Shield shield = _shields[i];
					float num2 = RadiusOf(shield);
					Vector3 val = CenterOf(shield);
					TeamIndex val2 = TeamOf(shield);
					float num3 = num2 * num2;
					for (int j = 0; j < readOnlyInstancesList.Count; j++)
					{
						CharacterBody val3 = readOnlyInstancesList[j];
						if ((Object)(object)val3 == (Object)null || (Object)(object)val3.teamComponent == (Object)null || val3.teamComponent.teamIndex != val2 || (Object)(object)val3.healthComponent == (Object)null || !val3.healthComponent.alive)
						{
							continue;
						}
						Vector3 val4 = ((Component)val3).transform.position - val;
						if (((Vector3)(ref val4)).sqrMagnitude <= num3)
						{
							val3.AddTimedBuff(armorBoost, Duration);
							if (!_buffLogged)
							{
								_buffLogged = true;
								Log((LogLevel)16, "泡泡护盾护甲:已给护盾内的 " + val3.GetDisplayName() + " 挂上 +200 护甲 buff(" + ((Object)armorBoost).name + ",半径 " + num2.ToString("0.##") + " 米)。");
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "泡泡护盾护甲:异常(已忽略本帧)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static TeamIndex TeamOf(Shield shield)
		{
			//IL_0023: 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)
			GameObject gameObject = shield.gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return (TeamIndex)1;
			}
			TeamComponent component = gameObject.GetComponent<TeamComponent>();
			if ((Object)(object)component != (Object)null)
			{
				return component.teamIndex;
			}
			TeamFilter component2 = gameObject.GetComponent<TeamFilter>();
			if (!((Object)(object)component2 != (Object)null))
			{
				return (TeamIndex)1;
			}
			return component2.teamIndex;
		}

		private static Vector3 CenterOf(Shield shield)
		{
			//IL_0014: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)shield.center != (Object)null)
			{
				return shield.center.position;
			}
			if (!((Object)(object)shield.gameObject != (Object)null))
			{
				return Vector3.zero;
			}
			return shield.gameObject.transform.position;
		}

		private static float RadiusOf(Shield shield)
		{
			//IL_009c: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (shield.radius > 0f)
			{
				return shield.radius;
			}
			float radius = Radius;
			if (radius > 0f)
			{
				shield.radius = radius;
				return radius;
			}
			float num = 0f;
			if ((Object)(object)shield.gameObject != (Object)null)
			{
				ChildLocator componentInChildren = shield.gameObject.GetComponentInChildren<ChildLocator>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					Transform val = componentInChildren.FindChild("Bubble");
					if ((Object)(object)val == (Object)null)
					{
						val = componentInChildren.FindChild("Collision");
					}
					if ((Object)(object)val != (Object)null)
					{
						shield.center = val;
						Collider component = ((Component)val).GetComponent<Collider>();
						if ((Object)(object)component != (Object)null)
						{
							Bounds bounds = component.bounds;
							num = Mathf.Max(((Bounds)(ref bounds)).extents.x, Mathf.Max(((Bounds)(ref bounds)).extents.y, ((Bounds)(ref bounds)).extents.z));
						}
					}
				}
			}
			if (num > 0f)
			{
				shield.radius = num;
				if (!_radiusLogged)
				{
					_radiusLogged = true;
					Log((LogLevel)16, "泡泡护盾护甲:判定半径 " + num.ToString("0.##") + " 米(自动按护盾模型算,可用配置 Radius 覆盖)。");
				}
				return num;
			}
			return 10f;
		}

		private static void LogOnce(ref bool flag, LogLevel level, string message)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!flag)
			{
				flag = true;
				Log(level, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)message);
			}
		}
	}
	internal static class EngineerPressureMine
	{
		private const float VanillaDamagePercent = 900f;

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _damagePercent;

		private static ConfigEntry<bool> _noEarlyDetonation;

		private static readonly FieldInfo _targetFinderField = AccessTools.Field(typeof(WaitForTarget), "targetFinder");

		private static FieldInfo _lookRangeField;

		private static float _scaleBase = -1f;

		private static float _scaleLastWritten = float.MinValue;

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

		private static PropertyInfo _armingMachineProp;

		private static PropertyInfo _machineStateProp;

		private static bool _propsResolved;

		private static bool _damageLogged;

		private static bool _triggerLogged;

		private static bool _suppressLogged;

		private static bool _propsLogged;

		private static bool _detonateLogged;

		private static bool _errorLogged;

		private static bool Enabled
		{
			get
			{
				if (_enabled != null)
				{
					return _enabled.Value;
				}
				return true;
			}
		}

		private static float DamagePercent
		{
			get
			{
				if (_damagePercent == null)
				{
					return 900f;
				}
				return Mathf.Max(0f, _damagePercent.Value);
			}
		}

		private static bool NoEarlyDetonation
		{
			get
			{
				if (_noEarlyDetonation != null)
				{
					return _noEarlyDetonation.Value;
				}
				return true;
			}
		}

		private static float DamageRatio => DamagePercent / 900f;

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("副武器.压力地雷", "PressureMineTweaks", true, "是否启用压力地雷(M2)的两项调整:满蓄力伤害提到 1000%,以及蓄满之前不会被引爆。");
			_damagePercent = config.Bind<float>("副武器.压力地雷", "DamagePercent", 1000f, "满蓄力时地雷造成的伤害(百分比):原版是 900(投掷 300% × 满蓄力倍率 3)。只改满蓄力那一档,半蓄力仍是原来的 300%。");
			_noEarlyDetonation = config.Bind<bool>("副武器.压力地雷", "NoEarlyDetonation", true, "地雷在完全准备好(蓄满)之前不会被引爆:原版蓄力中的 3 秒里,敌人进到 4 米内就能把它引爆(只有 300% 伤害、爆炸半径还只有 0.2 倍)。");
		}

		internal static string Summary()
		{
			if (!Enabled)
			{
				return "";
			}
			string text = " [压力地雷:" + DamagePercent.ToString("0") + "%";
			if (NoEarlyDetonation)
			{
				text += " 蓄满前不炸";
			}
			return text + "]";
		}

		internal static void Patch(Harmony harmony)
		{
			if (!Enabled)
			{
				Log((LogLevel)16, "压力地雷:按配置保持原版,不挂补丁。");
				return;
			}
			SafePatch(harmony, typeof(BaseMineArmingState), "OnEnter", "蓄力状态", "ArmingOnEnterPostfix", prefix: false);
			SafePatch(harmony, typeof(Detonate), "OnEnter", "引爆(只打日志)", "DetonateOnEnterPostfix", prefix: false);
			if (NoEarlyDetonation)
			{
				SafePatch(harmony, typeof(WaitForTarget), "OnEnter", "等目标状态", "WaitForTargetOnEnterPostfix", prefix: false);
				SafePatch(harmony, typeof(WaitForTarget), "FixedUpdate", "等目标状态每帧", "WaitForTargetFixedUpdatePrefix", prefix: true);
			}
		}

		private static void SafePatch(Harmony harmony, Type stateType, string methodName, string label, string patchName, bool prefix)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(stateType, methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log((LogLevel)2, "压力地雷补丁失败:取不到 " + stateType.Name + "." + methodName + "。");
				return;
			}
			HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(EngineerPressureMine), patchName, (Type[])null, (Type[])null));
			if (prefix)
			{
				harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Log((LogLevel)16, "补丁已挂载:" + stateType.Name + "." + methodName + " <- EngineerPressureMine." + patchName + "(" + label + ")");
		}

		private static void ArmingOnEnterPostfix(BaseMineArmingState __instance)
		{
			try
			{
				if (__instance != null)
				{
					bool flag = __instance is MineArmingFull;
					TrackFullState(__instance, flag);
					if (flag)
					{
						ApplyDamageScale(__instance);
					}
					else
					{
						ApplyNoEarlyTrigger(__instance);
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "压力地雷:改蓄力状态时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void TrackFullState(BaseMineArmingState state, bool full)
		{
			if ((Object)(object)((EntityState)state).outer == (Object)null)
			{
				return;
			}
			GameObject gameObject = ((Component)((EntityState)state).outer).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)gameObject).GetInstanceID();
			if (full)
			{
				if (_fullyArmed.Count > 256)
				{
					_fullyArmed.Clear();
				}
				_fullyArmed.Add(instanceID);
			}
			else
			{
				_fullyArmed.Remove(instanceID);
			}
		}

		private static void ApplyDamageScale(BaseMineArmingState state)
		{
			float damageRatio = DamageRatio;
			if (Mathf.Abs(damageRatio - 1f) < 0.0001f)
			{
				return;
			}
			float damageScale = state.damageScale;
			if (damageScale <= 0f)
			{
				return;
			}
			if (Mathf.Abs(damageScale - _scaleLastWritten) > 0.0001f)
			{
				_scaleBase = damageScale;
			}
			float num = _scaleBase * damageRatio;
			if (!(Mathf.Abs(damageScale - num) <= 0.0001f))
			{
				state.damageScale = num;
				_scaleLastWritten = num;
				if (!_damageLogged)
				{
					_damageLogged = true;
					Log((LogLevel)16, "压力地雷:满蓄力伤害倍率 " + _scaleBase.ToString("0.###") + " → " + num.ToString("0.###") + "(投掷 300% × 倍率 → 合计 " + (300f * num).ToString("0.#") + "%);半蓄力档不受影响。");
				}
			}
		}

		private static void ApplyNoEarlyTrigger(BaseMineArmingState state)
		{
			if (NoEarlyDetonation && state.triggerRadius != 0f)
			{
				state.triggerRadius = 0f;
				if (!_triggerLogged)
				{
					_triggerLogged = true;
					Log((LogLevel)16, "压力地雷:未蓄满的档位触发半径已归零(索敌器关闭 → 完全准备好之前不会引爆)。");
				}
			}
		}

		private static void WaitForTargetOnEnterPostfix(WaitForTarget __instance)
		{
			try
			{
				if (__instance == null || IsFullyArmed(__instance))
				{
					return;
				}
				Suppress(__instance);
				if (!(_targetFinderField != null))
				{
					return;
				}
				object? value = _targetFinderField.GetValue(__instance);
				Behaviour val = (Behaviour)((value is Behaviour) ? value : null);
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = false;
					if (_lookRangeField == null)
					{
						_lookRangeField = AccessTools.Field(((object)val).GetType(), "lookRange");
					}
					if (_lookRangeField != null)
					{
						_lookRangeField.SetValue(val, 0f);
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "压力地雷:关闭索敌器时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void WaitForTargetFixedUpdatePrefix(WaitForTarget __instance)
		{
			try
			{
				if (__instance != null && !IsFullyArmed(__instance))
				{
					Suppress(__instance);
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "压力地雷:屏蔽索敌时异常(已忽略本帧)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static bool IsFullyArmed(WaitForTarget state)
		{
			if ((Object)(object)((EntityState)state).outer != (Object)null && (Object)(object)((Component)((EntityState)state).outer).gameObject != (Object)null && _fullyArmed.Contains(((Object)((Component)((EntityState)state).outer).gameObject).GetInstanceID()))
			{
				return true;
			}
			return CurrentArmingState(state) is MineArmingFull;
		}

		private static object CurrentArmingState(object mineState)
		{
			ResolveProps();
			if (_armingMachineProp == null || _machineStateProp == null)
			{
				return null;
			}
			object value = _armingMachineProp.GetValue(mineState, null);
			if (value == null)
			{
				return null;
			}
			return _machineStateProp.GetValue(value, null);
		}

		private static void ResolveProps()
		{
			if (!_propsResolved)
			{
				_propsResolved = true;
				_armingMachineProp = typeof(BaseMineState).GetProperty("armingStateMachine", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_machineStateProp = typeof(EntityStateMachine).GetProperty("state", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (_armingMachineProp == null || _machineStateProp == null)
				{
					LogOnce(ref _propsLogged, (LogLevel)4, "压力地雷:取不到蓄力状态机的反射入口,将只靠「是否记录过蓄满」判定。");
				}
			}
		}

		private static void Suppress(WaitForTarget state)
		{
			if ((Object)(object)((EntityState)state).outer == (Object)null)
			{
				return;
			}
			GameObject gameObject = ((Component)((EntityState)state).outer).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return;
			}
			ProjectileSphereTargetFinder[] componentsInChildren = gameObject.GetComponentsInChildren<ProjectileSphereTargetFinder>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (!((Object)(object)componentsInChildren[i] == (Object)null))
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
					componentsInChildren[i].lookRange = 0f;
				}
			}
			ProjectileTargetComponent component = gameObject.GetComponent<ProjectileTargetComponent>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.target != (Object)null)
			{
				component.target = null;
			}
			if (!_suppressLogged)
			{
				_suppressLogged = true;
				Log((LogLevel)16, "压力地雷:蓄满前屏蔽索敌(清掉已锁定的目标 + 关闭 " + componentsInChildren.Length + " 个索敌器)→ 只会在完全准备好之后引爆。");
			}
		}

		private static void DetonateOnEnterPostfix(Detonate __instance)
		{
			try
			{
				if (__instance != null && !_detonateLogged)
				{
					object obj = CurrentArmingState(__instance);
					string text = ((obj != null) ? obj.GetType().Name : "未知");
					float num = -1f;
					BaseMineArmingState val = (BaseMineArmingState)((obj is BaseMineArmingState) ? obj : null);
					if (val != null)
					{
						num = val.damageScale;
					}
					_detonateLogged = true;
					Log((LogLevel)16, "压力地雷:引爆时蓄力档 = " + text + ",伤害倍率 = " + num.ToString("0.###") + "(合计约 " + (300f * Mathf.Max(0f, num)).ToString("0.#") + "%)。");
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "压力地雷:引爆日志异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void LogOnce(ref bool flag, LogLevel level, string message)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!flag)
			{
				flag = true;
				Log(level, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)message);
			}
		}
	}
	internal static class EngineerShoulderHarpoons
	{
		private const string TurretBodyName = "EngiWalkerTurretBody";

		private const string HarpoonPrefabName = "EngiHarpoon";

		private const float BeamDisabledCooldown = 99999f;

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _interval;

		private static ConfigEntry<float> _damagePercent;

		private static ConfigEntry<bool> _disableBeam;

		private static ConfigEntry<float> _attackSpeedScale;

		private static readonly Type _fireStateType = typeof(Fire);

		private static readonly FieldInfo _prefabField = AccessTools.Field(_fireStateType, "projectilePrefab");

		private static readonly FieldInfo _muzzleField = AccessTools.Field(_fireStateType, "muzzleflashEffectPrefab");

		private static GameObject _projectilePrefab;

		private static GameObject _muzzleEffect;

		private static Type _aiOwnershipType;

		private static FieldInfo _aiOwnerMasterField;

		private static Type _minionOwnershipType;

		private static PropertyInfo _minionOwnerMasterProp;

		private static readonly Dictionary<int, float> _timers = new Dictionary<int, float>();

		private static readonly List<int> _present = new List<int>();

		private static float _pruneTimer;

		private static bool _indexResolved;

		private static BodyIndex _turretBodyIndex;

		private static bool _missingLogged;

		private static bool _errorLogged;

		private static bool _prefabLogged;

		private static bool _beamLogged;

		private static bool _firstFireLogged;

		private static bool _clientLogged;

		private static bool _ownerMissingLogged;

		private static bool Enabled
		{
			get
			{
				if (_enabled != null)
				{
					return _enabled.Value;
				}
				return true;
			}
		}

		private static float Interval
		{
			get
			{
				if (_interval == null)
				{
					return 3f;
				}
				return Mathf.Max(0.05f, _interval.Value);
			}
		}

		private static float DamagePercent
		{
			get
			{
				if (_damagePercent == null)
				{
					return 500f;
				}
				return _damagePercent.Value;
			}
		}

		private static bool DisableBeam
		{
			get
			{
				if (_disableBeam != null)
				{
					return _disableBeam.Value;
				}
				return true;
			}
		}

		private static float AttackSpeedScale
		{
			get
			{
				if (_attackSpeedScale == null)
				{
					return 0.5f;
				}
				return Mathf.Max(0f, _attackSpeedScale.Value);
			}
		}

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("特殊技能.移动炮台.鱼叉", "HarpoonWeapon", true, "是否把移动炮台的主武器换成热鱼叉(Thermal Harpoons)导弹。");
			_interval = config.Bind<float>("特殊技能.移动炮台.鱼叉", "Interval", 3f, "开火间隔(秒):每隔这么久朝当前目标打一发。");
			_damagePercent = config.Bind<float>("特殊技能.移动炮台.鱼叉", "DamagePercent", 500f, "鱼叉伤害倍率(百分比):500 = 500% 攻击力。原版工程师的热鱼叉正好也是 500%/发。");
			_disableBeam = config.Bind<bool>("特殊技能.移动炮台.鱼叉", "DisableOriginalBeam", true, "是否停用移动炮台原来的激光主武器(把它的冷却顶到走不完)。");
			_attackSpeedScale = config.Bind<float>("特殊技能.移动炮台.鱼叉", "AttackSpeedScale", 0.5f, "开火频率受攻击速度加成的比例:实际间隔 = 间隔 ÷ (1 + (攻击速度 - 1) × 这个值)。 1 = 完全跟随攻击速度;0.5 = 只吃一半(+200% 攻击速度实际只当 +100% 用,3 秒一发变成 1.5 秒一发);0 = 完全不受攻击速度影响。");
			_aiOwnershipType = AccessTools.TypeByName("RoR2.CharacterAI.AIOwnership");
			if (_aiOwnershipType != null)
			{
				_aiOwnerMasterField = AccessTools.Field(_aiOwnershipType, "ownerMaster");
			}
			_minionOwnershipType = AccessTools.TypeByName("RoR2.MinionOwnership");
			if (_minionOwnershipType != null)
			{
				_minionOwnerMasterProp = AccessTools.Property(_minionOwnershipType, "ownerMaster");
			}
			if (_prefabField == null && !_missingLogged)
			{
				_missingLogged = true;
				Log((LogLevel)4, "肩炮鱼叉:取不到 EngiMissilePainter.Fire.projectilePrefab,会改用 ProjectileCatalog 找 EngiHarpoon。");
			}
		}

		internal static string Summary()
		{
			if (!Enabled)
			{
				return "";
			}
			string text = ((AttackSpeedScale > 0f) ? (" 射速受攻速影响×" + AttackSpeedScale.ToString("0.##")) : "");
			return " [主武器:热鱼叉 " + Interval.ToString("0.##") + "s / " + DamagePercent.ToString("0") + "%" + text + "]";
		}

		internal static void Tick()
		{
			if (!Enabled)
			{
				return;
			}
			try
			{
				if (ResolveIndex())
				{
					ResolveProjectile();
					if (!NetworkServer.active)
					{
						LogOnce(ref _clientLogged, (LogLevel)16, "肩炮鱼叉:当前不是服务端(联机客户端),开火交给主机处理。");
						return;
					}
					_present.Clear();
					ScanAndFire();
					Prune(Time.deltaTime);
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "肩炮鱼叉:逻辑异常(已忽略本帧)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static bool ResolveIndex()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_001a: 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)
			if (_indexResolved)
			{
				return true;
			}
			BodyIndex val = BodyCatalog.FindBodyIndex("EngiWalkerTurretBody");
			if ((int)val == -1)
			{
				return false;
			}
			_turretBodyIndex = val;
			_indexResolved = true;
			return true;
		}

		private static void ResolveProjectile()
		{
			if ((Object)(object)_projectilePrefab != (Object)null)
			{
				return;
			}
			if (_prefabField != null)
			{
				object? value = _prefabField.GetValue(null);
				_projectilePrefab = (GameObject)((value is GameObject) ? value : null);
			}
			if ((Object)(object)_projectilePrefab == (Object)null)
			{
				int num = ProjectileCatalog.FindProjectileIndex("EngiHarpoon");
				if (num >= 0)
				{
					_projectilePrefab = ProjectileCatalog.GetProjectilePrefab(num);
				}
			}
			if (!((Object)(object)_projectilePrefab == (Object)null))
			{
				if (_muzzleField != null)
				{
					object? value2 = _muzzleField.GetValue(null);
					_muzzleEffect = (GameObject)((value2 is GameObject) ? value2 : null);
				}
				if (!_prefabLogged)
				{
					_prefabLogged = true;
					Log((LogLevel)16, "肩炮鱼叉:已拿到热鱼叉射弹(" + ((Object)_projectilePrefab).name + ")" + (((Object)(object)_muzzleEffect != (Object)null) ? (",枪口火焰 " + ((Object)_muzzleEffect).name) : "") + "。");
				}
			}
		}

		private static void ScanAndFire()
		{
			//IL_0029: 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)
			IList<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList;
			if (readOnlyInstancesList == null)
			{
				return;
			}
			float deltaTime = Time.deltaTime;
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				CharacterBody val = readOnlyInstancesList[i];
				if ((Object)(object)val == (Object)null || val.bodyIndex != _turretBodyIndex)
				{
					continue;
				}
				int instanceID = ((Object)val).GetInstanceID();
				_present.Add(instanceID);
				DisableBeamNow(val);
				if (!((Object)(object)_projectilePrefab == (Object)null))
				{
					if (!_timers.TryGetValue(instanceID, out var value))
					{
						value = 0f;
					}
					value -= deltaTime;
					if (value <= 0f)
					{
						value = (Fire(val) ? IntervalFor(val) : 0f);
					}
					_timers[instanceID] = value;
				}
			}
		}

		private static float IntervalFor(CharacterBody turret)
		{
			float attackSpeedScale = AttackSpeedScale;
			if (attackSpeedScale <= 0f)
			{
				return Interval;
			}
			float num = 1f + (AttackSpeedOf(turret) - 1f) * attackSpeedScale;
			if (num < 0.1f)
			{
				num = 0.1f;
			}
			return Mathf.Max(0.05f, Interval / num);
		}

		private static float AttackSpeedOf(CharacterBody turret)
		{
			CharacterMaster master = turret.master;
			CharacterMaster val = (((Object)(object)master != (Object)null) ? OwnerMasterOf(master) : null);
			CharacterBody val2 = (((Object)(object)val != (Object)null) ? val.GetBody() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.attackSpeed;
			}
			LogOnce(ref _ownerMissingLogged, (LogLevel)16, "肩炮鱼叉:找不到炮台的主人,攻击速度改用炮台自己的数值(射速加成可能不生效)。");
			return turret.attackSpeed;
		}

		private static CharacterMaster OwnerMasterOf(CharacterMaster turretMaster)
		{
			if ((Object)(object)turretMaster == (Object)null)
			{
				return null;
			}
			if (_aiOwnershipType != null && _aiOwnerMasterField != null)
			{
				Component component = ((Component)turretMaster).GetComponent(_aiOwnershipType);
				if ((Object)(object)component != (Object)null)
				{
					object? value = _aiOwnerMasterField.GetValue(component);
					CharacterMaster val = (CharacterMaster)((value is CharacterMaster) ? value : null);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			if (_minionOwnershipType != null && _minionOwnerMasterProp != null)
			{
				Component component2 = ((Component)turretMaster).GetComponent(_minionOwnershipType);
				if ((Object)(object)component2 != (Object)null)
				{
					object? value2 = _minionOwnerMasterProp.GetValue(component2, null);
					CharacterMaster val2 = (CharacterMaster)((value2 is CharacterMaster) ? value2 : null);
					if ((Object)(object)val2 != (Object)null)
					{
						return val2;
					}
				}
			}
			return null;
		}

		internal static void DisableBeamNow(CharacterBody body)
		{
			if (!DisableBeam || (Object)(object)body == (Object)null)
			{
				return;
			}
			SkillLocator skillLocator = body.skillLocator;
			GenericSkill val = (((Object)(object)skillLocator != (Object)null) ? skillLocator.primary : null);
			SkillDef val2 = (((Object)(object)val != (Object)null) ? val.skillDef : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			if (val2.baseRechargeInterval != 99999f)
			{
				float baseRechargeInterval = val2.baseRechargeInterval;
				val2.baseRechargeInterval = 99999f;
				val.RecalculateValues();
				if (!_beamLogged)
				{
					_beamLogged = true;
					Log((LogLevel)16, "肩炮鱼叉:已停用移动炮台的激光主武器(" + ((Object)val2).name + ",冷却 " + baseRechargeInterval.ToString("0.##") + " → " + 99999f.ToString("0") + " 秒)。");
				}
			}
			if (val.stock > 0)
			{
				val.stock = 0;
			}
		}

		private static bool Fire(CharacterBody body)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			CharacterMaster master = body.master;
			BaseAI val = (((Object)(object)master != (Object)null) ? ((Component)master).GetComponent<BaseAI>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Target currentEnemy = val.currentEnemy;
			if (currentEnemy == null || (Object)(object)currentEnemy.gameObject == (Object)null)
			{
				return false;
			}
			Vector3 val2 = (((Object)(object)body.inputBank != (Object)null) ? body.inputBank.aimOrigin : ((Component)body).transform.position);
			Vector3 position = default(Vector3);
			if (!currentEnemy.GetBullseyePosition(ref position))
			{
				position = currentEnemy.gameObject.transform.position;
			}
			Vector3 val3 = position - val2;
			if (((Vector3)(ref val3)).sqrMagnitude < 0.25f)
			{
				return false;
			}
			((Vector3)(ref val3)).Normalize();
			if ((Object)(object)_muzzleEffect != (Object)null)
			{
				EffectManager.SimpleEffect(_muzzleEffect, val2, Util.QuaternionSafeLookRotation(val3), true);
			}
			float num = body.damage * (DamagePercent / 100f);
			bool flag = Util.CheckRoll(body.crit, master);
			MissileUtils.FireMissile(val2, body, default(ProcChainMask), currentEnemy.gameObject, num, flag, _projectilePrefab, (DamageColorIndex)0, Vector3.up, 0f, false);
			if (!_firstFireLogged)
			{
				_firstFireLogged = true;
				CharacterMaster val4 = (((Object)(object)body.master != (Object)null) ? OwnerMasterOf(body.master) : null);
				CharacterBody val5 = (((Object)(object)val4 != (Object)null) ? val4.GetBody() : null);
				Log((LogLevel)16, "肩炮鱼叉:第一发已打出 —— 伤害 " + num.ToString("0.##") + "(" + DamagePercent.ToString("0") + "% × 攻击力 " + body.damage.ToString("0.##") + "),基础间隔 " + Interval.ToString("0.##") + " 秒,实际间隔 " + IntervalFor(body).ToString("0.##") + " 秒。攻击速度:炮台自身 " + body.attackSpeed.ToString("0.##") + (((Object)(object)val5 != (Object)null) ? (",主人 " + val5.attackSpeed.ToString("0.##")) : "(未找到主人)") + ",生效比例 " + AttackSpeedScale.ToString("0.##") + "。");
			}
			return true;
		}

		private static void Prune(float delta)
		{
			_pruneTimer -= delta;
			if (_pruneTimer > 0f)
			{
				return;
			}
			_pruneTimer = 5f;
			List<int> list = new List<int>();
			foreach (int key in _timers.Keys)
			{
				if (!_present.Contains(key))
				{
					list.Add(key);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				_timers.Remove(list[i]);
			}
		}

		private static void LogOnce(ref bool flag, LogLevel level, string message)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!flag)
			{
				flag = true;
				Log(level, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)message);
			}
		}
	}
	internal static class EngineerShoulderTurrets
	{
		internal sealed class Attachment
		{
			public CharacterBody turret;

			public CharacterBody owner;

			public int slot;

			public Collider[] disabledColliders = EmptyColliders;

			public CharacterDirection disabledDirection;
		}

		private const string TurretBodyName = "EngiWalkerTurretBody";

		private const string EngineerBodyName = "EngiBody";

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _sideOffset;

		private static ConfigEntry<float> _heightOffset;

		private static ConfigEntry<float> _tiltAngle;

		private static ConfigEntry<float> _forwardOffset;

		private static ConfigEntry<float> _scale;

		private static ConfigEntry<float> _fallbackRadius;

		private static readonly List<Attachment> _attached = new List<Attachment>();

		private static readonly Dictionary<CharacterBody, int> _slotCounter = new Dictionary<CharacterBody, int>();

		private static bool _indicesResolved;

		private static BodyIndex _turretBodyIndex;

		private static BodyIndex _engineerBodyIndex;

		private static Type _aiOwnershipType;

		private static FieldInfo _aiOwnerMasterField;

		private static bool _catalogLogged;

		private static bool _firstAttachLogged;

		private static bool _failedLogged;

		private static readonly Collider[] EmptyColliders = (Collider[])(object)new Collider[0];

		internal static List<Attachment> Attached => _attached;

		private static bool Enabled
		{
			get
			{
				if (_enabled != null)
				{
					return _enabled.Value;
				}
				return true;
			}
		}

		private static float Side
		{
			get
			{
				if (_sideOffset == null)
				{
					return 0.85f;
				}
				return _sideOffset.Value;
			}
		}

		private static float Height
		{
			get
			{
				if (_heightOffset == null)
				{
					return 0.5f;
				}
				return _heightOffset.Value;
			}
		}

		private static float Tilt
		{
			get
			{
				if (_tiltAngle == null)
				{
					return 90f;
				}
				return _tiltAngle.Value;
			}
		}

		private static float Forward
		{
			get
			{
				if (_forwardOffset == null)
				{
					return 0f;
				}
				return _forwardOffset.Value;
			}
		}

		private static float Scale
		{
			get
			{
				if (_scale == null)
				{
					return 0.5f;
				}
				return Mathf.Max(0.05f, _scale.Value);
			}
		}

		private static float FallbackRadius
		{
			get
			{
				if (_fallbackRadius == null)
				{
					return 12f;
				}
				return _fallbackRadius.Value;
			}
		}

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("特殊技能.移动炮台", "ShoulderMount", true, "替代 R「移动炮台」生成的炮台是否吸附在工程师的两肩上(true),而不是在地上自由行走(false)。");
			_sideOffset = config.Bind<float>("特殊技能.移动炮台", "SideOffset", 0.85f, "肩部横向偏移:炮台中心离工程师中轴左右各多远。炮台是横躺的(长 2.0 × 缩放 0.5 = 1.0),中心离中轴太近的话内侧会插进工程师身体里(工程师半径 0.5)。");
			_heightOffset = config.Bind<float>("特殊技能.移动炮台", "HeightOffset", 0.5f, "肩部高度:以工程师身体根节点(胶囊中心,脚底往上约 0.91)为 0 点往上多少。0 = 和身体中心齐平(约胸口),1.5 = 头顶上方。");
			_tiltAngle = config.Bind<float>("特殊技能.移动炮台", "TiltAngle", 90f, "炮台的侧翻角度(度):绕它自己的前后轴翻转,让炮台横躺在肩上、头顶朝外,而不是竖直站在地上。0 = 站着(原版),90 = 完全横躺(右肩的向右倒、左肩的向左倒)。");
			_forwardOffset = config.Bind<float>("特殊技能.移动炮台", "ForwardOffset", 0f, "肩部前后偏移:正数朝工程师正面,负数朝背面。");
			_scale = config.Bind<float>("特殊技能.移动炮台", "Scale", 0.5f, "炮台缩放:1 = 原版大小(比工程师还高,架在肩上会很夸张)。");
			_fallbackRadius = config.Bind<float>("特殊技能.移动炮台", "OwnerSearchRadius", 12f, "兜底归属判定半径(米):读不到 AIOwnership 时(例如联机客户端),在这个半径内找最近的工程师当主人。小于 0 = 不做兜底。");
			try
			{
				_aiOwnershipType = AccessTools.TypeByName("RoR2.CharacterAI.AIOwnership");
				if (_aiOwnershipType != null)
				{
					_aiOwnerMasterField = AccessTools.Field(_aiOwnershipType, "ownerMaster");
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "移动炮台:取 AIOwnership 类型失败(只影响归属判定精度)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		internal static string Summary()
		{
			if (!Enabled)
			{
				return " [移动炮台:原样在地上走]";
			}
			return " [移动炮台:吸附双肩 侧" + Side.ToString("0.##") + " 高" + Height.ToString("0.##") + " 缩放" + Scale.ToString("0.##") + "]";
		}

		internal static void Tick()
		{
			if (!Enabled)
			{
				return;
			}
			try
			{
				if (ResolveBodyIndices())
				{
					Prune();
					ScanForNew();
					AssignSlots();
					UpdateAll();
				}
			}
			catch (Exception ex)
			{
				if (!_failedLogged)
				{
					_failedLogged = true;
					Log((LogLevel)4, "移动炮台:肩挂逻辑异常(已忽略本帧)—— " + ex.GetType().Name + " " + ex.Message);
				}
			}
		}

		private unsafe static bool ResolveBodyIndices()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (_indicesResolved)
			{
				return true;
			}
			BodyIndex val = BodyCatalog.FindBodyIndex("EngiWalkerTurretBody");
			BodyIndex val2 = BodyCatalog.FindBodyIndex("EngiBody");
			if ((int)val == -1 || (int)val2 == -1)
			{
				return false;
			}
			_turretBodyIndex = val;
			_engineerBodyIndex = val2;
			_indicesResolved = true;
			if (!_catalogLogged)
			{
				_catalogLogged = true;
				Log((LogLevel)16, "移动炮台:bodyIndex 已解析 —— EngiWalkerTurretBody=" + ((object)(*(BodyIndex*)(&val))/*cast due to .constrained prefix*/).ToString() + ",EngiBody=" + ((object)(*(BodyIndex*)(&val2))/*cast due to .constrained prefix*/).ToString());
			}
			return true;
		}

		private static void Prune()
		{
			for (int num = _attached.Count - 1; num >= 0; num--)
			{
				Attachment attachment = _attached[num];
				if ((Object)(object)attachment.turret == (Object)null)
				{
					_attached.RemoveAt(num);
				}
				else if ((Object)(object)attachment.owner == (Object)null || (Object)(object)attachment.owner.healthComponent == (Object)null || !attachment.owner.healthComponent.alive)
				{
					Restore(attachment);
					_attached.RemoveAt(num);
				}
				else
				{
					HealthComponent healthComponent = attachment.turret.healthComponent;
					if ((Object)(object)healthComponent != (Object)null && !healthComponent.alive)
					{
						Restore(attachment);
						_attached.RemoveAt(num);
					}
				}
			}
		}

		private static void AssignSlots()
		{
			Dictionary<CharacterBody, int> slotCounter = _slotCounter;
			slotCounter.Clear();
			for (int i = 0; i < _attached.Count; i++)
			{
				Attachment attachment = _attached[i];
				if (!((Object)(object)attachment.owner == (Object)null))
				{
					if (!slotCounter.TryGetValue(attachment.owner, out var value))
					{
						value = 0;
					}
					attachment.slot = value % 2;
					slotCounter[attachment.owner] = value + 1;
				}
			}
		}

		private static void UpdateAll()
		{
			for (int i = 0; i < _attached.Count; i++)
			{
				Attachment attachment = _attached[i];
				Rigidbody component = ((Component)attachment.turret).GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null && !component.isKinematic)
				{
					Mount(attachment);
				}
				CharacterDirection component2 = ((Component)attachment.turret).GetComponent<CharacterDirection>();
				if ((Object)(object)component2 != (Object)null && ((Behaviour)component2).enabled)
				{
					((Behaviour)component2).enabled = false;
					attachment.disabledDirection = component2;
				}
				Follow(attachment);
			}
		}

		internal static void Forget(CharacterBody turret)
		{
			if ((Object)(object)turret == (Object)null)
			{
				return;
			}
			for (int num = _attached.Count - 1; num >= 0; num--)
			{
				if (_attached[num].turret == turret)
				{
					_attached.RemoveAt(num);
				}
			}
		}

		private static void ScanForNew()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			List<Attachment> list = new List<Attachment>();
			IList<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList;
			if (readOnlyInstancesList == null)
			{
				return;
			}
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				CharacterBody val = readOnlyInstancesList[i];
				if (!((Object)(object)val == (Object)null) && val.bodyIndex == _turretBodyIndex && !IsTracked(val))
				{
					CharacterBody val2 = FindOwner(val);
					if (!((Object)(object)val2 == (Object)null))
					{
						Attachment item = new Attachment
						{
							turret = val,
							owner = val2,
							slot = -1
						};
						_attached.Add(item);
						list.Add(item);
					}
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			AssignSlots();
			for (int j = 0; j < list.Count; j++)
			{
				Attachment attachment = list[j];
				Mount(attachment);
				Follow(attachment);
				if (!_firstAttachLogged)
				{
					_firstAttachLogged = true;
					Log((LogLevel)16, "移动炮台:已把炮台吸到工程师肩上(槽位 " + attachment.slot + ",横向 " + Side.ToString("0.##") + " / 高度 " + Height.ToString("0.##") + " / 前后 " + Forward.ToString("0.##") + " / 侧翻 " + Tilt.ToString("0") + ",缩放 " + Scale.ToString("0.##") + ")。");
				}
				else
				{
					Log((LogLevel)32, "移动炮台:新炮台挂到槽位 " + attachment.slot + "。");
				}
			}
		}

		private static bool IsTracked(CharacterBody turret)
		{
			for (int i = 0; i < _attached.Count; i++)
			{
				if (_attached[i].turret == turret)
				{
					return true;
				}
			}
			return false;
		}

		private static void Mount(Attachment a)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody turret = a.turret;
			CharacterMotor component = ((Component)turret).GetComponent<CharacterMotor>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			Rigidbody component2 = ((Component)turret).GetComponent<Rigidbody>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.velocity = Vector3.zero;
				component2.angularVelocity = Vector3.zero;
				component2.isKinematic = true;
			}
			CharacterDirection component3 = ((Component)turret).GetComponent<CharacterDirection>();
			if ((Object)(object)component3 != (Object)null && ((Behaviour)component3).enabled)
			{
				((Behaviour)component3).enabled = false;
				a.disabledDirection = component3;
			}
			Collider[] components = ((Component)turret).GetComponents<Collider>();
			if (components != null && components.Length != 0)
			{
				List<Collider> list = new List<Collider>();
				for (int i = 0; i < components.Length; i++)
				{
					if ((Object)(object)components[i] != (Object)null && components[i].enabled)
					{
						components[i].enabled = false;
						list.Add(components[i]);
					}
				}
				a.disabledColliders = list.ToArray();
			}
			((Component)turret).transform.localScale = Vector3.one * Scale;
		}

		private static void Follow(Attachment a)
		{
			//IL_0028: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_009a: 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_00a4: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody owner = a.owner;
			Vector3 val = (((Object)(object)owner.characterDirection != (Object)null) ? owner.characterDirection.forward : ((Component)owner).transform.forward);
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
			{
				val = Vector3.forward;
			}
			else
			{
				((Vector3)(ref val)).Normalize();
			}
			Vector3 val2 = Vector3.Cross(Vector3.up, val);
			float num = ((a.slot == 0) ? Side : (0f - Side));
			Vector3 position = ((Component)owner).transform.position + Vector3.up * Height + val2 * num + val * Forward;
			((Component)a.turret).transform.position = position;
			Quaternion val3 = Quaternion.LookRotation(val, Vector3.up);
			float num2 = ((a.slot == 0) ? (0f - Tilt) : Tilt);
			((Component)a.turret).transform.rotation = val3 * Quaternion.AngleAxis(num2, Vector3.forward);
		}

		private static void Restore(Attachment a)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody turret = a.turret;
			if ((Object)(object)turret == (Object)null)
			{
				return;
			}
			for (int i = 0; i < a.disabledColliders.Length; i++)
			{
				if ((Object)(object)a.disabledColliders[i] != (Object)null)
				{
					a.disabledColliders[i].enabled = true;
				}
			}
			a.disabledColliders = EmptyColliders;
			if ((Object)(object)a.disabledDirection != (Object)null)
			{
				((Behaviour)a.disabledDirection).enabled = true;
				a.disabledDirection = null;
			}
			((Component)turret).transform.localScale = Vector3.one;
			CharacterMotor component = ((Component)turret).GetComponent<CharacterMotor>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = true;
			}
			Rigidbody component2 = ((Component)turret).GetComponent<Rigidbody>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.isKinematic = false;
			}
			Collider[] components = ((Component)turret).GetComponents<Collider>();
			if (components == null)
			{
				return;
			}
			for (int j = 0; j < components.Length; j++)
			{
				if ((Object)(object)components[j] != (Object)null)
				{
					components[j].enabled = true;
				}
			}
		}

		private static CharacterBody FindOwner(CharacterBody turret)
		{
			CharacterBody val = FindOwnerByAiOwnership(turret);
			if ((Object)(object)val == (Object)null)
			{
				val = FindNearestEngineer(turret);
			}
			if ((Object)(object)val != (Object)null && (Object)(object)val.healthComponent != (Object)null && !val.healthComponent.alive)
			{
				return null;
			}
			return val;
		}

		private static CharacterBody FindOwnerByAiOwnership(CharacterBody turret)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (_aiOwnershipType == null || _aiOwnerMasterField == null || (Object)(object)turret.master == (Object)null)
			{
				return null;
			}
			Component component = ((Component)turret.master).GetComponent(_aiOwnershipType);
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			object? value = _aiOwnerMasterField.GetValue(component);
			CharacterMaster val = (CharacterMaster)((value is CharacterMaster) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			CharacterBody body = val.GetBody();
			if ((Object)(object)body == (Object)null || body.bodyIndex != _engineerBodyIndex)
			{
				return null;
			}
			return body;
		}

		private static CharacterBody FindNearestEngineer(CharacterBody turret)
		{
			//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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			float fallbackRadius = FallbackRadius;
			if (fallbackRadius < 0f)
			{
				return null;
			}
			IList<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList;
			if (readOnlyInstancesList == null)
			{
				return null;
			}
			TeamIndex val = (TeamIndex)(((Object)(object)turret.teamComponent != (Object)null) ? ((int)turret.teamComponent.teamIndex) : 0);
			Vector3 position = ((Component)turret).transform.position;
			CharacterBody result = null;
			float num = fallbackRadius * fallbackRadius;
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				CharacterBody val2 = readOnlyInstancesList[i];
				if (!((Object)(object)val2 == (Object)null) && val2.bodyIndex == _engineerBodyIndex && (!((Object)(object)val2.teamComponent != (Object)null) || val2.teamComponent.teamIndex == val))
				{
					Vector3 val3 = ((Component)val2).transform.position - position;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (sqrMagnitude <= num)
					{
						num = sqrMagnitude;
						result = val2;
					}
				}
			}
			return result;
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)message);
			}
		}
	}
	internal static class EngineerSkillText
	{
		private const string MineToken = "ENGI_SECONDARY_DESCRIPTION";

		private const string BubbleToken = "ENGI_UTILITY_DESCRIPTION";

		private const string TurretToken = "ENGI_SPECIAL_ALT1_DESCRIPTION";

		private const string MineDefault = "放置一枚能够造成<style=cIsDamage>1000%的伤害</style>的压力地雷,但是需要时间准备。最多放置4枚。";

		private const string BubbleDefault = "放置一个圆形防护盾以阻挡伤害。";

		private const string TurretDefault = "立即装备便携式鱼叉导弹发射器,发射的导弹可造成<style=cIsDamage>500%的伤害</style>,每次放置2座。";

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<string> _languages;

		private static ConfigEntry<string> _mineText;

		private static ConfigEntry<string> _bubbleText;

		private static ConfigEntry<string> _turretText;

		private static bool _applied;

		private static bool _errorLogged;

		private static bool Enabled
		{
			get
			{
				if (_enabled != null)
				{
					return _enabled.Value;
				}
				return false;
			}
		}

		private static string[] Languages
		{
			get
			{
				string text = ((_languages != null) ? _languages.Value : "zh-CN");
				if (string.IsNullOrEmpty(text))
				{
					return new string[1] { "zh-CN" };
				}
				string[] array = text.Split(new char[1] { ',' });
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = array[i].Trim();
				}
				return array;
			}
		}

		private static string MineText
		{
			get
			{
				if (_mineText == null)
				{
					return "放置一枚能够造成<style=cIsDamage>1000%的伤害</style>的压力地雷,但是需要时间准备。最多放置4枚。";
				}
				return _mineText.Value;
			}
		}

		private static string BubbleText
		{
			get
			{
				if (_bubbleText == null)
				{
					return "放置一个圆形防护盾以阻挡伤害。";
				}
				return _bubbleText.Value;
			}
		}

		private static string TurretText
		{
			get
			{
				if (_turretText == null)
				{
					return "立即装备便携式鱼叉导弹发射器,发射的导弹可造成<style=cIsDamage>500%的伤害</style>,每次放置2座。";
				}
				return _turretText.Value;
			}
		}

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("技能文本", "OverrideSkillText", true, "是否改写工程师三个技能在游戏里显示的说明文本(压力地雷 / 泡泡护盾 / 移动炮台)。");
			_languages = config.Bind<string>("技能文本", "Languages", "zh-CN,en", "把这些文本写进哪些语言(逗号分隔的语言代码)。默认中文和英文都写,这样切语言也能看到新文本;只想要中文就填 zh-CN。");
			_mineText = config.Bind<string>("技能文本", "MineText", "放置一枚能够造成<style=cIsDamage>1000%的伤害</style>的压力地雷,但是需要时间准备。最多放置4枚。", "M2「压力地雷」的说明文本。");
			_bubbleText = config.Bind<string>("技能文本", "BubbleShieldText", "放置一个圆形防护盾以阻挡伤害。", "Shift「泡泡护盾」的说明文本。");
			_turretText = config.Bind<string>("技能文本", "WalkerTurretText", "立即装备便携式鱼叉导弹发射器,发射的导弹可造成<style=cIsDamage>500%的伤害</style>,每次放置2座。", "替代 R「移动炮台」的说明文本。");
			Apply();
		}

		internal static string Summary()
		{
			if (!Enabled)
			{
				return "";
			}
			return " [技能文本已改写]";
		}

		internal static void Apply()
		{
			if (!Enabled || _applied)
			{
				return;
			}
			_applied = true;
			string[] languages = Languages;
			try
			{
				for (int i = 0; i < languages.Length; i++)
				{
					Add("ENGI_SECONDARY_DESCRIPTION", MineText, languages[i]);
					Add("ENGI_UTILITY_DESCRIPTION", BubbleText, languages[i]);
					Add("ENGI_SPECIAL_ALT1_DESCRIPTION", TurretText, languages[i]);
				}
				Log((LogLevel)16, "技能文本:已改写 压力地雷 / 泡泡护盾 / 移动炮台 的说明(语言:" + string.Join("/", languages) + ")。");
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)2, "技能文本:写入语言表失败 —— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void Add(string token, string text, string language)
		{
			if (!string.IsNullOrEmpty(text))
			{
				LanguageAPI.Add(token, text, language);
			}
		}

		private static void LogOnce(ref bool flag, LogLevel level, string message)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!flag)
			{
				flag = true;
				Log(level, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)message);
			}
		}
	}
	internal static class EngineerTurretPair
	{
		private const string TurretBodyName = "EngiWalkerTurretBody";

		private const string TurretMasterName = "EngiWalkerTurretMaster";

		private const string TurretSkillName = "PlaceWalkerTurret";

		private const string TurretDescriptionToken = "ENGI_SPECIAL_ALT1_DESCRIPTION";

		private const float VanillaRecharge = 30f;

		private const int PairCount = 2;

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<int> _maxStock;

		private static ConfigEntry<float> _recharge;

		private static ConfigEntry<bool> _killOld;

		private static readonly FieldInfo _reportSummon = AccessTools.Field(typeof(MasterSummonReport), "masterSummon");

		private static readonly FieldInfo _reportSummonMaster = AccessTools.Field(typeof(MasterSummonReport), "summonMasterInstance");

		private static readonly FieldInfo _reportSummonBody = AccessTools.Field(typeof(MasterSummonReport), "summonBodyInstance");

		private static readonly FieldInfo _reportLeader = AccessTools.Field(typeof(MasterSummonReport), "leaderMasterInstance");

		private static Type _aiOwnershipType;

		private static FieldInfo _aiOwnerMasterField;

		private static readonly Dictionary<int, List<CharacterBody>> _byOwner = new Dictionary<int, List<CharacterBody>>();

		private static SkillDef _skillDef;

		private static bool _stockLogged;

		private static bool _rechargeLogged;

		private static bool _spawnLogged;

		private static bool _errorLogged;

		private static bool _recursing;

		private static bool Enabled
		{
			get
			{
				if (_enabled != null)
				{
					return _enabled.Value;
				}
				return true;
			}
		}

		private static int MaxStock
		{
			get
			{
				if (_maxStock == null)
				{
					return 1;
				}
				return Mathf.Max(1, _maxStock.Value);
			}
		}

		private static float RechargeInterval
		{
			get
			{
				if (_recharge == null)
				{
					return 30f;
				}
				return Mathf.Max(0f, _recharge.Value);
			}
		}

		private static bool KillOld
		{
			get
			{
				if (_killOld != null)
				{
					return _killOld.Value;
				}
				return true;
			}
		}

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("特殊技能.移动炮台.数量", "PairTurrets", true, "是否让「移动炮台」成对生成:技能只有一层,但一次放出来两个(分别挂左右肩)。");
			_maxStock = config.Bind<int>("特殊技能.移动炮台.数量", "MaxStock", 1, "移动炮台技能最多能攒几层:原版是 2,改成 1 就是「放一次就用完」。");
			_recharge = config.Bind<float>("特殊技能.移动炮台.数量", "RechargeInterval", 60f, "移动炮台技能每层的充能时间(秒):原版是 30 秒。");
			_killOld = config.Bind<bool>("特殊技能.移动炮台.数量", "KillOldOnRecast", true, "重放时是否先让上一次那两个炮台死亡(只杀同一个工程师名下的)。");
			try
			{
				_aiOwnershipType = AccessTools.TypeByName("RoR2.CharacterAI.AIOwnership");
				if (_aiOwnershipType != null)
				{
					_aiOwnerMasterField = AccessTools.Field(_aiOwnershipType, "ownerMaster");
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "移动炮台数量:取 AIOwnership 失败(只影响认主精度)—— " + ex.GetType().Name + " " + ex.Message);
			}
			MasterSummon.onServerMasterSummonGlobal += OnServerMasterSummon;
		}

		internal static string Summary()
		{
			if (!Enabled)
			{
				return "";
			}
			return " [移动炮台:成对 上限" + MaxStock + "层 冷却" + RechargeInterval.ToString("0.#") + "s" + (KillOld ? " 重放清旧" : "") + "]";
		}

		internal static void Tick()
		{
			if (!Enabled)
			{
				return;
			}
			try
			{
				ApplySkillValues();
				EnforceCap();
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "移动炮台数量:异常(已忽略本帧)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void ApplySkillValues()
		{
			if ((Object)(object)_skillDef == (Object)null)
			{
				_skillDef = FindTurretSkill();
				if ((Object)(object)_skillDef == (Object)null)
				{
					return;
				}
			}
			bool flag = false;
			int maxStock = MaxStock;
			if (_skillDef.baseMaxStock != maxStock)
			{
				int baseMaxStock = _skillDef.baseMaxStock;
				_skillDef.baseMaxStock = maxStock;
				flag = true;
				if (!_stockLogged)
				{
					_stockLogged = true;
					Log((LogLevel)16, "移动炮台:PlaceWalkerTurret 的层数上限 " + baseMaxStock + " → " + maxStock + "。");
				}
			}
			float rechargeInterval = RechargeInterval;
			if (Mathf.Abs(_skillDef.baseRechargeInterval - rechargeInterval) > 0.01f)
			{
				float baseRechargeInterval = _skillDef.baseRechargeInterval;
				_skillDef.baseRechargeInterval = rechargeInterval;
				flag = true;
				if (!_rechargeLogged)
				{
					_rechargeLogged = true;
					Log((LogLevel)16, "移动炮台:PlaceWalkerTurret 的冷却 " + baseRechargeInterval.ToString("0.#") + "s → " + rechargeInterval.ToString("0.#") + "s。");
				}
			}
			if (flag)
			{
				RecalculateEngineers();
			}
		}

		private static SkillDef FindTurretSkill()
		{
			IEnumerable<SkillDef> allSkillDefs = SkillCatalog.allSkillDefs;
			if (allSkillDefs == null)
			{
				return null;
			}
			foreach (SkillDef item in allSkillDefs)
			{
				if (!((Object)(object)item == (Object)null))
				{
					string name = ((Object)item).name;
					if (string.Equals(item.skillName, "PlaceWalkerTurret", StringComparison.Ordinal) || (name != null && name.IndexOf("PlaceWalkerTurret", StringComparison.Ordinal) >= 0) || string.Equals(item.skillDescriptionToken, "ENGI_SPECIAL_ALT1_DESCRIPTION", StringComparison.Ordinal))
					{
						return item;
					}
				}
			}
			return null;
		}

		private static void RecalculateEngineers()
		{
			IList<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList;
			if (readOnlyInstancesList == null)
			{
				return;
			}
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				CharacterBody val = readOnlyInstancesList[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.skillLocator == (Object)null))
				{
					GenericSkill special = val.skillLocator.special;
					if ((Object)(object)special != (Object)null)
					{
						special.RecalculateValues();
					}
				}
			}
		}

		private static void OnServerMasterSummon(MasterSummonReport report)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled)
			{
				return;
			}
			try
			{
				CharacterBody val = (CharacterBody)((_reportSummonBody != null) ? /*isinst with value type is only supported in some contexts*/: null);
				if ((Object)(object)val != (Object)null && IsWalkerTurret(val))
				{
					EngineerShoulderHarpoons.DisableBeamNow(val);
					object turretMaster = (object)((_reportSummonMaster != null) ? /*isinst with value type is only supported in some contexts*/: null);
					CharacterMaster val2 = (CharacterMaster)((_reportLeader != null) ? /*isinst with value type is only supported in some contexts*/: null);
					Register(OwnerOf((CharacterMaster)turretMaster) ?? val2, val);
				}
				if (_recursing || !IsWalkerTurret(report, val))
				{
					return;
				}
				MasterSummon val3 = (MasterSummon)((_reportSummon != null) ? /*isinst with value type is only supported in some contexts*/: null);
				if (val3 != null)
				{
					CharacterMaster val4 = (CharacterMaster)((_reportLeader != null) ? /*isinst with value type is only supported in some contexts*/: null);
					int num = 0;
					if (KillOld)
					{
						num = KillOldTurrets(val4, val);
					}
					_recursing = true;
					try
					{
						Clone(val3).Perform();
					}
					finally
					{
						_recursing = false;
					}
					if (!_spawnLogged)
					{
						_spawnLogged = true;
						Log((LogLevel)16, "移动炮台数量:一次放置已补成两个(主人 " + (((Object)(object)val4 != (Object)null) ? ((Object)val4).name : "未知") + (KillOld ? (",清掉旧炮台 " + num + " 个") : "") + ")。");
					}
					else if (KillOld)
					{
						Log((LogLevel)32, "移动炮台数量:重放清掉旧炮台 " + num + " 个。");
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "移动炮台数量:处理召唤事件时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static bool IsWalkerTurret(MasterSummonReport report, CharacterBody body)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			CharacterMaster val = (CharacterMaster)((_reportSummonMaster != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val != (Object)null && ((Object)val).name.StartsWith("EngiWalkerTurretMaster", StringComparison.Ordinal))
			{
				return true;
			}
			if ((Object)(object)body != (Object)null)
			{
				return IsWalkerTurret(body);
			}
			return false;
		}

		private static bool IsWalkerTurret(CharacterBody body)
		{
			return ((Object)body).name.StartsWith("EngiWalkerTurretBody", StringComparison.Ordinal);
		}

		private static int KeyFor(CharacterMaster owner)
		{
			if (!((Object)(object)owner != (Object)null))
			{
				return 0;
			}
			return ((Object)owner).GetInstanceID();
		}

		private static List<CharacterBody> ListFor(int key)
		{
			if (!_byOwner.TryGetValue(key, out var value))
			{
				value = new List<CharacterBody>();
				_byOwner[key] = value;
			}
			return value;
		}

		private static void Register(CharacterMaster owner, CharacterBody body)
		{
			if ((Object)(object)body == (Object)null)
			{
				return;
			}
			List<CharacterBody> list = ListFor(KeyFor(owner));
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i] == body)
				{
					return;
				}
			}
			list.Add(body);
		}

		private static CharacterMaster OwnerOf(CharacterMaster turretMaster)
		{
			if ((Object)(object)turretMaster == (Object)null || _aiOwnershipType == null || _aiOwnerMasterField == null)
			{
				return null;
			}
			Component component = ((Component)turretMaster).GetComponent(_aiOwnershipType);
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			object? value = _aiOwnerMasterField.GetValue(component);
			return (CharacterMaster)((value is CharacterMaster) ? value : null);
		}

		private static int KillOldTurrets(CharacterMaster owner, CharacterBody keep)
		{
			List<CharacterBody> list = ListFor(KeyFor(owner));
			List<CharacterBody> list2 = new List<CharacterBody>();
			for (int i = 0; i < list.Count; i++)
			{
				CharacterBody val = list[i];
				if (!((Object)(object)val == (Object)null) && val != keep)
				{
					list2.Add(val);
				}
			}
			for (int j = 0; j < list2.Count; j++)
			{
				list.Remove(list2[j]);
				Kill(list2[j]);
			}
			return list2.Count;
		}

		private static void EnforceCap()
		{
			List<int> list = new List<int>(_byOwner.Keys);
			for (int i = 0; i < list.Count; i++)
			{
				List<CharacterBody> list2 = _byOwner[list[i]];
				for (int num = list2.Count - 1; num >= 0; num--)
				{
					if ((Object)(object)list2[num] == (Object)null)
					{
						list2.RemoveAt(num);
					}
				}
				while (list2.Count > 2)
				{
					CharacterBody turret = list2[0];
					list2.RemoveAt(0);
					Kill(turret);
				}
			}
		}

		private static void Kill(CharacterBody turret)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)turret == (Object)null)
			{
				return;
			}
			EngineerShoulderTurrets.Forget(turret);
			CharacterMaster master = turret.master;
			if ((Object)(object)master != (Object)null)
			{
				master.TrueKill();
				return;
			}
			HealthComponent healthComponent = turret.healthComponent;
			if ((Object)(object)healthComponent != (Object)null)
			{
				healthComponent.Suicide((GameObject)null, (GameObject)null, DamageTypeCombo.op_Implicit((DamageType)0));
			}
		}

		private static MasterSummon Clone(MasterSummon source)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			MasterSummon val = new MasterSummon();
			FieldInfo[] fields = typeof(MasterSummon).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			for (int i = 0; i < fields.Length; i++)
			{
				fields[i].SetValue(val, fields[i].GetValue(source));
			}
			return val;
		}

		private static void LogOnce(ref bool flag, LogLevel level, string message)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!flag)
			{
				flag = true;
				Log(level, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)message);
			}
		}
	}
	internal static class EngineerWalkerTurretAI
	{
		private const string StaticMasterName = "EngiTurretMaster";

		private const string WalkerMasterName = "EngiWalkerTurretMaster";

		private static readonly string[] DriverFields = new string[28]
		{
			"customName", "skillSlot", "requiredSkill", "requireSkillReady", "requireEquipmentReady", "shouldFireEquipment", "minUserHealthFraction", "maxUserHealthFraction", "minTargetHealthFraction", "maxTargetHealthFraction",
			"minDistance", "maxDistance", "selectionRequiresTargetLoS", "selectionRequiresOnGround", "selectionRequiresTargetNonFlier", "selectionRequiresAimTarget", "maxTimesSelected", "moveTargetType", "activationRequiresTargetLoS", "activationRequiresAimTargetLoS",
			"activationRequiresAimConfirmation", "movementType", "moveInputScale", "aimVectorDampTimeOverride", "aimVectorMaxSpeedOverride", "aimType", "ignoreNodeGraph", "shouldSprint"
		};

		private static readonly string[] AiFields = new string[17]
		{
			"fullVision", "xrayVision", "retaliateUntargetable", "neverRetaliateFriendlies", "ignoreFliers", "isHealer", "prioritizePlayers", "copyLeaderTarget", "enemyAttentionDuration", "leaderTargetCooldown",
			"desiredSpawnNodeGraphType", "aimVectorDampTime", "aimVectorMaxSpeed", "aimVectorDampTimeOverride", "aimVectorMaxSpeedOverride", "shouldMissFirstOffScreenShot", "forceUpdateEveryFrame"
		};

		private static readonly string[] SkippedAiFields = new string[2] { "targetRefreshInterval", "maxVisionDistance" };

		private static ManualLogSource _log;

		private static ConfigEntry<bool> _enabled;

		private static FieldInfo[] _driverFields;

		private static FieldInfo[] _aiFields;

		private static GameObject _staticPrefab;

		private static GameObject _walkerPrefab;

		private static MasterIndex _walkerMasterIndex;

		private static bool _resolved;

		private static bool _prefabApplied;

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

		private static bool _missingLogged;

		private static bool _errorLogged;

		private static bool Enabled
		{
			get
			{
				if (_enabled != null)
				{
					return _enabled.Value;
				}
				return true;
			}
		}

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_enabled = config.Bind<bool>("特殊技能.移动炮台.AI", "CopyStaticTurretAI", true, "让移动炮台的 AI 完整照抄固定炮台:站定在原地、60 米内对有视线的敌人瞄准后才开火,不再追击、绕圈、跑回主人身边。改的是 master prefab,关掉本项需要重开游戏才恢复。");
			_driverFields = Resolve(typeof(AISkillDriver), DriverFields);
			_aiFields = Resolve(typeof(BaseAI), AiFields);
		}

		internal static string Summary()
		{
			if (!Enabled)
			{
				return "";
			}
			return " [移动炮台 AI = 固定炮台 AI]";
		}

		private static FieldInfo[] Resolve(Type type, string[] names)
		{
			List<FieldInfo> list = new List<FieldInfo>();
			for (int i = 0; i < names.Length; i++)
			{
				FieldInfo fieldInfo = AccessTools.Field(type, names[i]);
				if (fieldInfo != null)
				{
					list.Add(fieldInfo);
				}
				else if (!_missingLogged)
				{
					_missingLogged = true;
					if (_log != null)
					{
						_log.Log((LogLevel)4, (object)("移动炮台 AI:取不到字段 " + type.Name + "." + names[i] + "(该字段不做照搬,其余照常)。"));
					}
				}
			}
			return list.ToArray();
		}

		internal static void Tick()
		{
			if (!Enabled)
			{
				return;
			}
			try
			{
				if (_resolved || ResolvePrefabs())
				{
					if (!_prefabApplied)
					{
						Apply(_staticPrefab, _walkerPrefab, "移动炮台 prefab");
						_prefabApplied = true;
					}
					SyncExisting();
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "移动炮台 AI:照搬时异常(已忽略本帧)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static bool ResolvePrefabs()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_0016: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			MasterIndex val = MasterCatalog.FindMasterIndex("EngiTurretMaster");
			MasterIndex val2 = MasterCatalog.FindMasterIndex("EngiWalkerTurretMaster");
			if (val == MasterIndex.none || val2 == MasterIndex.none)
			{
				return false;
			}
			GameObject masterPrefab = MasterCatalog.GetMasterPrefab(val);
			GameObject masterPrefab2 = MasterCatalog.GetMasterPrefab(val2);
			if ((Object)(object)masterPrefab == (Object)null || (Object)(object)masterPrefab2 == (Object)null)
			{
				return false;
			}
			_staticPrefab = masterPrefab;
			_walkerPrefab = masterPrefab2;
			_walkerMasterIndex = val2;
			_resolved = true;
			Log((LogLevel)16, "移动炮台 AI:已定位到两个 master prefab(模板 EngiTurretMaster → 目标 EngiWalkerTurretMaster)。");
			return true;
		}

		private static void Apply(GameObject src, GameObject dst, string what)
		{
			BaseAI component = src.GetComponent<BaseAI>();
			BaseAI component2 = dst.GetComponent<BaseAI>();
			if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null)
			{
				Copy(component, component2, _aiFields);
			}
			AISkillDriver[] components = src.GetComponents<AISkillDriver>();
			AISkillDriver[] components2 = dst.GetComponents<AISkillDriver>();
			if (components == null || components2 == null)
			{
				return;
			}
			int num = Math.Min(components.Length, components2.Length);
			List<string> list = new List<string>();
			for (int i = 0; i < components2.Length; i++)
			{
				AISkillDriver val = components2[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (i < num && (Object)(object)components[i] != (Object)null)
				{
					AISkillDriver val2 = components[i];
					string customName = val.customName;
					Copy(val2, val, _driverFields);
					((Behaviour)val).enabled = ((Behaviour)val2).enabled;
					list.Add("  " + customName + " → " + val.customName + "(" + val.minDistance.ToString("0.#") + "~" + (float.IsInfinity(val.maxDistance) ? "∞" : val.maxDistance.ToString("0.#")) + "m,skillSlot " + ((object)Unsafe.As<SkillSlot, SkillSlot>(ref val.skillSlot)/*cast due to .constrained prefix*/).ToString() + ")");
				}
				else
				{
					list.Add("  " + val.customName + " → 停用");
					if (((Behaviour)val).enabled)
					{
						((Behaviour)val).enabled = false;
					}
				}
			}
			if (list.Count > 0)
			{
				Log((LogLevel)16, "移动炮台 AI 已照抄固定炮台(" + what + "):");
				for (int j = 0; j < list.Count; j++)
				{
					Log((LogLevel)16, list[j]);
				}
			}
		}

		private static void SyncExisting()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			IList<CharacterMaster> readOnlyInstancesList = CharacterMaster.readOnlyInstancesList;
			if (readOnlyInstancesList == null)
			{
				return;
			}
			for (int i = 0; i < readOnlyInstancesList.Count; i++)
			{
				CharacterMaster val = readOnlyInstancesList[i];
				if (!((Object)(object)val == (Object)null) && !(val.masterIndex != _walkerMasterIndex))
				{
					int instanceID = ((Object)val).GetInstanceID();
					if (!_syncedInstances.Contains(instanceID))
					{
						_syncedInstances.Add(instanceID);
						Apply(_staticPrefab, ((Component)val).gameObject, "场上已有炮台");
					}
				}
			}
		}

		private static void Copy(object src, object dst, FieldInfo[] fields)
		{
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					fieldInfo.SetValue(dst, fieldInfo.GetValue(src));
				}
				catch (Exception ex)
				{
					LogOnce(ref _errorLogged, (LogLevel)4, "移动炮台 AI:字段 " + fieldInfo.Name + " 照搬失败(已跳过)—— " + ex.GetType().Name + " " + ex.Message);
				}
			}
		}

		private static void LogOnce(ref bool flag, LogLevel level, string message)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!flag)
			{
				flag = true;
				Log(level, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)message);
			}
		}
	}
	internal static class EngineerWalkerTurretStats
	{
		private static ManualLogSource _log;

		private static ConfigEntry<bool> _rangeEnabled;

		private static ConfigEntry<float> _rangeMultiplier;

		private static readonly FieldInfo _beamRangeField = AccessTools.Field(typeof(FireBeam), "maxDistance");

		private static float _beamBase = -1f;

		private static float _beamLastWritten = float.MinValue;

		private static bool _missingLogged;

		private static bool _errorLogged;

		private static bool _beamLogged;

		private static bool RangeEnabled
		{
			get
			{
				if (_rangeEnabled != null)
				{
					return _rangeEnabled.Value;
				}
				return true;
			}
		}

		private static float RangeMul
		{
			get
			{
				if (_rangeMultiplier == null)
				{
					return 1.5f;
				}
				return Mathf.Max(0f, _rangeMultiplier.Value);
			}
		}

		internal static void Init(ConfigFile config, ManualLogSource log)
		{
			_log = log;
			_rangeEnabled = config.Bind<bool>("特殊技能.移动炮台.数值", "BoostBeamRange", true, "是否加长移动炮台的激光射程。");
			_rangeMultiplier = config.Bind<float>("特殊技能.移动炮台.数值", "BeamRangeMultiplier", 1.5f, "激光射程倍率:1 = 原版(FireBeam.maxDistance 25 米),2.4 = 刚好覆盖照抄后的 60 米索敌判定。");
			if (_beamRangeField == null && !_missingLogged)
			{
				_missingLogged = true;
				Log((LogLevel)4, "移动炮台数值:取不到 FireBeam.maxDistance,激光射程改动不生效。");
			}
		}

		internal static string Summary()
		{
			if (!RangeEnabled)
			{
				return "";
			}
			float num = ((_beamBase > 0f) ? _beamBase : 25f);
			return " [激光射程 " + num.ToString("0.#") + " → " + (num * RangeMul).ToString("0.#") + "m]";
		}

		internal static void Patch(Harmony harmony)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			if (!RangeEnabled)
			{
				Log((LogLevel)16, "移动炮台数值:按配置保持原版激光射程,不挂补丁。");
				return;
			}
			Type typeFromHandle = typeof(FireBeam);
			MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "OnEnter", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log((LogLevel)2, "移动炮台数值补丁失败:取不到 " + typeFromHandle.FullName + ".OnEnter。");
				return;
			}
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(EngineerWalkerTurretStats), "FireBeamOnEnterPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log((LogLevel)16, "补丁已挂载:" + typeFromHandle.Name + ".OnEnter <- EngineerWalkerTurretStats.FireBeamOnEnterPostfix(移动炮台激光射程 ×" + RangeMul.ToString("0.##") + ")");
		}

		private static void FireBeamOnEnterPostfix(FireBeam __instance)
		{
			try
			{
				if (__instance == null)
				{
					return;
				}
				float num = ((_beamRangeField != null) ? ((float)_beamRangeField.GetValue(__instance)) : 0f);
				if (num <= 0f)
				{
					return;
				}
				if (Mathf.Abs(num - _beamLastWritten) > 0.001f)
				{
					_beamBase = num;
				}
				float num2 = _beamBase * RangeMul;
				if (!(Mathf.Abs(num - num2) <= 0.001f))
				{
					_beamRangeField.SetValue(__instance, num2);
					_beamLastWritten = num2;
					if (!_beamLogged)
					{
						_beamLogged = true;
						Log((LogLevel)16, "移动炮台激光射程:" + _beamBase.ToString("0.##") + " → " + num2.ToString("0.##") + " 米(FireBeam.maxDistance;只有移动炮台用这个状态,默认炮台走 FireGauss 不受影响)。");
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce(ref _errorLogged, (LogLevel)4, "移动炮台数值:改激光射程时异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static void LogOnce(ref bool flag, LogLevel level, string message)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!flag)
			{
				flag = true;
				Log(level, message);
			}
		}

		private static void Log(LogLevel level, string message)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (_log != null)
			{
				_log.Log(level, (object)message);
			}
		}
	}
	[BepInPlugin("com.sparkletwilight.sparkleengineertweaks", "SparkleEngineerTweaks", "1.11.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SparkleEngineerTweaksPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.sparkletwilight.sparkleengineertweaks";

		public const string PluginName = "SparkleEngineerTweaks";

		public const string PluginVersion = "1.11.0";

		public void Awake()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			EngineerShoulderTurrets.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			EngineerWalkerTurretAI.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			EngineerShoulderHarpoons.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			EngineerTurretPair.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			EngineerWalkerTurretStats.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			EngineerBubbleShieldArmor.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			EngineerPressureMine.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			EngineerSkillText.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			Harmony harmony = new Harmony("com.sparkletwilight.sparkleengineertweaks");
			SafePatch("泡泡护盾护甲", delegate
			{
				EngineerBubbleShieldArmor.Patch(harmony);
			});
			SafePatch("移动炮台数值", delegate
			{
				EngineerWalkerTurretStats.Patch(harmony);
			});
			SafePatch("压力地雷", delegate
			{
				EngineerPressureMine.Patch(harmony);
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)("SparkleEngineerTweaks v1.11.0 已加载。" + EngineerShoulderTurrets.Summary() + EngineerWalkerTurretAI.Summary() + EngineerShoulderHarpoons.Summary() + EngineerTurretPair.Summary() + EngineerWalkerTurretStats.Summary() + EngineerBubbleShieldArmor.Summary() + EngineerPressureMine.Summary() + EngineerSkillText.Summary()));
		}

		public void Update()
		{
			EngineerShoulderTurrets.Tick();
			EngineerWalkerTurretAI.Tick();
			EngineerTurretPair.Tick();
			EngineerShoulderHarpoons.Tick();
			EngineerBubbleShieldArmor.Tick();
		}

		private void SafePatch(string label, Action patch)
		{
			try
			{
				patch();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("SparkleEngineerTweaks:「" + label + "」挂补丁时抛异常,已跳过该模块 —— " + ex.GetType().Name + " " + ex.Message));
			}
		}
	}
}