using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using EntityStates;
using HG;
using JetBrains.Annotations;
using RoR2.Audio;
using RoR2.Networking;
using RoR2.Orbs;
using RoR2.PostProcessing;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;

namespace RoR2;

[DisallowMultipleComponent]
[RequireComponent(typeof(CharacterBody))]
public class HealthComponent : NetworkBehaviour, IManagedMonoBehaviour
{
	private static class AssetReferences
	{
		public static GameObject bearEffectPrefab;

		public static GameObject bearVoidEffectPrefab;

		public static GameObject executeEffectPrefab;

		public static GameObject critGlassesVoidExecuteEffectPrefab;

		public static GameObject shieldBreakEffectPrefab;

		public static GameObject loseCoinsImpactEffectPrefab;

		public static GameObject gainCoinsImpactEffectPrefab;

		public static GameObject damageRejectedPrefab;

		public static GameObject bossDamageBonusImpactEffectPrefab;

		public static GameObject pulverizedEffectPrefab;

		public static GameObject diamondDamageBonusImpactEffectPrefab;

		public static GameObject crowbarImpactEffectPrefab;

		public static GameObject captainBodyArmorBlockEffectPrefab;

		public static GameObject mercExposeConsumeEffectPrefab;

		public static GameObject explodeOnDeathVoidExplosionPrefab;

		public static GameObject fragileDamageBonusBreakEffectPrefab;

		public static GameObject healthOrbPrefab;

		public static GameObject permanentDebuffEffectPrefab;

		public static void Resolve()
		{
			AsyncOperationHandle<GameObject> asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/BearProc");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				bearEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/BearVoidProc");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				bearVoidEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/OmniEffect/OmniImpactExecute");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				executeEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ShieldBreakEffect");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				shieldBreakEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/CoinImpact");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				loseCoinsImpactEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/GainCoinsImpact");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				gainCoinsImpactEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/DamageRejected");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				damageRejectedPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/ImpactBossDamageBonus");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				bossDamageBonusImpactEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/PulverizedEffect");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				pulverizedEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/DiamondDamageBonusEffect");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				diamondDamageBonusImpactEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/ImpactCrowbar");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				crowbarImpactEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/CaptainBodyArmorBlockEffect");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				captainBodyArmorBlockEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/PermanentDebuffEffect");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				permanentDebuffEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/MercExposeConsumeEffect");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				mercExposeConsumeEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/CritGlassesVoidExecuteEffect");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				critGlassesVoidExecuteEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/NetworkedObjects/ExplodeOnDeathVoidExplosion");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				explodeOnDeathVoidExplosionPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/Effects/ImpactEffects/DelicateWatchProcEffect");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				fragileDamageBonusBreakEffectPrefab = x.Result;
			};
			asyncOperationHandle = LegacyResourcesAPI.LoadAsync<GameObject>("Prefabs/NetworkedObjects/TreebotFruitPack");
			asyncOperationHandle.Completed += delegate(AsyncOperationHandle<GameObject> x)
			{
				healthOrbPrefab = x.Result;
			};
		}
	}

	private class HealMessage : MessageBase
	{
		public GameObject target;

		public float amount;

		public override void Serialize(NetworkWriter writer)
		{
			writer.Write(target);
			writer.Write(amount);
		}

		public override void Deserialize(NetworkReader reader)
		{
			target = reader.ReadGameObject();
			amount = reader.ReadSingle();
		}
	}

	private struct ItemCounts
	{
		public int bear;

		public int armorPlate;

		public int goldOnHit;

		public int goldOnHurt;

		public int phasing;

		public int thorns;

		public int invadingDoppelganger;

		public int medkit;

		public int parentEgg;

		public int fragileDamageBonus;

		public int minHealthPercentage;

		public int noxiousThorn;

		public int antlerShield;

		public int increaseHealing;

		public int barrierOnOverHeal;

		public int repeatHeal;

		public int novaOnHeal;

		public int adaptiveArmor;

		public int healingPotion;

		public int infusion;

		public int missileVoid;

		public int unstableTransmitter;

		public ItemCounts([NotNull] Inventory src)
		{
			bear = src.GetItemCount(RoR2Content.Items.Bear);
			armorPlate = src.GetItemCount(RoR2Content.Items.ArmorPlate);
			goldOnHit = src.GetItemCount(RoR2Content.Items.GoldOnHit);
			goldOnHurt = src.GetItemCount(DLC1Content.Items.GoldOnHurt);
			phasing = src.GetItemCount(RoR2Content.Items.Phasing);
			thorns = src.GetItemCount(RoR2Content.Items.Thorns);
			invadingDoppelganger = src.GetItemCount(RoR2Content.Items.InvadingDoppelganger);
			medkit = src.GetItemCount(RoR2Content.Items.Medkit);
			fragileDamageBonus = src.GetItemCount(DLC1Content.Items.FragileDamageBonus);
			minHealthPercentage = src.GetItemCount(RoR2Content.Items.MinHealthPercentage);
			increaseHealing = src.GetItemCount(RoR2Content.Items.IncreaseHealing);
			barrierOnOverHeal = src.GetItemCount(RoR2Content.Items.BarrierOnOverHeal);
			repeatHeal = src.GetItemCount(RoR2Content.Items.RepeatHeal);
			novaOnHeal = src.GetItemCount(RoR2Content.Items.NovaOnHeal);
			adaptiveArmor = src.GetItemCount(RoR2Content.Items.AdaptiveArmor);
			healingPotion = src.GetItemCount(DLC1Content.Items.HealingPotion);
			infusion = src.GetItemCount(RoR2Content.Items.Infusion);
			parentEgg = src.GetItemCount(RoR2Content.Items.ParentEgg);
			missileVoid = src.GetItemCount(DLC1Content.Items.MissileVoid);
			unstableTransmitter = src.GetItemCount(DLC2Content.Items.TeleportOnLowHealth);
			noxiousThorn = src.GetItemCount(DLC2Content.Items.TriggerEnemyDebuffs);
			antlerShield = src.GetItemCount(DLC2Content.Items.NegateAttack);
		}
	}

	public struct HealthBarValues
	{
		public bool hasInfusion;

		public bool hasVoidShields;

		public bool isVoid;

		public bool isElite;

		public bool isBoss;

		public float cullFraction;

		public float healthFraction;

		public float shieldFraction;

		public float barrierFraction;

		public float magneticFraction;

		public float curseFraction;

		public float ospFraction;

		public int healthDisplayValue;

		public int maxHealthDisplayValue;
	}

	private class RepeatHealComponent : MonoBehaviour
	{
		private float reserve;

		private float timer;

		private const float interval = 0.2f;

		public float healthFractionToRestorePerSecond = 0.1f;

		public HealthComponent healthComponent;

		private void FixedUpdate()
		{
			timer -= Time.fixedDeltaTime;
			if (timer <= 0f)
			{
				timer = 0.2f;
				if (reserve > 0f)
				{
					float num = Mathf.Min(healthComponent.fullHealth * healthFractionToRestorePerSecond * 0.2f, reserve);
					reserve -= num;
					ProcChainMask procChainMask = default(ProcChainMask);
					procChainMask.AddProc(ProcType.RepeatHeal);
					healthComponent.Heal(num, procChainMask);
				}
			}
		}

		public void AddReserve(float amount, float max)
		{
			reserve = Mathf.Min(reserve + amount, max);
		}
	}

	public static readonly float lowHealthFraction;

	[SyncVar]
	[HideInInspector]
	[Tooltip("How much health this object has.")]
	public float health = 100f;

	[HideInInspector]
	[Tooltip("How much shield this object has.")]
	[SyncVar]
	public float shield;

	[HideInInspector]
	[SyncVar(hook = "SetBarrier")]
	[Tooltip("How much barrier this object has.")]
	public float barrier;

	[SyncVar]
	[HideInInspector]
	public float magnetiCharge;

	public bool dontShowHealthbar;

	private const float recentlyTookDamageCoyoteTimer_Duration = 0.2f;

	[NonSerialized]
	public float recentlyTookDamageCoyoteTimer;

	public float globalDeathEventChanceCoefficient = 1f;

	[SyncVar]
	private uint _killingDamageType;

	public CharacterBody body;

	private ModelLocator modelLocator;

	private IPainAnimationHandler painAnimationHandler;

	private IOnIncomingDamageServerReceiver[] onIncomingDamageReceivers;

	private IOnTakeDamageServerReceiver[] onTakeDamageReceivers;

	public ScreenDamageCalculator screenDamageCalculator;

	public const float frozenExecuteThreshold = 0.3f;

	private const float adaptiveArmorPerOnePercentTaken = 30f;

	private const float adaptiveArmorDecayPerSecond = 40f;

	private const float adaptiveArmorCap = 400f;

	public const float medkitActivationDelay = 2f;

	private const float devilOrbMaxTimer = 0.1f;

	private float devilOrbHealPool;

	private float devilOrbTimer;

	private float regenAccumulator;

	private bool wasAlive = true;

	private float adaptiveArmorValue;

	private bool isShieldRegenForced;

	public bool forceCulled;

	private float ospTimer;

	private const float ospBufferDuration = 0.1f;

	private float serverDamageTakenThisUpdate;

	private RepeatHealComponent repeatHealComponent;

	private ItemCounts itemCounts;

	private EquipmentIndex currentEquipmentIndex;

	private static int kCmdCmdHealFull;

	private static int kCmdCmdRechargeShieldFull;

	private static int kCmdCmdAddBarrier;

	private static int kCmdCmdForceShieldRegen;

	public bool recentlyTookDamage
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		get
		{
			return recentlyTookDamageCoyoteTimer > 0f;
		}
	}

	public DamageTypeCombo killingDamageType
	{
		get
		{
			return _killingDamageType;
		}
		private set
		{
			Network_killingDamageType = (uint)(ulong)value;
		}
	}

	public bool alive => health > 0f;

	public float fullHealth => body.maxHealth;

	public float fullShield => body.maxShield;

	public float fullBarrier => body.maxBarrier;

	public float combinedHealth => health + shield + barrier;

	public float fullCombinedHealth => fullHealth + fullShield;

	public float combinedHealthFraction => combinedHealth / fullCombinedHealth;

	public float missingCombinedHealth => fullCombinedHealth - (combinedHealth - barrier);

	public Run.FixedTimeStamp lastHitTime { get; private set; }

	public Run.FixedTimeStamp lastHealTime { get; private set; }

	public GameObject lastHitAttacker { get; private set; }

	public float timeSinceLastHit => lastHitTime.timeSince;

	public float timeSinceLastHeal => lastHealTime.timeSince;

	public bool godMode { get; set; }

	public float potionReserve { get; private set; }

	public bool isInFrozenState { get; set; }

	public bool isHealthLow => (health + shield) / fullCombinedHealth <= lowHealthFraction;

	public float Networkhealth
	{
		get
		{
			return health;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref health, 1u);
		}
	}

	public float Networkshield
	{
		get
		{
			return shield;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref shield, 2u);
		}
	}

	public float Networkbarrier
	{
		get
		{
			return barrier;
		}
		[param: In]
		set
		{
			if (NetworkServer.localClientActive && !base.syncVarHookGuard)
			{
				base.syncVarHookGuard = true;
				SetBarrier(value);
				base.syncVarHookGuard = false;
			}
			SetSyncVar(value, ref barrier, 4u);
		}
	}

	public float NetworkmagnetiCharge
	{
		get
		{
			return magnetiCharge;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref magnetiCharge, 8u);
		}
	}

	public uint Network_killingDamageType
	{
		get
		{
			return _killingDamageType;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref _killingDamageType, 16u);
		}
	}

	public static event Action<HealthComponent, float, ProcChainMask> onCharacterHealServer;

	private void SetBarrier(float newBarrier)
	{
		float num = barrier;
		Networkbarrier = newBarrier;
		if (barrier <= 0f && num > 0f)
		{
			body.MarkAllStatsDirty();
		}
	}

	public void OnValidate()
	{
		if (base.gameObject.GetComponents<HealthComponent>().Length > 1)
		{
			Debug.LogErrorFormat(base.gameObject, "{0} has multiple health components!!", base.gameObject);
		}
	}

	public float Heal(float amount, ProcChainMask procChainMask, bool nonRegen = true)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Single RoR2.HealthComponent::Heal(System.Single, RoR2.ProcChainMask, System.Boolean)' called on client");
			return 0f;
		}
		if (!alive || amount <= 0f || body.HasBuff(RoR2Content.Buffs.HealingDisabled))
		{
			return 0f;
		}
		recentlyTookDamageCoyoteTimer = 0.2f;
		float num = health;
		bool flag = false;
		if (currentEquipmentIndex == RoR2Content.Equipment.LunarPotion.equipmentIndex && !procChainMask.HasProc(ProcType.LunarPotionActivation))
		{
			potionReserve += amount;
			return amount;
		}
		if (nonRegen && !procChainMask.HasProc(ProcType.CritHeal) && Util.CheckRoll(body.critHeal, body.master))
		{
			procChainMask.AddProc(ProcType.CritHeal);
			flag = true;
		}
		if (flag)
		{
			amount *= 2f;
		}
		if (itemCounts.increaseHealing > 0)
		{
			amount *= 1f + (float)itemCounts.increaseHealing;
		}
		if (body.teamComponent.teamIndex == TeamIndex.Player && Run.instance.selectedDifficulty >= DifficultyIndex.Eclipse5)
		{
			amount /= 2f;
		}
		if (nonRegen && (bool)repeatHealComponent && !procChainMask.HasProc(ProcType.RepeatHeal))
		{
			repeatHealComponent.healthFractionToRestorePerSecond = 0.1f / (float)itemCounts.repeatHeal;
			repeatHealComponent.AddReserve(amount * (float)(1 + itemCounts.repeatHeal), fullHealth);
			return 0f;
		}
		if (body.HasBuff(DLC2Content.Buffs.lunarruin))
		{
			amount *= 0.8f;
		}
		if (body.HasBuff(DLC2Content.Buffs.SojournHealing))
		{
			int buffCount = body.GetBuffCount(DLC2Content.Buffs.SojournHealing);
			float num2 = 1f - (float)buffCount * 0.1f;
			if (num2 < 0f)
			{
				num2 = 0f;
			}
			amount *= num2;
		}
		float num3 = amount;
		if (health < fullHealth)
		{
			float num4 = Mathf.Max(Mathf.Min(amount, fullHealth - health), 0f);
			num3 = amount - num4;
			Networkhealth = health + num4;
		}
		if (num3 > 0f && nonRegen && itemCounts.barrierOnOverHeal > 0)
		{
			float value = num3 * ((float)itemCounts.barrierOnOverHeal * 0.5f);
			AddBarrier(value);
		}
		if (nonRegen)
		{
			lastHealTime = Run.FixedTimeStamp.now;
			SendHeal(base.gameObject, amount, flag);
			if (itemCounts.novaOnHeal > 0 && !procChainMask.HasProc(ProcType.HealNova))
			{
				devilOrbHealPool = Mathf.Min(devilOrbHealPool + amount * (float)itemCounts.novaOnHeal, fullCombinedHealth);
			}
		}
		if (flag)
		{
			GlobalEventManager.instance.OnCrit(body, null, body.master, amount / fullHealth * 10f, procChainMask);
		}
		if (nonRegen)
		{
			HealthComponent.onCharacterHealServer?.Invoke(this, amount, procChainMask);
		}
		if ((bool)body.inventory && body.inventory.GetItemCount(DLC2Content.Items.LowerHealthHigherDamage) > 0 && alive)
		{
			body.UpdateLowerHealthHigherDamage();
		}
		return health - num;
	}

	public void UsePotion()
	{
		ProcChainMask procChainMask = default(ProcChainMask);
		procChainMask.AddProc(ProcType.LunarPotionActivation);
		Heal(potionReserve, procChainMask);
	}

	public float HealFraction(float fraction, ProcChainMask procChainMask)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Single RoR2.HealthComponent::HealFraction(System.Single, RoR2.ProcChainMask)' called on client");
			return 0f;
		}
		return Heal(fraction * fullHealth, procChainMask);
	}

	public void SetCurrentHealthLevel()
	{
	}

	public float GetNormalizedHealth()
	{
		return health / fullHealth;
	}

	[Command]
	public void CmdHealFull()
	{
		HealFraction(1f, default(ProcChainMask));
	}

	[Server]
	public void RechargeShieldFull()
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::RechargeShieldFull()' called on client");
		}
		else if (shield < fullShield)
		{
			Networkshield = fullShield;
		}
	}

	[Command]
	public void CmdRechargeShieldFull()
	{
		RechargeShieldFull();
	}

	[Server]
	public void RechargeShield(float value)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::RechargeShield(System.Single)' called on client");
		}
		else if (shield < fullShield)
		{
			Networkshield = shield + value;
			if (shield > fullShield)
			{
				Networkshield = fullShield;
			}
		}
	}

	[Server]
	public void AddBarrier(float value)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::AddBarrier(System.Single)' called on client");
		}
		else if (alive && barrier < fullBarrier)
		{
			Networkbarrier = Mathf.Min(barrier + value, fullBarrier);
		}
	}

	[Server]
	public void AddCharge(float value)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::AddCharge(System.Single)' called on client");
		}
		else if (alive && magnetiCharge < fullHealth)
		{
			NetworkmagnetiCharge = Mathf.Min(barrier + value, fullBarrier);
		}
	}

	[Command]
	private void CmdAddBarrier(float value)
	{
		AddBarrier(value);
	}

	public void AddBarrierAuthority(float value)
	{
		if (NetworkServer.active)
		{
			AddBarrier(value);
		}
		else
		{
			CallCmdAddBarrier(value);
		}
	}

	[Command]
	private void CmdForceShieldRegen()
	{
		ForceShieldRegen();
	}

	public void ForceShieldRegen()
	{
		if (NetworkServer.active)
		{
			isShieldRegenForced = true;
		}
		else
		{
			CallCmdForceShieldRegen();
		}
	}

	[Server]
	public void Die(bool noCorpse = false)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::Die(System.Boolean)' called on client");
			return;
		}
		Networkhealth = 0f;
		modelLocator.forceCulled = noCorpse;
		if ((bool)body && body.cost > 0f && CombatDirector.instancesList.Count > 0)
		{
			CombatDirector combatDirector = CombatDirector.instancesList[0];
			if (body.isElite || CombatDirector.IsEliteOnlyArtifactActive())
			{
				combatDirector.monsterCredit += body.cost;
			}
			else
			{
				combatDirector.refundedMonsterCredit += body.cost;
			}
			Debug.LogError("Refunded CombatDirector " + body.cost + " credits");
		}
	}

	[Server]
	public void TakeDamageForce(DamageInfo damageInfo, bool alwaysApply = false, bool disableAirControlUntilCollision = false)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::TakeDamageForce(RoR2.DamageInfo,System.Boolean,System.Boolean)' called on client");
		}
		else if (!body.HasBuff(RoR2Content.Buffs.EngiShield) || !(shield > 0f))
		{
			CharacterMotor component = GetComponent<CharacterMotor>();
			if ((bool)component)
			{
				component.ApplyForce(damageInfo.force, alwaysApply, disableAirControlUntilCollision);
			}
			Rigidbody component2 = GetComponent<Rigidbody>();
			if ((bool)component2)
			{
				component2.AddForce(damageInfo.force, ForceMode.Impulse);
			}
		}
	}

	[Server]
	public void TakeDamageForce(Vector3 force, bool alwaysApply = false, bool disableAirControlUntilCollision = false)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::TakeDamageForce(UnityEngine.Vector3,System.Boolean,System.Boolean)' called on client");
		}
		else if (!body.HasBuff(RoR2Content.Buffs.EngiShield) || !(shield > 0f))
		{
			CharacterMotor component = GetComponent<CharacterMotor>();
			if ((bool)component)
			{
				component.ApplyForce(force, alwaysApply, disableAirControlUntilCollision);
			}
			Rigidbody component2 = GetComponent<Rigidbody>();
			if ((bool)component2)
			{
				component2.AddForce(force, ForceMode.Impulse);
			}
		}
	}

	[Server]
	public void TakeDamage(DamageInfo damageInfo)
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::TakeDamage(RoR2.DamageInfo)' called on client");
		}
		else
		{
			TakeDamageProcess(damageInfo);
		}
	}

	private void TakeDamageProcess(DamageInfo damageInfo)
	{
		if (body.HasBuff(DLC2Content.Buffs.HiddenRejectAllDamage))
		{
			return;
		}
		if (!damageInfo.canRejectForce)
		{
			TakeDamageForce(damageInfo);
		}
		if (!alive || godMode || ospTimer > 0f)
		{
			return;
		}
		CharacterMaster characterMaster = null;
		CharacterBody characterBody = null;
		TeamIndex teamIndex = TeamIndex.None;
		Vector3 vector = Vector3.zero;
		float num = combinedHealth;
		if ((bool)damageInfo.attacker)
		{
			characterBody = damageInfo.attacker.GetComponent<CharacterBody>();
			if ((bool)characterBody)
			{
				teamIndex = characterBody.teamComponent.teamIndex;
				vector = characterBody.corePosition - damageInfo.position;
			}
		}
		if ((DamageTypeExtended)(damageInfo.damageType & DamageTypeExtended.DamagePercentOfMaxHealth) == DamageTypeExtended.DamagePercentOfMaxHealth)
		{
			damageInfo.damage = fullHealth * 0.1f;
		}
		bool flag = (ulong)(damageInfo.damageType & DamageType.BypassArmor) != 0;
		bool flag2 = (ulong)(damageInfo.damageType & DamageType.BypassBlock) != 0;
		if (!flag2 && itemCounts.bear > 0 && Util.CheckRoll(Util.ConvertAmplificationPercentageIntoReductionPercentage(15f * (float)itemCounts.bear)))
		{
			EffectData effectData = new EffectData
			{
				origin = damageInfo.position,
				rotation = Util.QuaternionSafeLookRotation((damageInfo.force != Vector3.zero) ? damageInfo.force : UnityEngine.Random.onUnitSphere)
			};
			EffectManager.SpawnEffect(AssetReferences.bearEffectPrefab, effectData, transmit: true);
			damageInfo.rejected = true;
		}
		if (!flag2 && body.HasBuff(DLC1Content.Buffs.BearVoidReady) && damageInfo.damage > 0f)
		{
			EffectData effectData2 = new EffectData
			{
				origin = damageInfo.position,
				rotation = Util.QuaternionSafeLookRotation((damageInfo.force != Vector3.zero) ? damageInfo.force : UnityEngine.Random.onUnitSphere)
			};
			EffectManager.SpawnEffect(AssetReferences.bearVoidEffectPrefab, effectData2, transmit: true);
			damageInfo.rejected = true;
			body.RemoveBuff(DLC1Content.Buffs.BearVoidReady);
			int itemCount = body.inventory.GetItemCount(DLC1Content.Items.BearVoid);
			Mathf.CeilToInt(15f * Mathf.Pow(0.9f, itemCount));
			body.AddTimedBuff(DLC1Content.Buffs.BearVoidCooldown, 15f * Mathf.Pow(0.9f, itemCount));
		}
		if (body.HasBuff(RoR2Content.Buffs.HiddenInvincibility) && !flag)
		{
			damageInfo.rejected = true;
		}
		if (((ulong)(damageInfo.damageType & DamageTypeExtended.SojournVehicleDamage) == 0) & body.HasBuff(DLC2Content.Buffs.SojournVehicle))
		{
			damageInfo.rejected = true;
		}
		if (body.HasBuff(RoR2Content.Buffs.Immune) && (!characterBody || !characterBody.HasBuff(JunkContent.Buffs.GoldEmpowered)))
		{
			EffectManager.SpawnEffect(AssetReferences.damageRejectedPrefab, new EffectData
			{
				origin = damageInfo.position
			}, transmit: true);
			damageInfo.rejected = true;
		}
		if (!damageInfo.rejected && body.HasBuff(JunkContent.Buffs.BodyArmor))
		{
			body.RemoveBuff(JunkContent.Buffs.BodyArmor);
			EffectData effectData3 = new EffectData
			{
				origin = damageInfo.position,
				rotation = Util.QuaternionSafeLookRotation((damageInfo.force != Vector3.zero) ? damageInfo.force : UnityEngine.Random.onUnitSphere)
			};
			EffectManager.SpawnEffect(AssetReferences.captainBodyArmorBlockEffectPrefab, effectData3, transmit: true);
			damageInfo.rejected = true;
		}
		IOnIncomingDamageServerReceiver[] array = onIncomingDamageReceivers;
		for (int i = 0; i < array.Length; i++)
		{
			array[i].OnIncomingDamageServer(damageInfo);
		}
		if (damageInfo.rejected)
		{
			return;
		}
		if (body.HasBuff(DLC2Content.Buffs.lunarruin))
		{
			float num2 = (float)body.GetBuffCount(DLC2Content.Buffs.lunarruin) * 0.1f;
			float num3 = damageInfo.damage * num2;
			damageInfo.damage += num3;
		}
		float num4 = damageInfo.damage;
		if (teamIndex == body.teamComponent.teamIndex)
		{
			TeamDef teamDef = TeamCatalog.GetTeamDef(teamIndex);
			if (teamDef != null)
			{
				num4 *= teamDef.friendlyFireScaling;
			}
		}
		if (num4 > 0f)
		{
			if ((bool)characterBody)
			{
				if (characterBody.canPerformBackstab && (DamageType)(damageInfo.damageType & DamageType.DoT) != DamageType.DoT && (damageInfo.procChainMask.HasProc(ProcType.Backstab) || BackstabManager.IsBackstab(-vector, body)))
				{
					damageInfo.crit = true;
					damageInfo.procChainMask.AddProc(ProcType.Backstab);
					if ((bool)BackstabManager.backstabImpactEffectPrefab)
					{
						EffectManager.SimpleImpactEffect(BackstabManager.backstabImpactEffectPrefab, damageInfo.position, -damageInfo.force, transmit: true);
					}
				}
				characterMaster = characterBody.master;
				if ((bool)characterMaster && (bool)characterMaster.inventory)
				{
					if (num >= fullCombinedHealth * 0.9f)
					{
						int itemCount2 = characterMaster.inventory.GetItemCount(RoR2Content.Items.Crowbar);
						if (itemCount2 > 0)
						{
							num4 *= 1f + 0.75f * (float)itemCount2;
							EffectManager.SimpleImpactEffect(AssetReferences.crowbarImpactEffectPrefab, damageInfo.position, -damageInfo.force, transmit: true);
						}
					}
					if (num >= fullCombinedHealth && !damageInfo.rejected)
					{
						int itemCount3 = characterMaster.inventory.GetItemCount(DLC1Content.Items.ExplodeOnDeathVoid);
						if (itemCount3 > 0)
						{
							Vector3 corePosition = Util.GetCorePosition(body);
							float damageCoefficient = 2.6f * (1f + (float)(itemCount3 - 1) * 0.6f);
							float baseDamage = Util.OnKillProcDamage(characterBody.damage, damageCoefficient);
							GameObject obj = UnityEngine.Object.Instantiate(AssetReferences.explodeOnDeathVoidExplosionPrefab, corePosition, Quaternion.identity);
							DelayBlast component = obj.GetComponent<DelayBlast>();
							component.position = corePosition;
							component.baseDamage = baseDamage;
							component.baseForce = 1000f;
							component.radius = 12f + 2.4f * ((float)itemCount3 - 1f);
							component.attacker = damageInfo.attacker;
							component.inflictor = null;
							component.crit = Util.CheckRoll(characterBody.crit, characterMaster);
							component.maxTimer = 0.2f;
							component.damageColorIndex = DamageColorIndex.Void;
							component.falloffModel = BlastAttack.FalloffModel.SweetSpot;
							obj.GetComponent<TeamFilter>().teamIndex = teamIndex;
							NetworkServer.Spawn(obj);
						}
					}
					int itemCount4 = characterMaster.inventory.GetItemCount(RoR2Content.Items.NearbyDamageBonus);
					if (itemCount4 > 0 && vector.sqrMagnitude <= 169f)
					{
						damageInfo.damageColorIndex = DamageColorIndex.Nearby;
						num4 *= 1f + (float)itemCount4 * 0.2f;
						EffectManager.SimpleImpactEffect(AssetReferences.diamondDamageBonusImpactEffectPrefab, damageInfo.position, vector, transmit: true);
					}
					int itemCount5 = characterMaster.inventory.GetItemCount(DLC1Content.Items.FragileDamageBonus);
					if (itemCount5 > 0)
					{
						num4 *= 1f + (float)itemCount5 * 0.2f;
					}
					if (characterMaster.GetBody().HasBuff(DLC2Content.Buffs.LowerHealthHigherDamageBuff))
					{
						int itemCount6 = characterMaster.inventory.GetItemCount(DLC2Content.Items.LowerHealthHigherDamage);
						num4 *= 1f + (float)itemCount6 * 0.2f;
					}
					if (damageInfo.procCoefficient > 0f)
					{
						int itemCount7 = characterMaster.inventory.GetItemCount(RoR2Content.Items.ArmorReductionOnHit);
						if (itemCount7 > 0 && !body.HasBuff(RoR2Content.Buffs.Pulverized))
						{
							body.AddTimedBuff(RoR2Content.Buffs.PulverizeBuildup, 2f * damageInfo.procCoefficient);
							if (body.GetBuffCount(RoR2Content.Buffs.PulverizeBuildup) >= 5)
							{
								body.ClearTimedBuffs(RoR2Content.Buffs.PulverizeBuildup);
								body.AddTimedBuff(RoR2Content.Buffs.Pulverized, 8f * (float)itemCount7);
								EffectManager.SpawnEffect(AssetReferences.pulverizedEffectPrefab, new EffectData
								{
									origin = body.corePosition,
									scale = body.radius
								}, transmit: true);
							}
						}
						int itemCount8 = characterMaster.inventory.GetItemCount(DLC1Content.Items.PermanentDebuffOnHit);
						bool flag3 = false;
						for (int j = 0; j < itemCount8; j++)
						{
							if (Util.CheckRoll(100f * damageInfo.procCoefficient, characterMaster))
							{
								body.AddBuff(DLC1Content.Buffs.PermanentDebuff);
								flag3 = true;
							}
						}
						if (flag3)
						{
							EffectManager.SpawnEffect(AssetReferences.permanentDebuffEffectPrefab, new EffectData
							{
								origin = damageInfo.position,
								scale = itemCount8
							}, transmit: true);
						}
						if (body.HasBuff(RoR2Content.Buffs.MercExpose) && (bool)characterBody && characterBody.bodyIndex == BodyCatalog.FindBodyIndex("MercBody"))
						{
							body.RemoveBuff(RoR2Content.Buffs.MercExpose);
							float num5 = characterBody.damage * 3.5f;
							num4 += num5;
							damageInfo.damage += num5;
							SkillLocator skillLocator = characterBody.skillLocator;
							if ((bool)skillLocator)
							{
								skillLocator.DeductCooldownFromAllSkillsServer(1f);
							}
							EffectManager.SimpleImpactEffect(AssetReferences.mercExposeConsumeEffectPrefab, damageInfo.position, Vector3.up, transmit: true);
						}
					}
					if (body.isBoss)
					{
						int itemCount9 = characterMaster.inventory.GetItemCount(RoR2Content.Items.BossDamageBonus);
						if (itemCount9 > 0)
						{
							num4 *= 1f + 0.2f * (float)itemCount9;
							damageInfo.damageColorIndex = DamageColorIndex.WeakPoint;
							EffectManager.SimpleImpactEffect(AssetReferences.bossDamageBonusImpactEffectPrefab, damageInfo.position, -damageInfo.force, transmit: true);
						}
					}
				}
				if (damageInfo.crit)
				{
					num4 *= characterBody.critMultiplier;
				}
			}
			if ((ulong)(damageInfo.damageType & DamageType.WeakPointHit) != 0L)
			{
				num4 *= 1.5f;
				damageInfo.damageColorIndex = DamageColorIndex.WeakPoint;
			}
			if (body.HasBuff(RoR2Content.Buffs.DeathMark))
			{
				num4 *= 1.5f;
				damageInfo.damageColorIndex = DamageColorIndex.DeathMark;
			}
			if (!flag)
			{
				float armor = body.armor;
				armor += adaptiveArmorValue;
				bool flag4 = (ulong)(damageInfo.damageType & DamageType.AOE) != 0;
				if ((body.bodyFlags & CharacterBody.BodyFlags.ResistantToAOE) != 0 && flag4)
				{
					armor += 300f;
				}
				float num6 = ((armor >= 0f) ? (1f - armor / (armor + 100f)) : (2f - 100f / (100f - armor)));
				num4 = Mathf.Max(1f, num4 * num6);
				if (itemCounts.armorPlate > 0)
				{
					num4 = Mathf.Max(1f, num4 - 5f * (float)itemCounts.armorPlate);
					EntitySoundManager.EmitSoundServer(LegacyResourcesAPI.Load<NetworkSoundEventDef>("NetworkSoundEventDefs/nseArmorPlateBlock").index, base.gameObject);
				}
				if (itemCounts.parentEgg > 0)
				{
					Heal((float)itemCounts.parentEgg * 15f, default(ProcChainMask));
					EntitySoundManager.EmitSoundServer(LegacyResourcesAPI.Load<NetworkSoundEventDef>("NetworkSoundEventDefs/nseParentEggHeal").index, base.gameObject);
				}
			}
			if (body.hasOneShotProtection && (DamageType)(damageInfo.damageType & DamageType.BypassOneShotProtection) != DamageType.BypassOneShotProtection)
			{
				float num7 = (fullCombinedHealth + barrier) * (1f - body.oneShotProtectionFraction);
				float b = Mathf.Max(0f, num7 - serverDamageTakenThisUpdate);
				float num8 = num4;
				num4 = Mathf.Min(num4, b);
				if (num4 != num8)
				{
					TriggerOneShotProtection();
				}
			}
			if ((ulong)(damageInfo.damageType & DamageType.BonusToLowHealth) != 0)
			{
				float num9 = Mathf.Lerp(3f, 1f, combinedHealthFraction);
				num4 *= num9;
			}
			if (body.HasBuff(RoR2Content.Buffs.LunarShell) && num4 > fullHealth * 0.1f)
			{
				num4 = fullHealth * 0.1f;
			}
			if (itemCounts.minHealthPercentage > 0)
			{
				float num10 = fullCombinedHealth * ((float)itemCounts.minHealthPercentage / 100f);
				num4 = Mathf.Max(0f, Mathf.Min(num4, combinedHealth - num10));
			}
		}
		if ((ulong)(damageInfo.damageType & DamageType.SlowOnHit) != 0L)
		{
			body.AddTimedBuff(RoR2Content.Buffs.Slow50, 2f);
		}
		if ((ulong)(damageInfo.damageType & DamageType.ClayGoo) != 0L && (body.bodyFlags & CharacterBody.BodyFlags.ImmuneToGoo) == 0)
		{
			body.AddTimedBuff(RoR2Content.Buffs.ClayGoo, 2f);
		}
		if ((ulong)(damageInfo.damageType & DamageType.Nullify) != 0L)
		{
			body.AddTimedBuff(RoR2Content.Buffs.NullifyStack, 8f);
		}
		if ((ulong)(damageInfo.damageType & DamageType.CrippleOnHit) != 0L || ((bool)characterBody && characterBody.HasBuff(RoR2Content.Buffs.AffixLunar)))
		{
			body.AddTimedBuff(RoR2Content.Buffs.Cripple, 3f);
		}
		if ((ulong)(damageInfo.damageType & DamageType.ApplyMercExpose) != 0L)
		{
			Debug.LogFormat("Adding expose");
			body.AddBuff(RoR2Content.Buffs.MercExpose);
		}
		CharacterMaster master = body.master;
		if ((bool)master)
		{
			if (itemCounts.goldOnHit > 0)
			{
				uint num11 = (uint)(num4 / fullCombinedHealth * (float)master.money * (float)itemCounts.goldOnHit);
				uint money = master.money;
				master.money = (uint)Mathf.Max(0f, (float)master.money - (float)num11);
				if (money - master.money != 0)
				{
					GoldOrb goldOrb = new GoldOrb();
					goldOrb.origin = damageInfo.position;
					goldOrb.target = (characterBody ? characterBody.mainHurtBox : body.mainHurtBox);
					goldOrb.goldAmount = 0u;
					OrbManager.instance.AddOrb(goldOrb);
					EffectManager.SimpleImpactEffect(AssetReferences.loseCoinsImpactEffectPrefab, damageInfo.position, Vector3.up, transmit: true);
				}
			}
			if (itemCounts.goldOnHurt > 0 && characterBody != body && characterBody != null)
			{
				int num12 = 3;
				GoldOrb goldOrb2 = new GoldOrb();
				goldOrb2.origin = damageInfo.position;
				goldOrb2.target = body.mainHurtBox;
				goldOrb2.goldAmount = (uint)((float)(itemCounts.goldOnHurt * num12) * Run.instance.difficultyCoefficient);
				OrbManager.instance.AddOrb(goldOrb2);
				EffectManager.SimpleImpactEffect(AssetReferences.gainCoinsImpactEffectPrefab, damageInfo.position, Vector3.up, transmit: true);
			}
		}
		if (itemCounts.adaptiveArmor > 0)
		{
			float num13 = num4 / fullCombinedHealth * 100f * 30f * (float)itemCounts.adaptiveArmor;
			adaptiveArmorValue = Mathf.Min(adaptiveArmorValue + num13, 400f);
		}
		float num14 = num4;
		if (num14 > 0f)
		{
			isShieldRegenForced = false;
		}
		if (body.teamComponent.teamIndex == TeamIndex.Player && Run.instance.selectedDifficulty >= DifficultyIndex.Eclipse8)
		{
			float num15 = num14 / fullCombinedHealth * 100f;
			float num16 = 0.4f;
			int num17 = Mathf.FloorToInt(num15 * num16);
			for (int k = 0; k < num17; k++)
			{
				body.AddBuff(RoR2Content.Buffs.PermanentCurse);
			}
		}
		if (num14 > 0f && barrier > 0f)
		{
			if (num14 <= barrier)
			{
				Networkbarrier = barrier - num14;
				num14 = 0f;
			}
			else
			{
				num14 -= barrier;
				Networkbarrier = 0f;
			}
		}
		if (num14 > 0f && shield > 0f)
		{
			if (num14 <= shield)
			{
				Networkshield = shield - num14;
				num14 = 0f;
			}
			else
			{
				num14 -= shield;
				Networkshield = 0f;
				float scale = 1f;
				if ((bool)body)
				{
					scale = body.radius;
				}
				EffectManager.SpawnEffect(AssetReferences.shieldBreakEffectPrefab, new EffectData
				{
					origin = base.transform.position,
					scale = scale
				}, transmit: true);
			}
		}
		if (!flag2 && body.HasBuff(DLC2Content.Buffs.DelayedDamageBuff) && damageInfo.damage > 0f && !damageInfo.delayedDamageSecondHalf && !damageInfo.rejected)
		{
			Transform transform = (body.mainHurtBox ? body.mainHurtBox.transform : base.transform);
			UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/DelayedDamageIndicator"), transform.position, Quaternion.identity, transform);
			Util.PlaySound("Play_item_proc_delayedDamage", body.gameObject);
			num14 *= 0.5f;
			num4 = num14;
			DamageInfo damageInfo2 = new DamageInfo
			{
				crit = damageInfo.crit,
				damage = num14,
				damageType = DamageType.BypassArmor,
				attacker = damageInfo.attacker,
				position = damageInfo.position,
				inflictor = damageInfo.inflictor,
				damageColorIndex = damageInfo.damageColorIndex,
				delayedDamageSecondHalf = true
			};
			damageInfo2.damageType |= damageInfo.damageType & DamageType.NonLethal;
			body.SecondHalfOfDelayedDamage(damageInfo2);
		}
		bool flag5 = (ulong)(damageInfo.damageType & DamageType.VoidDeath) != 0L && (body.bodyFlags & CharacterBody.BodyFlags.ImmuneToVoidDeath) == 0;
		float executionHealthLost = 0f;
		GameObject gameObject = null;
		if (num14 > 0f)
		{
			float num18 = health - num14;
			if (num18 < 1f && (ulong)(damageInfo.damageType & DamageType.NonLethal) != 0L && health >= 1f)
			{
				num18 = 1f;
			}
			Networkhealth = num18;
			recentlyTookDamageCoyoteTimer = 0.2f;
		}
		if (health > 0f && body.teamComponent.teamIndex == TeamIndex.Player && (bool)body.inventory && body.inventory.GetItemCount(DLC2Content.Items.LowerHealthHigherDamage) > 0)
		{
			body.UpdateLowerHealthHigherDamage();
		}
		float num19 = float.NegativeInfinity;
		bool flag6 = (body.bodyFlags & CharacterBody.BodyFlags.ImmuneToExecutes) != 0;
		if (!flag5 && !flag6)
		{
			if (isInFrozenState && num19 < 0.3f)
			{
				num19 = 0.3f;
				gameObject = FrozenState.executeEffectPrefab;
			}
			if ((bool)characterBody)
			{
				if (body.isElite)
				{
					float executeEliteHealthFraction = characterBody.executeEliteHealthFraction;
					if (num19 < executeEliteHealthFraction)
					{
						num19 = executeEliteHealthFraction;
						gameObject = AssetReferences.executeEffectPrefab;
					}
				}
				if (!body.isBoss && (bool)characterBody.inventory && Util.CheckRoll((float)characterBody.inventory.GetItemCount(DLC1Content.Items.CritGlassesVoid) * 0.5f * damageInfo.procCoefficient, characterBody.master))
				{
					flag5 = true;
					gameObject = AssetReferences.critGlassesVoidExecuteEffectPrefab;
					damageInfo.damageType |= (DamageTypeCombo)DamageType.VoidDeath;
				}
			}
		}
		if (flag5 || (num19 > 0f && combinedHealthFraction <= num19))
		{
			flag5 = true;
			executionHealthLost = Mathf.Max(combinedHealth, 0f);
			if (health > 0f)
			{
				Networkhealth = 0f;
			}
			if (shield > 0f)
			{
				Networkshield = 0f;
			}
			if (barrier > 0f)
			{
				Networkbarrier = 0f;
			}
		}
		if (damageInfo.canRejectForce)
		{
			TakeDamageForce(damageInfo);
		}
		DamageReport damageReport = new DamageReport(damageInfo, this, num4, num);
		IOnTakeDamageServerReceiver[] array2 = onTakeDamageReceivers;
		for (int i = 0; i < array2.Length; i++)
		{
			array2[i].OnTakeDamageServer(damageReport);
		}
		if (num4 > 0f)
		{
			SendDamageDealt(damageReport);
		}
		UpdateLastHitTime(damageReport.damageDealt, damageInfo.position, (ulong)(damageInfo.damageType & DamageType.Silent) != 0, damageInfo.attacker);
		if ((bool)damageInfo.attacker)
		{
			List<IOnDamageDealtServerReceiver> gameObjectComponents = GetComponentsCache<IOnDamageDealtServerReceiver>.GetGameObjectComponents(damageInfo.attacker);
			foreach (IOnDamageDealtServerReceiver item in gameObjectComponents)
			{
				item.OnDamageDealtServer(damageReport);
			}
			GetComponentsCache<IOnDamageDealtServerReceiver>.ReturnBuffer(gameObjectComponents);
		}
		if ((bool)damageInfo.inflictor)
		{
			List<IOnDamageInflictedServerReceiver> gameObjectComponents2 = GetComponentsCache<IOnDamageInflictedServerReceiver>.GetGameObjectComponents(damageInfo.inflictor);
			foreach (IOnDamageInflictedServerReceiver item2 in gameObjectComponents2)
			{
				item2.OnDamageInflictedServer(damageReport);
			}
			GetComponentsCache<IOnDamageInflictedServerReceiver>.ReturnBuffer(gameObjectComponents2);
		}
		GlobalEventManager.ServerDamageDealt(damageReport);
		if (!alive)
		{
			killingDamageType = damageInfo.damageType;
			if (flag5)
			{
				GlobalEventManager.ServerCharacterExecuted(damageReport, executionHealthLost);
				if ((object)gameObject != null)
				{
					EffectManager.SpawnEffect(gameObject, new EffectData
					{
						origin = body.corePosition,
						scale = (body ? body.radius : 1f)
					}, transmit: true);
				}
			}
			IOnKilledServerReceiver[] components = GetComponents<IOnKilledServerReceiver>();
			for (int i = 0; i < components.Length; i++)
			{
				components[i].OnKilledServer(damageReport);
			}
			if ((bool)damageInfo.attacker)
			{
				IOnKilledOtherServerReceiver[] components2 = damageInfo.attacker.GetComponents<IOnKilledOtherServerReceiver>();
				for (int i = 0; i < components2.Length; i++)
				{
					components2[i].OnKilledOtherServer(damageReport);
				}
			}
			if (Util.CheckRoll(globalDeathEventChanceCoefficient * 100f))
			{
				GlobalEventManager.instance.OnCharacterDeath(damageReport);
			}
		}
		else
		{
			if (!(num4 > 0f))
			{
				return;
			}
			int a = 5 + 2 * (itemCounts.thorns - 1);
			if (itemCounts.thorns > 0 && !damageReport.damageInfo.procChainMask.HasProc(ProcType.Thorns))
			{
				bool flag7 = itemCounts.invadingDoppelganger > 0;
				float radius = 25f + 10f * (float)(itemCounts.thorns - 1);
				bool isCrit = body.RollCrit();
				float damageValue = 1.6f * body.damage;
				TeamIndex teamIndex2 = body.teamComponent.teamIndex;
				HurtBox[] hurtBoxes = new SphereSearch
				{
					origin = damageReport.damageInfo.position,
					radius = radius,
					mask = LayerIndex.entityPrecise.mask,
					queryTriggerInteraction = QueryTriggerInteraction.UseGlobal
				}.RefreshCandidates().FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(teamIndex2)).OrderCandidatesByDistance()
					.FilterCandidatesByDistinctHurtBoxEntities()
					.GetHurtBoxes();
				for (int l = 0; l < Mathf.Min(a, hurtBoxes.Length); l++)
				{
					LightningOrb lightningOrb = new LightningOrb();
					lightningOrb.attacker = base.gameObject;
					lightningOrb.bouncedObjects = null;
					lightningOrb.bouncesRemaining = 0;
					lightningOrb.damageCoefficientPerBounce = 1f;
					lightningOrb.damageColorIndex = DamageColorIndex.Item;
					lightningOrb.damageValue = damageValue;
					lightningOrb.isCrit = isCrit;
					lightningOrb.lightningType = LightningOrb.LightningType.RazorWire;
					lightningOrb.origin = damageReport.damageInfo.position;
					lightningOrb.procChainMask = default(ProcChainMask);
					lightningOrb.procChainMask.AddProc(ProcType.Thorns);
					lightningOrb.procCoefficient = (flag7 ? 0f : 0.5f);
					lightningOrb.range = 0f;
					lightningOrb.teamIndex = teamIndex2;
					lightningOrb.target = hurtBoxes[l];
					OrbManager.instance.AddOrb(lightningOrb);
				}
			}
			if (!flag2 && itemCounts.antlerShield > 0 && characterBody != null && !damageInfo.delayedDamageSecondHalf && damageInfo.attacker.GetComponent<TeamComponent>().teamIndex != body.teamComponent.teamIndex && Util.CheckRoll(50f + 5f * (float)(itemCounts.antlerShield - 1)))
			{
				bool flag8 = itemCounts.invadingDoppelganger > 0;
				float damageValue2 = damageInfo.damage / 10f * (float)itemCounts.antlerShield;
				bool isCrit2 = body.RollCrit();
				TeamIndex teamIndex3 = body.teamComponent.teamIndex;
				LightningOrb lightningOrb2 = new LightningOrb();
				lightningOrb2.attacker = base.gameObject;
				lightningOrb2.bouncedObjects = null;
				lightningOrb2.bouncesRemaining = 0;
				lightningOrb2.damageCoefficientPerBounce = 1f;
				lightningOrb2.damageColorIndex = DamageColorIndex.Item;
				lightningOrb2.damageValue = damageValue2;
				lightningOrb2.isCrit = isCrit2;
				lightningOrb2.lightningType = LightningOrb.LightningType.AntlerShield;
				lightningOrb2.origin = damageReport.damageInfo.position;
				lightningOrb2.procChainMask = default(ProcChainMask);
				lightningOrb2.procChainMask.AddProc(ProcType.Thorns);
				lightningOrb2.procCoefficient = (flag8 ? 0f : 0.3f);
				lightningOrb2.range = 0f;
				lightningOrb2.teamIndex = teamIndex3;
				lightningOrb2.target = characterBody.mainHurtBox;
				OrbManager.instance.AddOrb(lightningOrb2);
				Util.PlaySound("Play_item_proc_negateAttack", body.gameObject);
			}
			if (!flag2 && itemCounts.noxiousThorn > 0 && Util.CheckRoll(25f))
			{
				body.TriggerEnemyDebuffs(damageInfo);
			}
			if (!body.HasBuff(DLC2Content.Buffs.AurelioniteBlessing))
			{
				return;
			}
			int baseCost = 1;
			int difficultyScaledCost = Run.instance.GetDifficultyScaledCost(baseCost);
			uint money2 = characterMaster.money;
			characterMaster.money = (uint)Mathf.Max(0f, (float)characterMaster.money - (float)difficultyScaledCost);
			if (money2 - characterMaster.money != 0 || !characterBody.isPlayerControlled)
			{
				GoldOrb goldOrb3 = new GoldOrb();
				goldOrb3.origin = characterBody.transform.position;
				goldOrb3.target = (body ? body.mainHurtBox : characterBody.mainHurtBox);
				goldOrb3.goldAmount = (uint)difficultyScaledCost;
				OrbManager.instance.AddOrb(goldOrb3);
				EffectManager.SimpleImpactEffect(AssetReferences.loseCoinsImpactEffectPrefab, damageInfo.position, Vector3.up, transmit: true);
				if (!characterBody.isPlayerControlled)
				{
					characterMaster.money = money2;
				}
			}
		}
	}

	[Server]
	private void TriggerOneShotProtection()
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::TriggerOneShotProtection()' called on client");
			return;
		}
		ospTimer = 0.1f;
		if (body.GetBuffCount(DLC2Content.Buffs.DelayedDamageDebuff) > 0)
		{
			body.protectFromOneShot = true;
		}
	}

	[Server]
	public void Suicide(GameObject killerOverride = null, GameObject inflictorOverride = null, DamageTypeCombo damageType = default(DamageTypeCombo))
	{
		if (!NetworkServer.active)
		{
			Debug.LogWarning("[Server] function 'System.Void RoR2.HealthComponent::Suicide(UnityEngine.GameObject,UnityEngine.GameObject,RoR2.DamageTypeCombo)' called on client");
		}
		else if (alive && !godMode)
		{
			float combinedHealthBeforeDamage = combinedHealth;
			DamageInfo damageInfo = new DamageInfo();
			damageInfo.damage = combinedHealth;
			damageInfo.position = base.transform.position;
			damageInfo.damageType = damageType;
			damageInfo.procCoefficient = 1f;
			if ((bool)killerOverride)
			{
				damageInfo.attacker = killerOverride;
			}
			if ((bool)inflictorOverride)
			{
				damageInfo.inflictor = inflictorOverride;
			}
			Networkhealth = 0f;
			DamageReport damageReport = new DamageReport(damageInfo, this, damageInfo.damage, combinedHealthBeforeDamage);
			killingDamageType = damageInfo.damageType;
			IOnKilledServerReceiver[] components = GetComponents<IOnKilledServerReceiver>();
			for (int i = 0; i < components.Length; i++)
			{
				components[i].OnKilledServer(damageReport);
			}
			GlobalEventManager.instance.OnCharacterDeath(damageReport);
		}
	}

	public void UpdateLastHitTime(float damageValue, Vector3 damagePosition, bool damageIsSilent, GameObject attacker)
	{
		if (NetworkServer.active && (bool)body && damageValue > 0f)
		{
			if (itemCounts.medkit > 0)
			{
				body.AddTimedBuff(RoR2Content.Buffs.MedkitHeal, 2f);
			}
			if (itemCounts.healingPotion > 0 && isHealthLow)
			{
				body.inventory.RemoveItem(DLC1Content.Items.HealingPotion);
				body.inventory.GiveItem(DLC1Content.Items.HealingPotionConsumed);
				CharacterMasterNotificationQueue.SendTransformNotification(body.master, DLC1Content.Items.HealingPotion.itemIndex, DLC1Content.Items.HealingPotionConsumed.itemIndex, CharacterMasterNotificationQueue.TransformationType.Default);
				HealFraction(0.75f, default(ProcChainMask));
				EffectData effectData = new EffectData
				{
					origin = base.transform.position
				};
				effectData.SetNetworkedObjectReference(base.gameObject);
				EffectManager.SpawnEffect(LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/HealingPotionEffect"), effectData, transmit: true);
			}
			if (body.GetBuffCount(DLC2Content.Buffs.RevitalizeBuff) > 0 && isHealthLow)
			{
				body.RemoveBuff(DLC2Content.Buffs.RevitalizeBuff);
				HealFraction(0.5f, default(ProcChainMask));
				EffectData effectData2 = new EffectData
				{
					origin = base.transform.position
				};
				effectData2.SetNetworkedObjectReference(base.gameObject);
				EffectManager.SpawnEffect(LegacyResourcesAPI.Load<GameObject>("Seeker/RevitalizeBuffVFXConsumed"), effectData2, transmit: true);
			}
			float num = 120f;
			if (isHealthLow && body.HasBuff(DLC2Content.Buffs.TeleportOnLowHealth) && itemCounts.unstableTransmitter > 0)
			{
				body.RemoveBuff(DLC2Content.Buffs.TeleportOnLowHealth);
				float duration = Mathf.Max(num - num * ((float)(itemCounts.unstableTransmitter - 1) * 0.2f), 15f);
				body.AddTimedBuff(DLC2Content.Buffs.TeleportOnLowHealthCooldown, duration);
				body.hasTeleported = true;
				body.AddTimedBuff(RoR2Content.Buffs.HiddenInvincibility, 2f);
				body.CallRpcTeleportCharacterToSafety();
			}
			if (itemCounts.fragileDamageBonus > 0 && isHealthLow)
			{
				body.inventory.GiveItem(DLC1Content.Items.FragileDamageBonusConsumed, itemCounts.fragileDamageBonus);
				body.inventory.RemoveItem(DLC1Content.Items.FragileDamageBonus, itemCounts.fragileDamageBonus);
				CharacterMasterNotificationQueue.SendTransformNotification(body.master, DLC1Content.Items.FragileDamageBonus.itemIndex, DLC1Content.Items.FragileDamageBonusConsumed.itemIndex, CharacterMasterNotificationQueue.TransformationType.Default);
				EffectData effectData3 = new EffectData
				{
					origin = base.transform.position
				};
				effectData3.SetNetworkedObjectReference(base.gameObject);
				EffectManager.SpawnEffect(AssetReferences.fragileDamageBonusBreakEffectPrefab, effectData3, transmit: true);
			}
		}
		if (damageIsSilent)
		{
			return;
		}
		lastHitTime = Run.FixedTimeStamp.now;
		lastHitAttacker = attacker;
		serverDamageTakenThisUpdate += damageValue;
		if ((bool)modelLocator)
		{
			Transform modelTransform = modelLocator.modelTransform;
			if ((bool)modelTransform)
			{
				Animator component = modelTransform.GetComponent<Animator>();
				if ((bool)component)
				{
					string layerName = "Flinch";
					int layerIndex = component.GetLayerIndex(layerName);
					if (layerIndex >= 0)
					{
						component.SetLayerWeight(layerIndex, 1f + Mathf.Clamp01(damageValue / fullCombinedHealth * 10f) * 3f);
						component.Play("FlinchStart", layerIndex);
					}
				}
			}
		}
		painAnimationHandler?.HandlePain(damageValue, damagePosition);
	}

	[InitDuringStartup]
	private static void Init()
	{
		AssetReferences.Resolve();
	}

	private void Awake()
	{
		body = GetComponent<CharacterBody>();
		modelLocator = GetComponent<ModelLocator>();
		painAnimationHandler = GetComponent<IPainAnimationHandler>();
		onIncomingDamageReceivers = GetComponents<IOnIncomingDamageServerReceiver>();
		onTakeDamageReceivers = GetComponents<IOnTakeDamageServerReceiver>();
		lastHitTime = Run.FixedTimeStamp.negativeInfinity;
		lastHealTime = Run.FixedTimeStamp.negativeInfinity;
		body.onInventoryChanged += OnInventoryChanged;
	}

	private void OnDestroy()
	{
		body.onInventoryChanged -= OnInventoryChanged;
	}

	public void FixedUpdate()
	{
		ManagedFixedUpdate(Time.fixedDeltaTime);
	}

	public void ManagedFixedUpdate(float deltaTime)
	{
		if (NetworkServer.active)
		{
			ServerFixedUpdate(deltaTime);
		}
		if (!alive && wasAlive)
		{
			wasAlive = false;
			if ((bool)modelLocator)
			{
				modelLocator.forceCulled = forceCulled;
			}
			GetComponent<CharacterDeathBehavior>()?.OnDeath();
		}
	}

	private void ServerFixedUpdate(float deltaTime)
	{
		if (recentlyTookDamageCoyoteTimer > 0f)
		{
			recentlyTookDamageCoyoteTimer -= deltaTime;
		}
		if (!alive)
		{
			return;
		}
		regenAccumulator += body.regen * deltaTime;
		if (barrier > 0f)
		{
			Networkbarrier = Mathf.Max(barrier - body.barrierDecayRate * deltaTime, 0f);
			if (barrier <= 0f)
			{
				body.MarkAllStatsDirty();
			}
		}
		else if (barrier <= 0f && body.HasBuff(DLC2Content.Buffs.GeodeBuff))
		{
			body.RemoveBuff(DLC2Content.Buffs.GeodeBuff);
		}
		if (regenAccumulator > 1f)
		{
			float num = Mathf.Floor(regenAccumulator);
			regenAccumulator -= num;
			Heal(num, default(ProcChainMask), nonRegen: false);
		}
		if (regenAccumulator < -1f)
		{
			float num2 = Mathf.Ceil(regenAccumulator);
			regenAccumulator -= num2;
			Networkhealth = health + num2;
			if (health <= 0f)
			{
				Suicide();
			}
		}
		float num3 = shield;
		bool flag = num3 >= body.maxShield;
		if ((body.outOfDanger || isShieldRegenForced) && !flag)
		{
			num3 += body.maxShield * 0.5f * deltaTime;
			if (num3 > body.maxShield)
			{
				num3 = body.maxShield;
			}
		}
		if (num3 >= body.maxShield && !flag)
		{
			Util.PlaySound("Play_item_proc_personal_shield_end", base.gameObject);
		}
		if (!num3.Equals(shield))
		{
			Networkshield = num3;
		}
		if (devilOrbHealPool > 0f)
		{
			devilOrbTimer -= deltaTime;
			if (devilOrbTimer <= 0f)
			{
				devilOrbTimer += 0.1f;
				float scale = 1f;
				float num4 = fullCombinedHealth / 10f;
				float num5 = 2.5f;
				devilOrbHealPool -= num4;
				DevilOrb devilOrb = new DevilOrb();
				devilOrb.origin = body.aimOriginTransform.position;
				devilOrb.damageValue = num4 * num5;
				devilOrb.teamIndex = TeamComponent.GetObjectTeam(base.gameObject);
				devilOrb.attacker = base.gameObject;
				devilOrb.damageColorIndex = DamageColorIndex.Poison;
				devilOrb.scale = scale;
				devilOrb.procChainMask.AddProc(ProcType.HealNova);
				devilOrb.effectType = DevilOrb.EffectType.Skull;
				HurtBox hurtBox = devilOrb.PickNextTarget(devilOrb.origin, 40f);
				if ((bool)hurtBox)
				{
					devilOrb.target = hurtBox;
					devilOrb.isCrit = Util.CheckRoll(body.crit, body.master);
					OrbManager.instance.AddOrb(devilOrb);
				}
			}
		}
		adaptiveArmorValue = Mathf.Max(0f, adaptiveArmorValue - 40f * deltaTime);
		serverDamageTakenThisUpdate = 0f;
		ospTimer -= deltaTime;
	}

	private static void SendDamageDealt(DamageReport damageReport)
	{
		DamageInfo damageInfo = damageReport.damageInfo;
		DamageDealtMessage damageDealtMessage = new DamageDealtMessage();
		damageDealtMessage.victim = damageReport.victim.gameObject;
		damageDealtMessage.damage = damageReport.damageDealt;
		damageDealtMessage.attacker = damageInfo.attacker;
		damageDealtMessage.position = damageInfo.position;
		damageDealtMessage.crit = damageInfo.crit;
		damageDealtMessage.damageType = damageInfo.damageType;
		damageDealtMessage.damageColorIndex = damageInfo.damageColorIndex;
		damageDealtMessage.hitLowHealth = damageReport.hitLowHealth;
		NetworkServer.SendToAll(60, damageDealtMessage);
	}

	[NetworkMessageHandler(msgType = 60, client = true)]
	private static void HandleDamageDealt(NetworkMessage netMsg)
	{
		DamageDealtMessage damageDealtMessage = netMsg.ReadMessage<DamageDealtMessage>();
		if ((bool)damageDealtMessage.victim)
		{
			HealthComponent component = damageDealtMessage.victim.GetComponent<HealthComponent>();
			if ((bool)component && !NetworkServer.active)
			{
				component.UpdateLastHitTime(damageDealtMessage.damage, damageDealtMessage.position, damageDealtMessage.isSilent, damageDealtMessage.attacker);
			}
		}
		if (SettingsConVars.enableDamageNumbers.value && (bool)DamageNumberManager.instance)
		{
			TeamComponent teamComponent = null;
			if ((bool)damageDealtMessage.attacker)
			{
				teamComponent = damageDealtMessage.attacker.GetComponent<TeamComponent>();
			}
			DamageNumberManager.instance.SpawnDamageNumber(damageDealtMessage.damage, damageDealtMessage.position, damageDealtMessage.crit, teamComponent ? teamComponent.teamIndex : TeamIndex.None, damageDealtMessage.damageColorIndex);
		}
		GlobalEventManager.ClientDamageNotified(damageDealtMessage);
	}

	private static void SendHeal(GameObject target, float amount, bool isCrit)
	{
		HealMessage healMessage = new HealMessage();
		healMessage.target = target;
		healMessage.amount = (isCrit ? (0f - amount) : amount);
		NetworkServer.SendToAll(61, healMessage);
	}

	[NetworkMessageHandler(msgType = 61, client = true)]
	private static void HandleHeal(NetworkMessage netMsg)
	{
		HealMessage healMessage = netMsg.ReadMessage<HealMessage>();
		if (SettingsConVars.enableDamageNumbers.value && (bool)healMessage.target)
		{
			if ((bool)DamageNumberManager.instance)
			{
				DamageNumberManager.instance.SpawnDamageNumber(healMessage.amount, Util.GetCorePosition(healMessage.target), healMessage.amount < 0f, TeamIndex.Player, DamageColorIndex.Heal);
			}
			HealthComponent component = healMessage.target.GetComponent<HealthComponent>();
			if ((bool)component && !NetworkServer.active)
			{
				component.lastHealTime = Run.FixedTimeStamp.now;
			}
		}
	}

	private void OnInventoryChanged()
	{
		itemCounts = default(ItemCounts);
		Inventory inventory = body.inventory;
		itemCounts = (inventory ? new ItemCounts(inventory) : default(ItemCounts));
		currentEquipmentIndex = (inventory ? inventory.currentEquipmentIndex : EquipmentIndex.None);
		if (!NetworkServer.active)
		{
			return;
		}
		bool flag = itemCounts.repeatHeal != 0;
		if (flag != (bool)repeatHealComponent)
		{
			if (flag)
			{
				repeatHealComponent = base.gameObject.AddComponent<RepeatHealComponent>();
				repeatHealComponent.healthComponent = this;
			}
			else
			{
				UnityEngine.Object.Destroy(repeatHealComponent);
				repeatHealComponent = null;
			}
		}
	}

	public HealthBarValues GetHealthBarValues()
	{
		float num = 1f - 1f / body.cursePenalty;
		float num2 = (1f - num) / fullCombinedHealth;
		float num3 = body.oneShotProtectionFraction * fullCombinedHealth - missingCombinedHealth;
		HealthBarValues result = default(HealthBarValues);
		result.hasInfusion = (float)itemCounts.infusion > 0f;
		result.hasVoidShields = (float)itemCounts.missileVoid > 0f;
		result.isElite = body.isElite;
		result.isBoss = body.isBoss;
		result.isVoid = (body.bodyFlags & CharacterBody.BodyFlags.Void) != 0;
		result.cullFraction = ((isInFrozenState && (body.bodyFlags & CharacterBody.BodyFlags.ImmuneToExecutes) == 0) ? Mathf.Clamp01(0.3f * fullCombinedHealth * num2) : 0f);
		result.healthFraction = Mathf.Clamp01(health * num2);
		result.shieldFraction = Mathf.Clamp01(shield * num2);
		result.barrierFraction = Mathf.Clamp01(barrier * num2);
		result.magneticFraction = Mathf.Clamp01(magnetiCharge * num2);
		result.curseFraction = num;
		result.ospFraction = num3 * num2;
		result.healthDisplayValue = (int)combinedHealth;
		result.maxHealthDisplayValue = (int)fullHealth;
		return result;
	}

	static HealthComponent()
	{
		lowHealthFraction = 0.25f;
		kCmdCmdHealFull = -290141736;
		NetworkBehaviour.RegisterCommandDelegate(typeof(HealthComponent), kCmdCmdHealFull, InvokeCmdCmdHealFull);
		kCmdCmdRechargeShieldFull = -833942624;
		NetworkBehaviour.RegisterCommandDelegate(typeof(HealthComponent), kCmdCmdRechargeShieldFull, InvokeCmdCmdRechargeShieldFull);
		kCmdCmdAddBarrier = -1976809257;
		NetworkBehaviour.RegisterCommandDelegate(typeof(HealthComponent), kCmdCmdAddBarrier, InvokeCmdCmdAddBarrier);
		kCmdCmdForceShieldRegen = -1029271894;
		NetworkBehaviour.RegisterCommandDelegate(typeof(HealthComponent), kCmdCmdForceShieldRegen, InvokeCmdCmdForceShieldRegen);
		NetworkCRC.RegisterBehaviour("HealthComponent", 0);
	}

	private void UNetVersion()
	{
	}

	protected static void InvokeCmdCmdHealFull(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkServer.active)
		{
			Debug.LogError("Command CmdHealFull called on client.");
		}
		else
		{
			((HealthComponent)obj).CmdHealFull();
		}
	}

	protected static void InvokeCmdCmdRechargeShieldFull(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkServer.active)
		{
			Debug.LogError("Command CmdRechargeShieldFull called on client.");
		}
		else
		{
			((HealthComponent)obj).CmdRechargeShieldFull();
		}
	}

	protected static void InvokeCmdCmdAddBarrier(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkServer.active)
		{
			Debug.LogError("Command CmdAddBarrier called on client.");
		}
		else
		{
			((HealthComponent)obj).CmdAddBarrier(reader.ReadSingle());
		}
	}

	protected static void InvokeCmdCmdForceShieldRegen(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkServer.active)
		{
			Debug.LogError("Command CmdForceShieldRegen called on client.");
		}
		else
		{
			((HealthComponent)obj).CmdForceShieldRegen();
		}
	}

	public void CallCmdHealFull()
	{
		if (!NetworkClient.active)
		{
			Debug.LogError("Command function CmdHealFull called on server.");
			return;
		}
		if (base.isServer)
		{
			CmdHealFull();
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)5);
		networkWriter.WritePackedUInt32((uint)kCmdCmdHealFull);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		SendCommandInternal(networkWriter, 0, "CmdHealFull");
	}

	public void CallCmdRechargeShieldFull()
	{
		if (!NetworkClient.active)
		{
			Debug.LogError("Command function CmdRechargeShieldFull called on server.");
			return;
		}
		if (base.isServer)
		{
			CmdRechargeShieldFull();
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)5);
		networkWriter.WritePackedUInt32((uint)kCmdCmdRechargeShieldFull);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		SendCommandInternal(networkWriter, 0, "CmdRechargeShieldFull");
	}

	public void CallCmdAddBarrier(float value)
	{
		if (!NetworkClient.active)
		{
			Debug.LogError("Command function CmdAddBarrier called on server.");
			return;
		}
		if (base.isServer)
		{
			CmdAddBarrier(value);
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)5);
		networkWriter.WritePackedUInt32((uint)kCmdCmdAddBarrier);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		networkWriter.Write(value);
		SendCommandInternal(networkWriter, 0, "CmdAddBarrier");
	}

	public void CallCmdForceShieldRegen()
	{
		if (!NetworkClient.active)
		{
			Debug.LogError("Command function CmdForceShieldRegen called on server.");
			return;
		}
		if (base.isServer)
		{
			CmdForceShieldRegen();
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)5);
		networkWriter.WritePackedUInt32((uint)kCmdCmdForceShieldRegen);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		SendCommandInternal(networkWriter, 0, "CmdForceShieldRegen");
	}

	public override bool OnSerialize(NetworkWriter writer, bool forceAll)
	{
		if (forceAll)
		{
			writer.Write(health);
			writer.Write(shield);
			writer.Write(barrier);
			writer.Write(magnetiCharge);
			writer.WritePackedUInt32(_killingDamageType);
			return true;
		}
		bool flag = false;
		if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(health);
		}
		if ((base.syncVarDirtyBits & 2u) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(shield);
		}
		if ((base.syncVarDirtyBits & 4u) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(barrier);
		}
		if ((base.syncVarDirtyBits & 8u) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(magnetiCharge);
		}
		if ((base.syncVarDirtyBits & 0x10u) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.WritePackedUInt32(_killingDamageType);
		}
		if (!flag)
		{
			writer.WritePackedUInt32(base.syncVarDirtyBits);
		}
		return flag;
	}

	public override void OnDeserialize(NetworkReader reader, bool initialState)
	{
		if (initialState)
		{
			health = reader.ReadSingle();
			shield = reader.ReadSingle();
			barrier = reader.ReadSingle();
			magnetiCharge = reader.ReadSingle();
			_killingDamageType = reader.ReadPackedUInt32();
			return;
		}
		int num = (int)reader.ReadPackedUInt32();
		if (((uint)num & (true ? 1u : 0u)) != 0)
		{
			health = reader.ReadSingle();
		}
		if (((uint)num & 2u) != 0)
		{
			shield = reader.ReadSingle();
		}
		if (((uint)num & 4u) != 0)
		{
			SetBarrier(reader.ReadSingle());
		}
		if (((uint)num & 8u) != 0)
		{
			magnetiCharge = reader.ReadSingle();
		}
		if (((uint)num & 0x10u) != 0)
		{
			_killingDamageType = reader.ReadPackedUInt32();
		}
	}

	public override void PreStartClient()
	{
	}
}
