Пример #1
0
        // Note: facing is only used by the legacy positioning code
        // The world coordinate model uses Actor.Orientation
        public void CheckFire(Actor self, AttackBase attack, IMove move, IFacing facing, Target target)
        {
            if (FireDelay > 0)
            {
                return;
            }

            var limitedAmmo = self.TraitOrDefault <LimitedAmmo>();

            if (limitedAmmo != null && !limitedAmmo.HasAmmo())
            {
                return;
            }

            if (!Combat.IsInRange(self.CenterLocation, Weapon.Range, target))
            {
                return;
            }
            if (Combat.IsInRange(self.CenterLocation, Weapon.MinRange, target))
            {
                return;
            }
            if (!IsValidAgainst(self.World, target))
            {
                return;
            }

            var barrel   = Barrels[Burst % Barrels.Length];
            var destMove = target.IsActor ? target.Actor.TraitOrDefault <IMove>() : null;

            var muzzlePosition       = self.CenterPosition + MuzzleOffset(self, barrel);
            var legacyMuzzlePosition = PPos.FromWPos(muzzlePosition);
            var legacyMuzzleAltitude = Game.CellSize * muzzlePosition.Z / 1024;
            var legacyFacing         = MuzzleOrientation(self, barrel).Yaw.Angle / 4;

            var args = new ProjectileArgs
            {
                weapon      = Weapon,
                firedBy     = self,
                target      = target,
                src         = legacyMuzzlePosition,
                srcAltitude = legacyMuzzleAltitude,

                dest         = target.CenterLocation,
                destAltitude = destMove != null ? destMove.Altitude : 0,

                facing = legacyFacing,

                firepowerModifier = self.TraitsImplementing <IFirepowerModifier>()
                                    .Select(a => a.GetFirepowerModifier())
                                    .Product()
            };

            attack.ScheduleDelayedAction(Info.FireDelay, () =>
            {
                if (args.weapon.Projectile != null)
                {
                    var projectile = args.weapon.Projectile.Create(args);
                    if (projectile != null)
                    {
                        self.World.Add(projectile);
                    }

                    if (args.weapon.Report != null && args.weapon.Report.Any())
                    {
                        Sound.Play(args.weapon.Report.Random(self.World.SharedRandom) + ".aud", self.CenterLocation);
                    }
                }
            });

            foreach (var na in self.TraitsImplementing <INotifyAttack>())
            {
                na.Attacking(self, target);
            }

            Recoil = Info.Recoil;

            if (--Burst > 0)
            {
                FireDelay = Weapon.BurstDelay;
            }
            else
            {
                FireDelay = Weapon.ROF;
                Burst     = Weapon.Burst;
            }
        }