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

@@ -1,6 +1,8 @@
NEW:
All Mods:
An error dialog is now displayed when server connections are lost.
Added AttackMove and Guard abilities to Aircraft and Helicopters.
Aircraft and Helicopters can now be guarded by other units.
Unified the main menu navigation between TD and other mods:
Moved Create Game and Direct Connect facilities to the server browser.
Added skirmish mode to RA and D2k to complement TD's skirmish mode.
@@ -19,7 +21,6 @@ NEW:
Fixed transparency glitches in the sniper icon.
Tiberian Dawn:
Commando can now plant C4 on bridges.
Helicopters can now AttackMove.
Engine:
Converted Aircraft CruiseAltitude to world coordinates.
Converted Health Radius to world coordinates.

View File

@@ -153,6 +153,7 @@ namespace OpenRA.Traits
Activity MoveTo(CPos cell, int nearEnough);
Activity MoveTo(CPos cell, Actor ignoredActor);
Activity MoveWithinRange(Target target, WRange range);
Activity MoveFollow(Actor self, Target target, WRange range);
CPos NearestMoveableCell(CPos target);
}

View File

@@ -60,7 +60,7 @@ namespace OpenRA.Mods.Cnc
new FacingInit(64)
});
a.QueueActivity(Fly.ToCell(self.Location + new CVec(9, 0)));
a.QueueActivity(new Fly(a, Target.FromCell(self.Location + new CVec(9, 0))));
a.QueueActivity(new Land(Target.FromActor(self)));
a.QueueActivity(new CallFunc(() =>
{
@@ -71,7 +71,8 @@ namespace OpenRA.Mods.Cnc
self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit));
Sound.PlayNotification(self.Owner, "Speech", (Info as ProductionAirdropInfo).ReadyAudio, self.Owner.Country.Race);
}));
a.QueueActivity(Fly.ToCell(endPos));
a.QueueActivity(new Fly(a, Target.FromCell(endPos)));
a.QueueActivity(new RemoveSelf());
});

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) };

View File

@@ -116,6 +116,8 @@
EmptyWeapon: HeliExplode
CombatDebugOverlay:
AttackMove:
Guard:
Guardable:
BodyOrientation:
UpdatesPlayerStatistics:
Huntable:
@@ -209,7 +211,6 @@
NotifyAll: true
ScaredyCat:
RenderInfantryPanic:
AttackMove:
CrushableInfantry:
^DINO:
@@ -274,6 +275,7 @@
CombatDebugOverlay:
BodyOrientation:
Huntable:
AttackMove:
LuaScriptEvents:
^Ship:

View File

@@ -171,7 +171,6 @@ E6:
Captures:
CaptureTypes: building, husk
-AutoTarget:
AttackMove:
RenderInfantryProne:
IdleAnimations: idle1,idle2
StandAnimations: stand, stand2

View File

@@ -66,6 +66,5 @@ LST:
Types: Infantry, Vehicle
MaxWeight: 5
PipCount: 5
AttackMove:
RejectsOrders:

View File

@@ -27,7 +27,6 @@ MCV:
NoTransformSounds: deploy1.aud
RenderUnit:
MustBeDestroyed:
AttackMove:
BaseBuilding:
LeavesHusk:
HuskActor: MCV.Husk
@@ -67,7 +66,6 @@ HARV:
Type: Heavy
RevealsShroud:
Range: 4
AttackMove:
LeavesHusk:
HuskActor: HARV.Husk
-GainsExperience:
@@ -556,7 +554,6 @@ MHQ:
WithIdleOverlay@SPINNER:
Sequence: spinner
Offset: -256,0,256
AttackMove:
Explodes:
Weapon: UnitExplodeSmall
EmptyWeapon: UnitExplodeSmall

View File

@@ -29,7 +29,7 @@ end
Actor.ScriptedMove = function(actor, location)
if Actor.HasTrait(actor, "Helicopter") then
actor:QueueActivity(OpenRA.New("HeliFly", { location.CenterPosition }))
Internal.HeliFlyToPos(actor, location.CenterPosition)
else
actor:QueueActivity(OpenRA.New("Move", { location }))
end
@@ -52,7 +52,7 @@ Actor.AttackMove = function(actor, location)
end
Actor.HeliFly = function(actor, position)
actor:QueueActivity(OpenRA.New("HeliFly", { position }))
Internal.HeliFlyToPos(actor, position)
end
Actor.HeliLand = function(actor, requireSpace)

View File

@@ -207,6 +207,7 @@
BodyOrientation:
UpdatesPlayerStatistics:
Huntable:
AttackMove:
LuaScriptEvents:
^Helicopter:

View File

@@ -52,7 +52,6 @@ ENGINEER:
Captures:
CaptureTypes: husk
-AutoTarget:
AttackMove:
BAZOOKA:
Inherits: ^Infantry
@@ -110,5 +109,3 @@ MEDIC:
Passenger:
PipType: Blue
-AutoTarget:
AttackMove:

View File

@@ -297,5 +297,3 @@ SABOTEUR:
C4Demolition:
C4Delay: 45
-AutoTarget:
AttackMove:

View File

@@ -24,7 +24,6 @@
Range: 8
MustBeDestroyed:
BaseBuilding:
-AttackMove:
Explodes:
Weapon: UnitExplodeScale
EmptyWeapon: UnitExplodeScale
@@ -80,7 +79,6 @@ HARVESTER:
Explodes:
Weapon: UnitExplodeScale
EmptyWeapon: UnitExplodeScale
-AttackMove:
LeavesHusk:
HuskActor: Harvester.Husk
WithHarvestAnimation:

View File

@@ -848,7 +848,6 @@ Rules:
TakeCover:
Spy:
-AutoTarget:
AttackMove:
-RenderInfantry:
RenderSpy:
IdleAnimations: idle1,idle2

View File

@@ -832,7 +832,6 @@ Rules:
Range: 40
RenderUnit:
Image: MNLY
AttackMove:
MustBeDestroyed:
Transforms:
IntoActor: ftur

View File

@@ -102,6 +102,10 @@ MIG:
ROT: 5
Speed: 186
RearmBuildings: afld
AutoTarget:
TargetWhenIdle: false
TargetWhenDamaged: false
EnableStances: false
RenderUnit:
CameraPitch: 99
WithShadow:
@@ -154,6 +158,10 @@ YAK:
InitialFacing: 192
ROT: 5
Speed: 149
AutoTarget:
TargetWhenIdle: false
TargetWhenDamaged: false
EnableStances: false
RenderUnit:
CameraPitch: 99
WithShadow:
@@ -247,6 +255,10 @@ HELI:
InitialFacing: 20
ROT: 4
Speed: 149
AutoTarget:
TargetWhenIdle: false
TargetWhenDamaged: false
EnableStances: false
RenderUnit:
WithRotor:
Offset: 0,0,85
@@ -293,6 +305,10 @@ HIND:
InitialFacing: 20
ROT: 4
Speed: 112
AutoTarget:
TargetWhenIdle: false
TargetWhenDamaged: false
EnableStances: false
RenderUnit:
WithRotor:
WithShadow:
@@ -334,4 +350,4 @@ U2:
SmokeTrailWhenDamaged:
Offset: -1c43,0,0
Interval: 2
RejectsOrders:
RejectsOrders:

View File

@@ -196,6 +196,9 @@
TargetTypes: Air
GroundedTargetTypes: Ground
HiddenUnderFog:
AttackMove:
Guard:
Guardable:
GainsExperience:
GivesExperience:
DrawLineToTarget:

View File

@@ -177,7 +177,6 @@ E6:
CaptureTypes: husk
TakeCover:
-AutoTarget:
AttackMove:
-RenderInfantry:
RenderInfantryProne:
IdleAnimations: idle1,idle2
@@ -212,7 +211,6 @@ SPY:
Infiltrates:
Types: Cash, SupportPower, Exploration
-AutoTarget:
AttackMove:
-RenderInfantry:
RenderSpy:
IdleAnimations: idle1,idle2
@@ -289,7 +287,6 @@ MEDI:
Cursor: heal
TakeCover:
-AutoTarget:
AttackMove:
-RenderInfantry:
RenderInfantryProne:
IdleAnimations: idle1,idle2
@@ -325,7 +322,6 @@ MECH:
Cursor: repair
TakeCover:
-AutoTarget:
AttackMove:
-RenderInfantry:
RenderInfantryProne:
IdleAnimations: idle1,idle2
@@ -346,7 +342,6 @@ EINSTEIN:
RevealsShroud:
Range: 2
-AutoTarget:
AttackMove:
ProximityCaptor:
Types: CivilianInfantry
-RenderInfantry:
@@ -369,7 +364,6 @@ DELPHI:
RevealsShroud:
Range: 2
-AutoTarget:
AttackMove:
ProximityCaptor:
Types: CivilianInfantry
-RenderInfantry:
@@ -410,7 +404,6 @@ THF:
InfiltrateTypes: Cash
TakeCover:
-AutoTarget:
AttackMove:
SHOK:
Inherits: ^Infantry

View File

@@ -43,7 +43,6 @@ SS:
-DetectCloaked:
AutoTarget:
InitialStance: HoldFire
AttackMove:
MSUB:
Inherits: ^Ship
@@ -90,7 +89,6 @@ MSUB:
-DetectCloaked:
AutoTarget:
InitialStance: HoldFire
AttackMove:
DD:
Inherits: ^Ship
@@ -225,7 +223,6 @@ LST:
PipCount: 5
IronCurtainable:
RepairableNear:
AttackMove:
PT:
Inherits: ^Ship

View File

@@ -271,7 +271,6 @@ HARV:
Range: 4
RenderHarvester:
ImagesByFullness: harvempty, harvhalf, harv
-AttackMove:
GpsDot:
String: Harvester
LeavesHusk:
@@ -316,7 +315,6 @@ MCV:
RenderUnit:
MustBeDestroyed:
BaseBuilding:
-AttackMove:
LeavesHusk:
HuskActor: MCV.Husk
@@ -418,7 +416,6 @@ MNLY.AP:
MineImmune:
LimitedAmmo:
Ammo: 5
AttackMove:
DetectCloaked:
Range: 5
RenderDetectionCircle:
@@ -451,7 +448,6 @@ MNLY.AT:
MineImmune:
LimitedAmmo:
Ammo: 3
AttackMove:
DetectCloaked:
Range: 5
RenderDetectionCircle:
@@ -480,7 +476,6 @@ TRUK:
RenderUnit:
SupplyTruck:
Payload: 500
AttackMove:
MGG:
Inherits: ^Vehicle
@@ -505,7 +500,6 @@ MGG:
WithIdleOverlay@SPINNER:
Offset: -299,0,171
Sequence: spinner
AttackMove:
RevealsShroud:
Range: 6
CreatesShroud:
@@ -542,7 +536,6 @@ MRJ:
WithIdleOverlay@SPINNER:
Sequence: spinner
Offset: -256,0,256
AttackMove:
Explodes:
Weapon: UnitExplodeSmall
EmptyWeapon: UnitExplodeSmall
@@ -646,7 +639,6 @@ DTRK:
RevealsShroud:
Range: 3
RenderUnit:
AttackMove:
Explodes:
Weapon: MiniNuke
EmptyWeapon: MiniNuke
@@ -717,11 +709,9 @@ QTNK:
Selectable:
Bounds: 44,38,0,-4
RenderUnit:
AttackMove:
Explodes:
Weapon: UnitExplodeSmall
MadTank:
-EjectOnDeath:
TargetableUnit:
TargetTypes: Ground, MADTank

View File

@@ -195,6 +195,7 @@
Buildable:
Queue: Aircraft
HiddenUnderFog:
AttackMove:
GainsExperience:
GivesExperience:
DrawLineToTarget:

View File

@@ -165,7 +165,6 @@ ENGINEER:
Captures:
CaptureTypes: building
-AutoTarget:
AttackMove:
-RenderInfantry:
RenderInfantryProne:
IdleAnimations: idle1,idle2
@@ -292,7 +291,6 @@ CHAMSPY:
Infiltrates:
Types: Cash, SupportPower, Exploration
-AutoTarget:
AttackMove:
-RenderInfantry:
RenderSpy:
IdleAnimations: idle1,idle2
@@ -468,7 +466,6 @@ MHIJACK:
RevealsShroud:
Range: 6
-AutoTarget:
-AttackMove:
TakeCover:
-RenderInfantry:
RenderInfantryProne:
@@ -495,7 +492,6 @@ TRATOS:
Range: 4
TakeCover:
-AutoTarget:
-AttackMove:
-RenderInfantry:
RenderInfantryProne:
IdleAnimations: idle1,idle2
@@ -521,7 +517,6 @@ OXANNA:
Range: 4
TakeCover:
-AutoTarget:
-AttackMove:
-RenderInfantry:
RenderInfantryProne:
IdleAnimations: idle1,idle2
@@ -547,7 +542,6 @@ SLAV:
Range: 4
TakeCover:
-AutoTarget:
-AttackMove:
-RenderInfantry:
RenderInfantryProne:
IdleAnimations: idle1,idle2
@@ -605,7 +599,6 @@ VISSML:
TargetableUnit:
TargetTypes: Ground
-AutoTarget:
-AttackMove:
-RenderInfantry:
RenderUnit:

View File

@@ -24,7 +24,6 @@ MCV:
Range: 4
MustBeDestroyed:
BaseBuilding:
-AttackMove:
Transforms:
IntoActor: gacnst
Offset: -1,-1
@@ -57,7 +56,6 @@ APC:
Range: 5
Turreted:
ROT: 10
-AttackMove:
Cargo:
Types: Infantry
MaxWeight: 5
@@ -93,7 +91,6 @@ HARV:
Type: Heavy
RevealsShroud:
Range: 4
AttackMove:
-GainsExperience:
RenderSprites:
RenderVoxels:
@@ -188,7 +185,6 @@ TRUCKB:
Range: 5
SupplyTruck:
Payload: 500
AttackMove:
RenderSprites:
RenderVoxels:
WithVoxelBody:
@@ -212,7 +208,6 @@ LPST:
ROT: 5
RevealsShroud:
Range: 10
AttackMove:
RenderSprites:
RenderVoxels:
WithVoxelBody:
@@ -242,7 +237,6 @@ ICBM:
ROT: 5
RevealsShroud:
Range: 7
AttackMove:
RenderSprites:
RenderVoxels:
WithVoxelBody:
@@ -275,7 +269,6 @@ REPAIR:
Weapon: Repair
AttackMedic:
Cursor: repair
AttackMove:
RenderSprites:
RenderVoxels:
WithVoxelBody:
@@ -299,7 +292,6 @@ ART2:
ROT: 2
RevealsShroud:
Range: 9
AttackMove:
RenderSprites:
RenderVoxels:
WithVoxelBody:
@@ -330,7 +322,6 @@ WEED:
Type: Heavy
RevealsShroud:
Range: 4
AttackMove:
-GainsExperience:
RenderSprites:
RenderVoxels:
@@ -355,7 +346,6 @@ BUS:
Type: Light
RevealsShroud:
Range: 5
-AttackMove:
Cargo:
Types: Infantry
MaxWeight: 20
@@ -384,7 +374,6 @@ PICK:
Type: Light
RevealsShroud:
Range: 5
-AttackMove:
Cargo:
Types: Infantry
MaxWeight: 2
@@ -413,7 +402,6 @@ CAR:
Type: Light
RevealsShroud:
Range: 5
-AttackMove:
Cargo:
Types: Infantry
MaxWeight: 4
@@ -443,7 +431,6 @@ GGHUNT:
RevealsShroud:
Range: 7
RenderUnit:
AttackMove:
DemoTruck:
Explodes:
Weapon: SuicideBomb
@@ -468,7 +455,6 @@ WINI:
Type: Light
RevealsShroud:
Range: 5
-AttackMove:
Cargo:
Types: Infantry
MaxWeight: 5
@@ -648,7 +634,6 @@ SAPC:
Type: Heavy
RevealsShroud:
Range: 5
-AttackMove:
Cargo:
Types: Infantry
MaxWeight: 5
@@ -734,7 +719,6 @@ TTNK:
Type: Light
RevealsShroud:
Range: 5
-AttackMove:
RenderSprites:
RenderVoxels:
WithVoxelBody: