Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js	(révision 13408)
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js	(copie de travail)
@@ -10,7 +10,7 @@
 		"</attribute>" +
 		"<text/>" +
 	"</element>" +
-	"<element name='EjectHealth' a:help='Percentage of maximum health below which this holder no longer allows garrisoning'>" +
+	"<element name='EjectHealth' a:help='Fraction of maximum health below which this holder no longer allows garrisoning'>" +
 		"<ref name='nonNegativeDecimal'/>" +
 	"</element>" + 
 	"<element name='BuffHeal' a:help='Number of hit points that will be restored to this holder&apos;s garrisoned units each second'>" +
@@ -18,7 +18,12 @@
 	"</element>" +
 	"<element name='LoadingRange' a:help='The maximum distance from this holder at which entities are allowed to garrison. Should be about 2.0 for land entities and preferably greater for ships'>" +
 		"<ref name='nonNegativeDecimal'/>" +
-	"</element>";
+	"</element>" +
+	"<optional>" +
+		"<element name='FoodProduction' a:help='Fraction of food that will be produced by this holder&apos;s garrisoned units each second'>" +
+			"<ref name='nonNegativeDecimal'/>" +
+		"</element>" +
+	"</optional>";
 
 /**
  * Initialize GarrisonHolder Component
@@ -28,7 +33,8 @@
 	// Garrisoned Units
 	this.entities = [];
 	this.spaceOccupied = 0;
-	this.timer = undefined;
+	this.healTimer = undefined;
+	this.foodTimer = undefined;
 };
 
 /**
@@ -75,6 +81,20 @@
 };
 
 /**
+ * Get the heal rate with which garrisoned units will be healed
+ */
+GarrisonHolder.prototype.GetFoodRate = function()
+{
+	if(this.template.FoodProduction)
+	{
+		var foodRate = +this.template.FoodProduction;
+		return ApplyTechModificationsToEntity("GarrisonHolder/FoodProduction", foodRate, this.entity);
+	}
+	else
+		return 0;
+};
+
+/**
  * Get number of garrisoned units capable of shooting arrows
  * Not necessarily archers
  */
@@ -113,7 +133,7 @@
 /**
  * Garrison a unit inside.
  * Returns true if successful, false if not
- * The timer for AutoHeal is started here
+ * The timers for AutoHeal and food production are started here
  */
 GarrisonHolder.prototype.Garrison = function(entity)
 {
@@ -130,12 +150,19 @@
 	if (this.GetCapacity() < this.spaceOccupied + 1)
 		return false;
 
-	if (!this.timer && this.GetHealRate() > 0)
+	if (!this.healTimer && this.GetHealRate() > 0)
 	{
  		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-		this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {});
+		this.healTimer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {});
 	}
 
+	if (!this.foodTimer && this.GetFoodRate() > 0)
+	{
+		this.foodProduced = 0;
+ 		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+		this.foodTimer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "FoodTimeout", 1000, {});
+	}
+
 	var cmpPosition = Engine.QueryInterface(entity, IID_Position);
 	if (cmpPosition)
 	{
@@ -383,8 +410,8 @@
 	if (this.entities.length == 0)
 	{
 		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-		cmpTimer.CancelTimer(this.timer);
-		this.timer = undefined;
+		cmpTimer.CancelTimer(this.healTimer);
+		this.healTimer = undefined;
 	}
 	else
 	{
@@ -399,10 +426,46 @@
 			}
 		}
 		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-		this.timer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {});
+		this.healTimer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "HealTimeout", 1000, {});
 	}
 };
 
+/**
+ * Called every second. Produce food (in corrals)
+ */
+GarrisonHolder.prototype.FoodTimeout = function(data)
+{
+	if (this.entities.length == 0)
+	{
+		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+		cmpTimer.CancelTimer(this.foodTimer);
+		this.foodTimer = undefined;
+	}
+	else
+	{
+		var totalFood = 0;
+		for each (var entity in this.entities)
+		{
+			var cmpResourceSupply = Engine.QueryInterface(entity, IID_ResourceSupply);
+			if (cmpResourceSupply && cmpResourceSupply.GetType().generic == "food")
+				totalFood += cmpResourceSupply.GetMaxAmount();
+		}
+		this.foodProduced += Math.round(totalFood*this.GetFoodRate()*100000);
+		if (this.foodProduced >= 100000)
+		{
+			var newFood = parseInt(this.foodProduced/100000);
+			var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+			cmpPlayer.AddResource("food", newFood);
+			var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
+			if (cmpStatisticsTracker)
+				cmpStatisticsTracker.IncreaseResourceGatheredCounter("food", newFood, "meat");
+			this.foodProduced -= newFood*100000;
+		}
+		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+		this.foodTimer = cmpTimer.SetTimeout(this.entity, IID_GarrisonHolder, "FoodTimeout", 1000, {});
+	}
+};
+
 GarrisonHolder.prototype.UpdateGarrisonFlag = function()
 {
 	var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
@@ -422,11 +485,16 @@
  */
 GarrisonHolder.prototype.OnDestroy = function()
 {
-	if (this.timer)
+	if (this.healTimer)
 	{
 		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-		cmpTimer.CancelTimer(this.timer);
+		cmpTimer.CancelTimer(this.healTimer);
 	}
+	if (this.foodTimer)
+	{
+		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+		cmpTimer.CancelTimer(this.foodTimer);
+	}
 };
 
 /**
Index: binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/UnitAI.js	(révision 13408)
+++ binaries/data/mods/public/simulation/components/UnitAI.js	(copie de travail)
@@ -599,13 +599,19 @@
 
 		if (this.MoveToTarget(this.order.data.target))
 		{
-			this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING");
+			if (this.IsAnimal())
+				this.SetNextState("ANIMAL.GARRISON.APPROACHING");
+			else
+				this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING");
 		}
 		else
 		{
 			// We do a range check before actually garrisoning
 			this.StopMoving();
-			this.SetNextState("INDIVIDUAL.GARRISON.GARRISONED");
+			if (this.IsAnimal())
+				this.SetNextState("ANIMAL.GARRISON.GARRISONED");
+			else
+				this.SetNextState("INDIVIDUAL.GARRISON.GARRISONED");
 		}
 	},
 
@@ -2429,6 +2435,10 @@
 		
 		"WALKING": "INDIVIDUAL.WALKING",	// reuse the same walking behaviour for animals
 							// only used for domestic animals
+
+		"GARRISON": "INDIVIDUAL.GARRISON",	// reuse the same garrison behaviour for animals
+							// only used for domestic animals
+
 	},
 };
 
@@ -4217,10 +4227,8 @@
 	if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByMutualAllyOfPlayer(cmpOwnership.GetOwner(), target)))
 		return false;
 
-	// Don't let animals garrison for now
-	// (If we want to support that, we'll need to change Order.Garrison so it
-	// doesn't move the animal into an INVIDIDUAL.* state)
-	if (this.IsAnimal())
+	// Don't let non domestic animals garrison for now
+	if (this.IsAnimal() && !this.IsDomestic())
 		return false;
 
 	return true;
Index: binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml	(révision 13408)
+++ binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml	(copie de travail)
@@ -12,10 +12,11 @@
   </Footprint>
   <GarrisonHolder>
     <Max>10</Max>
-    <EjectHealth>0.1</EjectHealth>
+    <EjectHealth>0.7</EjectHealth>
     <List datatype="tokens">Animal</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>2</LoadingRange>
+    <FoodProduction>0.002</FoodProduction>
   </GarrisonHolder>
   <Health>
     <Max>500</Max>
