use new orders system in various traits

This commit is contained in:
Bob
2010-10-03 05:08:14 +13:00
committed by Paul Chote
parent 711d05da98
commit 4bc9e01516
12 changed files with 313 additions and 170 deletions

View File

@@ -8,11 +8,14 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using System.Drawing;
namespace OpenRA.Mods.RA
{
@@ -21,21 +24,19 @@ namespace OpenRA.Mods.RA
public readonly float C4Delay = 0;
}
class C4Demolition : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice
class C4Demolition : IIssueOrder2, IResolveOrder, IOrderVoice
{
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public IEnumerable<IOrderTargeter> Orders
{
return mi.Modifiers.HasModifier(Modifiers.Ctrl) ? 1001 : 1;
get { yield return new UnitTraitOrderTargeter<Building>( "C4", 6, "c4", true, false ); }
}
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) return null;
if (underCursor == null) return null;
if (!underCursor.HasTrait<Building>()) return null;
if (self.Owner.Stances[underCursor.Owner] != Stance.Enemy && !mi.Modifiers.HasModifier(Modifiers.Ctrl)) return null;
if( order.OrderID == "C4" )
return new Order( "C4", self, target.Actor );
return new Order("C4", self, underCursor);
return null;
}
public void ResolveOrder(Actor self, Order order)
@@ -58,11 +59,6 @@ namespace OpenRA.Mods.RA
}
}
public string CursorForOrder(Actor self, Order order)
{
return (order.OrderString == "C4") ? "c4" : null;
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "C4") ? "Attack" : null;

View File

@@ -13,30 +13,29 @@ using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Orders;
using System.Collections.Generic;
namespace OpenRA.Mods.RA
{
class EngineerCaptureInfo : TraitInfo<EngineerCapture> {}
class EngineerCapture : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice
class EngineerCapture : IIssueOrder2, IResolveOrder, IOrderVoice
{
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public IEnumerable<IOrderTargeter> Orders
{
return 5;
get
{
yield return new EnterBuildingOrderTargeter<Building>( "CaptureBuilding", 5, true, false,
target => target.Info.Traits.Get<BuildingInfo>().Capturable );
}
}
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) return null;
if (underCursor == null) return null;
if (self.Owner.Stances[underCursor.Owner] == Stance.Ally) return null;
if (!underCursor.HasTrait<Building>() || !underCursor.Info.Traits.Get<BuildingInfo>().Capturable) return null;
if( order.OrderID == "CaptureBuilding" )
return new Order( order.OrderID, self, target.Actor );
return new Order("CaptureBuilding", self, underCursor);
}
public string CursorForOrder(Actor self, Order order)
{
return (order.OrderString == "CaptureBuilding") ? "capture" : null;
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)

View File

@@ -8,9 +8,11 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
@@ -18,33 +20,19 @@ namespace OpenRA.Mods.RA
{
class EngineerRepairInfo : TraitInfo<EngineerRepair> {}
class EngineerRepair : IIssueOrder, IResolveOrder, IOrderCursor, IOrderVoice
class EngineerRepair : IIssueOrder2, IResolveOrder, IOrderVoice
{
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public IEnumerable<IOrderTargeter> Orders
{
return 5;
get { yield return new EngineerRepairOrderTargeter(); }
}
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) return null;
if (underCursor == null) return null;
if (!CanRepair(self, underCursor)) return null;
if( order.OrderID == "EngineerRepair" )
return new Order( order.OrderID, self, target.Actor );
return new Order("EngineerRepair", self, underCursor);
}
bool CanRepair(Actor self, Actor a)
{
if (!a.HasTrait<Building>()) return false;
return (self.Owner.Stances[a.Owner] == Stance.Ally);
}
public string CursorForOrder(Actor self, Order order)
{
if (order.OrderString != "EngineerRepair") return null;
if (order.TargetActor == null) return null;
return (order.TargetActor.GetDamageState() == DamageState.Undamaged) ? "goldwrench-blocked" : "goldwrench";
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)
@@ -72,5 +60,22 @@ namespace OpenRA.Mods.RA
self.QueueActivity(new RepairBuilding(order.TargetActor));
}
}
class EngineerRepairOrderTargeter : UnitTraitOrderTargeter<Building>
{
public EngineerRepairOrderTargeter()
: base( "EngineerRepair", 6, "goldwrench", false, true )
{
}
public override bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
{
if( !base.CanTargetUnit( self, target, forceAttack, forceMove, ref cursor ) ) return false;
if( target.GetDamageState() > DamageState.Undamaged )
cursor = "goldwrench-blocked";
return true;
}
}
}
}

View File

@@ -15,6 +15,7 @@ using OpenRA.Effects;
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.Mods.RA.Orders;
namespace OpenRA.Mods.RA
{
@@ -29,8 +30,8 @@ namespace OpenRA.Mods.RA
public object Create(ActorInitializer init) { return new Harvester(init.self, this); }
}
public class Harvester : IIssueOrder, IResolveOrder, INotifyDamage, IPips,
IRenderModifier, IExplodeModifier, IOrderCursor, IOrderVoice,
public class Harvester : IIssueOrder2, IResolveOrder, INotifyDamage, IPips,
IRenderModifier, IExplodeModifier, IOrderVoice,
ISpeedModifier
{
Dictionary<ResourceTypeInfo, int> contents = new Dictionary<ResourceTypeInfo, int>();
@@ -93,37 +94,23 @@ namespace OpenRA.Mods.RA
contents.Clear();
}
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public IEnumerable<IOrderTargeter> Orders
{
return 5;
get
{
yield return new EnterBuildingOrderTargeter<IAcceptOre>( "Deliver", 5, false, true, _ => !IsEmpty );
yield return new HarvestOrderTargeter();
}
}
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
{
if (mi.Button == MouseButton.Left) return null;
if( order.OrderID == "Deliver" )
return new Order( order.OrderID, self, target.Actor );
// Don't leak info about resources under the shroud
if (!self.World.LocalPlayer.Shroud.IsExplored(xy)) return null;
if( order.OrderID == "Harvest" )
return new Order( order.OrderID, self, Util.CellContaining( target.CenterLocation ) );
if (underCursor != null
&& self.Owner.Stances[ underCursor.Owner ] == Stance.Ally
&& underCursor.HasTrait<IAcceptOre>())
{
return new Order("Deliver", self, underCursor);
}
var res = self.World.WorldActor.Trait<ResourceLayer>().GetResource(xy);
var info = self.Info.Traits.Get<HarvesterInfo>();
if (underCursor == null && res != null && info.Resources.Contains(res.info.Name) && !IsFull)
return new Order("Harvest", self, xy);
return null;
}
public string CursorForOrder(Actor self, Order order)
{
if (order.OrderString == "Harvest") return "attackmove";
if (order.OrderString == "Deliver") return IsEmpty ? "enter-blocked" : "enter";
return null;
}
@@ -222,5 +209,30 @@ namespace OpenRA.Mods.RA
return float2.Lerp(1f, Info.FullyLoadedSpeed,
contents.Values.Sum() / (float)Info.Capacity);
}
class HarvestOrderTargeter : IOrderTargeter
{
public string OrderID { get { return "Harvest";}}
public int OrderPriority { get { return 10; } }
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 )
{
// Don't leak info about resources under the shroud
if( !self.World.LocalPlayer.Shroud.IsExplored( location ) ) return false;
var res = self.World.WorldActor.Trait<ResourceLayer>().GetResource( location );
var info = self.Info.Traits.Get<HarvesterInfo>();
if( res == null ) return false;
if( !info.Resources.Contains( res.info.Name ) ) return false;
cursor = "attackmove";
return true;
}
}
}
}

View File

@@ -93,7 +93,10 @@
<Compile Include="Effects\TeslaZap.cs" />
<Compile Include="LimitedAmmo.cs" />
<Compile Include="MPStartLocations.cs" />
<Compile Include="Orders\DeployOrderTargeter.cs" />
<Compile Include="Orders\EnterBuildingOrderTargeter.cs" />
<Compile Include="Orders\PlaceBuildingOrderGenerator.cs" />
<Compile Include="Orders\UnitOrderTargeter.cs" />
<Compile Include="Player\ActorGroupProxy.cs" />
<Compile Include="Aircraft.cs" />
<Compile Include="Player\ClassicProductionQueue.cs" />

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Orders
{
class DeployOrderTargeter : IOrderTargeter
{
readonly Func<bool> useDeployCursor;
public DeployOrderTargeter( string order, int priority )
: this( order, priority, () => true )
{
}
public DeployOrderTargeter( string order, int priority, Func<bool> useDeployCursor )
{
this.OrderID = order;
this.OrderPriority = priority;
this.useDeployCursor = useDeployCursor;
}
public string OrderID { get; private set; }
public int OrderPriority { get; private set; }
public bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
{
cursor = useDeployCursor() ? "deploy" : "deploy-blocked";
return self == target;
}
public bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor )
{
return false;
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Orders
{
class EnterBuildingOrderTargeter<T> : UnitTraitOrderTargeter<T>
{
readonly Func<Actor, bool> useEnterCursor;
public EnterBuildingOrderTargeter( string order, int priority, bool targetEnemy, bool targetAlly, Func<Actor, bool> useEnterCursor )
: base( order, priority, "enter", targetEnemy, targetAlly )
{
this.useEnterCursor = useEnterCursor;
}
public override bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
{
if( !base.CanTargetUnit( self, target, forceAttack, forceMove, ref cursor ) ) return false;
cursor = useEnterCursor( target ) ? "enter" : "enter-blocked";
return true;
}
}
}

View File

@@ -0,0 +1,70 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 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 LICENSE.
*/
#endregion
using System;
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Orders
{
class UnitOrderTargeter : IOrderTargeter
{
readonly string cursor;
readonly bool targetEnemyUnits, targetAllyUnits;
public UnitOrderTargeter( string order, int priority, string cursor, bool targetEnemyUnits, bool targetAllyUnits )
{
this.OrderID = order;
this.OrderPriority = priority;
this.cursor = cursor;
this.targetEnemyUnits = targetEnemyUnits;
this.targetAllyUnits = targetAllyUnits;
}
public string OrderID { get; private set; }
public int OrderPriority { get; private set; }
public virtual bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
{
if( self == null ) throw new ArgumentNullException( "self" );
if( target == null ) throw new ArgumentNullException( "target" );
cursor = this.cursor;
var playerRelationship = self.Owner.Stances[ target.Owner ];
if( !forceAttack && playerRelationship == Stance.Ally && !targetAllyUnits ) return false;
if( !forceAttack && playerRelationship == Stance.Enemy && !targetEnemyUnits ) return false;
return true;
}
public virtual bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor )
{
return false;
}
}
class UnitTraitOrderTargeter<T> : UnitOrderTargeter
{
public UnitTraitOrderTargeter( string order, int priority, string cursor, bool targetEnemyUnits, bool targetAllyUnits )
: base( order, priority, cursor, targetEnemyUnits, targetAllyUnits )
{
}
public override bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
{
if( !base.CanTargetUnit( self, target, forceAttack, forceMove, ref cursor ) ) return false;
if( !target.HasTrait<T>() ) return false;
return true;
}
}
}

View File

@@ -11,12 +11,13 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
using OpenRA.Mods.RA.Orders;
namespace OpenRA.Mods.RA
{
class PrimaryBuildingInfo : TraitInfo<PrimaryBuilding> { }
class PrimaryBuilding : IIssueOrder, IResolveOrder, IOrderCursor, ITags
class PrimaryBuilding : IIssueOrder2, IResolveOrder, ITags
{
bool isPrimary = false;
public bool IsPrimary { get { return isPrimary; } }
@@ -26,23 +27,19 @@ namespace OpenRA.Mods.RA
yield return (isPrimary) ? TagType.Primary : TagType.None;
}
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public IEnumerable<IOrderTargeter> Orders
{
return 0;
get { yield return new DeployOrderTargeter( "PrimaryProducer", 1 ); }
}
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 == self)
return new Order("PrimaryProducer", self);
if( order.OrderID == "PrimaryProducer" )
return new Order( order.OrderID, self );
return null;
}
public string CursorForOrder(Actor self, Order order)
{
return (order.OrderString == "PrimaryProducer") ? "deploy" : null;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "PrimaryProducer")

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Mods.RA
public object Create(ActorInitializer init) { return new RallyPoint(init.self); }
}
public class RallyPoint : IRender, IIssueOrder, IResolveOrder, ITick
public class RallyPoint : IRender, IIssueOrder2, IResolveOrder, ITick
{
[Sync]
public int2 rallyPoint;
@@ -43,15 +43,17 @@ namespace OpenRA.Mods.RA
anim.Image, Traits.Util.CenterOfCell(rallyPoint));
}
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public IEnumerable<IOrderTargeter> Orders
{
return 0;
get { yield return new RallyPointOrderTargeter(); }
}
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
{
if (mi.Button == MouseButton.Left || underCursor != null) return null;
return new Order("SetRallyPoint", self, xy);
if( order.OrderID == "SetRallyPoint" )
return new Order( order.OrderID, self, Traits.Util.CellContaining( target.CenterLocation ) );
return null;
}
public void ResolveOrder( Actor self, Order order )
@@ -61,5 +63,21 @@ namespace OpenRA.Mods.RA
}
public void Tick(Actor self) { anim.Tick(); }
class RallyPointOrderTargeter : IOrderTargeter
{
public string OrderID { get { return "SetRallyPoint"; } }
public int OrderPriority { get { return 0; } }
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 )
{
return true;
}
}
}
}

View File

@@ -8,40 +8,35 @@
*/
#endregion
using System.Drawing;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
using System.Drawing;
using System.Collections.Generic;
namespace OpenRA.Mods.RA
{
class SpyInfo : TraitInfo<Spy> { }
class Spy : IIssueOrder, IResolveOrder, IOrderCursor
class Spy : IIssueOrder2, IResolveOrder
{
public int OrderPriority(Actor self, int2 xy, MouseInput mi, Actor underCursor)
public IEnumerable<IOrderTargeter> Orders
{
return 5;
get { yield return new UnitTraitOrderTargeter<IAcceptSpy>( "SpyInfiltrate", 5, "enter", true, false ); }
}
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) return null;
if (underCursor == null) return null;
if (underCursor.Owner == self.Owner) return null;
if (!underCursor.HasTrait<IAcceptSpy>()) return null;
if( order.OrderID == "SpyInfiltrate" )
return new Order( order.OrderID, self, target.Actor );
return new Order("Infiltrate", self, underCursor);
}
public string CursorForOrder(Actor self, Order order)
{
return (order.OrderString == "Infiltrate") ? "enter" : null;
return null;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Infiltrate")
if (order.OrderString == "SpyInfiltrate")
{
self.CancelActivity();
self.QueueActivity(new Move(order.TargetActor, 1));

View File

@@ -13,6 +13,7 @@ using OpenRA.Traits;
using OpenRA.Traits.Activities;
using OpenRA.GameRules;
using System.Collections.Generic;
using OpenRA.Mods.RA.Orders;
namespace OpenRA.Mods.RA
{
@@ -25,16 +26,18 @@ namespace OpenRA.Mods.RA
public readonly string[] TransformSounds = {};
public readonly string[] NoTransformSounds = {};
public virtual object Create(ActorInitializer init) { return new Transforms(this); }
public virtual object Create(ActorInitializer init) { return new Transforms(init.self, this); }
}
class Transforms : IIssueOrder2, IResolveOrder, IOrderVoice
{
Actor self;
TransformsInfo Info;
BuildingInfo bi;
public Transforms(TransformsInfo info)
public Transforms(Actor self, TransformsInfo info)
{
this.self = self;
Info = info;
bi = Rules.Info[info.IntoActor].Traits.GetOrDefault<BuildingInfo>();
}
@@ -44,17 +47,20 @@ namespace OpenRA.Mods.RA
return (order.OrderString == "DeployTransform") ? "Move" : null;
}
bool CanDeploy(Actor self)
bool CanDeploy()
{
return (bi == null || self.World.CanPlaceBuilding(Info.IntoActor, bi, self.Location + Info.Offset, self));
}
public IEnumerable<IOrderTargeter> Orders { get { yield return new TransformOrderTargeter(); } }
public IEnumerable<IOrderTargeter> Orders
{
get { yield return new DeployOrderTargeter( "DeployTransform", 5, () => CanDeploy() ); }
}
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
{
if( order is TransformOrderTargeter )
return new Order( "DeployTransform", self );
if( order.OrderID == "DeployTransform" )
return new Order( order.OrderID, self );
return null;
}
@@ -63,7 +69,7 @@ namespace OpenRA.Mods.RA
{
if (order.OrderString == "DeployTransform")
{
if (!CanDeploy(self))
if (!CanDeploy())
{
foreach (var s in Info.NoTransformSounds)
Sound.PlayToPlayer(self.Owner, s);
@@ -77,29 +83,5 @@ namespace OpenRA.Mods.RA
self.QueueActivity(new Transform(self, Info.IntoActor, Info.Offset, Info.Facing, Info.TransformSounds));
}
}
class TransformOrderTargeter : IOrderTargeter
{
public string OrderID
{
get { return "DeployTransform"; }
}
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;
}
}
}
}