protected override void DoImpact(WPos pos, Actor firedBy, WarheadArgs args)
        {
            var world = firedBy.World;

            if (world.LocalPlayer != null)
            {
                var devMode = world.LocalPlayer.PlayerActor.TraitOrDefault <DebugVisualizations>();
                if (devMode != null && devMode.CombatGeometry)
                {
                    WDist[] rng = Exts.MakeArray(Range.Length, i => WDist.FromCells(Range[i].Length));
                    world.WorldActor.Trait <WarheadDebugOverlay>().AddImpact(pos, rng, DebugOverlayColor);
                }
            }

            var targetTile = world.Map.CellContaining(pos);

            for (var i = 0; i < Range.Length; i++)
            {
                var affectedCells = world.Map.FindTilesInCircle(targetTile, (int)Math.Ceiling((decimal)Range[i].Length / 1024));

                var raLayer = world.WorldActor.TraitsImplementing <TintedCellsLayer>()
                              .First(l => l.Info.Name == LayerName);

                foreach (var cell in affectedCells)
                {
                    int mul = GetIntensityFalloff((pos - world.Map.CenterOfCell(cell)).Length);
                    IncreaseTintedCellLevel(cell, mul, Falloff[i], raLayer);
                }
            }
        }
Пример #2
0
        public override void DoImpact(Target target, WarheadArgs args)
        {
            var firedBy = args.SourceActor;
            var actors  = target.Type == TargetType.Actor ? new[] { target.Actor } :
            firedBy.World.FindActorsInCircle(target.CenterPosition, Range);

            foreach (var a in actors)
            {
                // Don't do anything on friendly fire
                if (a.Owner == firedBy.Owner)
                {
                    continue;
                }

                if (Duration == 0)
                {
                    a.ChangeOwner(firedBy.Owner);                     // Permanent
                }
                else
                {
                    var tempOwnerManager = a.TraitOrDefault <TemporaryOwnerManager>();
                    if (tempOwnerManager == null)
                    {
                        continue;
                    }

                    tempOwnerManager.ChangeOwner(a, firedBy.Owner, Duration);
                }

                // Stop shooting, you have new enemies
                a.CancelActivity();
            }
        }
Пример #3
0
        // TODO: Allow maximum resource removal to be defined. (Per tile, and in total).
        public override void DoImpact(Target target, WarheadArgs args)
        {
            if (target.Type == TargetType.Invalid)
            {
                return;
            }

            var firedBy = args.SourceActor;
            var pos     = target.CenterPosition;
            var world   = firedBy.World;
            var dat     = world.Map.DistanceAboveTerrain(pos);

            if (dat > AirThreshold)
            {
                return;
            }

            var targetTile = world.Map.CellContaining(pos);
            var resLayer   = world.WorldActor.Trait <ResourceLayer>();

            var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0;
            var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]);

            // Destroy all resources in the selected tiles
            foreach (var cell in allCells)
            {
                resLayer.Destroy(cell);
            }
        }
Пример #4
0
        void Explode(World world, bool removeProjectile)
        {
            if (removeProjectile)
            {
                world.AddFrameEndTask(w => { w.Remove(this); w.ScreenMap.Remove(this); });
            }

            if (detonated)
            {
                return;
            }

            var target      = Target.FromPos(pos);
            var warheadArgs = new WarheadArgs
            {
                Weapon       = weapon,
                Source       = target.CenterPosition,
                SourceActor  = firedBy.PlayerActor,
                WeaponTarget = target
            };

            weapon.Impact(target, warheadArgs);

            detonated = true;
        }
Пример #5
0
        public void Tick(World world)
        {
            lastPos   = pos;
            pos      += velocity;
            velocity += acceleration;

            if (pos.Z <= args.PassiveTarget.Z)
            {
                pos += new WVec(0, 0, args.PassiveTarget.Z - pos.Z);
                world.AddFrameEndTask(w => w.Remove(this));

                var warheadArgs = new WarheadArgs(args)
                {
                    ImpactOrientation = new WRot(WAngle.Zero, Util.GetVerticalAngle(lastPos, pos), args.Facing),
                    ImpactPosition    = pos,
                };

                args.Weapon.Impact(Target.FromPos(pos), warheadArgs);
            }

            if (anim != null)
            {
                anim.Tick();
            }
        }
Пример #6
0
        void Explode(World world, bool removeProjectile)
        {
            if (removeProjectile)
            {
                world.AddFrameEndTask(w => { w.Remove(this); w.ScreenMap.Remove(this); });
            }

            if (detonated)
            {
                return;
            }

            var target      = Target.FromPos(pos);
            var warheadArgs = new WarheadArgs
            {
                Weapon       = weapon,
                Source       = target.CenterPosition,
                SourceActor  = firedBy.PlayerActor,
                WeaponTarget = target
            };

            weapon.Impact(target, warheadArgs);

            foreach (var flash in world.WorldActor.TraitsImplementing <FlashPaletteEffect>())
            {
                if (flash.Info.Type == flashType)
                {
                    flash.Enable(-1);
                }
            }

            detonated = true;
        }
Пример #7
0
        public override void DoImpact(Target target, WarheadArgs args)
        {
            var firedBy = args.SourceActor;

            // Used by traits or warheads that damage a single actor, rather than a position
            if (target.Type == TargetType.Actor)
            {
                var victim = target.Actor;

                if (!IsValidAgainst(victim, firedBy))
                {
                    return;
                }

                var closestActiveShape = victim.TraitsImplementing <HitShape>().Where(Exts.IsTraitEnabled)
                                         .MinByOrDefault(t => t.DistanceFromEdge(victim, victim.CenterPosition));

                // Cannot be damaged without an active HitShape
                if (closestActiveShape == null)
                {
                    return;
                }

                InflictDamage(victim, firedBy, closestActiveShape.Info, args.DamageModifiers);
            }
            else if (target.Type != TargetType.Invalid)
            {
                DoImpact(target.CenterPosition, firedBy, args.DamageModifiers);
            }
        }
Пример #8
0
        public override void DoImpact(Target target, WarheadArgs args)
        {
            var firedBy = args.SourceActor;
            var actors  = target.Type == TargetType.Actor ? new[] { target.Actor } :
            firedBy.World.FindActorsInCircle(target.CenterPosition, Range);

            foreach (var a in actors)
            {
                // Don't do anything on friendly fire
                if (a.Owner == firedBy.Owner)
                {
                    continue;
                }

                if (!target.IsValidFor(firedBy))
                {
                    return;
                }

                if (!IsValidAgainst(a, firedBy))
                {
                    continue;
                }

                a.ChangeOwner(a.World.Players.First(p => p.InternalName == Owner));                 // Permanent

                // Stop shooting, you have new enemies
                a.CancelActivity();
            }
        }
Пример #9
0
 public DelayedImpact(int delay, IWarhead wh, Target target, WarheadArgs args)
 {
     this.wh     = wh;
     this.delay  = delay;
     this.target = target;
     this.args   = args;
 }
Пример #10
0
        public void Tick(World world)
        {
            // Check for blocking actors
            WPos blockedPos;

            if (info.Blockable)
            {
                // If GuidedTarget has become invalid due to getting killed the same tick,
                // we need to set target to args.PassiveTarget to prevent target.CenterPosition below from crashing.
                // The warheads have target validity checks themselves so they don't need this, but AnyBlockingActorsBetween does.
                if (target.Type == TargetType.Invalid)
                {
                    target = Target.FromPos(args.PassiveTarget);
                }

                if (BlocksProjectiles.AnyBlockingActorsBetween(world, args.Source, target.CenterPosition,
                                                               info.Width, out blockedPos))
                {
                    target = Target.FromPos(blockedPos);
                }
            }

            var warheadArgs = new WarheadArgs(args)
            {
                ImpactOrientation = new WRot(WAngle.Zero, Util.GetVerticalAngle(args.Source, target.CenterPosition), args.Facing),
                ImpactPosition    = target.CenterPosition,
            };

            args.Weapon.Impact(target, warheadArgs);
            world.AddFrameEndTask(w => w.Remove(this));
        }
Пример #11
0
        void ITick.Tick(Actor self)
        {
            if (IsTraitDisabled)
            {
                return;
            }

            var density = info.Density.Length == 2
                                ? world.SharedRandom.Next(info.Density[0], info.Density[1])
                                : info.Density[0];

            var weapons = mapsize * density / 1000;
            var firer   = info.Enemy ? world.Players.First(x => x.PlayerName == info.Owner).PlayerActor : world.WorldActor;

            for (var i = 0; i < weapons; i++)
            {
                var tpos = world.Map.CenterOfCell(world.Map.ChooseRandomCell(world.SharedRandom))
                           + new WVec(WDist.Zero, WDist.Zero, info.Altitude);

                var args = new WarheadArgs
                {
                    Weapon       = info.WeaponInfo,
                    Source       = tpos,
                    SourceActor  = firer,
                    WeaponTarget = Target.FromPos(tpos)
                };

                info.WeaponInfo.Impact(Target.FromPos(tpos), args);
            }
        }
Пример #12
0
        public override void DoImpact(Target target, WarheadArgs args)
        {
            if (target.Type == TargetType.Invalid)
            {
                return;
            }

            var firedBy    = args.SourceActor;
            var map        = firedBy.World.Map;
            var targetCell = map.CellContaining(target.CenterPosition);

            var targetCells = CellsMatching(targetCell, false);

            foreach (var c in targetCells)
            {
                FireProjectileAtCell(map, firedBy, target, c, args);
            }

            if (RandomClusterCount != 0)
            {
                var randomTargetCells = CellsMatching(targetCell, true);
                var clusterCount      = RandomClusterCount < 0 ? randomTargetCells.Count() : RandomClusterCount;
                if (randomTargetCells.Any())
                {
                    for (var i = 0; i < clusterCount; i++)
                    {
                        FireProjectileAtCell(map, firedBy, target, randomTargetCells.Random(firedBy.World.SharedRandom), args);
                    }
                }
            }
        }
Пример #13
0
        public void Tick(World world)
        {
            if (--delay < 0)
            {
                WPos target;
                if (args.GuidedTarget.IsValidFor(args.SourceActor))
                {
                    target = args.GuidedTarget.CenterPosition + new WVec(WDist.Zero, WDist.Zero, altitude);
                }
                else
                {
                    target = args.PassiveTarget + new WVec(WDist.Zero, WDist.Zero, altitude);
                }

                world.AddFrameEndTask(w => w.Remove(this));

                var warheadArgs = new WarheadArgs(args)
                {
                    ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(args.Source, target), args.CurrentMuzzleFacing()),
                    ImpactPosition    = target,
                };

                args.Weapon.Impact(Target.FromPos(target), warheadArgs);
            }
        }
Пример #14
0
        public void Tick(World world)
        {
            if (!exploded)
            {
                lastPos   = pos;
                pos      += velocity;
                velocity += acceleration;

                if (pos.Z <= args.PassiveTarget.Z)
                {
                    pos += new WVec(0, 0, args.PassiveTarget.Z - pos.Z);

                    var warheadArgs = new WarheadArgs(args)
                    {
                        ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(lastPos, pos), args.Facing),
                        ImpactPosition    = pos,
                    };

                    args.Weapon.Impact(Target.FromPos(pos), warheadArgs);
                    exploded = true;

                    if (!string.IsNullOrEmpty(info.ParachuteClosingSequence))
                    {
                        parachute.PlayThen(info.ParachuteClosingSequence, () => world.AddFrameEndTask(w => w.Remove(this)));
                    }
                    else
                    {
                        parachute.PlayBackwardsThen(info.ParachuteOpeningSequence, () => world.AddFrameEndTask(w => w.Remove(this)));
                    }
                }

                if (!exploded && !string.IsNullOrEmpty(info.PointDefenseType))
                {
                    var shouldExplode = world.ActorsWithTrait <IPointDefense>().Any(x => x.Trait.Destroy(pos, args.SourceActor.Owner, info.PointDefenseType));
                    if (shouldExplode)
                    {
                        var warheadArgs = new WarheadArgs(args)
                        {
                            ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(lastPos, pos), args.Facing),
                            ImpactPosition    = pos,
                        };

                        args.Weapon.Impact(Target.FromPos(pos), warheadArgs);
                        exploded = true;
                        world.AddFrameEndTask(w => w.Remove(this));
                    }
                }

                if (anim != null)
                {
                    anim.Tick();
                }
            }

            if (parachute != null)
            {
                parachute.Tick();
            }
        }
Пример #15
0
        public override void DoImpact(Target target, WarheadArgs args)
        {
            var firedBy = args.SourceActor;

            if (!target.IsValidFor(firedBy))
            {
                return;
            }

            var map        = firedBy.World.Map;
            var targetCell = map.CellContaining(target.CenterPosition);

            var targetCells = map.FindTilesInCircle(targetCell, Range);
            var cell        = targetCells.GetEnumerator();

            foreach (var a in Actors)
            {
                var td = new TypeDictionary();
                var ai = map.Rules.Actors[a.ToLowerInvariant()];

                td.Add(new OwnerInit(firedBy.World.Players.First(p => p.InternalName == InternalOwner)));

                while (cell.MoveNext())
                {
                    if (!firedBy.World.ActorMap.GetActorsAt(cell.Current).Any() && TerrainTypes.Contains(firedBy.World.Map.GetTerrainInfo(cell.Current).Type))
                    {
                        td.Add(new LocationInit(cell.Current));
                        var unit = firedBy.World.CreateActor(false, a.ToLowerInvariant(), td);

                        firedBy.World.AddFrameEndTask(w =>
                        {
                            w.Add(unit);

                            var palette = Palette;
                            if (UsePlayerPalette)
                            {
                                palette += unit.Owner.InternalName;
                            }

                            var spawn = firedBy.World.Map.CenterOfCell(cell.Current);

                            if (Image != null)
                            {
                                w.Add(new SpriteEffect(spawn, w, Image, Sequence, palette));
                            }

                            var sound = Sounds.RandomOrDefault(firedBy.World.LocalRandom);
                            if (sound != null)
                            {
                                Game.Sound.Play(SoundType.World, sound, spawn);
                            }
                        });

                        break;
                    }
                }
            }
        }
Пример #16
0
        protected override void DoImpact(WPos pos, Actor firedBy, WarheadArgs args)
        {
            var debugVis = firedBy.World.WorldActor.TraitOrDefault <DebugVisualizations>();

            if (debugVis != null && debugVis.CombatGeometry)
            {
                firedBy.World.WorldActor.Trait <WarheadDebugOverlay>().AddImpact(pos, Range, DebugOverlayColor);
            }

            foreach (var victim in firedBy.World.FindActorsOnCircle(pos, Range[Range.Length - 1]))
            {
                if (!IsValidAgainst(victim, firedBy))
                {
                    continue;
                }

                var closestActiveShape = victim.TraitsImplementing <HitShape>()
                                         .Where(Exts.IsTraitEnabled)
                                         .Select(s => Pair.New(s, s.DistanceFromEdge(victim, pos)))
                                         .MinByOrDefault(s => s.Second);

                // Cannot be damaged without an active HitShape.
                if (closestActiveShape.First == null)
                {
                    continue;
                }

                var falloffDistance = 0;
                switch (DamageCalculationType)
                {
                case DamageCalculationType.HitShape:
                    falloffDistance = closestActiveShape.Second.Length;
                    break;

                case DamageCalculationType.ClosestTargetablePosition:
                    falloffDistance = victim.GetTargetablePositions().Select(x => (x - pos).Length).Min();
                    break;

                case DamageCalculationType.CenterPosition:
                    falloffDistance = (victim.CenterPosition - pos).Length;
                    break;
                }

                // The range to target is more than the range the warhead covers, so GetDamageFalloff() is going to give us 0 and we're going to do 0 damage anyway, so bail early.
                if (falloffDistance > Range[Range.Length - 1].Length)
                {
                    continue;
                }

                var localModifiers     = args.DamageModifiers.Append(GetDamageFalloff(falloffDistance));
                var updatedWarheadArgs = new WarheadArgs(args)
                {
                    DamageModifiers = localModifiers.ToArray(),
                };

                InflictDamage(victim, firedBy, closestActiveShape.First, updatedWarheadArgs);
            }
        }
Пример #17
0
        protected override void DoImpact(WPos pos, Actor firedBy, WarheadArgs args)
        {
            if (Spread == WDist.Zero)
            {
                return;
            }

            var debugVis = firedBy.World.WorldActor.TraitOrDefault <DebugVisualizations>();

            if (debugVis != null && debugVis.CombatGeometry)
            {
                firedBy.World.WorldActor.Trait <WarheadDebugOverlay>().AddImpact(pos, new[] { WDist.Zero, Spread }, DebugOverlayColor);
            }

            foreach (var victim in firedBy.World.FindActorsOnCircle(pos, Spread))
            {
                if (!IsValidAgainst(victim, firedBy))
                {
                    continue;
                }

                var closestActiveShape = victim.TraitsImplementing <HitShape>()
                                         .Where(Exts.IsTraitEnabled)
                                         .Select(s => Pair.New(s, s.DistanceFromEdge(victim, pos)))
                                         .MinByOrDefault(s => s.Second);

                // Cannot be damaged without an active HitShape or if HitShape is outside Spread
                if (closestActiveShape.First == null || closestActiveShape.Second > Spread)
                {
                    continue;
                }

                var building = victim.TraitOrDefault <Building>();

                var adjustedDamageModifiers = args.DamageModifiers.Append(DamageVersus(victim, closestActiveShape.First, args));

                if (MaxAffect > 0 && building != null)
                {
                    var affectedcells = building.OccupiedCells().Select(x => (pos - firedBy.World.Map.CenterOfCell(x.First)).Length)
                                        .Where(x => x > Spread.Length).OrderBy(x => x).Take(MaxAffect);

                    var delivereddamage = 0;

                    foreach (var c in affectedcells)
                    {
                        delivereddamage += Util.ApplyPercentageModifiers(Damage, adjustedDamageModifiers.Append(int2.Lerp(PercentAtMax, 100, c, Spread.Length)));
                    }

                    victim.InflictDamage(firedBy, new Damage(delivereddamage, DamageTypes));
                }
                else
                {
                    var damage = Util.ApplyPercentageModifiers(Damage,
                                                               adjustedDamageModifiers.Append(int2.Lerp(PercentAtMax, 100, closestActiveShape.Second.Length, Spread.Length)));
                    victim.InflictDamage(firedBy, new Damage(damage, DamageTypes));
                }
            }
        }
        public override void DoImpact(Target target, WarheadArgs args)
        {
            var firedBy = args.SourceActor;

            if (!target.IsValidFor(firedBy))
            {
                return;
            }

            var map        = firedBy.World.Map;
            var targetCell = map.CellContaining(target.CenterPosition);

            if (!IsValidImpact(target.CenterPosition, firedBy))
            {
                return;
            }

            var targetCells = map.FindTilesInCircle(targetCell, Range);
            var cell        = targetCells.GetEnumerator();

            foreach (var passenger in args.SourceActor.TraitOrDefault <Cargo>().Passengers)
            {
                var a = passenger.Info.Name;
                //var placed = false;
                var td = new TypeDictionary();
                var ai = map.Rules.Actors[a.ToLowerInvariant()];

                if (OwnerType == ASOwnerType.Attacker)
                {
                    td.Add(new OwnerInit(firedBy.Owner));
                }
                else
                {
                    td.Add(new OwnerInit(firedBy.World.Players.First(p => p.InternalName == InternalOwner)));
                }


                firedBy.World.AddFrameEndTask(w =>
                {
                    firedBy.TraitOrDefault <ProductionCA>().Produce(firedBy, passenger.Info, firedBy.TraitOrDefault <ProductionCA>().Info.Produces[0], td, unit => {
                        //Game.Debug(String.Join("; ", firedBy.TraitOrDefault<Production>() ));

                        if (passenger.TraitOrDefault <Cargo>() != null)
                        {
                            foreach (var p in passenger.TraitOrDefault <Cargo>().Passengers)
                            {
                                //Game.Debug(String.Join("; ", passenger.TraitOrDefault<Cargo>().Passengers));
                                //Game.Debug(p.Info.Name);

                                var newPassenger = firedBy.World.CreateActor(false, p.Info.Name, td);
                                unit.TraitOrDefault <Cargo>().Load(unit, newPassenger);
                            }
                        }
                    });
                });
            }
        }
Пример #19
0
 public override void DoImpact(Target target, WarheadArgs args)
 {
     foreach (var flash in args.SourceActor.World.WorldActor.TraitsImplementing <FlashPaletteEffect>())
     {
         if (flash.Info.Type == FlashType)
         {
             flash.Enable(Duration);
         }
     }
 }
 public DelayedWeaponTrigger(AttachDelayedWeaponWarhead warhead, WarheadArgs args)
 {
     this.args     = args;
     TriggerTime   = warhead.TriggerTime;
     RemainingTime = TriggerTime;
     DeathTypes    = warhead.DeathTypes;
     weaponInfo    = warhead.WeaponInfo;
     AttachedBy    = args.SourceActor;
     IsValid       = true;
 }
Пример #21
0
        public void Impact()
        {
            var pos         = forceToGround ? projectilepos - new WVec(0, 0, world.Map.DistanceAboveTerrain(projectilepos).Length) : projectilepos;
            var warheadArgs = new WarheadArgs(args)
            {
                ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(lastPos, projectilepos), args.Facing),
                ImpactPosition    = pos,
            };

            args.Weapon.Impact(Target.FromPos(pos), warheadArgs);
        }
Пример #22
0
        public override void DoImpact(Target target, WarheadArgs args)
        {
            if (target.Type == TargetType.Invalid)
            {
                return;
            }

            var firedBy = args.SourceActor;
            var world   = firedBy.World;

            if (Chance < world.LocalRandom.Next(100))
            {
                return;
            }

            var pos = target.CenterPosition;
            var dat = world.Map.DistanceAboveTerrain(pos);

            if (dat > AirThreshold)
            {
                return;
            }

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

            var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0;
            var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]);

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

                var cellActors = world.ActorMap.GetActorsAt(sc);
                if (cellActors.Any(a => !IsValidAgainst(a, firedBy)))
                {
                    continue;
                }

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

                smudgeLayer.AddSmudge(sc);
            }
        }
        public void Tick(World world)
        {
            if (ticks == 0)
            {
                if (hitanim != null)
                {
                    hitanim.PlayThen(info.HitAnimSequence, () => animationComplete = true);
                }
                else
                {
                    animationComplete = true;
                }

                if (info.LineWidth.Length > 0)
                {
                    var actors = world.FindActorsOnLine(args.Source, target, info.LineWidth);
                    foreach (var a in actors)
                    {
                        var warheadArgs = new WarheadArgs(args)
                        {
                            ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(args.Source, target), args.Facing),

                            // Calculating an impact position is bogus for line damage.
                            // FindActorsOnLine guarantees that the beam touches the target's HitShape,
                            // so we just assume a center hit to avoid bogus warhead recalculations.
                            ImpactPosition = a.CenterPosition,
                        };

                        args.Weapon.Impact(Target.FromActor(a), warheadArgs);
                    }
                }
                else
                {
                    var warheadArgs = new WarheadArgs(args)
                    {
                        ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(args.Source, target), args.Facing),
                        ImpactPosition    = target,
                    };

                    args.Weapon.Impact(Target.FromPos(target), warheadArgs);
                }
            }

            if (hitanim != null)
            {
                hitanim.Tick();
            }

            if (ticks++ > info.Duration && animationComplete)
            {
                world.AddFrameEndTask(w => w.Remove(this));
            }
        }
Пример #24
0
 public override void DoImpact(Target target, WarheadArgs args)
 {
     args.SourceActor.World.AddFrameEndTask(world =>
     {
         world.CreateActor(BitActors.Random(world.SharedRandom), new TypeDictionary
         {
             new LocationInit(world.Map.CellContaining(target.CenterPosition)),
             new ColonyBitInit(args.SourceActor),
             new OwnerInit(world.Players.First(player => player.InternalName == "Neutral"))
         });
     });
 }
Пример #25
0
        public void Tick(World world)
        {
            lastPos = pos;
            if (--lifetime < 0)
            {
                world.AddFrameEndTask(w => { w.Remove(this); w.ScreenMap.Remove(this); });
                return;
            }

            if (--randomRate < 0)
            {
                var forward = speed.Length == 2
                                        ? world.SharedRandom.Next(speed[0].Length, speed[1].Length)
                                        : speed[0].Length;

                var height = gravity.Length == 2
                                        ? world.SharedRandom.Next(gravity[0].Length, gravity[1].Length)
                                        : gravity[0].Length;

                offset = new WVec(forward, 0, height);

                if (turnRate > 0)
                {
                    facing = (facing + world.SharedRandom.Next(-turnRate, turnRate)) & 0xFF;
                }

                offset = offset.Rotate(WRot.FromFacing(facing));

                randomRate = smoke.RandomRate;
            }

            anim.Tick();

            pos += offset;

            world.ScreenMap.Update(this, pos, anim.Image);

            if (canDamage && --explosionInterval < 0)
            {
                var args = new WarheadArgs
                {
                    Weapon            = smoke.Weapon,
                    Source            = pos,
                    SourceActor       = invoker,
                    WeaponTarget      = Target.FromPos(pos),
                    ImpactOrientation = new WRot(WAngle.Zero, Common.Util.GetVerticalAngle(lastPos, pos), WAngle.FromFacing(facing)),
                    ImpactPosition    = pos
                };

                smoke.Weapon.Impact(Target.FromPos(pos), args);
                explosionInterval = smoke.Weapon.ReloadDelay;
            }
        }
Пример #26
0
        public void Tick(World world)
        {
            world.AddFrameEndTask(w => w.Remove(this));

            var warheadArgs = new WarheadArgs(args)
            {
                ImpactOrientation = new WRot(WAngle.Zero, WAngle.Zero, args.CurrentMuzzleFacing()),
                ImpactPosition    = args.Source,
            };

            args.Weapon.Impact(Target.FromPos(args.Source), warheadArgs);
        }
Пример #27
0
        public void Tick(World world)
        {
            source = args.CurrentSource();

            if (hasLaunchEffect && ticks == 0)
            {
                world.AddFrameEndTask(w => w.Add(new SpriteEffect(args.CurrentSource, args.CurrentMuzzleFacing, world,
                                                                  info.LaunchEffectImage, info.LaunchEffectSequence, info.LaunchEffectPalette)));
            }

            // Beam tracks target
            if (info.TrackTarget && args.GuidedTarget.IsValidFor(args.SourceActor))
            {
                target = args.Weapon.TargetActorCenter ? args.GuidedTarget.CenterPosition : args.GuidedTarget.Positions.PositionClosestTo(source);
            }

            // Check for blocking actors
            WPos blockedPos;

            if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target,
                                                                             info.Width, out blockedPos))
            {
                target = blockedPos;
            }

            if (ticks < info.DamageDuration && --interval <= 0)
            {
                var warheadArgs = new WarheadArgs(args)
                {
                    ImpactOrientation = new WRot(WAngle.Zero, Util.GetVerticalAngle(source, target), args.CurrentMuzzleFacing()),
                    ImpactPosition    = target,
                };

                args.Weapon.Impact(Target.FromPos(target), warheadArgs);
                interval = info.DamageInterval;
            }

            if (showHitAnim)
            {
                if (ticks == 0)
                {
                    hitanim.PlayThen(info.HitAnimSequence, () => showHitAnim = false);
                }

                hitanim.Tick();
            }

            if (++ticks >= info.Duration && !showHitAnim)
            {
                world.AddFrameEndTask(w => w.Remove(this));
            }
        }
Пример #28
0
        public override void DoImpact(Target target, WarheadArgs args)
        {
            if (target.Type == TargetType.Invalid)
            {
                return;
            }

            var firedBy       = args.SourceActor;
            var pos           = target.CenterPosition;
            var world         = firedBy.World;
            var actorAtImpact = ImpactActors ? ActorTypeAtImpact(world, pos, firedBy) : ImpactActorType.None;

            // Ignore the impact if there are only invalid actors within range
            if (actorAtImpact == ImpactActorType.Invalid)
            {
                return;
            }

            // Ignore the impact if there are no valid actors and no valid terrain
            // (impacts are allowed on valid actors sitting on invalid terrain!)
            if (actorAtImpact == ImpactActorType.None && !IsValidAgainstTerrain(world, pos))
            {
                return;
            }

            var explosion = Explosions.RandomOrDefault(world.LocalRandom);

            if (Image != null && explosion != null)
            {
                if (ForceDisplayAtGroundLevel)
                {
                    var dat = world.Map.DistanceAboveTerrain(pos);
                    pos -= new WVec(0, 0, dat.Length);
                }

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

                world.AddFrameEndTask(w => w.Add(new SpriteEffect(pos, w, Image, explosion, palette)));
            }

            var impactSound = ImpactSounds.RandomOrDefault(world.LocalRandom);

            if (impactSound != null && world.LocalRandom.Next(0, 100) < ImpactSoundChance)
            {
                Game.Sound.Play(SoundType.World, impactSound, pos);
            }
        }
Пример #29
0
        public override void DoImpact(Target target, WarheadArgs args)
        {
            if (target.Type == TargetType.Invalid)
            {
                return;
            }

            var firedBy = args.SourceActor;
            var world   = firedBy.World;
            var layer   = world.WorldActor.Trait <BuildableTerrainLayer>();
            var cell    = world.Map.CellContaining(target.CenterPosition);

            layer.HitTile(cell, Damage);
        }
        public override void DoImpact(Target target, WarheadArgs args)
        {
            var firedBy = args.SourceActor;

            if (!target.IsValidFor(firedBy))
            {
                return;
            }

            var pos = target.CenterPosition;

            if (!IsValidImpact(pos, firedBy))
            {
                return;
            }

            var availableActors = firedBy.World.FindActorsOnCircle(pos, Range);

            foreach (var actor in availableActors)
            {
                if (!IsValidAgainst(actor, firedBy))
                {
                    continue;
                }

                if (actor.IsDead)
                {
                    continue;
                }

                var activeShapes = actor.TraitsImplementing <HitShape>().Where(Exts.IsTraitEnabled);
                if (!activeShapes.Any())
                {
                    continue;
                }

                var distance = activeShapes.Min(t => t.DistanceFromEdge(actor, pos));

                if (distance > Range)
                {
                    continue;
                }

                var attachable = actor.TraitsImplementing <DelayedWeaponAttachable>().FirstOrDefault(a => a.CanAttach(Type));
                if (attachable != null)
                {
                    attachable.Attach(new DelayedWeaponTrigger(this, args));
                }
            }
        }