Example #1
0
        public NukeLaunch(Player firedBy, string name, WeaponInfo weapon, string weaponPalette, string upSequence, string downSequence,
			WPos launchPos, WPos targetPos, WDist velocity, int delay, bool skipAscent, string flashType)
        {
            this.firedBy = firedBy;
            this.weapon = weapon;
            this.weaponPalette = weaponPalette;
            this.downSequence = downSequence;
            this.delay = delay;
            turn = delay / 2;
            this.flashType = flashType;

            var offset = new WVec(WDist.Zero, WDist.Zero, velocity * turn);
            ascendSource = launchPos;
            ascendTarget = launchPos + offset;
            descendSource = targetPos + offset;
            descendTarget = targetPos;

            anim = new Animation(firedBy.World, name);
            anim.PlayRepeating(upSequence);

            pos = launchPos;
            if (weapon.Report != null && weapon.Report.Any())
                Game.Sound.Play(weapon.Report.Random(firedBy.World.SharedRandom), pos);

            if (skipAscent)
                ticks = turn;
        }
Example #2
0
		public IonCannon(Player firedBy, WeaponInfo weapon, World world, CPos location, string effect, string palette, int delay)
		{
			this.firedBy = firedBy;
			this.weapon = weapon;
			this.palette = palette;
			weaponDelay = delay;
			target = Target.FromCell(world, location);
			anim = new Animation(world, effect);
			anim.PlayThen("idle", () => Finish(world));
		}
Example #3
0
 public SwallowActor(Actor self, Target target, WeaponInfo weapon)
 {
     this.target = target;
     this.weapon = weapon;
     sandworm = self.Trait<Sandworm>();
     positionable = self.Trait<Mobile>();
     swallow = self.Trait<AttackSwallow>();
     manager = self.Trait<UpgradeManager>();
     radarPings = self.World.WorldActor.TraitOrDefault<RadarPings>();
 }
Example #4
0
        public IonCannon(Player firedBy, WeaponInfo weapon, World world, WPos launchPos, CPos location, string effect, string sequence, string palette, int delay)
        {
            this.firedBy = firedBy;
            this.weapon = weapon;
            this.palette = palette;
            weaponDelay = delay;
            target = Target.FromCell(world, location);
            anim = new Animation(world, effect);
            anim.PlayThen(sequence, () => Finish(world));

            if (weapon.Report != null && weapon.Report.Any())
                Game.Sound.Play(SoundType.World, weapon.Report.Random(firedBy.World.SharedRandom), launchPos);
        }
Example #5
0
		public SwallowActor(Actor self, Target target, WeaponInfo weapon)
		{
			this.target = target;
			this.weapon = weapon;
			sandworm = self.Trait<Sandworm>();
			positionable = self.Trait<Mobile>();
			swallow = self.Trait<AttackSwallow>();
			withSpriteBody = self.Trait<WithSpriteBody>();
			radarPings = self.World.WorldActor.TraitOrDefault<RadarPings>();
			countdown = swallow.Info.AttackTime;

			withSpriteBody.DefaultAnimation.ReplaceAnim(sandworm.Info.BurrowedSequence);
			stance = AttackState.Burrowed;
			location = target.Actor.Location;
		}
Example #6
0
        public SwallowActor(Actor self, Target target, WeaponInfo weapon)
        {
            this.target = target;
            this.weapon = weapon;
            sandworm = self.Trait<Sandworm>();
            positionable = self.Trait<Mobile>();
            swallow = self.Trait<AttackSwallow>();
            renderUnit = self.Trait<RenderUnit>();
            radarPings = self.World.WorldActor.TraitOrDefault<RadarPings>();
            countdown = swallow.Info.AttackTime;

            renderUnit.DefaultAnimation.ReplaceAnim("burrowed");
            stance = AttackState.Burrowed;
            location = target.Actor.Location;
        }
Example #7
0
        public Turret Turret; // where this weapon is mounted -- possibly shared

        #endregion Fields

        #region Constructors

        public Weapon(string weaponName, Turret turret, int[] localOffset)
        {
            Info = Rules.Weapons[weaponName.ToLowerInvariant()];
            Burst = Info.Burst;
            Turret = turret;

            var barrels = new List<Barrel>();
            for (var i = 0; i < localOffset.Length / 3; i++)
                barrels.Add(new Barrel
                {
                    Position = new int2(localOffset[3 * i], localOffset[3 * i + 1]),
                    Facing = localOffset[3 * i + 2]
                });

            // if no barrels specified, the default is "turret position; turret facing".
            if (barrels.Count == 0)
                barrels.Add(new Barrel { Position = int2.Zero, Facing = 0 });

            Barrels = barrels.ToArray();
        }
Example #8
0
        public Leap(Actor self, Actor target, WeaponInfo weapon, WRange speed, WAngle angle)
        {
            var targetMobile = target.TraitOrDefault<Mobile>();
            if (targetMobile == null)
                throw new InvalidOperationException("Leap requires a target actor with the Mobile trait");

            this.weapon = weapon;
            this.angle = angle;
            mobile = self.Trait<Mobile>();
            mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, targetMobile.fromCell, targetMobile.fromSubCell);
            mobile.IsMoving = true;

            from = self.CenterPosition;
            to = targetMobile.fromCell.CenterPosition + MobileInfo.SubCellOffsets[targetMobile.fromSubCell];
            length = Math.Max((to - from).Length / speed.Range, 1);

            self.Trait<RenderInfantry>().Attacking(self, Target.FromActor(target));

            if (weapon.Report != null && weapon.Report.Any())
                Sound.Play(weapon.Report.Random(self.World.SharedRandom), self.CenterPosition);
        }
Example #9
0
        public Turret Turret; // where this weapon is mounted -- possibly shared

        #endregion Fields

        #region Constructors

        public Weapon(string weaponName, Turret turret, int[] localOffset, int recoil)
        {
            Info = Rules.Weapons[weaponName.ToLowerInvariant()];
            Burst = Info.Burst;
            Turret = turret;
            Recoil = recoil;

            var barrels = new List<Barrel>();
            for (var i = 0; i < localOffset.Length / 5; i++)
                barrels.Add(new Barrel
                {
                    TurretSpaceOffset = new PVecInt(localOffset[5 * i], localOffset[5 * i + 1]),
                    ScreenSpaceOffset = new PVecInt(localOffset[5 * i + 2], localOffset[5 * i + 3]),
                    Facing = localOffset[5 * i + 4]
                });

            // if no barrels specified, the default is "turret position; turret facing".
            if (barrels.Count == 0)
                barrels.Add(new Barrel { TurretSpaceOffset = PVecInt.Zero, ScreenSpaceOffset = PVecInt.Zero, Facing = 0 });

            Barrels = barrels.ToArray();
        }
Example #10
0
        public Leap(Actor self, Actor target, WeaponInfo weapon, WDist speed, WAngle angle)
        {
            var targetMobile = target.TraitOrDefault<Mobile>();
            if (targetMobile == null)
                throw new InvalidOperationException("Leap requires a target actor with the Mobile trait");

            this.weapon = weapon;
            this.angle = angle;
            mobile = self.Trait<Mobile>();
            mobile.SetLocation(mobile.FromCell, mobile.FromSubCell, targetMobile.FromCell, targetMobile.FromSubCell);
            mobile.IsMoving = true;

            from = self.CenterPosition;
            to = self.World.Map.CenterOfSubCell(targetMobile.FromCell, targetMobile.FromSubCell);
            length = Math.Max((to - from).Length / speed.Length, 1);

            // HACK: why isn't this using the interface?
            self.Trait<WithInfantryBody>().Attacking(self, Target.FromActor(target));

            if (weapon.Report != null && weapon.Report.Any())
                Sound.Play(weapon.Report.Random(self.World.SharedRandom), self.CenterPosition);
        }
Example #11
0
        public static bool WeaponValidForTarget(WeaponInfo weapon, Target target)
        {
            // todo: fix this properly.
            if (!target.IsValid) return false;
            if (!target.IsActor) return weapon.ValidTargets.Contains("Ground") // hack!
                || (weapon.ValidTargets.Contains("Water") &&
                    Game.world.GetTerrainType(Util.CellContaining(target.CenterLocation)) == "Water"); // even bigger hack!

            var targetable = target.Actor.TraitOrDefault<ITargetable>();
            if (targetable == null || !weapon.ValidTargets.Intersect(targetable.TargetTypes).Any())
                return false;

            if (weapon.Warheads.All( w => w.EffectivenessAgainst(target.Actor) <= 0))
                return false;

            return true;
        }
Example #12
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);
        }
Example #13
0
		public void RulesetLoaded(Ruleset rules, ActorInfo ai)
		{
			ExplosionWeapon = string.IsNullOrEmpty(Explosion) ? null : rules.Weapons[Explosion.ToLowerInvariant()];
		}
Example #14
0
 public static bool WeaponValidForTarget( WeaponInfo weapon, World world, int2 location )
 {
     if( weapon.ValidTargets.Contains( "Ground" ) && world.GetTerrainType( location ) != "Water" ) return true;
     if( weapon.ValidTargets.Contains( "Water" ) && world.GetTerrainType( location ) == "Water" ) return true;
     return false;
 }
Example #15
0
        public static bool WeaponValidForTarget(WeaponInfo weapon, Actor target)
        {
            var targetable = target.TraitOrDefault<ITargetable>();
            if (targetable == null || !weapon.ValidTargets.Intersect(targetable.TargetTypes).Any())
                return false;

            if (weapon.Warheads.All( w => w.EffectivenessAgainst(target) <= 0))
                return false;

            return true;
        }
Example #16
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);
                            victim.InflictDamage(firedBy, damage, warhead);
                        }
                    } break;

                case DamageModel.PerCell:
                    {
                        foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0]))
                            foreach (var unit in world.FindActorsInBox(t, t))
                                unit.InflictDamage(firedBy,
                                    (int)(warhead.Damage * warhead.EffectivenessAgainst(unit.Info)), warhead);
                    } break;
            }
        }
Example #17
0
		public static void DoImpacts(WPos pos, Actor firedBy, WeaponInfo weapon, float damageModifier)
		{
			foreach (var wh in weapon.Warheads)
			{
				var warhead = wh;
				Action a = () => DoImpact(pos, warhead, weapon, firedBy, damageModifier);

				if (warhead.Delay > 0)
					firedBy.World.AddFrameEndTask(
						w => w.Add(new DelayedAction(warhead.Delay, a)));
				else
					a();
			}
		}
Example #18
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));
		}
Example #19
0
 public void RulesetLoaded(Ruleset rules, ActorInfo ai)
 {
     WeaponInfo = rules.Weapons[Weapon.ToLowerInvariant()];
 }
Example #20
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;
			}
		}
Example #21
0
        public static bool WeaponValidForTarget(WeaponInfo weapon, Actor target)
        {
            var ownedInfo = target.Info.Traits.GetOrDefault<OwnedActorInfo>();

            if (!weapon.ValidTargets.Contains(ownedInfo.TargetType))
                return false;

            if (weapon.Warheads.All( w => w.EffectivenessAgainst(ownedInfo.Armor) <= 0))
                return false;

            if (weapon.Underwater && !ownedInfo.WaterBound)
                return false;

            return true;
        }