public override void DoImpact(Target target, Actor firedBy, IEnumerable <int> damageModifiers)
        {
            if (!target.IsValidFor(firedBy))
            {
                return;
            }

            var random     = firedBy.World.SharedRandom;
            var pos        = target.CenterPosition + new WVec(Radius.X == 0 ? 0 : random.Next(-Radius.X, Radius.X), Radius.Y == 0 ? 0 : random.Next(-Radius.Y, Radius.Y), 0);
            var world      = firedBy.World;
            var targetTile = world.Map.CellContaining(pos);
            var isValid    = IsValidImpact(pos, firedBy);

            if ((!world.Map.Contains(targetTile)) || (!isValid))
            {
                return;
            }

            var palette = ExplosionPalette;

            if (UsePlayerPalette)
            {
                palette += firedBy.Owner.InternalName;
            }

            if (ForceDisplayAtGroundLevel)
            {
                var dat = world.Map.DistanceAboveTerrain(pos);
                pos = new WPos(pos.X, pos.Y, pos.Z - dat.Length);
            }

            var explosion = Explosions.RandomOrDefault(Game.CosmeticRandom);

            if (Image != null && explosion != null)
            {
                world.AddFrameEndTask(w => w.Add(new SpriteEffect(pos, w, Image, explosion, palette)));
            }

            if (ShrapnelWeapon != null)
            {
                WeaponInfo weaponInfo;
                var        weaponToLower = ShrapnelWeapon.ToLowerInvariant();

                if (!Game.ModData.DefaultRules.Weapons.TryGetValue(weaponToLower, out weaponInfo))
                {
                    throw new YamlException("Weapons Ruleset does not contain an entry '{0}'".F(weaponToLower));
                }

                var rotation      = WRot.FromFacing(world.SharedRandom.Next(1024));
                var range         = world.SharedRandom.Next(ShrapnelRange[0].Length, ShrapnelRange[1].Length);
                var passiveTarget = pos + new WVec(range, 0, 0).Rotate(rotation);

                var args = new ProjectileArgs
                {
                    Weapon              = weaponInfo,
                    DamageModifiers     = new int[0],
                    InaccuracyModifiers = new int[0],
                    RangeModifiers      = new int[0],
                    Source              = pos,
                    CurrentSource       = () => pos,
                    SourceActor         = firedBy,
                    PassiveTarget       = passiveTarget,
                    GuidedTarget        = target
                };

                world.AddFrameEndTask(x =>
                {
                    if (args.Weapon.Projectile != null)
                    {
                        var projectile = args.Weapon.Projectile.Create(args);
                        if (projectile != null)
                        {
                            world.Add(projectile);
                        }
                    }
                    else
                    {
                        foreach (var warhead in args.Weapon.Warheads.Keys)
                        {
                            var wh = warhead;                             // force the closure to bind to the current warhead

                            if (wh.Delay > 0)
                            {
                                firedBy.World.AddFrameEndTask(w => w.Add(new DelayedImpact(wh.Delay, wh, Target.FromPos(args.PassiveTarget), args.SourceActor, new int[0])));
                            }
                            else
                            {
                                wh.DoImpact(Target.FromPos(args.PassiveTarget), args.SourceActor, new int[0]);
                            }
                        }
                    }
                });
            }

            var impactSound = ImpactSounds.RandomOrDefault(Game.CosmeticRandom);

            if (impactSound != null && Game.CosmeticRandom.Next(0, 100) < ImpactSoundChance)
            {
                Game.Sound.Play(SoundType.World, impactSound, pos);
            }
        }