Decompiled source of SparkleRexTweaks v1.12.0

plugins/SparkleRexTweaks.dll

Decompiled 6 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using R2API;
using RoR2;
using RoR2.Projectile;
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("SparkleRexTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.12.0.0")]
[assembly: AssemblyInformationalVersion("1.12.0")]
[assembly: AssemblyProduct("SparkleRexTweaks")]
[assembly: AssemblyTitle("SparkleRexTweaks")]
[assembly: AssemblyVersion("1.12.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 SparkleRexTweaks
{
	public static class RexBrambleVolley
	{
		private const string StateTypeName = "EntityStates.Treebot.Weapon.FirePlantSonicBoom";

		private const string MethodName = "CalculateProcCoefficient";

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _procCoefficient;

		private static ManualLogSource _log;

		private static bool _patched;

		private static bool _appliedLogged;

		private static float _vanillaValue = float.NaN;

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

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_enabled = cfg.Bind<bool>("BrambleVolley", "Enabled", true, "是否调整替代 Shift「树莓齐射」(Bramble Volley)的触发系数。false = 保持原版。");
			_procCoefficient = cfg.Bind<float>("BrambleVolley", "ProcCoefficient", 1f, "「树莓齐射」的触发系数(原版 0.5)。\n系数越高,尤克里里、导弹、三尖匕首之类的命中类道具越容易触发。\n填 1 = 每次命中都按满概率判定。填 0 或负数 = 沿用原版数值。\n这个值是运行期读取的(改完存档重进即可,不用重启游戏)。");
		}

		public static string Summary()
		{
			if (!IsEnabled)
			{
				return " [树莓齐射:原版未改动]";
			}
			if (!_patched)
			{
				return " [树莓齐射:补丁未挂载]";
			}
			float num = TargetValue();
			if (num <= 0f)
			{
				return " [树莓齐射:沿用原版触发系数]";
			}
			return " [树莓齐射:触发系数 → " + num.ToString("0.##") + "]";
		}

		private static float TargetValue()
		{
			if (_procCoefficient == null)
			{
				return 1f;
			}
			return _procCoefficient.Value;
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			if (!IsEnabled)
			{
				Log((LogLevel)16, "树莓齐射:按配置保持原版,不挂补丁。");
				return;
			}
			Type type = AccessTools.TypeByName("EntityStates.Treebot.Weapon.FirePlantSonicBoom");
			if (type == null)
			{
				Log((LogLevel)2, "树莓齐射补丁失败:取不到类型 EntityStates.Treebot.Weapon.FirePlantSonicBoom。");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "CalculateProcCoefficient", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				methodInfo = type.GetMethod("CalculateProcCoefficient", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (methodInfo == null)
			{
				Log((LogLevel)2, "树莓齐射补丁失败:取不到 EntityStates.Treebot.Weapon.FirePlantSonicBoom.CalculateProcCoefficient。");
				return;
			}
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RexBrambleVolley), "CalculateProcCoefficientPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_patched = true;
			Log((LogLevel)16, "补丁已挂载:EntityStates.Treebot.Weapon.FirePlantSonicBoom.CalculateProcCoefficient <- CalculateProcCoefficientPostfix(触发系数 0.5 → " + TargetValue().ToString("0.##") + ")");
		}

		public static void CalculateProcCoefficientPostfix(ref float __result)
		{
			try
			{
				if (!IsEnabled)
				{
					return;
				}
				float vanillaValue = __result;
				if (float.IsNaN(_vanillaValue))
				{
					_vanillaValue = vanillaValue;
				}
				float num = TargetValue();
				if (!(num <= 0f))
				{
					__result = num;
					if (!_appliedLogged)
					{
						_appliedLogged = true;
						Log((LogLevel)16, "树莓齐射已生效 —— 触发系数 " + vanillaValue.ToString("0.##") + " → " + num.ToString("0.##"));
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "树莓齐射:结算异常(已忽略)—— " + ex.GetType().Name + " " + ex.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);
			}
		}
	}
	public static class RexEntangle
	{
		private const string FlowerTypeNameNested = "EntityStates.Treebot.TreebotFlower+TreebotFlower2Projectile";

		private const string FlowerTypeNameDotted = "EntityStates.Treebot.TreebotFlower.TreebotFlower2Projectile";

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _interval;

		private static ConfigEntry<float> _tendrilLifetime;

		private static ConfigEntry<float> _damageMultiplier;

		private static ConfigEntry<float> _weakenDuration;

		private static ConfigEntry<float> _catchInterval;

		private static ConfigEntry<float> _procCoefficient;

		private static ConfigEntry<bool> _triggerProcs;

		private static ManualLogSource _log;

		private static Type _flowerType;

		private static MethodInfo _rootPulseMethod;

		private static float _intervalValue = 1.5f;

		private static float _tendrilValue = 1.5f;

		private static float _weakenValue = 3f;

		private static bool _triggerProcsValue = true;

		private static bool _firstPulseLogged;

		private static bool _fieldResolveFailedLogged;

		private static float _lastLogAt = -999f;

		private static float _storedDamage = float.NaN;

		private static bool _damageFieldFailedLogged;

		private static float _vanillaProcCoefficient = float.NaN;

		private static bool _procCoefficientLogged;

		private static bool _procCoefficientFieldFailedLogged;

		public static bool CatchOnlyNew;

		private static bool _skipContainsPatched;

		private static bool _catchLogged;

		private static bool _catchFailedLogged;

		private static bool _procTriggerLogged;

		private static bool _procTriggerFailedLogged;

		private static readonly ConditionalWeakTable<object, StrongBox<float>> _catchTimers = new ConditionalWeakTable<object, StrongBox<float>>();

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

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_enabled = cfg.Bind<bool>("TendrilGrowth", "Enabled", true, "是否让「触须生长」在花朵存续期间反复捆绑敌人。false = 完全保持原版(每个目标只被拉动、伤害一次)。");
			_interval = cfg.Bind<float>("TendrilGrowth", "PulseInterval", 1.5f, "触须重新捆绑的间隔(秒)。原版是 duration / rootPulseCount。\n这个值会被写进 IL,改完需要重启游戏;填 0 或负数 = 沿用原版间隔。");
			_tendrilLifetime = cfg.Bind<float>("TendrilGrowth", "TendrilLifetime", 1.5f, "每次生成的触须存活多久(秒)。原版是「一直到花朵消失」。\n这个值会被写进 IL,改完需要重启游戏;填 0 或负数 = 沿用原版(一直挂到花谢)。\n和上面的间隔填一样的数,就能做到「旧触须刚消失,新触须立刻捆上」。");
			_damageMultiplier = cfg.Bind<float>("TendrilGrowth", "DamageMultiplier", 1f, "每次捆绑造成的伤害倍率。1 = 和原版那一次伤害一样(200%);\n想削弱持续输出就填 0.5 之类。这个值是运行期读取的。");
			_weakenDuration = cfg.Bind<float>("TendrilGrowth", "WeakenDuration", 3f, "触须每次拉扯时给目标附加的「弱化」时间(秒)。\n弱化 = 雷克斯被动「自然毒素」那个减益(降低移动速度、护甲和伤害),\n也就是 M1 最后一个注射器附带的效果。填 0 或负数 = 不附加弱化。\n这个值会被写进 IL,改完需要重启游戏。");
			_catchInterval = cfg.Bind<float>("TendrilGrowth", "CatchScanInterval", 0.15f, "额外扫描「溜进范围但还没被捆过」的敌人的间隔(秒)。\n原版只在每次脉冲那一刻做一次范围检测,移速快的敌人可能从两次脉冲之间\n直接冲过花朵范围、压根没被捆住。开着这个就会高频补扫,新目标一进范围\n立刻被拉住、吃一次伤害(已有的目标仍按上面的间隔结算,不会多打)。\n填 0 或负数 = 关掉补扫(回到原版那种只在脉冲时检测的行为)。这个值运行期读取。");
			_procCoefficient = cfg.Bind<float>("TendrilGrowth", "ProcCoefficient", 1f, "捆绑伤害的触发系数(procCoefficient)。1 = 每次捆绑都能正常触发道具效果\n(尤克里里、导弹、吸血镰刀等),原版这个技能通常是 0(完全不触发)。\n填负数 = 沿用原版值。这个值运行期读取。");
			_triggerProcs = cfg.Bind<bool>("TendrilGrowth", "TriggerItemProcs", true, "让捆绑伤害走官方的命中流程(TakeDamage 之后补一句 GlobalEventManager.OnHitEnemy),这样道具效果才会真的触发。\n原版花朵只调了 TakeDamage、从没调过 OnHitEnemy,所以哪怕触发系数是 1,\n三尖匕首、尤克里里之类的命中类道具也一次都不会触发。\nfalse = 保持原版(不触发任何命中类道具)。");
		}

		public static string Summary()
		{
			if (_enabled == null || !_enabled.Value)
			{
				return " [触须生长:原版未改动]";
			}
			string text = " [触须生长:每" + IntervalValue().ToString("0.##") + "s 重新捆绑一次,触须存活 " + TendrilLifetimeValue().ToString("0.##") + "s";
			if (WeakenDurationValue() > 0f)
			{
				text = text + ",每次拉扯附加弱化 " + WeakenDurationValue().ToString("0.##") + "s";
			}
			if (CatchIntervalValue() > 0f)
			{
				text += ",新目标进范围立刻捆住";
			}
			float num = ProcCoefficientValue();
			if (num >= 0f)
			{
				text = text + ",触发系数 " + num.ToString("0.##");
			}
			return text + "]";
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_01ff: Expected O, but got Unknown
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Expected O, but got Unknown
			if (!IsEnabled)
			{
				Log((LogLevel)16, "触须生长:按配置保持原版,不挂任何补丁。");
				return;
			}
			_intervalValue = IntervalValue();
			_tendrilValue = TendrilLifetimeValue();
			_weakenValue = WeakenDurationValue();
			_triggerProcsValue = TriggerProcsValue();
			_flowerType = AccessTools.TypeByName("EntityStates.Treebot.TreebotFlower+TreebotFlower2Projectile") ?? AccessTools.TypeByName("EntityStates.Treebot.TreebotFlower.TreebotFlower2Projectile");
			if (_flowerType == null)
			{
				Log((LogLevel)2, "触须生长补丁失败:找不到状态类型 EntityStates.Treebot.TreebotFlower.TreebotFlower2Projectile(EntityStates.Treebot.TreebotFlower+TreebotFlower2Projectile)。");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(_flowerType, "FixedUpdate", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(_flowerType, "RootPulse", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				Log((LogLevel)2, "触须生长补丁失败:取不到方法(FixedUpdate=" + ((methodInfo == null) ? "缺失" : "OK") + ",RootPulse=" + ((methodInfo2 == null) ? "缺失" : "OK") + ")。");
				return;
			}
			bool num = _intervalValue > 0f;
			bool flag = _tendrilValue > 0f;
			if (num)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RexEntangle), "PulseIntervalTranspiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:" + _flowerType.Name + ".FixedUpdate <- PulseIntervalTranspiler(脉冲间隔写死为 " + _intervalValue.ToString("0.##") + "s)");
			}
			else
			{
				Log((LogLevel)16, "脉冲间隔沿用原版 duration / rootPulseCount。");
			}
			_rootPulseMethod = methodInfo2;
			HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(RexEntangle), "RootPulseTranspiler", (Type[])null, (Type[])null));
			harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(AccessTools.Method(typeof(RexEntangle), "RootPulsePrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.Method(typeof(RexEntangle), "RootPulsePostfix", (Type[])null, (Type[])null)), val, (HarmonyMethod)null, (HarmonyMethod)null);
			Log((LogLevel)16, "补丁已挂载:" + _flowerType.Name + ".RootPulse <- RootPulseTranspiler(已捆绑目标不再跳过" + (flag ? (",触须存活写死为 " + _tendrilValue.ToString("0.##") + "s") : ",触须存活沿用原版") + ")");
			float num2 = CatchIntervalValue();
			if (num2 > 0f && _skipContainsPatched)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RexEntangle), "CatchStragglersPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:" + _flowerType.Name + ".FixedUpdate <- CatchStragglersPostfix(每 " + num2.ToString("0.##") + "s 补扫一次新目标)");
			}
			else if (num2 <= 0f)
			{
				Log((LogLevel)16, "补扫按配置关闭:只在每次脉冲那一刻检测范围。");
			}
			else
			{
				Log((LogLevel)4, "补扫未启用:「已捆绑不再跳过」那段 IL 没改成功,开了补扫会变成高频伤害,已跳过。");
			}
		}

		private static float IntervalValue()
		{
			if (_interval != null)
			{
				return _interval.Value;
			}
			return 1.5f;
		}

		private static float TendrilLifetimeValue()
		{
			if (_tendrilLifetime != null)
			{
				return _tendrilLifetime.Value;
			}
			return 1.5f;
		}

		private static float WeakenDurationValue()
		{
			if (_weakenDuration != null)
			{
				return _weakenDuration.Value;
			}
			return 3f;
		}

		private static float CatchIntervalValue()
		{
			if (_catchInterval != null)
			{
				return _catchInterval.Value;
			}
			return 0.15f;
		}

		private static float ProcCoefficientValue()
		{
			if (_procCoefficient != null)
			{
				return _procCoefficient.Value;
			}
			return 1f;
		}

		private static bool TriggerProcsValue()
		{
			if (_triggerProcs != null)
			{
				return _triggerProcs.Value;
			}
			return true;
		}

		public static IEnumerable<CodeInstruction> PulseIntervalTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			FieldInfo fieldInfo = Field("duration");
			FieldInfo fieldInfo2 = Field("rootPulseCount");
			if (fieldInfo == null || fieldInfo2 == null)
			{
				LogResolveFailed("PulseIntervalTranspiler", "duration=" + ((fieldInfo == null) ? "缺失" : "OK") + ",rootPulseCount=" + ((fieldInfo2 == null) ? "缺失" : "OK"));
				return list;
			}
			for (int i = 0; i + 2 < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldsfld && IsField(list[i].operand, fieldInfo) && list[i + 1].opcode == OpCodes.Ldsfld && IsField(list[i + 1].operand, fieldInfo2) && list[i + 2].opcode == OpCodes.Div)
				{
					list[i] = new CodeInstruction(OpCodes.Ldc_R4, (object)_intervalValue);
					list[i + 1] = new CodeInstruction(OpCodes.Nop, (object)null);
					list[i + 2] = new CodeInstruction(OpCodes.Nop, (object)null);
					Log((LogLevel)16, "脉冲间隔已改写为 " + _intervalValue.ToString("0.##") + "s(原版是 duration / rootPulseCount)。");
					return list;
				}
			}
			Log((LogLevel)2, "脉冲间隔改写失败:FixedUpdate 里没找到 duration / rootPulseCount。");
			return list;
		}

		public static IEnumerable<CodeInstruction> RootPulseTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			//IL_0833: Unknown result type (might be due to invalid IL or missing references)
			//IL_083d: Expected O, but got Unknown
			//IL_0849: Unknown result type (might be due to invalid IL or missing references)
			//IL_0853: Expected O, but got Unknown
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Expected O, but got Unknown
			//IL_04af: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b5: Expected O, but got Unknown
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Expected O, but got Unknown
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Expected O, but got Unknown
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Expected O, but got Unknown
			//IL_06cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d3: Expected O, but got Unknown
			//IL_06f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f9: Expected O, but got Unknown
			//IL_0702: Unknown result type (might be due to invalid IL or missing references)
			//IL_0708: Expected O, but got Unknown
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			FieldInfo fieldInfo = Field("rootedBodies");
			FieldInfo fieldInfo2 = Field("duration");
			if (fieldInfo != null)
			{
				FieldInfo fieldInfo3 = AccessTools.Field(typeof(RexEntangle), "CatchOnlyNew");
				int num = 0;
				if (fieldInfo3 == null)
				{
					Log((LogLevel)2, "已捆绑判定改写失败:取不到字段 CatchOnlyNew。");
				}
				else
				{
					for (int i = 3; i + 1 < list.Count; i++)
					{
						MethodInfo methodInfo = list[i].operand as MethodInfo;
						bool flag = list[i + 1].opcode == OpCodes.Brtrue || list[i + 1].opcode == OpCodes.Brtrue_S;
						if (list[i].opcode == OpCodes.Callvirt && methodInfo != null && methodInfo.Name == "Contains" && flag && PrecededBy(list, i, 3, OpCodes.Ldfld, fieldInfo))
						{
							list.InsertRange(i + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
							{
								new CodeInstruction(OpCodes.Ldsfld, (object)fieldInfo3),
								new CodeInstruction(OpCodes.And, (object)null)
							});
							num++;
							i += 2;
						}
					}
					if (num > 0)
					{
						_skipContainsPatched = true;
						Log((LogLevel)16, "已捆绑判定已改写(" + num + " 处:跳过条件变成「已捆绑 且 本次是补抓调用」):正常脉冲时被捆住的目标每轮都会再拉一次、再吃一次伤害;补扫只处理新目标。");
					}
					else
					{
						Log((LogLevel)2, "已捆绑判定改写失败:RootPulse 里没找到 rootedBodies.Contains + brtrue。");
					}
				}
			}
			else
			{
				LogResolveFailed("RootPulseTranspiler", "rootedBodies=缺失");
			}
			if (_tendrilValue > 0f)
			{
				if (fieldInfo2 != null)
				{
					bool flag2 = false;
					for (int j = 1; j + 4 < list.Count; j++)
					{
						MethodInfo methodInfo2 = list[j + 4].operand as MethodInfo;
						if (list[j].opcode == OpCodes.Ldsfld && IsField(list[j].operand, fieldInfo2) && list[j + 1].opcode == OpCodes.Ldarg_0 && list[j + 2].opcode == OpCodes.Call && list[j + 3].opcode == OpCodes.Sub && list[j + 4].opcode == OpCodes.Call && methodInfo2 != null && methodInfo2.Name == "Max" && list[j - 1].opcode == OpCodes.Ldc_R4)
						{
							list[j - 1] = new CodeInstruction(OpCodes.Ldc_R4, (object)_tendrilValue);
							for (int k = j; k <= j + 4; k++)
							{
								list[k] = new CodeInstruction(OpCodes.Nop, (object)null);
							}
							flag2 = true;
							Log((LogLevel)16, "触须存活时间已改写为 " + _tendrilValue.ToString("0.##") + "s(原版是一直挂到花朵消失)。");
							break;
						}
					}
					if (!flag2)
					{
						Log((LogLevel)2, "触须存活时间改写失败:RootPulse 里没找到 Mathf.Max(0.2, duration - fixedAge)。");
					}
				}
				else
				{
					LogResolveFailed("RootPulseTranspiler(触须存活)", "duration=缺失");
				}
			}
			if (_weakenValue > 0f)
			{
				FieldInfo fieldInfo4 = WeakBuffField();
				MethodInfo methodInfo3 = AddTimedBuffMethod(fieldInfo4);
				if (fieldInfo4 == null || methodInfo3 == null)
				{
					Log((LogLevel)2, "弱化附加失败:取不到 RoR2Content.Buffs.Weak(" + ((fieldInfo4 == null) ? "缺失" : "OK") + ")或 CharacterBody.AddTimedBuff(" + ((methodInfo3 == null) ? "缺失" : "OK") + ")。");
				}
				else
				{
					bool flag3 = false;
					for (int l = 1; l + 1 < list.Count; l++)
					{
						if (flag3)
						{
							break;
						}
						FieldInfo fieldInfo5 = list[l].operand as FieldInfo;
						if (!(list[l].opcode != OpCodes.Ldsfld) && !(fieldInfo5 == null) && !(fieldInfo5.Name != "Entangle") && !(list[l + 1].opcode != OpCodes.Callvirt))
						{
							CodeInstruction val = list[l - 1];
							if (IsLoadLocal(val.opcode))
							{
								list.InsertRange(l + 2, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[4]
								{
									new CodeInstruction(val.opcode, val.operand),
									new CodeInstruction(OpCodes.Ldsfld, (object)fieldInfo4),
									new CodeInstruction(OpCodes.Ldc_R4, (object)_weakenValue),
									new CodeInstruction(OpCodes.Callvirt, (object)methodInfo3)
								});
								flag3 = true;
								Log((LogLevel)16, "弱化附加已插入:每次拉扯给目标 " + _weakenValue.ToString("0.##") + "s 弱化(RoR2Content.Buffs.Weak)。");
							}
						}
					}
					if (!flag3)
					{
						Log((LogLevel)2, "弱化附加失败:RootPulse 里没找到 AddBuff(Entangle) 那一段。");
					}
				}
			}
			if (_triggerProcsValue)
			{
				MethodInfo methodInfo4 = AccessTools.Method(typeof(RexEntangle), "TriggerOnHit", (Type[])null, (Type[])null);
				FieldInfo fieldInfo6 = AccessTools.Field(typeof(HurtBox), "healthComponent");
				if (methodInfo4 == null || fieldInfo6 == null)
				{
					Log((LogLevel)2, "命中流程接入失败:取不到 TriggerOnHit(" + ((methodInfo4 == null) ? "缺失" : "OK") + ")或 HurtBox.healthComponent(" + ((fieldInfo6 == null) ? "缺失" : "OK") + ")。");
				}
				else
				{
					bool flag4 = false;
					for (int m = 3; m < list.Count; m++)
					{
						if (flag4)
						{
							break;
						}
						MethodInfo methodInfo5 = list[m].operand as MethodInfo;
						if (!(list[m].opcode != OpCodes.Callvirt) && !(methodInfo5 == null) && !(methodInfo5.Name != "TakeDamage") && IsLoadLocal(list[m - 1].opcode) && !(list[m - 2].opcode != OpCodes.Ldfld) && IsField(list[m - 2].operand, fieldInfo6) && IsLoadLocal(list[m - 3].opcode))
						{
							list.InsertRange(m + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
							{
								new CodeInstruction(list[m - 1].opcode, list[m - 1].operand),
								new CodeInstruction(list[m - 3].opcode, list[m - 3].operand),
								new CodeInstruction(OpCodes.Call, (object)methodInfo4)
							});
							flag4 = true;
							Log((LogLevel)16, "命中流程已接入:TakeDamage 之后补一句 GlobalEventManager.OnHitEnemy(照抄官方 FireSonicBoom 的写法),现在捆绑伤害能正常触发三尖匕首、尤克里里之类的道具了。");
						}
					}
					if (!flag4)
					{
						Log((LogLevel)2, "命中流程接入失败:RootPulse 里没找到 hurtBox.healthComponent.TakeDamage。");
					}
				}
			}
			FieldInfo fieldInfo7 = Field("procCoefficient");
			MethodInfo methodInfo6 = AccessTools.Method(typeof(RexEntangle), "CurrentProcCoefficient", (Type[])null, (Type[])null);
			if (fieldInfo7 == null || methodInfo6 == null)
			{
				Log((LogLevel)2, "触发系数 IL 改写失败:取不到字段 procCoefficient(" + ((fieldInfo7 == null) ? "缺失" : "OK") + ")或方法 CurrentProcCoefficient(" + ((methodInfo6 == null) ? "缺失" : "OK") + ")。");
			}
			else
			{
				bool flag5 = false;
				for (int n = 0; n + 1 < list.Count; n++)
				{
					if (flag5)
					{
						break;
					}
					if (IsLoadArg0(list[n]) && !(list[n + 1].opcode != OpCodes.Ldfld) && IsField(list[n + 1].operand, fieldInfo7))
					{
						list[n] = new CodeInstruction(OpCodes.Nop, (object)null);
						list[n + 1] = new CodeInstruction(OpCodes.Call, (object)methodInfo6);
						flag5 = true;
						Log((LogLevel)16, "触发系数 IL 已改写:DamageInfo.procCoefficient 现在直接取配置值(当前 " + CurrentProcCoefficient().ToString("0.##") + "),每次捆绑都能触发道具效果;原版字段值见首次扎根那行日志。");
					}
				}
				if (!flag5)
				{
					Log((LogLevel)2, "触发系数 IL 改写失败:RootPulse 里没找到 ldarg.0 / ldfld procCoefficient。");
				}
			}
			return list;
		}

		public static void CatchStragglersPostfix(object __instance)
		{
			try
			{
				if (!IsEnabled || __instance == null || _rootPulseMethod == null)
				{
					return;
				}
				float interval = CatchIntervalValue();
				if (interval <= 0f)
				{
					return;
				}
				float num = Time.fixedDeltaTime;
				if (num <= 0f)
				{
					num = Time.deltaTime;
				}
				StrongBox<float> value = _catchTimers.GetValue(__instance, (object k) => new StrongBox<float>(interval));
				value.Value -= num;
				if (!(value.Value > 0f))
				{
					value.Value = interval;
					CatchOnlyNew = true;
					try
					{
						_rootPulseMethod.Invoke(__instance, null);
					}
					finally
					{
						CatchOnlyNew = false;
					}
					if (!_catchLogged)
					{
						_catchLogged = true;
						Log((LogLevel)16, "补扫已启用:每 " + interval.ToString("0.##") + "s 额外检测一次范围内的新目标(持续伤害仍按每 " + ((_intervalValue > 0f) ? _intervalValue.ToString("0.##") : "原版") + "s 结算)。");
					}
				}
			}
			catch (Exception ex)
			{
				if (!_catchFailedLogged)
				{
					_catchFailedLogged = true;
					Log((LogLevel)4, "补扫调用异常(已忽略,之后不再提示):" + ex.GetType().Name + " " + ex.Message);
				}
			}
		}

		private static void ApplyProcCoefficient(object instance)
		{
			float num = ProcCoefficientValue();
			if (num < 0f || instance == null)
			{
				return;
			}
			FieldInfo fieldInfo = Field("procCoefficient");
			if (fieldInfo == null)
			{
				if (!_procCoefficientFieldFailedLogged)
				{
					_procCoefficientFieldFailedLogged = true;
					Log((LogLevel)2, "触发系数未生效:取不到字段 procCoefficient。");
				}
				return;
			}
			float num2 = Convert.ToSingle(fieldInfo.GetValue(instance));
			if (float.IsNaN(_vanillaProcCoefficient))
			{
				_vanillaProcCoefficient = num2;
			}
			if (!(Mathf.Abs(num2 - num) < 0.0001f))
			{
				fieldInfo.SetValue(instance, num);
				if (!_procCoefficientLogged)
				{
					_procCoefficientLogged = true;
					Log((LogLevel)16, "触发系数(实例字段覆写)已设为 " + num.ToString("0.##") + "(原版 " + _vanillaProcCoefficient.ToString("0.##") + ")。");
				}
			}
		}

		public static float CurrentProcCoefficient()
		{
			float num = ProcCoefficientValue();
			if (num < 0f)
			{
				if (!float.IsNaN(_vanillaProcCoefficient))
				{
					return _vanillaProcCoefficient;
				}
				return 0f;
			}
			return num;
		}

		public static void RootPulsePrefix(object __instance)
		{
			_storedDamage = float.NaN;
			try
			{
				ApplyProcCoefficient(__instance);
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "触发系数(实例字段覆写)异常,IL 改写那路仍会生效:" + ex.GetType().Name + " " + ex.Message);
			}
			try
			{
				if (_enabled == null || !_enabled.Value || __instance == null || _damageMultiplier == null)
				{
					return;
				}
				float value = _damageMultiplier.Value;
				if (value <= 0f || Mathf.Abs(value - 1f) < 0.001f)
				{
					return;
				}
				FieldInfo fieldInfo = Field("damage");
				if (fieldInfo == null)
				{
					if (!_damageFieldFailedLogged)
					{
						_damageFieldFailedLogged = true;
						Log((LogLevel)2, "伤害倍率未生效:取不到字段 damage。");
					}
				}
				else
				{
					float num = Convert.ToSingle(fieldInfo.GetValue(__instance));
					fieldInfo.SetValue(__instance, num * value);
					_storedDamage = num;
				}
			}
			catch (Exception ex2)
			{
				Log((LogLevel)4, "伤害倍率改写异常(已忽略):" + ex2.GetType().Name + " " + ex2.Message);
			}
		}

		public static void RootPulsePostfix(object __instance)
		{
			try
			{
				if (!float.IsNaN(_storedDamage) && __instance != null)
				{
					FieldInfo fieldInfo = Field("damage");
					if (fieldInfo != null)
					{
						fieldInfo.SetValue(__instance, _storedDamage);
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "伤害倍率还原异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
			finally
			{
				_storedDamage = float.NaN;
			}
			if (_firstPulseLogged)
			{
				return;
			}
			_firstPulseLogged = true;
			try
			{
				FieldInfo fieldInfo2 = Field("duration");
				FieldInfo fieldInfo3 = Field("rootPulseCount");
				if (!(fieldInfo2 == null) && !(fieldInfo3 == null))
				{
					float num = Convert.ToSingle(fieldInfo2.GetValue(null));
					float num2 = Convert.ToSingle(fieldInfo3.GetValue(null));
					float num3 = ((num2 > 0f) ? (num / num2) : num);
					float num4 = ((_intervalValue > 0f) ? _intervalValue : num3);
					float num5 = ((_tendrilValue > 0f) ? _tendrilValue : num3);
					string text = (float.IsNaN(_vanillaProcCoefficient) ? "未知" : _vanillaProcCoefficient.ToString("0.##"));
					Log((LogLevel)16, "触须生长已生效:花朵存活 " + num.ToString("0.##") + "s,原版脉冲间隔 " + num3.ToString("0.##") + "s → 现在 " + num4.ToString("0.##") + "s;触须存活 " + num5.ToString("0.##") + "s;触发系数 " + text + " → " + ((ProcCoefficientValue() < 0f) ? "沿用原版" : ProcCoefficientValue().ToString("0.##")) + "。");
					LogFlowerSnapshot(__instance);
				}
			}
			catch (Exception ex2)
			{
				Log((LogLevel)4, "读取原版节奏失败(已忽略):" + ex2.GetType().Name + " " + ex2.Message);
			}
		}

		private static FieldInfo Field(string name)
		{
			if (_flowerType == null)
			{
				return null;
			}
			return AccessTools.Field(_flowerType, name);
		}

		private static bool IsField(object operand, FieldInfo field)
		{
			FieldInfo fieldInfo = operand as FieldInfo;
			if (fieldInfo == null || field == null)
			{
				return false;
			}
			if (!(fieldInfo == field) && !fieldInfo.Equals(field))
			{
				if (fieldInfo.Name == field.Name)
				{
					return fieldInfo.DeclaringType == field.DeclaringType;
				}
				return false;
			}
			return true;
		}

		private static bool PrecededBy(List<CodeInstruction> list, int i, int back, OpCode opcode, FieldInfo field)
		{
			for (int j = Mathf.Max(0, i - back); j < i; j++)
			{
				if (list[j].opcode == opcode && IsField(list[j].operand, field))
				{
					return true;
				}
			}
			return false;
		}

		public static void TriggerOnHit(DamageInfo damageInfo, HurtBox hurtBox)
		{
			try
			{
				GlobalEventManager instance = GlobalEventManager.instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)hurtBox == (Object)null)
				{
					return;
				}
				HealthComponent healthComponent = hurtBox.healthComponent;
				if (!((Object)(object)healthComponent == (Object)null))
				{
					instance.OnHitEnemy(damageInfo, ((Component)healthComponent).gameObject);
					if (!_procTriggerLogged)
					{
						_procTriggerLogged = true;
						Log((LogLevel)16, "捆绑伤害已接入命中流程:触发系数 " + damageInfo.procCoefficient.ToString("0.##") + ",attacker=" + (((Object)(object)damageInfo.attacker == (Object)null) ? "null" : ((Object)damageInfo.attacker).name) + ",victim=" + ((Object)((Component)healthComponent).gameObject).name);
					}
				}
			}
			catch (Exception ex)
			{
				if (!_procTriggerFailedLogged)
				{
					_procTriggerFailedLogged = true;
					Log((LogLevel)4, "命中流程调用异常(已忽略,之后不再提示):" + ex.GetType().Name + " " + ex.Message);
				}
			}
		}

		private static void LogFlowerSnapshot(object instance)
		{
			if (instance == null)
			{
				return;
			}
			try
			{
				string text = "缺失";
				FieldInfo fieldInfo = Field("owner");
				if (fieldInfo != null)
				{
					object? value = fieldInfo.GetValue(instance);
					Object val = (Object)((value is Object) ? value : null);
					text = ((val == (Object)null) ? "null" : (val.name + "(" + ((object)val).GetType().Name + ")"));
				}
				string text2 = "缺失";
				FieldInfo fieldInfo2 = Field("procChainMask");
				if (fieldInfo2 != null)
				{
					object value2 = fieldInfo2.GetValue(instance);
					text2 = ((value2 == null) ? "null" : value2.ToString());
				}
				string text3 = "缺失";
				FieldInfo fieldInfo3 = Field("damageType");
				if (fieldInfo3 != null)
				{
					object value3 = fieldInfo3.GetValue(instance);
					text3 = ((value3 == null) ? "null" : value3.ToString());
				}
				string text4 = "缺失";
				FieldInfo fieldInfo4 = Field("procCoefficient");
				if (fieldInfo4 != null)
				{
					text4 = Convert.ToSingle(fieldInfo4.GetValue(instance)).ToString("0.###");
				}
				Log((LogLevel)16, "花朵字段快照:procCoefficient=" + text4 + ",procChainMask=" + text2 + ",damageType=" + text3 + ",owner=" + text + "。");
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "花朵字段快照失败(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static FieldInfo WeakBuffField()
		{
			Type type = typeof(CharacterBody).Assembly.GetType("RoR2.RoR2Content+Buffs");
			if (type == null)
			{
				type = AccessTools.TypeByName("RoR2.RoR2Content+Buffs");
			}
			if (!(type == null))
			{
				return AccessTools.Field(type, "Weak");
			}
			return null;
		}

		private static MethodInfo AddTimedBuffMethod(FieldInfo weakField)
		{
			Type type = ((weakField != null) ? weakField.FieldType : AccessTools.TypeByName("RoR2.BuffIndex"));
			if (type == null)
			{
				return null;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(CharacterBody), "AddTimedBuff", new Type[2]
			{
				type,
				typeof(float)
			}, (Type[])null);
			if (methodInfo != null)
			{
				return methodInfo;
			}
			MethodInfo[] methods = typeof(CharacterBody).GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo2 in methods)
			{
				if (!(methodInfo2.Name != "AddTimedBuff"))
				{
					ParameterInfo[] parameters = methodInfo2.GetParameters();
					if (parameters.Length == 2 && parameters[0].ParameterType == type && parameters[1].ParameterType == typeof(float))
					{
						return methodInfo2;
					}
				}
			}
			return null;
		}

		private static bool IsLoadArg0(CodeInstruction ins)
		{
			if (ins.opcode == OpCodes.Ldarg_0)
			{
				return true;
			}
			if (ins.opcode != OpCodes.Ldarg && ins.opcode != OpCodes.Ldarg_S)
			{
				return false;
			}
			try
			{
				return Convert.ToInt32(ins.operand) == 0;
			}
			catch (Exception)
			{
				return false;
			}
		}

		private static bool IsLoadLocal(OpCode opcode)
		{
			if (!(opcode == OpCodes.Ldloc) && !(opcode == OpCodes.Ldloc_S) && !(opcode == OpCodes.Ldloc_0) && !(opcode == OpCodes.Ldloc_1) && !(opcode == OpCodes.Ldloc_2))
			{
				return opcode == OpCodes.Ldloc_3;
			}
			return true;
		}

		private static void LogResolveFailed(string where, string detail)
		{
			if (!_fieldResolveFailedLogged)
			{
				_fieldResolveFailedLogged = true;
				Log((LogLevel)2, "触须生长未生效:" + where + " 取不到字段(" + detail + ")。");
			}
		}

		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);
			}
		}

		private static void LogThrottled(string message)
		{
			if (!(Time.time - _lastLogAt < 3f))
			{
				_lastLogAt = Time.time;
				Log((LogLevel)16, message);
			}
		}
	}
	public static class RexFruitHarvest
	{
		private const string BuffAssetName = "SparkleRexFruitHarvest";

		private const string RexBodyNameToken = "TREEBOT_BODY_NAME";

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<float> _healthPercentPerStack;

		private static ConfigEntry<int> _maxStacks;

		private static ConfigEntry<bool> _onlyRex;

		private static ConfigEntry<bool> _onlyHarvestFruit;

		private static ConfigEntry<string> _fruitNameFilter;

		private static ManualLogSource _log;

		private static BuffDef _buffDef;

		private static BuffIndex _buffIndex = (BuffIndex)(-1);

		private static bool _buffIndexTried;

		private static FieldInfo _aliveField;

		private static FieldInfo _baseObjectField;

		private static FieldInfo _teamFilterField;

		private static bool _fieldsTried;

		private static MethodInfo _maxHealthSetter;

		private static FieldInfo _maxHealthField;

		private static bool _maxHealthWriterTried;

		private static bool _iconResolved;

		private static bool _grantedLogged;

		private static bool _statsLogged;

		private static readonly ConditionalWeakTable<HealthPickup, StrongBox<bool>> AlreadyGranted = new ConditionalWeakTable<HealthPickup, StrongBox<bool>>();

		private static readonly HashSet<string> _unknownFruitNames = new HashSet<string>();

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

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_enabled = cfg.Bind<bool>("Harvest", "Enabled", true, "是否启用「拾取治疗果实获得一层生机」:雷克斯捡起「命令:收割」掉落的果实后,\n获得一层可叠加的 buff,每层提升 1% 最大生命值(普通 buff,下一关清空)。");
			_healthPercentPerStack = cfg.Bind<float>("Harvest", "HealthPercentPerStack", 1f, "每层 buff 提升的最大生命值百分比(1 = 每层 +1%)。\n和游戏里的「珍珠」一样是按<b>当前最大生命值</b>的比例加成,\n所以等级越高、最大生命值越大,每层加的血也越多。这个值是运行期读取的。");
			_maxStacks = cfg.Bind<int>("Harvest", "MaxStacks", 0, "层数上限。0 = 不限制。这个值是运行期读取的。");
			_onlyRex = cfg.Bind<bool>("Harvest", "OnlyRex", true, "只有雷克斯(Treebot)拾取果实才给 buff。false = 任何角色捡到都给。");
			_onlyHarvestFruit = cfg.Bind<bool>("Harvest", "OnlyHarvestFruit", true, "只认「命令:收割」掉落的果实(按果实对象名匹配)。\nfalse = 任何带 HealthPickup 的治疗拾取物都算(比如星际书桌植物种的果实)。");
			_fruitNameFilter = cfg.Bind<string>("Harvest", "FruitObjectName", "TreebotFruitPack", "果实对象名关键字(不区分大小写)。游戏改版导致名字变了可以在这里改,不用重新编译。");
			TryCreateBuff();
			AddLanguage();
		}

		public static string Summary()
		{
			if (!IsEnabled)
			{
				return " [果实:原版未改动]";
			}
			if ((Object)(object)_buffDef == (Object)null)
			{
				return " [果实:buff 注册失败]";
			}
			return " [果实:拾取治疗果实 +" + HealthPercentPerStack().ToString("0.##") + "% 最大生命值/层(随等级成长)]";
		}

		private static float HealthPercentPerStack()
		{
			if (_healthPercentPerStack == null)
			{
				return 1f;
			}
			return _healthPercentPerStack.Value;
		}

		private static int MaxStacksValue()
		{
			if (_maxStacks == null)
			{
				return 0;
			}
			return _maxStacks.Value;
		}

		private static bool OnlyRexValue()
		{
			if (_onlyRex != null)
			{
				return _onlyRex.Value;
			}
			return true;
		}

		private static bool OnlyHarvestFruitValue()
		{
			if (_onlyHarvestFruit != null)
			{
				return _onlyHarvestFruit.Value;
			}
			return true;
		}

		private static void TryCreateBuff()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				BuffDef val = ScriptableObject.CreateInstance<BuffDef>();
				((Object)val).name = "SparkleRexFruitHarvest";
				val.canStack = true;
				val.isDebuff = false;
				val.isHidden = false;
				val.isCooldown = false;
				val.isDOT = false;
				val.buffColor = new Color(0.42f, 0.88f, 0.34f, 1f);
				if (!ContentAddition.AddBuffDef(val))
				{
					Log((LogLevel)2, "果实生机:R2API 拒绝了自定义 buff(AddBuffDef 返回 false),本功能不会生效。");
					return;
				}
				_buffDef = val;
				Log((LogLevel)16, "果实生机:自定义 buff 已注册(SparkleRexFruitHarvest)。");
			}
			catch (Exception ex)
			{
				Log((LogLevel)2, "果实生机:注册 buff 失败 —— " + ex.GetType().Name + " " + ex.Message + "。请确认安装了 R2API 的 ContentManagement 模块。");
				_buffDef = null;
			}
		}

		private static void ResolveIcon()
		{
			if (_iconResolved || (Object)(object)_buffDef == (Object)null)
			{
				return;
			}
			_iconResolved = true;
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(BuffCatalog), "buffDefs");
				BuffDef[] array = ((fieldInfo != null) ? (fieldInfo.GetValue(null) as BuffDef[]) : null);
				if (array == null)
				{
					return;
				}
				foreach (BuffDef val in array)
				{
					if (!((Object)(object)val == (Object)null) && !((Object)(object)val.iconSprite == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && ((Object)val).name.IndexOf("fruiting", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						_buffDef.iconSprite = val.iconSprite;
						Log((LogLevel)16, "果实生机:buff 图标已借用 " + ((Object)val).name + " 的图标。");
						break;
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "果实生机:取图标失败(不影响数值)—— " + ex.Message);
			}
		}

		private static void AddLanguage()
		{
			string text = "果实生机";
			string text2 = "每层使<style=cIsHealing>最大生命值</style>提升 " + HealthPercentPerStack().ToString("0.##") + "%(按当前最大生命值计算,随等级成长)。";
			string text3 = "Harvest Vitality";
			string text4 = "Increases <style=cIsHealing>maximum health</style> by " + HealthPercentPerStack().ToString("0.##") + "% per stack.";
			string[] array = new string[3] { "BUFF_SPARKLEREXFRUITHARVEST_NAME", "SparkleRexFruitHarvest_NAME", "SparkleRexFruitHarvest" };
			foreach (string obj in array)
			{
				LanguageAPI.Add(obj, text, "zh-CN");
				LanguageAPI.Add(obj, text3, "en");
			}
			array = new string[2] { "BUFF_SPARKLEREXFRUITHARVEST_DESCRIPTION", "SparkleRexFruitHarvest_DESCRIPTION" };
			foreach (string obj2 in array)
			{
				LanguageAPI.Add(obj2, text2, "zh-CN");
				LanguageAPI.Add(obj2, text4, "en");
			}
		}

		private static bool EnsureBuffIndex()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_001e: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if ((int)_buffIndex != -1)
			{
				return true;
			}
			if ((Object)(object)_buffDef == (Object)null)
			{
				return false;
			}
			int num = Convert.ToInt32(_buffDef.buffIndex);
			if (num < 0)
			{
				object obj = BuffCatalog.FindBuffIndex(((Object)_buffDef).name);
				num = ((obj == null) ? (-1) : Convert.ToInt32(obj));
			}
			if (num < 0)
			{
				if (!_buffIndexTried)
				{
					_buffIndexTried = true;
					Log((LogLevel)4, "果实生机:还没拿到自定义 buff 的序号(BuffCatalog 未初始化?),稍后自动重试。");
				}
				return false;
			}
			_buffIndex = (BuffIndex)Enum.ToObject(typeof(BuffIndex), num);
			Log((LogLevel)16, "果实生机:buff 序号已定位(" + num + ")。");
			return true;
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			if (!IsEnabled)
			{
				Log((LogLevel)16, "果实生机:按配置保持原版,不挂任何补丁。");
				return;
			}
			if ((Object)(object)_buffDef == (Object)null)
			{
				Log((LogLevel)4, "果实生机:buff 没注册成功,不挂补丁。");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(HealthPickup), "OnTriggerStay", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log((LogLevel)2, "果实生机补丁失败:取不到 HealthPickup.OnTriggerStay。");
			}
			else
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(RexFruitHarvest), "HealthPickupPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log((LogLevel)16, "补丁已挂载:HealthPickup.OnTriggerStay <- HealthPickupPrefix(拾取果实发一层 buff)");
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(CharacterBody), "RecalculateStats", (Type[])null, (Type[])null);
			if (methodInfo2 == null)
			{
				Log((LogLevel)2, "果实生机补丁失败:取不到 CharacterBody.RecalculateStats。");
				return;
			}
			harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RexFruitHarvest), "RecalculateStatsPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log((LogLevel)16, "补丁已挂载:CharacterBody.RecalculateStats <- RecalculateStatsPostfix(按层数放大最终 maxHealth,并补上差值)");
		}

		public static void HealthPickupPrefix(HealthPickup __instance, Collider other)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!IsEnabled || (Object)(object)__instance == (Object)null || (Object)(object)other == (Object)null || !NetworkServer.active || !IsAlive(__instance))
				{
					return;
				}
				GameObject gameObject = ((Component)other).gameObject;
				if ((Object)(object)gameObject == (Object)null)
				{
					return;
				}
				int num = FruitTeamIndex(__instance);
				int num2 = Convert.ToInt32(TeamComponent.GetObjectTeam(gameObject));
				if (num >= 0 && num2 != num)
				{
					return;
				}
				CharacterBody component = ((Component)other).GetComponent<CharacterBody>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				if (OnlyHarvestFruitValue() && !IsHarvestFruit(__instance))
				{
					LogUnknownFruit(FruitName(__instance));
				}
				else
				{
					if ((OnlyRexValue() && !IsRex(component)) || AlreadyGranted.TryGetValue(__instance, out var _))
					{
						return;
					}
					AlreadyGranted.Add(__instance, new StrongBox<bool>(value: true));
					ResolveIcon();
					if (!EnsureBuffIndex())
					{
						return;
					}
					int buffCount = component.GetBuffCount(_buffIndex);
					int num3 = MaxStacksValue();
					if (num3 <= 0 || buffCount < num3)
					{
						component.AddBuff(_buffIndex);
						if (!_grantedLogged)
						{
							_grantedLogged = true;
							Log((LogLevel)16, "果实生机已生效:" + ((Object)component).name + " 拾取 " + FruitName(__instance) + ",第 " + (buffCount + 1) + " 层 —— 最大生命值 +" + (HealthPercentPerStack() * (float)(buffCount + 1)).ToString("0.##") + "%");
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "果实生机:拾取判定异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		public static void RecalculateStatsPostfix(CharacterBody __instance)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!IsEnabled || (Object)(object)__instance == (Object)null || !EnsureBuffIndex())
				{
					return;
				}
				int num = __instance.GetBuffCount(_buffIndex);
				if (num <= 0)
				{
					return;
				}
				int num2 = MaxStacksValue();
				if (num2 > 0 && num > num2)
				{
					num = num2;
				}
				float maxHealth = __instance.maxHealth;
				float num3 = maxHealth * (1f + HealthPercentPerStack() / 100f * (float)num);
				if (num3 <= maxHealth)
				{
					return;
				}
				SetMaxHealth(__instance, num3);
				HealthComponent healthComponent = __instance.healthComponent;
				if (!((Object)(object)healthComponent == (Object)null))
				{
					float num4 = num3 - maxHealth;
					if (num4 > 0f)
					{
						healthComponent.Heal(num4, default(ProcChainMask), false);
					}
					else if (healthComponent.health > num3)
					{
						healthComponent.Networkhealth = Mathf.Max(healthComponent.health + num4, num3);
					}
					if (!_statsLogged)
					{
						_statsLogged = true;
						Log((LogLevel)16, "果实生机:属性已加成 —— " + ((Object)__instance).name + " 等级 " + __instance.level + ",层数 " + num + ",最大生命值 " + maxHealth.ToString("0.#") + " → " + num3.ToString("0.#"));
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "果实生机:属性结算异常(已忽略)—— " + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static bool SetMaxHealth(CharacterBody body, float value)
		{
			EnsureMaxHealthWriter();
			if (_maxHealthSetter != null)
			{
				_maxHealthSetter.Invoke(body, new object[1] { value });
				return true;
			}
			if (_maxHealthField != null)
			{
				_maxHealthField.SetValue(body, value);
				return true;
			}
			return false;
		}

		private static void EnsureMaxHealthWriter()
		{
			if (!_maxHealthWriterTried)
			{
				_maxHealthWriterTried = true;
				_maxHealthField = AccessTools.Field(typeof(CharacterBody), "<maxHealth>k__BackingField");
				if (_maxHealthField == null)
				{
					_maxHealthField = AccessTools.Field(typeof(CharacterBody), "maxHealth");
				}
				_maxHealthSetter = typeof(CharacterBody).GetProperty("maxHealth", BindingFlags.Instance | BindingFlags.Public).GetSetMethod(nonPublic: true);
				if (_maxHealthField == null && _maxHealthSetter == null)
				{
					Log((LogLevel)2, "果实生机:取不到 CharacterBody.maxHealth 的写入方式,生命值加成不会生效。");
				}
			}
		}

		private static void EnsureFields()
		{
			if (!_fieldsTried)
			{
				_fieldsTried = true;
				_aliveField = AccessTools.Field(typeof(HealthPickup), "alive");
				_baseObjectField = AccessTools.Field(typeof(HealthPickup), "baseObject");
				_teamFilterField = AccessTools.Field(typeof(HealthPickup), "teamFilter");
			}
		}

		private static bool IsAlive(HealthPickup pickup)
		{
			EnsureFields();
			if (_aliveField == null)
			{
				return true;
			}
			object value = _aliveField.GetValue(pickup);
			if (value != null)
			{
				return Convert.ToBoolean(value);
			}
			return true;
		}

		private static int FruitTeamIndex(HealthPickup pickup)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			EnsureFields();
			if (_teamFilterField == null)
			{
				return -1;
			}
			object? value = _teamFilterField.GetValue(pickup);
			TeamFilter val = (TeamFilter)((value is TeamFilter) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return -1;
			}
			return Convert.ToInt32(val.teamIndex);
		}

		private static string FruitName(HealthPickup pickup)
		{
			EnsureFields();
			GameObject val = (GameObject)((_baseObjectField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name))
			{
				return ((Object)val).name;
			}
			if (!((Object)(object)((Component)pickup).gameObject != (Object)null))
			{
				return "(未知)";
			}
			return ((Object)((Component)pickup).gameObject).name;
		}

		private static bool IsHarvestFruit(HealthPickup pickup)
		{
			string text = ((_fruitNameFilter != null) ? _fruitNameFilter.Value : "TreebotFruitPack");
			if (string.IsNullOrEmpty(text))
			{
				return true;
			}
			if (!NameMatches(FruitName(pickup), text))
			{
				return NameMatches(((Object)(object)((Component)pickup).gameObject != (Object)null) ? ((Object)((Component)pickup).gameObject).name : null, text);
			}
			return true;
		}

		private static bool NameMatches(string name, string filter)
		{
			if (!string.IsNullOrEmpty(name))
			{
				return name.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static void LogUnknownFruit(string name)
		{
			if (!string.IsNullOrEmpty(name) && !_unknownFruitNames.Contains(name))
			{
				_unknownFruitNames.Add(name);
				Log((LogLevel)16, "果实生机:跳过了一个治疗拾取物(对象名 " + name + ")—— 如果它就是「命令:收割」掉落的果实,请把 Harvest/FruitObjectName 改成 " + name + " 的一部分。");
			}
		}

		private static bool IsRex(CharacterBody body)
		{
			if (!string.IsNullOrEmpty(body.baseNameToken) && string.Equals(body.baseNameToken, "TREEBOT_BODY_NAME", StringComparison.Ordinal))
			{
				return true;
			}
			if (!string.IsNullOrEmpty(((Object)body).name))
			{
				return ((Object)body).name.IndexOf("TreebotBody", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		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);
			}
		}
	}
	public static class RexSelfHarm
	{
		private const int Sentinel = int.MaxValue;

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<bool> _skipCurse;

		private static ConfigEntry<bool> _onlyTreebot;

		private static ManualLogSource _log;

		private static FieldInfo _comboDamageType;

		private static bool _firstSuppressLogged;

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

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_enabled = cfg.Bind<bool>("SelfHarm", "Enabled", true, "是否处理技能自伤在日食难度下的副作用。false = 完全保持原版。");
			_skipCurse = cfg.Bind<bool>("SelfHarm", "SkipEclipseCurse", true, "技能自伤是否跳过日食 8 的「永久诅咒」(每次受伤都会永久降低一点生命值上限)。\n扣的血一分不少,只是不再叠这个层数。被真正的敌人打到时照常叠。\n这个值是运行期读取的。");
			_onlyTreebot = cfg.Bind<bool>("SelfHarm", "OnlyForTreebot", false, "只处理雷克斯的自伤。false(默认)= 任何角色符合特征的自伤都不叠诅咒,\n和 CurseCatcher 的 Self Damage=false 是一个语义。这个值是运行期读取的。");
		}

		public static string Summary()
		{
			if (!IsEnabled)
			{
				return " [自伤:原版未改动]";
			}
			if (SkipCurseValue())
			{
				if (_onlyTreebot == null || !_onlyTreebot.Value)
				{
					return " [自伤:技能自伤不叠日食诅咒]";
				}
				return " [自伤:雷克斯技能不叠日食诅咒]";
			}
			return " [自伤:照常叠日食诅咒]";
		}

		private static bool SkipCurseValue()
		{
			if (_skipCurse != null)
			{
				return _skipCurse.Value;
			}
			return true;
		}

		private static bool OnlyTreebotValue()
		{
			if (_onlyTreebot != null)
			{
				return _onlyTreebot.Value;
			}
			return false;
		}

		public static void Patch(Harmony harmony)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			if (!IsEnabled)
			{
				Log((LogLevel)16, "自伤处理:按配置保持原版,不挂任何补丁。");
				return;
			}
			if (!SkipCurseValue())
			{
				Log((LogLevel)16, "自伤处理:按配置保留日食诅咒,不挂补丁。");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(HealthComponent), "TakeDamageProcess", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log((LogLevel)2, "自伤补丁失败:取不到 HealthComponent.TakeDamageProcess。");
				return;
			}
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RexSelfHarm), "TakeDamageProcessTranspiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
			Log((LogLevel)16, "补丁已挂载:HealthComponent.TakeDamageProcess <- TakeDamageProcessTranspiler(自伤跳过日食诅咒)");
		}

		public static IEnumerable<CodeInstruction> TakeDamageProcessTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.Method(typeof(RexSelfHarm), "TeamComparand", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = FindGetter("get_teamComponent");
			MethodInfo methodInfo3 = FindGetter("get_teamIndex");
			FieldInfo fieldInfo = AccessTools.Field(typeof(HealthComponent), "body");
			if (methodInfo2 == null || methodInfo3 == null || fieldInfo == null)
			{
				Log((LogLevel)2, "日食诅咒改写失败:取不到 teamComponent / teamIndex / body 引用。");
				return list;
			}
			int num = 0;
			for (int i = 0; i + 3 < list.Count; i++)
			{
				if (IsCall(list[i], methodInfo2) && IsCall(list[i + 1], methodInfo3) && !(list[i + 2].opcode != OpCodes.Ldc_I4_1))
				{
					OpCode opcode = list[i + 3].opcode;
					if (!(opcode != OpCodes.Bne_Un) || !(opcode != OpCodes.Bne_Un_S))
					{
						List<CodeInstruction> list2 = new List<CodeInstruction>
						{
							new CodeInstruction(OpCodes.Ldarg_0, (object)null),
							new CodeInstruction(OpCodes.Ldfld, (object)fieldInfo),
							new CodeInstruction(OpCodes.Ldarg_1, (object)null),
							new CodeInstruction(OpCodes.Call, (object)methodInfo)
						};
						list[i + 2] = list2[0];
						list.InsertRange(i + 3, list2.GetRange(1, list2.Count - 1));
						num++;
						i += 3;
					}
				}
			}
			if (num > 0)
			{
				Log((LogLevel)16, "日食诅咒已改写(" + num + " 处 TeamIndex.Player 比较 → TeamComparand):符合条件的技术自伤照常扣血,但不再叠「永久诅咒」。");
			}
			else
			{
				Log((LogLevel)2, "日食诅咒改写失败:TakeDamageProcess 里没找到 get_teamComponent / get_teamIndex / ldc.i4.1 / bne.un 这一串。");
			}
			return list;
		}

		public static int TeamComparand(CharacterBody body, DamageInfo damageInfo)
		{
			try
			{
				if (!IsEnabled || !SkipCurseValue() || (Object)(object)body == (Object)null || damageInfo == null)
				{
					return 1;
				}
				if (!IsSelfHarm(damageInfo))
				{
					return 1;
				}
				if (OnlyTreebotValue() && ((Object)body).name == null)
				{
					return 1;
				}
				if (OnlyTreebotValue() && !((Object)body).name.StartsWith("TreebotBody"))
				{
					return 1;
				}
				if (!_firstSuppressLogged)
				{
					_firstSuppressLogged = true;
					Log((LogLevel)16, "技能自伤已识别(damage=" + damageInfo.damage.ToString("0.##") + ",body=" + ((Object)body).name + "):扣血保留,但不会再叠日食的「永久诅咒」。");
				}
				return int.MaxValue;
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "自伤判定异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
				return 1;
			}
		}

		private static bool IsSelfHarm(DamageInfo info)
		{
			if ((Object)(object)info.attacker != (Object)null || (Object)(object)info.inflictor != (Object)null)
			{
				return false;
			}
			if (Math.Abs(info.procCoefficient) > 0.0001f)
			{
				return false;
			}
			return (DamageTypeValue(info) & 1) != 0;
		}

		private static int DamageTypeValue(DamageInfo info)
		{
			//IL_000e: 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)
			try
			{
				if (_comboDamageType == null)
				{
					_comboDamageType = AccessTools.Field(((object)info.damageType).GetType(), "damageType");
				}
				if (_comboDamageType == null)
				{
					return 0;
				}
				return Convert.ToInt32(_comboDamageType.GetValue(info.damageType));
			}
			catch (Exception)
			{
				return 0;
			}
		}

		private static bool IsCall(CodeInstruction instruction, MethodInfo method)
		{
			if (instruction.opcode == OpCodes.Callvirt)
			{
				return instruction.operand as MethodInfo == method;
			}
			return false;
		}

		private static MethodInfo FindGetter(string name)
		{
			Type[] obj = new Type[3]
			{
				typeof(HealthComponent),
				typeof(CharacterBody),
				typeof(TeamComponent)
			};
			string text = (name.StartsWith("get_") ? name.Substring(4) : name);
			Type[] array = obj;
			for (int i = 0; i < array.Length; i++)
			{
				MethodInfo methodInfo = AccessTools.PropertyGetter(array[i], text);
				if (methodInfo != null)
				{
					return methodInfo;
				}
			}
			return null;
		}

		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);
			}
		}
	}
	public static class RexSyringe
	{
		private const string StateTypeName = "EntityStates.Treebot.Weapon.FireSyringe";

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<bool> _firstSyringeSpecial;

		private static ConfigEntry<float> _procCoefficient;

		private static ManualLogSource _log;

		private static Type _stateType;

		private static bool _firstApplyLogged;

		private static float _vanillaProcCoefficient = float.NaN;

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

		public static bool FirstSyringeSpecialEnabled
		{
			get
			{
				if (IsEnabled)
				{
					if (_firstSyringeSpecial != null)
					{
						return _firstSyringeSpecial.Value;
					}
					return true;
				}
				return false;
			}
		}

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

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_enabled = cfg.Bind<bool>("Inject", "Enabled", true, "是否调整 M1「命令:注射」。false = 完全保持原版。");
			_firstSyringeSpecial = cfg.Bind<bool>("Inject", "FirstSyringeIsSpecial", true, "把带弱化 + 吸取的那枚注射器挪到**最先发射**的那枚。\n原版它是最后一枚(技能原文:The last syringe Weakens and heals for 60% of damage dealt)。\n这样第一发先挂上弱化,后面两发吃到更高的伤害。\nfalse = 保持原版顺序(最后一枚才是特殊的)。改完需要重启游戏。");
			_procCoefficient = cfg.Bind<float>("Inject", "ProcCoefficient", 0.7f, "M1 每枚注射器的触发系数(原版 0.5)。系数越高,\n尤克里里、导弹、三尖匕首之类的命中类道具越容易触发。\n填负数 = 沿用原版 0.5。这个值运行期读取,改完下次开火就生效。");
		}

		public static string Summary()
		{
			if (!IsEnabled)
			{
				return " [命令:注射:原版未改动]";
			}
			string text = " [命令:注射:";
			text = ((!FirstSyringeSpecialEnabled) ? (text + "顺序沿用原版") : (text + "第一枚带弱化+吸取"));
			if (ProcCoefficientValue() >= 0f)
			{
				text = text + ",触发系数 0.5 → " + ProcCoefficientValue().ToString("0.##");
			}
			return text + "]";
		}

		private static float ProcCoefficientValue()
		{
			if (_procCoefficient != null)
			{
				return _procCoefficient.Value;
			}
			return 0.7f;
		}

		public static void Patch(Harmony harmony)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			if (!IsEnabled)
			{
				Log((LogLevel)16, "命令:注射:按配置保持原版,不挂任何补丁。");
				return;
			}
			_stateType = AccessTools.TypeByName("EntityStates.Treebot.Weapon.FireSyringe");
			if (_stateType == null)
			{
				Log((LogLevel)2, "命令:注射补丁失败:找不到状态类型 EntityStates.Treebot.Weapon.FireSyringe。");
				return;
			}
			if (IsSpecialOrderEnabled)
			{
				MethodInfo methodInfo = AccessTools.Method(_stateType, "FixedUpdate", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RexSyringe), "FirstSyringeTranspiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
					Log((LogLevel)16, "补丁已挂载:" + _stateType.Name + ".FixedUpdate <- FirstSyringeTranspiler(特殊注射器挪到第一枚)");
				}
				else
				{
					Log((LogLevel)2, "命令:注射补丁失败:取不到 FixedUpdate。");
				}
			}
			else
			{
				Log((LogLevel)16, "命令:注射:按配置保持原版顺序(最后一枚才是特殊的)。");
			}
			if (ProcCoefficientValue() >= 0f)
			{
				MethodInfo methodInfo2 = AccessTools.Method(typeof(ProjectileManager), "InitializeProjectile", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(RexSyringe), "InitializeProjectilePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log((LogLevel)16, "补丁已挂载:ProjectileManager.InitializeProjectile <- InitializeProjectilePostfix(触发系数 → " + ProcCoefficientValue().ToString("0.##") + ")");
				}
				else
				{
					Log((LogLevel)2, "命令:注射补丁失败:取不到 ProjectileManager.InitializeProjectile。");
				}
			}
		}

		public static IEnumerable<CodeInstruction> FirstSyringeTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			FieldInfo fieldInfo = AccessTools.Field(_stateType, "projectileCount");
			if (fieldInfo == null)
			{
				Log((LogLevel)2, "顺序调整失败:取不到字段 projectileCount。");
				return list;
			}
			int num = 0;
			for (int i = 0; i + 3 < list.Count; i++)
			{
				FieldInfo fieldInfo2 = list[i].operand as FieldInfo;
				if (!(list[i].opcode != OpCodes.Ldsfld) && !(fieldInfo2 == null) && !(fieldInfo2 != fieldInfo) && !(list[i + 1].opcode != OpCodes.Ldc_I4_1) && !(list[i + 2].opcode != OpCodes.Sub))
				{
					OpCode opcode = list[i + 3].opcode;
					if (!(opcode != OpCodes.Bne_Un) || !(opcode != OpCodes.Bne_Un_S))
					{
						list[i] = new CodeInstruction(OpCodes.Ldc_I4_0, (object)null);
						list[i + 1].opcode = OpCodes.Nop;
						list[i + 1].operand = null;
						list[i + 2].opcode = OpCodes.Nop;
						list[i + 2].operand = null;
						num++;
						i += 3;
					}
				}
			}
			if (num > 0)
			{
				Log((LogLevel)16, "顺序已调整(" + num + " 处 projectileCount-1 → 0):最先发射的那枚现在是带弱化 + 吸取的特殊注射器。");
			}
			else
			{
				Log((LogLevel)2, "顺序调整失败:FixedUpdate 里没找到 projectileCount - 1 + bne.un 那一串。");
			}
			return list;
		}

		public static void InitializeProjectilePostfix(ProjectileController projectileController, FireProjectileInfo fireProjectileInfo)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!IsEnabled || (Object)(object)projectileController == (Object)null || !IsSyringePrefab(fireProjectileInfo.projectilePrefab))
				{
					return;
				}
				float num = ProcCoefficientValue();
				if (num < 0f)
				{
					return;
				}
				float procCoefficient = projectileController.procCoefficient;
				if (float.IsNaN(_vanillaProcCoefficient))
				{
					_vanillaProcCoefficient = procCoefficient;
				}
				if (!(Mathf.Abs(procCoefficient - num) < 0.0001f))
				{
					projectileController.procCoefficient = num;
					if (!_firstApplyLogged)
					{
						_firstApplyLogged = true;
						Log((LogLevel)16, "命令:注射已生效 —— 触发系数 " + _vanillaProcCoefficient.ToString("0.##") + " → " + num.ToString("0.##") + ",每一枚注射器都能更容易触发道具效果。");
					}
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "触发系数改写异常(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static bool IsSyringePrefab(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null || _stateType == null)
			{
				return false;
			}
			FieldInfo fieldInfo = AccessTools.Field(_stateType, "projectilePrefab");
			FieldInfo fieldInfo2 = AccessTools.Field(_stateType, "finalProjectilePrefab");
			if (fieldInfo != null)
			{
				object value = fieldInfo.GetValue(null);
				if (prefab == value)
				{
					return true;
				}
			}
			if (fieldInfo2 != null)
			{
				object value2 = fieldInfo2.GetValue(null);
				if (prefab == value2)
				{
					return true;
				}
			}
			return false;
		}

		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);
			}
		}
	}
	public static class SkillDescriptions
	{
		private const string SpecialToken = "TREEBOT_SPECIAL_DESCRIPTION";

		private const string SpecialAltToken = "TREEBOT_SPECIAL_ALT1_DESCRIPTION";

		private const string PrimaryToken = "TREEBOT_PRIMARY_DESCRIPTION";

		private const string DefaultZh = "<style=cIsHealth>25%生命值</style>。发射一朵会<style=cIsDamage>扎根</style>并持续造成<style=cIsDamage>200%伤害</style>的花朵。能对范围内的目标造成<style=cIsUtility>弱化</style>。";

		private const string DefaultEn = "<style=cIsHealth>25% HP</style>. Fire a flower that <style=cIsDamage>roots</style> and continuously deals <style=cIsDamage>200% damage</style>. <style=cIsUtility>Weakens</style> targets in the area.";

		private const string PreviousDefaultZh = "<style=cIsHealth>25%生命值</style>。发射一朵会<style=cIsDamage>扎根</style>并造成<style=cIsDamage>200%伤害</style>的花朵。<style=cIsHealing>每命中一个目标便会对你进行一次治疗</style>。<style=cIsUtility>花朵存续期间,触须每 1.5 秒重新捆住目标</style>,<style=cIsUtility>将其拉近、再次造成伤害,并使其弱化 3 秒</style>。<style=cIsUtility>进入范围的新目标会被立刻捆住</style>。<style=cIsUtility>捆绑伤害可触发道具效果</style>。";

		private const string DefaultAltZh = "发射弩弹,造成<style=cIsDamage>330%的伤害</style>且弩弹将<style=cIsDamage>注入</style>敌人。此敌人被击败时,掉落多个<style=cIsHealing>治疗果实</style>,可治疗<style=cIsHealing>25%的生命值</style>并<style=cIsHealing>略微提升最大生命值</style>。";

		private const string DefaultAltEn = "Fire a bolt for <style=cIsDamage>330% damage</style> that <style=cIsDamage>infects</style> the enemy. When defeated, they drop multiple <style=cIsHealing>healing fruits</style> that heal for <style=cIsHealing>25% of your health</style> and <style=cIsHealing>slightly increase your maximum health</style>.";

		private const string DefaultPrimaryZh = "发射3个注射器,造成<style=cIsDamage>3x80%伤害</style>。第一个注射器会造成<style=cIsDamage>弱化</style>并<style=cIsHealing>将所施加伤害的60%转化为生命值</style>。";

		private const string DefaultPrimaryEn = "Fire 3 syringes for <style=cIsDamage>3x80% damage</style>. The first syringe <style=cIsDamage>Weakens</style> and <style=cIsHealing>heals for 60% of damage dealt</style>.";

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<string> _specialText;

		private static ConfigEntry<string> _specialAltText;

		private static ConfigEntry<string> _primaryText;

		private static ManualLogSource _log;

		public static void Init(ConfigFile cfg, ManualLogSource logger)
		{
			_log = logger;
			_enabled = cfg.Bind<bool>("Descriptions", "Enabled", true, "是否改写技能说明文字。false = 完全保留原版文案。");
			_specialText = cfg.Bind<string>("Descriptions", "TendrilGrowthDescription", "<style=cIsHealth>25%生命值</style>。发射一朵会<style=cIsDamage>扎根</style>并持续造成<style=cIsDamage>200%伤害</style>的花朵。能对范围内的目标造成<style=cIsUtility>弱化</style>。", "「触须生长」(R)的说明文字。留空 = 不改写。\n支持 <style=cIsUtility> / <style=cIsDamage> 之类的富文本标签。");
			_specialAltText = cfg.Bind<string>("Descriptions", "HarvestDescription", "发射弩弹,造成<style=cIsDamage>330%的伤害</style>且弩弹将<style=cIsDamage>注入</style>敌人。此敌人被击败时,掉落多个<style=cIsHealing>治疗果实</style>,可治疗<style=cIsHealing>25%的生命值</style>并<style=cIsHealing>略微提升最大生命值</style>。", "「命令:收割」(替代 R)的说明文字。只在「拾取果实给 buff」开启时才会改写,\n留空 = 不改写。支持 <style=cIsHealing> 之类的富文本标签。");
			_primaryText = cfg.Bind<string>("Descriptions", "InjectDescription", "发射3个注射器,造成<style=cIsDamage>3x80%伤害</style>。第一个注射器会造成<style=cIsDamage>弱化</style>并<style=cIsHealing>将所施加伤害的60%转化为生命值</style>。", "「命令:注射」(M1)的说明文字。只在「第一枚换成特殊注射器」开启时才会改写,\n留空 = 不改写。支持 <style=cIsUtility> / <style=cIsDamage> 之类的富文本标签。");
		}

		public static void Apply(bool tendrilEnabled, bool syringeReordered, bool harvestEnabled)
		{
			try
			{
				if (_enabled == null || !_enabled.Value)
				{
					Log((LogLevel)16, "技能说明:按配置保留原版文案。");
					return;
				}
				if (tendrilEnabled)
				{
					ApplyToken("TREEBOT_SPECIAL_DESCRIPTION", "<style=cIsHealth>25% HP</style>. Fire a flower that <style=cIsDamage>roots</style> and continuously deals <style=cIsDamage>200% damage</style>. <style=cIsUtility>Weakens</style> targets in the area.", "触须生长", Resolved(_specialText, "<style=cIsHealth>25%生命值</style>。发射一朵会<style=cIsDamage>扎根</style>并持续造成<style=cIsDamage>200%伤害</style>的花朵。能对范围内的目标造成<style=cIsUtility>弱化</style>。", "<style=cIsHealth>25%生命值</style>。发射一朵会<style=cIsDamage>扎根</style>并造成<style=cIsDamage>200%伤害</style>的花朵。<style=cIsHealing>每命中一个目标便会对你进行一次治疗</style>。<style=cIsUtility>花朵存续期间,触须每 1.5 秒重新捆住目标</style>,<style=cIsUtility>将其拉近、再次造成伤害,并使其弱化 3 秒</style>。<style=cIsUtility>进入范围的新目标会被立刻捆住</style>。<style=cIsUtility>捆绑伤害可触发道具效果</style>。"));
				}
				else
				{
					Log((LogLevel)16, "技能说明:触须生长未启用,保留原版文案。");
				}
				if (harvestEnabled)
				{
					ApplyToken("TREEBOT_SPECIAL_ALT1_DESCRIPTION", "Fire a bolt for <style=cIsDamage>330% damage</style> that <style=cIsDamage>infects</style> the enemy. When defeated, they drop multiple <style=cIsHealing>healing fruits</style> that heal for <style=cIsHealing>25% of your health</style> and <style=cIsHealing>slightly increase your maximum health</style>.", "命令:收割", Resolved(_specialAltText, "发射弩弹,造成<style=cIsDamage>330%的伤害</style>且弩弹将<style=cIsDamage>注入</style>敌人。此敌人被击败时,掉落多个<style=cIsHealing>治疗果实</style>,可治疗<style=cIsHealing>25%的生命值</style>并<style=cIsHealing>略微提升最大生命值</style>。", null));
				}
				else
				{
					Log((LogLevel)16, "技能说明:果实 buff 未启用,保留「命令:收割」原版文案。");
				}
				if (syringeReordered)
				{
					ApplyToken("TREEBOT_PRIMARY_DESCRIPTION", "Fire 3 syringes for <style=cIsDamage>3x80% damage</style>. The first syringe <style=cIsDamage>Weakens</style> and <style=cIsHealing>heals for 60% of damage dealt</style>.", "命令:注射", Resolved(_primaryText, "发射3个注射器,造成<style=cIsDamage>3x80%伤害</style>。第一个注射器会造成<style=cIsDamage>弱化</style>并<style=cIsHealing>将所施加伤害的60%转化为生命值</style>。", null));
				}
				else
				{
					Log((LogLevel)16, "技能说明:命令:注射未调整顺序,保留原版文案。");
				}
			}
			catch (Exception ex)
			{
				Log((LogLevel)4, "技能说明改写失败(已忽略):" + ex.GetType().Name + " " + ex.Message);
			}
		}

		private static string Resolved(ConfigEntry<string> entry, string current, string previous)
		{
			if (entry == null)
			{
				return current;
			}
			if (!string.IsNullOrEmpty(previous) && entry.Value == previous)
			{
				return current;
			}
			return entry.Value;
		}

		private static void ApplyToken(string token, string english, string label, string chinese)
		{
			if (!string.IsNullOrEmpty(chinese))
			{
				LanguageAPI.Add(token, chinese, "zh-CN");
				LanguageAPI.Add(token, english, "en");
				Log((LogLevel)16, "技能说明已改写:" + token + "(" + label + ")。");
			}
		}

		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.sparklerextweaks", "SparkleRexTweaks", "1.12.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SparkleRexTweaksPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.sparkletwilight.sparklerextweaks";

		public const string PluginName = "SparkleRexTweaks";

		public const string PluginVersion = "1.12.0";

		public void Awake()
		{
			//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_008a: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00a1: Expected O, but got Unknown
			RexEntangle.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			RexSyringe.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			RexSelfHarm.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			RexFruitHarvest.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			RexBrambleVolley.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			SkillDescriptions.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			SkillDescriptions.Apply(RexEntangle.IsEnabled, RexSyringe.FirstSyringeSpecialEnabled, RexFruitHarvest.IsEnabled);
			Harmony val = new Harmony("com.sparkletwilight.sparklerextweaks");
			RexEntangle.Patch(val);
			RexSyringe.Patch(val);
			RexSelfHarm.Patch(val);
			RexFruitHarvest.Patch(val);
			RexBrambleVolley.Patch(val);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("SparkleRexTweaks v1.12.0 已加载。" + RexEntangle.Summary() + RexSyringe.Summary() + RexSelfHarm.Summary() + RexFruitHarvest.Summary() + RexBrambleVolley.Summary()));
		}
	}
}