using System.Collections.Generic; using Cielonos.MainGame.Buffs; using Cielonos.MainGame.Buffs.Character; using Cielonos.MainGame.Characters; using Cielonos.MainGame.UI; using DamageNumbersPro; using SLSUtilities.FunctionalAnimation; using SLSUtilities.WwiseAssistance; using UnityEngine; namespace Cielonos.MainGame.Inventory.Collections { public class ElectronicNeutralizingBullet : SupportEquipmentBase { private const string ProjectileVfxName = "Projectile"; private const string DamagePerSecondAttribute = "DamagePerSecond"; private Transform _muzzle; public override void Initialize() { base.Initialize(); if (activeAttributeData != null) { activeAttributeSm = new AttributeSubmodule(this, activeAttributeData); } } public override void OnObtained() { base.OnObtained(); _muzzle = player.bodyPartsSc.AuxiliaryDrone.center; } public override void OnPress(List modifiers = default) { if (!functionSm.mainFunction.IsAvailable()) { PlayerCanvas.SupportEquipmentsUIArea[this].CanNotUseOutlineAnimation(); return; } CharacterBase target = CombatManager.EnemySm.Query(50f) .Where(enemy => enemy.buffSm.HasBuff()) .LockonFirst(); target ??= CombatManager.EnemySm.Query(50f).LockonFirst(); GenerateProjectile(target, 50f, _muzzle); functionSm.mainFunction.Execute(); PlayerCanvas.SupportEquipmentsUIArea[this].UseOutlineAnimation(); } private void GenerateProjectile(CharacterBase target, float speed, Transform muzzle = null) { muzzle ??= _muzzle; vfxData.SpawnMuzzleVFX(ProjectileVfxName, player, muzzle); Projectile projectile = vfxData.SpawnVFX(ProjectileVfxName, player, muzzle) .GetComponentInChildren(); Vector3 direction = muzzle.transform.forward; if (target != null) { direction = (target.CenterPoint.position - projectile.transform.position).normalized; } projectile.Initialize(player, this, false, 1, Fraction.Enemy) .SetAttackSubmodule(attackData[ProjectileVfxName]) .SetTimeSubmodule(10f) .SetHitSubmodule() .SetAdaptiveTraceMoveSubmodule(target, speed, 10f, 60f, 30f, direction) .SetRaycastSubmodule(default, 0.25f, 0.5f); projectile.SetImpulseSubmodule().WithDynamicForce(20f); projectile.hitSm.AddHitSound(AK.EVENTS.ELECTRONICNEUTRALIZINGBULLET_NORMALHIT); projectile.eventSm.onHit.Add((hitTarget, hitPosition) => { projectile.hitSm.isAutoPlayHitSound = false; NeutralizeElectronicParalysis(hitTarget, hitPosition); }); AudioManager.Post(AK.EVENTS.ELECTRONICNEUTRALIZINGBULLET_SHOOT, muzzle.gameObject); } private void NeutralizeElectronicParalysis(CharacterBase target, Vector3 hitPosition) { if (!target.buffSm.TryGetBuff(out ElectronicParalysis paralysis)) { feedbackSc.PlayFeedback("NormalHit"); AudioManager.Post(AK.EVENTS.ELECTRONICNEUTRALIZINGBULLET_NORMALHIT, hitPosition); return; } var longestStack = paralysis.independentStackSubmodule.LongestUnit; if (longestStack == null) return; BuffContext removeContext = new BuffContext(); removeContext.Set(Incapacitation.SkipRiseAnimationKey, true); paralysis.Remove(removeContext); float remainingTime = Mathf.Max(0f, longestStack.remainingTime); float damage = remainingTime * (passiveAttributeSm?.GetItemAttribute(DamagePerSecondAttribute) ?? 0f); if (damage > 0f) { float ratio = damage / 1000f; Attack.Context context = new Attack.Context(player, target, nameof(ElectronicNeutralizingBullet), hitPosition); Attack.Value value = new Attack.Value(ratio >= 1, damage, 0f, Attack.Type.Energy, DisruptionType.Must, Breakthrough.Type.Forced); Attack.Result result = new Attack.Result(context, value); target.GetHit(Breakthrough.Type.Forced, out _, DisruptionType.Must); target.TakeDepletion(result); target.TakeDamage(result, out DamageNumber damageNumber); damageNumber.SetScale(ratio); damageNumber.SetPosition(hitPosition + Vector3.up); } feedbackSc.PlayFeedback("EffectiveHit"); AudioManager.Post(AK.EVENTS.ELECTRONICNEUTRALIZINGBULLET_EFFECTIVEHIT, hitPosition); } } }