private void OnHandSelected(EntityUid uid, MeleeWeaponComponent comp, HandSelectedEvent args)
        {
            var curTime = _gameTiming.CurTime;
            var cool    = TimeSpan.FromSeconds(comp.CooldownTime * 0.5f);

            if (curTime < comp.CooldownEnd)
            {
                if (comp.CooldownEnd - curTime < cool)
                {
                    comp.LastAttackTime = curTime;
                    comp.CooldownEnd   += cool;
                }
                else
                {
                    return;
                }
            }
            else
            {
                comp.LastAttackTime = curTime;
                comp.CooldownEnd    = curTime + cool;
            }

            RaiseLocalEvent(uid, new RefreshItemCooldownEvent(comp.LastAttackTime, comp.CooldownEnd), false);
        }
        private void OnClickAttack(EntityUid owner, MeleeWeaponComponent comp, ClickAttackEvent args)
        {
            args.Handled = true;
            var curTime = _gameTiming.CurTime;

            if (curTime < comp.CooldownEnd || args.Target == null)
            {
                return;
            }

            var location = EntityManager.GetComponent <TransformComponent>(args.User).Coordinates;
            var diff     = args.ClickLocation.ToMapPos(EntityManager) - location.ToMapPos(EntityManager);
            var angle    = Angle.FromWorldVec(diff);

            if (args.Target is { Valid : true } target)
            {
                // Raise event before doing damage so we can cancel damage if the event is handled
                var hitEvent = new MeleeHitEvent(new List <EntityUid>()
                {
                    target
                }, args.User);
                RaiseLocalEvent(owner, hitEvent, false);

                if (!hitEvent.Handled)
                {
                    var targets = new[] { target };
                    SendAnimation(comp.ClickArc, angle, args.User, owner, targets, comp.ClickAttackEffect, false);

                    RaiseLocalEvent(target, new AttackedEvent(args.Used, args.User, args.ClickLocation));

                    var modifiedDamage = DamageSpecifier.ApplyModifierSets(comp.Damage + hitEvent.BonusDamage, hitEvent.ModifiersList);
                    var damageResult   = _damageableSystem.TryChangeDamage(target, modifiedDamage);

                    if (damageResult != null)
                    {
                        if (args.Used == args.User)
                        {
                            _logSystem.Add(LogType.MeleeHit,
                                           $"{ToPrettyString(args.User):user} melee attacked {ToPrettyString(args.Target.Value):target} using their hands and dealt {damageResult.Total:damage} damage");
                        }
                        else
                        {
                            _logSystem.Add(LogType.MeleeHit,
                                           $"{ToPrettyString(args.User):user} melee attacked {ToPrettyString(args.Target.Value):target} using {ToPrettyString(args.Used):used} and dealt {damageResult.Total:damage} damage");
                        }
                    }

                    if (hitEvent.HitSoundOverride != null)
                    {
                        SoundSystem.Play(Filter.Pvs(owner), hitEvent.HitSoundOverride.GetSound(), target, AudioHelpers.WithVariation(0.25f));
                    }
                    else
                    {
                        SoundSystem.Play(Filter.Pvs(owner), comp.HitSound.GetSound(), target);
                    }
                }
            }
Beispiel #3
0
        private void OnClickAttack(EntityUid uid, MeleeWeaponComponent comp, ClickAttackEvent args)
        {
            args.Handled = true;
            var curTime = _gameTiming.CurTime;

            if (curTime < comp.CooldownEnd || !args.Target.IsValid())
            {
                return;
            }

            var owner  = EntityManager.GetEntity(uid);
            var target = args.TargetEntity;

            var location = args.User.Transform.Coordinates;
            var diff     = args.ClickLocation.ToMapPos(owner.EntityManager) - location.ToMapPos(owner.EntityManager);
            var angle    = Angle.FromWorldVec(diff);

            if (target != null)
            {
                // Raise event before doing damage so we can cancel damage if the event is handled
                var hitEvent = new MeleeHitEvent(new List <IEntity>()
                {
                    target
                }, args.User);
                RaiseLocalEvent(uid, hitEvent, false);

                if (!hitEvent.Handled)
                {
                    var targets = new[] { target };
                    SendAnimation(comp.ClickArc, angle, args.User, owner, targets, comp.ClickAttackEffect, false);

                    if (target.TryGetComponent(out IDamageableComponent? damageableComponent))
                    {
                        damageableComponent.TryChangeDamage(comp.DamageType, comp.Damage);
                    }

                    SoundSystem.Play(Filter.Pvs(owner), comp.HitSound.GetSound(), target);
                }
            }
            else
            {
                SoundSystem.Play(Filter.Pvs(owner), comp.MissSound.GetSound(), args.User);
                return;
            }

            comp.LastAttackTime = curTime;
            comp.CooldownEnd    = comp.LastAttackTime + TimeSpan.FromSeconds(comp.CooldownTime);

            RaiseLocalEvent(uid, new RefreshItemCooldownEvent(comp.LastAttackTime, comp.CooldownEnd), false);
        }
Beispiel #4
0
        /// <summary>
        ///     Used for melee weapons that want some behavior on AfterInteract,
        ///     but also want the cooldown (stun batons, flashes)
        /// </summary>
        private void OnAfterInteract(EntityUid uid, MeleeWeaponComponent comp, AfterInteractEvent args)
        {
            if (!args.CanReach)
            {
                return;
            }

            var curTime = _gameTiming.CurTime;

            if (curTime < comp.CooldownEnd)
            {
                return;
            }

            var owner = EntityManager.GetEntity(uid);

            if (args.Target == null)
            {
                return;
            }

            var location = args.User.Transform.Coordinates;
            var diff     = args.ClickLocation.ToMapPos(owner.EntityManager) - location.ToMapPos(owner.EntityManager);
            var angle    = Angle.FromWorldVec(diff);

            var hitEvent = new MeleeInteractEvent(args.Target, args.User);

            RaiseLocalEvent(uid, hitEvent, false);

            if (!hitEvent.CanInteract)
            {
                return;
            }
            SendAnimation(comp.ClickArc, angle, args.User, owner, new List <IEntity>()
            {
                args.Target
            }, comp.ClickAttackEffect, false);

            comp.LastAttackTime = curTime;
            comp.CooldownEnd    = comp.LastAttackTime + TimeSpan.FromSeconds(comp.CooldownTime);

            RaiseLocalEvent(uid, new RefreshItemCooldownEvent(comp.LastAttackTime, comp.CooldownEnd), false);
        }
Beispiel #5
0
        private void OnWideAttack(EntityUid uid, MeleeWeaponComponent comp, WideAttackEvent args)
        {
            args.Handled = true;
            var curTime = _gameTiming.CurTime;

            if (curTime < comp.CooldownEnd)
            {
                return;
            }

            var owner = EntityManager.GetEntity(uid);

            var location = args.User.Transform.Coordinates;
            var diff     = args.ClickLocation.ToMapPos(owner.EntityManager) - location.ToMapPos(owner.EntityManager);
            var angle    = Angle.FromWorldVec(diff);

            // This should really be improved. GetEntitiesInArc uses pos instead of bounding boxes.
            var entities = ArcRayCast(args.User.Transform.WorldPosition, angle, comp.ArcWidth, comp.Range, owner.Transform.MapID, args.User);

            var hitEntities = new List <IEntity>();

            foreach (var entity in entities)
            {
                if (!entity.Transform.IsMapTransform || entity == args.User)
                {
                    continue;
                }

                if (ComponentManager.HasComponent <IDamageableComponent>(entity.Uid))
                {
                    hitEntities.Add(entity);
                }
            }

            // Raise event before doing damage so we can cancel damage if handled
            var hitEvent = new MeleeHitEvent(hitEntities, args.User);

            RaiseLocalEvent(uid, hitEvent, false);
            SendAnimation(comp.Arc, angle, args.User, owner, hitEntities);

            if (!hitEvent.Handled)
            {
                if (entities.Count != 0)
                {
                    SoundSystem.Play(Filter.Pvs(owner), comp.HitSound.GetSound(), entities.First().Transform.Coordinates);
                }
                else
                {
                    SoundSystem.Play(Filter.Pvs(owner), comp.MissSound.GetSound(), args.User.Transform.Coordinates);
                }

                foreach (var entity in hitEntities)
                {
                    if (entity.TryGetComponent <IDamageableComponent>(out var damageComponent))
                    {
                        damageComponent.TryChangeDamage(comp.DamageType, comp.Damage);
                    }
                }
            }

            comp.LastAttackTime = curTime;
            comp.CooldownEnd    = comp.LastAttackTime + TimeSpan.FromSeconds(comp.ArcCooldownTime);

            RaiseLocalEvent(uid, new RefreshItemCooldownEvent(comp.LastAttackTime, comp.CooldownEnd), false);
        }