Example #1
0
 public Fly(Actor self, Target t, WDist minRange, WDist maxRange,
            WPos?initialTargetPosition = null, Color?targetLineColor = null)
     : this(self, t, initialTargetPosition, targetLineColor)
 {
     this.maxRange = maxRange;
     this.minRange = minRange;
 }
Example #2
0
 public MoveWithinRange(Actor self, Target target, WDist minRange, WDist maxRange,
                        WPos?initialTargetPosition = null, Color?targetLineColor = null)
     : base(self, target, initialTargetPosition, targetLineColor)
 {
     this.minRange = minRange;
     this.maxRange = maxRange;
 }
Example #3
0
 // For places that only want to update some of the fields (usually DamageModifiers)
 public WarheadArgs(WarheadArgs args)
 {
     Weapon          = args.Weapon;
     DamageModifiers = args.DamageModifiers;
     Source          = args.Source;
     SourceActor     = args.SourceActor;
     WeaponTarget    = args.WeaponTarget;
 }
Example #4
0
 public WarheadArgs(ProjectileArgs args)
 {
     Weapon          = args.Weapon;
     DamageModifiers = args.DamageModifiers;
     Source          = args.Source;
     SourceActor     = args.SourceActor;
     WeaponTarget    = args.GuidedTarget;
 }
Example #5
0
        public Activity MoveToTarget(Actor self, Target target,
                                     WPos?initialTargetPosition = null, Color?targetLineColor = null)
        {
            if (target.Type == TargetType.Invalid)
            {
                return(null);
            }

            return(new MoveAdjacentTo(self, target, initialTargetPosition, targetLineColor));
        }
Example #6
0
        public Activity MoveWithinRange(Target target, WDist range,
                                        WPos?initialTargetPosition = null, Color?targetLineColor = null)
        {
            if (!Info.CanHover)
            {
                return(new Fly(self, target, WDist.Zero, range, initialTargetPosition, targetLineColor));
            }

            return(new HeliFly(self, target, WDist.Zero, range, initialTargetPosition, targetLineColor));
        }
Example #7
0
		public RadarPing Add(Func<bool> isVisible, WPos position, Color color, int duration)
		{
			var ping = new RadarPing(isVisible, position, color, duration,
				info.FromRadius, info.ToRadius, info.ShrinkSpeed, info.RotationSpeed);

			if (ping.IsVisible())
				LastPingPosition = ping.Position;

			Pings.Add(ping);

			return ping;
		}
Example #8
0
        public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange,
                                   WPos?initialTargetPosition = null, Color?targetLineColor = null)
        {
            if (!Info.CanHover)
            {
                return(new FlyFollow(self, target, minRange, maxRange,
                                     initialTargetPosition, targetLineColor));
            }

            return(new Follow(self, target, minRange, maxRange,
                              initialTargetPosition, targetLineColor));
        }
Example #9
0
        public Activity MoveToTarget(Actor self, Target target,
                                     WPos?initialTargetPosition = null, Color?targetLineColor = null)
        {
            if (!Info.CanHover)
            {
                return(new Fly(self, target, WDist.FromCells(3), WDist.FromCells(5),
                               initialTargetPosition, targetLineColor));
            }

            return(ActivityUtils.SequenceActivities(self,
                                                    new HeliFly(self, target, initialTargetPosition, targetLineColor),
                                                    new Turn(self, Info.InitialFacing)));
        }
Example #10
0
        public RadarPing Add(Func <bool> isVisible, WPos position, Color color, int duration)
        {
            var ping = new RadarPing(isVisible, position, color, duration, info.FromRadius, info.ToRadius, info.ShrinkSpeed, info.RotationSpeed);

            if (ping.IsVisible())
            {
                LastPingPosition = ping.Position;
            }

            Pings.Add(ping);

            return(ping);
        }
Example #11
0
		public Follow(Actor self, Target target, WDist minRange, WDist maxRange,
			WPos? initialTargetPosition, Color? targetLineColor = null)
		{
			this.target = target;
			this.minRange = minRange;
			this.maxRange = maxRange;
			this.targetLineColor = targetLineColor;
			move = self.Trait<IMove>();

			// The target may become hidden between the initial order request and the first tick (e.g. if queued)
			// Moving to any position (even if quite stale) is still better than immediately giving up
			if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner))
			    || target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain)
				lastVisibleTarget = Target.FromPos(target.CenterPosition);
			else if (initialTargetPosition.HasValue)
				lastVisibleTarget = Target.FromPos(initialTargetPosition.Value);
		}
Example #12
0
        public Fly(Actor self, Target t, WPos?initialTargetPosition = null, Color?targetLineColor = null)
        {
            aircraft             = self.Trait <Aircraft>();
            target               = t;
            this.targetLineColor = targetLineColor;

            // The target may become hidden between the initial order request and the first tick (e.g. if queued)
            // Moving to any position (even if quite stale) is still better than immediately giving up
            if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) ||
                target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain)
            {
                lastVisibleTarget = Target.FromPos(target.CenterPosition);
            }
            else if (initialTargetPosition.HasValue)
            {
                lastVisibleTarget = Target.FromPos(initialTargetPosition.Value);
            }
        }
        void ITick.Tick(Actor self)
        {
            if (IsTraitDisabled)
            {
                return;
            }

            if (state != PeriodicConditionState.Ready && --ticks < 0)
            {
                if (IsEnabled)
                {
                    ticks = info.CooldownDuration.Length == 2
                                                ? self.World.SharedRandom.Next(info.CooldownDuration[0], info.CooldownDuration[1])
                                                : info.CooldownDuration[0];
                    cooldown = ticks;
                    DisableCondition();
                    state = PeriodicConditionState.Charging;
                }
                else
                {
                    ticks = info.ActiveDuration.Length == 2
                                                ? self.World.SharedRandom.Next(info.ActiveDuration[0], info.ActiveDuration[1])
                                                : info.ActiveDuration[0];
                    active = ticks;
                    state  = PeriodicConditionState.Ready;
                }
            }

            if (Info.Triggers.HasFlag(PeriodicConditionTrigger.Move))
            {
                if (state == PeriodicConditionState.Ready && (lastPos == null || lastPos.Value != self.CenterPosition))
                {
                    TryEnableCondition();
                }

                lastPos = self.CenterPosition;
            }
        }
Example #14
0
        public MoveAdjacentTo(Actor self, Target target, WPos?initialTargetPosition = null, Color?targetLineColor = null)
        {
            this.target          = target;
            this.targetLineColor = targetLineColor;
            Mobile           = self.Trait <Mobile>();
            pathFinder       = self.World.WorldActor.Trait <IPathFinder>();
            domainIndex      = self.World.WorldActor.Trait <DomainIndex>();
            ChildHasPriority = false;

            // The target may become hidden between the initial order request and the first tick (e.g. if queued)
            // Moving to any position (even if quite stale) is still better than immediately giving up
            if ((target.Type == TargetType.Actor && target.Actor.CanBeViewedByPlayer(self.Owner)) ||
                target.Type == TargetType.FrozenActor || target.Type == TargetType.Terrain)
            {
                lastVisibleTarget         = Target.FromPos(target.CenterPosition);
                lastVisibleTargetLocation = self.World.Map.CellContaining(target.CenterPosition);
            }
            else if (initialTargetPosition.HasValue)
            {
                lastVisibleTarget         = Target.FromPos(initialTargetPosition.Value);
                lastVisibleTargetLocation = self.World.Map.CellContaining(initialTargetPosition.Value);
            }
        }
Example #15
0
 public Activity MoveWithinRange(Target target, WDist range,
                                 WPos?initialTargetPosition = null, Color?targetLineColor = null)
 {
     return(new MoveWithinRange(self, target, WDist.Zero, range, initialTargetPosition, targetLineColor));
 }
Example #16
0
 public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange,
                            WPos?initialTargetPosition = null, Color?targetLineColor = null)
 {
     return(WrapMove(new Follow(self, target, minRange, maxRange, initialTargetPosition, targetLineColor)));
 }
Example #17
0
 public Activity MoveToTarget(Actor self, Target target,
                              WPos?initialTargetPosition = null, Color?targetLineColor = null)
 {
     return(new ShootableBallisticMissileFly(self, target));
 }
Example #18
0
 public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange,
                            WPos?initialTargetPosition = null, Color?targetLineColor = null)
 {
     return(null);
 }
Example #19
0
 public Fly(Actor self, Target t, WDist nearEnough, WPos?initialTargetPosition = null, Color?targetLineColor = null)
     : this(self, t, initialTargetPosition, targetLineColor)
 {
     this.nearEnough = nearEnough;
 }
Example #20
0
 public Activity MoveToTarget(Actor self, Target target, WPos?initialTargetPosition = default(WPos?), Primitives.Color?targetLineColor = default(Primitives.Color?))
 {
     return(null);
 }
Example #21
0
        public Actor[] SendAirstrike(Actor self, WPos target, WAngle?facing = null)
        {
            var aircraft = new List <Actor>();

            if (!facing.HasValue)
            {
                facing = new WAngle(1024 * self.World.SharedRandom.Next(info.QuantizedFacings) / info.QuantizedFacings);
            }

            Actor  camera          = null;
            Beacon beacon          = null;
            var    aircraftInRange = new Dictionary <Actor, bool>();

            Action <Actor> onEnterRange = a =>
            {
                // Spawn a camera and remove the beacon when the first plane enters the target area
                if (info.CameraActor != null && camera == null && !aircraftInRange.Any(kv => kv.Value))
                {
                    self.World.AddFrameEndTask(w =>
                    {
                        camera = w.CreateActor(info.CameraActor, new TypeDictionary
                        {
                            new LocationInit(self.World.Map.CellContaining(target)),
                            new OwnerInit(self.Owner),
                        });
                    });
                }

                RemoveBeacon(beacon);

                aircraftInRange[a] = true;
            };

            Action <Actor> onExitRange = a =>
            {
                aircraftInRange[a] = false;

                // Remove the camera when the final plane leaves the target area
                if (!aircraftInRange.Any(kv => kv.Value))
                {
                    RemoveCamera(camera);
                }
            };

            Action <Actor> onRemovedFromWorld = a =>
            {
                aircraftInRange[a] = false;

                // Checking for attack range is not relevant here because
                // aircraft may be shot down before entering the range.
                // If at the map's edge, they may be removed from world before leaving.
                if (aircraftInRange.All(kv => !kv.Key.IsInWorld))
                {
                    RemoveCamera(camera);
                    RemoveBeacon(beacon);
                }
            };

            WPos?startPos = null;

            // Create the actors immediately so they can be returned.
            foreach (var squadMember in info.Squad)
            {
                var a = self.World.CreateActor(false, squadMember.UnitType, new TypeDictionary
                {
                    new OwnerInit(self.Owner),
                    new FacingInit(facing.Value)
                });

                aircraft.Add(a);
                aircraftInRange.Add(a, false);
            }

            self.World.AddFrameEndTask(w =>
            {
                PlayLaunchSounds();

                Actor distanceTestActor = null;
                for (var i = 0; i < aircraft.Count; i++)
                {
                    var squadMember = info.Squad[i];
                    var actor       = aircraft[i];

                    var altitude       = self.World.Map.Rules.Actors[squadMember.UnitType].TraitInfo <AircraftInfo>().CruiseAltitude.Length;
                    var attackRotation = WRot.FromYaw(facing.Value);
                    var delta          = new WVec(0, -1024, 0).Rotate(attackRotation);
                    var targetPos      = target + new WVec(0, 0, altitude);
                    var startEdge      = targetPos - (self.World.Map.DistanceToEdge(target, -delta) + info.Cordon).Length * delta / 1024;
                    var finishEdge     = targetPos + (self.World.Map.DistanceToEdge(target, delta) + info.Cordon).Length * delta / 1024;

                    startPos = startEdge;

                    // Includes the 90 degree rotation between body and world coordinates
                    var so           = squadMember.SpawnOffset;
                    var to           = squadMember.TargetOffset;
                    var spawnOffset  = new WVec(so.Y, -1 * so.X, 0).Rotate(attackRotation);
                    var targetOffset = new WVec(to.Y, 0, 0).Rotate(attackRotation);

                    actor.Trait <IPositionable>().SetPosition(actor, startEdge + spawnOffset);
                    w.Add(actor);

                    var attack = actor.Trait <AttackBomber>();
                    attack.SetTarget(self.World, targetPos + targetOffset);
                    attack.OnEnteredAttackRange += onEnterRange;
                    attack.OnExitedAttackRange  += onExitRange;
                    attack.OnRemovedFromWorld   += onRemovedFromWorld;

                    for (var strikes = 0; strikes < info.Strikes; strikes++)
                    {
                        actor.QueueActivity(new Fly(actor, Target.FromPos(target + spawnOffset)));
                        if (info.Strikes > 1)
                        {
                            actor.QueueActivity(new FlyForward(actor, info.CircleDelay));
                        }
                    }

                    actor.QueueActivity(new Fly(actor, Target.FromPos(finishEdge + spawnOffset)));
                    actor.QueueActivity(new RemoveSelf());
                    distanceTestActor = actor;
                }

                if (Info.DisplayBeacon && startPos.HasValue)
                {
                    var distance = (target - startPos.Value).HorizontalLength;

                    beacon = new Beacon(
                        self.Owner,
                        new WPos(target.X, target.Y, 0),
                        Info.BeaconPaletteIsPlayerPalette,
                        Info.BeaconPalette,
                        Info.BeaconImage,
                        Info.BeaconPoster,
                        Info.BeaconPosterPalette,
                        Info.BeaconSequence,
                        Info.ArrowSequence,
                        Info.CircleSequence,
                        Info.ClockSequence,
                        () => 1 - ((distanceTestActor.CenterPosition - target).HorizontalLength - info.BeaconDistanceOffset.Length) * 1f / distance,
                        Info.BeaconDelay);

                    w.Add(beacon);
                }
            });

            return(aircraft.ToArray());
        }
Example #22
0
 public Activity MoveWithinRange(Target target, WDist minRange, WDist maxRange,
                                 WPos?initialTargetPosition = null, Color?targetLineColor = null)
 {
     return(new ShootableBallisticMissileFly(self, target));
 }
Example #23
0
 public Activity MoveWithinRange(Target target, WDist range, WPos?initialTargetPosition = default(WPos?), Primitives.Color?targetLineColor = default(Primitives.Color?))
 {
     return(null);
 }
Example #24
0
 public Activity MoveWithinRange(Target target, WDist minRange, WDist maxRange,
                                 WPos?initialTargetPosition = null, Color?targetLineColor = null)
 {
     return(null);
 }
Example #25
0
 public Activity MoveFollow(Actor self, Target target, WDist minRange, WDist maxRange, WPos?initialTargetPosition = default(WPos?), Primitives.Color?targetLineColor = default(Primitives.Color?))
 {
     return(null);
 }
Example #26
0
 public Activity MoveToTarget(Actor self, Target target,
                              WPos?initialTargetPosition = null, Color?targetLineColor = null)
 {
     return(null);
 }
Example #27
0
        public void SendAirstrike(Actor self, WPos target, bool randomize = true, int attackFacing = 0)
        {
            if (randomize)
            {
                attackFacing = 256 * self.World.SharedRandom.Next(info.QuantizedFacings) / info.QuantizedFacings;
            }

            Actor  camera          = null;
            Beacon beacon          = null;
            var    aircraftInRange = new Dictionary <Actor, bool>();

            Action <Actor> onEnterRange = a =>
            {
                // Spawn a camera and remove the beacon when the first plane enters the target area
                if (info.CameraActor != null && camera == null && !aircraftInRange.Any(kv => kv.Value))
                {
                    self.World.AddFrameEndTask(w =>
                    {
                        camera = w.CreateActor(info.CameraActor, new TypeDictionary
                        {
                            new LocationInit(self.World.Map.CellContaining(target)),
                            new OwnerInit(self.Owner),
                        });
                    });
                }

                RemoveBeacon(beacon);

                aircraftInRange[a] = true;
            };

            Action <Actor> onExitRange = a =>
            {
                aircraftInRange[a] = false;

                // Remove the camera when the final plane leaves the target area
                if (!aircraftInRange.Any(kv => kv.Value))
                {
                    RemoveCamera(camera);
                }
            };

            Action <Actor> onRemovedFromWorld = a =>
            {
                aircraftInRange[a] = false;

                // Checking for attack range is not relevant here because
                // aircraft may be shot down before entering. Thus we remove
                // the camera and beacon only if the whole squad is dead.
                if (aircraftInRange.All(kv => kv.Key.IsDead))
                {
                    RemoveCamera(camera);
                    RemoveBeacon(beacon);
                }
            };

            self.World.AddFrameEndTask(w =>
            {
                WPos?startPos = null;
                foreach (var squadMember in info.Squad)
                {
                    var altitude       = self.World.Map.Rules.Actors[squadMember.UnitType].TraitInfo <AircraftInfo>().CruiseAltitude.Length;
                    var attackRotation = WRot.FromFacing(attackFacing);
                    var delta          = new WVec(0, -1024, 0).Rotate(attackRotation);
                    var targetPos      = target + new WVec(0, 0, altitude);
                    var startEdge      = targetPos - (self.World.Map.DistanceToEdge(targetPos, -delta) + info.Cordon).Length * delta / 1024;
                    var finishEdge     = targetPos + (self.World.Map.DistanceToEdge(targetPos, delta) + info.Cordon).Length * delta / 1024;

                    startPos = startEdge;

                    PlayLaunchSounds();

                    var spawnOffset  = squadMember.SpawnOffset.Rotate(attackRotation);
                    var targetOffset = squadMember.TargetOffset.Rotate(attackRotation);

                    var a = w.CreateActor(squadMember.UnitType, new TypeDictionary
                    {
                        new CenterPositionInit(startEdge + spawnOffset),
                        new OwnerInit(self.Owner),
                        new FacingInit(attackFacing),
                        new CreationActivityDelayInit(squadMember.SpawnDelay)
                    });

                    var attack = a.Trait <AttackBomber>();
                    attack.SetTarget(w, targetPos + targetOffset);
                    attack.OnEnteredAttackRange += onEnterRange;
                    attack.OnExitedAttackRange  += onExitRange;
                    attack.OnRemovedFromWorld   += onRemovedFromWorld;

                    for (var strikes = 0; strikes < info.Strikes; strikes++)
                    {
                        a.QueueActivity(new Fly(a, Target.FromPos(target + spawnOffset)));
                        if (info.Strikes > 1)
                        {
                            a.QueueActivity(new FlyTimed(info.CircleDelay, a));
                        }
                    }

                    a.QueueActivity(new Fly(a, Target.FromPos(finishEdge + spawnOffset)));
                    a.QueueActivity(new RemoveSelf());
                    aircraftInRange.Add(a, false);
                }

                if (Info.DisplayBeacon && startPos.HasValue)
                {
                    var distance = (target - startPos.Value).HorizontalLength;

                    beacon = new Beacon(
                        self.Owner,
                        new WPos(target.X, target.Y, 0),
                        Info.BeaconPaletteIsPlayerPalette,
                        Info.BeaconPalette,
                        Info.BeaconImage,
                        Info.BeaconPoster,
                        Info.BeaconPosterPalette,
                        Info.BeaconSequence,
                        Info.ArrowSequence,
                        Info.CircleSequence,
                        Info.ClockSequence,
                        () =>
                    {
                        // To account for different spawn times and potentially different movement speeds.
                        var closestActor = aircraftInRange.Keys.MinBy(x => (x.CenterPosition - target).HorizontalLengthSquared);
                        return(1 - ((closestActor.CenterPosition - target).HorizontalLength - info.BeaconDistanceOffset.Length) * 1f / distance);
                    },
                        Info.BeaconDelay);

                    w.Add(beacon);
                }
            });
        }