Merge pull request #4478 from pchote/aircraft-follow

Add Guard and AttackMove to RA and C&C aircraft.
This commit is contained in:
Matthias Mailänder
2014-02-01 00:38:21 -08:00
46 changed files with 243 additions and 157 deletions

View File

@@ -0,0 +1,44 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using OpenRA.Mods.RA.Air;
using OpenRA.Mods.RA.Move;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
{
public class FlyFollow : Activity
{
Target target;
Plane plane;
WRange range;
public FlyFollow(Actor self, Target target, WRange range)
{
this.target = target;
plane = self.Trait<Plane>();
this.range = range;
}
public override Activity Tick(Actor self)
{
if (IsCanceled || !target.IsValidFor(self))
return NextActivity;
if (target.IsInRange(self.CenterPosition, range))
{
Fly.FlyToward(self, plane, plane.Facing, plane.Info.CruiseAltitude);
return this;
}
return Util.SequenceActivities(new Fly(self, target, WRange.Zero, range), this);
}
}
}

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Mods.RA.Activities
public class Follow : Activity
{
Target target;
Mobile mobile;
IMove move;
WRange range;
int nextPathTime;
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Activities
public Follow(Actor self, Target target, WRange range)
{
this.target = target;
mobile = self.Trait<Mobile>();
move = self.Trait<IMove>();
this.range = range;
}
@@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Activities
nextPathTime = self.World.SharedRandom.Next(delayBetweenPathingAttempts - delaySpread,
delayBetweenPathingAttempts + delaySpread);
return Util.SequenceActivities(mobile.MoveWithinRange(target, range), this);
return Util.SequenceActivities(move.MoveWithinRange(target, range), this);
}
}
}

View File

@@ -15,9 +15,23 @@ namespace OpenRA.Mods.RA.Air
{
public class Fly : Activity
{
readonly WPos pos;
readonly Plane plane;
readonly Target target;
readonly WRange maxRange;
readonly WRange minRange;
Fly(WPos pos) { this.pos = pos; }
public Fly(Actor self, Target t)
{
plane = self.Trait<Plane>();
target = t;
}
public Fly(Actor self, Target t, WRange minRange, WRange maxRange)
: this(self, t)
{
this.maxRange = maxRange;
this.minRange = minRange;
}
public static void FlyToward(Actor self, Plane plane, int desiredFacing, WRange desiredAltitude)
{
@@ -36,20 +50,22 @@ namespace OpenRA.Mods.RA.Air
plane.SetPosition(self, plane.CenterPosition + move);
}
public static Fly ToPos(WPos pos) { return new Fly(pos); }
public static Fly ToCell(CPos pos) { return new Fly(pos.CenterPosition); }
public override Activity Tick(Actor self)
{
if (IsCanceled)
return NextActivity;
// Inside the target annulus, so we're done
var insideMaxRange = maxRange.Range > 0 && target.IsInRange(plane.CenterPosition, maxRange);
var insideMinRange = minRange.Range > 0 && target.IsInRange(plane.CenterPosition, minRange);
if (insideMaxRange && !insideMinRange)
return NextActivity;
// Close enough (ported from old code which checked length against sqrt(50) px)
var d = pos - self.CenterPosition;
var d = target.CenterPosition - self.CenterPosition;
if (d.HorizontalLengthSquared < 91022)
return NextActivity;
var plane = self.Trait<Plane>();
var desiredFacing = Util.GetFacing(d, plane.Facing);
// Don't turn until we've reached the cruise altitude
@@ -63,7 +79,7 @@ namespace OpenRA.Mods.RA.Air
public override IEnumerable<Target> GetTargets(Actor self)
{
yield return Target.FromPos(pos);
yield return target;
}
}
}

View File

@@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA.Air
if (IsCanceled)
return NextActivity;
inner = Util.SequenceActivities(Fly.ToPos(target.CenterPosition), new FlyTimed(50));
inner = Util.SequenceActivities(new Fly(self, target), new FlyTimed(50));
}
inner = Util.RunActivity(self, inner);

View File

@@ -15,10 +15,23 @@ namespace OpenRA.Mods.RA.Air
{
class HeliFly : Activity
{
readonly WPos pos;
readonly Helicopter helicopter;
readonly Target target;
readonly WRange maxRange;
readonly WRange minRange;
public HeliFly(WPos pos) { this.pos = pos; }
public HeliFly(CPos pos) { this.pos = pos.CenterPosition; }
public HeliFly(Actor self, Target t)
{
helicopter = self.Trait<Helicopter>();
target = t;
}
public HeliFly(Actor self, Target t, WRange minRange, WRange maxRange)
: this(self, t)
{
this.maxRange = maxRange;
this.minRange = minRange;
}
public static bool AdjustAltitude(Actor self, Helicopter helicopter, WRange targetAltitude)
{
@@ -38,18 +51,29 @@ namespace OpenRA.Mods.RA.Air
if (IsCanceled)
return NextActivity;
var helicopter = self.Trait<Helicopter>();
if (AdjustAltitude(self, helicopter, helicopter.Info.CruiseAltitude))
return this;
var pos = target.CenterPosition;
// Rotate towards the target
var dist = pos - self.CenterPosition;
var desiredFacing = Util.GetFacing(dist, helicopter.Facing);
helicopter.Facing = Util.TickFacing(helicopter.Facing, desiredFacing, helicopter.ROT);
var move = helicopter.FlyStep(desiredFacing);
// Inside the minimum range, so reverse
if (minRange.Range > 0 && target.IsInRange(helicopter.CenterPosition, minRange))
{
helicopter.SetPosition(self, helicopter.CenterPosition - move);
return this;
}
// Inside the maximum range, so we're done
if (maxRange.Range > 0 && target.IsInRange(helicopter.CenterPosition, maxRange))
return NextActivity;
// The next move would overshoot, so just set the final position
var move = helicopter.FlyStep(desiredFacing);
if (dist.HorizontalLengthSquared < move.HorizontalLengthSquared)
{
helicopter.SetPosition(self, pos + new WVec(0, 0, helicopter.Info.CruiseAltitude.Range - pos.Z));
@@ -63,7 +87,7 @@ namespace OpenRA.Mods.RA.Air
public override IEnumerable<Target> GetTargets(Actor self)
{
yield return Target.FromPos(pos);
yield return target;
}
}
}

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Mods.RA.Air
if (nearestHpad == null)
return Util.SequenceActivities(new Turn(initialFacing), new HeliLand(true), NextActivity);
else
return Util.SequenceActivities(new HeliFly(nearestHpad.CenterPosition));
return Util.SequenceActivities(new HeliFly(self, Target.FromActor(nearestHpad)));
}
var res = dest.TraitOrDefault<Reservable>();
@@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA.Air
var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero;
return Util.SequenceActivities(
new HeliFly(dest.CenterPosition + offset),
new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)),
new Turn(initialFacing),
new HeliLand(false),
new Rearm(self),

View File

@@ -28,11 +28,13 @@ namespace OpenRA.Mods.RA.Air
class Helicopter : Aircraft, ITick, IResolveOrder, IMove
{
public HelicopterInfo Info;
Actor self;
bool firstTick = true;
public Helicopter(ActorInitializer init, HelicopterInfo info)
: base(init, info)
{
self = init.self;
Info = info;
}
@@ -46,11 +48,12 @@ namespace OpenRA.Mods.RA.Air
if (order.OrderString == "Move")
{
var target = self.World.ClampToWorld(order.TargetLocation);
var cell = self.World.ClampToWorld(order.TargetLocation);
var t = Target.FromCell(cell);
self.SetTargetLine(Target.FromCell(target), Color.Green);
self.SetTargetLine(t, Color.Green);
self.CancelActivity();
self.QueueActivity(new HeliFly(target));
self.QueueActivity(new HeliFly(self, t));
if (Info.LandWhenIdle)
{
@@ -78,7 +81,7 @@ namespace OpenRA.Mods.RA.Air
self.SetTargetLine(Target.FromActor(order.TargetActor), Color.Green);
self.CancelActivity();
self.QueueActivity(new HeliFly(order.TargetActor.CenterPosition + offset));
self.QueueActivity(new HeliFly(self, Target.FromPos(order.TargetActor.CenterPosition + offset)));
self.QueueActivity(new Turn(Info.InitialFacing));
self.QueueActivity(new HeliLand(false));
self.QueueActivity(new ResupplyAircraft());
@@ -149,9 +152,11 @@ namespace OpenRA.Mods.RA.Air
return (d * 1024 * 8) / (int)distSq;
}
public Activity MoveTo(CPos cell, int nearEnough) { return new HeliFly(cell); }
public Activity MoveTo(CPos cell, Actor ignoredActor) { return new HeliFly(cell); }
public Activity MoveWithinRange(Target target, WRange range) { return new HeliFly(target.CenterPosition); }
public Activity MoveTo(CPos cell, int nearEnough) { return new HeliFly(self, Target.FromCell(cell)); }
public Activity MoveTo(CPos cell, Actor ignoredActor) { return new HeliFly(self, Target.FromCell(cell)); }
public Activity MoveWithinRange(Target target, WRange range) { return new HeliFly(self, target, WRange.Zero, range); }
public Activity MoveWithinRange(Target target, WRange minRange, WRange maxRange) { return new HeliFly(self, target, minRange, maxRange); }
public Activity MoveFollow(Actor self, Target target, WRange range) { return new Follow(self, target, range); }
public CPos NearestMoveableCell(CPos cell) { return cell; }
}
}

View File

@@ -9,6 +9,7 @@
#endregion
using System.Drawing;
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air
@@ -24,10 +25,12 @@ namespace OpenRA.Mods.RA.Air
{
public readonly PlaneInfo Info;
[Sync] public WPos RTBPathHash;
Actor self;
public Plane(ActorInitializer init, PlaneInfo info)
: base(init, info)
{
self = init.self;
Info = info;
}
@@ -48,10 +51,11 @@ namespace OpenRA.Mods.RA.Air
{
UnReserve();
var target = self.World.ClampToWorld(order.TargetLocation);
self.SetTargetLine(Target.FromCell(target), Color.Green);
var cell = self.World.ClampToWorld(order.TargetLocation);
var t = Target.FromCell(cell);
self.SetTargetLine(t, Color.Green);
self.CancelActivity();
self.QueueActivity(Fly.ToCell(target));
self.QueueActivity(new Fly(self, t));
self.QueueActivity(new FlyCircle());
}
else if (order.OrderString == "Enter")
@@ -89,9 +93,11 @@ namespace OpenRA.Mods.RA.Air
}
}
public Activity MoveTo(CPos cell, int nearEnough) { return Fly.ToCell(cell); }
public Activity MoveTo(CPos cell, Actor ignoredActor) { return Fly.ToCell(cell); }
public Activity MoveWithinRange(Target target, WRange range) { return Fly.ToPos(target.CenterPosition); }
public Activity MoveTo(CPos cell, int nearEnough) { return Util.SequenceActivities(new Fly(self, Target.FromCell(cell)), new FlyCircle()); }
public Activity MoveTo(CPos cell, Actor ignoredActor) { return Util.SequenceActivities(new Fly(self, Target.FromCell(cell)), new FlyCircle()); }
public Activity MoveWithinRange(Target target, WRange range) { return Util.SequenceActivities(new Fly(self, target, WRange.Zero, range), new FlyCircle()); }
public Activity MoveWithinRange(Target target, WRange minRange, WRange maxRange) { return Util.SequenceActivities(new Fly(self, target, minRange, maxRange), new FlyCircle()); }
public Activity MoveFollow(Actor self, Target target, WRange range) { return new FlyFollow(self, target, range); }
public CPos NearestMoveableCell(CPos cell) { return cell; }
}
}

View File

@@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA.Air
return;
}
self.QueueActivity(Fly.ToCell(someBuilding.Location));
self.QueueActivity(new Fly(self, Target.FromActor(someBuilding)));
self.QueueActivity(new FlyCircle());
}
}

View File

@@ -110,15 +110,15 @@ namespace OpenRA.Mods.RA.Air
self.CancelActivity();
if (nearestAfld != null)
return Util.SequenceActivities(Fly.ToCell(nearestAfld.Location), new FlyCircle());
return Util.SequenceActivities(new Fly(self, Target.FromActor(nearestAfld)), new FlyCircle());
else
return new FlyCircle();
}
return Util.SequenceActivities(
Fly.ToPos(w1),
Fly.ToPos(w2),
Fly.ToPos(w3),
new Fly(self, Target.FromPos(w1)),
new Fly(self, Target.FromPos(w2)),
new Fly(self, Target.FromPos(w3)),
new Land(Target.FromActor(dest)),
NextActivity);
}

View File

@@ -99,8 +99,10 @@ namespace OpenRA.Mods.RA
var range = WRange.FromCells(Math.Max(0, weapon.Weapon.Range.Range / 1024 - RangeTolerance));
attack.Target = target;
if (allowMove && self.HasTrait<Mobile>() && !self.Info.Traits.Get<MobileInfo>().OnRails)
return Util.SequenceActivities(new Follow(self, target, range), this);
var mobile = self.TraitOrDefault<Mobile>();
if (allowMove && mobile != null && !mobile.Info.OnRails)
return Util.SequenceActivities(mobile.MoveFollow(self, target, range), this);
}
return NextActivity;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -8,10 +8,10 @@
*/
#endregion
using OpenRA.FileFormats;
using OpenRA.Traits;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
@@ -29,65 +29,79 @@ namespace OpenRA.Mods.RA
[Desc("Ticks to wait until next AutoTarget: attempt.")]
public readonly int MaximumScanTimeInterval = 8;
public readonly bool TargetWhenIdle = true;
public readonly bool TargetWhenDamaged = true;
public readonly bool EnableStances = true;
public object Create(ActorInitializer init) { return new AutoTarget(init.self, this); }
}
public enum UnitStance { HoldFire, ReturnFire, Defend, AttackAnything };
public enum UnitStance { HoldFire, ReturnFire, Defend, AttackAnything }
public class AutoTarget : INotifyIdle, INotifyDamage, ITick, IResolveOrder, ISync
{
readonly AutoTargetInfo Info;
readonly AutoTargetInfo info;
readonly AttackBase attack;
readonly AttackTurreted at;
[Sync] int nextScanTime = 0;
[Sync] public int nextScanTime = 0;
public UnitStance stance;
[Sync] public int stanceNumber { get { return (int)stance; } }
public UnitStance predictedStance; /* NOT SYNCED: do not refer to this anywhere other than UI code */
public UnitStance Stance;
[Sync] public Actor Aggressor;
[Sync] public Actor TargetedActor;
// NOT SYNCED: do not refer to this anywhere other than UI code
public UnitStance PredictedStance;
public AutoTarget(Actor self, AutoTargetInfo info)
{
Info = info;
this.info = info;
attack = self.Trait<AttackBase>();
stance = Info.InitialStance;
predictedStance = stance;
Stance = info.InitialStance;
PredictedStance = Stance;
at = self.TraitOrDefault<AttackTurreted>();
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "SetUnitStance")
stance = (UnitStance)order.TargetLocation.X;
if (order.OrderString == "SetUnitStance" && info.EnableStances)
Stance = (UnitStance)order.TargetLocation.X;
}
public void Damaged(Actor self, AttackInfo e)
{
if (!self.IsIdle) return;
if (e.Attacker.Destroyed) return;
if (!self.IsIdle || !info.TargetWhenDamaged)
return;
if (stance < UnitStance.ReturnFire) return;
if (e.Attacker.Destroyed)
return;
if (Stance < UnitStance.ReturnFire) return;
// not a lot we can do about things we can't hurt... although maybe we should automatically run away?
if (!attack.HasAnyValidWeapons(Target.FromActor(e.Attacker))) return;
if (!attack.HasAnyValidWeapons(Target.FromActor(e.Attacker)))
return;
// don't retaliate against own units force-firing on us. it's usually not what the player wanted.
if (e.Attacker.AppearsFriendlyTo(self)) return;
// don't retaliate against own units force-firing on us. It's usually not what the player wanted.
if (e.Attacker.AppearsFriendlyTo(self))
return;
if (e.Damage < 0) return; // don't retaliate against healers
// don't retaliate against healers
if (e.Damage < 0)
return;
Aggressor = e.Attacker;
if (at == null || !at.IsReachableTarget(at.Target, Info.AllowMovement && stance != UnitStance.Defend))
if (at == null || !at.IsReachableTarget(at.Target, info.AllowMovement && Stance != UnitStance.Defend))
Attack(self, e.Attacker);
}
public void TickIdle(Actor self)
{
if (stance < UnitStance.Defend) return;
if (Stance < UnitStance.Defend || !info.TargetWhenIdle)
return;
if (at == null || !at.IsReachableTarget(at.Target, Info.AllowMovement && stance != UnitStance.Defend))
var allowMovement = info.AllowMovement && Stance != UnitStance.Defend;
if (at == null || !at.IsReachableTarget(at.Target, allowMovement))
ScanAndAttack(self);
}
@@ -99,7 +113,7 @@ namespace OpenRA.Mods.RA
public Actor ScanForTarget(Actor self, Actor currentTarget)
{
var range = Info.ScanRadius > 0 ? WRange.FromCells(Info.ScanRadius) : attack.GetMaximumRange();
var range = info.ScanRadius > 0 ? WRange.FromCells(info.ScanRadius) : attack.GetMaximumRange();
if (self.IsIdle || currentTarget == null || !Target.FromActor(currentTarget).IsInRange(self.CenterPosition, range))
if (nextScanTime <= 0)
return ChooseTarget(self, range);
@@ -119,12 +133,12 @@ namespace OpenRA.Mods.RA
TargetedActor = targetActor;
var target = Target.FromActor(targetActor);
self.SetTargetLine(target, Color.Red, false);
attack.AttackTarget(target, false, Info.AllowMovement && stance != UnitStance.Defend);
attack.AttackTarget(target, false, info.AllowMovement && Stance != UnitStance.Defend);
}
Actor ChooseTarget(Actor self, WRange range)
{
nextScanTime = self.World.SharedRandom.Next(Info.MinimumScanTimeInterval, Info.MaximumScanTimeInterval);
nextScanTime = self.World.SharedRandom.Next(info.MinimumScanTimeInterval, info.MaximumScanTimeInterval);
var inRange = self.World.FindActorsInCircle(self.CenterPosition, range);
if (self.Owner.HasFogVisibility())
@@ -150,5 +164,4 @@ namespace OpenRA.Mods.RA
[Desc("Will not get automatically targeted by enemy (like walls)")]
class AutoTargetIgnoreInfo : TraitInfo<AutoTargetIgnore> { }
class AutoTargetIgnore { }
}

View File

@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class GuardInfo : TraitInfo<Guard>, Requires<MobileInfo> { }
class GuardInfo : TraitInfo<Guard> { }
class Guard : IResolveOrder, IOrderVoice
{
@@ -30,8 +30,7 @@ namespace OpenRA.Mods.RA
self.SetTargetLine(target, Color.Yellow);
var range = WRange.FromCells(target.Actor.Info.Traits.Get<GuardableInfo>().Range);
self.QueueActivity(false, new AttackMove.AttackMoveActivity(self,
new Follow(self, target, range)));
self.QueueActivity(false, new AttackMove.AttackMoveActivity(self, self.Trait<IMove>().MoveFollow(self, target, range)));
}
}

View File

@@ -272,7 +272,7 @@ namespace OpenRA.Mods.RA.Missions
void SetAlliedUnitsToDefensiveStance()
{
foreach (var actor in world.Actors.Where(a => a.IsInWorld && a.Owner == allies && !a.IsDead() && a.HasTrait<AutoTarget>()))
actor.Trait<AutoTarget>().stance = UnitStance.Defend;
actor.Trait<AutoTarget>().Stance = UnitStance.Defend;
}
public void WorldLoaded(World w, WorldRenderer wr)

View File

@@ -349,7 +349,7 @@ namespace OpenRA.Mods.RA.Missions
void SetupSubStances()
{
foreach (var actor in world.Actors.Where(a => a.IsInWorld && a.Owner == soviets && !a.IsDead() && a.HasTrait<TargetableSubmarine>()))
actor.Trait<AutoTarget>().stance = UnitStance.Defend;
actor.Trait<AutoTarget>().Stance = UnitStance.Defend;
}
public void WorldLoaded(World w, WorldRenderer wr)

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
@@ -206,7 +206,7 @@ namespace OpenRA.Mods.RA.Missions
new FacingInit(Traits.Util.GetFacing(waypoints[1] - waypoints[0], 0))
});
foreach (var waypoint in waypoints)
m.QueueActivity(Fly.ToCell(waypoint));
m.QueueActivity(new Fly(m, Target.FromCell(waypoint)));
m.QueueActivity(new RemoveSelf());
}
@@ -221,12 +221,12 @@ namespace OpenRA.Mods.RA.Missions
var exit = lz.Info.Traits.WithInterface<ExitInfo>().FirstOrDefault();
var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero;
chinook.QueueActivity(new HeliFly(lz.CenterPosition + offset)); // no reservation of hpad but it's not needed
chinook.QueueActivity(new HeliFly(chinook, Target.FromPos(lz.CenterPosition + offset))); // no reservation of hpad but it's not needed
chinook.QueueActivity(new Turn(0));
chinook.QueueActivity(new HeliLand(false));
chinook.QueueActivity(new UnloadCargo(true));
chinook.QueueActivity(new Wait(150));
chinook.QueueActivity(new HeliFly(entry));
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(entry)));
chinook.QueueActivity(new RemoveSelf());
}
@@ -290,7 +290,7 @@ namespace OpenRA.Mods.RA.Missions
foreach (var actor in actors.Values)
{
if (actor.Owner == allies && actor.HasTrait<AutoTarget>())
actor.Trait<AutoTarget>().stance = UnitStance.Defend;
actor.Trait<AutoTarget>().Stance = UnitStance.Defend;
if (actor.IsInWorld && (actor.HasTrait<Bridge>() || actor.Owner == allies || (actor.Owner == soviets && actor.HasTrait<Building>())))
actor.AddTrait(new Invulnerable());

View File

@@ -45,12 +45,12 @@ namespace OpenRA.Mods.RA.Missions
public static Actor ExtractUnitWithChinook(World world, Player owner, Actor unit, CPos entry, CPos lz, CPos exit)
{
var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) });
chinook.QueueActivity(new HeliFly(lz));
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(lz)));
chinook.QueueActivity(new Turn(0));
chinook.QueueActivity(new HeliLand(true));
chinook.QueueActivity(new WaitFor(() => chinook.Trait<Cargo>().Passengers.Contains(unit)));
chinook.QueueActivity(new Wait(150));
chinook.QueueActivity(new HeliFly(exit));
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(exit)));
chinook.QueueActivity(new RemoveSelf());
return chinook;
}
@@ -60,13 +60,13 @@ namespace OpenRA.Mods.RA.Missions
var unit = world.CreateActor(false, unitName, new TypeDictionary { new OwnerInit(owner) });
var chinook = world.CreateActor("tran", new TypeDictionary { new OwnerInit(owner), new LocationInit(entry) });
chinook.Trait<Cargo>().Load(chinook, unit);
chinook.QueueActivity(new HeliFly(lz));
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(lz)));
chinook.QueueActivity(new Turn(0));
chinook.QueueActivity(new HeliLand(true));
chinook.QueueActivity(new UnloadCargo(true));
chinook.QueueActivity(new CallFunc(() => afterUnload(unit)));
chinook.QueueActivity(new Wait(150));
chinook.QueueActivity(new HeliFly(exit));
chinook.QueueActivity(new HeliFly(chinook, Target.FromCell(exit)));
chinook.QueueActivity(new RemoveSelf());
return Pair.New(chinook, unit);
}
@@ -101,7 +101,7 @@ namespace OpenRA.Mods.RA.Missions
});
badger.Trait<AttackBomber>().SetTarget(location.CenterPosition);
badger.QueueActivity(Fly.ToCell(location));
badger.QueueActivity(new Fly(badger, Target.FromCell(location)));
badger.QueueActivity(new FlyOffMap());
badger.QueueActivity(new RemoveSelf());
}

View File

@@ -123,7 +123,7 @@ namespace OpenRA.Mods.RA.Missions
void SetSovietUnitsToDefensiveStance()
{
foreach (var actor in world.Actors.Where(a => a.IsInWorld && a.Owner == soviets && !a.IsDead() && a.HasTrait<AutoTarget>()))
actor.Trait<AutoTarget>().stance = UnitStance.Defend;
actor.Trait<AutoTarget>().Stance = UnitStance.Defend;
}
Actor FirstUnshroudedOrDefault(IEnumerable<Actor> actors, World world, int shroudRange)

View File

@@ -540,6 +540,7 @@ namespace OpenRA.Mods.RA.Move
public Activity MoveTo(CPos cell, int nearEnough) { return new Move(cell, nearEnough); }
public Activity MoveTo(CPos cell, Actor ignoredActor) { return new Move(cell, ignoredActor); }
public Activity MoveWithinRange(Target target, WRange range) { return new Move(target, range); }
public Activity MoveFollow(Actor self, Target target, WRange range) { return new Follow(self, target, range); }
public Activity MoveTo(Func<List<CPos>> pathFunc) { return new Move(pathFunc); }
}
}

View File

@@ -488,6 +488,7 @@
<Compile Include="Render\WithCrateBody.cs" />
<Compile Include="Buildings\Demolishable.cs" />
<Compile Include="Widgets\Logic\DisconnectWatcherLogic.cs" />
<Compile Include="Activities\FlyFollow.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
@@ -263,7 +263,7 @@ namespace OpenRA.Mods.RA.Scripting
[LuaGlobal]
public void FlyToPos(Actor actor, WPos pos)
{
actor.QueueActivity(Fly.ToPos(pos));
actor.QueueActivity(new Fly(actor, Target.FromPos(pos)));
}
[LuaGlobal]
@@ -278,12 +278,18 @@ namespace OpenRA.Mods.RA.Scripting
actor.QueueActivity(new FlyAttack(Target.FromCell(location)));
}
[LuaGlobal]
public void HeliFlyToPos(Actor actor, WPos pos)
{
actor.QueueActivity(new HeliFly(actor, Target.FromPos(pos)));
}
[LuaGlobal]
public void SetUnitStance(Actor actor, string stance)
{
var at = actor.TraitOrDefault<AutoTarget>();
if (at != null)
at.stance = Enum<UnitStance>.Parse(stance);
at.Stance = Enum<UnitStance>.Parse(stance);
}
[LuaGlobal]

View File

@@ -92,7 +92,7 @@ namespace OpenRA.Mods.RA
if (flare != null)
a.QueueActivity(new CallFunc(() => flare.Destroy()));
a.QueueActivity(Fly.ToPos(finishEdge + spawnOffset));
a.QueueActivity(new Fly(a, Target.FromPos(finishEdge + spawnOffset)));
a.QueueActivity(new RemoveSelf());
}
});

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA
});
plane.CancelActivity();
plane.QueueActivity(Fly.ToCell(order.TargetLocation));
plane.QueueActivity(new Fly(plane, Target.FromCell(order.TargetLocation)));
plane.QueueActivity(new CallFunc(() => plane.World.AddFrameEndTask( w =>
{
var camera = w.CreateActor("camera", new TypeDictionary

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
@@ -150,7 +150,7 @@ namespace OpenRA.Mods.RA.Widgets
var stances = Enum<UnitStance>.GetValues();
var nextStance = stances.Concat(stances)
.SkipWhile(s => s != actor.Second.predictedStance)
.SkipWhile(s => s != actor.Second.PredictedStance)
.Skip(1)
.First();
@@ -158,7 +158,7 @@ namespace OpenRA.Mods.RA.Widgets
{
var at = a.TraitOrDefault<AutoTarget>();
if (at != null)
at.predictedStance = nextStance;
at.PredictedStance = nextStance;
// FIXME: Abuse of the type system here with `CPos`
return new Order("SetUnitStance", a, false) { TargetLocation = new CPos((int)nextStance, 0) };