Index: binaries/data/mods/public/gui/common/tooltips.js
===================================================================
--- binaries/data/mods/public/gui/common/tooltips.js	(revision 16470)
+++ 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 16470)
+++ 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;
+			let c = g_Players[i].color;
+
+			unitCaptureBar.sprite = "color: " + c.r + " " + c.g + " " + c.b + " 128";
+		}
+
+		// TODO determinte stats format 
+		Engine.GetGUIObjectByName("captureStats").caption = translate("Capture points");
+		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 16470)
+++ binaries/data/mods/public/gui/session/selection_panels_middle/single_details_area.xml	(working copy)
@@ -20,16 +20,24 @@
 		</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"/>
+			<!-- TODO use repeat -->
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar0"/>
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar1"/>
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar2"/>
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar3"/>
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar4"/>
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar5"/>
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar6"/>
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar7"/>
+			<object type="image" sprite="playerColorBackground" ghost="true" name="captureBar8"/>
 			<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 16470)
+++ 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 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 16470)
+++ 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 metres)'><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, IID_Player);
+		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
Index: binaries/data/mods/public/simulation/components/Builder.js
===================================================================
--- binaries/data/mods/public/simulation/components/Builder.js	(revision 16470)
+++ binaries/data/mods/public/simulation/components/Builder.js	(working copy)
@@ -26,25 +26,24 @@
 
 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 [];
+
+	// disable building of structures from other civs
+	if (cmpIdentity.GetCiv() != cmpPlayer.GetCiv())
+		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.GetRange = function()
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,143 @@
+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;
+};
+
+//// Interface functions ////
+
+/**
+ * Returns the current capture points array
+ */
+Capturable.prototype.GetCapturePoints = function()
+{
+	return this.cp;
+};
+
+Capturable.prototype.GetMaxCapturePoints = function()
+{
+	return this.maxCp;
+};
+
+/**
+ * Reset all capture points by assigning them to the current owner
+ */
+Capturable.prototype.ResetCapturePoints = function()
+{
+	this.cp = [];
+	var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
+	var playerId = QueryOwnerInterface(this.entity, IID_Player).GetPlayerID();
+
+	// FIXME: check if this works with observers, defeated players, stuff like that
+	for (let i = 0; i < cmpPlayerManager.GetNumPlayers(); i++)
+		if (i == playerId)
+			this.cp[i] = this.maxCp;
+		else
+			this.cp[i] = 0;
+};
+
+/**
+ * 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)
+{
+	// Before changing the value, activate Fogging if necessary to hide changes
+	let cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging);
+	if (cmpFogging)
+		cmpFogging.Activate();
+
+	var cmpPlayerSource = QueryPlayerIDInterface(player, IID_Player);
+
+	if (!cmpPlayerSource)
+		warn(source + " has no player component defined on its owner ");
+
+	var sourceEnemyCp = 0;
+	var sourceAllyCp = 0;
+	for (let i in this.cp)
+	{
+		let cp = this.cp[i];
+		if (cmpPlayerSource.IsAlly(i))
+			sourceAllyCp += cp;
+		else
+			sourceEnemyCp += cp;
+	}
+
+	var newCp = [];
+	for (let i in this.cp)
+	{
+		if (i == cmpPlayerSource.GetPlayerID())
+			newCp[i] = this.cp[i] + amount;
+		else if (cmpPlayerSource.IsAlly(i))
+			newCp[i] = this.cp[i];
+		else // subtract proportional amount
+			newCp[i] = this.cp[i] - amount * this.cp[i] / sourceEnemyCp;
+	}
+	this.cp = newCp;
+
+	if (sourceEnemyCp > amount)
+		return false;
+
+	// We proceed to the capture part
+
+	var bestPlayer = 0;
+	for (let i in this.cp)
+	{
+		if (this.cp[i] >= this.cp[bestPlayer])
+			bestPlayer = i;
+	}
+
+	var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+	cmpOwnership.SetOwner(bestPlayer);
+
+	return true;
+};
+
+/**
+ * Check if the source can (re)capture points from this building
+ */
+Capturable.prototype.CanCapture = function(playerID)
+{
+	var cmpPlayerSource = QueryPlayerIDInterface(playerID, IID_Player);
+
+	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)
+	{
+		var scale = this.maxCp / oldMaxCp;
+		for (let i in this.cp)
+			this.cp[i] *= scale;
+	}
+};
+
+Capturable.prototype.OnOwnershipChanged = function(msg)
+{
+	this.ResetCapturePoints();
+};
+
+Engine.RegisterComponentType(IID_Capturable, "Capturable", Capturable);
Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js	(revision 16470)
+++ 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 16470)
+++ binaries/data/mods/public/simulation/components/GuiInterface.js	(working copy)
@@ -267,6 +267,14 @@
 		ret.needsRepair = cmpMirage.NeedsRepair();
 	}
 
+	var cmpCapturable = Engine.QueryInterface(ent, IID_Capturable);
+	if (cmpCapturable)
+	{
+		ret.capturePoints = cmpCapturable.GetCapturePoints();
+		ret.maxCapturePoints = cmpCapturable.GetMaxCapturePoints();
+	}
+	// TODO mirage support
+
 	var cmpBuilder = Engine.QueryInterface(ent, IID_Builder);
 	if (cmpBuilder)
 		ret.builder = true;
@@ -1701,8 +1709,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/ProductionQueue.js
===================================================================
--- binaries/data/mods/public/simulation/components/ProductionQueue.js	(revision 16470)
+++ binaries/data/mods/public/simulation/components/ProductionQueue.js	(working copy)
@@ -154,13 +154,20 @@
 	if (!cmpTechnologyManager)
 		return [];
 	
+	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+	var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
+	if (!cmpPlayer || !cmpIdentity)
+		return [];
+
+	// don't allow researching techs of other civs
+	if (cmpIdentity.GetCiv() != cmpPlayer.GetCiv())
+		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", ...}
Index: binaries/data/mods/public/simulation/components/TerritoryDecay.js
===================================================================
--- binaries/data/mods/public/simulation/components/TerritoryDecay.js	(revision 16470)
+++ 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>";
 
@@ -9,10 +9,12 @@
 {
 	this.timer = undefined;
 	this.decaying = false;
+	this.convertTo = 0; // by default, convert to gaia
 };
 
 TerritoryDecay.prototype.IsConnected = function()
 {
+	this.convertTo = 0;
 	var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
 	if (!cmpPosition || !cmpPosition.IsInWorld())
 		return false;
@@ -22,8 +24,8 @@
 		return false;
 		
 	// Prevent special gaia buildings from decaying (e.g. fences, ruins)
-	if (cmpOwnership.GetOwner() == 0)
-		return true;
+	// if (cmpOwnership.GetOwner() == 0)
+	//	return true;
 
 	var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager);
 	if (!cmpTerritoryManager)
@@ -32,9 +34,10 @@
 	var pos = cmpPosition.GetPosition2D();
 	var tileOwner = cmpTerritoryManager.GetOwner(pos.x, pos.y);
 	if (tileOwner != cmpOwnership.GetOwner())
+	{
+		this.convertTo = tileOwner;
 		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 +67,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 +91,13 @@
 
 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));
+	cmpCapturable.Reduce(decayRate, this.convertTo);
 };
 
 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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 16470)
+++ 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>
