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);
                    }
                }
            }
示例#2
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);

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

                    _damageableSystem.TryChangeDamage(target.Uid,
                                                      DamageSpecifier.ApplyModifierSets(comp.Damage, hitEvent.ModifiersList));
                    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);
        }
示例#3
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.IsInContainer() || entity == args.User)
                {
                    continue;
                }

                if (EntityManager.HasComponent <DamageableComponent>(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)
                {
                    RaiseLocalEvent(entity.Uid, new AttackedEvent(args.Used, args.User, args.ClickLocation));

                    _damageableSystem.TryChangeDamage(entity.Uid,
                                                      DamageSpecifier.ApplyModifierSets(comp.Damage, hitEvent.ModifiersList));
                }
            }

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

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