added IIssueOrder2. most orders are broken, but Minelayer is fixed
This commit is contained in:
@@ -110,23 +110,6 @@ namespace OpenRA
|
||||
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
|
||||
}
|
||||
|
||||
public Order Order( int2 xy, MouseInput mi, Actor underCursor )
|
||||
{
|
||||
if (Owner != World.LocalPlayer)
|
||||
return null;
|
||||
|
||||
if (!World.Map.IsInMap(xy.X, xy.Y))
|
||||
return null;
|
||||
|
||||
if (Destroyed)
|
||||
return null;
|
||||
|
||||
return TraitsImplementing<IIssueOrder>()
|
||||
.OrderByDescending( x => x.OrderPriority( this, xy, mi, underCursor ) )
|
||||
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
|
||||
.FirstOrDefault( x => x != null );
|
||||
}
|
||||
|
||||
public RectangleF GetBounds(bool useAltitude)
|
||||
{
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
|
||||
@@ -178,7 +178,7 @@ namespace OpenRA
|
||||
LobbyInfoChanged();
|
||||
}
|
||||
|
||||
public static void IssueOrder(Order o) { orderManager.IssueOrder(o); } /* avoid exposing the OM to mod code */
|
||||
public static void IssueOrder( Order o ) { orderManager.IssueOrder( o ); } /* avoid exposing the OM to mod code */
|
||||
|
||||
|
||||
public static event Action AfterGameStart = () => {};
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Orders
|
||||
{
|
||||
@@ -25,17 +26,17 @@ namespace OpenRA.Orders
|
||||
.FirstOrDefault();
|
||||
|
||||
var orders = world.Selection.Actors
|
||||
.Select(a => a.Order(xy, mi, underCursor))
|
||||
.Select(a => OrderForUnit(a, xy, mi, underCursor))
|
||||
.Where(o => o != null)
|
||||
.ToArray();
|
||||
|
||||
var actorsInvolved = orders.Select(o => o.Subject).Distinct();
|
||||
var actorsInvolved = orders.Select(o => o.self).Distinct();
|
||||
if (actorsInvolved.Any())
|
||||
yield return new Order("CreateGroup", actorsInvolved.First().Owner.PlayerActor,
|
||||
string.Join(",", actorsInvolved.Select(a => a.ActorID.ToString()).ToArray()));
|
||||
|
||||
foreach (var o in orders)
|
||||
yield return o;
|
||||
foreach( var o in orders )
|
||||
yield return CheckSameOrder( o.iot, o.trait.IssueOrder( o.self, o.iot, o.target ) );
|
||||
}
|
||||
|
||||
public void Tick( World world ) {}
|
||||
@@ -61,23 +62,90 @@ namespace OpenRA.Orders
|
||||
}
|
||||
|
||||
public string GetCursor( World world, int2 xy, MouseInput mi )
|
||||
{
|
||||
if (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any())
|
||||
{
|
||||
var underCursor = world.FindUnitsAtMouse(mi.Location)
|
||||
.Where(a => a.Info.Traits.Contains<SelectableInfo>())
|
||||
.Any();
|
||||
.Where(a => a.Info.Traits.Contains<TargetableInfo>())
|
||||
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (underCursor)
|
||||
if( mi.Modifiers.HasModifier( Modifiers.Shift ) || !world.Selection.Actors.Any() )
|
||||
if( underCursor != null )
|
||||
return "select";
|
||||
|
||||
var orders = world.Selection.Actors
|
||||
.Select(a => OrderForUnit(a, xy, mi, underCursor))
|
||||
.Where(o => o != null)
|
||||
.ToArray();
|
||||
|
||||
if( orders.Length == 0 ) return "default";
|
||||
|
||||
return orders[ 0 ].cursor ?? "default";
|
||||
}
|
||||
|
||||
var c = Order(world, xy, mi)
|
||||
.Select(o => o.Subject.TraitsImplementing<IOrderCursor>()
|
||||
.Select(pc => pc.CursorForOrder(o.Subject, o)).FirstOrDefault(a => a != null))
|
||||
.FirstOrDefault(a => a != null);
|
||||
static UnitOrderResult OrderForUnit( Actor self, int2 xy, MouseInput mi, Actor underCursor )
|
||||
{
|
||||
if (self.Owner != self.World.LocalPlayer)
|
||||
return null;
|
||||
|
||||
return c ?? "default";
|
||||
if (!self.World.Map.IsInMap(xy.X, xy.Y))
|
||||
return null;
|
||||
|
||||
if (self.Destroyed)
|
||||
return null;
|
||||
|
||||
//var old = self.TraitsImplementing<IIssueOrder>()
|
||||
// .OrderByDescending( x => x.OrderPriority( self, xy, mi, underCursor ) )
|
||||
// .Select( x => x.IssueOrder( self, xy, mi, underCursor ) )
|
||||
// .FirstOrDefault( x => x != null );
|
||||
//if( old != null )
|
||||
// return old;
|
||||
|
||||
if( mi.Button == MouseButton.Right )
|
||||
{
|
||||
var uim = self.World.WorldActor.Trait<UnitInfluence>();
|
||||
foreach( var o in self.TraitsImplementing<IIssueOrder2>()
|
||||
.SelectMany( trait => trait.Orders
|
||||
.Select( x => new { Trait = trait, Order = x } ) )
|
||||
.OrderByDescending( x => x.Order.OrderPriority ) )
|
||||
{
|
||||
var actorsAt = uim.GetUnitsAt( xy ).ToList();
|
||||
|
||||
string cursor = null;
|
||||
if( o.Order.CanTargetUnit( self, underCursor, mi.Modifiers.HasModifier( Modifiers.Ctrl ), mi.Modifiers.HasModifier( Modifiers.Alt ), ref cursor ) )
|
||||
return new UnitOrderResult( self, o.Order, o.Trait, cursor, Target.FromActor( underCursor ) );
|
||||
if( o.Order.CanTargetLocation( self, xy, actorsAt, mi.Modifiers.HasModifier( Modifiers.Ctrl ), mi.Modifiers.HasModifier( Modifiers.Alt ), ref cursor ) )
|
||||
return new UnitOrderResult( self, o.Order, o.Trait, cursor, Target.FromCell( xy ) );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static Order CheckSameOrder( IOrderTargeter iot, Order order )
|
||||
{
|
||||
if( order == null && iot.OrderID != null )
|
||||
Game.Debug( "BUG: in order targeter - decided on {0} but then didn't order", iot.OrderID );
|
||||
else if( iot.OrderID != order.OrderString )
|
||||
Game.Debug( "BUG: in order targeter - decided on {0} but ordered {1}", iot.OrderID, order.OrderString );
|
||||
return order;
|
||||
}
|
||||
|
||||
class UnitOrderResult
|
||||
{
|
||||
public readonly Actor self;
|
||||
public readonly IOrderTargeter iot;
|
||||
public readonly IIssueOrder2 trait;
|
||||
public readonly string cursor;
|
||||
public readonly Target target;
|
||||
|
||||
public UnitOrderResult( Actor self, IOrderTargeter iot, IIssueOrder2 trait, string cursor, Target target )
|
||||
{
|
||||
this.self = self;
|
||||
this.iot = iot;
|
||||
this.trait = trait;
|
||||
this.cursor = cursor;
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using OpenRA.Effects;
|
||||
using OpenRA.Traits.Activities;
|
||||
using OpenRA.FileFormats;
|
||||
using System.Diagnostics;
|
||||
using OpenRA.Orders;
|
||||
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
@@ -53,7 +54,7 @@ namespace OpenRA.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class Mobile : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice, IOccupySpace, IMove, IFacing, INudge
|
||||
public class Mobile : IIssueOrder2, IResolveOrder, IOrderCursor, IOrderVoice, IOccupySpace, IMove, IFacing, INudge
|
||||
{
|
||||
public readonly Actor self;
|
||||
public readonly MobileInfo Info;
|
||||
@@ -131,21 +132,17 @@ namespace OpenRA.Traits
|
||||
self.CenterLocation = Util.CenterOfCell(fromCell);
|
||||
}
|
||||
|
||||
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
{
|
||||
// Force move takes precedence
|
||||
return mi.Modifiers.HasModifier(Modifiers.Alt) ? int.MaxValue : 0;
|
||||
}
|
||||
public IEnumerable<IOrderTargeter> Orders { get { yield return new MoveOrderTargeter( Info ); } }
|
||||
|
||||
// Note: Returns a valid order even if the unit can't move to the target
|
||||
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
|
||||
{
|
||||
if (Info.OnRails) return null;
|
||||
|
||||
if (mi.Button == MouseButton.Left) return null;
|
||||
|
||||
var type = (!self.World.LocalPlayer.Shroud.IsVisible(xy) || CanEnterCell(xy)) ? "Move" : "Move-Blocked";
|
||||
return new Order(type, self, xy, mi.Modifiers.HasModifier(Modifiers.Shift));
|
||||
if( order is MoveOrderTargeter )
|
||||
{
|
||||
if( Info.OnRails ) return null;
|
||||
return new Order( "Move", self, Util.CellContaining( target.CenterLocation ), false );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int2 NearestMoveableCell(int2 target)
|
||||
@@ -369,5 +366,31 @@ namespace OpenRA.Traits
|
||||
Log.Write("debug", "OnNudge #{0} refuses at {1}",
|
||||
self.ActorID, self.Location);
|
||||
}
|
||||
|
||||
class MoveOrderTargeter : IOrderTargeter
|
||||
{
|
||||
readonly MobileInfo unitType;
|
||||
|
||||
public MoveOrderTargeter( MobileInfo unitType )
|
||||
{
|
||||
this.unitType = unitType;
|
||||
}
|
||||
|
||||
public string OrderID { get { return "Move"; } }
|
||||
public int OrderPriority { get { return 4; } }
|
||||
|
||||
public bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor )
|
||||
{
|
||||
cursor = "move";
|
||||
if( self.World.LocalPlayer.Shroud.IsVisible( location ) && !self.Trait<Mobile>().CanEnterCell( location ) )
|
||||
cursor = "move-blocked";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,18 @@ namespace OpenRA.Traits
|
||||
Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor );
|
||||
int OrderPriority( Actor self, int2 xy, MouseInput mi, Actor underCursor );
|
||||
}
|
||||
public interface IIssueOrder2
|
||||
{
|
||||
IEnumerable<IOrderTargeter> Orders { get; }
|
||||
Order IssueOrder( Actor self, IOrderTargeter order, Target target );
|
||||
}
|
||||
public interface IOrderTargeter
|
||||
{
|
||||
string OrderID { get; }
|
||||
int OrderPriority { get; }
|
||||
bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor );
|
||||
bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor );
|
||||
}
|
||||
public interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
|
||||
public interface IOrderCursor { string CursorForOrder(Actor self, Order order); }
|
||||
public interface IOrderVoice { string VoicePhraseForOrder(Actor self, Order order); }
|
||||
|
||||
@@ -26,44 +26,35 @@ namespace OpenRA.Mods.RA
|
||||
public readonly string[] RearmBuildings = { "fix" };
|
||||
}
|
||||
|
||||
class Minelayer : IIssueOrder, IResolveOrder, IOrderCursor, IPostRenderSelection
|
||||
class Minelayer : IIssueOrder2, IResolveOrder, IPostRenderSelection
|
||||
{
|
||||
/* [Sync] when sync can cope with arrays! */
|
||||
public int2[] minefield = null;
|
||||
[Sync] int2 minefieldStart;
|
||||
|
||||
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
public IEnumerable<IOrderTargeter> Orders
|
||||
{
|
||||
return 5;
|
||||
get { yield return new BeginMinefieldOrderTargeter(); }
|
||||
}
|
||||
|
||||
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
|
||||
{
|
||||
if (mi.Button == MouseButton.Right && underCursor == null && mi.Modifiers.HasModifier(Modifiers.Ctrl))
|
||||
return new Order("BeginMinefield", self, xy);
|
||||
|
||||
if( order is BeginMinefieldOrderTargeter )
|
||||
{
|
||||
var start = Util.CellContaining( target.CenterLocation );
|
||||
self.World.OrderGenerator = new MinefieldOrderGenerator( self, start );
|
||||
return new Order( "BeginMinefield", self, start );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public string CursorForOrder(Actor self, Order order)
|
||||
{
|
||||
return (order.OrderString == "BeginMinefield") ? "ability" : null;
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "BeginMinefield")
|
||||
{
|
||||
//minefieldStart = order.TargetLocation;
|
||||
//if (self.Owner == self.World.LocalPlayer)
|
||||
// self.World.OrderGenerator = new MinefieldOrderGenerator(self);
|
||||
}
|
||||
if( order.OrderString == "BeginMinefield" )
|
||||
minefieldStart = order.TargetLocation;
|
||||
|
||||
if (order.OrderString == "PlaceMinefield")
|
||||
{
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
self.World.CancelInputMode();
|
||||
|
||||
var movement = self.Trait<IMove>();
|
||||
|
||||
minefield = GetMinefieldCells(minefieldStart, order.TargetLocation,
|
||||
@@ -97,9 +88,10 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
class MinefieldOrderGenerator : IOrderGenerator
|
||||
{
|
||||
Actor minelayer;
|
||||
readonly Actor minelayer;
|
||||
readonly int2 minefieldStart;
|
||||
|
||||
public MinefieldOrderGenerator(Actor self) { minelayer = self; }
|
||||
public MinefieldOrderGenerator(Actor self, int2 xy ) { minelayer = self; minefieldStart = xy; }
|
||||
|
||||
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi)
|
||||
{
|
||||
@@ -114,8 +106,11 @@ namespace OpenRA.Mods.RA
|
||||
? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (mi.Button == MouseButton.Right && underCursor == null)
|
||||
yield return new Order("PlaceMinefield", minelayer, xy);
|
||||
if( mi.Button == MouseButton.Right && underCursor == null )
|
||||
{
|
||||
minelayer.World.CancelInputMode();
|
||||
yield return new Order( "PlaceMinefield", minelayer, xy );
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick(World world)
|
||||
@@ -132,7 +127,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
var ml = minelayer.Trait<Minelayer>();
|
||||
var movement = minelayer.Trait<IMove>();
|
||||
var minefield = GetMinefieldCells(ml.minefieldStart, lastMousePos, minelayer.Info.Traits.Get<MinelayerInfo>().MinefieldDepth)
|
||||
var minefield = GetMinefieldCells(minefieldStart, lastMousePos, minelayer.Info.Traits.Get<MinelayerInfo>().MinefieldDepth)
|
||||
.Where(p => movement.CanEnterCell(p)).ToArray();
|
||||
|
||||
world.WorldRenderer.DrawLocus(Color.Cyan, minefield);
|
||||
@@ -151,5 +146,22 @@ namespace OpenRA.Mods.RA
|
||||
if (minefield != null)
|
||||
self.World.WorldRenderer.DrawLocus(Color.Cyan, minefield);
|
||||
}
|
||||
|
||||
class BeginMinefieldOrderTargeter : IOrderTargeter
|
||||
{
|
||||
public string OrderID { get { return "BeginMinefield"; } }
|
||||
public int OrderPriority { get { return 5; } }
|
||||
|
||||
public bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor )
|
||||
{
|
||||
cursor = "ability";
|
||||
return ( actorsAtLocation.Count == 0 && forceAttack );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using OpenRA.Mods.RA.Activities;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
using OpenRA.GameRules;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.RA
|
||||
{
|
||||
@@ -27,7 +28,7 @@ namespace OpenRA.Mods.RA
|
||||
public virtual object Create(ActorInitializer init) { return new Transforms(this); }
|
||||
}
|
||||
|
||||
class Transforms : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice
|
||||
class Transforms : IIssueOrder2, IResolveOrder, IOrderVoice
|
||||
{
|
||||
TransformsInfo Info;
|
||||
BuildingInfo bi;
|
||||
@@ -38,19 +39,6 @@ namespace OpenRA.Mods.RA
|
||||
bi = Rules.Info[info.IntoActor].Traits.GetOrDefault<BuildingInfo>();
|
||||
}
|
||||
|
||||
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
|
||||
{
|
||||
if (mi.Button == MouseButton.Right && self == underCursor)
|
||||
return new Order("DeployTransform", self);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public string VoicePhraseForOrder(Actor self, Order order)
|
||||
{
|
||||
return (order.OrderString == "DeployTransform") ? "Move" : null;
|
||||
@@ -61,6 +49,16 @@ namespace OpenRA.Mods.RA
|
||||
return (bi == null || self.World.CanPlaceBuilding(Info.IntoActor, bi, self.Location + Info.Offset, self));
|
||||
}
|
||||
|
||||
public IEnumerable<IOrderTargeter> Orders { get { yield return new TransformOrderTargeter(); } }
|
||||
|
||||
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
|
||||
{
|
||||
if( order is TransformOrderTargeter )
|
||||
return new Order( "DeployTransform", self );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void ResolveOrder( Actor self, Order order )
|
||||
{
|
||||
if (order.OrderString == "DeployTransform")
|
||||
@@ -80,12 +78,28 @@ namespace OpenRA.Mods.RA
|
||||
}
|
||||
}
|
||||
|
||||
public string CursorForOrder(Actor self, Order order)
|
||||
class TransformOrderTargeter : IOrderTargeter
|
||||
{
|
||||
if (order.OrderString != "DeployTransform")
|
||||
return null;
|
||||
public string OrderID
|
||||
{
|
||||
get { return "DeployTransform"; }
|
||||
}
|
||||
|
||||
return CanDeploy(self) ? "deploy" : "deploy-blocked";
|
||||
public int OrderPriority
|
||||
{
|
||||
get { return 5; }
|
||||
}
|
||||
|
||||
public bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
|
||||
{
|
||||
cursor = self.Trait<Transforms>().CanDeploy( self ) ? "deploy" : "deploy-blocked";
|
||||
return self == target;
|
||||
}
|
||||
|
||||
public bool CanTargetLocation( Actor self, int2 location, System.Collections.Generic.List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user