Ejemplo n.º 1
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.º 2
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.º 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;
            }
        }
Ejemplo n.º 4
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.º 5
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.º 6
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.º 7
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);
        }