Ejemplo n.º 1
0
		static string GetImpactSound(WarheadInfo warhead, bool isWater)
		{
			if (isWater && warhead.WaterImpactSound != null)
				return warhead.WaterImpactSound;

			if (warhead.ImpactSound != null)
				return warhead.ImpactSound;

			return null;
		}
Ejemplo n.º 2
0
 public static void AddSmudge(this Map map, int2 targetTile, WarheadInfo warhead)
 {
     if (warhead.SmudgeType == SmudgeType.None) return;
     if (warhead.Size[0] == 0 && warhead.Size[1] == 0)
         map.AddSmudge(warhead.SmudgeType == SmudgeType.Crater, targetTile.X, targetTile.Y);
     else
         foreach (var t in Game.world.FindTilesInCircle(targetTile, warhead.Size[0]))
             if ((t - targetTile).LengthSquared >= warhead.Size[1] * warhead.Size[1])
                 if (Rules.TerrainTypes[Game.world.GetTerrainType(t)].AcceptSmudge)
                     map.AddSmudge(warhead.SmudgeType == SmudgeType.Crater, t.X, t.Y);
 }
Ejemplo n.º 3
0
        public static void DoImpact(WarheadInfo warhead, ProjectileArgs args, int2 visualLocation)
        {
            var world = args.firedBy.World;
            var targetTile = ((1f / Game.CellSize) * args.dest.ToFloat2()).ToInt2();
            var isWater = world.GetTerrainType(targetTile) == TerrainType.Water;

            if (warhead.Explosion != 0)
                world.AddFrameEndTask(
                    w => w.Add(new Explosion(w, visualLocation, warhead.Explosion, isWater)));

            Sound.Play(GetImpactSound(warhead, isWater));

            if (!isWater) world.Map.AddSmudge(targetTile, warhead);
            if (warhead.Ore)
                world.WorldActor.traits.Get<ResourceLayer>().Destroy(targetTile);

            var firepowerModifier = args.firedBy.traits
                .WithInterface<IFirepowerModifier>()
                .Select(a => a.GetFirepowerModifier())
                .Product();

            switch (warhead.DamageModel)
            {
                case DamageModel.Normal:
                    {
                        var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2);
                        var hitActors = world.FindUnitsInCircle(args.dest, maxSpread);

                        foreach (var victim in hitActors)
                            victim.InflictDamage(args.firedBy,
                                (int)GetDamageToInflict(victim, args, warhead, firepowerModifier), warhead);
                    } break;

                case DamageModel.PerCell:
                    {
                        foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
                            foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new float2(1,1))))
                                unit.InflictDamage(args.firedBy,
                                    (int)(warhead.Damage * warhead.EffectivenessAgainst(
                                    unit.Info.Traits.Get<OwnedActorInfo>().Armor)), warhead);
                    } break;
            }
        }
Ejemplo n.º 4
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return State == PopupState.Closed ? Info.ClosedDamageMultiplier : 1f;
 }
Ejemplo n.º 5
0
        public static void DoImpact(WarheadInfo warhead, ProjectileArgs args)
        {
            var world = args.firedBy.World;
            var targetTile = Util.CellContaining(args.dest);

            if (!world.Map.IsInMap(targetTile))
                return;

            var isWater = world.GetTerrainInfo(targetTile).IsWater;
            var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion;

            if (explosionType != null)
                world.AddFrameEndTask(
                    w => w.Add(new Explosion(w, args.dest, explosionType, isWater, args.destAltitude)));

            Sound.Play(GetImpactSound(warhead, isWater), args.dest);

            if (warhead.SmudgeType != null)
            {
                var smudgeLayer = world.WorldActor.TraitsImplementing<SmudgeLayer>()
                    .FirstOrDefault(x => x.Info.Type == warhead.SmudgeType);
                if (smudgeLayer == null)
                    throw new NotImplementedException("Unknown smudge type `{0}`".F(warhead.SmudgeType));

                if (warhead.Size[0] > 0)
                {
                    var smudgeCells = world.FindTilesInCircle(targetTile, warhead.Size[0]);
                    if (warhead.Size.Length == 2 )
                        smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1])) ;

                    foreach (var sc in smudgeCells)
                    {
                        smudgeLayer.AddSmudge(sc);
                        if (warhead.Ore)
                            world.WorldActor.Trait<ResourceLayer>().Destroy(sc);
                    }
                }
                else
                    smudgeLayer.AddSmudge(targetTile);
            }

            if (warhead.Ore)
                world.WorldActor.Trait<ResourceLayer>().Destroy(targetTile);

            switch (warhead.DamageModel)
            {
                case DamageModel.Normal:
                    {
                        var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2);
                        var hitActors = world.FindUnitsInCircle(args.dest, maxSpread);

                        foreach (var victim in hitActors)
                        {
                            var damage = (int)GetDamageToInflict(victim, args, warhead, args.firepowerModifier);
                            victim.InflictDamage(args.firedBy, damage, warhead);
                        }
                    } break;

                case DamageModel.PerCell:
                    {
                        foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
                            foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new float2(1,1))))
                                unit.InflictDamage(args.firedBy,
                                    (int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead);
                    } break;
            }
        }
Ejemplo n.º 6
0
        static float GetDamageToInflict(Actor target, ProjectileArgs args, WarheadInfo warhead, float modifier)
        {
            // don't hit air units with splash from ground explosions, etc
            if (!WeaponValidForTarget(args.weapon, target)) return 0f;

            var health = target.Info.Traits.GetOrDefault<HealthInfo>();
            if( health == null ) return 0f;

            var distance = (int)Math.Max(0, (target.CenterLocation - args.dest).Length - health.Radius);
            var falloff = (float)GetDamageFalloff(distance / warhead.Spread);
            var rawDamage = (float)(warhead.Damage * modifier * falloff);
            var multiplier = (float)warhead.EffectivenessAgainst(target);

            return (float)(rawDamage * multiplier);
        }
Ejemplo n.º 7
0
		public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
		{
			return ArmorLevel > 0 ? (1 / (1 + ArmorLevel * info.ArmorModifier)) : 1;
		}
Ejemplo n.º 8
0
        public void InflictDamage(Actor attacker, int damage, WarheadInfo warhead)
        {
            if (IsDead) return;		/* overkill! don't count extra hits as more kills! */

            var oldState = GetDamageState();

            /* apply the damage modifiers, if we have any. */
            damage = (int)traits.WithInterface<IDamageModifier>().Aggregate(
                (float)damage, (a, t) => t.GetDamageModifier() * a);

            Health -= damage;
            if (Health <= 0)
            {
                Health = 0;
                if (attacker.Owner != null)
                    attacker.Owner.Kills++;

                if (RemoveOnDeath)
                    World.AddFrameEndTask(w => w.Remove(this));
            }

            var maxHP = this.GetMaxHP();

            if (Health > maxHP)	Health = maxHP;

            var newState = GetDamageState();

            foreach (var nd in traits.WithInterface<INotifyDamage>())
                nd.Damaged(this, new AttackInfo
                {
                    Attacker = attacker,
                    Damage = damage,
                    DamageState = newState,
                    DamageStateChanged = newState != oldState,
                    Warhead = warhead
                });
        }
Ejemplo n.º 9
0
        public static void DoImpact(WarheadInfo warhead, ProjectileArgs args)
        {
            var world = args.firedBy.World;
            var targetTile = args.dest.ToCPos();

            if (!world.Map.IsInMap(targetTile))
                return;

            var isWater = args.destAltitude == 0 && world.GetTerrainInfo(targetTile).IsWater;
            var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion;

            if (explosionType != null)
                world.AddFrameEndTask(
                    w => w.Add(new Explosion(w, args.dest, explosionType, isWater, args.destAltitude)));

            Sound.Play(GetImpactSound(warhead, isWater), args.dest);

            var smudgeLayers = world.WorldActor.TraitsImplementing<SmudgeLayer>().ToDictionary(x => x.Info.Type);

            if (warhead.Size[0] > 0)
            {
                var resLayer = world.WorldActor.Trait<ResourceLayer>();
                var allCells = world.FindTilesInCircle(targetTile, warhead.Size[0]).ToList();

                // `smudgeCells` might want to just be an outer shell of the cells:
                IEnumerable<CPos> smudgeCells = allCells;
                if (warhead.Size.Length == 2)
                    smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1]));

                // Draw the smudges:
                foreach (var sc in smudgeCells)
                {
                    var smudgeType = world.GetTerrainInfo(sc).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t));
                    if (smudgeType == null) continue;

                    SmudgeLayer smudgeLayer;
                    if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
                        throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));

                    smudgeLayer.AddSmudge(sc);
                    if (warhead.Ore)
                        resLayer.Destroy(sc);
                }

                // Destroy all resources in range, not just the outer shell:
                foreach (var cell in allCells)
                {
                    if (warhead.Ore)
                        resLayer.Destroy(cell);
                }
            }
            else
            {
                var smudgeType = world.GetTerrainInfo(targetTile).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t));
                if (smudgeType != null)
                {
                    SmudgeLayer smudgeLayer;
                    if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
                        throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));

                    smudgeLayer.AddSmudge(targetTile);
                }
            }

            if (warhead.Ore)
                world.WorldActor.Trait<ResourceLayer>().Destroy(targetTile);

            switch (warhead.DamageModel)
            {
                case DamageModel.Normal:
                    {
                        var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2);
                        var hitActors = world.FindUnitsInCircle(args.dest, (int)maxSpread);

                        foreach (var victim in hitActors)
                        {
                            var damage = (int)GetDamageToInflict(victim, args, warhead, args.firepowerModifier);
                            victim.InflictDamage(args.firedBy, damage, warhead);
                        }
                    } break;

                case DamageModel.PerCell:
                    {
                        foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
                            foreach (var unit in world.FindUnits(t.ToPPos(), (t + new CVec(1,1)).ToPPos()))
                                unit.InflictDamage(args.firedBy,
                                    (int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead);
                    } break;
            }
        }
Ejemplo n.º 10
0
 static float GetDamageToInflict(Actor target, ProjectileArgs args, WarheadInfo warhead, float modifier)
 {
     var selectable = target.Info.Traits.GetOrDefault<SelectableInfo>();
     var radius = selectable != null ? selectable.Radius : 0;
     var distance = Math.Max(0, (target.CenterLocation - args.dest).Length - radius);
     var rawDamage = warhead.Damage * modifier * (float)Math.Exp(-distance / warhead.Spread);
     var multiplier = warhead.EffectivenessAgainst(target.Info.Traits.Get<OwnedActorInfo>().Armor);
     return rawDamage * multiplier;
 }
Ejemplo n.º 11
0
		public static void DoImpact(WPos pos, WarheadInfo warhead, WeaponInfo weapon, Actor firedBy, float firepowerModifier)
		{
			var world = firedBy.World;
			var targetTile = world.Map.CellContaining(pos);

			if (!world.Map.Contains(targetTile))
				return;

			var isWater = pos.Z <= 0 && world.Map.GetTerrainInfo(targetTile).IsWater;
			var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion;
			var explosionTypePalette = isWater ? warhead.WaterExplosionPalette : warhead.ExplosionPalette;

			if (explosionType != null)
				world.AddFrameEndTask(w => w.Add(new Explosion(w, pos, explosionType, explosionTypePalette)));

			Sound.Play(GetImpactSound(warhead, isWater), pos);

			var smudgeLayers = world.WorldActor.TraitsImplementing<SmudgeLayer>().ToDictionary(x => x.Info.Type);
			var resLayer = warhead.DestroyResources || !string.IsNullOrEmpty(warhead.AddsResourceType) ? world.WorldActor.Trait<ResourceLayer>() : null;

			if (warhead.Size[0] > 0)
			{
				var allCells = world.Map.FindTilesInCircle(targetTile, warhead.Size[0]).ToList();

				// `smudgeCells` might want to just be an outer shell of the cells:
				IEnumerable<CPos> smudgeCells = allCells;
				if (warhead.Size.Length == 2)
					smudgeCells = smudgeCells.Except(world.Map.FindTilesInCircle(targetTile, warhead.Size[1]));

				// Draw the smudges:
				foreach (var sc in smudgeCells)
				{
					var smudgeType = world.Map.GetTerrainInfo(sc).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t));
					if (smudgeType == null) continue;

					SmudgeLayer smudgeLayer;
					if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
						throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));

					smudgeLayer.AddSmudge(sc);
					if (warhead.DestroyResources)
						resLayer.Destroy(sc);
				}

				// Destroy all resources in range, not just the outer shell:
				if (warhead.DestroyResources)
					foreach (var cell in allCells)
						resLayer.Destroy(cell);

				// Splatter resources:
				if (!string.IsNullOrEmpty(warhead.AddsResourceType))
				{
					var resourceType = world.WorldActor.TraitsImplementing<ResourceType>()
						.FirstOrDefault(t => t.Info.Name == warhead.AddsResourceType);

					if (resourceType == null)
						Log.Write("debug", "Warhead defines an invalid resource type '{0}'".F(warhead.AddsResourceType));
					else
					{
						foreach (var cell in allCells)
						{
							if (!resLayer.CanSpawnResourceAt(resourceType, cell))
								continue;

							var splash = world.SharedRandom.Next(1, resourceType.Info.MaxDensity - resLayer.GetResourceDensity(cell));
							resLayer.AddResource(resourceType, cell, splash);
						}
					}
				}
			}
			else
			{
				var smudgeType = world.Map.GetTerrainInfo(targetTile).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t));
				if (smudgeType != null)
				{
					SmudgeLayer smudgeLayer;
					if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
						throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));

					smudgeLayer.AddSmudge(targetTile);
				}
			}

			if (warhead.DestroyResources)
				world.WorldActor.Trait<ResourceLayer>().Destroy(targetTile);

			switch (warhead.DamageModel)
			{
				case DamageModel.Normal:
					{
						var maxSpread = new WRange((int)(warhead.Spread.Range * (float)Math.Log(Math.Abs(warhead.Damage), 2)));
						var hitActors = world.FindActorsInCircle(pos, maxSpread);

						foreach (var victim in hitActors)
						{
							var damage = (int)GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, true);
							victim.InflictDamage(firedBy, damage, warhead);
						}
					}
					break;

				case DamageModel.PerCell:
					{
						foreach (var t in world.Map.FindTilesInCircle(targetTile, warhead.Size[0]))
						{
							foreach (var unit in world.ActorMap.GetUnitsAt(t))
							{
								var damage = (int)GetDamageToInflict(pos, unit, warhead, weapon, firepowerModifier, false);
								unit.InflictDamage(firedBy, damage, warhead);
							}
						}
					}
					break;

				case DamageModel.HealthPercentage:
					{
						var range = new WRange(warhead.Size[0] * 1024);
						var hitActors = world.FindActorsInCircle(pos, range);

						foreach (var victim in hitActors)
						{
							var damage = GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, false);
							if (damage != 0) // will be 0 if the target doesn't have HealthInfo
							{
								var healthInfo = victim.Info.Traits.Get<HealthInfo>();
								damage = (float)(damage / 100 * healthInfo.HP);
							}

							victim.InflictDamage(firedBy, (int)damage, warhead);
						}
					}
					break;
			}
		}
Ejemplo n.º 12
0
		static float GetDamageToInflict(WPos pos, Actor target, WarheadInfo warhead, WeaponInfo weapon, float modifier, bool withFalloff)
		{
			// don't hit air units with splash from ground explosions, etc
			if (!weapon.IsValidAgainst(target))
				return 0;

			var healthInfo = target.Info.Traits.GetOrDefault<HealthInfo>();
			if (healthInfo == null)
				return 0;

			var rawDamage = (float)warhead.Damage;
			if (withFalloff)
			{
				var distance = Math.Max(0, (target.CenterPosition - pos).Length - healthInfo.Radius.Range);
				var falloff = (float)GetDamageFalloff(distance * 1f / warhead.Spread.Range);
				rawDamage = (float)(falloff * rawDamage);
			}

			return (float)(rawDamage * modifier * (float)warhead.EffectivenessAgainst(target.Info));
		}
Ejemplo n.º 13
0
        static float GetDamageToInflict(WPos pos, Actor target, WarheadInfo warhead, WeaponInfo weapon, float modifier)
        {
            // don't hit air units with splash from ground explosions, etc
            if (!weapon.IsValidAgainst(target))
                return 0f;

            var health = target.Info.Traits.GetOrDefault<HealthInfo>();
            if( health == null ) return 0f;

            var distance = (int)Math.Max(0, (target.CenterPosition - pos).Length * Game.CellSize / 1024 - health.Radius);
            var falloff = (float)GetDamageFalloff(distance / warhead.Spread);
            var rawDamage = (float)(warhead.Damage * modifier * falloff);
            var multiplier = (float)warhead.EffectivenessAgainst(target.Info);

            return (float)(rawDamage * multiplier);
        }
Ejemplo n.º 14
0
        public WeaponInfo(string name, MiniYaml content)
        {
            foreach (var kv in content.Nodes)
            {
                var key = kv.Key.Split('@')[0];
                switch (key)
                {
                    case "Range": FieldLoader.LoadField(this, "Range", content.Nodes["Range"].Value); break;
                    case "ROF": FieldLoader.LoadField(this, "ROF", content.Nodes["ROF"].Value); break;
                    case "Report": FieldLoader.LoadField(this, "Report", content.Nodes["Report"].Value); break;
                    case "Burst": FieldLoader.LoadField(this, "Burst", content.Nodes["Burst"].Value); break;
                    case "Charges": FieldLoader.LoadField(this, "Charges", content.Nodes["Charges"].Value); break;
                    case "ValidTargets": FieldLoader.LoadField(this, "ValidTargets", content.Nodes["ValidTargets"].Value); break;
                    case "Underwater": FieldLoader.LoadField(this, "Underwater", content.Nodes["Underwater"].Value); break;

                    case "Warhead":
                        {
                            var warhead = new WarheadInfo();
                            FieldLoader.Load(warhead, kv.Value);
                            Warheads.Add(warhead);
                        } break;

                    // in this case, it's an implementation of IProjectileInfo
                    default:
                        {
                            Projectile = Game.CreateObject<IProjectileInfo>(key + "Info");
                            FieldLoader.Load(Projectile, kv.Value);
                        } break;
                }
            }
        }
Ejemplo n.º 15
0
        public static void DoImpact(WPos pos, WarheadInfo warhead, WeaponInfo weapon, Actor firedBy, float firepowerModifier)
        {
            var world = firedBy.World;
            var targetTile = pos.ToCPos();

            if (!world.Map.IsInMap(targetTile))
                return;

            var isWater = pos.Z == 0 && world.GetTerrainInfo(targetTile).IsWater;
            var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion;

            if (explosionType != null)
                world.AddFrameEndTask(w => w.Add(new Explosion(w, pos, explosionType)));

            Sound.Play(GetImpactSound(warhead, isWater), pos);

            var smudgeLayers = world.WorldActor.TraitsImplementing<SmudgeLayer>().ToDictionary(x => x.Info.Type);

            if (warhead.Size[0] > 0)
            {
                var resLayer = world.WorldActor.Trait<ResourceLayer>();
                var allCells = world.FindTilesInCircle(targetTile, warhead.Size[0]).ToList();

                // `smudgeCells` might want to just be an outer shell of the cells:
                IEnumerable<CPos> smudgeCells = allCells;
                if (warhead.Size.Length == 2)
                    smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1]));

                // Draw the smudges:
                foreach (var sc in smudgeCells)
                {
                    var smudgeType = world.GetTerrainInfo(sc).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t));
                    if (smudgeType == null) continue;

                    SmudgeLayer smudgeLayer;
                    if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
                        throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));

                    smudgeLayer.AddSmudge(sc);
                    if (warhead.Ore)
                        resLayer.Destroy(sc);
                }

                // Destroy all resources in range, not just the outer shell:
                foreach (var cell in allCells)
                {
                    if (warhead.Ore)
                        resLayer.Destroy(cell);
                }
            }
            else
            {
                var smudgeType = world.GetTerrainInfo(targetTile).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t));
                if (smudgeType != null)
                {
                    SmudgeLayer smudgeLayer;
                    if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
                        throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));

                    smudgeLayer.AddSmudge(targetTile);
                }
            }

            if (warhead.Ore)
                world.WorldActor.Trait<ResourceLayer>().Destroy(targetTile);

            switch (warhead.DamageModel)
            {
                case DamageModel.Normal:
                    {
                        var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2);
                        var range = new WRange((int)maxSpread * 1024 / Game.CellSize);
                        var hitActors = world.FindActorsInCircle(pos, range);

                        foreach (var victim in hitActors)
                        {
                            var damage = (int)GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, true);
                            victim.InflictDamage(firedBy, damage, warhead);
                        }
                    } break;

                case DamageModel.PerCell:
                    {
                        foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
                            foreach (var unit in world.ActorMap.GetUnitsAt(t))
                            {
                                var damage = (int)GetDamageToInflict(pos, unit, warhead, weapon, firepowerModifier, false);
                                unit.InflictDamage(firedBy, damage, warhead);
                            }
                    } break;

                case DamageModel.HealthPercentage:
                    {
                        var range = new WRange(warhead.Size[0] * 1024);
                        var hitActors = world.FindActorsInCircle(pos, range);

                        foreach (var victim in hitActors)
                        {
                            var damage = GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, false);
                            if (damage != 0) // will be 0 if the target doesn't have HealthInfo
                            {
                                var healthInfo = victim.Info.Traits.Get<HealthInfo>();
                                damage = (float)(damage / 100 * healthInfo.HP);
                            }
                            victim.InflictDamage(firedBy, (int)damage, warhead);
                        }
                    } break;
            }
        }