added IIssueOrder2. most orders are broken, but Minelayer is fixed

This commit is contained in:
Bob
2010-10-02 18:16:02 +12:00
committed by Paul Chote
parent 0cd140849b
commit 3d805ff40d
7 changed files with 215 additions and 103 deletions

View File

@@ -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>();

View File

@@ -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 = () => {};

View File

@@ -11,7 +11,8 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
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;
string.Join(",", actorsInvolved.Select(a => a.ActorID.ToString()).ToArray()));
foreach( var o in orders )
yield return CheckSameOrder( o.iot, o.trait.IssueOrder( o.self, o.iot, o.target ) );
}
public void Tick( World world ) {}
@@ -62,22 +63,89 @@ 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();
if (underCursor)
return "select";
}
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.Info.Traits.Contains<TargetableInfo>())
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
.FirstOrDefault();
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);
return c ?? "default";
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";
}
static UnitOrderResult OrderForUnit( Actor self, int2 xy, MouseInput mi, Actor underCursor )
{
if (self.Owner != self.World.LocalPlayer)
return null;
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;
}
}
}
}

View File

@@ -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;
}
// 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)
{
if (Info.OnRails) return null;
if (mi.Button == MouseButton.Left) return null;
public IEnumerable<IOrderTargeter> Orders { get { yield return new MoveOrderTargeter( Info ); } }
var type = (!self.World.LocalPlayer.Shroud.IsVisible(xy) || CanEnterCell(xy)) ? "Move" : "Move-Blocked";
return new Order(type, self, xy, mi.Modifiers.HasModifier(Modifiers.Shift));
// Note: Returns a valid order even if the unit can't move to the target
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
{
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;
}
}
}
}

View File

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