using System; using System.Collections.Generic; using System.Linq; using HG; using JetBrains.Annotations; using RoR2.Orbs; using RoR2.Projectile; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; namespace RoR2; public class GlobalEventManager : MonoBehaviour { private static class CommonAssets { public static CharacterMaster wispSoulMasterPrefabMasterComponent; public static GameObject igniteOnKillExplosionEffectPrefab; public static GameObject missilePrefab; public static GameObject explodeOnDeathPrefab; public static GameObject daggerPrefab; public static GameObject bleedOnHitAndExplodeImpactEffect; public static GameObject bleedOnHitAndExplodeBlastEffect; public static GameObject minorConstructOnKillProjectile; public static GameObject knockbackFinEffect; public static GameObject runicMeteorEffect; public static GameObject missileVoidPrefab; public static GameObject eliteEarthHealerMaster; public static PickupDropTable dtSonorousEchoPath; public static GameObject loseCoinsImpactEffectPrefab; public static void Load() { AsyncOperationHandle asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/CharacterMasters/WispSoulMaster"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { wispSoulMasterPrefabMasterComponent = x.Result.GetComponent(); }; asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/Effects/ImpactEffects/IgniteExplosionVFX"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { igniteOnKillExplosionEffectPrefab = x.Result; }; asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/Projectiles/MissileProjectile"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { missilePrefab = x.Result; }; asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/Projectiles/DaggerProjectile"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { daggerPrefab = x.Result; }; asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/Effects/ImpactEffects/BleedOnHitAndExplode_Impact"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { bleedOnHitAndExplodeImpactEffect = x.Result; }; asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/NetworkedObjects/BleedOnHitAndExplodeDelay"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { bleedOnHitAndExplodeBlastEffect = x.Result; }; asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/Projectiles/MissileVoidProjectile"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { missileVoidPrefab = x.Result; }; asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/Effects/ImpactEffects/KnockBackHitEnemiesImpact"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { knockbackFinEffect = x.Result; }; asyncOperationHandle = LegacyResourcesAPI.LoadAsync("Prefabs/Effects/RunicMeteorStrikePredictionEffect"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { runicMeteorEffect = x.Result; }; asyncOperationHandle = Addressables.LoadAssetAsync("RoR2/DLC1/EliteEarth/AffixEarthHealerMaster.prefab"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { eliteEarthHealerMaster = x.Result; }; asyncOperationHandle = Addressables.LoadAssetAsync("RoR2/Base/ExplodeOnDeath/WilloWispDelay.prefab"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { explodeOnDeathPrefab = x.Result; }; asyncOperationHandle = Addressables.LoadAssetAsync("RoR2/DLC1/MinorConstructOnKill/MinorConstructOnKillProjectile.prefab"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { minorConstructOnKillProjectile = x.Result; }; AsyncOperationHandle asyncOperationHandle2 = Addressables.LoadAssetAsync("RoR2/DLC2/Items/ResetChests/dtSonorousEcho.asset"); asyncOperationHandle2.Completed += delegate(AsyncOperationHandle x) { dtSonorousEchoPath = x.Result; }; asyncOperationHandle = Addressables.LoadAssetAsync("RoR2/Base/Common/VFX/CoinImpact.prefab"); asyncOperationHandle.Completed += delegate(AsyncOperationHandle x) { loseCoinsImpactEffectPrefab = x.Result; }; } } public static GlobalEventManager instance; [Obsolete("Transform of the global event manager should not be used! You probably meant something else instead.", true)] private new Transform transform; [Obsolete("GameObject of the global event manager should not be used! You probably meant something else instead.", true)] private new GameObject gameObject; private static readonly string[] standardDeathQuoteTokens = (from i in Enumerable.Range(0, 37) select "PLAYER_DEATH_QUOTE_" + TextSerialization.ToStringInvariant(i)).ToArray(); private static readonly string[] fallDamageDeathQuoteTokens = (from i in Enumerable.Range(0, 5) select "PLAYER_DEATH_QUOTE_FALLDAMAGE_" + TextSerialization.ToStringInvariant(i)).ToArray(); private static readonly SphereSearch igniteOnKillSphereSearch = new SphereSearch(); private static readonly List igniteOnKillHurtBoxBuffer = new List(); public static event Action onCharacterDeathGlobal; public static event Action onTeamLevelUp; public static event Action onCharacterLevelUp; public static event Action OnInteractionsGlobal; public static event Action onClientDamageNotified; public static event Action onServerDamageDealt; public static event Action onServerCharacterExecuted; [InitDuringStartup] private static void Init() { CommonAssets.Load(); } private void OnEnable() { if ((bool)instance) { Debug.LogError("Only one GlobalEventManager can exist at a time."); } else { instance = this; } } private void OnDisable() { if (instance == this) { instance = null; } } public void OnHitEnemy([NotNull] DamageInfo damageInfo, [NotNull] GameObject victim) { ProcessHitEnemy(damageInfo, victim); } private void ProcessHitEnemy([NotNull] DamageInfo damageInfo, [NotNull] GameObject victim) { if (damageInfo.procCoefficient == 0f || damageInfo.rejected || !NetworkServer.active) { return; } if (damageInfo.attacker == null) { HandleDamageWithNoAttacker(damageInfo, victim); } if (!damageInfo.attacker || !(damageInfo.procCoefficient > 0f)) { return; } uint? maxStacksFromAttacker = null; if ((bool)damageInfo?.inflictor) { ProjectileDamage component = damageInfo.inflictor.GetComponent(); if ((bool)component && component.useDotMaxStacksFromAttacker) { maxStacksFromAttacker = component.dotMaxStacksFromAttacker; } } CharacterBody component2 = damageInfo.attacker.GetComponent(); CharacterBody characterBody = (victim ? victim.GetComponent() : null); if ((ulong)(damageInfo.damageType & DamageType.LunarRuin) != 0) { if ((ulong)(damageInfo.damageType & DamageTypeExtended.ApplyBuffPermanently) != 0L) { characterBody.AddTimedBuff(DLC2Content.Buffs.lunarruin, 420f); } else { DotController.InflictDot(characterBody.gameObject, damageInfo.attacker, DotController.DotIndex.LunarRuin, 5f); } } if ((ulong)(damageInfo.damageType & DamageTypeExtended.DisableAllSkills) != 0L) { if ((ulong)(damageInfo.damageType & DamageTypeExtended.ApplyBuffPermanently) != 0L) { Debug.LogFormat("Adding DisableAllSkills"); characterBody.AddTimedBuff(DLC2Content.Buffs.DisableAllSkills, 420f); } else { Debug.LogFormat("Adding DisableAllSkills for 5s"); characterBody.AddTimedBuff(DLC2Content.Buffs.DisableAllSkills, 5f); } } if (!component2) { return; } if ((ulong)(damageInfo.damageType & DamageType.PoisonOnHit) != 0) { DotController.InflictDot(victim, damageInfo.attacker, DotController.DotIndex.Poison, 10f * damageInfo.procCoefficient, 1f, maxStacksFromAttacker); } CharacterMaster master = component2.master; if (!master) { return; } Inventory inventory = master.inventory; TeamComponent component3 = component2.GetComponent(); TeamIndex teamIndex = (component3 ? component3.teamIndex : TeamIndex.Neutral); Vector3 aimOrigin = component2.aimOrigin; if (damageInfo.crit) { instance.OnCrit(component2, damageInfo, master, damageInfo.procCoefficient, damageInfo.procChainMask); } if (!damageInfo.procChainMask.HasProc(ProcType.HealOnHit)) { int itemCount = inventory.GetItemCount(RoR2Content.Items.Seed); if (itemCount > 0) { HealthComponent component4 = component2.GetComponent(); if ((bool)component4) { ProcChainMask procChainMask = damageInfo.procChainMask; procChainMask.AddProc(ProcType.HealOnHit); component4.Heal((float)itemCount * damageInfo.procCoefficient, procChainMask); } } } if (!damageInfo.procChainMask.HasProc(ProcType.BleedOnHit)) { bool flag = (ulong)(damageInfo.damageType & DamageType.BleedOnHit) != 0 || (inventory.GetItemCount(RoR2Content.Items.BleedOnHitAndExplode) > 0 && damageInfo.crit); if ((component2.bleedChance > 0f || flag) && (flag || Util.CheckRoll(damageInfo.procCoefficient * component2.bleedChance, master))) { ProcChainMask procChainMask2 = damageInfo.procChainMask; procChainMask2.AddProc(ProcType.BleedOnHit); DotController.InflictDot(victim, damageInfo.attacker, DotController.DotIndex.Bleed, 3f * damageInfo.procCoefficient, 1f, maxStacksFromAttacker); } } if (!damageInfo.procChainMask.HasProc(ProcType.FractureOnHit)) { int itemCount2 = inventory.GetItemCount(DLC1Content.Items.BleedOnHitVoid); itemCount2 += (component2.HasBuff(DLC1Content.Buffs.EliteVoid) ? 10 : 0); if (itemCount2 > 0 && Util.CheckRoll(damageInfo.procCoefficient * (float)itemCount2 * 10f, master)) { ProcChainMask procChainMask3 = damageInfo.procChainMask; procChainMask3.AddProc(ProcType.FractureOnHit); DotController.DotDef dotDef = DotController.GetDotDef(DotController.DotIndex.Fracture); DotController.InflictDot(victim, damageInfo.attacker, DotController.DotIndex.Fracture, dotDef.interval, 1f, maxStacksFromAttacker); } } bool flag2 = (ulong)(damageInfo.damageType & DamageType.BlightOnHit) != 0; if (flag2 && flag2) { _ = damageInfo.procChainMask; DotController.InflictDot(victim, damageInfo.attacker, DotController.DotIndex.Blight, 5f * damageInfo.procCoefficient, 1f, maxStacksFromAttacker); } if ((ulong)(damageInfo.damageType & DamageType.WeakOnHit) != 0) { characterBody.AddTimedBuff(RoR2Content.Buffs.Weak, 6f * damageInfo.procCoefficient); } if ((ulong)(damageInfo.damageType & DamageType.IgniteOnHit) != 0 || component2.HasBuff(RoR2Content.Buffs.AffixRed)) { float num = 0.5f; InflictDotInfo inflictDotInfo = default(InflictDotInfo); inflictDotInfo.attackerObject = damageInfo.attacker; inflictDotInfo.victimObject = victim; inflictDotInfo.totalDamage = damageInfo.damage * num; inflictDotInfo.damageMultiplier = 1f; inflictDotInfo.dotIndex = DotController.DotIndex.Burn; inflictDotInfo.maxStacksFromAttacker = maxStacksFromAttacker; InflictDotInfo dotInfo = inflictDotInfo; StrengthenBurnUtils.CheckDotForUpgrade(inventory, ref dotInfo); DotController.InflictDot(ref dotInfo); } int num2 = (component2.HasBuff(RoR2Content.Buffs.AffixWhite) ? 1 : 0); num2 += (component2.HasBuff(RoR2Content.Buffs.AffixHaunted) ? 2 : 0); if (num2 > 0 && (bool)characterBody) { EffectManager.SimpleImpactEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/AffixWhiteImpactEffect"), damageInfo.position, Vector3.up, transmit: true); characterBody.AddTimedBuff(RoR2Content.Buffs.Slow80, 1.5f * damageInfo.procCoefficient * (float)num2); } int itemCount3 = master.inventory.GetItemCount(RoR2Content.Items.SlowOnHit); if (itemCount3 > 0 && (bool)characterBody) { characterBody.AddTimedBuff(RoR2Content.Buffs.Slow60, 2f * (float)itemCount3); } int itemCount4 = master.inventory.GetItemCount(DLC1Content.Items.SlowOnHitVoid); if (itemCount4 > 0 && (bool)characterBody && Util.CheckRoll(Util.ConvertAmplificationPercentageIntoReductionPercentage(5f * (float)itemCount4 * damageInfo.procCoefficient), master)) { characterBody.AddTimedBuff(RoR2Content.Buffs.Nullified, 1f * (float)itemCount4); } if ((component2.HasBuff(RoR2Content.Buffs.AffixPoison) ? 1 : 0) > 0 && (bool)characterBody) { characterBody.AddTimedBuff(RoR2Content.Buffs.HealingDisabled, 8f * damageInfo.procCoefficient); } int itemCount5 = inventory.GetItemCount(RoR2Content.Items.GoldOnHit); if (itemCount5 > 0 && Util.CheckRoll(30f * damageInfo.procCoefficient, master)) { GoldOrb goldOrb = new GoldOrb(); goldOrb.origin = damageInfo.position; goldOrb.target = component2.mainHurtBox; goldOrb.goldAmount = (uint)((float)itemCount5 * 2f * Run.instance.difficultyCoefficient); OrbManager.instance.AddOrb(goldOrb); EffectManager.SimpleImpactEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/CoinImpact"), damageInfo.position, Vector3.up, transmit: true); } if (!damageInfo.procChainMask.HasProc(ProcType.Missile)) { int itemCount6 = inventory.GetItemCount(RoR2Content.Items.Missile); if (itemCount6 > 0) { if (Util.CheckRoll(10f * damageInfo.procCoefficient, master)) { float damageCoefficient = 3f * (float)itemCount6; float missileDamage = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient); MissileUtils.FireMissile(component2.corePosition, component2, damageInfo.procChainMask, victim, missileDamage, damageInfo.crit, CommonAssets.missilePrefab, DamageColorIndex.Item, addMissileProc: true); } } else { itemCount6 = inventory.GetItemCount(DLC1Content.Items.MissileVoid); if (itemCount6 > 0 && component2.healthComponent.shield > 0f) { int valueOrDefault = (component2?.inventory?.GetItemCount(DLC1Content.Items.MoreMissile)).GetValueOrDefault(); float num3 = Mathf.Max(1f, 1f + 0.5f * (float)(valueOrDefault - 1)); float damageCoefficient2 = 0.4f * (float)itemCount6; float damageValue = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient2) * num3; int num4 = ((valueOrDefault <= 0) ? 1 : 3); for (int i = 0; i < num4; i++) { MissileVoidOrb missileVoidOrb = new MissileVoidOrb(); missileVoidOrb.origin = aimOrigin; missileVoidOrb.damageValue = damageValue; missileVoidOrb.isCrit = damageInfo.crit; missileVoidOrb.teamIndex = teamIndex; missileVoidOrb.attacker = damageInfo.attacker; missileVoidOrb.procChainMask = damageInfo.procChainMask; missileVoidOrb.procChainMask.AddProc(ProcType.Missile); missileVoidOrb.procCoefficient = 0.2f; missileVoidOrb.damageColorIndex = DamageColorIndex.Void; HurtBox mainHurtBox = characterBody.mainHurtBox; if ((bool)mainHurtBox) { missileVoidOrb.target = mainHurtBox; OrbManager.instance.AddOrb(missileVoidOrb); } } } } } if (component2.HasBuff(JunkContent.Buffs.LoaderPylonPowered) && !damageInfo.procChainMask.HasProc(ProcType.LoaderLightning)) { float damageCoefficient3 = 0.3f; float damageValue2 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient3); LightningOrb lightningOrb = new LightningOrb(); lightningOrb.origin = damageInfo.position; lightningOrb.damageValue = damageValue2; lightningOrb.isCrit = damageInfo.crit; lightningOrb.bouncesRemaining = 3; lightningOrb.teamIndex = teamIndex; lightningOrb.attacker = damageInfo.attacker; lightningOrb.bouncedObjects = new List { victim.GetComponent() }; lightningOrb.procChainMask = damageInfo.procChainMask; lightningOrb.procChainMask.AddProc(ProcType.LoaderLightning); lightningOrb.procCoefficient = 0f; lightningOrb.lightningType = LightningOrb.LightningType.Loader; lightningOrb.damageColorIndex = DamageColorIndex.Item; lightningOrb.range = 20f; HurtBox hurtBox = lightningOrb.PickNextTarget(damageInfo.position); if ((bool)hurtBox) { lightningOrb.target = hurtBox; OrbManager.instance.AddOrb(lightningOrb); } } int itemCount7 = inventory.GetItemCount(RoR2Content.Items.ChainLightning); float num5 = 25f; if (itemCount7 > 0 && !damageInfo.procChainMask.HasProc(ProcType.ChainLightning) && Util.CheckRoll(num5 * damageInfo.procCoefficient, master)) { float damageCoefficient4 = 0.8f; float damageValue3 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient4); LightningOrb lightningOrb2 = new LightningOrb(); lightningOrb2.origin = damageInfo.position; lightningOrb2.damageValue = damageValue3; lightningOrb2.isCrit = damageInfo.crit; lightningOrb2.bouncesRemaining = 2 * itemCount7; lightningOrb2.teamIndex = teamIndex; lightningOrb2.attacker = damageInfo.attacker; lightningOrb2.bouncedObjects = new List { victim.GetComponent() }; lightningOrb2.procChainMask = damageInfo.procChainMask; lightningOrb2.procChainMask.AddProc(ProcType.ChainLightning); lightningOrb2.procCoefficient = 0.2f; lightningOrb2.lightningType = LightningOrb.LightningType.Ukulele; lightningOrb2.damageColorIndex = DamageColorIndex.Item; lightningOrb2.range += 2 * itemCount7; HurtBox hurtBox2 = lightningOrb2.PickNextTarget(damageInfo.position); if ((bool)hurtBox2) { lightningOrb2.target = hurtBox2; OrbManager.instance.AddOrb(lightningOrb2); } } int itemCount8 = inventory.GetItemCount(DLC1Content.Items.ChainLightningVoid); float num6 = 25f; if (itemCount8 > 0 && !damageInfo.procChainMask.HasProc(ProcType.ChainLightning) && Util.CheckRoll(num6 * damageInfo.procCoefficient, master)) { float damageCoefficient5 = 0.6f; float damageValue4 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient5); VoidLightningOrb voidLightningOrb = new VoidLightningOrb(); voidLightningOrb.origin = damageInfo.position; voidLightningOrb.damageValue = damageValue4; voidLightningOrb.isCrit = damageInfo.crit; voidLightningOrb.totalStrikes = 3 * itemCount8; voidLightningOrb.teamIndex = teamIndex; voidLightningOrb.attacker = damageInfo.attacker; voidLightningOrb.procChainMask = damageInfo.procChainMask; voidLightningOrb.procChainMask.AddProc(ProcType.ChainLightning); voidLightningOrb.procCoefficient = 0.2f; voidLightningOrb.damageColorIndex = DamageColorIndex.Void; voidLightningOrb.secondsPerStrike = 0.1f; HurtBox mainHurtBox2 = characterBody.mainHurtBox; if ((bool)mainHurtBox2) { voidLightningOrb.target = mainHurtBox2; OrbManager.instance.AddOrb(voidLightningOrb); } } int itemCount9 = inventory.GetItemCount(RoR2Content.Items.BounceNearby); if (itemCount9 > 0) { float num7 = (1f - 100f / (100f + 20f * (float)itemCount9)) * 100f; if (!damageInfo.procChainMask.HasProc(ProcType.BounceNearby) && Util.CheckRoll(num7 * damageInfo.procCoefficient, master)) { List list = CollectionPool>.RentCollection(); int maxTargets = 5 + itemCount9 * 5; BullseyeSearch search = new BullseyeSearch(); List list2 = CollectionPool>.RentCollection(); if ((bool)component2 && (bool)component2.healthComponent) { list2.Add(component2.healthComponent); } if ((bool)characterBody && (bool)characterBody.healthComponent) { list2.Add(characterBody.healthComponent); } BounceOrb.SearchForTargets(search, teamIndex, damageInfo.position, 30f, maxTargets, list, list2); CollectionPool>.ReturnCollection(list2); List bouncedObjects = new List { victim.GetComponent() }; float damageCoefficient6 = 1f; float damageValue5 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient6); int j = 0; for (int count = list.Count; j < count; j++) { HurtBox hurtBox3 = list[j]; if ((bool)hurtBox3) { BounceOrb bounceOrb = new BounceOrb(); bounceOrb.origin = damageInfo.position; bounceOrb.damageValue = damageValue5; bounceOrb.isCrit = damageInfo.crit; bounceOrb.teamIndex = teamIndex; bounceOrb.attacker = damageInfo.attacker; bounceOrb.procChainMask = damageInfo.procChainMask; bounceOrb.procChainMask.AddProc(ProcType.BounceNearby); bounceOrb.procCoefficient = 0.33f; bounceOrb.damageColorIndex = DamageColorIndex.Item; bounceOrb.bouncedObjects = bouncedObjects; bounceOrb.target = hurtBox3; OrbManager.instance.AddOrb(bounceOrb); } } CollectionPool>.ReturnCollection(list); } } int itemCount10 = inventory.GetItemCount(RoR2Content.Items.StickyBomb); if (itemCount10 > 0 && Util.CheckRoll(5f * (float)itemCount10 * damageInfo.procCoefficient, master) && (bool)characterBody) { bool alive = characterBody.healthComponent.alive; float num8 = 5f; Vector3 position = damageInfo.position; Vector3 forward = characterBody.corePosition - position; float magnitude = forward.magnitude; Quaternion rotation = ((magnitude != 0f) ? Util.QuaternionSafeLookRotation(forward) : UnityEngine.Random.rotationUniform); float damageCoefficient7 = 1.8f; float damage = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient7); ProjectileManager.instance.FireProjectile(LegacyResourcesAPI.Load("Prefabs/Projectiles/StickyBomb"), position, rotation, damageInfo.attacker, damage, 100f, damageInfo.crit, DamageColorIndex.Item, null, alive ? (magnitude * num8) : (-1f)); } if (!damageInfo.procChainMask.HasProc(ProcType.Rings) && damageInfo.damage / component2.damage >= 4f) { if (component2.HasBuff(RoR2Content.Buffs.ElementalRingsReady)) { int itemCount11 = inventory.GetItemCount(RoR2Content.Items.IceRing); int itemCount12 = inventory.GetItemCount(RoR2Content.Items.FireRing); component2.RemoveBuff(RoR2Content.Buffs.ElementalRingsReady); for (int k = 1; (float)k <= 10f; k++) { component2.AddTimedBuff(RoR2Content.Buffs.ElementalRingsCooldown, k); } ProcChainMask procChainMask4 = damageInfo.procChainMask; procChainMask4.AddProc(ProcType.Rings); Vector3 position2 = damageInfo.position; if (itemCount11 > 0) { float damageCoefficient8 = 2.5f * (float)itemCount11; float damage2 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient8); DamageInfo damageInfo2 = new DamageInfo { damage = damage2, damageColorIndex = DamageColorIndex.Item, damageType = DamageType.Generic, attacker = damageInfo.attacker, crit = damageInfo.crit, force = Vector3.zero, inflictor = null, position = position2, procChainMask = procChainMask4, procCoefficient = 1f }; EffectManager.SimpleImpactEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/IceRingExplosion"), position2, Vector3.up, transmit: true); characterBody.AddTimedBuff(RoR2Content.Buffs.Slow80, 3f * (float)itemCount11); characterBody.healthComponent.TakeDamage(damageInfo2); } if (itemCount12 > 0) { GameObject gameObject = LegacyResourcesAPI.Load("Prefabs/Projectiles/FireTornado"); float resetInterval = gameObject.GetComponent().resetInterval; float lifetime = gameObject.GetComponent().lifetime; float damageCoefficient9 = 3f * (float)itemCount12; float damage3 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient9) / lifetime * resetInterval; float speedOverride = 0f; Quaternion rotation2 = Quaternion.identity; Vector3 vector = position2 - aimOrigin; vector.y = 0f; if (vector != Vector3.zero) { speedOverride = -1f; rotation2 = Util.QuaternionSafeLookRotation(vector, Vector3.up); } ProjectileManager.instance.FireProjectile(new FireProjectileInfo { damage = damage3, crit = damageInfo.crit, damageColorIndex = DamageColorIndex.Item, position = position2, procChainMask = procChainMask4, force = 0f, owner = damageInfo.attacker, projectilePrefab = gameObject, rotation = rotation2, speedOverride = speedOverride, target = null }); } } else if (component2.HasBuff(DLC1Content.Buffs.ElementalRingVoidReady)) { int itemCount13 = inventory.GetItemCount(DLC1Content.Items.ElementalRingVoid); component2.RemoveBuff(DLC1Content.Buffs.ElementalRingVoidReady); for (int l = 1; (float)l <= 20f; l++) { component2.AddTimedBuff(DLC1Content.Buffs.ElementalRingVoidCooldown, l); } ProcChainMask procChainMask5 = damageInfo.procChainMask; procChainMask5.AddProc(ProcType.Rings); if (itemCount13 > 0) { GameObject projectilePrefab = LegacyResourcesAPI.Load("Prefabs/Projectiles/ElementalRingVoidBlackHole"); float damageCoefficient10 = 1f * (float)itemCount13; float damage4 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient10); ProjectileManager.instance.FireProjectile(new FireProjectileInfo { damage = damage4, crit = damageInfo.crit, damageColorIndex = DamageColorIndex.Void, position = damageInfo.position, procChainMask = procChainMask5, force = 6000f, owner = damageInfo.attacker, projectilePrefab = projectilePrefab, rotation = Quaternion.identity, target = null }); } } } int itemCount14 = master.inventory.GetItemCount(RoR2Content.Items.DeathMark); int num9 = 0; if (itemCount14 >= 1 && !characterBody.HasBuff(RoR2Content.Buffs.DeathMark)) { BuffIndex[] debuffBuffIndices = BuffCatalog.debuffBuffIndices; foreach (BuffIndex buffType in debuffBuffIndices) { if (characterBody.HasBuff(buffType)) { num9++; } } DotController dotController = DotController.FindDotController(victim.gameObject); if ((bool)dotController) { for (DotController.DotIndex dotIndex = DotController.DotIndex.Bleed; dotIndex < DotController.DotIndex.Count; dotIndex++) { if (dotController.HasDotActive(dotIndex)) { num9++; } } } if (num9 >= 4) { characterBody.AddTimedBuff(RoR2Content.Buffs.DeathMark, 7f * (float)itemCount14); } } if (damageInfo != null && damageInfo.inflictor != null && damageInfo.inflictor.GetComponent() != null && !damageInfo.procChainMask.HasProc(ProcType.BleedOnHit)) { int num10 = 0; if (inventory.GetEquipmentIndex() == RoR2Content.Equipment.Saw.equipmentIndex) { num10 = 1; } bool flag3 = (ulong)(damageInfo.damageType & DamageType.BleedOnHit) != 0; if ((num10 > 0 || flag3) && (flag3 || Util.CheckRoll(100f, master))) { ProcChainMask procChainMask6 = damageInfo.procChainMask; procChainMask6.AddProc(ProcType.BleedOnHit); DotController.InflictDot(victim, damageInfo.attacker, DotController.DotIndex.Bleed, 4f * damageInfo.procCoefficient, 1f, maxStacksFromAttacker); } } if (damageInfo.crit && (ulong)(damageInfo.damageType & DamageType.SuperBleedOnCrit) != 0L) { DotController.InflictDot(victim, damageInfo.attacker, DotController.DotIndex.SuperBleed, 15f * damageInfo.procCoefficient, 1f, maxStacksFromAttacker); } if (component2.HasBuff(RoR2Content.Buffs.LifeSteal)) { float amount = damageInfo.damage * 0.2f; component2.healthComponent.Heal(amount, damageInfo.procChainMask); } int itemCount15 = inventory.GetItemCount(RoR2Content.Items.FireballsOnHit); if (itemCount15 > 0 && !damageInfo.procChainMask.HasProc(ProcType.Meatball)) { InputBankTest component5 = component2.GetComponent(); Vector3 vector2 = (characterBody.characterMotor ? (victim.transform.position + Vector3.up * (characterBody.characterMotor.capsuleHeight * 0.5f + 2f)) : (victim.transform.position + Vector3.up * 2f)); Vector3 vector3 = (component5 ? component5.aimDirection : victim.transform.forward); vector3 = Vector3.up; float num11 = 20f; if (Util.CheckRoll(10f * damageInfo.procCoefficient, master)) { EffectData effectData = new EffectData { scale = 1f, origin = vector2 }; EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/MuzzleFlashes/MuzzleflashFireMeatBall"), effectData, transmit: true); int num12 = 3; float damageCoefficient11 = 3f * (float)itemCount15; float damage5 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, damageCoefficient11); float maxInclusive = 30f; ProcChainMask procChainMask7 = damageInfo.procChainMask; procChainMask7.AddProc(ProcType.Meatball); float speedOverride2 = UnityEngine.Random.Range(15f, maxInclusive); float num13 = 360 / num12; _ = num13 / 360f; float num14 = 1f; float num15 = num13; for (int n = 0; n < num12; n++) { float num16 = (float)n * MathF.PI * 2f / (float)num12; FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); fireProjectileInfo.projectilePrefab = LegacyResourcesAPI.Load("Prefabs/Projectiles/FireMeatBall"); fireProjectileInfo.position = vector2 + new Vector3(num14 * Mathf.Sin(num16), 0f, num14 * Mathf.Cos(num16)); fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(vector3); fireProjectileInfo.procChainMask = procChainMask7; fireProjectileInfo.target = victim; fireProjectileInfo.owner = component2.gameObject; fireProjectileInfo.damage = damage5; fireProjectileInfo.crit = damageInfo.crit; fireProjectileInfo.force = 200f; fireProjectileInfo.damageColorIndex = DamageColorIndex.Item; fireProjectileInfo.speedOverride = speedOverride2; fireProjectileInfo.useSpeedOverride = true; FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; num15 += num13; ProjectileManager.instance.FireProjectile(fireProjectileInfo2); vector3.x += Mathf.Sin(num16 + UnityEngine.Random.Range(0f - num11, num11)); vector3.z += Mathf.Cos(num16 + UnityEngine.Random.Range(0f - num11, num11)); } } } int itemCount16 = inventory.GetItemCount(RoR2Content.Items.LightningStrikeOnHit); if (itemCount16 > 0 && !damageInfo.procChainMask.HasProc(ProcType.LightningStrikeOnHit) && Util.CheckRoll(10f * damageInfo.procCoefficient, master)) { float damageValue6 = Util.OnHitProcDamage(damageInfo.damage, component2.damage, 5f * (float)itemCount16); ProcChainMask procChainMask8 = damageInfo.procChainMask; procChainMask8.AddProc(ProcType.LightningStrikeOnHit); HurtBox target = characterBody.mainHurtBox; if ((bool)characterBody.hurtBoxGroup) { target = characterBody.hurtBoxGroup.hurtBoxes[UnityEngine.Random.Range(0, characterBody.hurtBoxGroup.hurtBoxes.Length)]; } OrbManager.instance.AddOrb(new SimpleLightningStrikeOrb { attacker = component2.gameObject, damageColorIndex = DamageColorIndex.Item, damageValue = damageValue6, isCrit = Util.CheckRoll(component2.crit, master), procChainMask = procChainMask8, procCoefficient = 1f, target = target }); } if ((ulong)(damageInfo.damageType & DamageType.LunarSecondaryRootOnHit) != 0L && (bool)characterBody) { int itemCount17 = master.inventory.GetItemCount(RoR2Content.Items.LunarSecondaryReplacement); characterBody.AddTimedBuff(RoR2Content.Buffs.LunarSecondaryRoot, 3f * (float)itemCount17); } if ((ulong)(damageInfo.damageType & DamageType.FruitOnHit) != 0L && (bool)characterBody) { characterBody.AddTimedBuff(RoR2Content.Buffs.Fruiting, 10f); } if (inventory.GetItemCount(DLC1Content.Items.DroneWeaponsBoost) > 0) { DroneWeaponsBoostBehavior component6 = component2.GetComponent(); if ((bool)component6) { component6.OnEnemyHit(damageInfo, characterBody); } } if (victim.tag != "Player" && inventory.GetItemCount(DLC2Content.Items.IncreaseDamageOnMultiKill) > 0) { component2.AddIncreasedDamageMultiKillTime(); } if (component2.luminousShotReady) { DamageInfo damageInfo3 = new DamageInfo { damage = component2.luminousShotDamage, damageColorIndex = DamageColorIndex.Luminous, damageType = DamageType.Generic, attacker = component2.gameObject, position = characterBody.transform.position, crit = damageInfo.crit, force = Vector3.zero, inflictor = null, procCoefficient = 1f }; characterBody.healthComponent.TakeDamage(damageInfo3); EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/IncreasePrimaryDamageImpact"), new EffectData { origin = characterBody.transform.position }, transmit: true); component2.IncreasePrimaryDamageReset(); Util.PlaySound("Play_item_proc_increasePrimaryDamage", characterBody.gameObject); } if (component2.HasBuff(DLC2Content.Buffs.CookingRolling)) { characterBody.AddBuff(DLC2Content.Buffs.CookingRolled); } else if (component2.HasBuff(DLC2Content.Buffs.CookingSearing)) { characterBody.AddBuff(DLC2Content.Buffs.CookingRoasted); } if (characterBody.HasBuff(DLC2Content.Buffs.CookingOiled) && component2.HasBuff(DLC2Content.Buffs.CookingSearing)) { characterBody.AddBuff(DLC2Content.Buffs.CookingFlambe); characterBody.RemoveBuff(DLC2Content.Buffs.CookingOiled); } if (characterBody.HasBuff(DLC2Content.Buffs.CookingFlambe) && (DamageTypeExtended)damageInfo.damageType == DamageTypeExtended.ChefSearDamage) { float num17 = 0.75f; InflictDotInfo inflictDotInfo = default(InflictDotInfo); inflictDotInfo.attackerObject = damageInfo.attacker; inflictDotInfo.victimObject = victim; inflictDotInfo.totalDamage = component2.damage * num17; inflictDotInfo.damageMultiplier = 1f; inflictDotInfo.dotIndex = DotController.DotIndex.StrongerBurn; inflictDotInfo.maxStacksFromAttacker = maxStacksFromAttacker; InflictDotInfo dotInfo2 = inflictDotInfo; StrengthenBurnUtils.CheckDotForUpgrade(inventory, ref dotInfo2); for (int num18 = 0; num18 < 3; num18++) { DotController.InflictDot(ref dotInfo2); } } int itemCount18 = inventory.GetItemCount(DLC2Content.Items.MeteorAttackOnHighDamage); if (itemCount18 > 0 && !damageInfo.procChainMask.HasProc(ProcType.MeteorAttackOnHighDamage)) { float num19 = 0f; float num20 = (int)(damageInfo.damage / component2.damage); num19 = 5f + 1f * num20 * (float)itemCount18; if (num19 > 50f) { num19 = 50f; } if (Util.CheckRoll(num19 * damageInfo.procCoefficient, master)) { ProcChainMask procChainMask9 = damageInfo.procChainMask; procChainMask9.AddProc(ProcType.MeteorAttackOnHighDamage); float num21 = 20f + 0.5f * (float)itemCount18 * num20; if (num21 > 75f) { num21 = 75f; } num21 *= component2.damage; Vector3 vector4 = damageInfo.position; float num22 = 10f; float blastForce = 5000f; Vector3 origin = vector4 + Vector3.up * 6f; Vector3 onUnitSphere = UnityEngine.Random.onUnitSphere; onUnitSphere.y = -1f; if (Physics.Raycast(origin, onUnitSphere, out var hitInfo, 12f, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) { vector4 = hitInfo.point; } else if (Physics.Raycast(vector4, Vector3.down, out hitInfo, float.PositiveInfinity, LayerIndex.world.mask, QueryTriggerInteraction.Ignore)) { vector4 = hitInfo.point; } if (!component2.runicLensMeteorReady) { Util.PlaySound("Play_item_proc_meteorAttackOnHighDamage", component2.gameObject); EffectManager.SpawnEffect(CommonAssets.runicMeteorEffect, new EffectData { origin = vector4, scale = num22 }, transmit: true); new EffectData().origin = vector4; component2.runicLensUpdateVariables(num21, vector4, damageInfo, blastForce, num22); } } } int itemCount19 = inventory.GetItemCount(DLC2Content.Items.KnockBackHitEnemies); if (itemCount19 > 0 && !characterBody.isBoss) { CharacterMotor component7 = victim.GetComponent(); victim.GetComponent(); if ((bool)component7 && component7.isGrounded && !characterBody.isChampion && (characterBody.bodyFlags & CharacterBody.BodyFlags.IgnoreFallDamage) == 0 && !characterBody.HasBuff(DLC2Content.Buffs.KnockUpHitEnemies) && Util.CheckRoll(Util.ConvertAmplificationPercentageIntoReductionPercentage(7.5f * (float)itemCount19 * damageInfo.procCoefficient))) { Ray aimRay = component2.inputBank.GetAimRay(); characterBody.AddTimedBuff(DLC2Content.Buffs.KnockUpHitEnemies, 5f); float scale = 1f; switch (characterBody.hullClassification) { case HullClassification.Human: scale = 1f; break; case HullClassification.Golem: scale = 5f; break; case HullClassification.BeetleQueen: scale = 10f; break; } EffectManager.SpawnEffect(CommonAssets.knockbackFinEffect, new EffectData { origin = characterBody.gameObject.transform.position, scale = scale }, transmit: true); if (!characterBody.mainHurtBox) { _ = characterBody.transform; } else { _ = characterBody.mainHurtBox.transform; } Vector3 vector5 = new Vector3(0f, 1f, 0f); float num23 = component7.mass * 20f; float num24 = num23 + num23 / 10f * (float)(itemCount19 - 1); component7.ApplyForce(num24 * vector5); component7.ApplyForce(num24 / 2f * aimRay.direction); Util.PlaySound("Play_item_proc_knockBackHitEnemies", component2.gameObject); } } int itemCount20 = inventory.GetItemCount(DLC2Content.Items.StunAndPierce); if (itemCount20 > 0 && !damageInfo.procChainMask.HasProc(ProcType.StunAndPierceDamage) && Util.CheckRoll(15f * damageInfo.procCoefficient, master)) { float damage6 = component2.damage * 0.3f * (float)itemCount20; ProcChainMask procChainMask10 = damageInfo.procChainMask; procChainMask10.AddProc(ProcType.StunAndPierceDamage); Quaternion rotation3 = Quaternion.LookRotation(new Ray(component2.inputBank.aimOrigin, component2.inputBank.aimDirection).direction); GameObject projectilePrefab2 = LegacyResourcesAPI.Load("Prefabs/Projectiles/StunAndPierceBoomerang"); FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); fireProjectileInfo.projectilePrefab = projectilePrefab2; fireProjectileInfo.crit = component2.RollCrit(); fireProjectileInfo.damage = damage6; fireProjectileInfo.damageColorIndex = DamageColorIndex.Item; fireProjectileInfo.force = 0f; fireProjectileInfo.owner = component2.gameObject; fireProjectileInfo.position = aimOrigin; fireProjectileInfo.rotation = rotation3; FireProjectileInfo fireProjectileInfo3 = fireProjectileInfo; fireProjectileInfo3.procChainMask = procChainMask10; ProjectileManager.instance.FireProjectile(fireProjectileInfo3); } if (characterBody.HasBuff(DLC2Content.Buffs.EliteBeadCorruption) && !component2.HasBuff(DLC2Content.Buffs.EliteBead) && !damageInfo.procChainMask.HasProc(ProcType.Thorns)) { float damageValue7 = component2.maxHealth * 0.025f; component2.RollCrit(); _ = characterBody.teamComponent.teamIndex; LightningOrb lightningOrb3 = new LightningOrb(); lightningOrb3.attacker = characterBody.gameObject; lightningOrb3.bouncedObjects = null; lightningOrb3.bouncesRemaining = 0; lightningOrb3.damageCoefficientPerBounce = 1f; lightningOrb3.damageColorIndex = DamageColorIndex.WeakPoint; lightningOrb3.damageValue = damageValue7; lightningOrb3.isCrit = false; lightningOrb3.lightningType = LightningOrb.LightningType.BeadDamage; lightningOrb3.origin = characterBody.transform.position; lightningOrb3.procChainMask = default(ProcChainMask); lightningOrb3.procChainMask.AddProc(ProcType.Thorns); lightningOrb3.procCoefficient = 0.3f; lightningOrb3.range = 0f; lightningOrb3.target = component2.mainHurtBox; OrbManager.instance.AddOrb(lightningOrb3); } if (component2.HasBuff(DLC2Content.Buffs.EliteAurelionite)) { CharacterMaster master2 = component2.master; int baseCost = 2; int difficultyScaledCost = Run.instance.GetDifficultyScaledCost(baseCost); uint money = master2.money; master2.money = (uint)Mathf.Max(0f, (float)master2.money - (float)difficultyScaledCost); if (money - master2.money != 0) { GoldOrb goldOrb2 = new GoldOrb(); goldOrb2.origin = damageInfo.position; goldOrb2.target = (component2 ? component2.mainHurtBox : characterBody.mainHurtBox); goldOrb2.goldAmount = (uint)difficultyScaledCost + (uint)((float)difficultyScaledCost * 0.2f); OrbManager.instance.AddOrb(goldOrb2); EffectManager.SimpleImpactEffect(CommonAssets.loseCoinsImpactEffectPrefab, damageInfo.position, Vector3.up, transmit: true); } } } private void HandleDamageWithNoAttacker([NotNull] DamageInfo damageInfo, [NotNull] GameObject victim) { CharacterBody characterBody = (victim ? victim.GetComponent() : null); if (characterBody == null) { return; } if ((ulong)(damageInfo.damageType & DamageType.LunarRuin) != 0) { if ((ulong)(damageInfo.damageType & DamageTypeExtended.ApplyBuffPermanently) != 0L) { characterBody.AddTimedBuff(DLC2Content.Buffs.lunarruin, 420f); } else { DotController.InflictDot(characterBody.gameObject, damageInfo.attacker, DotController.DotIndex.LunarRuin, 5f); } } if ((ulong)(damageInfo.damageType & DamageTypeExtended.DisableAllSkills) != 0L) { if ((ulong)(damageInfo.damageType & DamageTypeExtended.ApplyBuffPermanently) != 0L) { Debug.LogFormat("Adding DisableAllSkills"); characterBody.AddTimedBuff(DLC2Content.Buffs.DisableAllSkills, 420f); } else { Debug.LogFormat("Adding DisableAllSkills for 5s"); characterBody.AddTimedBuff(DLC2Content.Buffs.DisableAllSkills, 5f); } } } public void OnCharacterHitGroundServer(CharacterBody characterBody, CharacterMotor.HitGroundInfo hitGroundInfo) { bool flag = RunArtifactManager.instance.IsArtifactEnabled(RoR2Content.Artifacts.weakAssKneesArtifactDef); float num = Mathf.Abs(hitGroundInfo.velocity.y); Inventory inventory = characterBody.inventory; _ = characterBody.master; CharacterMotor characterMotor = characterBody.characterMotor; bool tookFallDamage = false; if ((((bool)inventory && inventory.GetItemCount(RoR2Content.Items.FallBoots) != 0) ? 1 : 0) <= (false ? 1 : 0) && (characterBody.bodyFlags & CharacterBody.BodyFlags.IgnoreFallDamage) == 0) { float num2 = Mathf.Max(num - (characterBody.jumpPower + 20f), 0f); if (num2 > 0f) { HealthComponent component = characterBody.GetComponent(); if ((bool)component) { tookFallDamage = true; float num3 = num2 / 60f; DamageInfo damageInfo = new DamageInfo { attacker = null, inflictor = null, crit = false, damage = num3 * characterBody.maxHealth, damageType = (DamageType.NonLethal | DamageType.FallDamage), force = Vector3.zero, position = characterBody.footPosition, procCoefficient = 0f }; if (flag || (characterBody.teamComponent.teamIndex == TeamIndex.Player && Run.instance.selectedDifficulty >= DifficultyIndex.Eclipse3)) { damageInfo.damage *= 2f; damageInfo.damageType &= (DamageTypeCombo)(~DamageType.NonLethal); damageInfo.damageType |= (DamageTypeCombo)DamageType.BypassOneShotProtection; } component.TakeDamage(damageInfo); } } } OnCharacterHitGroundSFX(characterBody, hitGroundInfo, tookFallDamage); characterMotor.CallRpcOnHitGroundSFX(hitGroundInfo, tookFallDamage); } public void OnCharacterHitGroundSFX(CharacterBody characterBody, CharacterMotor.HitGroundInfo hitGroundInfo, bool tookFallDamage) { CharacterMotor characterMotor = characterBody.characterMotor; if (!characterMotor || (!hitGroundInfo.isValidForEffect && !(Run.FixedTimeStamp.now - characterMotor.lastGroundedTime > 0.2f))) { return; } Vector3 footPosition = characterBody.footPosition; float radius = characterBody.radius; if (!Physics.Raycast(new Ray(footPosition + Vector3.up * 1.5f, Vector3.down), out var hitInfo, 4f, (int)LayerIndex.world.mask | (int)LayerIndex.water.mask, QueryTriggerInteraction.Collide)) { return; } SurfaceDef objectSurfaceDef = SurfaceDefProvider.GetObjectSurfaceDef(hitInfo.collider, hitInfo.point); if (!objectSurfaceDef) { return; } if (NetworkServer.active) { EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/CharacterLandImpact"), new EffectData { origin = footPosition, scale = radius, color = objectSurfaceDef.approximateColor }, transmit: true); } if ((bool)objectSurfaceDef.footstepEffectPrefab) { EffectManager.SpawnEffect(objectSurfaceDef.footstepEffectPrefab, new EffectData { origin = hitInfo.point, scale = radius * 3f }, transmit: false); } SfxLocator component = characterBody.GetComponent(); if ((bool)component) { if (objectSurfaceDef.materialSwitchString != null && objectSurfaceDef.materialSwitchString.Length > 0) { AkSoundEngine.SetSwitch("material", objectSurfaceDef.materialSwitchString, characterBody.gameObject); } else { AkSoundEngine.SetSwitch("material", "dirt", characterBody.gameObject); } Util.PlaySound(component.landingSound, characterBody.gameObject); if (tookFallDamage) { Util.PlaySound(component.fallDamageSound, characterBody.gameObject); } } } [Obsolete("Use OnCharacterHitGroundServer instead, which this is just a backwards-compatibility wrapper for.", false)] public void OnCharacterHitGround(CharacterBody characterBody, Vector3 impactVelocity) { OnCharacterHitGroundServer(characterBody, new CharacterMotor.HitGroundInfo { velocity = impactVelocity }); } private void OnPlayerCharacterDeath(DamageReport damageReport, NetworkUser victimNetworkUser) { if ((bool)victimNetworkUser) { CharacterBody victimBody = damageReport.victimBody; string text = (((ulong)(damageReport.damageInfo.damageType & DamageType.VoidDeath) != 0L) ? "PLAYER_DEATH_QUOTE_VOIDDEATH" : (damageReport.isFallDamage ? fallDamageDeathQuoteTokens[UnityEngine.Random.Range(0, fallDamageDeathQuoteTokens.Length)] : ((!victimBody || !victimBody.inventory || victimBody.inventory.GetItemCount(RoR2Content.Items.LunarDagger) <= 0) ? standardDeathQuoteTokens[UnityEngine.Random.Range(0, standardDeathQuoteTokens.Length)] : "PLAYER_DEATH_QUOTE_BRITTLEDEATH"))); if ((bool)victimNetworkUser.masterController) { victimNetworkUser.masterController.finalMessageTokenServer = text; } Chat.SendBroadcastChat(new Chat.PlayerDeathChatMessage { subjectAsNetworkUser = victimNetworkUser, baseToken = text }); } } private static void ProcIgniteOnKill(DamageReport damageReport, int igniteOnKillCount, CharacterBody victimBody, TeamIndex attackerTeamIndex) { float num = 8f + 4f * (float)igniteOnKillCount; float radius = victimBody.radius; float num2 = num + radius; float num3 = 1.5f; float baseDamage = damageReport.attackerBody.damage * num3; Vector3 corePosition = victimBody.corePosition; igniteOnKillSphereSearch.origin = corePosition; igniteOnKillSphereSearch.mask = LayerIndex.entityPrecise.mask; igniteOnKillSphereSearch.radius = num2; igniteOnKillSphereSearch.RefreshCandidates(); igniteOnKillSphereSearch.FilterCandidatesByHurtBoxTeam(TeamMask.GetUnprotectedTeams(attackerTeamIndex)); igniteOnKillSphereSearch.FilterCandidatesByDistinctHurtBoxEntities(); igniteOnKillSphereSearch.OrderCandidatesByDistance(); igniteOnKillSphereSearch.GetHurtBoxes(igniteOnKillHurtBoxBuffer); igniteOnKillSphereSearch.ClearCandidates(); float value = (float)(1 + igniteOnKillCount) * 0.75f * damageReport.attackerBody.damage; for (int i = 0; i < igniteOnKillHurtBoxBuffer.Count; i++) { HurtBox hurtBox = igniteOnKillHurtBoxBuffer[i]; if ((bool)hurtBox.healthComponent) { InflictDotInfo inflictDotInfo = default(InflictDotInfo); inflictDotInfo.victimObject = hurtBox.healthComponent.gameObject; inflictDotInfo.attackerObject = damageReport.attacker; inflictDotInfo.totalDamage = value; inflictDotInfo.dotIndex = DotController.DotIndex.Burn; inflictDotInfo.damageMultiplier = 1f; InflictDotInfo dotInfo = inflictDotInfo; if ((bool)damageReport?.attackerMaster?.inventory) { StrengthenBurnUtils.CheckDotForUpgrade(damageReport.attackerMaster.inventory, ref dotInfo); } DotController.InflictDot(ref dotInfo); } } igniteOnKillHurtBoxBuffer.Clear(); BlastAttack blastAttack = new BlastAttack(); blastAttack.radius = num2; blastAttack.baseDamage = baseDamage; blastAttack.procCoefficient = 0f; blastAttack.crit = Util.CheckRoll(damageReport.attackerBody.crit, damageReport.attackerMaster); blastAttack.damageColorIndex = DamageColorIndex.Item; blastAttack.attackerFiltering = AttackerFiltering.Default; blastAttack.falloffModel = BlastAttack.FalloffModel.None; blastAttack.attacker = damageReport.attacker; blastAttack.teamIndex = attackerTeamIndex; blastAttack.position = corePosition; blastAttack.Fire(); EffectManager.SpawnEffect(CommonAssets.igniteOnKillExplosionEffectPrefab, new EffectData { origin = corePosition, scale = num2, rotation = Util.QuaternionSafeLookRotation(damageReport.damageInfo.force) }, transmit: true); } public void OnCharacterDeath(DamageReport damageReport) { if (!NetworkServer.active || damageReport == null) { return; } DamageInfo damageInfo = damageReport.damageInfo; GameObject gameObject = null; if ((bool)damageReport.victim) { gameObject = damageReport.victim.gameObject; } CharacterBody victimBody = damageReport.victimBody; TeamComponent teamComponent = null; CharacterMaster victimMaster = damageReport.victimMaster; TeamIndex teamIndex = damageReport.victimTeamIndex; Vector3 vector = Vector3.zero; Quaternion quaternion = Quaternion.identity; Vector3 vector2 = Vector3.zero; Transform transform = gameObject.transform; if ((bool)transform) { vector = transform.position; quaternion = transform.rotation; vector2 = vector; } InputBankTest inputBankTest = null; EquipmentIndex equipmentIndex = EquipmentIndex.None; EquipmentDef equipmentDef = null; if ((bool)victimBody) { teamComponent = victimBody.teamComponent; inputBankTest = victimBody.inputBank; vector2 = victimBody.corePosition; if ((bool)victimBody.equipmentSlot) { equipmentIndex = victimBody.equipmentSlot.equipmentIndex; equipmentDef = EquipmentCatalog.GetEquipmentDef(equipmentIndex); } } Ray ray = (inputBankTest ? inputBankTest.GetAimRay() : new Ray(vector, quaternion * Vector3.forward)); GameObject attacker = damageReport.attacker; CharacterBody attackerBody = damageReport.attackerBody; CharacterMaster attackerMaster = damageReport.attackerMaster; Inventory inventory = (attackerMaster ? attackerMaster.inventory : null); TeamIndex attackerTeamIndex = damageReport.attackerTeamIndex; if ((bool)teamComponent) { teamIndex = teamComponent.teamIndex; } if ((bool)victimBody && (bool)victimMaster) { PlayerCharacterMasterController playerCharacterMasterController = victimMaster.playerCharacterMasterController; if ((bool)playerCharacterMasterController) { NetworkUser networkUser = playerCharacterMasterController.networkUser; if ((bool)networkUser) { OnPlayerCharacterDeath(damageReport, networkUser); } } if (victimBody.HasBuff(RoR2Content.Buffs.AffixWhite)) { Vector3 position = vector2; GameObject gameObject2 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/GenericDelayBlast"), position, Quaternion.identity); float num = 12f + victimBody.radius; gameObject2.transform.localScale = new Vector3(num, num, num); DelayBlast component = gameObject2.GetComponent(); if ((bool)component) { component.position = position; component.baseDamage = victimBody.damage * 1.5f; component.baseForce = 2300f; component.attacker = gameObject; component.radius = num; component.crit = Util.CheckRoll(victimBody.crit, victimMaster); component.procCoefficient = 0.75f; component.maxTimer = 2f; component.falloffModel = BlastAttack.FalloffModel.None; component.explosionEffect = LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/AffixWhiteExplosion"); component.delayEffect = LegacyResourcesAPI.Load("Prefabs/Effects/AffixWhiteDelayEffect"); component.damageType = DamageType.Freeze2s; TeamFilter component2 = gameObject2.GetComponent(); if ((bool)component2) { component2.teamIndex = TeamComponent.GetObjectTeam(component.attacker); } } } if (victimBody.HasBuff(RoR2Content.Buffs.AffixPoison)) { Vector3 position2 = vector2; Quaternion rotation = Quaternion.LookRotation(ray.direction); GameObject gameObject3 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/CharacterMasters/UrchinTurretMaster"), position2, rotation); CharacterMaster component3 = gameObject3.GetComponent(); if ((bool)component3) { component3.teamIndex = teamIndex; NetworkServer.Spawn(gameObject3); component3.SpawnBodyHere(); } } if (RunArtifactManager.instance.IsArtifactEnabled(RoR2Content.Artifacts.wispOnDeath) && teamIndex == TeamIndex.Monster && victimMaster.masterIndex != CommonAssets.wispSoulMasterPrefabMasterComponent.masterIndex) { MasterSummon masterSummon = new MasterSummon(); masterSummon.position = vector2; masterSummon.ignoreTeamMemberLimit = true; masterSummon.masterPrefab = CommonAssets.wispSoulMasterPrefabMasterComponent.gameObject; masterSummon.summonerBodyObject = gameObject; masterSummon.rotation = Quaternion.LookRotation(ray.direction); masterSummon.Perform(); } if (victimBody.HasBuff(RoR2Content.Buffs.Fruiting) || (damageReport.damageInfo != null && (ulong)(damageReport.damageInfo.damageType & DamageType.FruitOnHit) != 0)) { EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/TreebotFruitDeathEffect.prefab"), new EffectData { origin = vector, rotation = UnityEngine.Random.rotation }, transmit: true); int num2 = Mathf.Min(Math.Max(1, (int)(victimBody.bestFitRadius * 2f)), 8); GameObject original = LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/TreebotFruitPack"); for (int i = 0; i < num2; i++) { GameObject obj = UnityEngine.Object.Instantiate(original, vector + UnityEngine.Random.insideUnitSphere * victimBody.radius * 0.5f, UnityEngine.Random.rotation); TeamFilter component4 = obj.GetComponent(); if ((bool)component4) { component4.teamIndex = attackerTeamIndex; } obj.GetComponentInChildren(); obj.transform.localScale = new Vector3(1f, 1f, 1f); NetworkServer.Spawn(obj); } } if (victimBody.HasBuff(DLC1Content.Buffs.EliteEarth)) { MasterSummon masterSummon2 = new MasterSummon(); masterSummon2.position = vector2; masterSummon2.ignoreTeamMemberLimit = true; masterSummon2.masterPrefab = CommonAssets.eliteEarthHealerMaster; masterSummon2.summonerBodyObject = gameObject; masterSummon2.rotation = Quaternion.LookRotation(ray.direction); masterSummon2.Perform(); } if (victimBody.HasBuff(DLC1Content.Buffs.EliteVoid) && (!victimMaster || victimMaster.IsDeadAndOutOfLivesServer())) { Vector3 position3 = vector2; GameObject gameObject4 = UnityEngine.Object.Instantiate(Addressables.LoadAssetAsync("RoR2/DLC1/EliteVoid/VoidInfestorMaster.prefab").WaitForCompletion(), position3, Quaternion.identity); CharacterMaster component5 = gameObject4.GetComponent(); if ((bool)component5) { component5.teamIndex = TeamIndex.Void; NetworkServer.Spawn(gameObject4); component5.SpawnBodyHere(); } } } if ((bool)attackerBody) { attackerBody.HandleOnKillEffectsServer(damageReport); if ((bool)attackerMaster && (bool)inventory) { int itemCount = inventory.GetItemCount(RoR2Content.Items.IgniteOnKill); if (itemCount > 0) { ProcIgniteOnKill(damageReport, itemCount, victimBody, attackerTeamIndex); } int itemCount2 = inventory.GetItemCount(RoR2Content.Items.ExplodeOnDeath); if (itemCount2 > 0) { Vector3 position4 = vector2; float damageCoefficient = 3.5f * (1f + (float)(itemCount2 - 1) * 0.8f); float baseDamage = Util.OnKillProcDamage(attackerBody.damage, damageCoefficient); GameObject obj2 = UnityEngine.Object.Instantiate(CommonAssets.explodeOnDeathPrefab, position4, Quaternion.identity); DelayBlast component6 = obj2.GetComponent(); if ((bool)component6) { component6.position = position4; component6.baseDamage = baseDamage; component6.baseForce = 2000f; component6.bonusForce = Vector3.up * 1000f; component6.radius = 12f + 2.4f * ((float)itemCount2 - 1f); component6.attacker = damageInfo.attacker; component6.inflictor = null; component6.crit = Util.CheckRoll(attackerBody.crit, attackerMaster); component6.maxTimer = 0.5f; component6.damageColorIndex = DamageColorIndex.Item; component6.falloffModel = BlastAttack.FalloffModel.SweetSpot; } TeamFilter component7 = obj2.GetComponent(); if ((bool)component7) { component7.teamIndex = attackerTeamIndex; } NetworkServer.Spawn(obj2); } int itemCount3 = inventory.GetItemCount(RoR2Content.Items.Dagger); if (itemCount3 > 0) { float damageCoefficient2 = 1.5f * (float)itemCount3; Vector3 vector3 = vector + Vector3.up * 1.8f; for (int j = 0; j < 3; j++) { ProjectileManager.instance.FireProjectile(CommonAssets.daggerPrefab, vector3 + UnityEngine.Random.insideUnitSphere * 0.5f, Util.QuaternionSafeLookRotation(Vector3.up + UnityEngine.Random.insideUnitSphere * 0.1f), attackerBody.gameObject, Util.OnKillProcDamage(attackerBody.damage, damageCoefficient2), 200f, Util.CheckRoll(attackerBody.crit, attackerMaster), DamageColorIndex.Item); } } int itemCount4 = inventory.GetItemCount(RoR2Content.Items.Tooth); if (itemCount4 > 0) { float num3 = Mathf.Pow(itemCount4, 0.25f); GameObject obj3 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/HealPack"), vector, UnityEngine.Random.rotation); TeamFilter component8 = obj3.GetComponent(); if ((bool)component8) { component8.teamIndex = attackerTeamIndex; } HealthPickup componentInChildren = obj3.GetComponentInChildren(); if ((bool)componentInChildren) { componentInChildren.flatHealing = 8f; componentInChildren.fractionalHealing = 0.02f * (float)itemCount4; } obj3.transform.localScale = new Vector3(num3, num3, num3); NetworkServer.Spawn(obj3); } float num4 = 0f; float num5 = 0f; float num6 = 0f; float num7 = 0f; if (victimBody.HasBuff(DLC2Content.Buffs.CookingChopped)) { num4 += 1f; num5 += 2f; num6 += 0.04f; num7 += 0.75f; } if (victimBody.HasBuff(DLC2Content.Buffs.CookingOiled)) { num4 += 1f; num5 += 2f; num6 += 0.04f; num7 += 0.75f; } if (victimBody.HasBuff(DLC2Content.Buffs.CookingRoasted)) { num4 += 1f; num5 += 2f; num6 += 0.04f; num7 += 0.75f; } if (victimBody.HasBuff(DLC2Content.Buffs.CookingRolled)) { num4 += 1f; num5 += 2f; num6 += 0.04f; num7 += 0.75f; } if (victimBody.HasBuff(DLC2Content.Buffs.CookingFlambe)) { num4 += 1f; num5 += 2f; num6 += 0.04f; num7 += 0.75f; } if (num4 > 1f) { GameObject obj4 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Chef/ChefFoodPickup"), vector, UnityEngine.Random.rotation); TeamFilter component9 = obj4.GetComponent(); if ((bool)component9) { component9.teamIndex = attackerTeamIndex; } HealthPickup componentInChildren2 = obj4.GetComponentInChildren(); if ((bool)componentInChildren2) { componentInChildren2.flatHealing = num5; componentInChildren2.fractionalHealing = num6; } obj4.transform.localScale = new Vector3(num7, num7, num7); NetworkServer.Spawn(obj4); } int itemCount5 = inventory.GetItemCount(RoR2Content.Items.Infusion); if (itemCount5 > 0) { int num8 = itemCount5 * 100; if (inventory.infusionBonus < num8) { InfusionOrb infusionOrb = new InfusionOrb(); infusionOrb.origin = vector; infusionOrb.target = Util.FindBodyMainHurtBox(attackerBody); infusionOrb.maxHpValue = itemCount5; OrbManager.instance.AddOrb(infusionOrb); } } if ((DamageType)(damageInfo.damageType & DamageType.ResetCooldownsOnKill) == DamageType.ResetCooldownsOnKill) { EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/Bandit2ResetEffect"), new EffectData { origin = damageInfo.position }, transmit: true); SkillLocator skillLocator = attackerBody.skillLocator; if ((bool)skillLocator) { skillLocator.ResetSkills(); } } if ((DamageType)(damageInfo.damageType & DamageType.GiveSkullOnKill) == DamageType.GiveSkullOnKill && (bool)victimMaster) { EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/Bandit2KillEffect"), new EffectData { origin = damageInfo.position }, transmit: true); attackerBody.AddBuff(RoR2Content.Buffs.BanditSkull); } int itemCount6 = inventory.GetItemCount(RoR2Content.Items.Talisman); if (itemCount6 > 0 && (bool)attackerBody.equipmentSlot) { inventory.DeductActiveEquipmentCooldown(2f + (float)itemCount6 * 2f); } int itemCount7 = inventory.GetItemCount(JunkContent.Items.TempestOnKill); if (itemCount7 > 0 && Util.CheckRoll(25f, attackerMaster)) { GameObject obj5 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/TempestWard"), victimBody.footPosition, Quaternion.identity); TeamFilter component10 = obj5.GetComponent(); if ((bool)component10) { component10.teamIndex = attackerTeamIndex; } BuffWard component11 = obj5.GetComponent(); if ((bool)component11) { component11.expireDuration = 2f + 6f * (float)itemCount7; } NetworkServer.Spawn(obj5); } int itemCount8 = inventory.GetItemCount(RoR2Content.Items.Bandolier); if (itemCount8 > 0 && Util.CheckRoll((1f - 1f / Mathf.Pow(itemCount8 + 1, 0.33f)) * 100f, attackerMaster)) { GameObject obj6 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/AmmoPack"), vector, UnityEngine.Random.rotation); TeamFilter component12 = obj6.GetComponent(); if ((bool)component12) { component12.teamIndex = attackerTeamIndex; } NetworkServer.Spawn(obj6); } if ((bool)victimBody && damageReport.victimIsElite) { int itemCount9 = inventory.GetItemCount(RoR2Content.Items.HeadHunter); int itemCount10 = inventory.GetItemCount(RoR2Content.Items.KillEliteFrenzy); if (itemCount9 > 0) { float duration = 3f + 5f * (float)itemCount9; for (int k = 0; k < BuffCatalog.eliteBuffIndices.Length; k++) { BuffIndex buffIndex = BuffCatalog.eliteBuffIndices[k]; if (victimBody.HasBuff(buffIndex)) { attackerBody.AddTimedBuff(buffIndex, duration); } } } if (itemCount10 > 0) { attackerBody.AddTimedBuff(RoR2Content.Buffs.NoCooldowns, (float)itemCount10 * 4f); } } int itemCount11 = inventory.GetItemCount(RoR2Content.Items.GhostOnKill); if (itemCount11 > 0 && (bool)victimBody && Util.CheckRoll(7f, attackerMaster)) { Util.TryToCreateGhost(victimBody, attackerBody, itemCount11 * 30); } if (inventory.GetItemCount(DLC1Content.Items.MinorConstructOnKill) > 0 && (bool)victimBody && victimBody.isElite && !attackerMaster.IsDeployableLimited(DeployableSlot.MinorConstructOnKill)) { Vector3 forward = Quaternion.AngleAxis(UnityEngine.Random.Range(0, 360), Vector3.up) * Quaternion.AngleAxis(-80f, Vector3.right) * Vector3.forward; FireProjectileInfo fireProjectileInfo = default(FireProjectileInfo); fireProjectileInfo.projectilePrefab = CommonAssets.minorConstructOnKillProjectile; fireProjectileInfo.position = vector; fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(forward); fireProjectileInfo.procChainMask = default(ProcChainMask); fireProjectileInfo.target = gameObject; fireProjectileInfo.owner = attackerBody.gameObject; fireProjectileInfo.damage = 0f; fireProjectileInfo.crit = false; fireProjectileInfo.force = 0f; fireProjectileInfo.damageColorIndex = DamageColorIndex.Item; FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; ProjectileManager.instance.FireProjectile(fireProjectileInfo2); } int itemCount12 = inventory.GetItemCount(DLC1Content.Items.MoveSpeedOnKill); if (itemCount12 > 0) { int num9 = itemCount12 - 1; int num10 = 5; float num11 = 1f + (float)num9 * 0.5f; attackerBody.ClearTimedBuffs(DLC1Content.Buffs.KillMoveSpeed); for (int l = 0; l < num10; l++) { attackerBody.AddTimedBuff(DLC1Content.Buffs.KillMoveSpeed, num11 * (float)(l + 1) / (float)num10); } EffectData effectData = new EffectData(); effectData.origin = attackerBody.corePosition; CharacterMotor characterMotor = attackerBody.characterMotor; bool flag = false; if ((bool)characterMotor) { Vector3 moveDirection = characterMotor.moveDirection; if (moveDirection != Vector3.zero) { effectData.rotation = Util.QuaternionSafeLookRotation(moveDirection); flag = true; } } if (!flag) { effectData.rotation = attackerBody.transform.rotation; } EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/MoveSpeedOnKillActivate"), effectData, transmit: true); } if ((bool)equipmentDef && Util.CheckRoll(equipmentDef.dropOnDeathChance * 100f, attackerMaster) && (bool)victimBody) { PickupDropletController.CreatePickupDroplet(PickupCatalog.FindPickupIndex(equipmentIndex), vector + Vector3.up * 1.5f, Vector3.up * 20f + ray.direction * 2f); } int itemCount13 = inventory.GetItemCount(RoR2Content.Items.BarrierOnKill); if (itemCount13 > 0 && (bool)attackerBody.healthComponent) { attackerBody.healthComponent.AddBarrier(15f * (float)itemCount13); } int itemCount14 = inventory.GetItemCount(RoR2Content.Items.BonusGoldPackOnKill); if (itemCount14 > 0 && Util.CheckRoll(4f * (float)itemCount14, attackerMaster)) { GameObject obj7 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/BonusMoneyPack"), vector, UnityEngine.Random.rotation); TeamFilter component13 = obj7.GetComponent(); if ((bool)component13) { component13.teamIndex = attackerTeamIndex; } NetworkServer.Spawn(obj7); } int itemCount15 = inventory.GetItemCount(RoR2Content.Items.Plant); if (itemCount15 > 0) { GameObject obj8 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/InterstellarDeskPlant"), victimBody.footPosition, Quaternion.identity); DeskPlantController component14 = obj8.GetComponent(); if ((bool)component14) { if ((bool)component14.teamFilter) { component14.teamFilter.teamIndex = attackerTeamIndex; } component14.itemCount = itemCount15; } NetworkServer.Spawn(obj8); } int incubatorOnKillCount = attackerMaster.inventory.GetItemCount(JunkContent.Items.Incubator); if (incubatorOnKillCount > 0 && attackerMaster.GetDeployableCount(DeployableSlot.ParentPodAlly) + attackerMaster.GetDeployableCount(DeployableSlot.ParentAlly) < incubatorOnKillCount && Util.CheckRoll(7f + 1f * (float)incubatorOnKillCount, attackerMaster)) { DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(LegacyResourcesAPI.Load("SpawnCards/CharacterSpawnCards/cscParentPod"), new DirectorPlacementRule { placementMode = DirectorPlacementRule.PlacementMode.Approximate, minDistance = 3f, maxDistance = 20f, spawnOnTarget = transform }, RoR2Application.rng); directorSpawnRequest.summonerBodyObject = attacker; directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, (Action)delegate(SpawnCard.SpawnResult spawnResult) { if (spawnResult.success) { Inventory inventory2 = spawnResult.spawnedInstance.GetComponent().inventory; if ((bool)inventory2) { inventory2.GiveItem(RoR2Content.Items.BoostDamage, 30); inventory2.GiveItem(RoR2Content.Items.BoostHp, 10 * incubatorOnKillCount); } } }); DirectorCore.instance.TrySpawnObject(directorSpawnRequest); } int itemCount16 = inventory.GetItemCount(RoR2Content.Items.BleedOnHitAndExplode); if (itemCount16 > 0 && (bool)victimBody && (victimBody.HasBuff(RoR2Content.Buffs.Bleeding) || victimBody.HasBuff(RoR2Content.Buffs.SuperBleed))) { Util.PlaySound("Play_bleedOnCritAndExplode_explode", gameObject); Vector3 position5 = vector2; float damageCoefficient3 = 4f * (float)(1 + (itemCount16 - 1)); float num12 = 0.15f * (float)(1 + (itemCount16 - 1)); float baseDamage2 = Util.OnKillProcDamage(attackerBody.damage, damageCoefficient3) + victimBody.maxHealth * num12; GameObject obj9 = UnityEngine.Object.Instantiate(CommonAssets.bleedOnHitAndExplodeBlastEffect, position5, Quaternion.identity); DelayBlast component15 = obj9.GetComponent(); component15.position = position5; component15.baseDamage = baseDamage2; component15.baseForce = 0f; component15.radius = 16f; component15.attacker = damageInfo.attacker; component15.inflictor = null; component15.crit = Util.CheckRoll(attackerBody.crit, attackerMaster); component15.maxTimer = 0f; component15.damageColorIndex = DamageColorIndex.Item; component15.falloffModel = BlastAttack.FalloffModel.SweetSpot; obj9.GetComponent().teamIndex = attackerTeamIndex; NetworkServer.Spawn(obj9); } if (attackerMaster.inventory.GetItemCount(DLC2Content.Items.ResetChests) > 0) { int itemCount17 = attackerMaster.inventory.GetItemCount(DLC2Content.Items.ResetChests); if (victimBody.isChampion && Util.CheckRoll(100f, attackerMaster) && (bool)victimBody) { PickupDropletController.CreatePickupDroplet(CommonAssets.dtSonorousEchoPath.GenerateDrop(Run.instance.runRNG), vector + Vector3.up * 1.5f, Vector3.up * 20f + ray.direction * 2f); } if (victimBody.isElite && Util.CheckRoll(2f + 1f * (float)itemCount17, attackerMaster) && (bool)victimBody) { PickupDropletController.CreatePickupDroplet(CommonAssets.dtSonorousEchoPath.GenerateDrop(Run.instance.runRNG), vector + Vector3.up * 1.5f, Vector3.up * 20f + ray.direction * 2f); } } } } GlobalEventManager.onCharacterDeathGlobal?.Invoke(damageReport); } public void OnHitAll(DamageInfo damageInfo, GameObject hitObject) { OnHitAllProcess(damageInfo, hitObject); } private void OnHitAllProcess(DamageInfo damageInfo, GameObject hitObject) { if (damageInfo.procCoefficient == 0f || damageInfo.rejected) { return; } _ = NetworkServer.active; if (!damageInfo.attacker) { return; } CharacterBody component = damageInfo.attacker.GetComponent(); if (!component) { return; } CharacterMaster master = component.master; if (!master) { return; } Inventory inventory = master.inventory; if (!master.inventory) { return; } if (!damageInfo.procChainMask.HasProc(ProcType.Behemoth)) { int itemCount = inventory.GetItemCount(RoR2Content.Items.Behemoth); if (itemCount > 0 && damageInfo.procCoefficient != 0f) { float num = (1.5f + 2.5f * (float)itemCount) * damageInfo.procCoefficient; float damageCoefficient = 0.6f; float baseDamage = Util.OnHitProcDamage(damageInfo.damage, component.damage, damageCoefficient); EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/OmniEffect/OmniExplosionVFXQuick"), new EffectData { origin = damageInfo.position, scale = num, rotation = Util.QuaternionSafeLookRotation(damageInfo.force) }, transmit: true); BlastAttack obj = new BlastAttack { position = damageInfo.position, baseDamage = baseDamage, baseForce = 0f, radius = num, attacker = damageInfo.attacker, inflictor = null }; obj.teamIndex = TeamComponent.GetObjectTeam(obj.attacker); obj.crit = damageInfo.crit; obj.procChainMask = damageInfo.procChainMask; obj.procCoefficient = 0f; obj.damageColorIndex = DamageColorIndex.Item; obj.falloffModel = BlastAttack.FalloffModel.None; obj.damageType = damageInfo.damageType; obj.Fire(); } } if ((component.HasBuff(RoR2Content.Buffs.AffixBlue) ? 1 : 0) > 0) { float damageCoefficient2 = 0.5f; float damage = Util.OnHitProcDamage(damageInfo.damage, component.damage, damageCoefficient2); float force = 0f; Vector3 position = damageInfo.position; ProjectileManager.instance.FireProjectile(LegacyResourcesAPI.Load("Prefabs/Projectiles/LightningStake"), position, Quaternion.identity, damageInfo.attacker, damage, force, damageInfo.crit, DamageColorIndex.Item); } } public void OnCrit(CharacterBody body, DamageInfo damageInfo, CharacterMaster master, float procCoefficient, ProcChainMask procChainMask) { Vector3 hitPos = body.corePosition; GameObject gameObject = LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/Critspark"); if ((bool)body) { if (body.critMultiplier > 2f) { gameObject = LegacyResourcesAPI.Load("Prefabs/Effects/ImpactEffects/CritsparkHeavy"); } if ((bool)body && procCoefficient > 0f && (bool)master && (bool)master.inventory) { Inventory inventory = master.inventory; if (!procChainMask.HasProc(ProcType.HealOnCrit)) { procChainMask.AddProc(ProcType.HealOnCrit); int itemCount = inventory.GetItemCount(RoR2Content.Items.HealOnCrit); if (itemCount > 0 && (bool)body.healthComponent) { Util.PlaySound("Play_item_proc_crit_heal", body.gameObject); if (NetworkServer.active) { body.healthComponent.Heal((4f + (float)itemCount * 4f) * procCoefficient, procChainMask); } } } if (inventory.GetItemCount(RoR2Content.Items.AttackSpeedOnCrit) > 0) { body.AddTimedBuff(RoR2Content.Buffs.AttackSpeedOnCrit, 3f * procCoefficient); } int itemCount2 = inventory.GetItemCount(JunkContent.Items.CooldownOnCrit); if (itemCount2 > 0) { Util.PlaySound("Play_item_proc_crit_cooldown", body.gameObject); SkillLocator component = body.GetComponent(); if ((bool)component) { float dt = (float)itemCount2 * procCoefficient; if ((bool)component.primary) { component.primary.RunRecharge(dt); } if ((bool)component.secondary) { component.secondary.RunRecharge(dt); } if ((bool)component.utility) { component.utility.RunRecharge(dt); } if ((bool)component.special) { component.special.RunRecharge(dt); } } } } } if (damageInfo != null) { hitPos = damageInfo.position; } if ((bool)gameObject) { EffectManager.SimpleImpactEffect(gameObject, hitPos, Vector3.up, transmit: true); } } public static void OnTeamLevelUp(TeamIndex teamIndex) { GlobalEventManager.onTeamLevelUp?.Invoke(teamIndex); } public static void OnCharacterLevelUp(CharacterBody characterBody) { GlobalEventManager.onCharacterLevelUp?.Invoke(characterBody); } public void OnInteractionBegin(Interactor interactor, IInteractable interactable, GameObject interactableObject) { if (!interactor) { Debug.LogError("OnInteractionBegin invalid interactor!"); return; } if (interactable == null) { Debug.LogError("OnInteractionBegin invalid interactable!"); return; } if (!interactableObject) { Debug.LogError("OnInteractionBegin invalid interactableObject!"); return; } GlobalEventManager.OnInteractionsGlobal?.Invoke(interactor, interactable, interactableObject); CharacterBody component = interactor.GetComponent(); Vector3 vector = Vector3.zero; Quaternion rotation = Quaternion.identity; Transform transform = interactableObject.transform; if ((bool)transform) { vector = transform.position; rotation = transform.rotation; } if (!component) { return; } Inventory inventory = component.inventory; if (!inventory) { return; } InteractionProcFilter interactionProcFilter = interactableObject.GetComponent(); int itemCount = inventory.GetItemCount(RoR2Content.Items.Firework); if (itemCount > 0 && InteractableIsPermittedForSpawn((MonoBehaviour)interactable)) { Transform transform2 = interactableObject.GetComponent()?.modelTransform?.GetComponent()?.FindChild("FireworkOrigin"); Vector3 position = (transform2 ? transform2.position : (interactableObject.transform.position + Vector3.up * 2f)); int remaining = 4 + itemCount * 4; FireworkLauncher component2 = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/FireworkLauncher"), position, Quaternion.identity).GetComponent(); component2.owner = interactor.gameObject; component2.crit = Util.CheckRoll(component.crit, component.master); component2.remaining = remaining; } int squidStacks = inventory.GetItemCount(RoR2Content.Items.Squid); if (squidStacks > 0 && InteractableIsPermittedForSpawn((MonoBehaviour)interactable)) { CharacterSpawnCard spawnCard = LegacyResourcesAPI.Load("SpawnCards/CharacterSpawnCards/cscSquidTurret"); DirectorPlacementRule placementRule = new DirectorPlacementRule { placementMode = DirectorPlacementRule.PlacementMode.Approximate, minDistance = 5f, maxDistance = 25f, position = interactableObject.transform.position }; DirectorSpawnRequest directorSpawnRequest = new DirectorSpawnRequest(spawnCard, placementRule, RoR2Application.rng); directorSpawnRequest.teamIndexOverride = TeamIndex.Player; directorSpawnRequest.summonerBodyObject = interactor.gameObject; directorSpawnRequest.onSpawnedServer = (Action)Delegate.Combine(directorSpawnRequest.onSpawnedServer, (Action)delegate(SpawnCard.SpawnResult result) { if (result.success && (bool)result.spawnedInstance) { CharacterMaster component5 = result.spawnedInstance.GetComponent(); if ((bool)component5 && (bool)component5.inventory) { component5.inventory.GiveItem(RoR2Content.Items.HealthDecay, 30); component5.inventory.GiveItem(RoR2Content.Items.BoostAttackSpeed, 10 * (squidStacks - 1)); } } }); DirectorCore.instance.TrySpawnObject(directorSpawnRequest); } int itemCount2 = inventory.GetItemCount(RoR2Content.Items.MonstersOnShrineUse); if (itemCount2 <= 0) { return; } PurchaseInteraction component3 = interactableObject.GetComponent(); if (!component3 || !component3.isShrine || (bool)interactableObject.GetComponent()) { return; } GameObject gameObject = LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/Encounters/MonstersOnShrineUseEncounter"); if (!gameObject) { return; } GameObject gameObject2 = UnityEngine.Object.Instantiate(gameObject, vector, Quaternion.identity); NetworkServer.Spawn(gameObject2); CombatDirector component4 = gameObject2.GetComponent(); if ((bool)component4 && (bool)Stage.instance) { float monsterCredit = 40f * Stage.instance.entryDifficultyCoefficient * (float)itemCount2; DirectorCard directorCard = component4.SelectMonsterCardForCombatShrine(monsterCredit); if (directorCard != null) { component4.CombatShrineActivation(interactor, monsterCredit, directorCard); EffectData effectData = new EffectData { origin = vector, rotation = rotation }; EffectManager.SpawnEffect(LegacyResourcesAPI.Load("Prefabs/Effects/MonstersOnShrineUse"), effectData, transmit: true); } else { NetworkServer.Destroy(gameObject2); } } bool InteractableIsPermittedForSpawn(MonoBehaviour interactableAsMonoBehaviour) { if (!interactableAsMonoBehaviour) { return false; } if ((bool)interactionProcFilter) { return interactionProcFilter.shouldAllowOnInteractionBeginProc; } if ((bool)interactableAsMonoBehaviour.GetComponent()) { if (interactableAsMonoBehaviour.GetComponent().enabled) { return false; } return true; } if ((bool)interactableAsMonoBehaviour.GetComponent()) { return false; } if ((bool)interactableAsMonoBehaviour.GetComponent()) { return false; } if ((bool)interactableAsMonoBehaviour.GetComponent()) { return false; } return true; } } public static void ClientDamageNotified(DamageDealtMessage damageDealtMessage) { GlobalEventManager.onClientDamageNotified?.Invoke(damageDealtMessage); } public static void ServerDamageDealt(DamageReport damageReport) { GlobalEventManager.onServerDamageDealt?.Invoke(damageReport); } public static void ServerCharacterExecuted(DamageReport damageReport, float executionHealthLost) { GlobalEventManager.onServerCharacterExecuted?.Invoke(damageReport, executionHealthLost); } }