From 85fab4545141007032ae2419507714e4eec7ed2d Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Sat, 1 Aug 2015 23:53:58 -0500 Subject: [PATCH] Remove Actor.HasTrait() --- OpenRA.Game/Actor.cs | 5 -- OpenRA.Game/Graphics/WorldRenderer.cs | 4 +- OpenRA.Game/Orders/UnitOrderGenerator.cs | 6 +-- OpenRA.Game/TraitDictionary.cs | 6 --- OpenRA.Game/Traits/TraitsInterfaces.cs | 8 +-- .../WorldInteractionControllerWidget.cs | 4 +- OpenRA.Mods.Common/AI/AttackOrFleeFuzzy.cs | 14 ++--- OpenRA.Mods.Common/AI/HackyAI.cs | 52 ++++++++++--------- OpenRA.Mods.Common/AI/Squad.cs | 2 +- OpenRA.Mods.Common/AI/States/AirStates.cs | 4 +- OpenRA.Mods.Common/AI/States/GroundStates.cs | 2 +- OpenRA.Mods.Common/AI/States/StateBase.cs | 6 +-- .../Activities/Air/HeliAttack.cs | 2 +- OpenRA.Mods.Common/Activities/Attack.cs | 2 +- OpenRA.Mods.Common/Activities/Hunt.cs | 2 +- .../Activities/Move/MoveAdjacentTo.cs | 2 +- OpenRA.Mods.Common/Activities/Rearm.cs | 3 +- OpenRA.Mods.Common/ActorExts.cs | 6 +-- OpenRA.Mods.Common/Commands/DevCommands.cs | 2 +- OpenRA.Mods.Common/Effects/Bullet.cs | 2 +- OpenRA.Mods.Common/Effects/Missile.cs | 2 +- .../Orders/EnterAlliedActorTargeter.cs | 4 +- .../Scripting/Properties/CombatProperties.cs | 2 +- .../Scripting/Properties/GuardProperties.cs | 2 +- .../Scripting/Properties/PlayerProperties.cs | 2 +- OpenRA.Mods.Common/Traits/Air/Aircraft.cs | 10 ++-- .../Traits/Attack/AttackBase.cs | 2 +- .../Traits/Attack/AttackFollow.cs | 4 +- OpenRA.Mods.Common/Traits/AutoTarget.cs | 2 +- .../Traits/BlocksProjectiles.cs | 2 +- OpenRA.Mods.Common/Traits/BodyOrientation.cs | 2 +- OpenRA.Mods.Common/Traits/Buildings/Bridge.cs | 2 +- .../Traits/Buildings/Building.cs | 6 +-- .../Traits/Buildings/Refinery.cs | 2 +- OpenRA.Mods.Common/Traits/Crates/Crate.cs | 2 +- OpenRA.Mods.Common/Traits/EngineerRepair.cs | 4 +- OpenRA.Mods.Common/Traits/Guard.cs | 4 +- OpenRA.Mods.Common/Traits/Harvester.cs | 2 +- OpenRA.Mods.Common/Traits/KillsSelf.cs | 2 +- OpenRA.Mods.Common/Traits/Mobile.cs | 5 +- .../Traits/Modifiers/FrozenUnderFog.cs | 4 +- OpenRA.Mods.Common/Traits/Passenger.cs | 6 +-- .../Traits/Player/AllyRepair.cs | 2 +- .../Traits/Player/BaseAttackNotifier.cs | 2 +- .../Traits/Player/HarvesterAttackNotifier.cs | 4 +- .../Traits/Player/PlayerStatistics.cs | 6 +-- .../Traits/Player/ProvidesPrerequisite.cs | 2 +- .../Traits/Player/ProvidesTechPrerequisite.cs | 2 +- OpenRA.Mods.Common/Traits/Player/TechTree.cs | 2 +- OpenRA.Mods.Common/Traits/Render/Hovers.cs | 2 +- .../Render/WithBuildingPlacedAnimation.cs | 2 +- .../Render/WithBuildingPlacedOverlay.cs | 2 +- .../Traits/Render/WithDockingOverlay.cs | 2 +- .../Traits/Render/WithIdleOverlay.cs | 2 +- .../Traits/Render/WithRepairOverlay.cs | 2 +- .../Traits/Render/WithSpriteBody.cs | 2 +- OpenRA.Mods.Common/Traits/Repairable.cs | 2 +- OpenRA.Mods.Common/Traits/RepairableNear.cs | 2 +- .../Traits/Sound/AmbientSound.cs | 2 +- OpenRA.Mods.Common/Traits/SupplyTruck.cs | 2 +- .../SupportPowers/SupportPowerManager.cs | 4 +- OpenRA.Mods.Common/Traits/Targetable.cs | 2 +- OpenRA.Mods.Common/Traits/Tooltip.cs | 2 +- OpenRA.Mods.Common/Traits/Transforms.cs | 4 +- OpenRA.Mods.Common/TraitsInterfaces.cs | 3 ++ .../Logic/Ingame/ObserverStatsLogic.cs | 4 +- .../Widgets/ProductionTabsWidget.cs | 2 +- .../Widgets/ViewportControllerWidget.cs | 6 +-- .../Widgets/WorldCommandWidget.cs | 6 +-- OpenRA.Mods.D2k/Activities/SwallowActor.cs | 2 +- OpenRA.Mods.D2k/Traits/Carryable.cs | 2 +- .../Traits/Render/WithDeliveryOverlay.cs | 2 +- OpenRA.Mods.D2k/Traits/Sandworm.cs | 4 +- OpenRA.Mods.RA/Activities/Infiltrate.cs | 2 +- .../Traits/Buildings/ClonesProducedUnits.cs | 2 +- OpenRA.Mods.RA/Traits/Chronoshiftable.cs | 2 +- OpenRA.Mods.RA/Traits/Disguise.cs | 4 +- OpenRA.Mods.RA/Traits/Mine.cs | 2 +- .../Traits/SupportPowers/ChronoshiftPower.cs | 2 +- 79 files changed, 153 insertions(+), 153 deletions(-) diff --git a/OpenRA.Game/Actor.cs b/OpenRA.Game/Actor.cs index e9e3c9d304..d2b82a414e 100644 --- a/OpenRA.Game/Actor.cs +++ b/OpenRA.Game/Actor.cs @@ -226,11 +226,6 @@ namespace OpenRA return World.TraitDict.WithInterface(this); } - public bool HasTrait() - { - return World.TraitDict.Contains(this); - } - public void AddTrait(object trait) { World.TraitDict.AddTrait(this, trait); diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index e274de0557..9fd39bf910 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -181,7 +181,7 @@ namespace OpenRA.Graphics if (World.Type == WorldType.Regular && Game.Settings.Game.AlwaysShowStatusBars) { foreach (var g in World.Actors.Where(a => !a.Disposed - && a.HasTrait() + && a.Info.Traits.Contains() && !World.FogObscures(a) && !World.Selection.Actors.Contains(a))) @@ -193,7 +193,7 @@ namespace OpenRA.Graphics public void DrawRollover(Actor unit) { - if (unit.HasTrait()) + if (unit.Info.Traits.Contains()) new SelectionBarsRenderable(unit).Render(this); } diff --git a/OpenRA.Game/Orders/UnitOrderGenerator.cs b/OpenRA.Game/Orders/UnitOrderGenerator.cs index 83f0e85f4a..ea583a437c 100644 --- a/OpenRA.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Game/Orders/UnitOrderGenerator.cs @@ -20,7 +20,7 @@ namespace OpenRA.Orders public IEnumerable Order(World world, CPos xy, MouseInput mi) { var underCursor = world.ScreenMap.ActorsAt(mi) - .Where(a => !world.FogObscures(a) && a.HasTrait()) + .Where(a => !world.FogObscures(a) && a.Info.Traits.Contains()) .WithHighestSelectionPriority(); Target target; @@ -58,12 +58,12 @@ namespace OpenRA.Orders { var useSelect = false; var underCursor = world.ScreenMap.ActorsAt(mi) - .Where(a => !world.FogObscures(a) && a.HasTrait()) + .Where(a => !world.FogObscures(a) && a.Info.Traits.Contains()) .WithHighestSelectionPriority(); if (underCursor != null && (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any())) { - if (underCursor.HasTrait()) + if (underCursor.Info.Traits.Contains()) useSelect = true; } diff --git a/OpenRA.Game/TraitDictionary.cs b/OpenRA.Game/TraitDictionary.cs index a60bce30a9..3d6a9dbe30 100644 --- a/OpenRA.Game/TraitDictionary.cs +++ b/OpenRA.Game/TraitDictionary.cs @@ -84,12 +84,6 @@ namespace OpenRA throw new InvalidOperationException("Attempted to get trait from destroyed object ({0})".F(actor)); } - public bool Contains(Actor actor) - { - CheckDestroyed(actor); - return InnerGet().GetMultiple(actor.ActorID).Any(); - } - public T Get(Actor actor) { CheckDestroyed(actor); diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 2ee5cfb76c..82c22d2964 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -144,13 +144,13 @@ namespace OpenRA.Traits Player Owner { get; } } - public interface IToolTip + public interface ITooltip { ITooltipInfo TooltipInfo { get; } Player Owner { get; } } - public interface ITooltipInfo + public interface ITooltipInfo : ITraitInfo { string TooltipForPlayerStance(Stance stance); bool IsOwnerRowVisible { get; } @@ -226,6 +226,7 @@ namespace OpenRA.Traits public interface ITags { IEnumerable GetTags(); } public interface ISelectionBar { float GetValue(); Color GetColor(); } + public interface IPositionableInfo : ITraitInfo { } public interface IPositionable : IOccupySpace { bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any); @@ -296,6 +297,7 @@ namespace OpenRA.Traits public interface INotifyBecomingIdle { void OnBecomingIdle(Actor self); } public interface INotifyIdle { void TickIdle(Actor self); } + public interface IBlocksProjectilesInfo : ITraitInfo { } public interface IBlocksProjectiles { } public interface IRenderInfantrySequenceModifier { @@ -309,7 +311,7 @@ namespace OpenRA.Traits public interface IPostRenderSelection { IEnumerable RenderAfterWorld(WorldRenderer wr); } - public interface ITargetableInfo + public interface ITargetableInfo : ITraitInfo { HashSet GetTargetTypes(); } diff --git a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs index 3c35edf28d..c9188b3fe5 100644 --- a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs +++ b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs @@ -89,7 +89,7 @@ namespace OpenRA.Widgets { if (!hasBox && World.Selection.Actors.Any() && !multiClick) { - if (!(World.ScreenMap.ActorsAt(xy).Where(x => x.HasTrait() && + if (!(World.ScreenMap.ActorsAt(xy).Where(x => x.Info.Traits.Contains() && (x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x))).Any() && !mi.Modifiers.HasModifier(Modifiers.Ctrl) && !mi.Modifiers.HasModifier(Modifiers.Alt) && UnitOrderGenerator.InputOverridesSelection(World, xy, mi))) { @@ -301,7 +301,7 @@ namespace OpenRA.Widgets a = b; return world.ScreenMap.ActorsInBox(a, b) - .Where(x => x.HasTrait() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x))) + .Where(x => x.Info.Traits.Contains() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x))) .SubsetWithHighestSelectionPriority(); } diff --git a/OpenRA.Mods.Common/AI/AttackOrFleeFuzzy.cs b/OpenRA.Mods.Common/AI/AttackOrFleeFuzzy.cs index 8ba55a2971..7fb05dd331 100644 --- a/OpenRA.Mods.Common/AI/AttackOrFleeFuzzy.cs +++ b/OpenRA.Mods.Common/AI/AttackOrFleeFuzzy.cs @@ -176,7 +176,7 @@ namespace OpenRA.Mods.Common.AI var sumOfHp = 0; foreach (var a in actors) { - if (a.HasTrait()) + if (a.Info.Traits.Contains()) { sumOfMaxHp += a.Trait().MaxHP; sumOfHp += a.Trait().HP; @@ -191,7 +191,7 @@ namespace OpenRA.Mods.Common.AI protected float RelativePower(IEnumerable own, IEnumerable enemy) { - return RelativeValue(own, enemy, 100, SumOfValues, a => + return RelativeValue(own, enemy, 100, SumOfValues, a => { var sumOfDamage = 0; var arms = a.TraitsImplementing(); @@ -208,7 +208,7 @@ namespace OpenRA.Mods.Common.AI protected float RelativeSpeed(IEnumerable own, IEnumerable enemy) { - return RelativeValue(own, enemy, 100, Average, (Actor a) => a.Trait().Info.Speed); + return RelativeValue(own, enemy, 100, Average, (Actor a) => a.Trait().Info.Speed); } protected static float RelativeValue(IEnumerable own, IEnumerable enemy, float normalizeByValue, @@ -224,23 +224,23 @@ namespace OpenRA.Mods.Common.AI return relative.Clamp(0.0f, 999.0f); } - protected float SumOfValues(IEnumerable actors, Func getValue) + protected float SumOfValues(IEnumerable actors, Func getValue) where TTraitInfo : ITraitInfo { var sum = 0; foreach (var a in actors) - if (a.HasTrait()) + if (a.Info.Traits.Contains()) sum += getValue(a); return sum; } - protected float Average(IEnumerable actors, Func getValue) + protected float Average(IEnumerable actors, Func getValue) where TTraitInfo : ITraitInfo { var sum = 0; var countActors = 0; foreach (var a in actors) { - if (a.HasTrait()) + if (a.Info.Traits.Contains()) { sum += getValue(a); countActors++; diff --git a/OpenRA.Mods.Common/AI/HackyAI.cs b/OpenRA.Mods.Common/AI/HackyAI.cs index ca15330896..b0f6fd748e 100644 --- a/OpenRA.Mods.Common/AI/HackyAI.cs +++ b/OpenRA.Mods.Common/AI/HackyAI.cs @@ -167,8 +167,8 @@ namespace OpenRA.Mods.Common.AI { var randomBaseBuilding = World.Actors.Where( a => a.Owner == Player - && a.HasTrait() - && !a.HasTrait()) + && a.Info.Traits.Contains() + && !a.Info.Traits.Contains()) .RandomOrDefault(Random); return randomBaseBuilding != null ? randomBaseBuilding.Location : initialBaseCenter; @@ -232,7 +232,9 @@ namespace OpenRA.Mods.Common.AI pathfinder = World.WorldActor.Trait(); isEnemyUnit = unit => - Player.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait() && unit.HasTrait(); + Player.Stances[unit.Owner] == Stance.Enemy + && !unit.Info.Traits.Contains() + && unit.Info.Traits.Contains(); foreach (var decision in info.PowerDecisions) powerDecisions.Add(decision.OrderName, decision); @@ -279,8 +281,8 @@ namespace OpenRA.Mods.Common.AI { var baseProviders = World.Actors.Where( a => a.Owner == Player - && a.HasTrait() - && !a.HasTrait()); + && a.Info.Traits.Contains() + && !a.Info.Traits.Contains()); foreach (var b in baseProviders) { @@ -306,8 +308,8 @@ namespace OpenRA.Mods.Common.AI { var areaProviders = World.Actors.Where( a => a.Owner == Player - && a.HasTrait() - && !a.HasTrait()); + && a.Info.Traits.Contains() + && !a.Info.Traits.Contains()); foreach (var a in areaProviders) { @@ -487,7 +489,7 @@ namespace OpenRA.Mods.Common.AI case BuildingType.Defense: // Build near the closest enemy structure - var closestEnemy = World.Actors.Where(a => !a.Disposed && a.HasTrait() && Player.Stances[a.Owner] == Stance.Enemy) + var closestEnemy = World.Actors.Where(a => !a.Disposed && a.Info.Traits.Contains() && Player.Stances[a.Owner] == Stance.Enemy) .ClosestTo(World.Map.CenterOfCell(defenseCenter)); var targetCell = closestEnemy != null ? closestEnemy.Location : baseCenter; @@ -563,7 +565,7 @@ namespace OpenRA.Mods.Common.AI // Pick something worth attacking owned by that player var target = World.Actors - .Where(a => a.Owner == enemy && a.HasTrait()) + .Where(a => a.Owner == enemy && a.Info.Traits.Contains()) .ClosestTo(World.Map.CenterOfCell(GetRandomBaseCenter())); if (target == null) @@ -595,7 +597,7 @@ namespace OpenRA.Mods.Common.AI List FindEnemyConstructionYards() { return World.Actors.Where(a => Player.Stances[a.Owner] == Stance.Enemy && !a.IsDead - && a.HasTrait() && !a.HasTrait()).ToList(); + && a.Info.Traits.Contains() && !a.Info.Traits.Contains()).ToList(); } void CleanSquads() @@ -705,18 +707,18 @@ namespace OpenRA.Mods.Common.AI void FindNewUnits(Actor self) { var newUnits = self.World.ActorsWithTrait() - .Where(a => a.Actor.Owner == Player && !a.Actor.HasTrait() + .Where(a => a.Actor.Owner == Player && !a.Actor.Info.Traits.Contains() && !activeUnits.Contains(a.Actor)) .Select(a => a.Actor); foreach (var a in newUnits) { - if (a.HasTrait()) + if (a.Info.Traits.Contains()) QueueOrder(new Order("Harvest", a, false)); else unitsHangingAroundTheBase.Add(a); - if (a.HasTrait() && a.HasTrait()) + if (a.Info.Traits.Contains() && a.Info.Traits.Contains()) { var air = GetSquadOfType(SquadType.Air); if (air == null) @@ -740,7 +742,7 @@ namespace OpenRA.Mods.Common.AI var attackForce = RegisterNewSquad(SquadType.Assault); foreach (var a in unitsHangingAroundTheBase) - if (!a.HasTrait()) + if (!a.Info.Traits.Contains()) attackForce.Units.Add(a); unitsHangingAroundTheBase.Clear(); @@ -751,7 +753,7 @@ namespace OpenRA.Mods.Common.AI { var allEnemyBaseBuilder = FindEnemyConstructionYards(); var ownUnits = activeUnits - .Where(unit => unit.HasTrait() && !unit.HasTrait() && unit.IsIdle).ToList(); + .Where(unit => unit.Info.Traits.Contains() && !unit.Info.Traits.Contains() && unit.IsIdle).ToList(); if (!allEnemyBaseBuilder.Any() || (ownUnits.Count < Info.SquadSize)) return; @@ -759,7 +761,7 @@ namespace OpenRA.Mods.Common.AI foreach (var b in allEnemyBaseBuilder) { var enemies = World.FindActorsInCircle(b.CenterPosition, WDist.FromCells(Info.RushAttackScanRadius)) - .Where(unit => Player.Stances[unit.Owner] == Stance.Enemy && unit.HasTrait()).ToList(); + .Where(unit => Player.Stances[unit.Owner] == Stance.Enemy && unit.Info.Traits.Contains()).ToList(); if (rushFuzzy.CanAttack(ownUnits, enemies)) { @@ -788,8 +790,8 @@ namespace OpenRA.Mods.Common.AI if (!protectSq.IsValid) { var ownUnits = World.FindActorsInCircle(World.Map.CenterOfCell(GetRandomBaseCenter()), WDist.FromCells(Info.ProtectUnitScanRadius)) - .Where(unit => unit.Owner == Player && !unit.HasTrait() - && unit.HasTrait()); + .Where(unit => unit.Owner == Player && !unit.Info.Traits.Contains() + && unit.Info.Traits.Contains()); foreach (var a in ownUnits) protectSq.Units.Add(a); @@ -830,7 +832,7 @@ namespace OpenRA.Mods.Common.AI { // Find and deploy our mcv var mcv = self.World.Actors - .FirstOrDefault(a => a.Owner == Player && a.HasTrait()); + .FirstOrDefault(a => a.Owner == Player && a.Info.Traits.Contains()); if (mcv != null) { @@ -839,7 +841,7 @@ namespace OpenRA.Mods.Common.AI // Don't transform the mcv if it is a fact // HACK: This needs to query against MCVs directly - if (mcv.HasTrait()) + if (mcv.Info.Traits.Contains()) QueueOrder(new Order("DeployTransform", mcv, false)); } else @@ -851,7 +853,8 @@ namespace OpenRA.Mods.Common.AI void FindAndDeployBackupMcv(Actor self) { // HACK: This needs to query against MCVs directly - var mcvs = self.World.Actors.Where(a => a.Owner == Player && a.HasTrait() && a.HasTrait()); + var mcvs = self.World.Actors + .Where(a => a.Owner == Player && a.Info.Traits.Contains() && a.Info.Traits.Contains()); if (!mcvs.Any()) return; @@ -1010,7 +1013,8 @@ namespace OpenRA.Mods.Common.AI return; // No construction yards - Build a new MCV - if (!HasAdequateFact() && !self.World.Actors.Any(a => a.Owner == Player && a.HasTrait() && a.HasTrait())) + if (!HasAdequateFact() && !self.World.Actors.Any(a => + a.Owner == Player && a.Info.Traits.Contains() && a.Info.Traits.Contains())) BuildUnit("Vehicle", GetUnitInfoByCommonName("Mcv", Player).Name); foreach (var q in Info.UnitQueues) @@ -1069,14 +1073,14 @@ namespace OpenRA.Mods.Common.AI if (e.Attacker.Disposed) return; - if (!e.Attacker.HasTrait()) + if (!e.Attacker.Info.Traits.Contains()) return; if (e.Damage > 0) aggro[e.Attacker.Owner].Aggro += e.Damage; // Protected harvesters or building - if ((self.HasTrait() || self.HasTrait()) && + if ((self.Info.Traits.Contains() || self.Info.Traits.Contains()) && Player.Stances[e.Attacker.Owner] == Stance.Enemy) { defenseCenter = e.Attacker.Location; diff --git a/OpenRA.Mods.Common/AI/Squad.cs b/OpenRA.Mods.Common/AI/Squad.cs index fb1a460bbd..c21b41a7e5 100644 --- a/OpenRA.Mods.Common/AI/Squad.cs +++ b/OpenRA.Mods.Common/AI/Squad.cs @@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.AI public bool IsTargetValid { - get { return Target.IsValidFor(Units.FirstOrDefault()) && !Target.Actor.HasTrait(); } + get { return Target.IsValidFor(Units.FirstOrDefault()) && !Target.Actor.Info.Traits.Contains(); } } public bool IsTargetVisible diff --git a/OpenRA.Mods.Common/AI/States/AirStates.cs b/OpenRA.Mods.Common/AI/States/AirStates.cs index 9cb08991bc..eed023eb9f 100644 --- a/OpenRA.Mods.Common/AI/States/AirStates.cs +++ b/OpenRA.Mods.Common/AI/States/AirStates.cs @@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.AI var missileUnitsCount = 0; foreach (var unit in units) { - if (unit != null && unit.HasTrait() && !unit.HasTrait() + if (unit != null && unit.Info.Traits.Contains() && !unit.Info.Traits.Contains() && !unit.IsDisabled()) { var arms = unit.TraitsImplementing(); @@ -223,7 +223,7 @@ namespace OpenRA.Mods.Common.AI continue; } - if (owner.TargetActor.HasTrait() && CanAttackTarget(a, owner.TargetActor)) + if (owner.TargetActor.Info.Traits.Contains() && CanAttackTarget(a, owner.TargetActor)) owner.Bot.QueueOrder(new Order("Attack", a, false) { TargetActor = owner.TargetActor }); } } diff --git a/OpenRA.Mods.Common/AI/States/GroundStates.cs b/OpenRA.Mods.Common/AI/States/GroundStates.cs index fdb022a56f..87115e3ae6 100644 --- a/OpenRA.Mods.Common/AI/States/GroundStates.cs +++ b/OpenRA.Mods.Common/AI/States/GroundStates.cs @@ -95,7 +95,7 @@ namespace OpenRA.Mods.Common.AI { var enemies = owner.World.FindActorsInCircle(leader.CenterPosition, WDist.FromCells(12)) .Where(a1 => !a1.Disposed && !a1.IsDead); - var enemynearby = enemies.Where(a1 => a1.HasTrait() && leader.Owner.Stances[a1.Owner] == Stance.Enemy); + var enemynearby = enemies.Where(a1 => a1.Info.Traits.Contains() && leader.Owner.Stances[a1.Owner] == Stance.Enemy); var target = enemynearby.ClosestTo(leader.CenterPosition); if (target != null) { diff --git a/OpenRA.Mods.Common/AI/States/StateBase.cs b/OpenRA.Mods.Common/AI/States/StateBase.cs index fd255dbec5..81bc6ff132 100644 --- a/OpenRA.Mods.Common/AI/States/StateBase.cs +++ b/OpenRA.Mods.Common/AI/States/StateBase.cs @@ -60,7 +60,7 @@ namespace OpenRA.Mods.Common.AI protected static bool CanAttackTarget(Actor a, Actor target) { - if (!a.HasTrait()) + if (!a.Info.Traits.Contains()) return false; var targetTypes = target.TraitsImplementing().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes); @@ -82,11 +82,11 @@ namespace OpenRA.Mods.Common.AI var u = squad.Units.Random(squad.Random); var units = squad.World.FindActorsInCircle(u.CenterPosition, WDist.FromCells(DangerRadius)).ToList(); - var ownBaseBuildingAround = units.Where(unit => unit.Owner == squad.Bot.Player && unit.HasTrait()); + var ownBaseBuildingAround = units.Where(unit => unit.Owner == squad.Bot.Player && unit.Info.Traits.Contains()); if (ownBaseBuildingAround.Any()) return false; - var enemyAroundUnit = units.Where(unit => squad.Bot.Player.Stances[unit.Owner] == Stance.Enemy && unit.HasTrait()); + var enemyAroundUnit = units.Where(unit => squad.Bot.Player.Stances[unit.Owner] == Stance.Enemy && unit.Info.Traits.Contains()); if (!enemyAroundUnit.Any()) return false; diff --git a/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs b/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs index cf54845c5f..7840172f48 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliAttack.cs @@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Activities { target = value; if (target.Type == TargetType.Actor) - canHideUnderFog = target.Actor.HasTrait(); + canHideUnderFog = target.Actor.Info.Traits.Contains(); } } diff --git a/OpenRA.Mods.Common/Activities/Attack.cs b/OpenRA.Mods.Common/Activities/Attack.cs index cfad985837..a940ff235d 100644 --- a/OpenRA.Mods.Common/Activities/Attack.cs +++ b/OpenRA.Mods.Common/Activities/Attack.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Activities // HACK: This would otherwise break targeting frozen actors // 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. - if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.HasTrait() && !self.Owner.CanTargetActor(Target.Actor)) + if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.Info.Traits.Contains() && !self.Owner.CanTargetActor(Target.Actor)) return NextActivity; // Try to move within range diff --git a/OpenRA.Mods.Common/Activities/Hunt.cs b/OpenRA.Mods.Common/Activities/Hunt.cs index 55ff87989d..7bb9225e7a 100644 --- a/OpenRA.Mods.Common/Activities/Hunt.cs +++ b/OpenRA.Mods.Common/Activities/Hunt.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.Common.Activities { var attack = self.Trait(); targets = self.World.Actors.Where(a => self != a && !a.IsDead && a.IsInWorld && a.AppearsHostileTo(self) - && a.HasTrait() && IsTargetable(a, self) && attack.HasAnyValidWeapons(Target.FromActor(a))); + && a.Info.Traits.Contains() && IsTargetable(a, self) && attack.HasAnyValidWeapons(Target.FromActor(a))); } bool IsTargetable(Actor self, Actor viewer) diff --git a/OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs b/OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs index 90e9b519eb..255807ca26 100644 --- a/OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs +++ b/OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Activities { target = value; if (target.Type == TargetType.Actor) - canHideUnderFog = target.Actor.HasTrait(); + canHideUnderFog = target.Actor.Info.Traits.Contains(); } } diff --git a/OpenRA.Mods.Common/Activities/Rearm.cs b/OpenRA.Mods.Common/Activities/Rearm.cs index 99ad7c8480..5fa3824933 100644 --- a/OpenRA.Mods.Common/Activities/Rearm.cs +++ b/OpenRA.Mods.Common/Activities/Rearm.cs @@ -48,7 +48,8 @@ namespace OpenRA.Mods.Common.Activities continue; // HACK to check if we are on the helipad/airfield/etc. - var hostBuilding = self.World.ActorMap.GetUnitsAt(self.Location).FirstOrDefault(a => a.HasTrait()); + var hostBuilding = self.World.ActorMap.GetUnitsAt(self.Location) + .FirstOrDefault(a => a.Info.Traits.Contains()); if (hostBuilding == null || !hostBuilding.IsInWorld) return NextActivity; diff --git a/OpenRA.Mods.Common/ActorExts.cs b/OpenRA.Mods.Common/ActorExts.cs index 2e95bc5f5f..4c58c25e19 100644 --- a/OpenRA.Mods.Common/ActorExts.cs +++ b/OpenRA.Mods.Common/ActorExts.cs @@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common if (self.IsDead) return false; - if (!self.HasTrait()) + if (!self.Info.Traits.Contains()) return false; if (!self.IsInWorld) @@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common if (stance == Stance.Ally) return true; - if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.HasTrait()) + if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.Info.Traits.Contains()) return toActor.Owner.Stances[self.EffectiveOwner.Owner] == Stance.Ally; return stance == Stance.Ally; @@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common if (stance == Stance.Ally) return false; /* otherwise, we'll hate friendly disguised spies */ - if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.HasTrait()) + if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.Info.Traits.Contains()) return toActor.Owner.Stances[self.EffectiveOwner.Owner] == Stance.Enemy; return stance == Stance.Enemy; diff --git a/OpenRA.Mods.Common/Commands/DevCommands.cs b/OpenRA.Mods.Common/Commands/DevCommands.cs index 549b1b32b7..ec71d825ee 100644 --- a/OpenRA.Mods.Common/Commands/DevCommands.cs +++ b/OpenRA.Mods.Common/Commands/DevCommands.cs @@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Commands var leveluporder = new Order("DevLevelUp", actor, false); leveluporder.ExtraData = (uint)level; - if (actor.HasTrait()) + if (actor.Info.Traits.Contains()) world.IssueOrder(leveluporder); } diff --git a/OpenRA.Mods.Common/Effects/Bullet.cs b/OpenRA.Mods.Common/Effects/Bullet.cs index 0b04322fa3..7df4ce6e68 100644 --- a/OpenRA.Mods.Common/Effects/Bullet.cs +++ b/OpenRA.Mods.Common/Effects/Bullet.cs @@ -165,7 +165,7 @@ namespace OpenRA.Mods.Common.Effects contrail.Update(pos); if (ticks++ >= length || (info.Blockable && world.ActorMap - .GetUnitsAt(world.Map.CellContaining(pos)).Any(a => a.HasTrait()))) + .GetUnitsAt(world.Map.CellContaining(pos)).Any(a => a.Info.Traits.Contains()))) Explode(world); } diff --git a/OpenRA.Mods.Common/Effects/Missile.cs b/OpenRA.Mods.Common/Effects/Missile.cs index 456201b9ac..7e8a3c7f8b 100644 --- a/OpenRA.Mods.Common/Effects/Missile.cs +++ b/OpenRA.Mods.Common/Effects/Missile.cs @@ -201,7 +201,7 @@ namespace OpenRA.Mods.Common.Effects var shouldExplode = (pos.Z < 0) // Hit the ground || (dist.LengthSquared < info.CloseEnough.LengthSquared) // Within range || (info.RangeLimit != 0 && ticks > info.RangeLimit) // Ran out of fuel - || (info.Blockable && world.ActorMap.GetUnitsAt(cell).Any(a => a.HasTrait())) // Hit a wall or other blocking obstacle + || (info.Blockable && world.ActorMap.GetUnitsAt(cell).Any(a => a.Info.Traits.Contains())) // Hit a wall or other blocking obstacle || !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 diff --git a/OpenRA.Mods.Common/Orders/EnterAlliedActorTargeter.cs b/OpenRA.Mods.Common/Orders/EnterAlliedActorTargeter.cs index 82cb8cc93a..390e767b87 100644 --- a/OpenRA.Mods.Common/Orders/EnterAlliedActorTargeter.cs +++ b/OpenRA.Mods.Common/Orders/EnterAlliedActorTargeter.cs @@ -13,7 +13,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Orders { - public class EnterAlliedActorTargeter : UnitOrderTargeter + public class EnterAlliedActorTargeter : UnitOrderTargeter where T : ITraitInfo { readonly Func canTarget; readonly Func useEnterCursor; @@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Orders public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!target.HasTrait() || !canTarget(target)) + if (!target.Info.Traits.Contains() || !canTarget(target)) return false; cursor = useEnterCursor(target) ? "enter" : "enter-blocked"; diff --git a/OpenRA.Mods.Common/Scripting/Properties/CombatProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/CombatProperties.cs index 4177cc6107..863ddfdc15 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/CombatProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/CombatProperties.cs @@ -83,7 +83,7 @@ namespace OpenRA.Mods.Common.Scripting if (!target.IsValidFor(Self) || target.Type == TargetType.FrozenActor) Log.Write("lua", "{1} is an invalid target for {0}!", Self, targetActor); - if (!targetActor.HasTrait() && !Self.Owner.CanTargetActor(targetActor)) + if (!targetActor.Info.Traits.Contains() && !Self.Owner.CanTargetActor(targetActor)) Log.Write("lua", "{1} is not revealed for player {0}!", Self.Owner, targetActor); attackBase.AttackTarget(target, true, allowMove); diff --git a/OpenRA.Mods.Common/Scripting/Properties/GuardProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/GuardProperties.cs index ecadcc632b..5e1b59b8f7 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/GuardProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/GuardProperties.cs @@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Scripting [Desc("Guard the target actor.")] public void Guard(Actor targetActor) { - if (targetActor.HasTrait()) + if (targetActor.Info.Traits.Contains()) guard.GuardTarget(Self, Target.FromActor(targetActor)); } } diff --git a/OpenRA.Mods.Common/Scripting/Properties/PlayerProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/PlayerProperties.cs index 4d2638fe0e..2ac2b0a54f 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/PlayerProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/PlayerProperties.cs @@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Scripting public Actor[] GetGroundAttackers() { return Player.World.ActorsWithTrait().Select(a => a.Actor) - .Where(a => a.Owner == Player && !a.IsDead && a.IsInWorld && a.HasTrait()) + .Where(a => a.Owner == Player && !a.IsDead && a.IsInWorld && a.Info.Traits.Contains()) .ToArray(); } diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index c9bfd67942..ca9907ef63 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -19,7 +19,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public class AircraftInfo : ITraitInfo, IFacingInfo, IOccupySpaceInfo, ICruiseAltitudeInfo, UsesInit, UsesInit + public class AircraftInfo : IPositionableInfo, IFacingInfo, IOccupySpaceInfo, ICruiseAltitudeInfo, UsesInit, UsesInit { public readonly WDist CruiseAltitude = new WDist(1280); public readonly WDist IdealSeparation = new WDist(1706); @@ -120,7 +120,7 @@ namespace OpenRA.Mods.Common.Traits firstTick = false; // TODO: Aircraft husks don't properly unreserve. - if (self.HasTrait()) + if (self.Info.Traits.Contains()) 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.HasTrait() && a.Info.Traits.Get().CruiseAltitude == info.CruiseAltitude) + .Where(a => !a.IsDead && a.Info.Traits.Contains() && a.Info.Traits.Get().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.HasTrait()); + .FirstOrDefault(a => a.Info.Traits.Contains()); } protected void ReserveSpawnBuilding() @@ -341,7 +341,7 @@ namespace OpenRA.Mods.Common.Traits { get { - yield return new EnterAlliedActorTargeter("Enter", 5, + yield return new EnterAlliedActorTargeter("Enter", 5, target => AircraftCanEnter(target), target => !Reservable.IsReserved(target)); yield return new AircraftMoveOrderTargeter(info); diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs index 35f9933bf9..78cf948d86 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackBase.cs @@ -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.HasTrait())); + && (target.IsInRange(self.CenterPosition, GetMaximumRange()) || (allowMove && self.Info.Traits.Contains())); } class AttackOrderTargeter : IOrderTargeter diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs index f3ecf7af04..38c44274b1 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs +++ b/OpenRA.Mods.Common/Traits/Attack/AttackFollow.cs @@ -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.HasTrait()) - || (target.Type == TargetType.FrozenActor && target.FrozenActor.Info.Traits.Contains()); + var targetIsMobile = (target.Type == TargetType.Actor && target.Actor.Info.Traits.Contains()) + || (target.Type == TargetType.FrozenActor && target.FrozenActor.Info.Traits.Contains()); // 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)) diff --git a/OpenRA.Mods.Common/Traits/AutoTarget.cs b/OpenRA.Mods.Common/Traits/AutoTarget.cs index a256358d89..be1d678022 100644 --- a/OpenRA.Mods.Common/Traits/AutoTarget.cs +++ b/OpenRA.Mods.Common/Traits/AutoTarget.cs @@ -154,7 +154,7 @@ namespace OpenRA.Mods.Common.Traits return inRange .Where(a => a.AppearsHostileTo(self) && - !a.HasTrait() && + !a.Info.Traits.Contains() && attack.HasAnyValidWeapons(Target.FromActor(a)) && self.Owner.CanTargetActor(a)) .ClosestTo(self); diff --git a/OpenRA.Mods.Common/Traits/BlocksProjectiles.cs b/OpenRA.Mods.Common/Traits/BlocksProjectiles.cs index e93add1764..c41398abd6 100644 --- a/OpenRA.Mods.Common/Traits/BlocksProjectiles.cs +++ b/OpenRA.Mods.Common/Traits/BlocksProjectiles.cs @@ -15,6 +15,6 @@ namespace OpenRA.Mods.Common.Traits { // TODO: Add functionality like a customizable Height that is compared to projectile altitude [Desc("This actor blocks bullets and missiles with 'Blockable' property.")] - public class BlocksProjectilesInfo : TraitInfo { } + public class BlocksProjectilesInfo : TraitInfo, IBlocksProjectilesInfo { } public class BlocksProjectiles : IBlocksProjectiles { } } diff --git a/OpenRA.Mods.Common/Traits/BodyOrientation.cs b/OpenRA.Mods.Common/Traits/BodyOrientation.cs index 8d65700106..f25452a31d 100644 --- a/OpenRA.Mods.Common/Traits/BodyOrientation.cs +++ b/OpenRA.Mods.Common/Traits/BodyOrientation.cs @@ -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.HasTrait()) + if (self.Info.Traits.Contains()) 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 diff --git a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs index eade73b54c..b4bb963654 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs @@ -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.HasTrait() && !a.Trait().CanEnterCell(c)) + if (a.Info.Traits.Contains() && !a.Trait().CanEnterCell(c)) a.Kill(self); } diff --git a/OpenRA.Mods.Common/Traits/Buildings/Building.cs b/OpenRA.Mods.Common/Traits/Buildings/Building.cs index cefcc8686c..d7ac7860b2 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Building.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Building.cs @@ -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.HasTrait()); + && a.Info.Traits.Contains()); if (unitsAtPos.Any()) nearnessCandidates.Add(pos); } - else if (buildingAtPos.IsInWorld && buildingAtPos.HasTrait() + else if (buildingAtPos.IsInWorld && buildingAtPos.Info.Traits.Contains() && (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.HasTrait()) + if (SkipMakeAnimation || !self.Info.Traits.Contains()) NotifyBuildingComplete(self); } diff --git a/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs b/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs index 6312b6395f..8f68e05901 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Refinery.cs @@ -18,7 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public class RefineryInfo : ITraitInfo, Requires + public class RefineryInfo : IAcceptResourcesInfo, Requires { [Desc("Actual harvester facing when docking, 0-255 counter-clock-wise.")] public readonly int DockAngle = 0; diff --git a/OpenRA.Mods.Common/Traits/Crates/Crate.cs b/OpenRA.Mods.Common/Traits/Crates/Crate.cs index 813c48bb88..f21cb545b5 100644 --- a/OpenRA.Mods.Common/Traits/Crates/Crate.cs +++ b/OpenRA.Mods.Common/Traits/Crates/Crate.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - class CrateInfo : ITraitInfo, IOccupySpaceInfo, Requires + class CrateInfo : IPositionableInfo, IOccupySpaceInfo, Requires { [Desc("Length of time (in seconds) until the crate gets removed automatically. " + "A value of zero disables auto-removal.")] diff --git a/OpenRA.Mods.Common/Traits/EngineerRepair.cs b/OpenRA.Mods.Common/Traits/EngineerRepair.cs index ea4cff0c51..cee2c2a530 100644 --- a/OpenRA.Mods.Common/Traits/EngineerRepair.cs +++ b/OpenRA.Mods.Common/Traits/EngineerRepair.cs @@ -101,7 +101,7 @@ namespace OpenRA.Mods.Common.Traits public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - if (!target.HasTrait()) + if (!target.Info.Traits.Contains()) 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()) + if (!target.Info.Traits.Contains()) return false; if (self.Owner.Stances[target.Owner] != Stance.Ally) diff --git a/OpenRA.Mods.Common/Traits/Guard.cs b/OpenRA.Mods.Common/Traits/Guard.cs index 61a41bfb2d..bbbbd081a6 100644 --- a/OpenRA.Mods.Common/Traits/Guard.cs +++ b/OpenRA.Mods.Common/Traits/Guard.cs @@ -88,7 +88,7 @@ namespace OpenRA.Mods.Common.Traits public void Tick(World world) { - if (subjects.All(s => s.IsDead || !s.HasTrait())) + if (subjects.All(s => s.IsDead || !s.Info.Traits.Contains())) 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.HasTrait()); + a.Info.Traits.Contains()); } } } diff --git a/OpenRA.Mods.Common/Traits/Harvester.cs b/OpenRA.Mods.Common/Traits/Harvester.cs index db203b71a6..dbb356706f 100644 --- a/OpenRA.Mods.Common/Traits/Harvester.cs +++ b/OpenRA.Mods.Common/Traits/Harvester.cs @@ -297,7 +297,7 @@ namespace OpenRA.Mods.Common.Traits { get { - yield return new EnterAlliedActorTargeter("Deliver", 5, + yield return new EnterAlliedActorTargeter("Deliver", 5, proc => IsAcceptableProcType(proc), proc => !IsEmpty && proc.Trait().AllowDocking); yield return new HarvestOrderTargeter(); diff --git a/OpenRA.Mods.Common/Traits/KillsSelf.cs b/OpenRA.Mods.Common/Traits/KillsSelf.cs index 48ccc153ba..9265ac1162 100644 --- a/OpenRA.Mods.Common/Traits/KillsSelf.cs +++ b/OpenRA.Mods.Common/Traits/KillsSelf.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Traits if (self.IsDead) return; - if (Info.RemoveInstead || !self.HasTrait()) + if (Info.RemoveInstead || !self.Info.Traits.Contains()) self.Dispose(); else self.Kill(self); diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 71ea825cd7..8b432701df 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -38,7 +38,8 @@ namespace OpenRA.Mods.Common.Traits } [Desc("Unit is able to move.")] - public class MobileInfo : IMoveInfo, IOccupySpaceInfo, IFacingInfo, UsesInit, UsesInit, UsesInit + public class MobileInfo : IMoveInfo, IPositionableInfo, IOccupySpaceInfo, IFacingInfo, + UsesInit, UsesInit, UsesInit { [FieldLoader.LoadUsing("LoadSpeeds", true)] [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 .SelectMany(c => self.World.ActorMap.GetUnitsAt(c) - .Where(a => a.IsIdle && a.HasTrait()), + .Where(a => a.IsIdle && a.Info.Traits.Contains()), (c, a) => new { Cell = c, Actor = a }) .RandomOrDefault(self.World.SharedRandom); diff --git a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs index 3b30c7ea2b..b3d366046a 100644 --- a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs +++ b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs @@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Traits readonly bool startsRevealed; readonly PPos[] footprint; - readonly Lazy tooltip; + readonly Lazy tooltip; readonly Lazy health; readonly Dictionary visible; @@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits startsRevealed = info.StartsRevealed && !init.Contains(); var footprintCells = FootprintUtils.Tiles(init.Self).ToList(); footprint = footprintCells.SelectMany(c => map.ProjectedCellsCovering(c.ToMPos(map))).ToArray(); - tooltip = Exts.Lazy(() => init.Self.TraitsImplementing().FirstOrDefault()); + tooltip = Exts.Lazy(() => init.Self.TraitsImplementing().FirstOrDefault()); health = Exts.Lazy(() => init.Self.TraitOrDefault()); frozen = new Dictionary(); diff --git a/OpenRA.Mods.Common/Traits/Passenger.cs b/OpenRA.Mods.Common/Traits/Passenger.cs index 0df46d9083..0c0a5efb1b 100644 --- a/OpenRA.Mods.Common/Traits/Passenger.cs +++ b/OpenRA.Mods.Common/Traits/Passenger.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits { public enum AlternateTransportsMode { None, Force, Default, Always } - public class EnterTransportTargeter : EnterAlliedActorTargeter + public class EnterTransportTargeter : EnterAlliedActorTargeter { readonly AlternateTransportsMode mode; @@ -51,7 +51,7 @@ namespace OpenRA.Mods.Common.Traits } } - public class EnterTransportsTargeter : EnterAlliedActorTargeter + public class EnterTransportsTargeter : EnterAlliedActorTargeter { readonly AlternateTransportsMode mode; @@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits Info = info; Func canTarget = IsCorrectCargoType; Func useEnterCursor = CanEnter; - Orders = new EnterAlliedActorTargeter[] + Orders = new EnterAlliedActorTargeter[] { new EnterTransportTargeter("EnterTransport", 5, canTarget, useEnterCursor, Info.AlternateTransportsMode), new EnterTransportsTargeter("EnterTransports", 5, canTarget, useEnterCursor, Info.AlternateTransportsMode) diff --git a/OpenRA.Mods.Common/Traits/Player/AllyRepair.cs b/OpenRA.Mods.Common/Traits/Player/AllyRepair.cs index fd27c6afaf..30a2df05d2 100644 --- a/OpenRA.Mods.Common/Traits/Player/AllyRepair.cs +++ b/OpenRA.Mods.Common/Traits/Player/AllyRepair.cs @@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.Traits { var building = order.TargetActor; - if (building.HasTrait()) + if (building.Info.Traits.Contains()) if (building.AppearsFriendlyTo(self)) building.Trait().RepairBuilding(building, self.Owner); } diff --git a/OpenRA.Mods.Common/Traits/Player/BaseAttackNotifier.cs b/OpenRA.Mods.Common/Traits/Player/BaseAttackNotifier.cs index d3f427fdbf..0494ef1aa8 100644 --- a/OpenRA.Mods.Common/Traits/Player/BaseAttackNotifier.cs +++ b/OpenRA.Mods.Common/Traits/Player/BaseAttackNotifier.cs @@ -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.HasTrait()) + if (!self.Info.Traits.Contains()) return; if (e.Attacker == null) diff --git a/OpenRA.Mods.Common/Traits/Player/HarvesterAttackNotifier.cs b/OpenRA.Mods.Common/Traits/Player/HarvesterAttackNotifier.cs index fe02812b34..caa20dcb1a 100644 --- a/OpenRA.Mods.Common/Traits/Player/HarvesterAttackNotifier.cs +++ b/OpenRA.Mods.Common/Traits/Player/HarvesterAttackNotifier.cs @@ -47,8 +47,8 @@ namespace OpenRA.Mods.Common.Traits public void Damaged(Actor self, AttackInfo e) { - // only track last hit against our base - if (!self.HasTrait()) + // only track last hit against our harvesters + if (!self.Info.Traits.Contains()) return; // don't track self-damage diff --git a/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs b/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs index 10578444de..4f96c32465 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlayerStatistics.cs @@ -107,18 +107,18 @@ namespace OpenRA.Mods.Common.Traits var attackerStats = e.Attacker.Owner.PlayerActor.Trait(); var defenderStats = self.Owner.PlayerActor.Trait(); - if (self.HasTrait()) + if (self.Info.Traits.Contains()) { attackerStats.BuildingsKilled++; defenderStats.BuildingsDead++; } - else if (self.HasTrait()) + else if (self.Info.Traits.Contains()) { attackerStats.UnitsKilled++; defenderStats.UnitsDead++; } - if (self.HasTrait()) + if (self.Info.Traits.Contains()) { var cost = self.Info.Traits.Get().Cost; attackerStats.KillsCost += cost; diff --git a/OpenRA.Mods.Common/Traits/Player/ProvidesPrerequisite.cs b/OpenRA.Mods.Common/Traits/Player/ProvidesPrerequisite.cs index 773d0353bd..a56744f2ab 100644 --- a/OpenRA.Mods.Common/Traits/Player/ProvidesPrerequisite.cs +++ b/OpenRA.Mods.Common/Traits/Player/ProvidesPrerequisite.cs @@ -14,7 +14,7 @@ using OpenRA.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.")] public readonly string Prerequisite = null; diff --git a/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs b/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs index d9667b3e88..9065fb9047 100644 --- a/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs +++ b/OpenRA.Mods.Common/Traits/Player/ProvidesTechPrerequisite.cs @@ -13,7 +13,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public class ProvidesTechPrerequisiteInfo : ITraitInfo + public class ProvidesTechPrerequisiteInfo : ITechTreePrerequisiteInfo { public readonly string Name; public readonly string[] Prerequisites = { }; diff --git a/OpenRA.Mods.Common/Traits/Player/TechTree.cs b/OpenRA.Mods.Common/Traits/Player/TechTree.cs index 00fb3c624c..cc26cbd1e7 100644 --- a/OpenRA.Mods.Common/Traits/Player/TechTree.cs +++ b/OpenRA.Mods.Common/Traits/Player/TechTree.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Traits public void ActorChanged(Actor a) { var bi = a.Info.Traits.GetOrDefault(); - if (a.Owner == player && (a.HasTrait() || (bi != null && bi.BuildLimit > 0))) + if (a.Owner == player && (a.Info.Traits.Contains() || (bi != null && bi.BuildLimit > 0))) Update(); } diff --git a/OpenRA.Mods.Common/Traits/Render/Hovers.cs b/OpenRA.Mods.Common/Traits/Render/Hovers.cs index a02609e405..49e7e970b0 100644 --- a/OpenRA.Mods.Common/Traits/Render/Hovers.cs +++ b/OpenRA.Mods.Common/Traits/Render/Hovers.cs @@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Traits public Hovers(HoversInfo info, Actor self) { this.info = info; - aircraft = self.HasTrait(); + aircraft = self.Info.Traits.Contains(); } public IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r) diff --git a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs index 5b6294fe0b..b074d5194e 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedAnimation.cs @@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits { this.info = info; wsb = self.Trait(); - buildComplete = !self.HasTrait(); + buildComplete = !self.Info.Traits.Contains(); } public void BuildingComplete(Actor self) diff --git a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs index 7bbcb1b363..4a5085cf7c 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithBuildingPlacedOverlay.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.HasTrait(); // always render instantly for units + buildComplete = !self.Info.Traits.Contains(); // always render instantly for units overlay = new Animation(self.World, rs.GetImage(self)); diff --git a/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs index cb0631f846..a650248977 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDockingOverlay.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.Traits var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.HasTrait(); // always render instantly for units + buildComplete = !self.Info.Traits.Contains(); // always render instantly for units var overlay = new Animation(self.World, rs.GetImage(self)); overlay.Play(info.Sequence); diff --git a/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs index 2f4a58a107..d0fa673e3e 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithIdleOverlay.cs @@ -68,7 +68,7 @@ namespace OpenRA.Mods.Common.Traits var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.HasTrait(); // always render instantly for units + buildComplete = !self.Info.Traits.Contains(); // 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), diff --git a/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs b/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs index 52a4253640..9a5355bdf9 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithRepairOverlay.cs @@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits var rs = self.Trait(); var body = self.Trait(); - buildComplete = !self.HasTrait(); // always render instantly for units + buildComplete = !self.Info.Traits.Contains(); // always render instantly for units overlay = new Animation(self.World, rs.GetImage(self)); overlay.Play(info.Sequence); diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs index b7b5cdc42f..24ee8239fc 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs @@ -17,7 +17,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Default trait for rendering sprite-based actors.")] - public class WithSpriteBodyInfo : UpgradableTraitInfo, IRenderActorPreviewSpritesInfo, Requires + public class WithSpriteBodyInfo : UpgradableTraitInfo, ISpriteBodyInfo, IRenderActorPreviewSpritesInfo, Requires { [Desc("Animation to play when the actor is created."), SequenceReference] public readonly string StartSequence = null; diff --git a/OpenRA.Mods.Common/Traits/Repairable.cs b/OpenRA.Mods.Common/Traits/Repairable.cs index 310710d444..59e51c879f 100644 --- a/OpenRA.Mods.Common/Traits/Repairable.cs +++ b/OpenRA.Mods.Common/Traits/Repairable.cs @@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits { get { - yield return new EnterAlliedActorTargeter("Repair", 5, CanRepairAt, _ => CanRepair() || CanRearm()); + yield return new EnterAlliedActorTargeter("Repair", 5, CanRepairAt, _ => CanRepair() || CanRearm()); } } diff --git a/OpenRA.Mods.Common/Traits/RepairableNear.cs b/OpenRA.Mods.Common/Traits/RepairableNear.cs index ddae2b19d5..4de7aad94d 100644 --- a/OpenRA.Mods.Common/Traits/RepairableNear.cs +++ b/OpenRA.Mods.Common/Traits/RepairableNear.cs @@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits { get { - yield return new EnterAlliedActorTargeter("RepairNear", 5, + yield return new EnterAlliedActorTargeter("RepairNear", 5, target => CanRepairAt(target), _ => ShouldRepair()); } } diff --git a/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs b/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs index 7ad82ca1c7..80f1a7e52f 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AmbientSound.cs @@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.Traits { public AmbientSound(Actor self, AmbientSoundInfo info) { - if (self.HasTrait()) + if (self.Info.Traits.Contains()) Sound.PlayLooped(info.SoundFile, self.CenterPosition); else Sound.PlayLooped(info.SoundFile); diff --git a/OpenRA.Mods.Common/Traits/SupplyTruck.cs b/OpenRA.Mods.Common/Traits/SupplyTruck.cs index c80a63ddde..ae3ca5f03b 100644 --- a/OpenRA.Mods.Common/Traits/SupplyTruck.cs +++ b/OpenRA.Mods.Common/Traits/SupplyTruck.cs @@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - return target.HasTrait(); + return target.Info.Traits.Contains(); } public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs index 4486b77a6e..1a93ecb8ff 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs @@ -78,7 +78,7 @@ namespace OpenRA.Mods.Common.Traits void ActorRemoved(Actor a) { - if (a.Owner != Self.Owner || !a.HasTrait()) + if (a.Owner != Self.Owner || !a.Info.Traits.Contains()) return; foreach (var t in a.TraitsImplementing()) @@ -119,7 +119,7 @@ namespace OpenRA.Mods.Common.Traits public IEnumerable GetPowersForActor(Actor a) { - if (a.Owner != Self.Owner || !a.HasTrait()) + if (a.Owner != Self.Owner || !a.Info.Traits.Contains()) return NoInstances; return a.TraitsImplementing() diff --git a/OpenRA.Mods.Common/Traits/Targetable.cs b/OpenRA.Mods.Common/Traits/Targetable.cs index 45cc822a09..ff7397bcfc 100644 --- a/OpenRA.Mods.Common/Traits/Targetable.cs +++ b/OpenRA.Mods.Common/Traits/Targetable.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits { if (IsTraitDisabled) return false; - if (cloak == null || (!viewer.IsDead && viewer.HasTrait())) + if (cloak == null || (!viewer.IsDead && viewer.Info.Traits.Contains())) return true; return cloak.IsVisible(self, viewer.Owner); diff --git a/OpenRA.Mods.Common/Traits/Tooltip.cs b/OpenRA.Mods.Common/Traits/Tooltip.cs index 6bfb944c02..3d0de5e6d5 100644 --- a/OpenRA.Mods.Common/Traits/Tooltip.cs +++ b/OpenRA.Mods.Common/Traits/Tooltip.cs @@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits public bool IsOwnerRowVisible { get { return ShowOwnerRow; } } } - public class Tooltip : IToolTip + public class Tooltip : ITooltip { readonly Actor self; readonly TooltipInfo info; diff --git a/OpenRA.Mods.Common/Traits/Transforms.cs b/OpenRA.Mods.Common/Traits/Transforms.cs index 2a33b2c1de..739cb293f7 100644 --- a/OpenRA.Mods.Common/Traits/Transforms.cs +++ b/OpenRA.Mods.Common/Traits/Transforms.cs @@ -109,10 +109,10 @@ namespace OpenRA.Mods.Common.Traits if (!queued) self.CancelActivity(); - if (self.HasTrait()) + if (self.Info.Traits.Contains()) self.QueueActivity(new Turn(self, info.Facing)); - if (self.HasTrait()) + if (self.Info.Traits.Contains()) self.QueueActivity(new HeliLand(self, true)); foreach (var nt in self.TraitsImplementing()) diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index a3e912dc0e..a508234b20 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { + public interface ISpriteBodyInfo : ITraitInfo { } public interface ISpriteBody { void PlayCustomAnimation(Actor self, string newAnimation, Action after); @@ -67,6 +68,7 @@ namespace OpenRA.Mods.Common.Traits void Undocked(); } + public interface ITechTreePrerequisiteInfo : ITraitInfo { } public interface ITechTreePrerequisite { IEnumerable 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 IAcceptResourcesInfo : ITraitInfo { } public interface IAcceptResources { void OnDock(Actor harv, DeliverResources dockOrder); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs index 708855fd99..1640d5df00 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs @@ -245,7 +245,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic .Sum(a => a.Info.Traits.WithInterface().First().Cost); var harvesters = template.Get("HARVESTERS"); - harvesters.GetText = () => world.Actors.Count(a => a.Owner == player && !a.IsDead && a.HasTrait()).ToString(); + harvesters.GetText = () => world.Actors.Count(a => a.Owner == player && !a.IsDead && a.Info.Traits.Contains()).ToString(); return template; } @@ -280,7 +280,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { return ScrollItemWidget.Setup(template, () => false, () => { - var playerBase = world.Actors.FirstOrDefault(a => !a.IsDead && a.HasTrait() && a.Owner == player); + var playerBase = world.Actors.FirstOrDefault(a => !a.IsDead && a.Info.Traits.Contains() && a.Owner == player); if (playerBase != null) worldRenderer.Viewport.Center(playerBase.CenterPosition); }); diff --git a/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs b/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs index 14ea5e9943..135540d336 100644 --- a/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs @@ -198,7 +198,7 @@ namespace OpenRA.Mods.Common.Widgets // Is added to world.ActorAdded by the SidebarLogic handler public void ActorChanged(Actor a) { - if (a.HasTrait()) + if (a.Info.Traits.Contains()) { var allQueues = a.World.ActorsWithTrait() .Where(p => p.Actor.Owner == p.Actor.World.LocalPlayer && p.Actor.IsInWorld && p.Trait.Enabled) diff --git a/OpenRA.Mods.Common/Widgets/ViewportControllerWidget.cs b/OpenRA.Mods.Common/Widgets/ViewportControllerWidget.cs index dbd83528dd..e3d5f31122 100644 --- a/OpenRA.Mods.Common/Widgets/ViewportControllerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ViewportControllerWidget.cs @@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Widgets Lazy tooltipContainer; 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 FrozenActor FrozenActorTooltip { get; private set; } @@ -106,12 +106,12 @@ namespace OpenRA.Mods.Common.Widgets } var underCursor = world.ScreenMap.ActorsAt(worldRenderer.Viewport.ViewToWorldPx(Viewport.LastMousePos)) - .Where(a => !world.FogObscures(a) && a.HasTrait()) + .Where(a => !world.FogObscures(a) && a.Info.Traits.Contains()) .WithHighestSelectionPriority(); if (underCursor != null) { - ActorTooltip = underCursor.TraitsImplementing().First(); + ActorTooltip = underCursor.TraitsImplementing().First(); ActorTooltipExtra = underCursor.TraitsImplementing().ToArray(); TooltipType = WorldTooltipType.Actor; return; diff --git a/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs b/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs index 3021a1ac33..a3b48bfdb4 100644 --- a/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs +++ b/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs @@ -177,7 +177,7 @@ namespace OpenRA.Mods.Common.Widgets bool PerformGuard() { var actors = world.Selection.Actors - .Where(a => !a.Disposed && a.Owner == world.LocalPlayer && a.HasTrait()); + .Where(a => !a.Disposed && a.Owner == world.LocalPlayer && a.Info.Traits.Contains()); if (actors.Any()) world.OrderGenerator = new GuardOrderGenerator(actors); @@ -197,7 +197,7 @@ namespace OpenRA.Mods.Common.Widgets { var building = world.ActorsWithTrait() .Select(b => b.Actor) - .FirstOrDefault(a => a.Owner == world.LocalPlayer && a.HasTrait()); + .FirstOrDefault(a => a.Owner == world.LocalPlayer && a.Info.Traits.Contains()); // No buildings left if (building == null) @@ -223,7 +223,7 @@ namespace OpenRA.Mods.Common.Widgets bool CycleProductionBuildings() { var facilities = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == world.LocalPlayer && !a.Actor.HasTrait()) + .Where(a => a.Actor.Owner == world.LocalPlayer && !a.Actor.Info.Traits.Contains()) .OrderBy(f => f.Actor.Info.Traits.Get().Produces.First()) .Select(b => b.Actor) .ToList(); diff --git a/OpenRA.Mods.D2k/Activities/SwallowActor.cs b/OpenRA.Mods.D2k/Activities/SwallowActor.cs index 9379c21bab..389a6536bd 100644 --- a/OpenRA.Mods.D2k/Activities/SwallowActor.cs +++ b/OpenRA.Mods.D2k/Activities/SwallowActor.cs @@ -79,7 +79,7 @@ namespace OpenRA.Mods.D2k.Activities actor1.Dispose(); // Harvester insurance - if (!actor1.HasTrait()) + if (!actor1.Info.Traits.Contains()) return; var insurance = actor1.Owner.PlayerActor.TraitOrDefault(); diff --git a/OpenRA.Mods.D2k/Traits/Carryable.cs b/OpenRA.Mods.D2k/Traits/Carryable.cs index e96847daf3..cad10371eb 100644 --- a/OpenRA.Mods.D2k/Traits/Carryable.cs +++ b/OpenRA.Mods.D2k/Traits/Carryable.cs @@ -117,7 +117,7 @@ namespace OpenRA.Mods.D2k.Traits { // 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 - var findResources = self.HasTrait() && !(afterLandActivity is DeliverResources); + var findResources = self.Info.Traits.Contains() && !(afterLandActivity is DeliverResources); if (findResources) self.QueueActivity(new FindResources(self)); else diff --git a/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs b/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs index 017656005c..cd86d62c42 100644 --- a/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs +++ b/OpenRA.Mods.D2k/Traits/Render/WithDeliveryOverlay.cs @@ -49,7 +49,7 @@ namespace OpenRA.Mods.D2k.Traits var body = self.Trait(); // always render instantly for units - buildComplete = !self.HasTrait(); + buildComplete = !self.Info.Traits.Contains(); var overlay = new Animation(self.World, rs.GetImage(self)); overlay.Play(info.Sequence); diff --git a/OpenRA.Mods.D2k/Traits/Sandworm.cs b/OpenRA.Mods.D2k/Traits/Sandworm.cs index a2c9615faa..ce8c0d2e5c 100644 --- a/OpenRA.Mods.D2k/Traits/Sandworm.cs +++ b/OpenRA.Mods.D2k/Traits/Sandworm.cs @@ -99,7 +99,7 @@ namespace OpenRA.Mods.D2k.Traits targetCountdown = Info.TargetRescanInterval; // If close enough, we don't care about other actors. - var target = self.World.FindActorsInCircle(self.CenterPosition, Info.IgnoreNoiseAttackRange).FirstOrDefault(x => x.HasTrait()); + var target = self.World.FindActorsInCircle(self.CenterPosition, Info.IgnoreNoiseAttackRange).FirstOrDefault(x => x.Info.Traits.Contains()); if (target != null) { self.CancelActivity(); @@ -109,7 +109,7 @@ namespace OpenRA.Mods.D2k.Traits Func isValidTarget = a => { - if (!a.HasTrait()) + if (!a.Info.Traits.Contains()) return false; return mobile.CanEnterCell(a.Location, null, false); diff --git a/OpenRA.Mods.RA/Activities/Infiltrate.cs b/OpenRA.Mods.RA/Activities/Infiltrate.cs index 4e566770a6..1f7c23fad8 100644 --- a/OpenRA.Mods.RA/Activities/Infiltrate.cs +++ b/OpenRA.Mods.RA/Activities/Infiltrate.cs @@ -50,7 +50,7 @@ namespace OpenRA.Mods.RA.Activities self.Dispose(); - if (target.HasTrait()) + if (target.Info.Traits.Contains()) Sound.PlayToPlayer(self.Owner, "bldginf1.aud"); } } diff --git a/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs b/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs index 75bf52f0be..f8abd6b7cf 100644 --- a/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs +++ b/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Traits public void UnitProducedByOther(Actor self, Actor producer, Actor produced) { // No recursive cloning! - if (producer.Owner != self.Owner || producer.HasTrait()) + if (producer.Owner != self.Owner || producer.Info.Traits.Contains()) return; var ci = produced.Info.Traits.GetOrDefault(); diff --git a/OpenRA.Mods.RA/Traits/Chronoshiftable.cs b/OpenRA.Mods.RA/Traits/Chronoshiftable.cs index 68f7d33973..f5c4a5774b 100644 --- a/OpenRA.Mods.RA/Traits/Chronoshiftable.cs +++ b/OpenRA.Mods.RA/Traits/Chronoshiftable.cs @@ -64,7 +64,7 @@ namespace OpenRA.Mods.RA.Traits public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation) { // TODO: Allow enemy units to be chronoshifted into bad terrain to kill them - return self.HasTrait() && self.Trait().CanEnterCell(targetLocation); + return self.Info.Traits.Contains() && self.Trait().CanEnterCell(targetLocation); } public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere) diff --git a/OpenRA.Mods.RA/Traits/Disguise.cs b/OpenRA.Mods.RA/Traits/Disguise.cs index 73ecbc433d..96e814e4c1 100644 --- a/OpenRA.Mods.RA/Traits/Disguise.cs +++ b/OpenRA.Mods.RA/Traits/Disguise.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA.Traits public override object Create(ActorInitializer init) { return new DisguiseToolTip(init.Self, this); } } - class DisguiseToolTip : IToolTip + class DisguiseToolTip : ITooltip { readonly Actor self; readonly Disguise disguise; @@ -147,7 +147,7 @@ namespace OpenRA.Mods.RA.Traits else { AsSprite = target.Trait().GetImage(target); - var tooltip = target.TraitsImplementing().FirstOrDefault(); + var tooltip = target.TraitsImplementing().FirstOrDefault(); AsPlayer = tooltip.Owner; AsTooltipInfo = tooltip.TooltipInfo; } diff --git a/OpenRA.Mods.RA/Traits/Mine.cs b/OpenRA.Mods.RA/Traits/Mine.cs index 9372bfc7db..068fdcc293 100644 --- a/OpenRA.Mods.RA/Traits/Mine.cs +++ b/OpenRA.Mods.RA/Traits/Mine.cs @@ -39,7 +39,7 @@ namespace OpenRA.Mods.RA.Traits public void OnCrush(Actor crusher) { - if (crusher.HasTrait() || (self.Owner.Stances[crusher.Owner] == Stance.Ally && info.AvoidFriendly)) + if (crusher.Info.Traits.Contains() || (self.Owner.Stances[crusher.Owner] == Stance.Ally && info.AvoidFriendly)) return; var mobile = crusher.TraitOrDefault(); diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs index 3e33e74ff9..0c7ebdf689 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs @@ -64,7 +64,7 @@ namespace OpenRA.Mods.RA.Traits foreach (var t in tiles) units.UnionWith(Self.World.ActorMap.GetUnitsAt(t)); - return units.Where(a => a.HasTrait() && + return units.Where(a => a.Info.Traits.Contains() && !a.TraitsImplementing().Any(condition => condition.PreventsTeleport(a))); }