diff --git a/OpenRA.Game/GameRules/WeaponInfo.cs b/OpenRA.Game/GameRules/WeaponInfo.cs index aacdb0fea9..00838d70a8 100644 --- a/OpenRA.Game/GameRules/WeaponInfo.cs +++ b/OpenRA.Game/GameRules/WeaponInfo.cs @@ -125,8 +125,8 @@ namespace OpenRA.GameRules /// Checks if the weapon is valid against (can target) the actor. public bool IsValidAgainst(Actor victim, Actor firedBy) { - var targetable = victim.TraitOrDefault(); - if (targetable == null || !IsValidTarget(targetable.TargetTypes)) + var targetable = victim.TraitsImplementing().Where(Exts.IsTraitEnabled); + if (!IsValidTarget(targetable.SelectMany(t => t.TargetTypes))) return false; if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy))) @@ -138,8 +138,7 @@ namespace OpenRA.GameRules /// Checks if the weapon is valid against (can target) the frozen actor. public bool IsValidAgainst(FrozenActor victim, Actor firedBy) { - var targetable = victim.Info.Traits.GetOrDefault(); - if (targetable == null || !IsValidTarget(targetable.GetTargetTypes())) + if (!IsValidTarget(victim.TargetTypes)) return false; if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy))) diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs index 384de66273..a1c652889d 100644 --- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs +++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs @@ -27,6 +27,7 @@ namespace OpenRA.Traits public readonly PPos[] Footprint; public readonly WPos CenterPosition; public readonly Rectangle Bounds; + public readonly string[] TargetTypes; readonly IRemoveFrozenActor[] removeFrozenActors; readonly Actor actor; readonly Shroud shroud; @@ -56,6 +57,7 @@ namespace OpenRA.Traits CenterPosition = self.CenterPosition; Bounds = self.Bounds; + TargetTypes = self.TraitsImplementing().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes).Distinct().ToArray(); UpdateVisibility(); } diff --git a/OpenRA.Game/Traits/Target.cs b/OpenRA.Game/Traits/Target.cs index d5261e04fa..d8c8e3fff3 100644 --- a/OpenRA.Game/Traits/Target.cs +++ b/OpenRA.Game/Traits/Target.cs @@ -22,7 +22,7 @@ namespace OpenRA.Traits TargetType type; Actor actor; - ITargetable targetable; + IEnumerable targetable; FrozenActor frozen; WPos pos; int generation; @@ -48,7 +48,7 @@ namespace OpenRA.Traits return new Target { actor = a, - targetable = a.TraitOrDefault(), + targetable = a.TraitsImplementing(), type = TargetType.Actor, generation = a.Generation, }; @@ -83,15 +83,18 @@ namespace OpenRA.Traits if (targeter == null || Type == TargetType.Invalid) return false; - if (targetable != null && !targetable.TargetableBy(actor, targeter)) + var targeted = this.actor; + if (targeted != null && !targetable.Any(t => t.IsTraitEnabled() && t.TargetableBy(targeted, targeter))) return false; return true; } + // Currently all or nothing. + // TODO: either replace based on target type or put in singleton trait public bool RequiresForceFire { - get { return targetable != null && targetable.RequiresForceFire; } + get { return targetable != null && targetable.Any(Exts.IsTraitEnabled) && targetable.Where(Exts.IsTraitEnabled).All(t => t.RequiresForceFire); } } // Representative position - see Positions for the full set of targetable positions. @@ -123,12 +126,19 @@ namespace OpenRA.Traits switch (Type) { case TargetType.Actor: - var targetable = actor.TraitOrDefault(); - if (targetable == null) + var targetable = actor.TraitsImplementing().Where(Exts.IsTraitEnabled); + if (!targetable.Any()) return new[] { actor.CenterPosition }; - var positions = targetable.TargetablePositions(actor); - return positions.Any() ? positions : new[] { actor.CenterPosition }; + var targetablePositions = actor.TraitOrDefault(); + if (targetablePositions != null) + { + var positions = targetablePositions.TargetablePositions(actor); + if (positions.Any()) + return positions; + } + + return new[] { actor.CenterPosition }; case TargetType.FrozenActor: return new[] { frozen.CenterPosition }; case TargetType.Terrain: diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index ffd7ebb581..bef29acbf8 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -315,12 +315,17 @@ namespace OpenRA.Traits public interface ITargetable { + // Check IsTraitEnabled or !IsTraitDisabled first string[] TargetTypes { get; } - IEnumerable TargetablePositions(Actor self); bool TargetableBy(Actor self, Actor byActor); bool RequiresForceFire { get; } } + public interface ITargetablePositions + { + IEnumerable TargetablePositions(Actor self); + } + public interface INotifyStanceChanged { void StanceChanged(Actor self, Player a, Player b, diff --git a/OpenRA.Mods.Common/AI/States/StateBase.cs b/OpenRA.Mods.Common/AI/States/StateBase.cs index 7c898db728..fd255dbec5 100644 --- a/OpenRA.Mods.Common/AI/States/StateBase.cs +++ b/OpenRA.Mods.Common/AI/States/StateBase.cs @@ -63,13 +63,13 @@ namespace OpenRA.Mods.Common.AI if (!a.HasTrait()) return false; - var targetable = target.TraitOrDefault(); - if (targetable == null) + var targetTypes = target.TraitsImplementing().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes); + if (!targetTypes.Any()) return false; var arms = a.TraitsImplementing(); foreach (var arm in arms) - if (arm.Weapon.IsValidTarget(targetable.TargetTypes)) + if (arm.Weapon.IsValidTarget(targetTypes)) return true; return false; diff --git a/OpenRA.Mods.Common/AI/SupportPowerDecision.cs b/OpenRA.Mods.Common/AI/SupportPowerDecision.cs index a931e3b1de..13b0ad968c 100644 --- a/OpenRA.Mods.Common/AI/SupportPowerDecision.cs +++ b/OpenRA.Mods.Common/AI/SupportPowerDecision.cs @@ -125,14 +125,11 @@ namespace OpenRA.Mods.Common.AI if (a == null) return 0; - var targetable = a.TraitOrDefault(); - if (targetable == null) + var targetable = a.TraitsImplementing().Where(Exts.IsTraitEnabled); + if (!targetable.Any(t => t.TargetableBy(a, firedBy.PlayerActor))) return 0; - if (!targetable.TargetableBy(a, firedBy.PlayerActor)) - return 0; - - if (Types.Intersect(targetable.TargetTypes).Any()) + if (Types.Intersect(targetable.SelectMany(t => t.TargetTypes)).Any()) { switch (TargetMetric) { diff --git a/OpenRA.Mods.Common/Activities/Hunt.cs b/OpenRA.Mods.Common/Activities/Hunt.cs index af520042c6..55ff87989d 100644 --- a/OpenRA.Mods.Common/Activities/Hunt.cs +++ b/OpenRA.Mods.Common/Activities/Hunt.cs @@ -29,8 +29,7 @@ namespace OpenRA.Mods.Common.Activities bool IsTargetable(Actor self, Actor viewer) { - var targetable = self.TraitOrDefault(); - return targetable != null && targetable.TargetableBy(self, viewer); + return self.TraitsImplementing().Any(t => t.IsTraitEnabled() && t.TargetableBy(self, viewer)); } public override Activity Tick(Actor self) diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index aa9da4dc8c..e0cc610688 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -256,7 +256,6 @@ - @@ -293,7 +292,6 @@ - @@ -476,7 +474,7 @@ - + diff --git a/OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs b/OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs index 13ac615446..6e873260c1 100644 --- a/OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs +++ b/OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs @@ -77,12 +77,12 @@ namespace OpenRA.Mods.Common.Orders public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - return target.TraitsImplementing().Any(t => t.TargetTypes.Intersect(targetTypes).Any()); + return target.TraitsImplementing().Any(t => t.IsTraitEnabled() && t.TargetTypes.Intersect(targetTypes).Any()); } public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) { - return target.Info.Traits.WithInterface().Any(t => t.GetTargetTypes().Intersect(targetTypes).Any()); + return target.TargetTypes.Intersect(targetTypes).Any(); } } } diff --git a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs index d5bbe680a2..bf9b8a076d 100644 --- a/OpenRA.Mods.Common/Traits/Air/Aircraft.cs +++ b/OpenRA.Mods.Common/Traits/Air/Aircraft.cs @@ -35,6 +35,9 @@ namespace OpenRA.Mods.Common.Traits public readonly int InitialFacing = 0; public readonly int ROT = 255; public readonly int Speed = 1; + + [Desc("Minimum altitude where this aircraft is considered airborne")] + public readonly int MinAirborneAltitude = 1; public readonly string[] LandableTerrainTypes = { }; [Desc("Can the actor be ordered to move in to shroud?")] @@ -46,22 +49,52 @@ namespace OpenRA.Mods.Common.Traits [VoiceReference] public readonly string Voice = "Action"; + [UpgradeGrantedReference] + [Desc("The upgrades to grant to self while airborne.")] + public readonly string[] AirborneUpgrades = { }; + public IReadOnlyDictionary OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary(); } bool IOccupySpaceInfo.SharesCell { get { return false; } } } - public class Aircraft : IFacing, IPositionable, ISync, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing + public class Aircraft : IFacing, IPositionable, ISync, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyCreated, INotifyActorDisposing { static readonly Pair[] NoCells = { }; readonly AircraftInfo info; readonly Actor self; + UpgradeManager um; [Sync] public int Facing { get; set; } [Sync] public WPos CenterPosition { get; private set; } public CPos TopLeft { get { return self.World.Map.CellContaining(CenterPosition); } } public IDisposable Reservation; public int ROT { get { return info.ROT; } } + bool IsAirborne + { + get + { + return airborne; + } + + set + { + if (airborne == value) + return; + airborne = value; + if (um != null) + { + if (airborne) + foreach (var u in info.AirborneUpgrades) + um.GrantUpgrade(self, u, this); + else + foreach (var u in info.AirborneUpgrades) + um.RevokeUpgrade(self, u, this); + } + } + } + + bool airborne = false; public Aircraft(ActorInitializer init, AircraftInfo info) { @@ -77,6 +110,8 @@ namespace OpenRA.Mods.Common.Traits Facing = init.Contains() ? init.Get() : info.InitialFacing; } + public void Created(Actor self) { um = self.TraitOrDefault(); } + bool firstTick = true; public virtual void Tick(Actor self) { @@ -197,6 +232,7 @@ namespace OpenRA.Mods.Common.Traits { self.World.ScreenMap.Update(self); self.World.ActorMap.UpdatePosition(self, this); + IsAirborne = self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= info.MinAirborneAltitude; } } @@ -213,6 +249,8 @@ namespace OpenRA.Mods.Common.Traits self.World.ActorMap.AddInfluence(self, this); self.World.ActorMap.AddPosition(self, this); self.World.ScreenMap.Add(self); + if (self.World.Map.DistanceAboveTerrain(CenterPosition).Length >= info.MinAirborneAltitude) + IsAirborne = true; } public void RemovedFromWorld(Actor self) @@ -221,6 +259,7 @@ namespace OpenRA.Mods.Common.Traits self.World.ActorMap.RemoveInfluence(self, this); self.World.ActorMap.RemovePosition(self, this); self.World.ScreenMap.Remove(self); + IsAirborne = false; } public bool AircraftCanEnter(Actor a) diff --git a/OpenRA.Mods.Common/Traits/Air/TargetableAircraft.cs b/OpenRA.Mods.Common/Traits/Air/TargetableAircraft.cs deleted file mode 100644 index e8d9924197..0000000000 --- a/OpenRA.Mods.Common/Traits/Air/TargetableAircraft.cs +++ /dev/null @@ -1,43 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Collections.Generic; -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits -{ - public class TargetableAircraftInfo : TargetableUnitInfo - { - public readonly string[] GroundedTargetTypes = { }; - public override object Create(ActorInitializer init) { return new TargetableAircraft(init.Self, this); } - } - - public class TargetableAircraft : TargetableUnit - { - readonly TargetableAircraftInfo info; - readonly Actor self; - - public TargetableAircraft(Actor self, TargetableAircraftInfo info) - : base(self, info) - { - this.info = info; - this.self = self; - } - - public override string[] TargetTypes - { - get - { - return IsTraitDisabled ? None - : (self.CenterPosition.Z > 0 ? info.TargetTypes : info.GroundedTargetTypes); - } - } - } -} diff --git a/OpenRA.Mods.Common/Traits/Buildings/Building.cs b/OpenRA.Mods.Common/Traits/Buildings/Building.cs index ab0cdca8f5..2275addc09 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Building.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Building.cs @@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits bool IOccupySpaceInfo.SharesCell { get { return false; } } } - public class Building : IOccupySpace, INotifySold, INotifyTransform, ISync, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld + public class Building : IOccupySpace, INotifySold, INotifyTransform, ISync, INotifyCreated, INotifyAddedToWorld, INotifyRemovedFromWorld, ITargetablePositions { public readonly BuildingInfo Info; public bool BuildComplete { get; private set; } @@ -157,6 +157,11 @@ namespace OpenRA.Mods.Common.Traits Pair[] occupiedCells; public IEnumerable> OccupiedCells() { return occupiedCells; } + public IEnumerable TargetablePositions(Actor self) + { + return OccupiedCells().Select(c => self.World.Map.CenterOfCell(c.First)); + } + public void Created(Actor self) { if (SkipMakeAnimation || !self.HasTrait()) diff --git a/OpenRA.Mods.Common/Traits/Buildings/TargetableBuilding.cs b/OpenRA.Mods.Common/Traits/Buildings/TargetableBuilding.cs deleted file mode 100644 index e81b8fafbc..0000000000 --- a/OpenRA.Mods.Common/Traits/Buildings/TargetableBuilding.cs +++ /dev/null @@ -1,49 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Collections.Generic; -using System.Linq; -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits -{ - public class TargetableBuildingInfo : ITraitInfo, ITargetableInfo, Requires - { - [FieldLoader.Require] - public readonly string[] TargetTypes = { }; - public string[] GetTargetTypes() { return TargetTypes; } - - public bool RequiresForceFire = false; - - public object Create(ActorInitializer init) { return new TargetableBuilding(init.Self, this); } - } - - public class TargetableBuilding : ITargetable - { - readonly TargetableBuildingInfo info; - readonly Building building; - - public TargetableBuilding(Actor self, TargetableBuildingInfo info) - { - this.info = info; - building = self.Trait(); - } - - public string[] TargetTypes { get { return info.TargetTypes; } } - public bool TargetableBy(Actor self, Actor byActor) { return true; } - - public IEnumerable TargetablePositions(Actor self) - { - return building.OccupiedCells().Select(c => self.World.Map.CenterOfCell(c.First)); - } - - public bool RequiresForceFire { get { return info.RequiresForceFire; } } - } -} diff --git a/OpenRA.Mods.Common/Traits/Cloak.cs b/OpenRA.Mods.Common/Traits/Cloak.cs index 5f67f8327e..95860b4ed6 100644 --- a/OpenRA.Mods.Common/Traits/Cloak.cs +++ b/OpenRA.Mods.Common/Traits/Cloak.cs @@ -38,13 +38,18 @@ namespace OpenRA.Mods.Common.Traits public readonly string[] CloakTypes = { "Cloak" }; + [UpgradeGrantedReference] + [Desc("The upgrades to grant to self while cloaked.")] + public readonly string[] WhileCloakedUpgrades = { }; + public override object Create(ActorInitializer init) { return new Cloak(init.Self, this); } } - public class Cloak : UpgradableTrait, IRenderModifier, INotifyDamageStateChanged, INotifyAttack, ITick, IVisibilityModifier, IRadarColorModifier + public class Cloak : UpgradableTrait, IRenderModifier, INotifyDamageStateChanged, INotifyAttack, ITick, IVisibilityModifier, IRadarColorModifier, INotifyCreated { [Sync] int remainingTime; [Sync] bool damageDisabled; + UpgradeManager upgradeManager; Actor self; CPos? lastPos; @@ -57,6 +62,17 @@ namespace OpenRA.Mods.Common.Traits remainingTime = info.InitialDelay; } + public void Created(Actor self) + { + upgradeManager = self.TraitOrDefault(); + if (remainingTime == 0) + { + if (upgradeManager != null) + foreach (var u in Info.WhileCloakedUpgrades) + upgradeManager.GrantUpgrade(self, u, this); + } + } + protected override void UpgradeDisabled(Actor self) { Uncloak(); @@ -68,7 +84,12 @@ namespace OpenRA.Mods.Common.Traits public void Uncloak(int time) { if (Cloaked) + { Sound.Play(Info.UncloakSound, self.CenterPosition); + if (upgradeManager != null) + foreach (var u in Info.WhileCloakedUpgrades) + upgradeManager.RevokeUpgrade(self, u, this); + } remainingTime = Math.Max(remainingTime, time); } @@ -106,7 +127,12 @@ namespace OpenRA.Mods.Common.Traits return; if (remainingTime > 0 && !IsTraitDisabled && !damageDisabled && --remainingTime <= 0) + { Sound.Play(Info.CloakSound, self.CenterPosition); + if (upgradeManager != null) + foreach (var u in Info.WhileCloakedUpgrades) + upgradeManager.GrantUpgrade(self, u, this); + } if (self.IsDisabled()) Uncloak(); diff --git a/OpenRA.Mods.Common/Traits/Crates/DuplicateUnitCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/DuplicateUnitCrateAction.cs index bfb78ec27b..f6a83327a6 100644 --- a/OpenRA.Mods.Common/Traits/Crates/DuplicateUnitCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/DuplicateUnitCrateAction.cs @@ -57,8 +57,8 @@ namespace OpenRA.Mods.Common.Traits if (info.ValidFactions.Any() && !info.ValidFactions.Contains(collector.Owner.Faction.InternalName)) return false; - var targetable = collector.Info.Traits.GetOrDefault(); - if (targetable == null || !info.ValidTargets.Intersect(targetable.GetTargetTypes()).Any()) + var targetable = collector.TraitsImplementing(); + if (!info.ValidTargets.Intersect(targetable.SelectMany(t => t.TargetTypes)).Any()) return false; var positionable = collector.TraitOrDefault(); diff --git a/OpenRA.Mods.Common/Traits/TargetableUnit.cs b/OpenRA.Mods.Common/Traits/Targetable.cs similarity index 72% rename from OpenRA.Mods.Common/Traits/TargetableUnit.cs rename to OpenRA.Mods.Common/Traits/Targetable.cs index 733c792b10..c7323aa7c5 100644 --- a/OpenRA.Mods.Common/Traits/TargetableUnit.cs +++ b/OpenRA.Mods.Common/Traits/Targetable.cs @@ -14,7 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Actor can be targeted.")] - public class TargetableUnitInfo : UpgradableTraitInfo, ITargetableInfo + public class TargetableInfo : UpgradableTraitInfo, ITargetableInfo { [Desc("Target type. Used for filtering (in)valid targets.")] public readonly string[] TargetTypes = { }; @@ -22,15 +22,15 @@ namespace OpenRA.Mods.Common.Traits public bool RequiresForceFire = false; - public override object Create(ActorInitializer init) { return new TargetableUnit(init.Self, this); } + public override object Create(ActorInitializer init) { return new Targetable(init.Self, this); } } - public class TargetableUnit : UpgradableTrait, ITargetable + public class Targetable : UpgradableTrait, ITargetable { protected static readonly string[] None = new string[] { }; protected Cloak cloak; - public TargetableUnit(Actor self, TargetableUnitInfo info) + public Targetable(Actor self, TargetableInfo info) : base(info) { cloak = self.TraitOrDefault(); @@ -46,12 +46,7 @@ namespace OpenRA.Mods.Common.Traits return cloak.IsVisible(self, viewer.Owner); } - public virtual string[] TargetTypes { get { return IsTraitDisabled ? None : Info.TargetTypes; } } - - public virtual IEnumerable TargetablePositions(Actor self) - { - yield return self.CenterPosition; - } + public virtual string[] TargetTypes { get { return Info.TargetTypes; } } public bool RequiresForceFire { get { return Info.RequiresForceFire; } } } diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index ab12a839f0..7138902dc0 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -1965,6 +1965,92 @@ namespace OpenRA.Mods.Common.UtilityCommands } } + if (engineVersion < 20150902) + { + if (depth == 1) + { + if (node.Key == "TargetableUnit" || node.Key == "TargetableBuilding") + node.Key = "Targetable"; + else if (node.Key == "-TargetableUnit" || node.Key == "-TargetableBuilding") + node.Key = "-Targetable"; + } + else if (depth == 0) + { + // Split TargetableSubmarine into two Targetable traits + var targetableSubmarine = node.Value.Nodes.FirstOrDefault(n => n.Key == "TargetableSubmarine"); + if (targetableSubmarine != null) + { + node.Value.Nodes.RemoveAll(n => n.Key == "-Targetable"); + targetableSubmarine.Key = "Targetable"; + targetableSubmarine.Value.Nodes.Add(new MiniYamlNode("UpgradeTypes", "underwater")); + targetableSubmarine.Value.Nodes.Add(new MiniYamlNode("UpgradeMaxEnabledLevel", "0")); + var cloakedTargetTypes = targetableSubmarine.Value.Nodes.FirstOrDefault(n => n.Key == "CloakedTargetTypes"); + if (cloakedTargetTypes != null) + { + targetableSubmarine.Value.Nodes.Remove(cloakedTargetTypes); + cloakedTargetTypes.Key = "TargetTypes"; + } + else + cloakedTargetTypes = new MiniYamlNode("TargetTypes", ""); + node.Value.Nodes.Add(new MiniYamlNode("Targetable@UNDERWATER", "", new List { + cloakedTargetTypes, + new MiniYamlNode("UpgradeTypes", "underwater"), + new MiniYamlNode("UpgradeMinEnabledLevel", "1") + })); + } + + // Add `WhileCloakedUpgrades: underwater` to Cloak trait if `CloakTypes: Underwater` + var cloak = node.Value.Nodes.FirstOrDefault(n => (n.Key == "Cloak" || n.Key.StartsWith("Cloak@")) + && n.Value.Nodes.Any(p => p.Key == "CloakTypes" && p.Value.Value == "Underwater")); + if (cloak != null) + cloak.Value.Nodes.Add(new MiniYamlNode("WhileCloakedUpgrades", "underwater")); + + // Remove split traits if TargetableSubmarine was removed + var untargetableSubmarine = node.Value.Nodes.FirstOrDefault(n => n.Key == "-TargetableSubmarine"); + if (untargetableSubmarine != null) + { + untargetableSubmarine.Key = "-Targetable"; + node.Value.Nodes.Add(new MiniYamlNode("-Targetable@UNDERWATER", "")); + } + + // Split TargetableAircraft into two Targetable traits + var targetableAircraft = node.Value.Nodes.FirstOrDefault(n => n.Key == "TargetableAircraft"); + if (targetableAircraft != null) + { + node.Value.Nodes.RemoveAll(n => n.Key == "-Targetable"); + targetableAircraft.Key = "Targetable@AIRBORNE"; + targetableAircraft.Value.Nodes.Add(new MiniYamlNode("UpgradeTypes", "airborne")); + targetableAircraft.Value.Nodes.Add(new MiniYamlNode("UpgradeMinEnabledLevel", "1")); + var groundTargetTypes = targetableAircraft.Value.Nodes.FirstOrDefault(n => n.Key == "GroundedTargetTypes"); + if (groundTargetTypes != null) + { + targetableAircraft.Value.Nodes.Remove(groundTargetTypes); + groundTargetTypes.Key = "TargetTypes"; + } + else + groundTargetTypes = new MiniYamlNode("TargetTypes", ""); + node.Value.Nodes.Add(new MiniYamlNode("Targetable@GROUND", "", new List { + groundTargetTypes, + new MiniYamlNode("UpgradeTypes", "airborne"), + new MiniYamlNode("UpgradeMaxEnabledLevel", "0") + })); + } + + // Add `AirborneUpgrades: airborne` to Plane and Helicopter + var aircraft = node.Value.Nodes.FirstOrDefault(n => n.Key == "Plane" || n.Key == "Helicopter"); + if (aircraft != null) + aircraft.Value.Nodes.Add(new MiniYamlNode("AirborneUpgrades", "airborne")); + + // Remove split traits if TargetableAircraft was removed + var untargetableAircraft = node.Value.Nodes.FirstOrDefault(n => n.Key == "-TargetableAircraft"); + if (untargetableAircraft != null) + { + untargetableAircraft.Key = "-TargetableUnit@GROUND"; + node.Value.Nodes.Add(new MiniYamlNode("-TargetableUnit@AIRBORNE", "")); + } + } + } + UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1); } } diff --git a/OpenRA.Mods.Common/Warheads/Warhead.cs b/OpenRA.Mods.Common/Warheads/Warhead.cs index 42cbe57661..a471a97925 100644 --- a/OpenRA.Mods.Common/Warheads/Warhead.cs +++ b/OpenRA.Mods.Common/Warheads/Warhead.cs @@ -9,6 +9,7 @@ #endregion using System.Collections.Generic; +using System.Linq; using OpenRA.Traits; namespace OpenRA.Mods.Common.Warheads @@ -58,8 +59,8 @@ namespace OpenRA.Mods.Common.Warheads return false; // A target type is valid if it is in the valid targets list, and not in the invalid targets list. - var targetable = victim.TraitOrDefault(); - if (targetable == null || !IsValidTarget(targetable.TargetTypes)) + var targetable = victim.TraitsImplementing().Where(Exts.IsTraitEnabled); + if (!IsValidTarget(targetable.SelectMany(t => t.TargetTypes))) return false; return true; @@ -74,8 +75,7 @@ namespace OpenRA.Mods.Common.Warheads return false; // A target type is valid if it is in the valid targets list, and not in the invalid targets list. - var targetable = victim.Info.Traits.GetOrDefault(); - if (targetable == null || !IsValidTarget(targetable.GetTargetTypes())) + if (!IsValidTarget(victim.TargetTypes)) return false; return true; diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 37f7fb9e3f..d023e3e648 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -112,7 +112,6 @@ - diff --git a/OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs b/OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs index a53da96ba1..656ad379ac 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.RA.Traits if (order.ExtraData == 0 && order.TargetActor == null) return false; - ActorInfo ai; + IEnumerable targetTypes; if (order.ExtraData != 0) { @@ -74,13 +74,13 @@ namespace OpenRA.Mods.RA.Traits if (frozen == null) return false; - ai = frozen.Info; + targetTypes = frozen.TargetTypes; } else - ai = order.TargetActor.Info; + targetTypes = order.TargetActor.TraitsImplementing().Where(Exts.IsTraitEnabled) + .SelectMany(t => t.TargetTypes); - var i = ai.Traits.GetOrDefault(); - return i != null && i.GetTargetTypes().Intersect(Info.Types).Any(); + return targetTypes.Intersect(Info.Types).Any(); } public string VoicePhraseForOrder(Actor self, Order order) @@ -95,7 +95,8 @@ namespace OpenRA.Mods.RA.Traits return; var target = self.ResolveFrozenActorOrder(order, Color.Red); - if (target.Type != TargetType.Actor) + if (target.Type != TargetType.Actor + || target.Actor.TraitsImplementing().SelectMany(t => t.TargetTypes).Intersect(Info.Types).Any()) return; if (!order.Queued) diff --git a/OpenRA.Mods.RA/Traits/TargetableSubmarine.cs b/OpenRA.Mods.RA/Traits/TargetableSubmarine.cs deleted file mode 100644 index f90d1d79aa..0000000000 --- a/OpenRA.Mods.RA/Traits/TargetableSubmarine.cs +++ /dev/null @@ -1,42 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using OpenRA.Mods.Common.Traits; -using OpenRA.Traits; - -namespace OpenRA.Mods.RA.Traits -{ - public class TargetableSubmarineInfo : TargetableUnitInfo, Requires - { - public readonly string[] CloakedTargetTypes = { }; - - public override object Create(ActorInitializer init) { return new TargetableSubmarine(init.Self, this); } - } - - public class TargetableSubmarine : TargetableUnit - { - readonly TargetableSubmarineInfo info; - - public TargetableSubmarine(Actor self, TargetableSubmarineInfo info) - : base(self, info) - { - this.info = info; - } - - public override string[] TargetTypes - { - get - { - return IsTraitDisabled ? None - : (cloak.Cloaked ? info.CloakedTargetTypes : info.TargetTypes); - } - } - } -} diff --git a/mods/cnc/maps/nod05/map.yaml b/mods/cnc/maps/nod05/map.yaml index 95351d7f8c..7c202a329f 100644 --- a/mods/cnc/maps/nod05/map.yaml +++ b/mods/cnc/maps/nod05/map.yaml @@ -511,7 +511,7 @@ Rules: Buildable: Prerequisites: ~disabled A10: - TargetableUnit: + Targetable: Sequences: diff --git a/mods/cnc/rules/aircraft.yaml b/mods/cnc/rules/aircraft.yaml index d994101f9a..ee46c40815 100644 --- a/mods/cnc/rules/aircraft.yaml +++ b/mods/cnc/rules/aircraft.yaml @@ -16,6 +16,7 @@ TRAN: InitialFacing: 0 LandableTerrainTypes: Clear,Rough,Road,Ore,Beach,Tiberium,BlueTiberium AltitudeVelocity: 0c100 + AirborneUpgrades: airborne Health: HP: 90 Armor: @@ -56,6 +57,7 @@ HELI: RearmBuildings: hpad ROT: 4 Speed: 186 + AirborneUpgrades: airborne Health: HP: 125 Armor: @@ -107,6 +109,7 @@ ORCA: RearmBuildings: hpad ROT: 4 Speed: 186 + AirborneUpgrades: airborne Health: HP: 90 Armor: @@ -152,6 +155,7 @@ C17: ROT: 5 Speed: 326 Repulsable: False + AirborneUpgrades: airborne Health: HP: 25 Armor: @@ -188,6 +192,7 @@ A10: ROT: 4 Speed: 373 Repulsable: False + AirborneUpgrades: airborne Health: HP: 150 Armor: @@ -219,6 +224,7 @@ TRAN.Husk: Helicopter: ROT: 5 Speed: 140 + AirborneUpgrades: airborne RevealsShroud: Range: 8c0 Type: CenterPosition @@ -236,6 +242,7 @@ HELI.Husk: Helicopter: ROT: 4 Speed: 186 + AirborneUpgrades: airborne RevealsShroud: Range: 10c0 Type: CenterPosition @@ -251,6 +258,7 @@ ORCA.Husk: Helicopter: ROT: 4 Speed: 186 + AirborneUpgrades: airborne RevealsShroud: Range: 10c0 Type: CenterPosition diff --git a/mods/cnc/rules/civilian.yaml b/mods/cnc/rules/civilian.yaml index ce160cf1bd..73a453b466 100644 --- a/mods/cnc/rules/civilian.yaml +++ b/mods/cnc/rules/civilian.yaml @@ -374,7 +374,7 @@ BRIDGEHUT: CustomSelectionSize: CustomBounds: 48,48 BridgeHut: - TargetableBuilding: + Targetable: TargetTypes: BridgeHut, C4 C1: diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index f5ef357ec2..5f4966994c 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -64,7 +64,7 @@ SelectionDecorations: Selectable: Bounds: 24,24 - TargetableUnit: + Targetable: TargetTypes: Ground, Vehicle Repairable: Passenger: @@ -116,9 +116,14 @@ Inherits@2: ^GainsExperience AppearsOnRadar: UseLocation: yes - TargetableAircraft: + Targetable@GROUND: + TargetTypes: Ground, Vehicle + UpgradeTypes: airborne + UpgradeMaxEnabledLevel: 0 + Targetable@AIRBORNE: TargetTypes: Air - GroundedTargetTypes: Ground, Vehicle + UpgradeTypes: airborne + UpgradeMinEnabledLevel: 1 SelectionDecorations: Selectable: Bounds: 24,24 @@ -126,6 +131,7 @@ RepairBuildings: hpad RearmBuildings: LandWhenIdle: false + AirborneUpgrades: airborne HiddenUnderFog: Type: CenterPosition ActorLostNotification: @@ -172,7 +178,7 @@ SelectionDecorations: Selectable: Bounds: 12,17,0,-6 - TargetableUnit: + Targetable: TargetTypes: Ground, Infantry RenderSprites: QuantizeFacingsFromSequence: @@ -302,7 +308,7 @@ SelectionDecorations: Selectable: Bounds: 24,24 - TargetableUnit: + Targetable: TargetTypes: Ground HiddenUnderFog: QuantizeFacingsFromSequence: @@ -346,7 +352,7 @@ SelectionDecorations: Selectable: Bounds: 24,24 - TargetableUnit: + Targetable: TargetTypes: Ground AutoTarget: ScanRadius: 5 @@ -405,7 +411,7 @@ Water: 100 SelectionDecorations: Selectable: - TargetableUnit: + Targetable: TargetTypes: Ground, Water HiddenUnderFog: ActorLostNotification: @@ -421,7 +427,7 @@ SelectionDecorations: Selectable: Priority: 3 - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, Structure Armor: Type: Wood @@ -520,7 +526,7 @@ Tooltip: Name: Field -WithBuildingExplosion: - -TargetableBuilding: + -Targetable: -Demolishable: RenderSprites: Palette: terrain @@ -553,7 +559,7 @@ BuildSounds: hvydoor1.aud Adjacent: 7 TerrainTypes: Clear,Road - TargetableBuilding: + Targetable: TargetTypes: Ground, Wall Crushable: CrushClasses: wall @@ -662,7 +668,7 @@ AllowedTerrain: Clear, Rough, Road, Tiberium, BlueTiberium, Beach Burns: Interval: 2 - TargetableUnit: + Targetable: RequiresForceFire: yes TargetTypes: Ground, Husk Capturable: @@ -692,7 +698,7 @@ AlwaysVisible: Tooltip: Name: Bridge - TargetableBuilding: + Targetable: RequiresForceFire: yes TargetTypes: Ground, Water Health: diff --git a/mods/cnc/rules/vehicles.yaml b/mods/cnc/rules/vehicles.yaml index 4591d5b62b..31c0657e6c 100644 --- a/mods/cnc/rules/vehicles.yaml +++ b/mods/cnc/rules/vehicles.yaml @@ -528,7 +528,7 @@ STNK: AttackFrontal: AutoTarget: InitialStance: HoldFire - TargetableUnit: + Targetable: SpawnActorOnDeath: Actor: STNK.Husk -MustBeDestroyed: diff --git a/mods/d2k/rules/aircraft.yaml b/mods/d2k/rules/aircraft.yaml index 8ee9f578be..f2de72efea 100644 --- a/mods/d2k/rules/aircraft.yaml +++ b/mods/d2k/rules/aircraft.yaml @@ -20,6 +20,7 @@ carryall.reinforce: Repulsable: False LandAltitude: 100 LandWhenIdle: False + AirborneUpgrades: airborne SpawnActorOnDeath: Actor: carryall.husk Carryall: @@ -53,6 +54,7 @@ carryall.infantry: RepairBuildings: repair RearmBuildings: Repulsable: False + AirborneUpgrades: airborne Cargo: MaxWeight: 5 Types: Infantry @@ -77,6 +79,7 @@ frigate: RepairBuildings: repair RearmBuildings: Repulsable: False + AirborneUpgrades: airborne Health: HP: 500 -AppearsOnRadar: @@ -116,14 +119,20 @@ orni: Speed: 280 RepairBuildings: repair RearmBuildings: + AirborneUpgrades: airborne SpawnActorOnDeath: Actor: orni.husk SelectionDecorations: Selectable: Bounds: 32,32 - TargetableAircraft: + Targetable@GROUND: + TargetTypes: Ground, Vehicle + UpgradeTypes: airborne + UpgradeMaxEnabledLevel: 0 + Targetable@AIRBORNE: TargetTypes: Air - GroundedTargetTypes: Ground, Vehicle + UpgradeTypes: airborne + UpgradeMinEnabledLevel: 1 Voiced: VoiceSet: GenericVoice @@ -142,6 +151,7 @@ orni.bomber: RepairBuildings: repair RearmBuildings: Repulsable: False + AirborneUpgrades: airborne AmmoPool: Ammo: 5 Tooltip: @@ -161,6 +171,7 @@ orni.husk: Speed: 280 RepairBuildings: RearmBuildings: + AirborneUpgrades: airborne RenderSprites: Image: orni @@ -173,6 +184,7 @@ orni.bomber.husk: Speed: 350 RepairBuildings: RearmBuildings: + AirborneUpgrades: airborne RenderSprites: Image: orni @@ -185,6 +197,7 @@ carryall.husk: Speed: 210 RepairBuildings: RearmBuildings: + AirborneUpgrades: airborne RenderSprites: Image: carryall @@ -197,6 +210,7 @@ carryall.infantry.husk: Speed: 280 RepairBuildings: RearmBuildings: + AirborneUpgrades: airborne RenderSprites: Image: carryall diff --git a/mods/d2k/rules/arrakis.yaml b/mods/d2k/rules/arrakis.yaml index 2b442e5c74..8c68b70537 100644 --- a/mods/d2k/rules/arrakis.yaml +++ b/mods/d2k/rules/arrakis.yaml @@ -34,7 +34,7 @@ sandworm: Sand: 100 Dune: 100 Spice: 100 - TargetableUnit: + Targetable: TargetTypes: Ground WithFacingSpriteBody: WithAttackOverlay: diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index a00606d90d..d00a0e2d94 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -65,7 +65,7 @@ SelectionDecorations: Selectable: Bounds: 32,32 - TargetableUnit: + Targetable: TargetTypes: Ground, Vehicle, C4 Passenger: CargoType: Vehicle @@ -130,7 +130,7 @@ AllowedTerrain: Sand, Rock, Transition, Concrete, Spice, SpiceBlobs, Dune Burns: Interval: 4 - TargetableUnit: + Targetable: TargetTypes: Ground, Vehicle RequiresForceFire: yes Capturable: @@ -188,7 +188,7 @@ SelectionDecorations: Selectable: Bounds: 12,18,0,-6 - TargetableUnit: + Targetable: TargetTypes: Ground, Infantry UpgradeTypes: parachute UpgradeMaxEnabledLevel: 0 @@ -260,7 +260,7 @@ SelectionDecorations: Selectable: Priority: 2 - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, Structure Building: Dimensions: 1,1 diff --git a/mods/d2k/rules/misc.yaml b/mods/d2k/rules/misc.yaml index 785732fddf..c47a6a6244 100644 --- a/mods/d2k/rules/misc.yaml +++ b/mods/d2k/rules/misc.yaml @@ -133,6 +133,7 @@ waypoint: Inherits: carryall Helicopter: InitialFacing: 104 + AirborneUpgrades: airborne RenderSprites: Image: carryall Palette: colorpicker diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index d1fe88a150..ee1901cdc0 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -509,7 +509,7 @@ wall: NodeTypes: wall, turret LineBuildNode: Types: wall - TargetableBuilding: + Targetable: TargetTypes: Ground, Wall RenderSprites: WithWallSpriteBody: diff --git a/mods/ra/maps/allies-03a/map.yaml b/mods/ra/maps/allies-03a/map.yaml index 1db802e6ab..cf2c79583f 100644 --- a/mods/ra/maps/allies-03a/map.yaml +++ b/mods/ra/maps/allies-03a/map.yaml @@ -1382,21 +1382,19 @@ Rules: -ExternalCaptures: Captures: CaptureTypes: building - Cloak@JAIL: + Targetable: UpgradeTypes: jail - UpgradeMinEnabledLevel: 1 - InitialDelay: 0 - CloakDelay: 0 - Palette: + UpgradeMaxEnabledLevel: 0 + Targetable@PRISONER: + TargetTypes: Prisoner RenderSprites: Image: E6 MEDI: - Cloak@JAIL: + Targetable: UpgradeTypes: jail - UpgradeMinEnabledLevel: 1 - InitialDelay: 0 - CloakDelay: 0 - Palette: + UpgradeMaxEnabledLevel: 0 + Targetable@PRISONER: + TargetTypes: Prisoner E7.noautotarget: Inherits: E7 AutoTarget: @@ -1544,6 +1542,9 @@ Sequences: VoxelSequences: Weapons: + BarrelExplode: + Warhead@1Dam: + ValidTargets: Ground, Prisoner Voices: diff --git a/mods/ra/maps/allies-03b/map.yaml b/mods/ra/maps/allies-03b/map.yaml index 04745b5ce6..707a184049 100644 --- a/mods/ra/maps/allies-03b/map.yaml +++ b/mods/ra/maps/allies-03b/map.yaml @@ -1278,21 +1278,19 @@ Rules: Captures: CaptureTypes: building WithInfantryBody: - Cloak@JAIL: + Targetable: UpgradeTypes: jail - UpgradeMinEnabledLevel: 1 - InitialDelay: 0 - CloakDelay: 0 - Palette: + UpgradeMaxEnabledLevel: 0 + Targetable@PRISONER: + TargetTypes: Prisoner RenderSprites: Image: E6 MEDI: - Cloak@JAIL: + Targetable: UpgradeTypes: jail - UpgradeMinEnabledLevel: 1 - InitialDelay: 0 - CloakDelay: 0 - Palette: + UpgradeMaxEnabledLevel: 0 + Targetable@PRISONER: + TargetTypes: Prisoner E7.noautotarget: Inherits: E7 AutoTarget: @@ -1385,7 +1383,7 @@ Rules: -Selectable: -Demolishable: -Huntable: - -TargetableUnit: + -Targetable: -Armament: -WithMuzzleFlash: Cargo: @@ -1432,6 +1430,9 @@ Weapons: FireballLauncher: Projectile: High: True + BarrelExplode: + Warhead@1Dam: + ValidTargets: Ground, Prisoner Voices: diff --git a/mods/ra/maps/allies-05a/map.yaml b/mods/ra/maps/allies-05a/map.yaml index 48e58ce393..6664e0ae5a 100644 --- a/mods/ra/maps/allies-05a/map.yaml +++ b/mods/ra/maps/allies-05a/map.yaml @@ -1651,7 +1651,7 @@ Rules: Prerequisites: ~disabled LST: -Selectable: - TargetableUnit: + Targetable: TargetTypes: Ground, Water Tooltip: GenericVisibility: Enemy @@ -1668,8 +1668,8 @@ Rules: Range: 4c0 Tooltip: ShowOwnerRow: false - TargetableAircraft: - GroundedTargetTypes: Ground + Targetable@GROUND: + TargetTypes: Ground TRAN.IN: Inherits: TRAN RenderSprites: @@ -1696,13 +1696,13 @@ Rules: ShowOwnerRow: false WEAP: -InfiltrateForSupportPower: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, Mission Objectives MISS: Tooltip: Name: Prison ShowOwnerRow: False - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, Mission Objectives E7.noautotarget: Inherits: E7 diff --git a/mods/ra/maps/koth-hopes-anchor/map.yaml b/mods/ra/maps/koth-hopes-anchor/map.yaml index d413d0e478..50174a9578 100644 --- a/mods/ra/maps/koth-hopes-anchor/map.yaml +++ b/mods/ra/maps/koth-hopes-anchor/map.yaml @@ -644,7 +644,7 @@ Rules: DamageMultiplier@INVULNERABLE: Modifier: 0 -Selectable: - -TargetableBuilding: + -Targetable: Player: StrategicVictoryConditions: TicksToHold: 3000 diff --git a/mods/ra/maps/monster-tank-madness/map.yaml b/mods/ra/maps/monster-tank-madness/map.yaml index 011807840e..949cf039f8 100644 --- a/mods/ra/maps/monster-tank-madness/map.yaml +++ b/mods/ra/maps/monster-tank-madness/map.yaml @@ -2241,7 +2241,7 @@ Rules: RenderSprites: Image: DOME -InfiltrateForExploration: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, MissionObjective SPY: Infiltrates: diff --git a/mods/ra/maps/survival01/map.yaml b/mods/ra/maps/survival01/map.yaml index 9740347103..5cabc1f8bb 100644 --- a/mods/ra/maps/survival01/map.yaml +++ b/mods/ra/maps/survival01/map.yaml @@ -1282,7 +1282,7 @@ Rules: Power: Amount: 0 -Selectable: - -TargetableBuilding: + -Targetable: -GivesBuildableArea: -Huntable: RenderSprites: diff --git a/mods/ra/rules/aircraft.yaml b/mods/ra/rules/aircraft.yaml index 8fd804704b..5fb48bd807 100644 --- a/mods/ra/rules/aircraft.yaml +++ b/mods/ra/rules/aircraft.yaml @@ -12,6 +12,7 @@ BADR: Speed: 149 Repulsable: False MaximumPitch: 56 + AirborneUpgrades: airborne Cargo: MaxWeight: 10 -Selectable: @@ -49,6 +50,7 @@ BADR.Bomber: Speed: 149 Repulsable: False MaximumPitch: 56 + AirborneUpgrades: airborne AmmoPool: Ammo: 7 -Selectable: @@ -106,6 +108,7 @@ MIG: RearmBuildings: afld RepulsionSpeed: 40 MaximumPitch: 56 + AirborneUpgrades: airborne AutoTarget: TargetWhenIdle: false TargetWhenDamaged: false @@ -167,6 +170,7 @@ YAK: Speed: 178 RepulsionSpeed: 40 MaximumPitch: 56 + AirborneUpgrades: airborne AutoTarget: TargetWhenIdle: false TargetWhenDamaged: false @@ -215,6 +219,7 @@ TRAN: Speed: 112 LandableTerrainTypes: Clear,Rough,Road,Ore,Beach AltitudeVelocity: 0c100 + AirborneUpgrades: airborne WithRotor@PRIMARY: Offset: -597,0,341 Sequence: rotor2 @@ -261,6 +266,7 @@ HELI: InitialFacing: 20 ROT: 4 Speed: 149 + AirborneUpgrades: airborne AutoTarget: InitialStance: HoldFire WithRotor: @@ -312,6 +318,7 @@ HIND: InitialFacing: 20 ROT: 4 Speed: 112 + AirborneUpgrades: airborne AutoTarget: InitialStance: HoldFire WithRotor: @@ -341,10 +348,11 @@ U2: Speed: 373 Repulsable: False MaximumPitch: 56 + AirborneUpgrades: airborne AttackBomber: -Selectable: -Voiced: - -TargetableAircraft: + -Targetable@AIRBORNE: -GainsExperience: Contrail@1: Offset: -725,683,0 diff --git a/mods/ra/rules/civilian.yaml b/mods/ra/rules/civilian.yaml index d9b74437af..e49ce53d38 100644 --- a/mods/ra/rules/civilian.yaml +++ b/mods/ra/rules/civilian.yaml @@ -242,7 +242,7 @@ V19.Husk: Sequence: fire-loop -Health: -Selectable: - -TargetableBuilding: + -Targetable: -Demolishable: BARL: @@ -259,7 +259,7 @@ BARL: AutoTargetIgnore: Armor: Type: None - TargetableBuilding: + Targetable: TargetTypes: Ground, DemoTruck -ShakeOnDeath: -SoundOnDamageTransition: @@ -279,7 +279,7 @@ BRL3: AutoTargetIgnore: Armor: Type: None - TargetableBuilding: + Targetable: TargetTypes: Ground, DemoTruck -ShakeOnDeath: -SoundOnDamageTransition: @@ -497,7 +497,7 @@ BRIDGEHUT: CustomSelectionSize: CustomBounds: 48,48 BridgeHut: - TargetableBuilding: + Targetable: TargetTypes: BridgeHut, C4 BRIDGEHUT.small: @@ -508,7 +508,7 @@ BRIDGEHUT.small: CustomSelectionSize: CustomBounds: 24,24 BridgeHut: - TargetableBuilding: + Targetable: TargetTypes: BridgeHut, C4 V20: diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 1d39ccdaea..98159c7e57 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -77,7 +77,7 @@ SelectionDecorations: Selectable: Bounds: 24, 24 - TargetableUnit: + Targetable: TargetTypes: Ground, Repair, Vehicle UpgradeTypes: parachute UpgradeMaxEnabledLevel: 0 @@ -149,7 +149,7 @@ Ore: 70 Gems: 70 Beach: 70 - TargetableUnit: + Targetable: TargetTypes: Ground, C4, Repair, Tank ProximityCaptor: Types: Tank @@ -181,7 +181,7 @@ SelectionDecorations: Selectable: Bounds: 12,18,0,-8 - TargetableUnit: + Targetable: TargetTypes: Ground, Infantry, Disguise UpgradeTypes: parachute UpgradeMaxEnabledLevel: 0 @@ -299,7 +299,7 @@ SelectionDecorations: Selectable: Bounds: 24,24 - TargetableUnit: + Targetable: TargetTypes: Ground, Water, Repair HiddenUnderFog: AttackMove: @@ -339,9 +339,14 @@ SelectionDecorations: Selectable: Bounds: 24,24 - TargetableAircraft: + Targetable@GROUND: + TargetTypes: Ground, Repair, Vehicle + UpgradeTypes: airborne + UpgradeMaxEnabledLevel: 0 + Targetable@AIRBORNE: TargetTypes: Air - GroundedTargetTypes: Ground, Repair, Vehicle + UpgradeTypes: airborne + UpgradeMinEnabledLevel: 1 HiddenUnderFog: Type: CenterPosition AttackMove: @@ -385,7 +390,7 @@ SelectionDecorations: Selectable: Priority: 3 - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure Building: Dimensions: 1,1 @@ -433,7 +438,7 @@ ^Defense: Inherits: ^Building - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, Defense MustBeDestroyed: RequiredForShortGame: false @@ -462,7 +467,7 @@ NodeTypes: wall LineBuildNode: Types: wall - TargetableBuilding: + Targetable: TargetTypes: Ground, DetonateAttack, Wall RenderSprites: Palette: effect @@ -518,7 +523,7 @@ AutoTargetIgnore: Armor: Type: Light - TargetableBuilding: + Targetable: TargetTypes: Ground, DetonateAttack ^CivBuilding: @@ -533,7 +538,7 @@ -Selectable: Tooltip: Name: Field - -TargetableBuilding: + -Targetable: -Demolishable: ProximityCaptor: Types: CivilianField @@ -598,7 +603,7 @@ TransformOnCapture: ForceHealthPercentage: 25 DisabledOverlay: - TargetableUnit: + Targetable: TargetTypes: Ground, Husk RequiresForceFire: true Chronoshiftable: @@ -625,7 +630,7 @@ AlwaysVisible: Tooltip: Name: Bridge - TargetableBuilding: + Targetable: TargetTypes: Ground, Water RequiresForceFire: true Building: diff --git a/mods/ra/rules/fakes.yaml b/mods/ra/rules/fakes.yaml index ee8d3226a6..03156e202c 100644 --- a/mods/ra/rules/fakes.yaml +++ b/mods/ra/rules/fakes.yaml @@ -57,7 +57,7 @@ SYRF: GenericName: Shipyard GenericVisibility: Enemy GenericStancePrefix: False - TargetableBuilding: + Targetable: TargetTypes: Ground, Water Building: Footprint: xxx xxx xxx @@ -73,7 +73,7 @@ SYRF: SPEF: Inherits: ^FakeBuilding - TargetableBuilding: + Targetable: TargetTypes: Ground, Water Buildable: BuildPaletteOrder: 910 diff --git a/mods/ra/rules/husks.yaml b/mods/ra/rules/husks.yaml index c318134b13..7053e6a84e 100644 --- a/mods/ra/rules/husks.yaml +++ b/mods/ra/rules/husks.yaml @@ -88,6 +88,7 @@ TRAN.Husk: Helicopter: ROT: 4 Speed: 149 + AirborneUpgrades: airborne WithRotor@PRIMARY: Offset: -597,0,341 WithRotor@SECONDARY: @@ -119,6 +120,7 @@ BADR.Husk: Plane: ROT: 5 Speed: 149 + AirborneUpgrades: airborne SmokeTrailWhenDamaged@0: Offset: -432,560,0 Interval: 2 @@ -141,6 +143,7 @@ MIG.Husk: Plane: ROT: 5 Speed: 186 + AirborneUpgrades: airborne SmokeTrailWhenDamaged: Offset: -853,0,171 Interval: 2 @@ -160,6 +163,7 @@ YAK.Husk: Plane: ROT: 5 Speed: 149 + AirborneUpgrades: airborne SmokeTrailWhenDamaged: Offset: -853,0,0 Interval: 2 @@ -177,6 +181,7 @@ HELI.Husk: Helicopter: ROT: 4 Speed: 149 + AirborneUpgrades: airborne WithRotor: Offset: 0,0,85 SmokeTrailWhenDamaged: @@ -195,6 +200,7 @@ HIND.Husk: Helicopter: ROT: 4 Speed: 112 + AirborneUpgrades: airborne WithRotor: SmokeTrailWhenDamaged: Offset: -427,0,0 @@ -210,6 +216,7 @@ U2.Husk: Plane: ROT: 7 Speed: 373 + AirborneUpgrades: airborne Contrail@1: Offset: -725,683,0 Contrail@2: diff --git a/mods/ra/rules/infantry.yaml b/mods/ra/rules/infantry.yaml index 3e146ea846..bb368b3588 100644 --- a/mods/ra/rules/infantry.yaml +++ b/mods/ra/rules/infantry.yaml @@ -32,7 +32,7 @@ DOG: Voice: Attack AttackMove: Voice: Move - TargetableUnit: + Targetable: TargetTypes: Ground, Infantry WithInfantryBody: AttackSequence: shoot @@ -587,7 +587,7 @@ Ant: AttackSequence: bite Armament: Weapon: mandible - TargetableUnit: + Targetable: TargetTypes: Ground, Infantry WithDeathAnimation: UseDeathTypeSuffix: false diff --git a/mods/ra/rules/misc.yaml b/mods/ra/rules/misc.yaml index ecf82012b5..29306efdf3 100644 --- a/mods/ra/rules/misc.yaml +++ b/mods/ra/rules/misc.yaml @@ -22,7 +22,7 @@ MINP: Name: Mine ProximityCaptor: Types: Mine - TargetableUnit: + Targetable: TargetTypes: Ground BodyOrientation: QuantizedFacings: 1 @@ -53,7 +53,7 @@ MINV: Name: Mine ProximityCaptor: Types: Mine - TargetableUnit: + Targetable: TargetTypes: Ground BodyOrientation: QuantizedFacings: 1 @@ -431,5 +431,5 @@ CTFLAG: DamageMultiplier@INVULNERABLE: Modifier: 0 -Selectable: - -TargetableBuilding: + -Targetable: diff --git a/mods/ra/rules/ships.yaml b/mods/ra/rules/ships.yaml index 88a30d1686..52dd8c4666 100644 --- a/mods/ra/rules/ships.yaml +++ b/mods/ra/rules/ships.yaml @@ -19,16 +19,21 @@ SS: Speed: 71 RevealsShroud: Range: 6c0 - -TargetableUnit: - TargetableSubmarine: + Targetable: TargetTypes: Ground, Water, Repair - CloakedTargetTypes: Underwater, Repair + UpgradeTypes: underwater + UpgradeMaxEnabledLevel: 0 + Targetable@UNDERWATER: + TargetTypes: Underwater, Repair + UpgradeTypes: underwater + UpgradeMinEnabledLevel: 1 Cloak: CloakTypes: Underwater InitialDelay: 0 CloakDelay: 50 CloakSound: subshow1.aud UncloakSound: subshow1.aud + WhileCloakedUpgrades: underwater Armament: Weapon: TorpTube LocalOffset: 0,-171,0, 0,171,0 @@ -68,16 +73,21 @@ MSUB: Speed: 42 RevealsShroud: Range: 6c0 - -TargetableUnit: - TargetableSubmarine: + Targetable: TargetTypes: Ground, Water, Repair - CloakedTargetTypes: Underwater, Repair + UpgradeTypes: underwater + UpgradeMaxEnabledLevel: 0 + Targetable@UNDERWATER: + TargetTypes: Underwater, Repair + UpgradeTypes: underwater + UpgradeMinEnabledLevel: 1 Cloak: CloakTypes: Underwater InitialDelay: 0 CloakDelay: 100 CloakSound: subshow1.aud UncloakSound: subshow1.aud + WhileCloakedUpgrades: underwater Armament: Weapon: SubMissile LocalOffset: 0,-171,0, 0,171,0 diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 851f536b3c..27c6662fbd 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -100,7 +100,7 @@ SPEN: Queue: Building BuildPaletteOrder: 50 Prerequisites: anypower, ~structures.soviet, ~techlevel.low - TargetableBuilding: + Targetable: TargetTypes: Ground, Water, C4, DetonateAttack, SpyInfiltrate Building: Footprint: xxx xxx xxx @@ -181,7 +181,7 @@ SYRD: Tooltip: Name: Shipyard Description: Produces and repairs ships\nand transports. - TargetableBuilding: + Targetable: TargetTypes: Ground, Water, C4, DetonateAttack, SpyInfiltrate Building: Footprint: xxx xxx xxx @@ -476,7 +476,7 @@ DOME: Building: Footprint: xx xx Dimensions: 2,2 - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, SpyInfiltrate RequiresPower: CanPowerDown: @@ -823,7 +823,7 @@ WEAP: Power: Amount: -30 ProvidesPrerequisite@buildingname: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, SpyInfiltrate InfiltrateForSupportPower: Proxy: vehicles.upgraded @@ -920,7 +920,7 @@ PROC: Bounds: 72,50,0,12 SelectionDecorations: VisualBounds: 72,70,0,-2 - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, SpyInfiltrate Health: HP: 900 @@ -1050,7 +1050,7 @@ HPAD: RequiresPrerequisites: structures.germany Prerequisite: aircraft.germany ProvidesPrerequisite@buildingname: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, SpyInfiltrate InfiltrateForSupportPower: Proxy: aircraft.upgraded @@ -1159,7 +1159,7 @@ AFLD: Power: Amount: -20 ProvidesPrerequisite@buildingname: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, SpyInfiltrate InfiltrateForSupportPower: Proxy: aircraft.upgraded @@ -1191,7 +1191,7 @@ POWR: Amount: 100 InfiltrateForPowerOutage: AffectedByPowerOutage: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, SpyInfiltrate ScalePowerWithHealth: DisabledOverlay: @@ -1232,7 +1232,7 @@ APWR: Amount: 200 InfiltrateForPowerOutage: AffectedByPowerOutage: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, SpyInfiltrate ScalePowerWithHealth: DisabledOverlay: @@ -1332,7 +1332,7 @@ BARR: ProvidesPrerequisite@buildingname: InfiltrateForSupportPower: Proxy: barracks.upgraded - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, SpyInfiltrate KENN: @@ -1439,7 +1439,7 @@ TENT: ProvidesPrerequisite@buildingname: InfiltrateForSupportPower: Proxy: barracks.upgraded - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, Structure, SpyInfiltrate FIX: diff --git a/mods/ra/rules/vehicles.yaml b/mods/ra/rules/vehicles.yaml index e5c7946ab8..5d28012b62 100644 --- a/mods/ra/rules/vehicles.yaml +++ b/mods/ra/rules/vehicles.yaml @@ -699,7 +699,7 @@ QTNK: VisualBounds: 44,38,0,-4 MadTank: -EjectOnDeath: - TargetableUnit: + Targetable: TargetTypes: Ground, MADTank, Repair STNK: diff --git a/mods/ts/rules/aircraft.yaml b/mods/ts/rules/aircraft.yaml index 846b931d68..6cdcc566d2 100644 --- a/mods/ts/rules/aircraft.yaml +++ b/mods/ts/rules/aircraft.yaml @@ -10,6 +10,7 @@ DPOD: Speed: 149 InitialFacing: 0 LandableTerrainTypes: Clear + AirborneUpgrades: airborne Health: HP: 60 Armor: @@ -47,6 +48,7 @@ DSHP: LandableTerrainTypes: Clear TakeoffSound: dropup1.aud LandingSound: dropdwn1.aud + AirborneUpgrades: airborne Health: HP: 200 Armor: @@ -78,6 +80,7 @@ ORCA: RearmBuildings: gahpad, nahpad ROT: 5 Speed: 186 + AirborneUpgrades: airborne Health: HP: 200 Armor: @@ -117,6 +120,7 @@ ORCAB: MaximumPitch: 120 ROT: 3 Speed: 96 + AirborneUpgrades: airborne Health: HP: 260 Armor: @@ -159,6 +163,7 @@ ORCATRAN: LandableTerrainTypes: Clear TakeoffSound: dropup1.aud LandingSound: dropdwn1.aud + AirborneUpgrades: airborne Health: HP: 200 Armor: @@ -193,6 +198,7 @@ TRNSPORT: TakeoffSound: dropup1.aud LandingSound: dropdwn1.aud AltitudeVelocity: 64 + AirborneUpgrades: airborne Health: HP: 175 Armor: @@ -224,6 +230,7 @@ SCRIN: MaximumPitch: 90 ROT: 3 Speed: 168 + AirborneUpgrades: airborne Health: HP: 280 Armor: @@ -262,6 +269,7 @@ APACHE: RearmBuildings: gahpad, nahpad ROT: 5 Speed: 130 + AirborneUpgrades: airborne Health: HP: 225 Armor: diff --git a/mods/ts/rules/civilian-infantry.yaml b/mods/ts/rules/civilian-infantry.yaml index 3227e19cb5..6affd0532c 100644 --- a/mods/ts/rules/civilian-infantry.yaml +++ b/mods/ts/rules/civilian-infantry.yaml @@ -225,7 +225,7 @@ DOGGIE: Speed: 113 Voiced: VoiceSet: Fiend - TargetableUnit: + Targetable: TargetTypes: Ground Armament: Weapon: FiendShard diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index 7be22e3350..921cc974df 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -71,7 +71,7 @@ Palette: pips Selectable: Priority: 3 - TargetableBuilding: + Targetable: TargetTypes: Ground, Building, C4 Building: Dimensions: 1,1 @@ -187,7 +187,7 @@ NodeTypes: wall LineBuildNode: Types: wall - TargetableBuilding: + Targetable: TargetTypes: Ground, Wall, C4 RenderSprites: AutoSelectionSize: @@ -252,7 +252,7 @@ Bounds: 14,23,-1,-9 Voiced: VoiceSet: Infantry - TargetableUnit: + Targetable: TargetTypes: Ground, Infantry QuantizeFacingsFromSequence: Sequence: stand @@ -378,7 +378,7 @@ Palette: pips Voiced: VoiceSet: Vehicle - TargetableUnit: + Targetable: TargetTypes: Ground, Vehicle, Repair Repairable: RepairBuildings: gadept @@ -453,9 +453,14 @@ DrawLineToTarget: AppearsOnRadar: UseLocation: yes - TargetableAircraft: + Targetable@GROUND: + TargetTypes: Ground + UpgradeTypes: airborne + UpgradeMaxEnabledLevel: 0 + Targetable@AIRBORNE: TargetTypes: Air - GroundedTargetTypes: Ground + UpgradeTypes: airborne + UpgradeMinEnabledLevel: 1 Selectable: SelectionDecorations: Palette: pips @@ -484,6 +489,7 @@ LandWhenIdle: no CruiseAltitude: 2048 Voice: Move + AirborneUpgrades: airborne ^Plane: Inherits: ^Aircraft @@ -493,6 +499,7 @@ LandWhenIdle: no CruiseAltitude: 2560 Voice: Move + AirborneUpgrades: airborne ReturnOnIdle: ^Viceroid: @@ -520,7 +527,7 @@ Palette: pips Selectable: Bounds: 26,26,0,-3 - TargetableUnit: + Targetable: TargetTypes: Ground AttackMove: HiddenUnderFog: @@ -651,7 +658,7 @@ SelectionDecorations: Palette: pips Selectable: - TargetableBuilding: + Targetable: TargetTypes: Ground, Repair Guardable: HiddenUnderFog: @@ -681,7 +688,7 @@ Palette: pips Voiced: VoiceSet: Vehicle - TargetableUnit: + Targetable: TargetTypes: Ground, Vehicle Passenger: CargoType: Infantry diff --git a/mods/ts/rules/gdi-structures.yaml b/mods/ts/rules/gdi-structures.yaml index 19c49c311a..259074a9e4 100644 --- a/mods/ts/rules/gdi-structures.yaml +++ b/mods/ts/rules/gdi-structures.yaml @@ -30,7 +30,7 @@ GAPOWR: Amount: 100 InfiltrateForPowerOutage: AffectedByPowerOutage: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, SpyInfiltrate ScalePowerWithHealth: DisabledOverlay: @@ -288,7 +288,7 @@ GARADR: WithIdleOverlay@DISH: Sequence: idle-dish PauseOnLowPower: yes - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, SpyInfiltrate Power: Amount: -50 diff --git a/mods/ts/rules/nod-structures.yaml b/mods/ts/rules/nod-structures.yaml index bf0088f44c..7ed141a510 100644 --- a/mods/ts/rules/nod-structures.yaml +++ b/mods/ts/rules/nod-structures.yaml @@ -28,7 +28,7 @@ NAPOWR: Amount: 100 InfiltrateForPowerOutage: AffectedByPowerOutage: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, SpyInfiltrate ScalePowerWithHealth: DisabledOverlay: @@ -65,7 +65,7 @@ NAAPWR: Amount: 200 InfiltrateForPowerOutage: AffectedByPowerOutage: - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, DetonateAttack, SpyInfiltrate ScalePowerWithHealth: DisabledOverlay: @@ -243,7 +243,7 @@ NARADR: WithIdleOverlay@DISH: Sequence: idle-dish PauseOnLowPower: yes - TargetableBuilding: + Targetable: TargetTypes: Ground, C4, SpyInfiltrate Power: Amount: -50