Remove Actor.HasTrait<T>()

This commit is contained in:
atlimit8
2015-08-01 23:53:58 -05:00
parent 959914779f
commit 85fab45451
79 changed files with 153 additions and 153 deletions

View File

@@ -226,11 +226,6 @@ namespace OpenRA
return World.TraitDict.WithInterface<T>(this); return World.TraitDict.WithInterface<T>(this);
} }
public bool HasTrait<T>()
{
return World.TraitDict.Contains<T>(this);
}
public void AddTrait(object trait) public void AddTrait(object trait)
{ {
World.TraitDict.AddTrait(this, trait); World.TraitDict.AddTrait(this, trait);

View File

@@ -181,7 +181,7 @@ namespace OpenRA.Graphics
if (World.Type == WorldType.Regular && Game.Settings.Game.AlwaysShowStatusBars) if (World.Type == WorldType.Regular && Game.Settings.Game.AlwaysShowStatusBars)
{ {
foreach (var g in World.Actors.Where(a => !a.Disposed foreach (var g in World.Actors.Where(a => !a.Disposed
&& a.HasTrait<Selectable>() && a.Info.Traits.Contains<SelectableInfo>()
&& !World.FogObscures(a) && !World.FogObscures(a)
&& !World.Selection.Actors.Contains(a))) && !World.Selection.Actors.Contains(a)))
@@ -193,7 +193,7 @@ namespace OpenRA.Graphics
public void DrawRollover(Actor unit) public void DrawRollover(Actor unit)
{ {
if (unit.HasTrait<Selectable>()) if (unit.Info.Traits.Contains<SelectableInfo>())
new SelectionBarsRenderable(unit).Render(this); new SelectionBarsRenderable(unit).Render(this);
} }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Orders
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi) public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{ {
var underCursor = world.ScreenMap.ActorsAt(mi) var underCursor = world.ScreenMap.ActorsAt(mi)
.Where(a => !world.FogObscures(a) && a.HasTrait<ITargetable>()) .Where(a => !world.FogObscures(a) && a.Info.Traits.Contains<ITargetableInfo>())
.WithHighestSelectionPriority(); .WithHighestSelectionPriority();
Target target; Target target;
@@ -58,12 +58,12 @@ namespace OpenRA.Orders
{ {
var useSelect = false; var useSelect = false;
var underCursor = world.ScreenMap.ActorsAt(mi) var underCursor = world.ScreenMap.ActorsAt(mi)
.Where(a => !world.FogObscures(a) && a.HasTrait<ITargetable>()) .Where(a => !world.FogObscures(a) && a.Info.Traits.Contains<ITargetableInfo>())
.WithHighestSelectionPriority(); .WithHighestSelectionPriority();
if (underCursor != null && (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any())) if (underCursor != null && (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any()))
{ {
if (underCursor.HasTrait<Selectable>()) if (underCursor.Info.Traits.Contains<SelectableInfo>())
useSelect = true; useSelect = true;
} }

View File

@@ -84,12 +84,6 @@ namespace OpenRA
throw new InvalidOperationException("Attempted to get trait from destroyed object ({0})".F(actor)); throw new InvalidOperationException("Attempted to get trait from destroyed object ({0})".F(actor));
} }
public bool Contains<T>(Actor actor)
{
CheckDestroyed(actor);
return InnerGet<T>().GetMultiple(actor.ActorID).Any();
}
public T Get<T>(Actor actor) public T Get<T>(Actor actor)
{ {
CheckDestroyed(actor); CheckDestroyed(actor);

View File

@@ -144,13 +144,13 @@ namespace OpenRA.Traits
Player Owner { get; } Player Owner { get; }
} }
public interface IToolTip public interface ITooltip
{ {
ITooltipInfo TooltipInfo { get; } ITooltipInfo TooltipInfo { get; }
Player Owner { get; } Player Owner { get; }
} }
public interface ITooltipInfo public interface ITooltipInfo : ITraitInfo
{ {
string TooltipForPlayerStance(Stance stance); string TooltipForPlayerStance(Stance stance);
bool IsOwnerRowVisible { get; } bool IsOwnerRowVisible { get; }
@@ -226,6 +226,7 @@ namespace OpenRA.Traits
public interface ITags { IEnumerable<TagType> GetTags(); } public interface ITags { IEnumerable<TagType> GetTags(); }
public interface ISelectionBar { float GetValue(); Color GetColor(); } public interface ISelectionBar { float GetValue(); Color GetColor(); }
public interface IPositionableInfo : ITraitInfo { }
public interface IPositionable : IOccupySpace public interface IPositionable : IOccupySpace
{ {
bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any); bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any);
@@ -296,6 +297,7 @@ namespace OpenRA.Traits
public interface INotifyBecomingIdle { void OnBecomingIdle(Actor self); } public interface INotifyBecomingIdle { void OnBecomingIdle(Actor self); }
public interface INotifyIdle { void TickIdle(Actor self); } public interface INotifyIdle { void TickIdle(Actor self); }
public interface IBlocksProjectilesInfo : ITraitInfo { }
public interface IBlocksProjectiles { } public interface IBlocksProjectiles { }
public interface IRenderInfantrySequenceModifier public interface IRenderInfantrySequenceModifier
{ {
@@ -309,7 +311,7 @@ namespace OpenRA.Traits
public interface IPostRenderSelection { IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr); } public interface IPostRenderSelection { IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr); }
public interface ITargetableInfo public interface ITargetableInfo : ITraitInfo
{ {
HashSet<string> GetTargetTypes(); HashSet<string> GetTargetTypes();
} }

View File

@@ -89,7 +89,7 @@ namespace OpenRA.Widgets
{ {
if (!hasBox && World.Selection.Actors.Any() && !multiClick) if (!hasBox && World.Selection.Actors.Any() && !multiClick)
{ {
if (!(World.ScreenMap.ActorsAt(xy).Where(x => x.HasTrait<Selectable>() && if (!(World.ScreenMap.ActorsAt(xy).Where(x => x.Info.Traits.Contains<SelectableInfo>() &&
(x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x))).Any() && !mi.Modifiers.HasModifier(Modifiers.Ctrl) && (x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x))).Any() && !mi.Modifiers.HasModifier(Modifiers.Ctrl) &&
!mi.Modifiers.HasModifier(Modifiers.Alt) && UnitOrderGenerator.InputOverridesSelection(World, xy, mi))) !mi.Modifiers.HasModifier(Modifiers.Alt) && UnitOrderGenerator.InputOverridesSelection(World, xy, mi)))
{ {
@@ -301,7 +301,7 @@ namespace OpenRA.Widgets
a = b; a = b;
return world.ScreenMap.ActorsInBox(a, b) return world.ScreenMap.ActorsInBox(a, b)
.Where(x => x.HasTrait<Selectable>() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x))) .Where(x => x.Info.Traits.Contains<SelectableInfo>() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x)))
.SubsetWithHighestSelectionPriority(); .SubsetWithHighestSelectionPriority();
} }

View File

@@ -176,7 +176,7 @@ namespace OpenRA.Mods.Common.AI
var sumOfHp = 0; var sumOfHp = 0;
foreach (var a in actors) foreach (var a in actors)
{ {
if (a.HasTrait<Health>()) if (a.Info.Traits.Contains<HealthInfo>())
{ {
sumOfMaxHp += a.Trait<Health>().MaxHP; sumOfMaxHp += a.Trait<Health>().MaxHP;
sumOfHp += a.Trait<Health>().HP; sumOfHp += a.Trait<Health>().HP;
@@ -191,7 +191,7 @@ namespace OpenRA.Mods.Common.AI
protected float RelativePower(IEnumerable<Actor> own, IEnumerable<Actor> enemy) protected float RelativePower(IEnumerable<Actor> own, IEnumerable<Actor> enemy)
{ {
return RelativeValue(own, enemy, 100, SumOfValues<AttackBase>, a => return RelativeValue(own, enemy, 100, SumOfValues<AttackBaseInfo>, a =>
{ {
var sumOfDamage = 0; var sumOfDamage = 0;
var arms = a.TraitsImplementing<Armament>(); var arms = a.TraitsImplementing<Armament>();
@@ -208,7 +208,7 @@ namespace OpenRA.Mods.Common.AI
protected float RelativeSpeed(IEnumerable<Actor> own, IEnumerable<Actor> enemy) protected float RelativeSpeed(IEnumerable<Actor> own, IEnumerable<Actor> enemy)
{ {
return RelativeValue(own, enemy, 100, Average<Mobile>, (Actor a) => a.Trait<Mobile>().Info.Speed); return RelativeValue(own, enemy, 100, Average<MobileInfo>, (Actor a) => a.Trait<Mobile>().Info.Speed);
} }
protected static float RelativeValue(IEnumerable<Actor> own, IEnumerable<Actor> enemy, float normalizeByValue, protected static float RelativeValue(IEnumerable<Actor> own, IEnumerable<Actor> enemy, float normalizeByValue,
@@ -224,23 +224,23 @@ namespace OpenRA.Mods.Common.AI
return relative.Clamp(0.0f, 999.0f); return relative.Clamp(0.0f, 999.0f);
} }
protected float SumOfValues<Trait>(IEnumerable<Actor> actors, Func<Actor, int> getValue) protected float SumOfValues<TTraitInfo>(IEnumerable<Actor> actors, Func<Actor, int> getValue) where TTraitInfo : ITraitInfo
{ {
var sum = 0; var sum = 0;
foreach (var a in actors) foreach (var a in actors)
if (a.HasTrait<Trait>()) if (a.Info.Traits.Contains<TTraitInfo>())
sum += getValue(a); sum += getValue(a);
return sum; return sum;
} }
protected float Average<Trait>(IEnumerable<Actor> actors, Func<Actor, int> getValue) protected float Average<TTraitInfo>(IEnumerable<Actor> actors, Func<Actor, int> getValue) where TTraitInfo : ITraitInfo
{ {
var sum = 0; var sum = 0;
var countActors = 0; var countActors = 0;
foreach (var a in actors) foreach (var a in actors)
{ {
if (a.HasTrait<Trait>()) if (a.Info.Traits.Contains<TTraitInfo>())
{ {
sum += getValue(a); sum += getValue(a);
countActors++; countActors++;

View File

@@ -167,8 +167,8 @@ namespace OpenRA.Mods.Common.AI
{ {
var randomBaseBuilding = World.Actors.Where( var randomBaseBuilding = World.Actors.Where(
a => a.Owner == Player a => a.Owner == Player
&& a.HasTrait<BaseBuilding>() && a.Info.Traits.Contains<BaseBuildingInfo>()
&& !a.HasTrait<Mobile>()) && !a.Info.Traits.Contains<MobileInfo>())
.RandomOrDefault(Random); .RandomOrDefault(Random);
return randomBaseBuilding != null ? randomBaseBuilding.Location : initialBaseCenter; return randomBaseBuilding != null ? randomBaseBuilding.Location : initialBaseCenter;
@@ -232,7 +232,9 @@ namespace OpenRA.Mods.Common.AI
pathfinder = World.WorldActor.Trait<IPathFinder>(); pathfinder = World.WorldActor.Trait<IPathFinder>();
isEnemyUnit = unit => isEnemyUnit = unit =>
Player.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait<Husk>() && unit.HasTrait<ITargetable>(); Player.Stances[unit.Owner] == Stance.Enemy
&& !unit.Info.Traits.Contains<HuskInfo>()
&& unit.Info.Traits.Contains<ITargetableInfo>();
foreach (var decision in info.PowerDecisions) foreach (var decision in info.PowerDecisions)
powerDecisions.Add(decision.OrderName, decision); powerDecisions.Add(decision.OrderName, decision);
@@ -279,8 +281,8 @@ namespace OpenRA.Mods.Common.AI
{ {
var baseProviders = World.Actors.Where( var baseProviders = World.Actors.Where(
a => a.Owner == Player a => a.Owner == Player
&& a.HasTrait<BaseProvider>() && a.Info.Traits.Contains<BaseProviderInfo>()
&& !a.HasTrait<Mobile>()); && !a.Info.Traits.Contains<MobileInfo>());
foreach (var b in baseProviders) foreach (var b in baseProviders)
{ {
@@ -306,8 +308,8 @@ namespace OpenRA.Mods.Common.AI
{ {
var areaProviders = World.Actors.Where( var areaProviders = World.Actors.Where(
a => a.Owner == Player a => a.Owner == Player
&& a.HasTrait<GivesBuildableArea>() && a.Info.Traits.Contains<GivesBuildableAreaInfo>()
&& !a.HasTrait<Mobile>()); && !a.Info.Traits.Contains<MobileInfo>());
foreach (var a in areaProviders) foreach (var a in areaProviders)
{ {
@@ -487,7 +489,7 @@ namespace OpenRA.Mods.Common.AI
case BuildingType.Defense: case BuildingType.Defense:
// Build near the closest enemy structure // Build near the closest enemy structure
var closestEnemy = World.Actors.Where(a => !a.Disposed && a.HasTrait<Building>() && Player.Stances[a.Owner] == Stance.Enemy) var closestEnemy = World.Actors.Where(a => !a.Disposed && a.Info.Traits.Contains<BuildingInfo>() && Player.Stances[a.Owner] == Stance.Enemy)
.ClosestTo(World.Map.CenterOfCell(defenseCenter)); .ClosestTo(World.Map.CenterOfCell(defenseCenter));
var targetCell = closestEnemy != null ? closestEnemy.Location : baseCenter; var targetCell = closestEnemy != null ? closestEnemy.Location : baseCenter;
@@ -563,7 +565,7 @@ namespace OpenRA.Mods.Common.AI
// Pick something worth attacking owned by that player // Pick something worth attacking owned by that player
var target = World.Actors var target = World.Actors
.Where(a => a.Owner == enemy && a.HasTrait<IOccupySpace>()) .Where(a => a.Owner == enemy && a.Info.Traits.Contains<IOccupySpaceInfo>())
.ClosestTo(World.Map.CenterOfCell(GetRandomBaseCenter())); .ClosestTo(World.Map.CenterOfCell(GetRandomBaseCenter()));
if (target == null) if (target == null)
@@ -595,7 +597,7 @@ namespace OpenRA.Mods.Common.AI
List<Actor> FindEnemyConstructionYards() List<Actor> FindEnemyConstructionYards()
{ {
return World.Actors.Where(a => Player.Stances[a.Owner] == Stance.Enemy && !a.IsDead return World.Actors.Where(a => Player.Stances[a.Owner] == Stance.Enemy && !a.IsDead
&& a.HasTrait<BaseBuilding>() && !a.HasTrait<Mobile>()).ToList(); && a.Info.Traits.Contains<BaseBuildingInfo>() && !a.Info.Traits.Contains<MobileInfo>()).ToList();
} }
void CleanSquads() void CleanSquads()
@@ -705,18 +707,18 @@ namespace OpenRA.Mods.Common.AI
void FindNewUnits(Actor self) void FindNewUnits(Actor self)
{ {
var newUnits = self.World.ActorsWithTrait<IPositionable>() var newUnits = self.World.ActorsWithTrait<IPositionable>()
.Where(a => a.Actor.Owner == Player && !a.Actor.HasTrait<BaseBuilding>() .Where(a => a.Actor.Owner == Player && !a.Actor.Info.Traits.Contains<BaseBuildingInfo>()
&& !activeUnits.Contains(a.Actor)) && !activeUnits.Contains(a.Actor))
.Select(a => a.Actor); .Select(a => a.Actor);
foreach (var a in newUnits) foreach (var a in newUnits)
{ {
if (a.HasTrait<Harvester>()) if (a.Info.Traits.Contains<HarvesterInfo>())
QueueOrder(new Order("Harvest", a, false)); QueueOrder(new Order("Harvest", a, false));
else else
unitsHangingAroundTheBase.Add(a); unitsHangingAroundTheBase.Add(a);
if (a.HasTrait<Aircraft>() && a.HasTrait<AttackBase>()) if (a.Info.Traits.Contains<AircraftInfo>() && a.Info.Traits.Contains<AttackBaseInfo>())
{ {
var air = GetSquadOfType(SquadType.Air); var air = GetSquadOfType(SquadType.Air);
if (air == null) if (air == null)
@@ -740,7 +742,7 @@ namespace OpenRA.Mods.Common.AI
var attackForce = RegisterNewSquad(SquadType.Assault); var attackForce = RegisterNewSquad(SquadType.Assault);
foreach (var a in unitsHangingAroundTheBase) foreach (var a in unitsHangingAroundTheBase)
if (!a.HasTrait<Aircraft>()) if (!a.Info.Traits.Contains<AircraftInfo>())
attackForce.Units.Add(a); attackForce.Units.Add(a);
unitsHangingAroundTheBase.Clear(); unitsHangingAroundTheBase.Clear();
@@ -751,7 +753,7 @@ namespace OpenRA.Mods.Common.AI
{ {
var allEnemyBaseBuilder = FindEnemyConstructionYards(); var allEnemyBaseBuilder = FindEnemyConstructionYards();
var ownUnits = activeUnits var ownUnits = activeUnits
.Where(unit => unit.HasTrait<AttackBase>() && !unit.HasTrait<Aircraft>() && unit.IsIdle).ToList(); .Where(unit => unit.Info.Traits.Contains<AttackBaseInfo>() && !unit.Info.Traits.Contains<AircraftInfo>() && unit.IsIdle).ToList();
if (!allEnemyBaseBuilder.Any() || (ownUnits.Count < Info.SquadSize)) if (!allEnemyBaseBuilder.Any() || (ownUnits.Count < Info.SquadSize))
return; return;
@@ -759,7 +761,7 @@ namespace OpenRA.Mods.Common.AI
foreach (var b in allEnemyBaseBuilder) foreach (var b in allEnemyBaseBuilder)
{ {
var enemies = World.FindActorsInCircle(b.CenterPosition, WDist.FromCells(Info.RushAttackScanRadius)) var enemies = World.FindActorsInCircle(b.CenterPosition, WDist.FromCells(Info.RushAttackScanRadius))
.Where(unit => Player.Stances[unit.Owner] == Stance.Enemy && unit.HasTrait<AttackBase>()).ToList(); .Where(unit => Player.Stances[unit.Owner] == Stance.Enemy && unit.Info.Traits.Contains<AttackBaseInfo>()).ToList();
if (rushFuzzy.CanAttack(ownUnits, enemies)) if (rushFuzzy.CanAttack(ownUnits, enemies))
{ {
@@ -788,8 +790,8 @@ namespace OpenRA.Mods.Common.AI
if (!protectSq.IsValid) if (!protectSq.IsValid)
{ {
var ownUnits = World.FindActorsInCircle(World.Map.CenterOfCell(GetRandomBaseCenter()), WDist.FromCells(Info.ProtectUnitScanRadius)) var ownUnits = World.FindActorsInCircle(World.Map.CenterOfCell(GetRandomBaseCenter()), WDist.FromCells(Info.ProtectUnitScanRadius))
.Where(unit => unit.Owner == Player && !unit.HasTrait<Building>() .Where(unit => unit.Owner == Player && !unit.Info.Traits.Contains<BuildingInfo>()
&& unit.HasTrait<AttackBase>()); && unit.Info.Traits.Contains<AttackBaseInfo>());
foreach (var a in ownUnits) foreach (var a in ownUnits)
protectSq.Units.Add(a); protectSq.Units.Add(a);
@@ -830,7 +832,7 @@ namespace OpenRA.Mods.Common.AI
{ {
// Find and deploy our mcv // Find and deploy our mcv
var mcv = self.World.Actors var mcv = self.World.Actors
.FirstOrDefault(a => a.Owner == Player && a.HasTrait<BaseBuilding>()); .FirstOrDefault(a => a.Owner == Player && a.Info.Traits.Contains<BaseBuildingInfo>());
if (mcv != null) if (mcv != null)
{ {
@@ -839,7 +841,7 @@ namespace OpenRA.Mods.Common.AI
// Don't transform the mcv if it is a fact // Don't transform the mcv if it is a fact
// HACK: This needs to query against MCVs directly // HACK: This needs to query against MCVs directly
if (mcv.HasTrait<Mobile>()) if (mcv.Info.Traits.Contains<MobileInfo>())
QueueOrder(new Order("DeployTransform", mcv, false)); QueueOrder(new Order("DeployTransform", mcv, false));
} }
else else
@@ -851,7 +853,8 @@ namespace OpenRA.Mods.Common.AI
void FindAndDeployBackupMcv(Actor self) void FindAndDeployBackupMcv(Actor self)
{ {
// HACK: This needs to query against MCVs directly // HACK: This needs to query against MCVs directly
var mcvs = self.World.Actors.Where(a => a.Owner == Player && a.HasTrait<BaseBuilding>() && a.HasTrait<Mobile>()); var mcvs = self.World.Actors
.Where(a => a.Owner == Player && a.Info.Traits.Contains<BaseBuildingInfo>() && a.Info.Traits.Contains<MobileInfo>());
if (!mcvs.Any()) if (!mcvs.Any())
return; return;
@@ -1010,7 +1013,8 @@ namespace OpenRA.Mods.Common.AI
return; return;
// No construction yards - Build a new MCV // No construction yards - Build a new MCV
if (!HasAdequateFact() && !self.World.Actors.Any(a => a.Owner == Player && a.HasTrait<BaseBuilding>() && a.HasTrait<Mobile>())) if (!HasAdequateFact() && !self.World.Actors.Any(a =>
a.Owner == Player && a.Info.Traits.Contains<BaseBuildingInfo>() && a.Info.Traits.Contains<MobileInfo>()))
BuildUnit("Vehicle", GetUnitInfoByCommonName("Mcv", Player).Name); BuildUnit("Vehicle", GetUnitInfoByCommonName("Mcv", Player).Name);
foreach (var q in Info.UnitQueues) foreach (var q in Info.UnitQueues)
@@ -1069,14 +1073,14 @@ namespace OpenRA.Mods.Common.AI
if (e.Attacker.Disposed) if (e.Attacker.Disposed)
return; return;
if (!e.Attacker.HasTrait<ITargetable>()) if (!e.Attacker.Info.Traits.Contains<ITargetableInfo>())
return; return;
if (e.Damage > 0) if (e.Damage > 0)
aggro[e.Attacker.Owner].Aggro += e.Damage; aggro[e.Attacker.Owner].Aggro += e.Damage;
// Protected harvesters or building // Protected harvesters or building
if ((self.HasTrait<Harvester>() || self.HasTrait<Building>()) && if ((self.Info.Traits.Contains<HarvesterInfo>() || self.Info.Traits.Contains<BuildingInfo>()) &&
Player.Stances[e.Attacker.Owner] == Stance.Enemy) Player.Stances[e.Attacker.Owner] == Stance.Enemy)
{ {
defenseCenter = e.Attacker.Location; defenseCenter = e.Attacker.Location;

View File

@@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.AI
public bool IsTargetValid public bool IsTargetValid
{ {
get { return Target.IsValidFor(Units.FirstOrDefault()) && !Target.Actor.HasTrait<Husk>(); } get { return Target.IsValidFor(Units.FirstOrDefault()) && !Target.Actor.Info.Traits.Contains<HuskInfo>(); }
} }
public bool IsTargetVisible public bool IsTargetVisible

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.AI
var missileUnitsCount = 0; var missileUnitsCount = 0;
foreach (var unit in units) foreach (var unit in units)
{ {
if (unit != null && unit.HasTrait<AttackBase>() && !unit.HasTrait<Aircraft>() if (unit != null && unit.Info.Traits.Contains<AttackBaseInfo>() && !unit.Info.Traits.Contains<AircraftInfo>()
&& !unit.IsDisabled()) && !unit.IsDisabled())
{ {
var arms = unit.TraitsImplementing<Armament>(); var arms = unit.TraitsImplementing<Armament>();
@@ -223,7 +223,7 @@ namespace OpenRA.Mods.Common.AI
continue; continue;
} }
if (owner.TargetActor.HasTrait<ITargetable>() && CanAttackTarget(a, owner.TargetActor)) if (owner.TargetActor.Info.Traits.Contains<ITargetableInfo>() && CanAttackTarget(a, owner.TargetActor))
owner.Bot.QueueOrder(new Order("Attack", a, false) { TargetActor = owner.TargetActor }); owner.Bot.QueueOrder(new Order("Attack", a, false) { TargetActor = owner.TargetActor });
} }
} }

View File

@@ -95,7 +95,7 @@ namespace OpenRA.Mods.Common.AI
{ {
var enemies = owner.World.FindActorsInCircle(leader.CenterPosition, WDist.FromCells(12)) var enemies = owner.World.FindActorsInCircle(leader.CenterPosition, WDist.FromCells(12))
.Where(a1 => !a1.Disposed && !a1.IsDead); .Where(a1 => !a1.Disposed && !a1.IsDead);
var enemynearby = enemies.Where(a1 => a1.HasTrait<ITargetable>() && leader.Owner.Stances[a1.Owner] == Stance.Enemy); var enemynearby = enemies.Where(a1 => a1.Info.Traits.Contains<ITargetableInfo>() && leader.Owner.Stances[a1.Owner] == Stance.Enemy);
var target = enemynearby.ClosestTo(leader.CenterPosition); var target = enemynearby.ClosestTo(leader.CenterPosition);
if (target != null) if (target != null)
{ {

View File

@@ -60,7 +60,7 @@ namespace OpenRA.Mods.Common.AI
protected static bool CanAttackTarget(Actor a, Actor target) protected static bool CanAttackTarget(Actor a, Actor target)
{ {
if (!a.HasTrait<AttackBase>()) if (!a.Info.Traits.Contains<AttackBaseInfo>())
return false; return false;
var targetTypes = target.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes); var targetTypes = target.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes);
@@ -82,11 +82,11 @@ namespace OpenRA.Mods.Common.AI
var u = squad.Units.Random(squad.Random); var u = squad.Units.Random(squad.Random);
var units = squad.World.FindActorsInCircle(u.CenterPosition, WDist.FromCells(DangerRadius)).ToList(); var units = squad.World.FindActorsInCircle(u.CenterPosition, WDist.FromCells(DangerRadius)).ToList();
var ownBaseBuildingAround = units.Where(unit => unit.Owner == squad.Bot.Player && unit.HasTrait<Building>()); var ownBaseBuildingAround = units.Where(unit => unit.Owner == squad.Bot.Player && unit.Info.Traits.Contains<BuildingInfo>());
if (ownBaseBuildingAround.Any()) if (ownBaseBuildingAround.Any())
return false; return false;
var enemyAroundUnit = units.Where(unit => squad.Bot.Player.Stances[unit.Owner] == Stance.Enemy && unit.HasTrait<AttackBase>()); var enemyAroundUnit = units.Where(unit => squad.Bot.Player.Stances[unit.Owner] == Stance.Enemy && unit.Info.Traits.Contains<AttackBaseInfo>());
if (!enemyAroundUnit.Any()) if (!enemyAroundUnit.Any())
return false; return false;

View File

@@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Activities
{ {
target = value; target = value;
if (target.Type == TargetType.Actor) if (target.Type == TargetType.Actor)
canHideUnderFog = target.Actor.HasTrait<HiddenUnderFog>(); canHideUnderFog = target.Actor.Info.Traits.Contains<HiddenUnderFogInfo>();
} }
} }

View File

@@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Activities
// HACK: This would otherwise break targeting frozen actors // HACK: This would otherwise break targeting frozen actors
// The problem is that Shroud.IsTargetable returns false (as it should) for // The problem is that Shroud.IsTargetable returns false (as it should) for
// frozen actors, but we do want to explicitly target the underlying actor here. // frozen actors, but we do want to explicitly target the underlying actor here.
if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.HasTrait<FrozenUnderFog>() && !self.Owner.CanTargetActor(Target.Actor)) if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.Info.Traits.Contains<FrozenUnderFogInfo>() && !self.Owner.CanTargetActor(Target.Actor))
return NextActivity; return NextActivity;
// Try to move within range // Try to move within range

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Mods.Common.Activities
{ {
var attack = self.Trait<AttackBase>(); var attack = self.Trait<AttackBase>();
targets = self.World.Actors.Where(a => self != a && !a.IsDead && a.IsInWorld && a.AppearsHostileTo(self) targets = self.World.Actors.Where(a => self != a && !a.IsDead && a.IsInWorld && a.AppearsHostileTo(self)
&& a.HasTrait<Huntable>() && IsTargetable(a, self) && attack.HasAnyValidWeapons(Target.FromActor(a))); && a.Info.Traits.Contains<HuntableInfo>() && IsTargetable(a, self) && attack.HasAnyValidWeapons(Target.FromActor(a)));
} }
bool IsTargetable(Actor self, Actor viewer) bool IsTargetable(Actor self, Actor viewer)

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Activities
{ {
target = value; target = value;
if (target.Type == TargetType.Actor) if (target.Type == TargetType.Actor)
canHideUnderFog = target.Actor.HasTrait<HiddenUnderFog>(); canHideUnderFog = target.Actor.Info.Traits.Contains<HiddenUnderFogInfo>();
} }
} }

View File

@@ -48,7 +48,8 @@ namespace OpenRA.Mods.Common.Activities
continue; continue;
// HACK to check if we are on the helipad/airfield/etc. // HACK to check if we are on the helipad/airfield/etc.
var hostBuilding = self.World.ActorMap.GetUnitsAt(self.Location).FirstOrDefault(a => a.HasTrait<Building>()); var hostBuilding = self.World.ActorMap.GetUnitsAt(self.Location)
.FirstOrDefault(a => a.Info.Traits.Contains<BuildingInfo>());
if (hostBuilding == null || !hostBuilding.IsInWorld) if (hostBuilding == null || !hostBuilding.IsInWorld)
return NextActivity; return NextActivity;

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common
if (self.IsDead) if (self.IsDead)
return false; return false;
if (!self.HasTrait<IOccupySpace>()) if (!self.Info.Traits.Contains<IOccupySpace>())
return false; return false;
if (!self.IsInWorld) if (!self.IsInWorld)
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common
if (stance == Stance.Ally) if (stance == Stance.Ally)
return true; return true;
if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.HasTrait<IgnoresDisguise>()) if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.Info.Traits.Contains<IgnoresDisguiseInfo>())
return toActor.Owner.Stances[self.EffectiveOwner.Owner] == Stance.Ally; return toActor.Owner.Stances[self.EffectiveOwner.Owner] == Stance.Ally;
return stance == Stance.Ally; return stance == Stance.Ally;
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common
if (stance == Stance.Ally) if (stance == Stance.Ally)
return false; /* otherwise, we'll hate friendly disguised spies */ return false; /* otherwise, we'll hate friendly disguised spies */
if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.HasTrait<IgnoresDisguise>()) if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.Info.Traits.Contains<IgnoresDisguiseInfo>())
return toActor.Owner.Stances[self.EffectiveOwner.Owner] == Stance.Enemy; return toActor.Owner.Stances[self.EffectiveOwner.Owner] == Stance.Enemy;
return stance == Stance.Enemy; return stance == Stance.Enemy;

View File

@@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Commands
var leveluporder = new Order("DevLevelUp", actor, false); var leveluporder = new Order("DevLevelUp", actor, false);
leveluporder.ExtraData = (uint)level; leveluporder.ExtraData = (uint)level;
if (actor.HasTrait<GainsExperience>()) if (actor.Info.Traits.Contains<GainsExperienceInfo>())
world.IssueOrder(leveluporder); world.IssueOrder(leveluporder);
} }

View File

@@ -165,7 +165,7 @@ namespace OpenRA.Mods.Common.Effects
contrail.Update(pos); contrail.Update(pos);
if (ticks++ >= length || (info.Blockable && world.ActorMap if (ticks++ >= length || (info.Blockable && world.ActorMap
.GetUnitsAt(world.Map.CellContaining(pos)).Any(a => a.HasTrait<IBlocksProjectiles>()))) .GetUnitsAt(world.Map.CellContaining(pos)).Any(a => a.Info.Traits.Contains<IBlocksProjectilesInfo>())))
Explode(world); Explode(world);
} }

View File

@@ -201,7 +201,7 @@ namespace OpenRA.Mods.Common.Effects
var shouldExplode = (pos.Z < 0) // Hit the ground var shouldExplode = (pos.Z < 0) // Hit the ground
|| (dist.LengthSquared < info.CloseEnough.LengthSquared) // Within range || (dist.LengthSquared < info.CloseEnough.LengthSquared) // Within range
|| (info.RangeLimit != 0 && ticks > info.RangeLimit) // Ran out of fuel || (info.RangeLimit != 0 && ticks > info.RangeLimit) // Ran out of fuel
|| (info.Blockable && world.ActorMap.GetUnitsAt(cell).Any(a => a.HasTrait<IBlocksProjectiles>())) // Hit a wall or other blocking obstacle || (info.Blockable && world.ActorMap.GetUnitsAt(cell).Any(a => a.Info.Traits.Contains<IBlocksProjectilesInfo>())) // Hit a wall or other blocking obstacle
|| !world.Map.Contains(cell) // This also avoids an IndexOutOfRangeException in GetTerrainInfo below. || !world.Map.Contains(cell) // This also avoids an IndexOutOfRangeException in GetTerrainInfo below.
|| (!string.IsNullOrEmpty(info.BoundToTerrainType) && world.Map.GetTerrainInfo(cell).Type != info.BoundToTerrainType); // Hit incompatible terrain || (!string.IsNullOrEmpty(info.BoundToTerrainType) && world.Map.GetTerrainInfo(cell).Type != info.BoundToTerrainType); // Hit incompatible terrain

View File

@@ -13,7 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Orders namespace OpenRA.Mods.Common.Orders
{ {
public class EnterAlliedActorTargeter<T> : UnitOrderTargeter public class EnterAlliedActorTargeter<T> : UnitOrderTargeter where T : ITraitInfo
{ {
readonly Func<Actor, bool> canTarget; readonly Func<Actor, bool> canTarget;
readonly Func<Actor, bool> useEnterCursor; readonly Func<Actor, bool> useEnterCursor;
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Orders
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
{ {
if (!target.HasTrait<T>() || !canTarget(target)) if (!target.Info.Traits.Contains<T>() || !canTarget(target))
return false; return false;
cursor = useEnterCursor(target) ? "enter" : "enter-blocked"; cursor = useEnterCursor(target) ? "enter" : "enter-blocked";

View File

@@ -83,7 +83,7 @@ namespace OpenRA.Mods.Common.Scripting
if (!target.IsValidFor(Self) || target.Type == TargetType.FrozenActor) if (!target.IsValidFor(Self) || target.Type == TargetType.FrozenActor)
Log.Write("lua", "{1} is an invalid target for {0}!", Self, targetActor); Log.Write("lua", "{1} is an invalid target for {0}!", Self, targetActor);
if (!targetActor.HasTrait<FrozenUnderFog>() && !Self.Owner.CanTargetActor(targetActor)) if (!targetActor.Info.Traits.Contains<FrozenUnderFogInfo>() && !Self.Owner.CanTargetActor(targetActor))
Log.Write("lua", "{1} is not revealed for player {0}!", Self.Owner, targetActor); Log.Write("lua", "{1} is not revealed for player {0}!", Self.Owner, targetActor);
attackBase.AttackTarget(target, true, allowMove); attackBase.AttackTarget(target, true, allowMove);

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Guard the target actor.")] [Desc("Guard the target actor.")]
public void Guard(Actor targetActor) public void Guard(Actor targetActor)
{ {
if (targetActor.HasTrait<Guardable>()) if (targetActor.Info.Traits.Contains<GuardableInfo>())
guard.GuardTarget(Self, Target.FromActor(targetActor)); guard.GuardTarget(Self, Target.FromActor(targetActor));
} }
} }

View File

@@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Scripting
public Actor[] GetGroundAttackers() public Actor[] GetGroundAttackers()
{ {
return Player.World.ActorsWithTrait<AttackBase>().Select(a => a.Actor) return Player.World.ActorsWithTrait<AttackBase>().Select(a => a.Actor)
.Where(a => a.Owner == Player && !a.IsDead && a.IsInWorld && a.HasTrait<Mobile>()) .Where(a => a.Owner == Player && !a.IsDead && a.IsInWorld && a.Info.Traits.Contains<MobileInfo>())
.ToArray(); .ToArray();
} }

View File

@@ -19,7 +19,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
public class AircraftInfo : ITraitInfo, IFacingInfo, IOccupySpaceInfo, ICruiseAltitudeInfo, UsesInit<LocationInit>, UsesInit<FacingInit> public class AircraftInfo : IPositionableInfo, IFacingInfo, IOccupySpaceInfo, ICruiseAltitudeInfo, UsesInit<LocationInit>, UsesInit<FacingInit>
{ {
public readonly WDist CruiseAltitude = new WDist(1280); public readonly WDist CruiseAltitude = new WDist(1280);
public readonly WDist IdealSeparation = new WDist(1706); public readonly WDist IdealSeparation = new WDist(1706);
@@ -120,7 +120,7 @@ namespace OpenRA.Mods.Common.Traits
firstTick = false; firstTick = false;
// TODO: Aircraft husks don't properly unreserve. // TODO: Aircraft husks don't properly unreserve.
if (self.HasTrait<FallsToEarth>()) if (self.Info.Traits.Contains<FallsToEarthInfo>())
return; return;
ReserveSpawnBuilding(); ReserveSpawnBuilding();
@@ -158,7 +158,7 @@ namespace OpenRA.Mods.Common.Traits
return WVec.Zero; return WVec.Zero;
return self.World.FindActorsInCircle(self.CenterPosition, info.IdealSeparation) return self.World.FindActorsInCircle(self.CenterPosition, info.IdealSeparation)
.Where(a => !a.IsDead && a.HasTrait<Aircraft>() && a.Info.Traits.Get<AircraftInfo>().CruiseAltitude == info.CruiseAltitude) .Where(a => !a.IsDead && a.Info.Traits.Contains<AircraftInfo>() && a.Info.Traits.Get<AircraftInfo>().CruiseAltitude == info.CruiseAltitude)
.Select(GetRepulsionForce) .Select(GetRepulsionForce)
.Aggregate(WVec.Zero, (a, b) => a + b); .Aggregate(WVec.Zero, (a, b) => a + b);
} }
@@ -191,7 +191,7 @@ namespace OpenRA.Mods.Common.Traits
return null; // not on the ground. return null; // not on the ground.
return self.World.ActorMap.GetUnitsAt(self.Location) return self.World.ActorMap.GetUnitsAt(self.Location)
.FirstOrDefault(a => a.HasTrait<Reservable>()); .FirstOrDefault(a => a.Info.Traits.Contains<ReservableInfo>());
} }
protected void ReserveSpawnBuilding() protected void ReserveSpawnBuilding()
@@ -341,7 +341,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
get get
{ {
yield return new EnterAlliedActorTargeter<Building>("Enter", 5, yield return new EnterAlliedActorTargeter<BuildingInfo>("Enter", 5,
target => AircraftCanEnter(target), target => !Reservable.IsReserved(target)); target => AircraftCanEnter(target), target => !Reservable.IsReserved(target));
yield return new AircraftMoveOrderTargeter(info); yield return new AircraftMoveOrderTargeter(info);

View File

@@ -202,7 +202,7 @@ namespace OpenRA.Mods.Common.Traits
public bool IsReachableTarget(Target target, bool allowMove) public bool IsReachableTarget(Target target, bool allowMove)
{ {
return HasAnyValidWeapons(target) return HasAnyValidWeapons(target)
&& (target.IsInRange(self.CenterPosition, GetMaximumRange()) || (allowMove && self.HasTrait<IMove>())); && (target.IsInRange(self.CenterPosition, GetMaximumRange()) || (allowMove && self.Info.Traits.Contains<IMoveInfo>()));
} }
class AttackOrderTargeter : IOrderTargeter class AttackOrderTargeter : IOrderTargeter

View File

@@ -81,8 +81,8 @@ namespace OpenRA.Mods.Common.Traits
var weapon = attack.ChooseArmamentForTarget(target); var weapon = attack.ChooseArmamentForTarget(target);
if (weapon != null) if (weapon != null)
{ {
var targetIsMobile = (target.Type == TargetType.Actor && target.Actor.HasTrait<IMove>()) var targetIsMobile = (target.Type == TargetType.Actor && target.Actor.Info.Traits.Contains<IMoveInfo>())
|| (target.Type == TargetType.FrozenActor && target.FrozenActor.Info.Traits.Contains<IMove>()); || (target.Type == TargetType.FrozenActor && target.FrozenActor.Info.Traits.Contains<IMoveInfo>());
// Try and sit at least one cell closer than the max range to give some leeway if the target starts moving. // Try and sit at least one cell closer than the max range to give some leeway if the target starts moving.
var maxRange = targetIsMobile ? new WDist(Math.Max(weapon.Weapon.MinRange.Length, weapon.Weapon.Range.Length - 1024)) var maxRange = targetIsMobile ? new WDist(Math.Max(weapon.Weapon.MinRange.Length, weapon.Weapon.Range.Length - 1024))

View File

@@ -154,7 +154,7 @@ namespace OpenRA.Mods.Common.Traits
return inRange return inRange
.Where(a => .Where(a =>
a.AppearsHostileTo(self) && a.AppearsHostileTo(self) &&
!a.HasTrait<AutoTargetIgnore>() && !a.Info.Traits.Contains<AutoTargetIgnoreInfo>() &&
attack.HasAnyValidWeapons(Target.FromActor(a)) && attack.HasAnyValidWeapons(Target.FromActor(a)) &&
self.Owner.CanTargetActor(a)) self.Owner.CanTargetActor(a))
.ClosestTo(self); .ClosestTo(self);

View File

@@ -15,6 +15,6 @@ namespace OpenRA.Mods.Common.Traits
{ {
// TODO: Add functionality like a customizable Height that is compared to projectile altitude // TODO: Add functionality like a customizable Height that is compared to projectile altitude
[Desc("This actor blocks bullets and missiles with 'Blockable' property.")] [Desc("This actor blocks bullets and missiles with 'Blockable' property.")]
public class BlocksProjectilesInfo : TraitInfo<BlocksProjectiles> { } public class BlocksProjectilesInfo : TraitInfo<BlocksProjectiles>, IBlocksProjectilesInfo { }
public class BlocksProjectiles : IBlocksProjectiles { } public class BlocksProjectiles : IBlocksProjectiles { }
} }

View File

@@ -77,7 +77,7 @@ namespace OpenRA.Mods.Common.Traits
// If a sprite actor has neither custom QuantizedFacings nor a trait implementing IQuantizeBodyOrientationInfo, throw // If a sprite actor has neither custom QuantizedFacings nor a trait implementing IQuantizeBodyOrientationInfo, throw
if (qboi == null) if (qboi == null)
{ {
if (self.HasTrait<ISpriteBody>()) if (self.Info.Traits.Contains<ISpriteBodyInfo>())
throw new InvalidOperationException("Actor '" + self.Info.Name + "' has a sprite body but no facing quantization." throw new InvalidOperationException("Actor '" + self.Info.Name + "' has a sprite body but no facing quantization."
+ " Either add the QuantizeFacingsFromSequence trait or set custom QuantizedFacings on BodyOrientation."); + " Either add the QuantizeFacingsFromSequence trait or set custom QuantizedFacings on BodyOrientation.");
else else

View File

@@ -201,7 +201,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
foreach (var c in footprint.Keys) foreach (var c in footprint.Keys)
foreach (var a in self.World.ActorMap.GetUnitsAt(c)) foreach (var a in self.World.ActorMap.GetUnitsAt(c))
if (a.HasTrait<IPositionable>() && !a.Trait<IPositionable>().CanEnterCell(c)) if (a.Info.Traits.Contains<IPositionableInfo>() && !a.Trait<IPositionable>().CanEnterCell(c))
a.Kill(self); a.Kill(self);
} }

View File

@@ -87,12 +87,12 @@ namespace OpenRA.Mods.Common.Traits
{ {
var unitsAtPos = world.ActorMap.GetUnitsAt(pos).Where(a => a.IsInWorld var unitsAtPos = world.ActorMap.GetUnitsAt(pos).Where(a => a.IsInWorld
&& (a.Owner == p || (allyBuildRadius && a.Owner.Stances[p] == Stance.Ally)) && (a.Owner == p || (allyBuildRadius && a.Owner.Stances[p] == Stance.Ally))
&& a.HasTrait<GivesBuildableArea>()); && a.Info.Traits.Contains<GivesBuildableAreaInfo>());
if (unitsAtPos.Any()) if (unitsAtPos.Any())
nearnessCandidates.Add(pos); nearnessCandidates.Add(pos);
} }
else if (buildingAtPos.IsInWorld && buildingAtPos.HasTrait<GivesBuildableArea>() else if (buildingAtPos.IsInWorld && buildingAtPos.Info.Traits.Contains<GivesBuildableAreaInfo>()
&& (buildingAtPos.Owner == p || (allyBuildRadius && buildingAtPos.Owner.Stances[p] == Stance.Ally))) && (buildingAtPos.Owner == p || (allyBuildRadius && buildingAtPos.Owner.Stances[p] == Stance.Ally)))
nearnessCandidates.Add(pos); nearnessCandidates.Add(pos);
} }
@@ -164,7 +164,7 @@ namespace OpenRA.Mods.Common.Traits
public void Created(Actor self) public void Created(Actor self)
{ {
if (SkipMakeAnimation || !self.HasTrait<WithMakeAnimation>()) if (SkipMakeAnimation || !self.Info.Traits.Contains<WithMakeAnimationInfo>())
NotifyBuildingComplete(self); NotifyBuildingComplete(self);
} }

View File

@@ -18,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
public class RefineryInfo : ITraitInfo, Requires<WithSpriteBodyInfo> public class RefineryInfo : IAcceptResourcesInfo, Requires<WithSpriteBodyInfo>
{ {
[Desc("Actual harvester facing when docking, 0-255 counter-clock-wise.")] [Desc("Actual harvester facing when docking, 0-255 counter-clock-wise.")]
public readonly int DockAngle = 0; public readonly int DockAngle = 0;

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
class CrateInfo : ITraitInfo, IOccupySpaceInfo, Requires<RenderSpritesInfo> class CrateInfo : IPositionableInfo, IOccupySpaceInfo, Requires<RenderSpritesInfo>
{ {
[Desc("Length of time (in seconds) until the crate gets removed automatically. " + [Desc("Length of time (in seconds) until the crate gets removed automatically. " +
"A value of zero disables auto-removal.")] "A value of zero disables auto-removal.")]

View File

@@ -101,7 +101,7 @@ namespace OpenRA.Mods.Common.Traits
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
{ {
if (!target.HasTrait<EngineerRepairable>()) if (!target.Info.Traits.Contains<EngineerRepairableInfo>())
return false; return false;
if (self.Owner.Stances[target.Owner] != Stance.Ally) if (self.Owner.Stances[target.Owner] != Stance.Ally)
@@ -115,7 +115,7 @@ namespace OpenRA.Mods.Common.Traits
public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)
{ {
if (!target.Info.Traits.Contains<EngineerRepairable>()) if (!target.Info.Traits.Contains<EngineerRepairableInfo>())
return false; return false;
if (self.Owner.Stances[target.Owner] != Stance.Ally) if (self.Owner.Stances[target.Owner] != Stance.Ally)

View File

@@ -88,7 +88,7 @@ namespace OpenRA.Mods.Common.Traits
public void Tick(World world) public void Tick(World world)
{ {
if (subjects.All(s => s.IsDead || !s.HasTrait<Guard>())) if (subjects.All(s => s.IsDead || !s.Info.Traits.Contains<GuardInfo>()))
world.CancelInputMode(); world.CancelInputMode();
} }
@@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Traits
return world.ScreenMap.ActorsAt(mi) return world.ScreenMap.ActorsAt(mi)
.Where(a => !world.FogObscures(a) && !a.IsDead && .Where(a => !world.FogObscures(a) && !a.IsDead &&
a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) &&
a.HasTrait<Guardable>()); a.Info.Traits.Contains<GuardableInfo>());
} }
} }
} }

View File

@@ -297,7 +297,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
get get
{ {
yield return new EnterAlliedActorTargeter<IAcceptResources>("Deliver", 5, yield return new EnterAlliedActorTargeter<IAcceptResourcesInfo>("Deliver", 5,
proc => IsAcceptableProcType(proc), proc => IsAcceptableProcType(proc),
proc => !IsEmpty && proc.Trait<IAcceptResources>().AllowDocking); proc => !IsEmpty && proc.Trait<IAcceptResources>().AllowDocking);
yield return new HarvestOrderTargeter(); yield return new HarvestOrderTargeter();

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Traits
if (self.IsDead) if (self.IsDead)
return; return;
if (Info.RemoveInstead || !self.HasTrait<Health>()) if (Info.RemoveInstead || !self.Info.Traits.Contains<HealthInfo>())
self.Dispose(); self.Dispose();
else else
self.Kill(self); self.Kill(self);

View File

@@ -38,7 +38,8 @@ namespace OpenRA.Mods.Common.Traits
} }
[Desc("Unit is able to move.")] [Desc("Unit is able to move.")]
public class MobileInfo : IMoveInfo, IOccupySpaceInfo, IFacingInfo, UsesInit<FacingInit>, UsesInit<LocationInit>, UsesInit<SubCellInit> public class MobileInfo : IMoveInfo, IPositionableInfo, IOccupySpaceInfo, IFacingInfo,
UsesInit<FacingInit>, UsesInit<LocationInit>, UsesInit<SubCellInit>
{ {
[FieldLoader.LoadUsing("LoadSpeeds", true)] [FieldLoader.LoadUsing("LoadSpeeds", true)]
[Desc("Set Water: 0 for ground units and lower the value on rough terrain.")] [Desc("Set Water: 0 for ground units and lower the value on rough terrain.")]
@@ -664,7 +665,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
var cellInfo = notStupidCells var cellInfo = notStupidCells
.SelectMany(c => self.World.ActorMap.GetUnitsAt(c) .SelectMany(c => self.World.ActorMap.GetUnitsAt(c)
.Where(a => a.IsIdle && a.HasTrait<Mobile>()), .Where(a => a.IsIdle && a.Info.Traits.Contains<MobileInfo>()),
(c, a) => new { Cell = c, Actor = a }) (c, a) => new { Cell = c, Actor = a })
.RandomOrDefault(self.World.SharedRandom); .RandomOrDefault(self.World.SharedRandom);

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Traits
readonly bool startsRevealed; readonly bool startsRevealed;
readonly PPos[] footprint; readonly PPos[] footprint;
readonly Lazy<IToolTip> tooltip; readonly Lazy<ITooltip> tooltip;
readonly Lazy<Health> health; readonly Lazy<Health> health;
readonly Dictionary<Player, bool> visible; readonly Dictionary<Player, bool> visible;
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits
startsRevealed = info.StartsRevealed && !init.Contains<ParentActorInit>(); startsRevealed = info.StartsRevealed && !init.Contains<ParentActorInit>();
var footprintCells = FootprintUtils.Tiles(init.Self).ToList(); var footprintCells = FootprintUtils.Tiles(init.Self).ToList();
footprint = footprintCells.SelectMany(c => map.ProjectedCellsCovering(c.ToMPos(map))).ToArray(); footprint = footprintCells.SelectMany(c => map.ProjectedCellsCovering(c.ToMPos(map))).ToArray();
tooltip = Exts.Lazy(() => init.Self.TraitsImplementing<IToolTip>().FirstOrDefault()); tooltip = Exts.Lazy(() => init.Self.TraitsImplementing<ITooltip>().FirstOrDefault());
health = Exts.Lazy(() => init.Self.TraitOrDefault<Health>()); health = Exts.Lazy(() => init.Self.TraitOrDefault<Health>());
frozen = new Dictionary<Player, FrozenActor>(); frozen = new Dictionary<Player, FrozenActor>();

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
public enum AlternateTransportsMode { None, Force, Default, Always } public enum AlternateTransportsMode { None, Force, Default, Always }
public class EnterTransportTargeter : EnterAlliedActorTargeter<Cargo> public class EnterTransportTargeter : EnterAlliedActorTargeter<CargoInfo>
{ {
readonly AlternateTransportsMode mode; readonly AlternateTransportsMode mode;
@@ -51,7 +51,7 @@ namespace OpenRA.Mods.Common.Traits
} }
} }
public class EnterTransportsTargeter : EnterAlliedActorTargeter<Cargo> public class EnterTransportsTargeter : EnterAlliedActorTargeter<CargoInfo>
{ {
readonly AlternateTransportsMode mode; readonly AlternateTransportsMode mode;
@@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits
Info = info; Info = info;
Func<Actor, bool> canTarget = IsCorrectCargoType; Func<Actor, bool> canTarget = IsCorrectCargoType;
Func<Actor, bool> useEnterCursor = CanEnter; Func<Actor, bool> useEnterCursor = CanEnter;
Orders = new EnterAlliedActorTargeter<Cargo>[] Orders = new EnterAlliedActorTargeter<CargoInfo>[]
{ {
new EnterTransportTargeter("EnterTransport", 5, canTarget, useEnterCursor, Info.AlternateTransportsMode), new EnterTransportTargeter("EnterTransport", 5, canTarget, useEnterCursor, Info.AlternateTransportsMode),
new EnterTransportsTargeter("EnterTransports", 5, canTarget, useEnterCursor, Info.AlternateTransportsMode) new EnterTransportsTargeter("EnterTransports", 5, canTarget, useEnterCursor, Info.AlternateTransportsMode)

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
var building = order.TargetActor; var building = order.TargetActor;
if (building.HasTrait<RepairableBuilding>()) if (building.Info.Traits.Contains<RepairableBuildingInfo>())
if (building.AppearsFriendlyTo(self)) if (building.AppearsFriendlyTo(self))
building.Trait<RepairableBuilding>().RepairBuilding(building, self.Owner); building.Trait<RepairableBuilding>().RepairBuilding(building, self.Owner);
} }

View File

@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits
public void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
// only track last hit against our base // only track last hit against our base
if (!self.HasTrait<Building>()) if (!self.Info.Traits.Contains<BuildingInfo>())
return; return;
if (e.Attacker == null) if (e.Attacker == null)

View File

@@ -47,8 +47,8 @@ namespace OpenRA.Mods.Common.Traits
public void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
// only track last hit against our base // only track last hit against our harvesters
if (!self.HasTrait<Harvester>()) if (!self.Info.Traits.Contains<HarvesterInfo>())
return; return;
// don't track self-damage // don't track self-damage

View File

@@ -107,18 +107,18 @@ namespace OpenRA.Mods.Common.Traits
var attackerStats = e.Attacker.Owner.PlayerActor.Trait<PlayerStatistics>(); var attackerStats = e.Attacker.Owner.PlayerActor.Trait<PlayerStatistics>();
var defenderStats = self.Owner.PlayerActor.Trait<PlayerStatistics>(); var defenderStats = self.Owner.PlayerActor.Trait<PlayerStatistics>();
if (self.HasTrait<Building>()) if (self.Info.Traits.Contains<BuildingInfo>())
{ {
attackerStats.BuildingsKilled++; attackerStats.BuildingsKilled++;
defenderStats.BuildingsDead++; defenderStats.BuildingsDead++;
} }
else if (self.HasTrait<IPositionable>()) else if (self.Info.Traits.Contains<IPositionableInfo>())
{ {
attackerStats.UnitsKilled++; attackerStats.UnitsKilled++;
defenderStats.UnitsDead++; defenderStats.UnitsDead++;
} }
if (self.HasTrait<Valued>()) if (self.Info.Traits.Contains<ValuedInfo>())
{ {
var cost = self.Info.Traits.Get<ValuedInfo>().Cost; var cost = self.Info.Traits.Get<ValuedInfo>().Cost;
attackerStats.KillsCost += cost; attackerStats.KillsCost += cost;

View File

@@ -14,7 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
public class ProvidesPrerequisiteInfo : ITraitInfo public class ProvidesPrerequisiteInfo : ITechTreePrerequisiteInfo
{ {
[Desc("The prerequisite type that this provides. If left empty it defaults to the actor's name.")] [Desc("The prerequisite type that this provides. If left empty it defaults to the actor's name.")]
public readonly string Prerequisite = null; public readonly string Prerequisite = null;

View File

@@ -13,7 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
public class ProvidesTechPrerequisiteInfo : ITraitInfo public class ProvidesTechPrerequisiteInfo : ITechTreePrerequisiteInfo
{ {
public readonly string Name; public readonly string Name;
public readonly string[] Prerequisites = { }; public readonly string[] Prerequisites = { };

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Traits
public void ActorChanged(Actor a) public void ActorChanged(Actor a)
{ {
var bi = a.Info.Traits.GetOrDefault<BuildableInfo>(); var bi = a.Info.Traits.GetOrDefault<BuildableInfo>();
if (a.Owner == player && (a.HasTrait<ITechTreePrerequisite>() || (bi != null && bi.BuildLimit > 0))) if (a.Owner == player && (a.Info.Traits.Contains<ITechTreePrerequisiteInfo>() || (bi != null && bi.BuildLimit > 0)))
Update(); Update();
} }

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Traits
public Hovers(HoversInfo info, Actor self) public Hovers(HoversInfo info, Actor self)
{ {
this.info = info; this.info = info;
aircraft = self.HasTrait<Aircraft>(); aircraft = self.Info.Traits.Contains<AircraftInfo>();
} }
public IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r) public IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
this.info = info; this.info = info;
wsb = self.Trait<WithSpriteBody>(); wsb = self.Trait<WithSpriteBody>();
buildComplete = !self.HasTrait<Building>(); buildComplete = !self.Info.Traits.Contains<BuildingInfo>();
} }
public void BuildingComplete(Actor self) public void BuildingComplete(Actor self)

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits
var rs = self.Trait<RenderSprites>(); var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>(); var body = self.Trait<BodyOrientation>();
buildComplete = !self.HasTrait<Building>(); // always render instantly for units buildComplete = !self.Info.Traits.Contains<BuildingInfo>(); // always render instantly for units
overlay = new Animation(self.World, rs.GetImage(self)); overlay = new Animation(self.World, rs.GetImage(self));

View File

@@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.Traits
var rs = self.Trait<RenderSprites>(); var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>(); var body = self.Trait<BodyOrientation>();
buildComplete = !self.HasTrait<Building>(); // always render instantly for units buildComplete = !self.Info.Traits.Contains<BuildingInfo>(); // always render instantly for units
var overlay = new Animation(self.World, rs.GetImage(self)); var overlay = new Animation(self.World, rs.GetImage(self));
overlay.Play(info.Sequence); overlay.Play(info.Sequence);

View File

@@ -68,7 +68,7 @@ namespace OpenRA.Mods.Common.Traits
var rs = self.Trait<RenderSprites>(); var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>(); var body = self.Trait<BodyOrientation>();
buildComplete = !self.HasTrait<Building>(); // always render instantly for units buildComplete = !self.Info.Traits.Contains<BuildingInfo>(); // always render instantly for units
overlay = new Animation(self.World, rs.GetImage(self)); overlay = new Animation(self.World, rs.GetImage(self));
if (info.StartSequence != null) if (info.StartSequence != null)
overlay.PlayThen(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.StartSequence), overlay.PlayThen(RenderSprites.NormalizeSequence(overlay, self.GetDamageState(), info.StartSequence),

View File

@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits
var rs = self.Trait<RenderSprites>(); var rs = self.Trait<RenderSprites>();
var body = self.Trait<BodyOrientation>(); var body = self.Trait<BodyOrientation>();
buildComplete = !self.HasTrait<Building>(); // always render instantly for units buildComplete = !self.Info.Traits.Contains<BuildingInfo>(); // always render instantly for units
overlay = new Animation(self.World, rs.GetImage(self)); overlay = new Animation(self.World, rs.GetImage(self));
overlay.Play(info.Sequence); overlay.Play(info.Sequence);

View File

@@ -17,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[Desc("Default trait for rendering sprite-based actors.")] [Desc("Default trait for rendering sprite-based actors.")]
public class WithSpriteBodyInfo : UpgradableTraitInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo> public class WithSpriteBodyInfo : UpgradableTraitInfo, ISpriteBodyInfo, IRenderActorPreviewSpritesInfo, Requires<RenderSpritesInfo>
{ {
[Desc("Animation to play when the actor is created."), SequenceReference] [Desc("Animation to play when the actor is created."), SequenceReference]
public readonly string StartSequence = null; public readonly string StartSequence = null;

View File

@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
get get
{ {
yield return new EnterAlliedActorTargeter<Building>("Repair", 5, CanRepairAt, _ => CanRepair() || CanRearm()); yield return new EnterAlliedActorTargeter<BuildingInfo>("Repair", 5, CanRepairAt, _ => CanRepair() || CanRearm());
} }
} }

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
get get
{ {
yield return new EnterAlliedActorTargeter<Building>("RepairNear", 5, yield return new EnterAlliedActorTargeter<BuildingInfo>("RepairNear", 5,
target => CanRepairAt(target), _ => ShouldRepair()); target => CanRepairAt(target), _ => ShouldRepair());
} }
} }

View File

@@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
public AmbientSound(Actor self, AmbientSoundInfo info) public AmbientSound(Actor self, AmbientSoundInfo info)
{ {
if (self.HasTrait<IOccupySpace>()) if (self.Info.Traits.Contains<IOccupySpaceInfo>())
Sound.PlayLooped(info.SoundFile, self.CenterPosition); Sound.PlayLooped(info.SoundFile, self.CenterPosition);
else else
Sound.PlayLooped(info.SoundFile); Sound.PlayLooped(info.SoundFile);

View File

@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
{ {
return target.HasTrait<AcceptsSupplies>(); return target.Info.Traits.Contains<AcceptsSuppliesInfo>();
} }
public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)

View File

@@ -78,7 +78,7 @@ namespace OpenRA.Mods.Common.Traits
void ActorRemoved(Actor a) void ActorRemoved(Actor a)
{ {
if (a.Owner != Self.Owner || !a.HasTrait<SupportPower>()) if (a.Owner != Self.Owner || !a.Info.Traits.Contains<SupportPowerInfo>())
return; return;
foreach (var t in a.TraitsImplementing<SupportPower>()) foreach (var t in a.TraitsImplementing<SupportPower>())
@@ -119,7 +119,7 @@ namespace OpenRA.Mods.Common.Traits
public IEnumerable<SupportPowerInstance> GetPowersForActor(Actor a) public IEnumerable<SupportPowerInstance> GetPowersForActor(Actor a)
{ {
if (a.Owner != Self.Owner || !a.HasTrait<SupportPower>()) if (a.Owner != Self.Owner || !a.Info.Traits.Contains<SupportPowerInfo>())
return NoInstances; return NoInstances;
return a.TraitsImplementing<SupportPower>() return a.TraitsImplementing<SupportPower>()

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
if (IsTraitDisabled) if (IsTraitDisabled)
return false; return false;
if (cloak == null || (!viewer.IsDead && viewer.HasTrait<IgnoresCloak>())) if (cloak == null || (!viewer.IsDead && viewer.Info.Traits.Contains<IgnoresCloakInfo>()))
return true; return true;
return cloak.IsVisible(self, viewer.Owner); return cloak.IsVisible(self, viewer.Owner);

View File

@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits
public bool IsOwnerRowVisible { get { return ShowOwnerRow; } } public bool IsOwnerRowVisible { get { return ShowOwnerRow; } }
} }
public class Tooltip : IToolTip public class Tooltip : ITooltip
{ {
readonly Actor self; readonly Actor self;
readonly TooltipInfo info; readonly TooltipInfo info;

View File

@@ -109,10 +109,10 @@ namespace OpenRA.Mods.Common.Traits
if (!queued) if (!queued)
self.CancelActivity(); self.CancelActivity();
if (self.HasTrait<IFacing>()) if (self.Info.Traits.Contains<IFacingInfo>())
self.QueueActivity(new Turn(self, info.Facing)); self.QueueActivity(new Turn(self, info.Facing));
if (self.HasTrait<Helicopter>()) if (self.Info.Traits.Contains<HelicopterInfo>())
self.QueueActivity(new HeliLand(self, true)); self.QueueActivity(new HeliLand(self, true));
foreach (var nt in self.TraitsImplementing<INotifyTransform>()) foreach (var nt in self.TraitsImplementing<INotifyTransform>())

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
public interface ISpriteBodyInfo : ITraitInfo { }
public interface ISpriteBody public interface ISpriteBody
{ {
void PlayCustomAnimation(Actor self, string newAnimation, Action after); void PlayCustomAnimation(Actor self, string newAnimation, Action after);
@@ -67,6 +68,7 @@ namespace OpenRA.Mods.Common.Traits
void Undocked(); void Undocked();
} }
public interface ITechTreePrerequisiteInfo : ITraitInfo { }
public interface ITechTreePrerequisite public interface ITechTreePrerequisite
{ {
IEnumerable<string> ProvidesPrerequisites { get; } IEnumerable<string> ProvidesPrerequisites { get; }
@@ -91,6 +93,7 @@ namespace OpenRA.Mods.Common.Traits
public interface INotifyTransform { void BeforeTransform(Actor self); void OnTransform(Actor self); void AfterTransform(Actor toActor); } public interface INotifyTransform { void BeforeTransform(Actor self); void OnTransform(Actor self); void AfterTransform(Actor toActor); }
public interface IAcceptResourcesInfo : ITraitInfo { }
public interface IAcceptResources public interface IAcceptResources
{ {
void OnDock(Actor harv, DeliverResources dockOrder); void OnDock(Actor harv, DeliverResources dockOrder);

View File

@@ -245,7 +245,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
.Sum(a => a.Info.Traits.WithInterface<ValuedInfo>().First().Cost); .Sum(a => a.Info.Traits.WithInterface<ValuedInfo>().First().Cost);
var harvesters = template.Get<LabelWidget>("HARVESTERS"); var harvesters = template.Get<LabelWidget>("HARVESTERS");
harvesters.GetText = () => world.Actors.Count(a => a.Owner == player && !a.IsDead && a.HasTrait<Harvester>()).ToString(); harvesters.GetText = () => world.Actors.Count(a => a.Owner == player && !a.IsDead && a.Info.Traits.Contains<HarvesterInfo>()).ToString();
return template; return template;
} }
@@ -280,7 +280,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
return ScrollItemWidget.Setup(template, () => false, () => return ScrollItemWidget.Setup(template, () => false, () =>
{ {
var playerBase = world.Actors.FirstOrDefault(a => !a.IsDead && a.HasTrait<BaseBuilding>() && a.Owner == player); var playerBase = world.Actors.FirstOrDefault(a => !a.IsDead && a.Info.Traits.Contains<BaseBuildingInfo>() && a.Owner == player);
if (playerBase != null) if (playerBase != null)
worldRenderer.Viewport.Center(playerBase.CenterPosition); worldRenderer.Viewport.Center(playerBase.CenterPosition);
}); });

View File

@@ -198,7 +198,7 @@ namespace OpenRA.Mods.Common.Widgets
// Is added to world.ActorAdded by the SidebarLogic handler // Is added to world.ActorAdded by the SidebarLogic handler
public void ActorChanged(Actor a) public void ActorChanged(Actor a)
{ {
if (a.HasTrait<ProductionQueue>()) if (a.Info.Traits.Contains<ProductionQueueInfo>())
{ {
var allQueues = a.World.ActorsWithTrait<ProductionQueue>() var allQueues = a.World.ActorsWithTrait<ProductionQueue>()
.Where(p => p.Actor.Owner == p.Actor.World.LocalPlayer && p.Actor.IsInWorld && p.Trait.Enabled) .Where(p => p.Actor.Owner == p.Actor.World.LocalPlayer && p.Actor.IsInWorld && p.Trait.Enabled)

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Widgets
Lazy<TooltipContainerWidget> tooltipContainer; Lazy<TooltipContainerWidget> tooltipContainer;
public WorldTooltipType TooltipType { get; private set; } public WorldTooltipType TooltipType { get; private set; }
public IToolTip ActorTooltip { get; private set; } public ITooltip ActorTooltip { get; private set; }
public IProvideTooltipInfo[] ActorTooltipExtra { get; private set; } public IProvideTooltipInfo[] ActorTooltipExtra { get; private set; }
public FrozenActor FrozenActorTooltip { get; private set; } public FrozenActor FrozenActorTooltip { get; private set; }
@@ -106,12 +106,12 @@ namespace OpenRA.Mods.Common.Widgets
} }
var underCursor = world.ScreenMap.ActorsAt(worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos)) var underCursor = world.ScreenMap.ActorsAt(worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos))
.Where(a => !world.FogObscures(a) && a.HasTrait<IToolTip>()) .Where(a => !world.FogObscures(a) && a.Info.Traits.Contains<ITooltipInfo>())
.WithHighestSelectionPriority(); .WithHighestSelectionPriority();
if (underCursor != null) if (underCursor != null)
{ {
ActorTooltip = underCursor.TraitsImplementing<IToolTip>().First(); ActorTooltip = underCursor.TraitsImplementing<ITooltip>().First();
ActorTooltipExtra = underCursor.TraitsImplementing<IProvideTooltipInfo>().ToArray(); ActorTooltipExtra = underCursor.TraitsImplementing<IProvideTooltipInfo>().ToArray();
TooltipType = WorldTooltipType.Actor; TooltipType = WorldTooltipType.Actor;
return; return;

View File

@@ -177,7 +177,7 @@ namespace OpenRA.Mods.Common.Widgets
bool PerformGuard() bool PerformGuard()
{ {
var actors = world.Selection.Actors var actors = world.Selection.Actors
.Where(a => !a.Disposed && a.Owner == world.LocalPlayer && a.HasTrait<Guard>()); .Where(a => !a.Disposed && a.Owner == world.LocalPlayer && a.Info.Traits.Contains<GuardInfo>());
if (actors.Any()) if (actors.Any())
world.OrderGenerator = new GuardOrderGenerator(actors); world.OrderGenerator = new GuardOrderGenerator(actors);
@@ -197,7 +197,7 @@ namespace OpenRA.Mods.Common.Widgets
{ {
var building = world.ActorsWithTrait<Building>() var building = world.ActorsWithTrait<Building>()
.Select(b => b.Actor) .Select(b => b.Actor)
.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.HasTrait<Selectable>()); .FirstOrDefault(a => a.Owner == world.LocalPlayer && a.Info.Traits.Contains<SelectableInfo>());
// No buildings left // No buildings left
if (building == null) if (building == null)
@@ -223,7 +223,7 @@ namespace OpenRA.Mods.Common.Widgets
bool CycleProductionBuildings() bool CycleProductionBuildings()
{ {
var facilities = world.ActorsWithTrait<Production>() var facilities = world.ActorsWithTrait<Production>()
.Where(a => a.Actor.Owner == world.LocalPlayer && !a.Actor.HasTrait<BaseBuilding>()) .Where(a => a.Actor.Owner == world.LocalPlayer && !a.Actor.Info.Traits.Contains<BaseBuildingInfo>())
.OrderBy(f => f.Actor.Info.Traits.Get<ProductionInfo>().Produces.First()) .OrderBy(f => f.Actor.Info.Traits.Get<ProductionInfo>().Produces.First())
.Select(b => b.Actor) .Select(b => b.Actor)
.ToList(); .ToList();

View File

@@ -79,7 +79,7 @@ namespace OpenRA.Mods.D2k.Activities
actor1.Dispose(); actor1.Dispose();
// Harvester insurance // Harvester insurance
if (!actor1.HasTrait<Harvester>()) if (!actor1.Info.Traits.Contains<HarvesterInfo>())
return; return;
var insurance = actor1.Owner.PlayerActor.TraitOrDefault<HarvesterInsurance>(); var insurance = actor1.Owner.PlayerActor.TraitOrDefault<HarvesterInsurance>();

View File

@@ -117,7 +117,7 @@ namespace OpenRA.Mods.D2k.Traits
{ {
// HACK: Harvesters need special treatment to avoid getting stuck on resource fields, // HACK: Harvesters need special treatment to avoid getting stuck on resource fields,
// so if a Harvester's afterLandActivity is not DeliverResources, queue a new FindResources activity // so if a Harvester's afterLandActivity is not DeliverResources, queue a new FindResources activity
var findResources = self.HasTrait<Harvester>() && !(afterLandActivity is DeliverResources); var findResources = self.Info.Traits.Contains<HarvesterInfo>() && !(afterLandActivity is DeliverResources);
if (findResources) if (findResources)
self.QueueActivity(new FindResources(self)); self.QueueActivity(new FindResources(self));
else else

View File

@@ -49,7 +49,7 @@ namespace OpenRA.Mods.D2k.Traits
var body = self.Trait<BodyOrientation>(); var body = self.Trait<BodyOrientation>();
// always render instantly for units // always render instantly for units
buildComplete = !self.HasTrait<Building>(); buildComplete = !self.Info.Traits.Contains<BuildingInfo>();
var overlay = new Animation(self.World, rs.GetImage(self)); var overlay = new Animation(self.World, rs.GetImage(self));
overlay.Play(info.Sequence); overlay.Play(info.Sequence);

View File

@@ -99,7 +99,7 @@ namespace OpenRA.Mods.D2k.Traits
targetCountdown = Info.TargetRescanInterval; targetCountdown = Info.TargetRescanInterval;
// If close enough, we don't care about other actors. // If close enough, we don't care about other actors.
var target = self.World.FindActorsInCircle(self.CenterPosition, Info.IgnoreNoiseAttackRange).FirstOrDefault(x => x.HasTrait<AttractsWorms>()); var target = self.World.FindActorsInCircle(self.CenterPosition, Info.IgnoreNoiseAttackRange).FirstOrDefault(x => x.Info.Traits.Contains<AttractsWormsInfo>());
if (target != null) if (target != null)
{ {
self.CancelActivity(); self.CancelActivity();
@@ -109,7 +109,7 @@ namespace OpenRA.Mods.D2k.Traits
Func<Actor, bool> isValidTarget = a => Func<Actor, bool> isValidTarget = a =>
{ {
if (!a.HasTrait<AttractsWorms>()) if (!a.Info.Traits.Contains<AttractsWormsInfo>())
return false; return false;
return mobile.CanEnterCell(a.Location, null, false); return mobile.CanEnterCell(a.Location, null, false);

View File

@@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Activities
self.Dispose(); self.Dispose();
if (target.HasTrait<Building>()) if (target.Info.Traits.Contains<BuildingInfo>())
Sound.PlayToPlayer(self.Owner, "bldginf1.aud"); Sound.PlayToPlayer(self.Owner, "bldginf1.aud");
} }
} }

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Traits
public void UnitProducedByOther(Actor self, Actor producer, Actor produced) public void UnitProducedByOther(Actor self, Actor producer, Actor produced)
{ {
// No recursive cloning! // No recursive cloning!
if (producer.Owner != self.Owner || producer.HasTrait<ClonesProducedUnits>()) if (producer.Owner != self.Owner || producer.Info.Traits.Contains<ClonesProducedUnitsInfo>())
return; return;
var ci = produced.Info.Traits.GetOrDefault<CloneableInfo>(); var ci = produced.Info.Traits.GetOrDefault<CloneableInfo>();

View File

@@ -64,7 +64,7 @@ namespace OpenRA.Mods.RA.Traits
public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation) public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation)
{ {
// TODO: Allow enemy units to be chronoshifted into bad terrain to kill them // TODO: Allow enemy units to be chronoshifted into bad terrain to kill them
return self.HasTrait<IPositionable>() && self.Trait<IPositionable>().CanEnterCell(targetLocation); return self.Info.Traits.Contains<IPositionableInfo>() && self.Trait<IPositionable>().CanEnterCell(targetLocation);
} }
public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere) public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere)

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA.Traits
public override object Create(ActorInitializer init) { return new DisguiseToolTip(init.Self, this); } public override object Create(ActorInitializer init) { return new DisguiseToolTip(init.Self, this); }
} }
class DisguiseToolTip : IToolTip class DisguiseToolTip : ITooltip
{ {
readonly Actor self; readonly Actor self;
readonly Disguise disguise; readonly Disguise disguise;
@@ -147,7 +147,7 @@ namespace OpenRA.Mods.RA.Traits
else else
{ {
AsSprite = target.Trait<RenderSprites>().GetImage(target); AsSprite = target.Trait<RenderSprites>().GetImage(target);
var tooltip = target.TraitsImplementing<IToolTip>().FirstOrDefault(); var tooltip = target.TraitsImplementing<ITooltip>().FirstOrDefault();
AsPlayer = tooltip.Owner; AsPlayer = tooltip.Owner;
AsTooltipInfo = tooltip.TooltipInfo; AsTooltipInfo = tooltip.TooltipInfo;
} }

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.RA.Traits
public void OnCrush(Actor crusher) public void OnCrush(Actor crusher)
{ {
if (crusher.HasTrait<MineImmune>() || (self.Owner.Stances[crusher.Owner] == Stance.Ally && info.AvoidFriendly)) if (crusher.Info.Traits.Contains<MineImmuneInfo>() || (self.Owner.Stances[crusher.Owner] == Stance.Ally && info.AvoidFriendly))
return; return;
var mobile = crusher.TraitOrDefault<Mobile>(); var mobile = crusher.TraitOrDefault<Mobile>();

View File

@@ -64,7 +64,7 @@ namespace OpenRA.Mods.RA.Traits
foreach (var t in tiles) foreach (var t in tiles)
units.UnionWith(Self.World.ActorMap.GetUnitsAt(t)); units.UnionWith(Self.World.ActorMap.GetUnitsAt(t));
return units.Where(a => a.HasTrait<Chronoshiftable>() && return units.Where(a => a.Info.Traits.Contains<ChronoshiftableInfo>() &&
!a.TraitsImplementing<IPreventsTeleport>().Any(condition => condition.PreventsTeleport(a))); !a.TraitsImplementing<IPreventsTeleport>().Any(condition => condition.PreventsTeleport(a)));
} }