diff --git a/CHANGELOG b/CHANGELOG index b14683d7ff..862a6d3c10 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -61,6 +61,11 @@ NEW: Added maps: Blitzkrieg and Burlesca by s1w. Both Allied and Soviet factions now build general-purpose mines instead of AT and AP mines respectively. Added new attack-move cursor artwork. + Added Phase Transport, an Allied high-tech infantry transport which can cloak. + Attack Dogs, Snipers, Mobile Radar Jammers, Camo Pillboxes, Phase Transports, Radar Domes, and Spy Planes can now detect cloaked units. + Removed the submarine detection ability from Cruiser and Transport. + Added the submarine detection ability to Submarines and Missile Subs. + Increased the submarine detection range of Gunboat from 3 to 4. Tiberian Dawn: Chinook rotors now counter-rotate. Commando can now plant C4 on bridges. diff --git a/OpenRA.Mods.RA/Activities/UnloadCargo.cs b/OpenRA.Mods.RA/Activities/UnloadCargo.cs index 40ca5f011c..81a5be6796 100644 --- a/OpenRA.Mods.RA/Activities/UnloadCargo.cs +++ b/OpenRA.Mods.RA/Activities/UnloadCargo.cs @@ -20,12 +20,14 @@ namespace OpenRA.Mods.RA.Activities { readonly Actor self; readonly Cargo cargo; + readonly Cloak cloak; readonly bool unloadAll; public UnloadCargo(Actor self, bool unloadAll) { this.self = self; cargo = self.Trait(); + cloak = self.TraitOrDefault(); this.unloadAll = unloadAll; } @@ -52,6 +54,9 @@ namespace OpenRA.Mods.RA.Activities if (IsCanceled || cargo.IsEmpty(self)) return NextActivity; + if (cloak != null && cloak.Info.UncloakOnUnload) + cloak.Uncloak(); + var actor = cargo.Peek(self); var exitCell = ChooseExitCell(actor); diff --git a/OpenRA.Mods.RA/Cloak.cs b/OpenRA.Mods.RA/Cloak.cs index c1dd4b1449..2f5c3b25f3 100644 --- a/OpenRA.Mods.RA/Cloak.cs +++ b/OpenRA.Mods.RA/Cloak.cs @@ -22,12 +22,15 @@ namespace OpenRA.Mods.RA public readonly int InitialDelay = 10; // Ticks public readonly int CloakDelay = 30; // Ticks public readonly bool UncloakOnMove = false; + public readonly bool UncloakOnUnload = false; public readonly bool RequiresCrate = false; public readonly string CloakSound = null; public readonly string UncloakSound = null; public readonly string Palette = "cloak"; + public readonly string[] CloakTypes = { "Cloak" }; + public object Create(ActorInitializer init) { return new Cloak(init.self, this); } } @@ -38,24 +41,24 @@ namespace OpenRA.Mods.RA [Sync] bool crateDisabled; Actor self; - CloakInfo info; + public readonly CloakInfo Info; CPos? lastPos; public Cloak(Actor self, CloakInfo info) { - this.info = info; this.self = self; + Info = info; remainingTime = info.InitialDelay; crateDisabled = info.RequiresCrate; } - public void Uncloak() { Uncloak(info.CloakDelay); } + public void Uncloak() { Uncloak(Info.CloakDelay); } public void Uncloak(int time) { if (Cloaked) - Sound.Play(info.UncloakSound, self.CenterPosition); + Sound.Play(Info.UncloakSound, self.CenterPosition); remainingTime = Math.Max(remainingTime, time); } @@ -77,10 +80,10 @@ namespace OpenRA.Mods.RA return r; if (Cloaked && IsVisible(self, self.World.RenderPlayer)) - if (string.IsNullOrEmpty(info.Palette)) + if (string.IsNullOrEmpty(Info.Palette)) return r; else - return r.Select(a => a.WithPalette(wr.Palette(info.Palette))); + return r.Select(a => a.WithPalette(wr.Palette(Info.Palette))); else return SpriteRenderable.None; } @@ -88,15 +91,12 @@ namespace OpenRA.Mods.RA public void Tick(Actor self) { if (remainingTime > 0 && !crateDisabled && !damageDisabled && --remainingTime <= 0) - { - self.Generation++; - Sound.Play(info.CloakSound, self.CenterPosition); - } + Sound.Play(Info.CloakSound, self.CenterPosition); if (self.IsDisabled()) Uncloak(); - if (info.UncloakOnMove && (lastPos == null || lastPos.Value != self.Location)) + if (Info.UncloakOnMove && (lastPos == null || lastPos.Value != self.Location)) { Uncloak(); lastPos = self.Location; @@ -108,9 +108,14 @@ namespace OpenRA.Mods.RA if (!Cloaked || self.Owner.IsAlliedWith(viewer)) return true; - var centerPosition = self.CenterPosition; - return self.World.ActorsWithTrait().Any(a => a.Actor.Owner.IsAlliedWith(viewer) && - (centerPosition - a.Actor.CenterPosition).Length < WRange.FromCells(a.Actor.Info.Traits.Get().Range).Range); + return self.World.ActorsWithTrait().Any(a => + { + var dc = a.Actor.Info.Traits.Get(); + + return a.Actor.Owner.IsAlliedWith(viewer) + && Info.CloakTypes.Intersect(dc.CloakTypes).Any() + && (self.CenterPosition - a.Actor.CenterPosition).Length <= WRange.FromCells(dc.Range).Range; + }); } public Color RadarColorOverride(Actor self) @@ -121,7 +126,7 @@ namespace OpenRA.Mods.RA return c; } - public bool AcceptsCloakCrate { get { return info.RequiresCrate && crateDisabled; } } + public bool AcceptsCloakCrate { get { return Info.RequiresCrate && crateDisabled; } } public void ReceivedCloakCrate(Actor self) { diff --git a/OpenRA.Mods.RA/DetectCloaked.cs b/OpenRA.Mods.RA/DetectCloaked.cs index 3bc907390c..27a79b2717 100644 --- a/OpenRA.Mods.RA/DetectCloaked.cs +++ b/OpenRA.Mods.RA/DetectCloaked.cs @@ -14,6 +14,7 @@ namespace OpenRA.Mods.RA { class DetectCloakedInfo : TraitInfo { + public readonly string[] CloakTypes = { "Cloak" }; public readonly int Range = 5; } diff --git a/mods/ra/bits/stnk.shp b/mods/ra/bits/stnk.shp new file mode 100644 index 0000000000..a95933f3b7 Binary files /dev/null and b/mods/ra/bits/stnk.shp differ diff --git a/mods/ra/bits/stnkicon.shp b/mods/ra/bits/stnkicon.shp new file mode 100644 index 0000000000..050c82b186 Binary files /dev/null and b/mods/ra/bits/stnkicon.shp differ diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 00dad857f0..fbde3e6677 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -165,8 +165,6 @@ Voice: VehicleVoice TargetableUnit: TargetTypes: Ground, Water - DetectCloaked: - Range: 3 HiddenUnderFog: AttackMove: GainsExperience: diff --git a/mods/ra/rules/infantry.yaml b/mods/ra/rules/infantry.yaml index 722558fe21..61bed1839b 100644 --- a/mods/ra/rules/infantry.yaml +++ b/mods/ra/rules/infantry.yaml @@ -10,7 +10,7 @@ DOG: Cost: 200 Tooltip: Name: Attack Dog - Description: Anti-infantry unit. Not fooled by the \nSpy's disguise.\n Strong vs Infantry\n Weak vs Vehicles + Description: Anti-infantry unit.\nCan detect cloaked units and spies.\n Strong vs Infantry\n Weak vs Vehicles Selectable: Voice: DogVoice Bounds: 12,17,-1,-4 @@ -26,6 +26,8 @@ DOG: RenderInfantry: IdleAnimations: idle1,idle2 IgnoresDisguise: + DetectCloaked: + Range: 5 E1: Inherits: ^Infantry @@ -444,7 +446,7 @@ SNIPER: Cost: 700 Tooltip: Name: Sniper - Description: Elite sniper infantry unit.\n Strong vs Infantry\n Weak vs Vehicles + Description: Elite sniper infantry unit.\nCan detect cloaked units.\n Strong vs Infantry\n Weak vs Vehicles Buildable: Queue: Infantry BuildPaletteOrder: 80 @@ -462,7 +464,7 @@ SNIPER: RevealsShroud: Range: 6c0 AutoTarget: - InitialStance: HoldFire + InitialStance: ReturnFire Armament: Weapon: Sniper AttackFrontal: @@ -481,6 +483,8 @@ SNIPER: CaptureTypes: CivilianBuilding Sabotage: no SabotageHPRemoval: 0 + DetectCloaked: + Range: 6 Zombie: Inherits: ^Infantry diff --git a/mods/ra/rules/ships.yaml b/mods/ra/rules/ships.yaml index ee8b948283..1e0d425b0b 100644 --- a/mods/ra/rules/ships.yaml +++ b/mods/ra/rules/ships.yaml @@ -10,7 +10,7 @@ SS: Cost: 950 Tooltip: Name: Submarine - Description: Submerged anti-ship unit armed with \ntorpedoes.\n Strong vs Ships\n Weak vs Everything\n Special Ability: Submerge + Description: Submerged anti-ship unit armed with\ntorpedoes.\nCan detect other submarines.\n Strong vs Ships\n Weak vs Everything\n Special Ability: Submerge Health: HP: 250 Armor: @@ -26,6 +26,7 @@ SS: CloakedTargetTypes: Underwater RenderUnit: Cloak: + CloakTypes: Underwater InitialDelay: 0 CloakDelay: 50 CloakSound: subshow1.aud @@ -40,9 +41,12 @@ SS: Chronoshiftable: IronCurtainable: RepairableNear: - -DetectCloaked: AutoTarget: - InitialStance: HoldFire + InitialStance: ReturnFire + DetectCloaked: + CloakTypes: Underwater + Range: 4 + RenderDetectionCircle: MSUB: Inherits: ^Ship @@ -56,7 +60,7 @@ MSUB: Cost: 2400 Tooltip: Name: Missile Submarine - Description: Submerged anti-ground unit armed with \nlong-range ballistic missiles.\n Strong vs Buildings\n Weak vs Everything\n Special Ability: Submerge + Description: Submerged anti-ground unit armed with\nlong-range ballistic missiles.\nCan detect other submarines.\n Strong vs Buildings\n Weak vs Everything\n Special Ability: Submerge Health: HP: 400 Armor: @@ -72,6 +76,7 @@ MSUB: TargetTypes: Ground, Water CloakedTargetTypes: Underwater Cloak: + CloakTypes: Underwater InitialDelay: 0 CloakDelay: 100 CloakSound: subshow1.aud @@ -86,9 +91,12 @@ MSUB: Chronoshiftable: IronCurtainable: RepairableNear: - -DetectCloaked: AutoTarget: - InitialStance: HoldFire + InitialStance: ReturnFire + DetectCloaked: + CloakTypes: Underwater + Range: 4 + RenderDetectionCircle: DD: Inherits: ^Ship @@ -102,7 +110,7 @@ DD: Cost: 1000 Tooltip: Name: Destroyer - Description: Fast multi-role ship. \n Strong vs Submarines, Aircraft\n Weak vs Infantry, Tanks + Description: Fast multi-role ship.\nCan detect submarines.\n Strong vs Submarines, Aircraft\n Weak vs Infantry, Tanks Health: HP: 400 Armor: @@ -133,6 +141,7 @@ DD: IronCurtainable: RepairableNear: DetectCloaked: + CloakTypes: Underwater Range: 4 RenderDetectionCircle: @@ -148,7 +157,7 @@ CA: Cost: 2400 Tooltip: Name: Cruiser - Description: Very slow long-range ship. \n Strong vs Buildings\n Weak vs Ships, Submarines + Description: Very slow long-range ship.\n Strong vs Buildings\n Weak vs Ships, Submarines Health: HP: 800 Armor: @@ -237,7 +246,7 @@ PT: Cost: 500 Tooltip: Name: Gunboat - Description: Light scout & support ship. \n Strong vs Ships, Submarines\n Weak vs Aircraft + Description: Light scout & support ship.\nCan detect submarines.\n Strong vs Ships, Submarines\n Weak vs Aircraft Health: HP: 200 Armor: @@ -266,4 +275,8 @@ PT: Chronoshiftable: IronCurtainable: RepairableNear: + DetectCloaked: + CloakTypes: Underwater + Range: 4 + RenderDetectionCircle: diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 586f5e20f9..384f3e7f31 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -373,7 +373,7 @@ DOME: Cost: 1800 Tooltip: Name: Radar Dome - Description: Provides an overview of the battlefield.\n Requires power to operate. + Description: Provides an overview of the battlefield.\nCan detect cloaked units.\n Requires power to operate. Building: Power: -40 Footprint: xx xx @@ -393,6 +393,9 @@ DOME: Infiltratable: Type: Exploration InfiltrateForExploration: + DetectCloaked: + Range: 10 + RenderDetectionCircle: PBOX: Inherits: ^Building @@ -600,6 +603,8 @@ HBOX: OnEnter: HBOX.sniper OnExit: HBOX SkipMakeAnims: true + DetectCloaked: + Range: 6 HBOX.E1: Inherits: HBOX @@ -611,7 +616,7 @@ HBOX.E1: Hotkey: l Tooltip: Name: Camo Pillbox (Guns) - Description: Hidden defensive structure.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft + Description: Hidden defensive structure.\nCan detect cloaked units.\n Strong vs Infantry, Light Vehicles\n Weak vs Tanks, Aircraft RenderBuilding: Image: HBOX RenderRangeCircle: @@ -1062,7 +1067,7 @@ AFLD: Icon: spyplane ChargeTime: 180 Description: Spy Plane - LongDesc: Reveals an area of the map. + LongDesc: Reveals an area of the map\nand cloaked enemy units. SelectTargetSound: slcttgt1.aud EndChargeSound: spypln1.aud ParatroopersPower: diff --git a/mods/ra/rules/system-actors.yaml b/mods/ra/rules/system-actors.yaml index 1fabf9381a..572fcbd3d6 100644 --- a/mods/ra/rules/system-actors.yaml +++ b/mods/ra/rules/system-actors.yaml @@ -15,6 +15,7 @@ MINP: CloakSound: UncloakSound: Palette: + CloakTypes: Mine Tooltip: Name: Mine ProximityCaptor: @@ -40,6 +41,7 @@ MINV: CloakSound: UncloakSound: Palette: + CloakTypes: Mine Tooltip: Name: Mine ProximityCaptor: @@ -127,6 +129,8 @@ CAMERA: ProximityCaptor: Types: Camera BodyOrientation: + DetectCloaked: + Range: 10 FLARE: Immobile: diff --git a/mods/ra/rules/vehicles.yaml b/mods/ra/rules/vehicles.yaml index 4a9d6cc00a..ba4a4a92d8 100644 --- a/mods/ra/rules/vehicles.yaml +++ b/mods/ra/rules/vehicles.yaml @@ -398,7 +398,7 @@ MNLY.AP: Cost: 800 Tooltip: Name: Minelayer - Description: Lays mines to destroy unwary enemy units.\n Unarmed + Description: Lays mines to destroy unwary enemy units.\nCan detect mines.\n Unarmed Health: HP: 100 Armor: @@ -416,6 +416,7 @@ MNLY.AP: Ammo: 3 DetectCloaked: Range: 5 + CloakTypes: Mine RenderDetectionCircle: MNLY.AT: @@ -430,7 +431,7 @@ MNLY.AT: Cost: 800 Tooltip: Name: Minelayer - Description: Lays mines to destroy unwary enemy units.\n Unarmed + Description: Lays mines to destroy unwary enemy units.\nCan detect mines.\n Unarmed Health: HP: 100 Armor: @@ -448,6 +449,7 @@ MNLY.AT: Ammo: 3 DetectCloaked: Range: 5 + CloakTypes: Mine RenderDetectionCircle: TRUK: @@ -515,7 +517,7 @@ MRJ: Cost: 1000 Tooltip: Name: Mobile Radar Jammer - Description: Jams nearby enemy radar domes\nand deflects incoming missiles.\n Unarmed + Description: Jams nearby enemy radar domes\nand deflects incoming missiles.\nCan detect cloaked units.\n Unarmed Buildable: Queue: Vehicle BuildPaletteOrder: 150 @@ -542,6 +544,8 @@ MRJ: JamsMissiles: Range: 4 RenderJammerCircle: + DetectCloaked: + Range: 6 TTNK: Inherits: ^Tank @@ -672,11 +676,11 @@ CTNK: RenderUnit: AutoTarget: Armament@PRIMARY: - Weapon: ChronoTusk + Weapon: APTusk LocalOffset: 0,-171,0 LocalYaw: 100 Armament@SECONDARY: - Weapon: ChronoTusk + Weapon: APTusk LocalOffset: 0,171,0 LocalYaw: -100 AttackFrontal: @@ -713,4 +717,47 @@ QTNK: -EjectOnDeath: TargetableUnit: TargetTypes: Ground, MADTank - +STNK: + Inherits: ^Vehicle + Buildable: + Queue: Vehicle + BuildPaletteOrder: 170 + Prerequisites: atek + Owner: allies + Hotkey: p + Valued: + Cost: 1350 + Tooltip: + Name: Phase Transport + Description: Lightly armored infantry transport\nwhich can cloak. Can detect cloaked units.\n Strong vs Light Vehicles\n Weak vs Aircraft + Selectable: + Bounds: 28,28 + Health: + HP: 300 + Armor: + Type: Light + Mobile: + Speed: 113 + Crushes: wall, mine, crate, infantry + RevealsShroud: + Range: 6c0 + RenderUnit: + AutoTarget: + InitialStance: ReturnFire + Armament: + Weapon: APTusk + LocalOffset: 400,0,0 + Turreted: + ROT: 5 + AttackTurreted: + WithTurret: + Cargo: + Types: Infantry + MaxWeight: 3 + PipCount: 3 + Cloak: + InitialDelay: 125 + CloakDelay: 250 + UncloakOnUnload: True + DetectCloaked: + Range: 6 diff --git a/mods/ra/sequences/vehicles.yaml b/mods/ra/sequences/vehicles.yaml index 625354f1b7..ee2d8e4cb3 100644 --- a/mods/ra/sequences/vehicles.yaml +++ b/mods/ra/sequences/vehicles.yaml @@ -264,4 +264,14 @@ qtnk: Facings: 8 Length: 8 icon: qtnkicon + Start: 0 + +stnk: + idle: + Start: 0 + Facings: 32 + turret: + Start: 38 + Facings: 32 + icon: stnkicon Start: 0 \ No newline at end of file diff --git a/mods/ra/weapons.yaml b/mods/ra/weapons.yaml index d48e655367..29625e06b4 100644 --- a/mods/ra/weapons.yaml +++ b/mods/ra/weapons.yaml @@ -1241,7 +1241,7 @@ Sniper: Concrete: 0% InfDeath: 2 -ChronoTusk: +APTusk: ROF: 60 Range: 6c0 Report: MISSILE6.AUD