diff --git a/OpenRa.Game/Cursor.cs b/OpenRa.Game/Cursor.cs
index 2996b13a7f..bbc748bab7 100644
--- a/OpenRa.Game/Cursor.cs
+++ b/OpenRa.Game/Cursor.cs
@@ -25,6 +25,7 @@ namespace OpenRa
public static Cursor DeployBlocked { get { return new Cursor("deploy-blocked"); } }
public static Cursor Chronoshift { get { return new Cursor("chrono-target"); } }
public static Cursor ChronoshiftSelect { get { return new Cursor("chrono-select"); } }
+ public static Cursor Nuke { get { return new Cursor("nuke"); } }
public static Cursor Ability { get { return new Cursor("ability"); } }
public static Cursor C4 { get { return new Cursor("c4"); } }
public static Cursor Capture { get { return new Cursor("capture"); } }
diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index 4b20c55894..025eccea47 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -106,7 +106,6 @@
True
Resources.resx
-
@@ -222,6 +221,7 @@
+
diff --git a/OpenRa.Game/Traits/NukePower.cs b/OpenRa.Game/Traits/NukePower.cs
new file mode 100644
index 0000000000..9612773bd0
--- /dev/null
+++ b/OpenRa.Game/Traits/NukePower.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using OpenRa.Orders;
+
+namespace OpenRa.Traits
+{
+ class NukePowerInfo : SupportPowerInfo
+ {
+ public override object Create(Actor self) { return new NukePower(self, this); }
+ }
+
+ class NukePower : SupportPower, IResolveOrder
+ {
+ public NukePower(Actor self, NukePowerInfo info) : base(self, info) { }
+
+ protected override void OnBeginCharging() { Sound.Play("aprep1.aud"); }
+ protected override void OnFinishCharging() { Sound.Play("aready1.aud"); }
+ protected override void OnActivate()
+ {
+ Game.controller.orderGenerator = new SelectTarget();
+ Sound.Play("slcttgt1.aud");
+ }
+
+ public void ResolveOrder(Actor self, Order order)
+ {
+ if (order.OrderString == "NuclearMissile")
+ {
+ var silo = self.World.Actors.Where(a => a.Owner == self.Owner
+ && a.traits.Contains()).FirstOrDefault();
+ if (silo != null)
+ silo.traits.Get().PlayCustomAnim(silo, "active");
+
+ Owner.World.AddFrameEndTask(w =>
+ {
+ // Play to everyone but the current player
+ if (Owner != Owner.World.LocalPlayer)
+ Sound.Play("alaunch1.aud");
+
+ // TODO: FIRE ZE MISSILES
+ //w.Add(new NukeLaunch(silo));
+ });
+
+ Game.controller.CancelInputMode();
+ FinishActivate();
+ }
+ }
+
+ class SelectTarget : IOrderGenerator
+ {
+ public SelectTarget() { }
+
+ public IEnumerable Order(World world, int2 xy, MouseInput mi)
+ {
+ if (mi.Button == MouseButton.Right)
+ Game.controller.CancelInputMode();
+
+ return OrderInner(world, xy, mi);
+ }
+
+ IEnumerable OrderInner(World world, int2 xy, MouseInput mi)
+ {
+ if (mi.Button == MouseButton.Left)
+ {
+ yield return new Order("NuclearMissile", Game.world.LocalPlayer.PlayerActor, xy);
+ }
+
+ yield break;
+ }
+
+ public void Tick(World world)
+ {
+ var hasStructure = world.Actors
+ .Any(a => a.Owner == world.LocalPlayer && a.traits.Contains());
+
+ if (!hasStructure)
+ Game.controller.CancelInputMode();
+ }
+
+ public void Render(World world) { }
+ public Cursor GetCursor(World world, int2 xy, MouseInput mi) { return Cursor.Nuke; }
+ }
+ }
+
+ // tag trait for the building
+ class NukeSiloInfo : StatelessTraitInfo { }
+ class NukeSilo { }
+}
diff --git a/mods/ra/merge-rules.yaml b/mods/ra/merge-rules.yaml
index 5fbba749d7..97bb46195a 100644
--- a/mods/ra/merge-rules.yaml
+++ b/mods/ra/merge-rules.yaml
@@ -34,7 +34,14 @@ Player:
LongDesc: Reveals an area of the map.
Prerequisites: AFLD
TechLevel: 5
-
+ NukePower:
+ Image: atomicon
+ ChargeTime: 13
+ Description: Atom Bomb
+ LongDesc: Launches a nuclear missile at your target.
+ Prerequisites: MSLO
+ TechLevel: 12
+
World:
WaterPaletteRotation:
ChronoshiftPaletteEffect:
@@ -85,3 +92,7 @@ BRIDGE1:
BRIDGE2:
Bridge:
UseAlternateNames: yes
+
+
+MSLO:
+ NukeSilo:
\ No newline at end of file