diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 2463f7b8d6..4a421431f5 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -106,6 +106,7 @@ + diff --git a/OpenRA.Mods.RA/ProximityCaptor.cs b/OpenRA.Mods.RA/ProximityCaptor.cs new file mode 100644 index 0000000000..020106f5ba --- /dev/null +++ b/OpenRA.Mods.RA/ProximityCaptor.cs @@ -0,0 +1,48 @@ +#region Copyright & License Information +/* + * Copyright 2007-2010 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 LICENSE. + */ +#endregion + +using System.Linq; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + public class ProximityCaptorInfo : ITraitInfo + { + public readonly string[] Types = {}; + public object Create(ActorInitializer init) { return new ProximityCaptor(this); } + } + + public class ProximityCaptor + { + public readonly ProximityCaptorInfo Info; + + public string[] Types; + + [Sync] + public int Hash { get { return string.Join(",", Types).GetHashCode(); } } + + public ProximityCaptor(ProximityCaptorInfo info) + { + Info = info; + + Types = info.Types.Select(t => t.ToLowerInvariant()).OrderBy(t => t).ToArray(); + } + + public bool HasAny(string[] typesList) + { + return typesList.Select(t => t.ToLowerInvariant()).Any(flag => Types.Contains(flag)); + } + + public bool HasAll(string[] typesList) + { + return typesList.Select(t => t.ToLowerInvariant()).All(flag => Types.Contains(flag)); + } + } +} diff --git a/OpenRA.Mods.RA/ProximityCapturable.cs b/OpenRA.Mods.RA/ProximityCapturable.cs index 7b7fd37c51..55b2f6c537 100644 --- a/OpenRA.Mods.RA/ProximityCapturable.cs +++ b/OpenRA.Mods.RA/ProximityCapturable.cs @@ -9,6 +9,7 @@ namespace OpenRA.Mods.RA public readonly bool Permanent = false; public readonly int Range = 5; public readonly bool MustBeClear = false; + public readonly string[] CaptorTypes = {"Vehicle", "Tank", "Infantry"}; public object Create(ActorInitializer init) { return new ProximityCapturable(init.self, this); } } @@ -35,6 +36,13 @@ namespace OpenRA.Mods.RA [Sync] public bool MustBeClear = false; + public string[] CaptorTypes = {}; + + [Sync] + public int ActorTypesHash + { + get { return string.Join(",", CaptorTypes).GetHashCode(); } + } public Actor Self; public ProximityCapturable(Actor self, ProximityCapturableInfo info) @@ -45,6 +53,7 @@ namespace OpenRA.Mods.RA MustBeClear = info.MustBeClear; Self = self; OriginalOwner = self.Owner; + CaptorTypes = info.CaptorTypes; } public void Tick(Actor self) @@ -55,11 +64,11 @@ namespace OpenRA.Mods.RA if (!Captured) { - var captor = GetInRange(self, OriginalOwner, Range); + var captor = GetInRange(self, OriginalOwner, Range, CaptorTypes); if (captor != null) { - if (MustBeClear && !IsClear(self, captor.Owner, Range, OriginalOwner)) return; + if (MustBeClear && !IsClear(self, captor.Owner, Range, OriginalOwner, CaptorTypes)) return; ChangeOwnership(self, captor, OriginalOwner); } @@ -68,7 +77,7 @@ namespace OpenRA.Mods.RA } // if the area must be clear, and there is more than 1 player nearby => return ownership to default - if (MustBeClear && !IsClear(self, Owner, Range, OriginalOwner)) + if (MustBeClear && !IsClear(self, Owner, Range, OriginalOwner, CaptorTypes)) { // Revert Ownership ChangeOwnership(self, Owner, OriginalOwner); @@ -76,10 +85,10 @@ namespace OpenRA.Mods.RA } // See if the 'temporary' owner still is in range - if (!IsStillInRange(self, self.Owner, Range)) + if (!IsStillInRange(self, self.Owner, Range, CaptorTypes)) { // no.. So find a new one - var captor = GetInRange(self, OriginalOwner, Range); + var captor = GetInRange(self, OriginalOwner, Range, CaptorTypes); if (captor != null) // got one { @@ -140,26 +149,29 @@ namespace OpenRA.Mods.RA b.Stances[a] == Stance.Ally; } - public static bool IsClear(Actor self, Player currentOwner, int range, Player originalOwner) + public static bool IsClear(Actor self, Player currentOwner, int range, Player originalOwner, string[] actorTypes) { var unitsInRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range); - + return unitsInRange.Where(a => !a.Destroyed && a.IsInWorld && a != self && !a.Owner.NonCombatant && a.Owner != originalOwner) - .Where(a => a.Owner != currentOwner).All(a => AreMutualAllies(a.Owner, currentOwner)); + .Where(a => a.Owner != currentOwner) + .Where(a => actorTypes.Length == 0 || (a.HasTrait() && a.Trait().HasAny(actorTypes))) + .All(a => AreMutualAllies(a.Owner, currentOwner)); } // TODO exclude other NeutralActor that arent permanent - public static bool IsStillInRange(Actor self, Player currentOwner, int range) + public static bool IsStillInRange(Actor self, Player currentOwner, int range, string[] actorTypes) { var unitsInRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range); return unitsInRange .Where(a => a.Owner == currentOwner && !a.Destroyed && a.IsInWorld && a != self) + .Where(a => actorTypes.Length == 0 || (a.HasTrait() && a.Trait().HasAny(actorTypes))) .Any(); } // TODO exclude other NeutralActor that arent permanent - public static Actor GetInRange(Actor self, Player originalOwner, int range) + public static Actor GetInRange(Actor self, Player originalOwner, int range, string[] actorTypes) { var unitsInRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range); @@ -167,11 +179,12 @@ namespace OpenRA.Mods.RA .Where(a => a.Owner != originalOwner && !a.Destroyed && a.IsInWorld && a != self) .Where(a => !a.Owner.PlayerRef.OwnsWorld) .Where(a => !a.Owner.PlayerRef.NonCombatant) + .Where(a => actorTypes.Length == 0 || (a.HasTrait() && a.Trait().HasAny(actorTypes))) .OrderBy(a => (a.CenterLocation - self.CenterLocation).LengthSquared) .FirstOrDefault(); } - public static int CountPlayersNear(Actor self, Player ignoreMe, int range) + public static int CountPlayersNear(Actor self, Player ignoreMe, int range, string[] actorTypes) { var unitsInRange = self.World.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range); @@ -179,6 +192,7 @@ namespace OpenRA.Mods.RA .Where(a => a.Owner != ignoreMe && !a.Destroyed && a.IsInWorld && a != self) .Where(a => !a.Owner.PlayerRef.OwnsWorld) .Where(a => !a.Owner.PlayerRef.NonCombatant) + .Where(a =>actorTypes.Length == 0 || ( a.HasTrait() && a.Trait().HasAny(actorTypes))) .Select(a => a.Owner) .Distinct() .Count(); diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index b9ef110dcd..46b467f237 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -28,6 +28,8 @@ ActorLostNotification: Notification: unitlost.aud AttackMove: + ProximityCaptor: + Types:Vehicle ^Tank: AppearsOnRadar: @@ -59,6 +61,8 @@ ActorLostNotification: Notification: unitlost.aud AttackMove: + ProximityCaptor: + Types:Tank ^Helicopter: AppearsOnRadar: @@ -79,6 +83,8 @@ DrawLineToTarget: ActorLostNotification: Notification: unitlost.aud + ProximityCaptor: + Types:Helicopter ^Infantry: AppearsOnRadar: @@ -118,6 +124,8 @@ DrawLineToTarget: ActorLostNotification: Notification: unitlost.aud + ProximityCaptor: + Types:Infantry ^CivInfantry: Inherits: ^Infantry @@ -141,6 +149,8 @@ # ActorLostNotification: # Notification: civdead1.aud # NotifyAll: true + ProximityCaptor: + Types:CivilianInfantry ^Plane: AppearsOnRadar: @@ -155,6 +165,8 @@ DrawLineToTarget: ActorLostNotification: Notification: unitlost.aud + ProximityCaptor: + Types:Plane ^Ship: AppearsOnRadar: @@ -173,6 +185,8 @@ ActorLostNotification: Notification: unitlost.aud AttackMove: + ProximityCaptor: + Types:Ship ^Building: AppearsOnRadar: @@ -211,6 +225,8 @@ EditorAppearance: RelativeToTopLeft: yes ShakeOnDeath: + ProximityCaptor: + Types:Building ^CivBuilding: Inherits: ^Building @@ -226,6 +242,8 @@ # -FrozenUnderFog: Tooltip: Name: Civilian Building + ProximityCaptor: + Types:CivilianBuilding ^CivField: Inherits: ^CivBuilding @@ -237,6 +255,9 @@ RenderBuilding: OverrideTileset: DESERT OverrideImage: v23 + -ProximityCaptor: + ProximityCaptor: + Types:CivilianField ^Wall: AppearsOnRadar: @@ -263,6 +284,8 @@ EditorAppearance: RelativeToTopLeft: yes AutoTargetIgnore: + ProximityCaptor: + Types:Wall ^Tree: Tooltip: @@ -277,6 +300,8 @@ Terrain: Tree EditorAppearance: RelativeToTopLeft: yes + ProximityCaptor: + Types:Tree ^Rock: Tooltip: @@ -291,6 +316,8 @@ Terrain: Tree EditorAppearance: RelativeToTopLeft: yes + ProximityCaptor: + Types:Rock ^Husk: Health: @@ -303,6 +330,8 @@ HiddenUnderFog: AppearsOnRadar: Burns: + ProximityCaptor: + Types:Husk ^Bridge: Tooltip: @@ -318,3 +347,5 @@ Building: Footprint: ______ ______ ______ ______ Dimensions: 6,4 + ProximityCaptor: + Types:Bridge diff --git a/mods/cnc/rules/system.yaml b/mods/cnc/rules/system.yaml index b629ba35d7..c8c4cf19d7 100644 --- a/mods/cnc/rules/system.yaml +++ b/mods/cnc/rules/system.yaml @@ -191,3 +191,5 @@ CRATE: Unit: mcv RenderUnit: BelowUnits: + ProximityCaptor: + Types:Crate diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index d8f9b5fc4f..9693cbcae1 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -25,7 +25,9 @@ DrawLineToTarget: ActorLostNotification: Notification: unitlst1.aud - + ProximityCaptor: + Types:Vehicle + ^Tank: AppearsOnRadar: Mobile: @@ -53,6 +55,8 @@ DrawLineToTarget: ActorLostNotification: Notification: unitlst1.aud + ProximityCaptor: + Types:Tank ^Infantry: AppearsOnRadar: @@ -87,6 +91,8 @@ DrawLineToTarget: ActorLostNotification: Notification: unitlst1.aud + ProximityCaptor: + Types:Infantry ^Ship: AppearsOnRadar: @@ -107,6 +113,8 @@ DrawLineToTarget: ActorLostNotification: Notification: navylst1.aud + ProximityCaptor: + Types:Ship ^Plane: AppearsOnRadar: @@ -122,10 +130,13 @@ DrawLineToTarget: ActorLostNotification: Notification: aunitl1.aud +<<<<<<< HEAD DebugAircraftFacing: DebugAircraftSubPxX: DebugAircraftSubPxY: DebugAircraftAltitude: + ProximityCaptor: + Types:Plane ^Building: AppearsOnRadar: @@ -151,6 +162,8 @@ EditorAppearance: RelativeToTopLeft: yes ShakeOnDeath: + ProximityCaptor: + Types:Building ^Wall: AppearsOnRadar: @@ -179,6 +192,8 @@ EditorAppearance: RelativeToTopLeft: yes AutoTargetIgnore: + ProximityCaptor: + Types:Wall ^CivBuilding: Inherits: ^Building @@ -189,12 +204,17 @@ Type: Wood Tooltip: Name: Civilian Building + ProximityCaptor: + Types:CivilianBuilding ^CivField: Inherits: ^CivBuilding -Selectable: Tooltip: Name: Field + -ProximityCaptor: + ProximityCaptor: + Types:CivilianField ^Tree: Tooltip: @@ -209,6 +229,8 @@ Terrain: Tree EditorAppearance: RelativeToTopLeft: yes + ProximityCaptor: + Types:Tree ^Husk: Health: @@ -221,6 +243,8 @@ HiddenUnderFog: AppearsOnRadar: Burns: + ProximityCaptor: + Types:Husk ^Bridge: Tooltip: @@ -233,3 +257,5 @@ Dimensions: 4,2 Health: HP: 1000 + ProximityCaptor: + Types:Bridge diff --git a/mods/ra/rules/infantry.yaml b/mods/ra/rules/infantry.yaml index 0c6f5459ad..2cba4773ca 100644 --- a/mods/ra/rules/infantry.yaml +++ b/mods/ra/rules/infantry.yaml @@ -281,6 +281,9 @@ C1: Range: 2 AttackFrontal: PrimaryWeapon: Pistol + -ProximityCaptor: + ProximityCaptor: + Types:CivilianInfantry C2: Inherits: ^Infantry @@ -299,6 +302,9 @@ C2: Range: 2 AttackFrontal: PrimaryWeapon: Pistol + -ProximityCaptor: + ProximityCaptor: + Types:CivilianInfantry SHOK: Inherits: ^Infantry diff --git a/mods/ra/rules/system.yaml b/mods/ra/rules/system.yaml index ec7a139aaf..3a9d0ca1e8 100644 --- a/mods/ra/rules/system.yaml +++ b/mods/ra/rules/system.yaml @@ -208,6 +208,8 @@ MINP: InvisibleToOthers: Tooltip: Name: Anti-Personnel Mine + ProximityCaptor: + Types:Mine MINV: Mine: @@ -221,6 +223,8 @@ MINV: InvisibleToOthers: Tooltip: Name: Anti-Tank Mine + ProximityCaptor: + Types:Mine CRATE: Tooltip: @@ -279,13 +283,17 @@ CRATE: Unit: 4tnk RenderUnit: BelowUnits: + ProximityCaptor: + Types:Crate CAMERA: Aircraft: Health: HP:1000 RevealsShroud: - Range: 10 + Range: 10 + ProximityCaptor: + Types:Camera FLARE: Aircraft: @@ -298,6 +306,8 @@ FLARE: HiddenUnderFog: Tooltip: Name: Flare + ProximityCaptor: + Types: Flare powerproxy.parabombs: AirstrikePower: @@ -318,4 +328,4 @@ powerproxy.sonarpulse: AllowMultiple: yes OneShot: yes EndChargeSound: pulse1.aud - SelectTargetSound: slcttgt1.aud \ No newline at end of file + SelectTargetSound: slcttgt1.aud