Add ActorInfo.HasTraitInfo<T>() requiring ITraitInfo types

This commit is contained in:
atlimit8
2015-08-02 12:44:46 -05:00
parent 85fab45451
commit 8162fa27ab
77 changed files with 138 additions and 136 deletions

View File

@@ -120,7 +120,7 @@ namespace OpenRA.Mods.Common.Traits
firstTick = false;
// TODO: Aircraft husks don't properly unreserve.
if (self.Info.Traits.Contains<FallsToEarthInfo>())
if (self.Info.HasTraitInfo<FallsToEarthInfo>())
return;
ReserveSpawnBuilding();
@@ -158,7 +158,7 @@ namespace OpenRA.Mods.Common.Traits
return WVec.Zero;
return self.World.FindActorsInCircle(self.CenterPosition, info.IdealSeparation)
.Where(a => !a.IsDead && a.Info.Traits.Contains<AircraftInfo>() && a.Info.Traits.Get<AircraftInfo>().CruiseAltitude == info.CruiseAltitude)
.Where(a => !a.IsDead && a.Info.HasTraitInfo<AircraftInfo>() && a.Info.Traits.Get<AircraftInfo>().CruiseAltitude == info.CruiseAltitude)
.Select(GetRepulsionForce)
.Aggregate(WVec.Zero, (a, b) => a + b);
}
@@ -191,7 +191,7 @@ namespace OpenRA.Mods.Common.Traits
return null; // not on the ground.
return self.World.ActorMap.GetUnitsAt(self.Location)
.FirstOrDefault(a => a.Info.Traits.Contains<ReservableInfo>());
.FirstOrDefault(a => a.Info.HasTraitInfo<ReservableInfo>());
}
protected void ReserveSpawnBuilding()

View File

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

View File

@@ -81,8 +81,8 @@ namespace OpenRA.Mods.Common.Traits
var weapon = attack.ChooseArmamentForTarget(target);
if (weapon != null)
{
var targetIsMobile = (target.Type == TargetType.Actor && target.Actor.Info.Traits.Contains<IMoveInfo>())
|| (target.Type == TargetType.FrozenActor && target.FrozenActor.Info.Traits.Contains<IMoveInfo>());
var targetIsMobile = (target.Type == TargetType.Actor && target.Actor.Info.HasTraitInfo<IMoveInfo>())
|| (target.Type == TargetType.FrozenActor && target.FrozenActor.Info.HasTraitInfo<IMoveInfo>());
// 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))

View File

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

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 (qboi == null)
{
if (self.Info.Traits.Contains<ISpriteBodyInfo>())
if (self.Info.HasTraitInfo<ISpriteBodyInfo>())
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.");
else

View File

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

View File

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

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.Traits
if (csv != null)
return csv.Value;
var cost = a.Traits.Contains<ValuedInfo>() ? a.Traits.Get<ValuedInfo>().Cost : 0;
var cost = a.HasTraitInfo<ValuedInfo>() ? a.Traits.Get<ValuedInfo>().Cost : 0;
var time = cost
* (25 * 60) /* frames per min */
/ 1000;

View File

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

View File

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

View File

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

View File

@@ -665,7 +665,7 @@ namespace OpenRA.Mods.Common.Traits
{
var cellInfo = notStupidCells
.SelectMany(c => self.World.ActorMap.GetUnitsAt(c)
.Where(a => a.IsIdle && a.Info.Traits.Contains<MobileInfo>()),
.Where(a => a.IsIdle && a.Info.HasTraitInfo<MobileInfo>()),
(c, a) => new { Cell = c, Actor = a })
.RandomOrDefault(self.World.SharedRandom);

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.Traits
{
var building = order.TargetActor;
if (building.Info.Traits.Contains<RepairableBuildingInfo>())
if (building.Info.HasTraitInfo<RepairableBuildingInfo>())
if (building.AppearsFriendlyTo(self))
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)
{
// only track last hit against our base
if (!self.Info.Traits.Contains<BuildingInfo>())
if (!self.Info.HasTraitInfo<BuildingInfo>())
return;
if (e.Attacker == null)

View File

@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits
public void Damaged(Actor self, AttackInfo e)
{
// only track last hit against our harvesters
if (!self.Info.Traits.Contains<HarvesterInfo>())
if (!self.Info.HasTraitInfo<HarvesterInfo>())
return;
// 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 defenderStats = self.Owner.PlayerActor.Trait<PlayerStatistics>();
if (self.Info.Traits.Contains<BuildingInfo>())
if (self.Info.HasTraitInfo<BuildingInfo>())
{
attackerStats.BuildingsKilled++;
defenderStats.BuildingsDead++;
}
else if (self.Info.Traits.Contains<IPositionableInfo>())
else if (self.Info.HasTraitInfo<IPositionableInfo>())
{
attackerStats.UnitsKilled++;
defenderStats.UnitsDead++;
}
if (self.Info.Traits.Contains<ValuedInfo>())
if (self.Info.HasTraitInfo<ValuedInfo>())
{
var cost = self.Info.Traits.Get<ValuedInfo>().Cost;
attackerStats.KillsCost += cost;

View File

@@ -167,7 +167,7 @@ namespace OpenRA.Mods.Common.Traits
return self.World.Map.Rules.Actors.Values
.Where(x =>
x.Name[0] != '^' &&
x.Traits.Contains<BuildableInfo>() &&
x.HasTraitInfo<BuildableInfo>() &&
x.Traits.Get<BuildableInfo>().Queue.Contains(category));
}
@@ -254,7 +254,7 @@ namespace OpenRA.Mods.Common.Traits
if (!bi.Queue.Contains(Info.Type))
return; /* Not built by this queue */
var cost = unit.Traits.Contains<ValuedInfo>() ? unit.Traits.Get<ValuedInfo>().Cost : 0;
var cost = unit.HasTraitInfo<ValuedInfo>() ? unit.Traits.Get<ValuedInfo>().Cost : 0;
var time = GetBuildTime(order.TargetString);
if (BuildableItems().All(b => b.Name != order.TargetString))
@@ -278,7 +278,7 @@ namespace OpenRA.Mods.Common.Traits
var hasPlayedSound = false;
BeginProduction(new ProductionItem(this, order.TargetString, cost, playerPower, () => self.World.AddFrameEndTask(_ =>
{
var isBuilding = unit.Traits.Contains<BuildingInfo>();
var isBuilding = unit.HasTraitInfo<BuildingInfo>();
if (isBuilding && !hasPlayedSound)
hasPlayedSound = Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.ReadyAudio, self.Owner.Faction.InternalName);
@@ -314,7 +314,7 @@ namespace OpenRA.Mods.Common.Traits
public virtual int GetBuildTime(string unitString)
{
var unit = self.World.Map.Rules.Actors[unitString];
if (unit == null || !unit.Traits.Contains<BuildableInfo>())
if (unit == null || !unit.HasTraitInfo<BuildableInfo>())
return 0;
if (self.World.AllowDevCommands && self.Owner.PlayerActor.Trait<DeveloperMode>().FastBuild)

View File

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

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits
public Production(ActorInitializer init, ProductionInfo info)
{
Info = info;
occupiesSpace = init.Self.Info.Traits.Contains<IOccupySpaceInfo>();
occupiesSpace = init.Self.Info.HasTraitInfo<IOccupySpaceInfo>();
rp = Exts.Lazy(() => init.Self.IsDead ? null : init.Self.TraitOrDefault<RallyPoint>());
Faction = init.Contains<FactionInit>() ? init.Get<FactionInit, string>() : init.Self.Owner.Faction.InternalName;
}

View File

@@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Traits
public Hovers(HoversInfo info, Actor self)
{
this.info = info;
aircraft = self.Info.Traits.Contains<AircraftInfo>();
aircraft = self.Info.HasTraitInfo<AircraftInfo>();
}
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;
wsb = self.Trait<WithSpriteBody>();
buildComplete = !self.Info.Traits.Contains<BuildingInfo>();
buildComplete = !self.Info.HasTraitInfo<BuildingInfo>();
}
public void BuildingComplete(Actor self)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
{
domainIndexes = new Dictionary<uint, MovementClassDomainIndex>();
var movementClasses =
world.Map.Rules.Actors.Where(ai => ai.Value.Traits.Contains<MobileInfo>())
world.Map.Rules.Actors.Where(ai => ai.Value.HasTraitInfo<MobileInfo>())
.Select(ai => (uint)ai.Value.Traits.Get<MobileInfo>().GetMovementClass(world.TileSet)).Distinct();
foreach (var mc in movementClasses)