Index: binaries/data/mods/public/gui/common/functions_utility.js
===================================================================
--- binaries/data/mods/public/gui/common/functions_utility.js	(revision 16472)
+++ binaries/data/mods/public/gui/common/functions_utility.js	(working copy)
@@ -166,12 +166,16 @@
 // ====================================================================
 
 // Convert integer color values to string (for use in GUI objects)
-function rgbToGuiColor(color)
+function rgbToGuiColor(color, alpha)
 {
+	var ret;
 	if (color && ("r" in color) && ("g" in color) && ("b" in color))
-		return color.r + " " + color.g + " " + color.b;
-
-	return "0 0 0";
+		ret = color.r + " " + color.g + " " + color.b;
+	else
+		ret = "0 0 0";
+	if (alpha)
+		ret += " " + alpha;
+	return ret;
 }
 
 // ====================================================================
Index: binaries/data/mods/public/gui/common/tooltips.js
===================================================================
--- binaries/data/mods/public/gui/common/tooltips.js	(revision 16472)
+++ binaries/data/mods/public/gui/common/tooltips.js	(working copy)
@@ -140,6 +140,7 @@
 	if (type === "Charge") return translate("Charge Attack:");
 	if (type === "Melee") return translate("Melee Attack:");
 	if (type === "Ranged") return translate("Ranged Attack:");
+	if (type === "Capture") return translate("Capture Attack:");
 
 	warn(sprintf("Internationalization: Unexpected attack type found with code ‘%(attackType)s’. This attack type must be internationalized.", { attackType: type }));
 	return translate("Attack:");
@@ -169,6 +170,15 @@
 		});
 
 		var attackLabel = txtFormats.header[0] + getAttackTypeLabel(type) + txtFormats.header[1];
+		if (type == "Capture")
+		{
+			attacks.push(sprintf(translate("%(attackLabel)s %(details)s, %(rate)s"), {
+				attackLabel: attackLabel,
+				details: template.attack[type].value,
+				rate: rate
+			}));
+			continue;
+		}
 		if (type != "Ranged")
 		{
 			attacks.push(sprintf(translate("%(attackLabel)s %(details)s, %(rate)s"), {
Index: binaries/data/mods/public/gui/session/selection_details.js
===================================================================
--- binaries/data/mods/public/gui/session/selection_details.js	(revision 16472)
+++ binaries/data/mods/public/gui/session/selection_details.js	(working copy)
@@ -86,13 +86,35 @@
 		Engine.GetGUIObjectByName("healthSection").hidden = true;
 	}
 
-	// TODO: Stamina
-	var player = Engine.GetPlayerID();
-	if (entState.stamina && (entState.player == player || g_DevSettings.controlAll))
-		Engine.GetGUIObjectByName("staminaSection").hidden = false;
+	// CapturePoints
+	if (entState.capturePoints)
+	{
+		var size = 0;
+		for (let i in entState.capturePoints)
+		{
+			var unitCaptureBar = Engine.GetGUIObjectByName("captureBar["+i+"]");
+			var sizeObj = unitCaptureBar.size;
+			sizeObj.rleft = size;
+
+			size += 100*Math.max(0, Math.min(1, entState.capturePoints[i] / entState.maxCapturePoints));
+			sizeObj.rright = size;
+			unitCaptureBar.size = sizeObj;
+			unitCaptureBar.sprite = "color: " + rgbToGuiColor(g_Players[i].color, 128);
+		}
+
+		Engine.GetGUIObjectByName("captureStats").caption = sprintf(translate("%(capturePoints)s / %(maxCapturePoints)s"), {
+			capturePoints: Math.ceil(entState.capturePoints[entState.player]),
+			maxCapturePoints: entState.maxCapturePoints
+		});
+		Engine.GetGUIObjectByName("captureSection").hidden = false;
+	}
 	else
-		Engine.GetGUIObjectByName("staminaSection").hidden = true;
+	{
+		Engine.GetGUIObjectByName("captureSection").hidden = true;
+	}
 
+	// TODO: Stamina
+
 	// Experience
 	if (entState.promotion)
 	{
@@ -136,7 +158,7 @@
 		Engine.GetGUIObjectByName("resourceStats").caption = resources;
 
 		if (entState.hitpoints)
-			Engine.GetGUIObjectByName("resourceSection").size = Engine.GetGUIObjectByName("staminaSection").size;
+			Engine.GetGUIObjectByName("resourceSection").size = Engine.GetGUIObjectByName("captureSection").size;
 		else
 			Engine.GetGUIObjectByName("resourceSection").size = Engine.GetGUIObjectByName("healthSection").size;
 
Index: binaries/data/mods/public/gui/session/selection_panels_middle/single_details_area.xml
===================================================================
--- binaries/data/mods/public/gui/session/selection_panels_middle/single_details_area.xml	(revision 16472)
+++ binaries/data/mods/public/gui/session/selection_panels_middle/single_details_area.xml	(working copy)
@@ -20,16 +20,17 @@
 		</object>
 		</object>
 
-		<!-- Stamina bar -->
-		<object size="88 28 100% 52" name="staminaSection">
-		<object size="0 0 100% 16" name="staminaLabel" type="text" style="StatsTextLeft" ghost="true">
-			<translatableAttribute id="tooltip">Stamina:</translatableAttribute>
+		<!-- Capture bar -->
+		<object size="88 28 100% 52" name="captureSection">
+		<object size="0 0 100% 16" name="captureLabel" type="text" style="StatsTextLeft" ghost="true">
+			<translatableAttribute id="tooltip">Capture points:</translatableAttribute>
 		</object>
-		<object size="0 0 100% 16" name="staminaStats" type="text" style="StatsTextRight" ghost="true"/>
-		<object size="1 16 100% 23" name="stamina" type="image">
+		<object size="0 0 100% 16" name="captureStats" type="text" style="StatsTextRight" ghost="true"/>
+		<object size="1 16 100% 23" name="capture" type="image">
 			<object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/>
-			<object type="image" sprite="staminaBackground" ghost="true"/>
-			<object type="image" sprite="staminaForeground" ghost="true" name="staminaBar"/>
+			<repeat count="9">
+				<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar[n]"/>
+			</repeat>
 			<object type="image" sprite="statsBarShaderHorizontal" ghost="true"/>
 		</object>
 		</object>
Index: binaries/data/mods/public/gui/session/unit_actions.js
===================================================================
--- binaries/data/mods/public/gui/session/unit_actions.js	(revision 16472)
+++ binaries/data/mods/public/gui/session/unit_actions.js	(working copy)
@@ -99,9 +99,7 @@
 		{
 			if (!entState.attack || !targetState.hitpoints)
 				return false;
-			if (playerCheck(entState, targetState, ["Neutral", "Enemy"]))
-				return {"possible": Engine.GuiInterfaceCall("CanAttack", {"entity": entState.id, "target": targetState.id})};
-			return false;
+			return {"possible": Engine.GuiInterfaceCall("CanAttack", {"entity": entState.id, "target": targetState.id})};
 		},
 		"hotkeyActionCheck": function(target)
 		{
@@ -672,6 +670,13 @@
 					"icon": "kill_small.png"
 				};
 
+			if (entState.capturePoints && entState.capturePoints[entState.player] < entState.maxCapturePoints / 2)
+				return {
+					"tooltip": translate("You cannot destroy this entity as you own less than half the capture points"),
+					"icon": "kill_small.png"
+				};
+					
+
 			return {
 				"tooltip": translate("Delete"),
 				"icon": "kill_small.png"
Index: binaries/data/mods/public/simulation/components/Attack.js
===================================================================
--- binaries/data/mods/public/simulation/components/Attack.js	(revision 16472)
+++ binaries/data/mods/public/simulation/components/Attack.js	(working copy)
@@ -159,6 +159,20 @@
 		"</element>" +
 	"</optional>" +
 	"<optional>" +
+		"<element name='Capture'>" +
+			"<interleave>" +
+				"<element name='Value' a:help='Capture points value'><ref name='nonNegativeDecimal'/></element>" +
+				"<element name='MaxRange' a:help='Maximum attack range (in meters)'><ref name='nonNegativeDecimal'/></element>" +
+				"<element name='RepeatTime' a:help='Time between attacks (in milliseconds). The attack animation will be stretched to match this time'>" + // TODO: it shouldn't be stretched
+					"<data type='positiveInteger'/>" +
+				"</element>" +
+				Attack.prototype.bonusesSchema +
+				Attack.prototype.preferredClassesSchema +
+				Attack.prototype.restrictedClassesSchema +
+			"</interleave>" +
+		"</element>" +
+	"</optional>" +
+	"<optional>" +
 		"<element name='Charge'>" +
 			"<interleave>" +
 				"<element name='Hack' a:help='Hack damage strength'><ref name='nonNegativeDecimal'/></element>" +
@@ -198,6 +212,7 @@
 	if (this.template.Charge) ret.push("Charge");
 	if (this.template.Melee) ret.push("Melee");
 	if (this.template.Ranged) ret.push("Ranged");
+	if (this.template.Capture) ret.push("Capture");
 	return ret;
 };
 
@@ -309,23 +324,40 @@
 	if (cmpFormation)
 		return this.GetBestAttack();
 
-	const cmpIdentity = Engine.QueryInterface(target, IID_Identity);
+	var cmpIdentity = Engine.QueryInterface(target, IID_Identity);
 	if (!cmpIdentity) 
 		return undefined;
 
-	const targetClasses = cmpIdentity.GetClassesList();
-	const isTargetClass = function (value, i, a) { return targetClasses.indexOf(value) != -1; };
-	const types = this.GetAttackTypes();
-	const attack = this;
-	const isAllowed = function (value, i, a) { return !attack.GetRestrictedClasses(value).some(isTargetClass); }
-	const isPreferred = function (value, i, a) { return attack.GetPreferredClasses(value).some(isTargetClass); }
-	const byPreference = function (a, b) { return (types.indexOf(a) + (isPreferred(a) ? types.length : 0) ) - (types.indexOf(b) + (isPreferred(b) ? types.length : 0) ); }
 
+	var targetClasses = cmpIdentity.GetClassesList();
+	var isTargetClass = function (className) { return targetClasses.indexOf(className) != -1; };
+
 	// Always slaughter domestic animals instead of using a normal attack
 	if (isTargetClass("Domestic") && this.template.Slaughter) 
 		return "Slaughter";
 
-	return types.filter(isAllowed).sort(byPreference).pop();
+	var attack = this;
+	var isAllowed = function (type) { return !attack.GetRestrictedClasses(type).some(isTargetClass); }
+
+	var types = this.GetAttackTypes().filter(isAllowed);
+
+	// check if the target is capturable
+	var captureIndex = types.indexOf("Capture")
+	if (captureIndex != -1)
+	{
+		var cmpCapturable = Engine.QueryInterface(target, IID_Capturable);
+		var cmpPlayer = QueryOwnerInterface(this.entity);
+		if (cmpPlayer && cmpCapturable && cmpCapturable.CanCapture(cmpPlayer.GetPlayerID()))
+			return "Capture";
+		// not captureable, so remove this attack
+		types.splice(captureIndex, 1);
+	}
+
+	var isPreferred = function (className) { return attack.GetPreferredClasses(className).some(isTargetClass); }
+	var byPreference = function (a, b) { return (types.indexOf(a) + (isPreferred(a) ? types.length : 0) ) - (types.indexOf(b) + (isPreferred(b) ? types.length : 0) ); }
+
+
+	return types.sort(byPreference).pop();
 };
 
 Attack.prototype.CompareEntitiesByPreference = function(a, b)
@@ -367,7 +399,10 @@
 	{
 		return ApplyValueModificationsToEntity("Attack/" + type + splash + "/" + damageType, +(template[damageType] || 0), self.entity);
 	};
-	
+
+	if (type == "Capture")
+		return {value: applyMods("Value")};
+
 	return {
 		hack: applyMods("Hack"),
 		pierce: applyMods("Pierce"),
@@ -517,6 +552,25 @@
 		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
  		cmpTimer.SetTimeout(this.entity, IID_Attack, "MissileHit", timeToTarget*1000, {"type": type, "target": target, "position": realTargetPosition, "direction": missileDirection, "projectileId": id, "playerId":playerId});
 	}
+	else if (type == "Capture")
+	{
+		var multiplier = this.GetAttackBonus(type, target);
+		var cmpHealth = Engine.QueryInterface(target, IID_Health);
+		if (!cmpHealth || cmpHealth.GetHitpoints() == 0)
+			return;
+		multiplier *= cmpHealth.GetMaxHitpoints() / cmpHealth.GetHitpoints();
+
+		var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+		if (!cmpOwnership || cmpOwnership.GetOwner() == -1)
+			return;
+		var owner = cmpOwnership.GetOwner();
+		var cmpCapturable = Engine.QueryInterface(target, IID_Capturable);
+		if (!cmpCapturable || !cmpCapturable.CanCapture(owner))
+			return;
+		
+		var strength = this.GetAttackStrengths("Capture").value;
+		cmpCapturable.Reduce(strength * multiplier, owner);
+	}
 	else
 	{
 		// Melee attack - hurt the target immediately
@@ -585,7 +639,7 @@
 		// If friendlyFire isn't enabled, get all player enemies to pass to "Damage.CauseSplashDamage".
 		if (friendlyFire == "false")
 		{
-			var cmpPlayer = Engine.QueryInterface(Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetPlayerByID(data.playerId), IID_Player)
+			var cmpPlayer = QueryPlayerIDInterface(data.playerId);
 			playersToDamage = cmpPlayer.GetEnemies();
 		}
 		// Damage the units.
@@ -607,7 +661,7 @@
 	else
 	{
 		// If we didn't hit the main target look for nearby units
-		var cmpPlayer = Engine.QueryInterface(Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetPlayerByID(data.playerId), IID_Player)
+		var cmpPlayer = QueryPlayerIDInterface(data.playerId);
 		var ents = Damage.EntitiesNearPoint(Vector2D.from3D(data.position), targetPosition.horizDistanceTo(data.position) * 2, cmpPlayer.GetEnemies());
 
 		for (var i = 0; i < ents.length; i++)
Index: binaries/data/mods/public/simulation/components/Builder.js
===================================================================
--- binaries/data/mods/public/simulation/components/Builder.js	(revision 16472)
+++ binaries/data/mods/public/simulation/components/Builder.js	(working copy)
@@ -7,6 +7,7 @@
 		"<Entities datatype='tokens'>" +
 			"\n    structures/{civ}_barracks\n    structures/{civ}_civil_centre\n    structures/pers_apadana\n  " +
 		"</Entities>" +
+		"<AllowForeignBuilder>false</AllowForeignBuilder>" +
 	"</a:example>" +
 	"<element name='Rate' a:help='Construction speed multiplier (1.0 is normal speed, higher values are faster)'>" +
 		"<ref name='positiveDecimal'/>" +
@@ -16,7 +17,12 @@
 			"<value>tokens</value>" +
 		"</attribute>" +
 		"<text/>" +
-	"</element>";
+	"</element>" +
+	"<optional>" + 
+		"<element name='AllowForeignBuilder' a:help='Allow this entity to build buildings also when this civ doesn&apos;t match the owner&apos;s civ, so when this entity is considered a foreigner.'>" +
+			"<data type='boolean'/>" +
+		"</element>" +
+	"</optional>";
 
 Builder.prototype.Init = function()
 {
@@ -26,27 +32,32 @@
 
 Builder.prototype.GetEntitiesList = function()
 {
-	var entities = [];
 	var string = this.template.Entities._string;
-	if (string)
-	{
-		// Replace the "{civ}" codes with this entity's civ ID
-		var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
-		if (cmpIdentity)
-			string = string.replace(/\{civ\}/g, cmpIdentity.GetCiv());
-		entities = string.split(/\s+/);
-		
-		// Remove disabled entities
-		var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player)
-		var disabledEntities = cmpPlayer.GetDisabledTemplates();
-		
-		for (var i = entities.length - 1; i >= 0; --i)
-			if (disabledEntities[entities[i]])
-				entities.splice(i, 1);
-	}
-	return entities;
+	if (!string)
+		return [];
+
+	var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
+	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player)
+	if (!cmpIdentity || !cmpPlayer)
+		return [];
+
+	// possibly disable building of structures from other civs
+	if (cmpIdentity.GetCiv() != cmpPlayer.GetCiv() && !this.AllowForeignBuilder())
+		return [];
+	
+	// Replace the "{civ}" codes with this entity's civ ID
+	var entities = string.replace(/\{civ\}/g, cmpIdentity.GetCiv()).split(/\s+/);
+	// Remove disabled entities
+	var disabledEntities = cmpPlayer.GetDisabledTemplates();
+	return entities.filter(function(e) { return !disabledEntities[e]; });
 };
 
+Builder.prototype.AllowForeignBuilder = function()
+{
+	var allow = this.template.AllowForeignBuilder || false;
+	return allow == "true";
+};
+
 Builder.prototype.GetRange = function()
 {
 	var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
Index: binaries/data/mods/public/simulation/components/Capturable.js
===================================================================
--- binaries/data/mods/public/simulation/components/Capturable.js	(revision 0)
+++ binaries/data/mods/public/simulation/components/Capturable.js	(working copy)
@@ -0,0 +1,135 @@
+function Capturable() {}
+
+Capturable.prototype.Schema =
+	"<element name='CapturePoints' a:help='Maximum capture points'>" +
+		"<ref name='nonNegativeDecimal'/>" +
+	"</element>";
+
+Capturable.prototype.Init = function()
+{
+	// Cache this value 
+	this.maxCp = +this.template.CapturePoints;
+	this.cp = [];
+};
+
+//// Interface functions ////
+
+/**
+ * Returns the current capture points array
+ */
+Capturable.prototype.GetCapturePoints = function()
+{
+	return this.cp;
+};
+
+Capturable.prototype.GetMaxCapturePoints = function()
+{
+	return this.maxCp;
+};
+
+/**
+ * Reduces the amount of capture points of an entity,
+ * in the favour of the player of the source
+ * Returns true when captured
+ */
+Capturable.prototype.Reduce = function(amount, player)
+{
+	var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+	if (!cmpOwnership || cmpOwnership.GetOwner() == -1)
+		return;
+
+	// Before changing the value, activate Fogging if necessary to hide changes
+	var cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging);
+	if (cmpFogging)
+		cmpFogging.Activate();
+
+	var cmpPlayerSource = QueryPlayerIDInterface(player);
+
+	if (!cmpPlayerSource)
+		warn(source + " has no player component defined on its owner ");
+
+	var enemiesWithCp = 0;
+	for (let i in this.cp)
+		if (!cmpPlayerSource.IsAlly(i) && this.cp[i] > 0)
+			enemiesWithCp++;
+
+	var distributedAmount = amount / enemiesWithCp;
+	for (let i in this.cp)
+	{
+		if (cmpPlayerSource.IsAlly(i))
+			continue;
+		if (this.cp[i] > distributedAmount)
+			this.cp[i] -= distributedAmount;
+		else
+			this.cp[i] = 0;
+	}
+
+	// give all cp taken to the player
+	var currentCp = this.cp.reduce(function(a, b) { return a + b; });
+	this.cp[player] = this.GetMaxCapturePoints() - currentCp;
+
+	// if all cp has been taken from the owner, convert it
+	if (this.cp[cmpOwnership.GetOwner()] > 0)
+		return;
+
+	var bestPlayer = 0;
+	for (let i in this.cp)
+		if (this.cp[i] >= this.cp[bestPlayer])
+			bestPlayer = +i;
+
+	cmpOwnership.SetOwner(bestPlayer);
+
+	return;
+};
+
+/**
+ * Check if the source can (re)capture points from this building
+ */
+Capturable.prototype.CanCapture = function(playerID)
+{
+	var cmpPlayerSource = QueryPlayerIDInterface(playerID);
+
+	if (!cmpPlayerSource)
+		warn(source + " has no player component defined on its owner ");
+	var cp = this.GetCapturePoints()
+	var sourceEnemyCp = 0;
+	for (let i in this.GetCapturePoints())
+		if (!cmpPlayerSource.IsAlly(i))
+			sourceEnemyCp += cp[i];
+	return sourceEnemyCp > 0;
+};
+
+//// Private functions ////
+
+Capturable.prototype.OnValueModification = function(msg)
+{
+	if (msg.component != "Capturable")
+		return;
+
+	var oldMaxCp = this.GetMaxCapturePoints();
+	this.maxCp = Math.round(ApplyValueModificationsToEntity("Capturable/Max", +this.template.Max, this.entity));
+	if (oldMaxCp == this.maxCp)
+		return;
+
+	var scale = this.maxCp / oldMaxCp;
+	for (let i in this.cp)
+		this.cp[i] *= scale;
+};
+
+Capturable.prototype.OnOwnershipChanged = function(msg)
+{
+	// initialise the capture points when created
+	if (msg.from != -1)
+		return;
+
+	this.cp = [];
+	var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
+	// FIXME: check if this works with observers
+	for (let i = 0; i < cmpPlayerManager.GetNumPlayers(); ++i)
+		if (i == msg.to)
+			this.cp[i] = this.maxCp;
+		else
+			this.cp[i] = 0;
+};
+
+Engine.RegisterComponentType(IID_Capturable, "Capturable", Capturable);
Index: binaries/data/mods/public/simulation/components/Fogging.js
===================================================================
--- binaries/data/mods/public/simulation/components/Fogging.js	(revision 16472)
+++ binaries/data/mods/public/simulation/components/Fogging.js	(working copy)
@@ -125,6 +125,13 @@
 			cmpHealth.IsRepairable() && (cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints())
 		);
 
+	var cmpCapturable = Engine.QueryInterface(this.entity, IID_Capturable);
+	if (cmpCapturable)
+		cmpMirage.CopyCapturable(
+			cmpCapturable.GetMaxCapturePoints(), 
+			cmpCapturable.GetCapturePoints() 
+		);
+
 	var cmpResourceSupply = Engine.QueryInterface(this.entity, IID_ResourceSupply);
 	if (cmpResourceSupply)
 		cmpMirage.CopyResourceSupply(
Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js	(revision 16472)
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js	(working copy)
@@ -75,6 +75,7 @@
 			this.visibleGarrisonPoints.push({"offset":o, "entity": null});
 		}
 	}
+	this.captureTimers = {};
 };
 
 /**
@@ -269,11 +270,9 @@
 	if (this.GetGarrisonedEntitiesCount() + extraCount >= this.GetCapacity())
 		return false;
 
+	var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
 	if (!this.timer && this.GetHealRate() > 0)
-	{
- 		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
 		this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {});
-	}
 
 	// Actual garrisoning happens here
 	this.entities.push(entity);
@@ -291,6 +290,14 @@
 	var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
 	if (cmpUnitAI && cmpUnitAI.IsUnderAlert())
 		Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity});
+
+	var cmpAttack = Engine.QueryInterface(entity, IID_Attack);
+	if (cmpAttack && cmpAttack.GetAttackTypes().indexOf("Capture") != -1)
+	{
+		var repeatTime = cmpAttack.GetTimers("Capture").repeat;
+		var timer = cmpTimer.SetInterval(this.entity, IID_GarrisonHolder, "Recapture", repeatTime, repeatTime, {"entity": entity});
+		this.captureTimers[entity] = timer;
+	}
 	
 	return true;
 };
@@ -420,6 +427,20 @@
 	this.OrderWalkToRallyPoint(ejectedEntities);
 	this.UpdateGarrisonFlag();
 
+	if (forced || success)
+	{
+		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+		for (let ent of entities)
+		{
+			var timerId = this.captureTimers[ent];
+			if (timerId)
+			{
+				cmpTimer.CancelTimer(timerId);
+				this.captureTimers[ent] = 0;
+			}
+		}
+	}
+
 	return success;
 };
 
@@ -723,6 +744,16 @@
 	return false;
 };
 
+GarrisonHolder.prototype.Recapture = function(data)
+{
+	var cmpAttack = Engine.QueryInterface(data.entity, IID_Attack);
+	if (!cmpAttack)
+		return; // error
+	if (cmpAttack.GetAttackTypes().indexOf("Capture") == -1)
+		return; // error
+	cmpAttack.PerformAttack("Capture", this.entity);
+};
+
 /**
  * Initialise the garrisoned units
  */
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js	(revision 16472)
+++ binaries/data/mods/public/simulation/components/GuiInterface.js	(working copy)
@@ -267,6 +267,18 @@
 		ret.needsRepair = cmpMirage.NeedsRepair();
 	}
 
+	var cmpCapturable = Engine.QueryInterface(ent, IID_Capturable);
+	if (cmpCapturable)
+	{
+		ret.capturePoints = cmpCapturable.GetCapturePoints();
+		ret.maxCapturePoints = cmpCapturable.GetMaxCapturePoints();
+	}
+	if (cmpMirage && cmpMirage.Capturable())
+	{
+		ret.capturePoints = cmpMirage.GetCapturePoints();
+		ret.maxCapturePoints = cmpMirage.GetMaxCapturePoints();
+	}
+
 	var cmpBuilder = Engine.QueryInterface(ent, IID_Builder);
 	if (cmpBuilder)
 		ret.builder = true;
@@ -1701,8 +1713,22 @@
 	var cmpAttack = Engine.QueryInterface(data.entity, IID_Attack);
 	if (!cmpAttack)
 		return false;
+	var cmpEntityPlayer = QueryOwnerInterface(data.entity, IID_Player);
+	var cmpTargetPlayer = QueryOwnerInterface(data.target, IID_Player);
+	if (!cmpEntityPlayer || !cmpTargetPlayer)
+		return false;
 
-	return cmpAttack.CanAttack(data.target);
+
+	// if the owner is an enemy, it's up to the attack component to decide
+	if (!cmpEntityPlayer.IsAlly(cmpTargetPlayer.GetPlayerID()))
+		return cmpAttack.CanAttack(data.target);
+
+	// if the owner is an ally, we could still want to capture some capture points back
+	var cmpCapturable = Engine.QueryInterface(data.target, IID_Capturable);
+	if (cmpCapturable && cmpCapturable.CanCapture(cmpEntityPlayer.GetPlayerID()))
+		return cmpAttack.CanAttack(data.target);
+
+	return false;
 };
 
 /*
Index: binaries/data/mods/public/simulation/components/Mirage.js
===================================================================
--- binaries/data/mods/public/simulation/components/Mirage.js	(revision 16472)
+++ binaries/data/mods/public/simulation/components/Mirage.js	(working copy)
@@ -21,6 +21,10 @@
 	this.hitpoints = null;
 	this.needsRepair = null;
 
+	this.capturable = false;
+	this.capturePoints = [];
+	this.maxCapturePoints = 0;
+
 	this.resourceSupply = false;
 	this.maxAmount = null;
 	this.amount = null;
@@ -94,6 +98,30 @@
 	return this.needsRepair;
 };
 
+// Capture data
+
+Mirage.prototype.CopyCapturable = function(capturePoints, maxCapturePoints)
+{
+	this.capturable = true;
+	this.capturePoints = capturePoints;
+	this.maxCapturePoints = maxCapturePoints;
+}
+
+Mirage.prototype.Capturable = function()
+{
+	return this.capturable;
+}
+
+Mirage.prototype.GetMaxCapturePoints = function()
+{
+	return this.maxCapturePoints;
+}
+
+Mirage.prototype.GetCapturePoints = function()
+{
+	return this.capturePoints;
+}
+
 // ResourceSupply data
 
 Mirage.prototype.CopyResourceSupply = function(maxAmount, amount, type, isInfinite)
Index: binaries/data/mods/public/simulation/components/ProductionQueue.js
===================================================================
--- binaries/data/mods/public/simulation/components/ProductionQueue.js	(revision 16472)
+++ binaries/data/mods/public/simulation/components/ProductionQueue.js	(working copy)
@@ -29,7 +29,17 @@
 			"</attribute>" +
 			"<text/>" +
 		"</element>" +
-	"</optional>";
+	"</optional>" +
+	"<optional>" + 
+		"<element name='AllowForeignUnitRecruiter' a:help='Allow this entity to produce units also when this civ doesn&apos;t match the owner&apos;s civ, so when this entity is considered a foreign.'>" +
+			"<data type='boolean'/>" +
+		"</element>" +
+	"</optional>" + 
+	"<optional>" + 
+		"<element name='AllowForeignTechnologyResearcher' a:help='Allow this entity to research technologies also when this civ doesn&apos;t match the owner&apos;s civ, so when this entity is considered a foreign.'>" +
+			"<data type='boolean'/>" +
+		"</element>" +
+	"</optional>"; 
 
 ProductionQueue.prototype.Init = function()
 {
@@ -69,6 +79,18 @@
 	this.alertRaiser = undefined;
 };
 
+ProductionQueue.prototype.AllowForeignUnitRecruiter = function()
+{
+	var allow = this.template.AllowForeignUnitRecruiter || false;
+	return allow == "true";
+};
+
+ProductionQueue.prototype.AllowForeignTechnologyResearcher = function()
+{
+	var allow = this.template.AllowForeignTechnologyResearcher || false;
+	return allow == "true";
+};
+
 ProductionQueue.prototype.PutUnderAlert = function(raiser)
 {
 	this.alertRaiser = raiser;
@@ -97,15 +119,21 @@
 	if (!string)
 		return;
 	
+	var cmpPlayer = QueryOwnerInterface(this.entity);
+	var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
+	if (!cmpPlayer || !cmpIdentity)
+		return;
+
+	// possibly don't allow recruiting units of other civs
+	if (cmpIdentity.GetCiv() != cmpPlayer.GetCiv() && !this.AllowForeignUnitRecruiter())
+		return;
+
 	// Replace the "{civ}" codes with this entity's civ ID
-	var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
-	if (cmpIdentity)
-		string = string.replace(/\{civ\}/g, cmpIdentity.GetCiv());
+	string = string.replace(/\{civ\}/g, cmpIdentity.GetCiv());
 	
 	var entitiesList = string.split(/\s+/);
 	
 	// Remove disabled entities
-	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
 	var disabledEntities = cmpPlayer.GetDisabledTemplates();
 	
 	for (var i = entitiesList.length - 1; i >= 0; --i)
@@ -154,13 +182,20 @@
 	if (!cmpTechnologyManager)
 		return [];
 	
+	var cmpPlayer = QueryOwnerInterface(this.entity);
+	var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
+	if (!cmpPlayer || !cmpIdentity)
+		return [];
+
+	// possibly don't allow researching techs of other civs
+	if (cmpIdentity.GetCiv() != cmpPlayer.GetCiv() && !this.AllowForeignTechnologyResearcher())
+		return [];
+
 	var techs = string.split(/\s+/);
 	var techList = [];
 	var superseded = {}; // Stores the tech which supersedes the key
 
-	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
-	if (cmpPlayer)
-		var disabledTechnologies = cmpPlayer.GetDisabledTechnologies();
+	var disabledTechnologies = cmpPlayer.GetDisabledTechnologies();
 	
 	// Add any top level technologies to an array which corresponds to the displayed icons
 	// Also store what a technology is superceded by in the superceded object {"tech1":"techWhichSupercedesTech1", ...}
@@ -237,7 +272,7 @@
 	// TODO: there should probably be a limit on the number of queued batches
 	// TODO: there should be a way for the GUI to determine whether it's going
 	// to be possible to add a batch (based on resource costs and length limits)
-	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+	var cmpPlayer = QueryOwnerInterface(this.entity);
 
 	if (this.queue.length < MAX_QUEUE_SIZE)
 	{
@@ -314,7 +349,7 @@
 			var template = cmpTechTempMan.GetTemplate(templateName);
 			if (!template)
 				return;
-			var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+			var cmpPlayer = QueryOwnerInterface(this.entity);
 			var time = template.researchTime * cmpPlayer.GetCheatTimeMultiplier();
 
 			var cost = {};
@@ -479,7 +514,7 @@
  */
 ProductionQueue.prototype.GetBatchTime = function(batchSize)
 {
-	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+	var cmpPlayer = QueryOwnerInterface(this.entity);
 
 	var batchTimeModifier = ApplyValueModificationsToEntity("ProductionQueue/BatchTimeModifier", +this.template.BatchTimeModifier, this.entity);
 
@@ -651,7 +686,7 @@
 	// until we've used up all the time (so that we work accurately
 	// with items that take fractions of a second)
 	var time = g_ProgressInterval;
-	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+	var cmpPlayer = QueryOwnerInterface(this.entity);
 
 	while (time > 0 && this.queue.length)
 	{
@@ -729,7 +764,7 @@
 				
 				if (!this.spawnNotified)
 				{
-					var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+					var cmpPlayer = QueryOwnerInterface(this.entity);
 					var notification = {"players": [cmpPlayer.GetPlayerID()], "message": "Can't find free space to spawn trained units" };
 					var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
 					cmpGUIInterface.PushNotification(notification);
Index: binaries/data/mods/public/simulation/components/TerritoryDecay.js
===================================================================
--- binaries/data/mods/public/simulation/components/TerritoryDecay.js	(revision 16472)
+++ binaries/data/mods/public/simulation/components/TerritoryDecay.js	(working copy)
@@ -1,7 +1,7 @@
 function TerritoryDecay() {}
 
 TerritoryDecay.prototype.Schema =
-	"<element name='HealthDecayRate' a:help='Decay rate in hitpoints per second'>" +
+	"<element name='DecayRate' a:help='Decay rate in hitpoints per second'>" +
 		"<data type='positiveInteger'/>" +
 	"</element>";
 
@@ -33,8 +33,6 @@
 	var tileOwner = cmpTerritoryManager.GetOwner(pos.x, pos.y);
 	if (tileOwner != cmpOwnership.GetOwner())
 		return false;
-	// TODO: this should probably use the same territory restriction
-	// logic as BuildRestrictions, to handle allies etc
 
 	return cmpTerritoryManager.IsConnected(pos.x, pos.y);
 };
@@ -64,7 +62,7 @@
 	if (connected)
 		var decaying = false;
 	else
-		var decaying = (Math.round(ApplyValueModificationsToEntity("TerritoryDecay/HealthDecayRate", +this.template.HealthDecayRate, this.entity)) > 0);
+		var decaying = (Math.round(ApplyValueModificationsToEntity("TerritoryDecay/DecayRate", +this.template.DecayRate, this.entity)) > 0);
 	if (decaying === this.decaying)
 		return;
 	this.decaying = decaying;
@@ -88,13 +86,17 @@
 
 TerritoryDecay.prototype.Decay = function()
 {
-	var cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
-	if (!cmpHealth)
+	var cmpCapturable = Engine.QueryInterface(this.entity, IID_Capturable);
+	if (!cmpCapturable)
 		return; // error
 
-	var decayRate = ApplyValueModificationsToEntity("TerritoryDecay/HealthDecayRate", +this.template.HealthDecayRate, this.entity);
+	var decayRate = ApplyValueModificationsToEntity(
+		"TerritoryDecay/DecayRate",
+		+this.template.DecayRate,
+		this.entity);
 
-	cmpHealth.Reduce(Math.round(decayRate));
+	// Reduce capture points in favour of Gaia
+	cmpCapturable.Reduce(decayRate, 0);
 };
 
 Engine.RegisterComponentType(IID_TerritoryDecay, "TerritoryDecay", TerritoryDecay);
Index: binaries/data/mods/public/simulation/components/interfaces/Capturable.js
===================================================================
--- binaries/data/mods/public/simulation/components/interfaces/Capturable.js	(revision 0)
+++ binaries/data/mods/public/simulation/components/interfaces/Capturable.js	(working copy)
@@ -0,0 +1,3 @@
+Engine.RegisterInterface("Capturable");
+
+
Index: binaries/data/mods/public/simulation/data/technologies/decay_outpost.json
===================================================================
--- binaries/data/mods/public/simulation/data/technologies/decay_outpost.json	(revision 16472)
+++ binaries/data/mods/public/simulation/data/technologies/decay_outpost.json	(working copy)
@@ -7,7 +7,7 @@
 	"icon": "blocks_three.png",
 	"researchTime": 40,
 	"tooltip": "Territory decay -50% for Outposts.",
-	"modifications": [{"value": "TerritoryDecay/HealthDecayRate", "multiply": 0.5}],
+	"modifications": [{"value": "TerritoryDecay/DecayRate", "multiply": 0.5}],
 	"affects": ["Outpost"],
 	"soundComplete": "interface/alarm/alarm_upgradearmory.xml"
 }
Index: binaries/data/mods/public/simulation/data/technologies/romans/decay_logistics.json
===================================================================
--- binaries/data/mods/public/simulation/data/technologies/romans/decay_logistics.json	(revision 16472)
+++ binaries/data/mods/public/simulation/data/technologies/romans/decay_logistics.json	(working copy)
@@ -7,7 +7,7 @@
 	"icon": "handcart_empty.png",
 	"researchTime": 40,
 	"tooltip": "Entrenched Camps and Siege Walls decay 50% slower.",
-	"modifications": [{"value": "TerritoryDecay/HealthDecayRate", "multiply": 0.5}],
+	"modifications": [{"value": "TerritoryDecay/DecayRate", "multiply": 0.5}],
 	"affects": ["ArmyCamp", "SiegeWall"],
 	"soundComplete": "interface/alarm/alarm_upgradearmory.xml"
 }
Index: binaries/data/mods/public/simulation/helpers/Commands.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Commands.js	(revision 16472)
+++ binaries/data/mods/public/simulation/helpers/Commands.js	(working copy)
@@ -349,8 +349,18 @@
 
 	"delete-entities": function(player, cmd, data)
 	{
-		for each (var ent in data.entities)
+		for (let ent of data.entities)
 		{
+			// don't allow to delete entities who are half-captured
+			var cmpCapturable = Engine.QueryInterface(ent, IID_Capturable);
+			if (cmpCapturable)
+			{
+				var capturePoints = cmpCapturable.GetCapturePoints();
+				var maxCapturePoints = cmpCapturable.GetMaxCapturePoints();
+				if (capturePoints[player] < maxCapturePoints / 2)
+					return;
+			}
+			// either kill or delete the entity
 			var cmpHealth = Engine.QueryInterface(ent, IID_Health);
 			if (cmpHealth)
 			{
Index: binaries/data/mods/public/simulation/templates/structures/merc_camp_egyptian.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/merc_camp_egyptian.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/merc_camp_egyptian.xml	(working copy)
@@ -60,7 +60,7 @@
     </SoundGroups>
   </Sound>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/ptol_mercenary_camp.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/ptol_mercenary_camp.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/ptol_mercenary_camp.xml	(working copy)
@@ -62,7 +62,7 @@
     </SoundGroups>
   </Sound>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/ptol_military_colony.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/ptol_military_colony.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/ptol_military_colony.xml	(working copy)
@@ -76,7 +76,7 @@
     </SoundGroups>
   </Sound>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence>
     <Radius>80</Radius>
Index: binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml	(working copy)
@@ -76,7 +76,7 @@
     </SoundGroups>
   </Sound>
   <TerritoryDecay>
-    <HealthDecayRate>10</HealthDecayRate>
+    <DecayRate>10</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <ProductionQueue>
Index: binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_gate.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_gate.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_gate.xml	(working copy)
@@ -44,7 +44,7 @@
     </Obstructions>
   </Obstruction>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_long.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_long.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_long.xml	(working copy)
@@ -62,7 +62,7 @@
     <Static width="37.0" depth="5.0"/>
   </Obstruction>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_medium.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_medium.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_medium.xml	(working copy)
@@ -55,7 +55,7 @@
     <Static width="25.0" depth="5.0"/>
   </Obstruction>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_short.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_short.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_short.xml	(working copy)
@@ -42,7 +42,7 @@
     <Static width="13.0" depth="5.0"/>
   </Obstruction>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_tower.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/rome_siege_wall_tower.xml	(working copy)
@@ -36,7 +36,7 @@
     <Static width="7.0" depth="7.0"/>
   </Obstruction>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_tent.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_tent.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/rome_tent.xml	(working copy)
@@ -50,7 +50,7 @@
     </SoundGroups>
   </Sound>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
   <VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/sele_military_colony.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/sele_military_colony.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/structures/sele_military_colony.xml	(working copy)
@@ -75,7 +75,7 @@
     </SoundGroups>
   </Sound>
   <TerritoryDecay>
-    <HealthDecayRate>1</HealthDecayRate>
+    <DecayRate>1</DecayRate>
   </TerritoryDecay>
   <TerritoryInfluence>
     <Radius>80</Radius>
Index: binaries/data/mods/public/simulation/templates/template_structure.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/template_structure.xml	(working copy)
@@ -20,6 +20,9 @@
     <PlacementType>land</PlacementType>
     <Territory>own</Territory>
   </BuildRestrictions>
+  <Capturable>
+    <CapturePoints>1000</CapturePoints>
+  </Capturable>
   <Cost>
     <Population>0</Population>
     <PopulationBonus>0</PopulationBonus>
@@ -100,7 +103,7 @@
     <HeightOffset>12.0</HeightOffset>
   </StatusBars>
   <TerritoryDecay>
-    <HealthDecayRate>5</HealthDecayRate>
+    <DecayRate>5</DecayRate>
   </TerritoryDecay>
   <Visibility>
     <RetainInFog>true</RetainInFog>
Index: binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml	(working copy)
@@ -90,7 +90,7 @@
     <HeightOffset>18.0</HeightOffset>
   </StatusBars>
   <TerritoryDecay>
-    <HealthDecayRate>2</HealthDecayRate>
+    <DecayRate>2</DecayRate>
   </TerritoryDecay>
   <Vision>
     <Range>80</Range>
Index: binaries/data/mods/public/simulation/templates/template_unit_infantry.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_infantry.xml	(revision 16472)
+++ binaries/data/mods/public/simulation/templates/template_unit_infantry.xml	(working copy)
@@ -6,6 +6,11 @@
     <Crush>15</Crush>
   </Armour>
   <Attack>
+    <Capture>
+      <Value>10</Value>
+      <MaxRange>4</MaxRange>
+      <RepeatTime>1000</RepeatTime>
+    </Capture>
     <Slaughter>
       <Hack>50.0</Hack>
       <Pierce>0.0</Pierce>
