Decompiled source of RexEnhancements v1.0.0

RexEnhancements.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates.Treebot;
using EntityStates.Treebot.Weapon;
using HarmonyLib;
using RoR2;
using RoR2.ContentManagement;
using RoR2.Projectile;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;

[assembly: IgnoresAccessChecksTo("RoR2")]
[assembly: IgnoresAccessChecksTo("HGCSharpUtils")]
[assembly: IgnoresAccessChecksTo("HGUnityUtils")]
[assembly: IgnoresAccessChecksTo("com.unity.multiplayer-hlapi.Runtime")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: UnverifiableCode]
namespace RexEnhancements
{
	[BepInPlugin("com.Sagittariod.RexEnhancements", "Rex Enhancements", "1.1.0")]
	public class RexEnhancementsPlugin : BaseUnityPlugin
	{
		private class RexContentPackProvider : IContentPackProvider
		{
			private readonly ContentPack contentPack = new ContentPack();

			public string identifier => "com.Sagittariod.RexEnhancements";

			public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
			{
				try
				{
					PropertyInfo propertyInfo = AccessTools.Property(typeof(ContentPack), "identifier");
					if (propertyInfo != null)
					{
						propertyInfo.SetValue(contentPack, identifier, null);
					}
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Could not set content pack identifier: " + ex.Message));
				}
				contentPack.buffDefs.Add((BuffDef[])(object)new BuffDef[1] { curseCleanserBuff });
				args.ReportProgress(1f);
				yield break;
			}

			public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args)
			{
				ContentPack.Copy(contentPack, args.output);
				args.ReportProgress(1f);
				yield break;
			}

			public IEnumerator FinalizeAsync(FinalizeAsyncArgs args)
			{
				args.ReportProgress(1f);
				yield break;
			}
		}

		public class MortarHitTracker : MonoBehaviour
		{
			public int hits;
		}

		public class ConvalescenceController : MonoBehaviour
		{
			public CharacterBody body;

			public BuffDef buffDef;

			public float remainingTime;

			private void Awake()
			{
				body = ((Component)this).GetComponent<CharacterBody>();
			}

			public void AddStack()
			{
				if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)buffDef))
				{
					int buffCount = body.GetBuffCount(buffDef);
					remainingTime += 9f * Mathf.Pow(0.815f, (float)buffCount);
					UpdateBuffStacks();
				}
			}

			private void FixedUpdate()
			{
				if (NetworkServer.active && !(remainingTime <= 0f))
				{
					remainingTime -= Time.fixedDeltaTime;
					if (remainingTime <= 0f)
					{
						remainingTime = 0f;
						ClearBuffs();
						Object.Destroy((Object)(object)this);
					}
					else
					{
						UpdateBuffStacks();
					}
				}
			}

			private void UpdateBuffStacks()
			{
				if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)buffDef))
				{
					int stacksForTime = GetStacksForTime(remainingTime);
					int i;
					for (i = body.GetBuffCount(buffDef); i < stacksForTime; i++)
					{
						body.AddBuff(buffDef);
					}
					while (i > stacksForTime)
					{
						body.RemoveBuff(buffDef);
						i--;
					}
				}
			}

			private void ClearBuffs()
			{
				if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)buffDef))
				{
					for (int num = body.GetBuffCount(buffDef); num > 0; num--)
					{
						body.RemoveBuff(buffDef);
					}
				}
			}

			public static int GetStacksForTime(float t)
			{
				if (t <= 0f)
				{
					return 0;
				}
				int num = 0;
				float num2 = 0f;
				float num3 = 10f;
				while (t > num2)
				{
					num++;
					num2 += num3;
					num3 *= 0.815f;
					if (num > 100)
					{
						break;
					}
				}
				return num;
			}
		}

		internal static ManualLogSource Log;

		public static ConfigEntry<float> maxBonusDamage;

		public static ConfigEntry<float> maxBonusArmor;

		public static ConfigEntry<float> brambleVolleyDamage;

		public static ConfigEntry<float> disperseCooldown;

		public static ConfigEntry<bool> harvestEndlagReduction;

		public static ConfigEntry<float> injectProcCoefficient;

		public static ConfigEntry<float> injectDamage;

		public static ConfigEntry<bool> enableNewPassive;

		public static ConfigEntry<bool> enableConvalescenceBuff;

		public static BuffDef curseCleanserBuff;

		private const string TreebotBodyPath = "RoR2/Base/Treebot/TreebotBody.prefab";

		private const string KeywordToken = "KEYWORD_CONVALESCENCE";

		private const string TreebotNameToken = "TREEBOT_BODY_NAME";

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

		private static readonly HashSet<string> ConvalescenceSkillTokens = new HashSet<string> { "TREEBOT_SECONDARY_DESCRIPTION", "TREEBOT_SECONDARY_ALT1_DESCRIPTION", "TREEBOT_SPECIAL_DESCRIPTION", "TREEBOT_SPECIAL_ALT1_DESCRIPTION" };

		private static Action<CharacterBody, float> setDamage;

		private static Action<CharacterBody, float> setArmor;

		private static Action<CharacterBody, float> setMaxHealth;

		private static Action<CharacterBody, float> setCursePenalty;

		private static BodyIndex treebotBodyIndex = (BodyIndex)(-1);

		private Harmony harmony;

		private void Awake()
		{
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			enableNewPassive = ((BaseUnityPlugin)this).Config.Bind<bool>("Passive", "Enable New Passive", true, "If true, grants a new passive which increases armor and damage based on missing health");
			maxBonusDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Passive", "Max Bonus Damage", 0.3f, "Maximum percentage damage increase granted when at minimum health");
			maxBonusArmor = ((BaseUnityPlugin)this).Config.Bind<float>("Passive", "Max Bonus Armor", 50f, "Maximum armor increase granted when at minimum health");
			harvestEndlagReduction = ((BaseUnityPlugin)this).Config.Bind<bool>("Existing Skills", "Enable Faster Harvest", true, "If true, halves the endlag of DIRECTIVE: HARVEST");
			injectProcCoefficient = ((BaseUnityPlugin)this).Config.Bind<float>("Existing Skills", "DIRECTIVE - Inject Proc Coefficient", 0.8f, "Proc coefficient for DIRECTIVE: INJECT");
			brambleVolleyDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Skills - Utility", "Bramble Volley Damage", 10f, "Damage coefficient for Bramble Volley");
			disperseCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Skills - Utility", "Directive Disperse Cooldown", 4.5f, "Base cooldown in seconds for Directive: DISPERSE");
			injectDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Existing Skills", "DIRECTIVE - Inject Damage", 0.9f, "Damage coefficient for DIRECTIVE: INJECT");
			enableConvalescenceBuff = ((BaseUnityPlugin)this).Config.Bind<bool>("Existing Skills", "Enable Convalescence Buff", true, "If true, specific abilities grant the Convalescence buff which temporarily reduce Curse");
			setDamage = MakeSetter("damage");
			setArmor = MakeSetter("armor");
			setMaxHealth = MakeSetter("maxHealth");
			setCursePenalty = MakeSetter("cursePenalty");
			SetupBuff();
			ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)delegate(AddContentPackProviderDelegate add)
			{
				add.Invoke((IContentPackProvider)(object)new RexContentPackProvider());
			};
			BuildLanguage();
			harmony = new Harmony("com.Sagittariod.RexEnhancements");
			Patch(AccessTools.Method(typeof(Language), "GetLocalizedStringByToken", new Type[1] { typeof(string) }, (Type[])null), "LanguagePrefix");
			Patch(AccessTools.Method(typeof(CharacterBody), "RecalculateStats", (Type[])null, (Type[])null), null, "RecalculateStatsPostfix");
			Patch(AccessTools.Method(typeof(TreebotFireFruitSeed), "OnEnter", (Type[])null, (Type[])null), "FireFruitSeedPrefix");
			Patch(AccessTools.Method(typeof(FireSyringe), "OnEnter", (Type[])null, (Type[])null), "FireSyringePrefix");
			Patch(AccessTools.Method(typeof(FirePlantSonicBoom), "OnEnter", (Type[])null, (Type[])null), "FirePlantSonicBoomPrefix");
			Patch(AccessTools.Method(typeof(GlobalEventManager), "OnHitEnemy", new Type[2]
			{
				typeof(DamageInfo),
				typeof(GameObject)
			}, (Type[])null), null, "OnHitEnemyPostfix");
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnGameLoaded));
		}

		private void OnDestroy()
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(OnGameLoaded));
		}

		private void Patch(MethodInfo target, string prefix = null, string postfix = null)
		{
			//IL_0043: 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)
			if (target == null)
			{
				Log.LogError((object)("Patch target not found for " + (prefix ?? postfix)));
				return;
			}
			try
			{
				harmony.Patch((MethodBase)target, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(RexEnhancementsPlugin), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(RexEnhancementsPlugin), postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			catch (Exception ex)
			{
				Log.LogError((object)string.Concat("Failed to patch ", target.DeclaringType, ".", target.Name, ": ", ex));
			}
		}

		private static Action<CharacterBody, float> MakeSetter(string property)
		{
			MethodInfo setter = AccessTools.PropertySetter(typeof(CharacterBody), property);
			if (setter == null)
			{
				Log.LogError((object)("CharacterBody." + property + " setter not found."));
				return delegate
				{
				};
			}
			try
			{
				return (Action<CharacterBody, float>)Delegate.CreateDelegate(typeof(Action<CharacterBody, float>), setter);
			}
			catch
			{
				return delegate(CharacterBody b, float v)
				{
					setter.Invoke(b, new object[1] { v });
				};
			}
		}

		private void SetupBuff()
		{
			curseCleanserBuff = ScriptableObject.CreateInstance<BuffDef>();
			((Object)curseCleanserBuff).name = "Convalescence";
			curseCleanserBuff.canStack = true;
			curseCleanserBuff.isDebuff = false;
			curseCleanserBuff.isHidden = false;
			curseCleanserBuff.iconSprite = LoadSpriteFromManifest("Convalescence.png");
		}

		private Sprite LoadSpriteFromManifest(string fileName)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("RexEnhancements." + fileName);
				if (stream == null)
				{
					return null;
				}
				byte[] array = new byte[stream.Length];
				stream.Read(array, 0, array.Length);
				Texture2D val = new Texture2D(2, 2);
				Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
				MethodInfo methodInfo = ((!(type != null)) ? null : type.GetMethod("LoadImage", new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				}));
				if (methodInfo == null)
				{
					Log.LogWarning((object)"ImageConversion.LoadImage not found; buff icon unavailable.");
					return null;
				}
				methodInfo.Invoke(null, new object[2] { val, array });
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex);
				return null;
			}
		}

		private void OnGameLoaded()
		{
			//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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			treebotBodyIndex = BodyCatalog.FindBodyIndex("TreebotBody");
			try
			{
				SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Treebot/TreebotBodySonicBoom.asset").WaitForCompletion();
				if (Object.op_Implicit((Object)(object)val))
				{
					val.baseRechargeInterval = disperseCooldown.Value;
				}
				else
				{
					Log.LogWarning((object)"DIRECTIVE: DISPERSE skill not found.");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex);
			}
			try
			{
				ModifyPrefabs();
			}
			catch (Exception ex2)
			{
				Log.LogError((object)ex2);
			}
			try
			{
				GameObject val2 = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Treebot/TreebotBody.prefab").WaitForCompletion();
				SkillLocator val3 = ((!Object.op_Implicit((Object)(object)val2)) ? null : val2.GetComponent<SkillLocator>());
				if (!Object.op_Implicit((Object)(object)val3))
				{
					Log.LogWarning((object)"REX SkillLocator not found.");
					return;
				}
				if (enableNewPassive.Value)
				{
					val3.passiveSkill.keywordToken = string.Empty;
				}
				if (enableConvalescenceBuff.Value)
				{
					AddKeyword(val3.secondary);
					AddKeyword(val3.special);
				}
			}
			catch (Exception ex3)
			{
				Log.LogError((object)ex3);
			}
		}

		private static void AddKeyword(GenericSkill slot)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)slot))
			{
				return;
			}
			SkillFamily skillFamily = slot.skillFamily;
			if (!Object.op_Implicit((Object)(object)skillFamily) || skillFamily.variants == null)
			{
				return;
			}
			Variant[] variants = skillFamily.variants;
			for (int i = 0; i < variants.Length; i++)
			{
				Variant val = variants[i];
				SkillDef skillDef = val.skillDef;
				if (Object.op_Implicit((Object)(object)skillDef) && ConvalescenceSkillTokens.Contains(skillDef.skillDescriptionToken))
				{
					string[] array = skillDef.keywordTokens ?? new string[0];
					if (!array.Contains("KEYWORD_CONVALESCENCE"))
					{
						skillDef.keywordTokens = array.Concat(new string[1] { "KEYWORD_CONVALESCENCE" }).ToArray();
					}
				}
			}
		}

		private static void ModifyPrefabs()
		{
			//IL_0023: 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)
			string[] array = new string[2] { "RoR2/Base/Treebot/SyringeProjectile.prefab", "RoR2/Base/Treebot/SyringeProjectileHealing.prefab" };
			foreach (string text in array)
			{
				GameObject val = Addressables.LoadAssetAsync<GameObject>((object)text).WaitForCompletion();
				ProjectileController val2 = ((!Object.op_Implicit((Object)(object)val)) ? null : val.GetComponent<ProjectileController>());
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.procCoefficient = injectProcCoefficient.Value;
				}
				else
				{
					Log.LogWarning((object)("Projectile not found: " + text));
				}
			}
		}

		private static void BuildLanguage()
		{
			LanguageOverrides["TREEBOT_PRIMARY_DESCRIPTION"] = $"Fire 3 syringes for <style=cIsDamage>3x{injectDamage.Value * 100f}% damage</style>. The last syringe <style=cIsDamage>Weakens</style> and <style=cIsHealing>heals for 60% of damage dealt</style>.";
			LanguageOverrides["TREEBOT_UTILITY_ALT1_DESCRIPTION"] = $"<style=cIsHealth>20% HP</style>. Fire a <style=cIsUtility>Sonic Boom</style> that damages enemies for <style=cIsDamage>{brambleVolleyDamage.Value * 100f}% damage</style>. <style=cIsHealing>Heals for every target hit</style>.";
			if (enableNewPassive.Value)
			{
				LanguageOverrides["TREEBOT_PASSIVE_NAME"] = "Adaptive Plating";
				LanguageOverrides["TREEBOT_PASSIVE_DESCRIPTION"] = string.Format("Gain up to <style=cIsUtility>{1} armor</style> and deal up to <style=cIsDamage>+{0}% damage</style> based on your <style=cIsHealth>missing health</style>.", maxBonusDamage.Value * 100f, maxBonusArmor.Value);
			}
			else
			{
				LanguageOverrides["TREEBOT_PASSIVE_NAME"] = "Natural Toxins";
				LanguageOverrides["TREEBOT_PASSIVE_DESCRIPTION"] = "Certain attacks <style=cIsDamage>Weaken</style> enemies hit, reducing their movement speed, armor, and damage.";
			}
			LanguageOverrides["TREEBOT_SPECIAL_DESCRIPTION"] = "<style=cIsHealth>25% HP</style>. Fire a flower that <style=cIsDamage>roots</style> for <style=cIsDamage>200% damage</style>. <style=cIsHealing>Heals for every target hit</style>." + ((!enableConvalescenceBuff.Value) ? string.Empty : " <style=cIsUtility>Direct hits grant Convalescence.</style>");
			LanguageOverrides["TREEBOT_SPECIAL_ALT1_DESCRIPTION"] = "Fire a bolt that deals <style=cIsDamage>330% damage</style> and <style=cIsDamage>injects</style> an enemy. On death, drop multiple <style=cIsHealing>healing fruits</style> that heal for <style=cIsHealing>25% HP</style>." + ((!enableConvalescenceBuff.Value) ? string.Empty : " <style=cIsUtility>Direct hits grant Convalescence.</style>");
			LanguageOverrides["TREEBOT_SECONDARY_ALT1_DESCRIPTION"] = "Launch a series of seed bullets into the sky, raining down for <style=cIsDamage>450% damage per second</style>." + ((!enableConvalescenceBuff.Value) ? string.Empty : " <style=cIsUtility>Every 4 hits grants Convalescence.</style>");
			LanguageOverrides["TREEBOT_SECONDARY_DESCRIPTION"] = "<style=cIsHealth>15% HP</style>. Launch a mortar into the sky for <style=cIsDamage>450% damage</style>." + ((!enableConvalescenceBuff.Value) ? string.Empty : " <style=cIsUtility>Each hit grants Convalescence.</style>");
			if (enableConvalescenceBuff.Value)
			{
				LanguageOverrides["KEYWORD_CONVALESCENCE"] = "<style=cKeywordName>Convalescence</style><style=cSub>Reduces current <style=cIsHealth>Curse</style> by 15% per stack. Higher stacks have shorter durations.</style>";
			}
		}

		private static bool LanguagePrefix(string token, ref string __result)
		{
			if (token != null && LanguageOverrides.TryGetValue(token, out var value))
			{
				__result = value;
				return false;
			}
			return true;
		}

		private static bool IsRex(CharacterBody body)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//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)
			if (!Object.op_Implicit((Object)(object)body))
			{
				return false;
			}
			if ((int)treebotBodyIndex != -1)
			{
				return body.bodyIndex == treebotBodyIndex;
			}
			return body.baseNameToken == "TREEBOT_BODY_NAME";
		}

		private static void RecalculateStatsPostfix(CharacterBody __instance)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Invalid comparison between Unknown and I4
			try
			{
				if (!IsRex(__instance))
				{
					return;
				}
				HealthComponent healthComponent = __instance.healthComponent;
				if (!Object.op_Implicit((Object)(object)healthComponent))
				{
					return;
				}
				if (enableNewPassive.Value && healthComponent.fullHealth > 0f)
				{
					float num = Mathf.Clamp01(healthComponent.health / healthComponent.fullHealth);
					setDamage(__instance, __instance.damage * (1f + maxBonusDamage.Value * (1f - num)));
					setArmor(__instance, __instance.armor + maxBonusArmor.Value * (1f - num));
				}
				if (enableConvalescenceBuff.Value && Object.op_Implicit((Object)(object)curseCleanserBuff) && (int)curseCleanserBuff.buffIndex != -1)
				{
					int buffCount = __instance.GetBuffCount(curseCleanserBuff);
					if (buffCount > 0 && !(__instance.cursePenalty <= 1f))
					{
						float cursePenalty = __instance.cursePenalty;
						float num2 = __instance.maxHealth * cursePenalty;
						float num3 = num2 - __instance.maxHealth;
						float num4 = num3 * Mathf.Pow(0.85f, (float)buffCount);
						float num5 = num2 - num4;
						setMaxHealth(__instance, num5);
						setCursePenalty(__instance, num2 / num5);
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex);
			}
		}

		private static void FireFruitSeedPrefix(TreebotFireFruitSeed __instance)
		{
			if (harvestEndlagReduction.Value)
			{
				__instance.baseDuration = 0.5f;
			}
		}

		private static void FireSyringePrefix()
		{
			FireSyringe.damageCoefficient = injectDamage.Value;
		}

		private static void FirePlantSonicBoomPrefix()
		{
			FirePlantSonicBoom.damageCoefficient = brambleVolleyDamage.Value;
		}

		private static void OnHitEnemyPostfix(DamageInfo damageInfo)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			try
			{
				if (!enableConvalescenceBuff.Value || !NetworkServer.active || damageInfo == null || !Object.op_Implicit((Object)(object)curseCleanserBuff) || (int)curseCleanserBuff.buffIndex == -1 || !Object.op_Implicit((Object)(object)damageInfo.attacker) || !Object.op_Implicit((Object)(object)damageInfo.inflictor))
				{
					return;
				}
				CharacterBody component = damageInfo.attacker.GetComponent<CharacterBody>();
				if (!IsRex(component))
				{
					return;
				}
				string name = ((Object)damageInfo.inflictor).name;
				bool flag = false;
				if (name.Contains("TreebotFruitSeed") || name.Contains("TreebotMortar2") || name.Contains("TreebotFlower"))
				{
					flag = true;
				}
				else if (name.Contains("TreebotMortar"))
				{
					MortarHitTracker mortarHitTracker = ((Component)component).GetComponent<MortarHitTracker>();
					if (!Object.op_Implicit((Object)(object)mortarHitTracker))
					{
						mortarHitTracker = ((Component)component).gameObject.AddComponent<MortarHitTracker>();
					}
					mortarHitTracker.hits++;
					if (mortarHitTracker.hits >= 4)
					{
						flag = true;
						mortarHitTracker.hits = 0;
					}
				}
				if (flag)
				{
					ConvalescenceController convalescenceController = ((Component)component).GetComponent<ConvalescenceController>();
					if (!Object.op_Implicit((Object)(object)convalescenceController))
					{
						convalescenceController = ((Component)component).gameObject.AddComponent<ConvalescenceController>();
						convalescenceController.buffDef = curseCleanserBuff;
					}
					convalescenceController.AddStack();
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)ex);
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public string AssemblyName { get; }

		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
			AssemblyName = assemblyName;
		}
	}
}