r2mods/ilspy_dump/ror2_csproj/RoR2/HealthComponent.cs

2136 lines
65 KiB
C#

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()
{
}
}