diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index 686f62a19d..1b819034ed 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -181,6 +181,7 @@
+
diff --git a/OpenRa.Game/Traits/AttackBase.cs b/OpenRa.Game/Traits/AttackBase.cs
index 2253655437..041b9a8f74 100644
--- a/OpenRa.Game/Traits/AttackBase.cs
+++ b/OpenRa.Game/Traits/AttackBase.cs
@@ -91,6 +91,11 @@ namespace OpenRa.Game.Traits
bool CheckFire(Actor self, Unit unit, string weaponName, ref int fireDelay, int[] offset, ref int burst)
{
if (fireDelay > 0) return false;
+
+ var limitedAmmo = self.traits.GetOrDefault();
+ if (!limitedAmmo.HasAmmo())
+ return false;
+
var weapon = Rules.WeaponInfo[weaponName];
if (weapon.Range * weapon.Range < (target.Location - self.Location).LengthSquared) return false;
diff --git a/OpenRa.Game/Traits/LimitedAmmo.cs b/OpenRa.Game/Traits/LimitedAmmo.cs
new file mode 100644
index 0000000000..c032032376
--- /dev/null
+++ b/OpenRa.Game/Traits/LimitedAmmo.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OpenRa.Game.Traits
+{
+ class LimitedAmmo : INotifyAttack, IPips
+ {
+ int ammo;
+ Actor self;
+
+ public LimitedAmmo(Actor self)
+ {
+ ammo = self.Info.Ammo;
+ this.self = self;
+ }
+
+ public bool HasAmmo() { return ammo > 0; }
+
+ public void Attacking(Actor self) { --ammo; }
+
+ public IEnumerable GetPips()
+ {
+ return Graphics.Util.MakeArray(self.Info.Ammo,
+ i => ammo > i ? PipType.Green : PipType.Transparent);
+ }
+ }
+}