Exemple #1
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 = (int)Math.Max(0, (target.CenterPosition - pos).Length * Game.CellSize / 1024 - healthInfo.Radius);
                var falloff  = (float)GetDamageFalloff(distance / warhead.Spread);
                rawDamage = (float)(falloff * rawDamage);
            }
            return((float)(rawDamage * modifier * (float)warhead.EffectivenessAgainst(target.Info)));
        }
Exemple #2
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));
        }
Exemple #3
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;
            }
        }
Exemple #4
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       = 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);

            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, (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(Game.CellSize * t, Game.CellSize * (t + new int2(1, 1))))
                    {
                        unit.InflictDamage(args.firedBy,
                                           (int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead);
                    }
                }
            } break;
            }
        }