Index: binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/UnitAI.js	(révision 13208)
+++ binaries/data/mods/public/simulation/components/UnitAI.js	(copie de travail)
@@ -288,7 +288,7 @@
 			return;
 		}
 
-		this.SetHeldPosition(this.order.data.x, this.order.data.z);
+		this.ResetHeldPosition();
 		this.MoveToPoint(this.order.data.x, this.order.data.z);
 		if (this.IsAnimal())
 			this.SetNextState("ANIMAL.WALKING");   // WalkAndFight not applicable for animals
@@ -660,7 +660,7 @@
 
 		"Order.WalkAndFight": function(msg) {
 			var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
-			cmpFormation.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]);
+			cmpFormation.CallMemberFunction("ResetHeldPosition", []);
 
 			this.MoveToPoint(this.order.data.x, this.order.data.z);
 			this.SetNextState("WALKINGANDFIGHTING");
@@ -924,26 +924,13 @@
 
 		"WALKINGANDFIGHTING": {
 			"enter": function(msg) {
-				this.StartTimer(0, 1000);
+				this.StartTimer(1000, 1000);
+				this.FormationFindNewTargets();
 			},
 
 			"Timer": function(msg) {
-				// check if there are no enemies to attack
-				var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
-				for each (var ent in cmpFormation.members)
-				{
-					var cmpUnitAI =  Engine.QueryInterface(ent, IID_UnitAI);
-	    				if (cmpUnitAI.FindNewTargets())
-					{
-						if (cmpUnitAI.orderQueue[0] && cmpUnitAI.orderQueue[0].type == "Attack")
-						{
-							var data = cmpUnitAI.orderQueue[0].data;
-							cmpUnitAI.FinishOrder();
-							this.PushOrderFront("Attack", { "target": data.target, "force": false, "forceResponse": data.forceResponse });
-							break;
-						}
-					}
-				}
+				// check if there are no ennemies to attack
+				this.FormationFindNewTargets();
 			},
 
 			"leave": function(msg) {
@@ -1017,33 +1004,23 @@
 
 				// Have all members finished the task?
 				if (!cmpFormation.TestAllMemberFunction("HasFinishedOrder", []))
+				{
+					// If in WalkAndFight and some units are not fighting, send them back to fight
+					if (this.IsInWalkAndFight())
+						cmpFormation.CallMemberFunction("SendBackToFight", []);
 					return;
+				}
 
 				cmpFormation.CallMemberFunction("ResetFinishOrder", []);
 
+				// If in WalkAndFight, no more units fighting, will resume the walk
+				// but we must first duplicate the order, because FinishOrder will remove it
+				if (this.IsInWalkAndFight())
+					this.PushOrderFront(this.orderQueue[0].type, this.orderQueue[0].data);
+
 				// Execute the next order
 				if (this.FinishOrder())
-				{
-					// if WalkAndFight order, look for new target before moving again
-					if (this.orderQueue.length > 0 && this.orderQueue[0].type == "WalkAndFight")
-					{
-						for each (var ent in cmpFormation.members)
-						{
-							var cmpUnitAI =  Engine.QueryInterface(ent, IID_UnitAI);
-	    						if (cmpUnitAI.FindNewTargets())
-							{
-								if (cmpUnitAI.orderQueue[0] && cmpUnitAI.orderQueue[0].type == "Attack")
-								{
-									var data = cmpUnitAI.orderQueue[0].data;
-									cmpUnitAI.FinishOrder();
-									this.PushOrderFront("Attack", { "target": data.target, "force": false, "forceResponse": data.forceResponse });
-									break;
-								}
-							}
-						}
-					}
 					return;
-				}
 
 				// No more order left.
 				cmpFormation.Disband();
@@ -1253,8 +1230,9 @@
 
 		"WALKINGANDFIGHTING": {
 			"enter": function () {
-				this.StartTimer(0, 1000);
+				this.StartTimer(1000, 1000);
 				this.SelectAnimation("move");
+				this.FindNewTargets();
 			},
 
 			"Timer": function(msg) {
@@ -1459,14 +1437,22 @@
 					}
 
 					// Can't reach it, no longer owned by enemy, or it doesn't exist any more - give up
+
 					// Except if in WalkAndFight mode where we look for more ennemies around before moving again
-					if (this.FinishOrder())
+					// but we should take care that the new target is in order 0 while the old target was order 1
+					// so we must exchange them before FinishOrder
+
+					if (this.IsInWalkAndFight())
 					{
-						if (this.orderQueue.length > 0 && this.orderQueue[0].type == "WalkAndFight")
-	    						this.FindNewTargets();
-						return;
+						if (this.FindNewTargets())
+							this.orderQueue[1].data = this.orderQueue[0].data;
+						else if(this.GetTargetFromFormation())
+							this.orderQueue[1].data = this.orderQueue[0].data;		
 					}
 
+					if (this.FinishOrder())
+						return;
+
 					// See if we can switch to a new nearby enemy
 					if (this.FindNewTargets())
 					{
@@ -2712,6 +2698,9 @@
 				// if there are still queued formation orders left
 				if (cmpUnitAI.GetOrders().length > 1) 
 					return true;
+				// length = 1 for WalkAndFight, but we still want to return true
+				if (cmpUnitAI.IsInWalkAndFight())
+					return true;
 			}
 		}
 
@@ -3485,6 +3474,27 @@
 	return false;
 };
 
+/**
+ * Returns true if we are in WalkAndFight mode (which induces some change in Attack orders).
+ */
+UnitAI.prototype.IsInWalkAndFight = function()
+{
+	if (this.IsFormationMember())
+	{
+		var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI);
+		if (cmpUnitAI && cmpUnitAI.orderQueue[0] && cmpUnitAI.orderQueue[0].type == "WalkAndFight")
+			return true;
+	}
+	else
+	{
+		if (this.orderQueue[0] && this.orderQueue[0].type == "WalkAndFight")
+			return true;
+		if (this.orderQueue[1] && this.orderQueue[1].type == "WalkAndFight" && this.orderQueue[0].type == "Attack")
+			return true;
+	}
+	return false;
+};
+
 //// External interface functions ////
 
 UnitAI.prototype.SetFormationController = function(ent)
@@ -4078,6 +4088,11 @@
 	this.heldPosition = {"x": x, "z": z};
 };
 
+UnitAI.prototype.ResetHeldPosition = function(x, z)
+{
+	this.heldPosition = undefined;
+};
+
 UnitAI.prototype.GetHeldPosition = function(pos)
 {
 	return this.heldPosition;
@@ -4323,6 +4338,72 @@
 	return (cmpPack && cmpPack.IsPacking());
 };
 
+UnitAI.prototype.GetTargetFromFormation = function()
+{
+	if (!this.IsFormationMember())
+		return false;
+	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
+	if (!cmpAttack)
+		return false;
+	var targetlist = [];
+	var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI);
+	var cmpFormation = Engine.QueryInterface(cmpUnitAI.entity, IID_Formation);
+	for each (var ent in cmpFormation.members)
+	{
+		var cmpUnitAI =  Engine.QueryInterface(ent, IID_UnitAI);
+		var targetfound = undefined;
+		var order = cmpUnitAI.orderQueue[0];
+		if(order && order.type == "Attack")
+			targetfound = order.data.target;
+		if (targetfound && this.TargetIsAlive(targetfound) && targetlist.indexOf(targetfound) == -1)
+			targetlist.push(targetfound);
+	}
+	if (targetlist.length == 0)
+		return false;
+	var ents = targetlist.filter(function (v, i, a) { return cmpAttack.CanAttack(v); })
+		.sort(function (a, b) { return cmpAttack.CompareEntitiesByPreference(a, b); })
+	if (this.AttackVisibleEntity(ents, true))
+		return true;
+	return false;
+};
+
+UnitAI.prototype.SendBackToFight = function()
+{
+	if (!this.HasFinishedOrder())
+		return;
+	if (this.GetTargetFromFormation())
+		this.finishedOrder = false;
+};
+
+UnitAI.prototype.FormationFindNewTargets = function()
+{
+	var targetlist = [];
+	var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation);
+	for each (var ent in cmpFormation.members)
+	{
+		var cmpUnitAI =  Engine.QueryInterface(ent, IID_UnitAI);
+		var targetfound = undefined;
+		if (cmpUnitAI.FindNewTargets())
+			targetfound = cmpUnitAI.orderQueue[0].data.target;
+		if (targetfound && targetlist.indexOf(targetfound) == -1)
+			targetlist.push(targetfound);
+	}
+	if (targetlist.length > 0)
+	{
+		// Reaffect units which have not already found a target
+		for each (var ent in cmpFormation.members)
+		{
+			var cmpUnitAI =  Engine.QueryInterface(ent, IID_UnitAI);
+			if (!cmpUnitAI.orderQueue[0] || cmpUnitAI.orderQueue[0].type != "Attack")
+				cmpUnitAI.AttackVisibleEntity(targetlist, true);
+		}
+		// We don't want to rearrange the formation if the individual units are attacking
+		cmpFormation.SetRearrange(false);
+		this.SetNextStateAlwaysEntering("MEMBER");
+	}
+	return (targetlist.length > 0);
+};
+
 //// Animal specific functions ////
 
 UnitAI.prototype.MoveRandomly = function(distance)
