changes to TypeDictionary's interface. (build-palette is broken, so hasn't been tested)

This commit is contained in:
Bob
2010-01-12 13:27:59 +13:00
parent e6e5275f05
commit 5a29dd6ee2
36 changed files with 96 additions and 74 deletions

View File

@@ -33,6 +33,10 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="IjwFramework, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Ijw.DirectX\Release\IjwFramework.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>

View File

@@ -1,50 +1,56 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Linq;
using System.Reflection;
using IjwFramework.Collections;
namespace OpenRa namespace OpenRa
{ {
public class TypeDictionary public class TypeDictionary
{ {
Dictionary<Type, object> inner = new Dictionary<Type, object>(); Cache<Type, List<object>> innerInherit = new Cache<Type, List<object>>( _ => new List<object>() );
public void Add( Type t, object val )
{
inner.Add( t, val );
}
public void Add( object val ) public void Add( object val )
{ {
Add( val.GetType(), val ); var t = val.GetType();
}
public void Remove<T>() foreach( var i in t.GetInterfaces() )
{ innerInherit[ i ].Add( val );
inner.Remove( typeof( T ) ); foreach( var tt in t.BaseTypes() )
innerInherit[ tt ].Add( val );
} }
public bool Contains<T>() public bool Contains<T>()
{ {
return inner.ContainsKey( typeof( T ) ); return innerInherit.Keys.Contains( typeof( T ) );
} }
public T Get<T>() public T Get<T>()
{ {
return (T)inner[ typeof( T ) ]; var l = innerInherit[ typeof( T ) ];
if( l.Count == 1 )
return (T)l[ 0 ];
else if( l.Count == 0 )
throw new InvalidOperationException( string.Format( "TypeDictionary does not contain instance of type `{0}`", typeof( T ) ) );
else
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
} }
public T GetOrDefault<T>() public T GetOrDefault<T>()
{ {
object o = null; var l = innerInherit[ typeof( T ) ];
inner.TryGetValue(typeof(T), out o); if( l.Count == 1 )
return (T)o; return (T)l[ 0 ];
else if( l.Count == 0 )
return default( T );
else
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
} }
public IEnumerable<T> WithInterface<T>() public IEnumerable<T> WithInterface<T>()
{ {
foreach( var i in inner ) foreach( var i in innerInherit[ typeof( T ) ] )
if( i.Value is T ) yield return (T)i;
yield return (T)i.Value;
} }
public IEnumerator<object> GetEnumerator() public IEnumerator<object> GetEnumerator()
@@ -52,4 +58,16 @@ namespace OpenRa
return WithInterface<object>().GetEnumerator(); return WithInterface<object>().GetEnumerator();
} }
} }
static class TypeExts
{
public static IEnumerable<Type> BaseTypes( this Type t )
{
while( t != null )
{
yield return t;
t = t.BaseType;
}
}
}
} }

View File

@@ -49,7 +49,7 @@ namespace OpenRa.Game
var distance = (target.CenterLocation - loc).Length*1/24f; var distance = (target.CenterLocation - loc).Length*1/24f;
var rawDamage = weapon.Damage * (float)Math.Exp(-distance / warhead.Spread); var rawDamage = weapon.Damage * (float)Math.Exp(-distance / warhead.Spread);
var multiplier = warhead.EffectivenessAgainst(target.Info.Traits.WithInterface<OwnedActorInfo>().First().Armor); var multiplier = warhead.EffectivenessAgainst(target.Info.Traits.Get<OwnedActorInfo>().Armor);
return rawDamage * multiplier; return rawDamage * multiplier;
} }
@@ -59,7 +59,7 @@ namespace OpenRa.Game
var warhead = Rules.WarheadInfo[weapon.Warhead]; var warhead = Rules.WarheadInfo[weapon.Warhead];
var unit = target.traits.GetOrDefault<Unit>(); var unit = target.traits.GetOrDefault<Unit>();
if (warhead.EffectivenessAgainst(target.Info.Traits.WithInterface<OwnedActorInfo>().First().Armor) <= 0) if (warhead.EffectivenessAgainst(target.Info.Traits.Get<OwnedActorInfo>().Armor) <= 0)
return false; return false;
if (target.traits.Contains<Submarine>()) if (target.traits.Contains<Submarine>())
@@ -76,7 +76,7 @@ namespace OpenRa.Game
public static bool HasAnyValidWeapons(Actor self, Actor target) public static bool HasAnyValidWeapons(Actor self, Actor target)
{ {
var info = self.Info.Traits.WithInterface<AttackBaseInfo>().First(); var info = self.Info.Traits.Get<AttackBaseInfo>();
if (info.PrimaryWeapon != null && if (info.PrimaryWeapon != null &&
WeaponValidForTarget(self.GetPrimaryWeapon(), target)) return true; WeaponValidForTarget(self.GetPrimaryWeapon(), target)) return true;
if (info.SecondaryWeapon != null && if (info.SecondaryWeapon != null &&

View File

@@ -15,7 +15,7 @@ namespace OpenRa.Game.Effects
public Corpse(Actor fromActor, int death) public Corpse(Actor fromActor, int death)
{ {
anim = new Animation(fromActor.traits.WithInterface<RenderSimple>().FirstOrDefault().GetImage(fromActor)); anim = new Animation(fromActor.traits.GetOrDefault<RenderSimple>().GetImage(fromActor));
anim.PlayThen("die{0}".F(death + 1), anim.PlayThen("die{0}".F(death + 1),
() => Game.world.AddFrameEndTask(w => w.Remove(this))); () => Game.world.AddFrameEndTask(w => w.Remove(this)));

View File

@@ -32,7 +32,7 @@ namespace OpenRa.Game
public static WeaponInfo GetPrimaryWeapon(this Actor self) public static WeaponInfo GetPrimaryWeapon(this Actor self)
{ {
var info = self.Info.Traits.WithInterface<AttackBaseInfo>().FirstOrDefault(); var info = self.Info.Traits.GetOrDefault<AttackBaseInfo>();
if (info == null) return null; if (info == null) return null;
var weapon = info.PrimaryWeapon; var weapon = info.PrimaryWeapon;
@@ -43,7 +43,7 @@ namespace OpenRa.Game
public static WeaponInfo GetSecondaryWeapon(this Actor self) public static WeaponInfo GetSecondaryWeapon(this Actor self)
{ {
var info = self.Info.Traits.WithInterface<AttackBaseInfo>().FirstOrDefault(); var info = self.Info.Traits.GetOrDefault<AttackBaseInfo>();
if (info == null) return null; if (info == null) return null;
var weapon = info.SecondaryWeapon; var weapon = info.SecondaryWeapon;

View File

@@ -244,7 +244,7 @@ namespace OpenRa.Game
public static bool IsActorCrushableByActor(Actor a, Actor b) public static bool IsActorCrushableByActor(Actor a, Actor b)
{ {
return IsActorCrushableByMovementType(a, b.traits.WithInterface<IMovement>().FirstOrDefault().GetMovementType()); return IsActorCrushableByMovementType(a, b.traits.GetOrDefault<IMovement>().GetMovementType());
} }
public static bool IsActorPathableToCrush(Actor a, UnitMovementType umt) public static bool IsActorPathableToCrush(Actor a, UnitMovementType umt)

View File

@@ -14,7 +14,7 @@ namespace OpenRa.Game.GameRules
foreach( var b in Rules.Categories[ "Building" ] ) foreach( var b in Rules.Categories[ "Building" ] )
{ {
var info = Rules.NewUnitInfo[ b ]; var info = Rules.NewUnitInfo[ b ];
var pi = info.Traits.WithInterface<ProductionInfo>().FirstOrDefault(); var pi = info.Traits.GetOrDefault<ProductionInfo>();
if (pi != null) if (pi != null)
foreach( var p in pi.Produces ) foreach( var p in pi.Produces )
producesIndex[ p ].Add( info ); producesIndex[ p ].Add( info );

View File

@@ -169,7 +169,7 @@ namespace OpenRa.Game.Graphics
lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c); lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c);
lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c); lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c);
var healthAmount = (float)selectedUnit.Health / selectedUnit.Info.Traits.WithInterface<OwnedActorInfo>().First().HP; var healthAmount = (float)selectedUnit.Health / selectedUnit.Info.Traits.Get<OwnedActorInfo>().HP;
var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red
: (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow : (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow
: Color.LimeGreen; : Color.LimeGreen;

View File

@@ -40,7 +40,7 @@ namespace OpenRa.Game.Orders
if (!Game.LocalPlayer.Shroud.IsExplored(xy)) if (!Game.LocalPlayer.Shroud.IsExplored(xy))
return Cursor.MoveBlocked; return Cursor.MoveBlocked;
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault(); var movement = self.traits.GetOrDefault<IMovement>();
return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked; return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked;
} }
} }

View File

@@ -38,7 +38,7 @@ namespace OpenRa.Game.Orders
if (!Game.LocalPlayer.Shroud.IsExplored(xy)) if (!Game.LocalPlayer.Shroud.IsExplored(xy))
return Cursor.MoveBlocked; return Cursor.MoveBlocked;
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault(); var movement = self.traits.GetOrDefault<IMovement>();
return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked; return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked;
} }
} }

View File

@@ -57,7 +57,7 @@ namespace OpenRa.Game.Orders
Cursor CursorForOrderString(string s, Actor a, int2 location) Cursor CursorForOrderString(string s, Actor a, int2 location)
{ {
var movement = a.traits.WithInterface<IMovement>().FirstOrDefault(); var movement = a.traits.GetOrDefault<IMovement>();
switch (s) switch (s)
{ {
case "Attack": return Cursor.Attack; case "Attack": return Cursor.Attack;

View File

@@ -35,7 +35,7 @@ namespace OpenRa.Game
{ {
foreach (var t in Game.FindTilesInCircle( foreach (var t in Game.FindTilesInCircle(
(1f / Game.CellSize * a.CenterLocation).ToInt2(), (1f / Game.CellSize * a.CenterLocation).ToInt2(),
a.Info.Traits.WithInterface<OwnedActorInfo>().First().Sight)) a.Info.Traits.Get<OwnedActorInfo>().Sight))
explored[t.X, t.Y] = true; explored[t.X, t.Y] = true;
dirty = true; dirty = true;

View File

@@ -27,7 +27,7 @@ namespace OpenRa.Game.Traits.Activities
return new Move( Target, Range ) { NextActivity = this }; return new Move( Target, Range ) { NextActivity = this };
var desiredFacing = Util.GetFacing((Target.Location - self.Location).ToFloat2(), 0); var desiredFacing = Util.GetFacing((Target.Location - self.Location).ToFloat2(), 0);
var renderUnit = self.traits.WithInterface<RenderUnit>().FirstOrDefault(); var renderUnit = self.traits.GetOrDefault<RenderUnit>();
var numDirs = (renderUnit != null) var numDirs = (renderUnit != null)
? renderUnit.anim.CurrentSequence.Length : 8; ? renderUnit.anim.CurrentSequence.Length : 8;
@@ -37,7 +37,7 @@ namespace OpenRa.Game.Traits.Activities
return new Turn( desiredFacing ) { NextActivity = this }; return new Turn( desiredFacing ) { NextActivity = this };
} }
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.Get<AttackBase>();
attack.target = Target; attack.target = Target;
attack.DoAttack(self); attack.DoAttack(self);
return this; return this;

View File

@@ -19,7 +19,7 @@ namespace OpenRa.Game.Traits.Activities
if (target.Owner == self.Owner) if (target.Owner == self.Owner)
{ {
if (target.Health == target.Info.Traits.WithInterface<OwnedActorInfo>().First().HP) if (target.Health == target.Info.Traits.Get<OwnedActorInfo>().HP)
return NextActivity; return NextActivity;
target.InflictDamage(self, -EngineerCapture.EngineerDamage, Rules.WarheadInfo["Super"]); target.InflictDamage(self, -EngineerCapture.EngineerDamage, Rules.WarheadInfo["Super"]);
} }

View File

@@ -64,7 +64,7 @@ namespace OpenRa.Game.Traits.Activities
else if( unit.Facing != 64 ) else if( unit.Facing != 64 )
return new Turn( 64 ) { NextActivity = this }; return new Turn( 64 ) { NextActivity = this };
var renderUnit = self.traits.WithInterface<RenderUnit>().First(); var renderUnit = self.traits.Get<RenderUnit>();
if( renderUnit.anim.CurrentSequence.Name != "empty" ) if( renderUnit.anim.CurrentSequence.Name != "empty" )
renderUnit.PlayCustomAnimation( self, "empty", renderUnit.PlayCustomAnimation( self, "empty",
() => isDone = true ); () => isDone = true );

View File

@@ -33,7 +33,7 @@ namespace OpenRa.Game.Traits.Activities
{ {
var unit = self.traits.Get<Unit>(); var unit = self.traits.Get<Unit>();
var harv = self.traits.Get<Harvester>(); var harv = self.traits.Get<Harvester>();
var renderUnit = self.traits.WithInterface<RenderUnit>().First(); /* better have one of these! */ var renderUnit = self.traits.Get<RenderUnit>(); /* better have one of these! */
var isGem = false; var isGem = false;
if (!Rules.Map.ContainsResource(self.Location) || if (!Rules.Map.ContainsResource(self.Location) ||

View File

@@ -24,7 +24,7 @@ namespace OpenRa.Game.Traits.Activities
if (isCanceled) return NextActivity; if (isCanceled) return NextActivity;
var dest = ChooseHelipad(self); var dest = ChooseHelipad(self);
var initialFacing = self.Info.Traits.WithInterface<OwnedActorInfo>().First().InitialFacing; var initialFacing = self.Info.Traits.Get<OwnedActorInfo>().InitialFacing;
if (dest == null) if (dest == null)
return Util.SequenceActivities( return Util.SequenceActivities(

View File

@@ -17,7 +17,7 @@ namespace OpenRa.Game.Traits.Activities
if (remainingTicks == 0) if (remainingTicks == 0)
{ {
var unitCost = self.Info.Traits.Get<BuildableInfo>().Cost; var unitCost = self.Info.Traits.Get<BuildableInfo>().Cost;
var hp = self.Info.Traits.WithInterface<OwnedActorInfo>().First().HP; var hp = self.Info.Traits.Get<OwnedActorInfo>().HP;
var costPerHp = (Rules.General.URepairPercent * unitCost) / hp; var costPerHp = (Rules.General.URepairPercent * unitCost) / hp;
var hpToRepair = Math.Min(Rules.General.URepairStep, hp - self.Health); var hpToRepair = Math.Min(Rules.General.URepairStep, hp - self.Health);

View File

@@ -14,7 +14,7 @@ namespace OpenRa.Game.Traits.Activities
void DoSell(Actor self) void DoSell(Actor self)
{ {
var cost = self.Info.Traits.Get<BuildableInfo>().Cost; var cost = self.Info.Traits.Get<BuildableInfo>().Cost;
var hp = self.Info.Traits.WithInterface<OwnedActorInfo>().First().HP; var hp = self.Info.Traits.Get<OwnedActorInfo>().HP;
var refund = Rules.General.RefundPercent * self.Health * cost / hp; var refund = Rules.General.RefundPercent * self.Health * cost / hp;
self.Owner.GiveCash((int)refund); self.Owner.GiveCash((int)refund);
@@ -30,7 +30,7 @@ namespace OpenRa.Game.Traits.Activities
{ {
if (!started) if (!started)
{ {
var rb = self.traits.WithInterface<RenderBuilding>().First(); var rb = self.traits.Get<RenderBuilding>();
//var rb = self.traits.Get<RenderBuilding>(); //var rb = self.traits.Get<RenderBuilding>();
rb.PlayCustomAnimBackwards(self, "make", rb.PlayCustomAnimBackwards(self, "make",
() => Game.world.AddFrameEndTask(w => DoSell(self))); () => Game.world.AddFrameEndTask(w => DoSell(self)));

View File

@@ -44,7 +44,7 @@ namespace OpenRa.Game.Traits.Activities
if (cargo.IsEmpty(self)) if (cargo.IsEmpty(self))
return NextActivity; return NextActivity;
var ru = self.traits.WithInterface<RenderUnit>().FirstOrDefault(); var ru = self.traits.GetOrDefault<RenderUnit>();
if (ru != null) if (ru != null)
ru.PlayCustomAnimation(self, "unload", null); ru.PlayCustomAnimation(self, "unload", null);

View File

@@ -88,7 +88,7 @@ namespace OpenRa.Game.Traits
public void DoAttack(Actor self) public void DoAttack(Actor self)
{ {
var unit = self.traits.GetOrDefault<Unit>(); var unit = self.traits.GetOrDefault<Unit>();
var info = self.Info.Traits.WithInterface<AttackBaseInfo>().First(); var info = self.Info.Traits.Get<AttackBaseInfo>();
if (info.PrimaryWeapon != null && CheckFire(self, unit, info.PrimaryWeapon, ref primaryFireDelay, if (info.PrimaryWeapon != null && CheckFire(self, unit, info.PrimaryWeapon, ref primaryFireDelay,
info.PrimaryOffset, ref primaryBurst, info.PrimaryLocalOffset)) info.PrimaryOffset, ref primaryBurst, info.PrimaryLocalOffset))
@@ -142,7 +142,7 @@ namespace OpenRa.Game.Traits
var firePos = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, fireOffset, 0f).ToInt2(); var firePos = self.CenterLocation.ToInt2() + Util.GetTurretPosition(self, unit, fireOffset, 0f).ToInt2();
var thisTarget = target; // closure. var thisTarget = target; // closure.
var destUnit = thisTarget.traits.GetOrDefault<Unit>(); var destUnit = thisTarget.traits.GetOrDefault<Unit>();
var info = self.Info.Traits.WithInterface<AttackBaseInfo>().First(); var info = self.Info.Traits.Get<AttackBaseInfo>();
ScheduleDelayedAction(info.FireDelay, () => ScheduleDelayedAction(info.FireDelay, () =>
{ {

View File

@@ -9,7 +9,7 @@ namespace OpenRa.Game.Traits
{ {
void AttackTarget(Actor self, Actor target) void AttackTarget(Actor self, Actor target)
{ {
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.Get<AttackBase>();
if (target != null) if (target != null)
attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null)); attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null));
else else
@@ -19,14 +19,14 @@ namespace OpenRa.Game.Traits
bool NeedsNewTarget(Actor self) bool NeedsNewTarget(Actor self)
{ {
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.Get<AttackBase>();
var range = Util.GetMaximumRange(self); var range = Util.GetMaximumRange(self);
if (attack.target == null) if (attack.target == null)
return true; // he's dead. return true; // he's dead.
if ((attack.target.Location - self.Location).LengthSquared > range * range + 2) if ((attack.target.Location - self.Location).LengthSquared > range * range + 2)
return true; // wandered off faster than we could follow return true; // wandered off faster than we could follow
if (attack.target.Health == attack.target.Info.Traits.WithInterface<OwnedActorInfo>().First().HP) if (attack.target.Health == attack.target.Info.Traits.Get<OwnedActorInfo>().HP)
return true; // fully healed return true; // fully healed
return false; return false;
@@ -34,7 +34,7 @@ namespace OpenRa.Game.Traits
public void Tick(Actor self) public void Tick(Actor self)
{ {
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.Get<AttackBase>();
var range = Util.GetMaximumRange(self); var range = Util.GetMaximumRange(self);
if (NeedsNewTarget(self)) if (NeedsNewTarget(self))
@@ -48,7 +48,7 @@ namespace OpenRa.Game.Traits
return inRange return inRange
.Where(a => a.Owner == self.Owner && a != self) /* todo: one day deal with friendly players */ .Where(a => a.Owner == self.Owner && a != self) /* todo: one day deal with friendly players */
.Where(a => Combat.HasAnyValidWeapons(self, a)) .Where(a => Combat.HasAnyValidWeapons(self, a))
.Where(a => a.Health < a.Info.Traits.WithInterface<OwnedActorInfo>().First().HP) .Where(a => a.Health < a.Info.Traits.Get<OwnedActorInfo>().HP)
.OrderBy(a => (a.Location - self.Location).LengthSquared) .OrderBy(a => (a.Location - self.Location).LengthSquared)
.FirstOrDefault(); .FirstOrDefault();
} }

View File

@@ -8,7 +8,7 @@ namespace OpenRa.Game.Traits
{ {
void AttackTarget(Actor self, Actor target) void AttackTarget(Actor self, Actor target)
{ {
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.Get<AttackBase>();
if (target != null) if (target != null)
attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null)); attack.ResolveOrder(self, new Order("Attack", self, target, int2.Zero, null));
} }
@@ -17,7 +17,7 @@ namespace OpenRa.Game.Traits
{ {
if (!self.IsIdle) return; if (!self.IsIdle) return;
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.Get<AttackBase>();
var range = Util.GetMaximumRange(self); var range = Util.GetMaximumRange(self);
if (attack.target == null || if (attack.target == null ||
@@ -48,7 +48,7 @@ namespace OpenRa.Game.Traits
if (e.Damage < 0) if (e.Damage < 0)
return; // don't retaliate against healers return; // don't retaliate against healers
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.Get<AttackBase>();
if (attack.target != null) return; if (attack.target != null) return;
AttackTarget(self, e.Attacker); AttackTarget(self, e.Attacker);

View File

@@ -40,7 +40,7 @@ namespace OpenRa.Game.Traits
return; return;
} }
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault(); var movement = self.traits.GetOrDefault<IMovement>();
if (order.OrderString == "ChronoshiftSelf" && movement.CanEnterCell(order.TargetLocation)) if (order.OrderString == "ChronoshiftSelf" && movement.CanEnterCell(order.TargetLocation))
{ {
// Cannot chronoshift into unexplored location // Cannot chronoshift into unexplored location

View File

@@ -45,7 +45,7 @@ namespace OpenRa.Game.Traits
Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self, power); Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self, power);
} }
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault(); var movement = self.traits.GetOrDefault<IMovement>();
if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation)) if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation))
{ {
// Cannot chronoshift into unexplored location // Cannot chronoshift into unexplored location

View File

@@ -18,7 +18,7 @@ namespace OpenRa.Game.Traits
public new void ResolveOrder(Actor self, Order order) public new void ResolveOrder(Actor self, Order order)
{ {
// Override chronoshifting action to detonate vehicle // Override chronoshifting action to detonate vehicle
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault(); var movement = self.traits.GetOrDefault<IMovement>();
var chronosphere = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains<Chronosphere>()).FirstOrDefault(); var chronosphere = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains<Chronosphere>()).FirstOrDefault();
if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation)) if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation))
{ {
@@ -44,7 +44,7 @@ namespace OpenRa.Game.Traits
int2 detonateLocation = self.CenterLocation.ToInt2(); int2 detonateLocation = self.CenterLocation.ToInt2();
Game.world.AddFrameEndTask( Game.world.AddFrameEndTask(
w => w.Add(new Bullet(self.Info.Traits.WithInterface<AttackBaseInfo>().First().PrimaryWeapon, detonatedBy.Owner, detonatedBy, w => w.Add( new Bullet( self.Info.Traits.Get<AttackBaseInfo>().PrimaryWeapon, detonatedBy.Owner, detonatedBy,
detonateLocation, detonateLocation, altitude, altitude))); detonateLocation, detonateLocation, altitude, altitude)));
} }
} }

View File

@@ -52,7 +52,7 @@ namespace OpenRa.Game.Traits
{ {
self.CancelActivity(); self.CancelActivity();
self.QueueActivity(new HeliFly(Util.CenterOfCell(order.TargetLocation))); self.QueueActivity(new HeliFly(Util.CenterOfCell(order.TargetLocation)));
self.QueueActivity(new Turn(self.Info.Traits.WithInterface<OwnedActorInfo>().FirstOrDefault().InitialFacing)); self.QueueActivity( new Turn( self.Info.Traits.GetOrDefault<OwnedActorInfo>().InitialFacing ) );
self.QueueActivity(new HeliLand(true)); self.QueueActivity(new HeliLand(true));
} }
@@ -69,7 +69,7 @@ namespace OpenRa.Game.Traits
self.CancelActivity(); self.CancelActivity();
self.QueueActivity(new HeliFly(order.TargetActor.CenterLocation + offsetVec)); self.QueueActivity(new HeliFly(order.TargetActor.CenterLocation + offsetVec));
self.QueueActivity(new Turn(self.Info.Traits.WithInterface<OwnedActorInfo>().FirstOrDefault().InitialFacing)); self.QueueActivity( new Turn( self.Info.Traits.GetOrDefault<OwnedActorInfo>().InitialFacing ) );
self.QueueActivity(new HeliLand(false)); self.QueueActivity(new HeliLand(false));
self.QueueActivity(order.TargetActor.Info.Name == "hpad" self.QueueActivity(order.TargetActor.Info.Name == "hpad"
? (IActivity)new Rearm() : new Repair()); ? (IActivity)new Rearm() : new Repair());

View File

@@ -19,7 +19,7 @@ namespace OpenRa.Game.Traits
if (cargo == null || cargo.IsFull(underCursor)) if (cargo == null || cargo.IsFull(underCursor))
return null; return null;
var umt = self.traits.WithInterface<IMovement>().First().GetMovementType(); var umt = self.traits.Get<IMovement>().GetMovementType();
if (!underCursor.Info.Traits.Get<CargoInfo>().PassengerTypes.Contains(umt)) if (!underCursor.Info.Traits.Get<CargoInfo>().PassengerTypes.Contains(umt))
return null; return null;

View File

@@ -26,7 +26,7 @@ namespace OpenRa.Game.Traits
public virtual int CreationFacing( Actor self, Actor newUnit ) public virtual int CreationFacing( Actor self, Actor newUnit )
{ {
return newUnit.Info.Traits.WithInterface<OwnedActorInfo>().FirstOrDefault().InitialFacing; return newUnit.Info.Traits.GetOrDefault<OwnedActorInfo>().InitialFacing;
} }
public bool Produce( Actor self, LegacyUnitInfo producee ) public bool Produce( Actor self, LegacyUnitInfo producee )

View File

@@ -26,7 +26,7 @@ namespace OpenRa.Game.Traits
public RenderWarFactory(Actor self) public RenderWarFactory(Actor self)
{ {
this.self = self; this.self = self;
roof = new Animation(self.traits.WithInterface<RenderSimple>().First().GetImage(self)); roof = new Animation(self.traits.Get<RenderSimple>().GetImage(self));
} }
public void BuildingComplete( Actor self ) public void BuildingComplete( Actor self )

View File

@@ -19,7 +19,7 @@ namespace OpenRa.Game.Traits
public string GetImage(Actor self) public string GetImage(Actor self)
{ {
return self.Info.Traits.WithInterface<RenderSimpleInfo>().First().Image ?? self.Info.Name; return self.Info.Traits.Get<RenderSimpleInfo>().Image ?? self.Info.Name;
} }
public RenderSimple(Actor self) public RenderSimple(Actor self)

View File

@@ -16,8 +16,8 @@ namespace OpenRa.Game.Traits
: base(self) : base(self)
{ {
var unit = self.traits.Get<Unit>(); var unit = self.traits.Get<Unit>();
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.Get<AttackBase>();
var attackInfo = self.Info.Traits.WithInterface<AttackBaseInfo>().First(); var attackInfo = self.Info.Traits.Get<AttackBaseInfo>();
var muzzleFlash = new Animation(GetImage(self)); var muzzleFlash = new Animation(GetImage(self));
muzzleFlash.PlayFetchIndex("muzzle", muzzleFlash.PlayFetchIndex("muzzle",

View File

@@ -16,7 +16,7 @@ namespace OpenRa.Game.Traits
{ {
var isAttacking = self.GetCurrentActivity() is Activities.Attack; var isAttacking = self.GetCurrentActivity() is Activities.Attack;
var attack = self.traits.WithInterface<AttackBase>().FirstOrDefault(); var attack = self.traits.GetOrDefault<AttackBase>();
if (attack != null) if (attack != null)
anim.ReplaceAnim((attack.IsReloading() ? "empty-" : "") anim.ReplaceAnim((attack.IsReloading() ? "empty-" : "")

View File

@@ -16,8 +16,8 @@ namespace OpenRa.Game.Traits
{ {
var unit = self.traits.Get<Unit>(); var unit = self.traits.Get<Unit>();
var turreted = self.traits.Get<Turreted>(); var turreted = self.traits.Get<Turreted>();
var attack = self.traits.WithInterface<AttackBase>().FirstOrDefault(); var attack = self.traits.GetOrDefault<AttackBase>();
var attackInfo = self.Info.Traits.WithInterface<AttackBaseInfo>().First(); var attackInfo = self.Info.Traits.Get<AttackBaseInfo>();
var turretAnim = new Animation(GetImage(self)); var turretAnim = new Animation(GetImage(self));
turretAnim.PlayFacing( "turret", () => turreted.turretFacing ); turretAnim.PlayFacing( "turret", () => turreted.turretFacing );

View File

@@ -83,7 +83,7 @@ namespace OpenRa.Game.Traits
static float2 GetRecoil(Actor self, float recoil) static float2 GetRecoil(Actor self, float recoil)
{ {
if (self.LegacyInfo.Recoil == 0) return float2.Zero; if (self.LegacyInfo.Recoil == 0) return float2.Zero;
var rut = self.traits.WithInterface<RenderUnitTurreted>().FirstOrDefault(); var rut = self.traits.GetOrDefault<RenderUnitTurreted>();
if (rut == null) return float2.Zero; if (rut == null) return float2.Zero;
var facing = self.traits.Get<Turreted>().turretFacing; var facing = self.traits.Get<Turreted>().turretFacing;
@@ -106,7 +106,7 @@ namespace OpenRa.Game.Traits
{ {
if( unit == null ) return int2.Zero; /* things that don't have a rotating base don't need the turrets repositioned */ if( unit == null ) return int2.Zero; /* things that don't have a rotating base don't need the turrets repositioned */
var ru = self.traits.WithInterface<RenderUnit>().FirstOrDefault(); var ru = self.traits.GetOrDefault<RenderUnit>();
var numDirs = (ru != null) ? ru.anim.CurrentSequence.Length : 8; var numDirs = (ru != null) ? ru.anim.CurrentSequence.Length : 8;
var bodyFacing = unit.Facing; var bodyFacing = unit.Facing;
var quantizedFacing = QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs); var quantizedFacing = QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs);
@@ -145,7 +145,7 @@ namespace OpenRa.Game.Traits
public static float GetMaximumRange(Actor self) public static float GetMaximumRange(Actor self)
{ {
var info = self.Info.Traits.WithInterface<AttackBaseInfo>().First(); var info = self.Info.Traits.Get<AttackBaseInfo>();
return new[] { self.GetPrimaryWeapon(), self.GetSecondaryWeapon() } return new[] { self.GetPrimaryWeapon(), self.GetSecondaryWeapon() }
.Where(w => w != null).Max(w => w.Range); .Where(w => w != null).Max(w => w.Range);
} }

View File

@@ -16,8 +16,8 @@ namespace OpenRa.Game
for (int i = 0; i < 128; i++) for (int i = 0; i < 128; i++)
for (int j = 0; j < 128; j++) for (int j = 0; j < 128; j++)
influence[ i, j ] = new List<Actor>(); influence[ i, j ] = new List<Actor>();
Game.world.ActorRemoved += a => Remove(a, a.traits.WithInterface<IOccupySpace>().FirstOrDefault()); Game.world.ActorRemoved += a => Remove( a, a.traits.GetOrDefault<IOccupySpace>() );
} }
public void Tick() public void Tick()
@@ -53,7 +53,7 @@ namespace OpenRa.Game
for( int x = 0 ; x < 128 ; x++ ) for( int x = 0 ; x < 128 ; x++ )
if( influence[ x, y ] != null ) if( influence[ x, y ] != null )
foreach (var a in influence[ x, y ]) foreach (var a in influence[ x, y ])
if (!a.traits.WithInterface<IOccupySpace>().First().OccupiedCells().Contains( new int2( x, y ) ) ) if (!a.traits.Get<IOccupySpace>().OccupiedCells().Contains( new int2( x, y ) ) )
throw new InvalidOperationException( "UIM: Sanity check failed A" ); throw new InvalidOperationException( "UIM: Sanity check failed A" );
foreach( Actor a in Game.world.Actors ) foreach( Actor a in Game.world.Actors )