diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp
index 15178795c..28f7617ae 100644
--- a/src/action/action_attack.cpp
+++ b/src/action/action_attack.cpp
@@ -157,11 +157,11 @@ static int CheckForTargetInRange(CUnit &unit)
 			order->MinRange = unit.Type->MinAttackRange;
 			order->Range = unit.Stats->Variables[ATTACKRANGE_INDEX].Max;
 			order->goalPos.x = order->goalPos.y = -1;
-			unit.SubAction |= WEAK_TARGET; // weak target
+			order->SubAction.Attack |= WEAK_TARGET; // weak target
 			order->NewResetPath();
 		}
 	// Have a weak target, try a better target.
-	} else if (order->HasGoal() && (unit.SubAction & WEAK_TARGET)) {
+	} else if (order->HasGoal() && (order->SubAction.Attack & WEAK_TARGET)) {
 		CUnit *goal = order->GetGoal();
 		CUnit *temp = AttackUnitsInReactRange(unit);
 
@@ -231,7 +231,7 @@ static void MoveToTarget(CUnit &unit)
 			unit.State = 0;
 			const Vec2i dir = goal->tilePos + goal->Type->GetHalfTileSize() - unit.tilePos;
 			UnitHeadingFromDeltaXY(unit, dir);
-			unit.SubAction++;
+			order->SubAction.Attack++;
 			return;
 		}
 		//
@@ -244,8 +244,8 @@ static void MoveToTarget(CUnit &unit)
 			// Reached wall or ground, now attacking it
 			unit.State = 0;
 			UnitHeadingFromDeltaXY(unit, order->goalPos - unit.tilePos);
-			unit.SubAction &= WEAK_TARGET;
-			unit.SubAction |= ATTACK_TARGET;
+			order->SubAction.Attack &= WEAK_TARGET;
+			order->SubAction.Attack |= ATTACK_TARGET;
 			return;
 		}
 	}
@@ -320,7 +320,7 @@ static void AttackTarget(CUnit &unit)
 			if (unit.RestoreOrder()) {
 				return;
 			}
-			unit.SubAction = MOVE_TO_TARGET;
+			order->SubAction.Attack = MOVE_TO_TARGET;
 			return;
 		}
 		// Save current command to come back.
@@ -335,14 +335,14 @@ static void AttackTarget(CUnit &unit)
 		order->MinRange = unit.Type->MinAttackRange;
 		order->Range = unit.Stats->Variables[ATTACKRANGE_INDEX].Max;
 		order->NewResetPath();
-		unit.SubAction |= WEAK_TARGET;
+		order->SubAction.Attack |= WEAK_TARGET;
 
 	//
 	// Have a weak target, try a better target.
 	// FIXME: if out of range also try another target quick
 	//
 	} else {
-		if ((unit.SubAction & WEAK_TARGET)) {
+		if ((order->SubAction.Attack & WEAK_TARGET)) {
 			CUnit *temp = AttackUnitsInReactRange(unit);
 			if (temp && temp->Type->Priority > goal->Type->Priority) {
 				COrder *savedOrder = order->Clone();
@@ -355,7 +355,7 @@ static void AttackTarget(CUnit &unit)
 				order->SetGoal(temp);
 				order->goalPos.x = order->goalPos.y = -1;
 				order->MinRange = unit.Type->MinAttackRange;
-				unit.SubAction = MOVE_TO_TARGET;
+				order->SubAction.Attack = MOVE_TO_TARGET;
 				order->NewResetPath();
 			}
 		}
@@ -375,11 +375,11 @@ static void AttackTarget(CUnit &unit)
 		order->NewResetPath();
 		unit.Frame = 0;
 		unit.State = 0;
-		unit.SubAction &= WEAK_TARGET;
-		unit.SubAction |= MOVE_TO_TARGET;
+		order->SubAction.Attack &= WEAK_TARGET;
+		order->SubAction.Attack |= MOVE_TO_TARGET;
 	}
 	if (dist < unit.Type->MinAttackRange) {
-		unit.SubAction = MOVE_TO_TARGET;
+		order->SubAction.Attack = MOVE_TO_TARGET;
 	}
 
 	//
@@ -414,7 +414,7 @@ void HandleActionAttack(COrder& order, CUnit &unit)
 		return;
 	}
 
-	switch (unit.SubAction) {
+	switch (order.SubAction.Attack) {
 		case 0: // First entry
 		{
 			// did Order change ?
@@ -431,12 +431,12 @@ void HandleActionAttack(COrder& order, CUnit &unit)
 					const Vec2i dir = goal.tilePos + goal.Type->GetHalfTileSize() - unit.tilePos;
 
 					UnitHeadingFromDeltaXY(unit, dir);
-					unit.SubAction = ATTACK_TARGET;
+					order.SubAction.Attack = ATTACK_TARGET;
 					AttackTarget(unit);
 					return;
 				}
 			}
-			unit.SubAction = MOVE_TO_TARGET;
+			order.SubAction.Attack = MOVE_TO_TARGET;
 			order.NewResetPath();
 			// FIXME: should use a reachable place to reduce pathfinder time.
 			Assert(unit.State == 0);
diff --git a/src/action/action_board.cpp b/src/action/action_board.cpp
index 219167d8b..0b9120e2a 100644
--- a/src/action/action_board.cpp
+++ b/src/action/action_board.cpp
@@ -42,14 +42,51 @@
 #include "player.h"
 #include "unit.h"
 #include "actions.h"
-#include "interface.h"
 #include "pathfinder.h"
 #include "map.h"
+#include "iolib.h"
+#include "script.h"
 
 /*----------------------------------------------------------------------------
 --  Functions
 ----------------------------------------------------------------------------*/
 
+/* virtual */ void COrder_Board::Save(CFile &file, const CUnit &unit) const
+{
+	file.printf("{\"action-board\",");
+
+	file.printf(" \"range\", %d,", this->Range);
+	if (this->HasGoal()) {
+		CUnit &goal = *this->GetGoal();
+		if (goal.Destroyed) {
+			/* this unit is destroyed so it's not in the global unit
+			 * array - this means it won't be saved!!! */
+			printf ("FIXME: storing destroyed Goal - loading will fail.\n");
+		}
+		file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str());
+	}
+	file.printf(" \"state\", %d,\n  ", this->State);
+
+	SaveDataMove(file);
+
+	file.printf("}");
+}
+
+/* virtual */ bool COrder_Board::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
+{
+	if (this->ParseMoveData(l, j, value)) {
+		return true;
+	} else if (!strcmp("state", value)) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->State = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else {
+		return false;
+	}
+	return true;
+}
+
 /**
 **  Move to transporter.
 **
@@ -80,49 +117,47 @@ static int MoveToTransporter(CUnit &unit)
 **
 **  @return      True if ship arrived/present, False otherwise.
 */
-static int WaitForTransporter(CUnit &unit)
+bool COrder_Board::WaitForTransporter(CUnit &unit)
 {
 
 	if (unit.Wait) {
 		unit.Wait--;
-		return 0;
+		return false;
 	}
 
-	CUnit *trans = unit.CurrentOrder()->GetGoal();
+	const CUnit *trans = this->GetGoal();
 
 	if (!trans || !CanTransport(*trans, unit)) {
 		// FIXME: destination destroyed??
 		unit.Wait = 6;
-		return 0;
+		return false;
 	}
 
 	if (!trans->IsVisibleAsGoal(*unit.Player)) {
 		DebugPrint("Transporter Gone\n");
-		unit.CurrentOrder()->ClearGoal();
+		this->ClearGoal();
 		unit.Wait = 6;
-		return 0;
+		return false;
 	}
 
 	if (unit.MapDistanceTo(*trans) == 1) {
 		// enter transporter
-		return 1;
+		return true;
 	}
 
-	//
 	// FIXME: any enemies in range attack them, while waiting.
-	//
 
 	// n0b0dy: This means we have to search with a smaller range.
 	// It happens only when you reach the shore,and the transporter
 	// is not there. The unit searches with a big range, so it thinks
 	// it's there. This is why we reset the search. The transporter
 	// should be a lot closer now, so it's not as bad as it seems.
-	unit.SubAction = 0;
-	unit.CurrentOrder()->Range = 1;
+	this->State = 0;
+	this->Range = 1;
 	// Uhh wait a bit.
 	unit.Wait = 10;
 
-	return 0;
+	return false;
 }
 
 /**
@@ -130,26 +165,19 @@ static int WaitForTransporter(CUnit &unit)
 **
 **  @param unit  Pointer to unit.
 */
-static void EnterTransporter(CUnit &unit)
+static void EnterTransporter(CUnit &unit, COrder_Board &order)
 {
-	CUnit *transporter;
+	CUnit *transporter = order.GetGoal();
 
-	unit.ClearAction();
+	Assert(transporter != NULL);
 
-	transporter = unit.CurrentOrder()->GetGoal();
 	if (!transporter->IsVisibleAsGoal(*unit.Player)) {
 		DebugPrint("Transporter gone\n");
-		unit.CurrentOrder()->ClearGoal();
 		return;
 	}
 
-	unit.CurrentOrder()->ClearGoal();
-
-	//
-	// Place the unit inside the transporter.
-	//
-
 	if (transporter->BoardCount < transporter->Type->MaxOnBoard) {
+		// Place the unit inside the transporter.
 		unit.Remove(transporter);
 		transporter->BoardCount++;
 		unit.Boarded = 1;
@@ -166,6 +194,56 @@ static void EnterTransporter(CUnit &unit)
 	DebugPrint("No free slot in transporter\n");
 }
 
+/* virtual */ bool COrder_Board::Execute(CUnit &unit)
+{
+	switch (this->State) {
+		// Wait for transporter
+		case 201:
+			if (this->WaitForTransporter(unit)) {
+				this->State = 202;
+			} else {
+				UnitShowAnimation(unit, unit.Type->Animations->Still);
+			}
+			break;
+		// Enter transporter
+		case 202:
+			EnterTransporter(unit, *this);
+			return true;
+			break;
+		// Move to transporter
+		case 0:
+			if (unit.Wait) {
+				unit.Wait--;
+				return false;
+			}
+			this->NewResetPath();
+			this->State = 1;
+			// FALL THROUGH
+		default:
+			if (this->State <= 200) {
+				const int pathRet = MoveToTransporter(unit);
+				// FIXME: if near transporter wait for enter
+				if (pathRet) {
+					if (pathRet == PF_UNREACHABLE) {
+						if (++this->State == 200) {
+							return true;
+						} else {
+							// Try with a bigger range.
+							if (this->CheckRange()) {
+								this->Range++;
+								this->State--;
+							}
+						}
+					} else if (pathRet == PF_REACHED) {
+						this->State = 201;
+					}
+				}
+			}
+			break;
+	}
+	return false;
+}
+
 /**
 **  The unit boards a transporter.
 **
@@ -175,52 +253,8 @@ static void EnterTransporter(CUnit &unit)
 */
 void HandleActionBoard(COrder& order, CUnit &unit)
 {
-	switch (unit.SubAction) {
-		// Wait for transporter
-		case 201:
-			if (WaitForTransporter(unit)) {
-				unit.SubAction = 202;
-			} else {
-				UnitShowAnimation(unit, unit.Type->Animations->Still);
-			}
-			break;
-		// Enter transporter
-		case 202:
-			EnterTransporter(unit);
-			break;
-		// Move to transporter
-		case 0:
-			if (unit.Wait) {
-				unit.Wait--;
-				return;
-			}
-			order.NewResetPath();
-			unit.SubAction = 1;
-			// FALL THROUGH
-		default:
-			if (unit.SubAction <= 200) {
-				int i;
-				// FIXME: if near transporter wait for enter
-				if ((i = MoveToTransporter(unit))) {
-					if (i == PF_UNREACHABLE) {
-						if (++unit.SubAction == 200) {
-							unit.ClearAction();
-							order.ClearGoal();
-						} else {
-							//
-							// Try with a bigger range.
-							//
-							if (order.CheckRange()) {
-								order.Range++;
-								unit.SubAction--;
-							}
-						}
-					} else if (i == PF_REACHED) {
-						unit.SubAction = 201;
-					}
-				}
-			}
-			break;
+	if (order.Execute(unit)) {
+		unit.ClearAction();
 	}
 }
 
diff --git a/src/action/action_build.cpp b/src/action/action_build.cpp
index 47a2a266c..084afe6b1 100644
--- a/src/action/action_build.cpp
+++ b/src/action/action_build.cpp
@@ -56,6 +56,7 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
 
 enum
 {
+	State_Start = 0,
 	State_MoveToLocationMax = 10, // Range from prev
 	State_NearOfLocation = 11, // Range to next
 	State_StartBuilding_Failed = 20,
@@ -89,8 +90,8 @@ enum
 		}
 		file.printf(" \"building\", \"%s\",", UnitReference(this->BuildingUnit).c_str());
 	}
-	file.printf(" \"type\", \"%s\",\n  ", this->Type->Ident.c_str());
-
+	file.printf(" \"type\", \"%s\",", this->Type->Ident.c_str());
+	file.printf(" \"state\", %d,\n  ", this->State);
 	SaveDataMove(file);
 	file.printf("}");
 }
@@ -104,6 +105,11 @@ enum
 		lua_rawgeti(l, -1, j + 1);
 		this->BuildingUnit = CclGetUnitFromRef(l);
 		lua_pop(l, 1);
+	} else if (!strcmp(value, "state")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->State = LuaToNumber(l, -1);
+		lua_pop(l, 1);
 	} else if (!strcmp(value, "type")) {
 		++j;
 		lua_rawgeti(l, -1, j + 1);
@@ -135,18 +141,18 @@ void COrder_Build::AiUnitKilled(CUnit& unit)
 **
 **  @param unit  Unit to move
 */
-static bool MoveToLocation(CUnit &unit, COrder_Build &order)
+bool COrder_Build::MoveToLocation(CUnit &unit)
 {
 	// First entry
-	if (!unit.SubAction) {
-		order.Data.Move.Cycles = 0; //moving counter
-		unit.SubAction = 1;
-		order.NewResetPath();
+	if (this->State == 0) {
+		this->Data.Move.Cycles = 0; //moving counter
+		this->State = 1;
+		this->NewResetPath();
 	}
 	switch (DoActionMove(unit)) { // reached end-point?
 		case PF_UNREACHABLE: {
 			// Some tries to reach the goal
-			if (unit.SubAction++ < 10) {
+			if (this->State++ < 10) {
 				// To keep the load low, retry each 1/4 second.
 				// NOTE: we can already inform the AI about this problem?
 				unit.Wait = CYCLES_PER_SECOND / 4;
@@ -156,12 +162,12 @@ static bool MoveToLocation(CUnit &unit, COrder_Build &order)
 			unit.Player->Notify(NotifyYellow, unit.tilePos.x, unit.tilePos.y,
 				_("You cannot reach building place"));
 			if (unit.Player->AiEnabled) {
-				AiCanNotReach(unit, order.GetUnitType());
+				AiCanNotReach(unit, this->GetUnitType());
 			}
 			return true;
 		}
 		case PF_REACHED:
-			unit.SubAction = State_NearOfLocation;
+			this->State = State_NearOfLocation;
 			return false;
 
 		default:
@@ -219,10 +225,10 @@ private:
 **
 **  @param unit  Unit to check
 */
-static CUnit *CheckCanBuild(CUnit &unit, COrder_Build &order)
+CUnit *COrder_Build::CheckCanBuild(CUnit &unit)
 {
-	const Vec2i pos = order.goalPos;
-	const CUnitType &type = order.GetUnitType();
+	const Vec2i pos = this->goalPos;
+	const CUnitType &type = this->GetUnitType();
 
 	// Check if the building could be built there.
 
@@ -231,28 +237,27 @@ static CUnit *CheckCanBuild(CUnit &unit, COrder_Build &order)
 	if (ontop != NULL) {
 		return ontop;
 	}
-
+#if 0
 	/*
 	 * FIXME: rb - CheckAlreadyBuilding should be somehow
 	 * enabled/disable via game lua scripting
 	 */
 	CUnit *building = AlreadyBuildingFinder(unit, type).Find(Map.Field(pos));
 	if (building != NULL) {
-		if (unit.CurrentOrder() == &order) {
+		if (unit.CurrentOrder() == this) {
 			DebugPrint("%d: Worker [%d] is helping build: %s [%d]\n"
 					_C_ unit.Player->Index _C_ unit.Slot
 					_C_ building->Type->Name.c_str()
 					_C_ building->Slot);
 
-		unit.SubAction = 0;
-		delete &order;
-		unit.Orders[0] = COrder::NewActionRepair(unit, *building);
-		return NULL;
+			delete this; // Bad
+			unit.Orders[0] = COrder::NewActionRepair(unit, *building);
+			return NULL;
 		}
 	}
-
+#endif
 	// Some tries to build the building.
-	unit.SubAction++;
+	this->State++;
 	// To keep the load low, retry each 10 cycles
 	// NOTE: we can already inform the AI about this problem?
 	unit.Wait = 10;
@@ -311,12 +316,12 @@ bool COrder_Build::StartBuilding(CUnit &unit, CUnit &ontop)
 	if (!type.BuilderOutside) {
 		UnitShowAnimation(unit, unit.Type->Animations->Still);
 		unit.Remove(build);
-		unit.SubAction = State_BuildFromInside;
+		this->State = State_BuildFromInside;
 		if (unit.Selected) {
 			SelectedUnitChanged();
 		}
 	} else {
-		unit.SubAction = State_BuildFromOutside;
+		this->State = State_BuildFromOutside;
 		this->BuildingUnit = build;
 		unit.Direction = DirectionToHeading(build->tilePos - unit.tilePos);
 		UnitUpdateHeading(unit);
@@ -372,24 +377,24 @@ bool COrder_Build::BuildFromOutside(CUnit &unit) const
 		unit.Wait--;
 		return false;
 	}
-	if (unit.SubAction <= State_MoveToLocationMax) {
-		if (MoveToLocation(unit, *this)) {
+	if (this->State <= State_MoveToLocationMax) {
+		if (this->MoveToLocation(unit)) {
 			return true;
 		}
 	}
 	const CUnitType &type = this->GetUnitType();
 
-	if (State_NearOfLocation <= unit.SubAction && unit.SubAction < State_StartBuilding_Failed) {
+	if (State_NearOfLocation <= this->State && this->State < State_StartBuilding_Failed) {
 		if (CheckLimit(unit, type) == false) {
 			return true;
 		}
-		CUnit *ontop = CheckCanBuild(unit, *this);
+		CUnit *ontop = this->CheckCanBuild(unit);
 
 		if (ontop != NULL) {
 			this->StartBuilding(unit, *ontop);
 		}
 	}
-	if (unit.SubAction == State_StartBuilding_Failed) {
+	if (this->State == State_StartBuilding_Failed) {
 		unit.Player->Notify(NotifyYellow, unit.tilePos.x, unit.tilePos.y,
 			_("You cannot build %s here"), type.Name.c_str());
 		if (unit.Player->AiEnabled) {
@@ -397,7 +402,7 @@ bool COrder_Build::BuildFromOutside(CUnit &unit) const
 		}
 		return true;
 	}
-	if (unit.SubAction == State_BuildFromOutside) {
+	if (this->State == State_BuildFromOutside) {
 		this->BuildFromOutside(unit);
 	}
 
diff --git a/src/action/action_die.cpp b/src/action/action_die.cpp
index 3646c1cca..389fc9a73 100644
--- a/src/action/action_die.cpp
+++ b/src/action/action_die.cpp
@@ -106,7 +106,6 @@ static bool AnimateActionDie(CUnit &unit)
 	unit.Stats = &type.Stats[unit.Player->Index];
 	unit.Place(unit.tilePos);
 
-	unit.SubAction = 0;
 	unit.Frame = 0;
 	UnitUpdateHeading(unit);
 	AnimateActionDie(unit); // with new corpse.
diff --git a/src/action/action_follow.cpp b/src/action/action_follow.cpp
index ab821e0de..21408a57c 100644
--- a/src/action/action_follow.cpp
+++ b/src/action/action_follow.cpp
@@ -42,7 +42,6 @@
 #include "unittype.h"
 #include "pathfinder.h"
 #include "map.h"
-#include "interface.h"
 #include "actions.h"
 
 /*----------------------------------------------------------------------------
@@ -67,7 +66,7 @@ void HandleActionFollow(COrder& order, CUnit &unit)
 	CUnit *goal = order.GetGoal();
 
 	// Reached target
-	if (unit.SubAction == 128) {
+	if (order.SubAction.Follow == 128) {
 
 		if (!goal || !goal->IsVisibleAsGoal(*unit.Player)) {
 			DebugPrint("Goal gone\n");
@@ -91,14 +90,14 @@ void HandleActionFollow(COrder& order, CUnit &unit)
 			unit.Wait = 10;
 			if (order.Range > 1) {
 				order.Range = 1;
-				unit.SubAction = 0;
+				order.SubAction.Follow = 0;
 			}
 			return;
 		}
-		unit.SubAction = 0;
+		order.SubAction.Follow = 0;
 	}
-	if (!unit.SubAction) { // first entry
-		unit.SubAction = 1;
+	if (!order.SubAction.Follow) { // first entry
+		order.SubAction .Follow= 1;
 		order.NewResetPath();
 		Assert(unit.State == 0);
 	}
@@ -161,7 +160,7 @@ void HandleActionFollow(COrder& order, CUnit &unit)
 				return;
 			}
 			order.goalPos = goal->tilePos;
-			unit.SubAction = 128;
+			order.SubAction.Follow = 128;
 		}
 			// FALL THROUGH
 		default:
diff --git a/src/action/action_move.cpp b/src/action/action_move.cpp
index 3c35c2edb..864fd5901 100644
--- a/src/action/action_move.cpp
+++ b/src/action/action_move.cpp
@@ -182,13 +182,6 @@ void HandleActionMove(COrder& order, CUnit &unit)
 		return;
 	}
 
-	if (!unit.SubAction) { // first entry
-		unit.SubAction = 1;
-		unit.CurrentOrder()->NewResetPath();
-		order.Data.Move.Cycles = 0;
-		Assert(unit.State == 0);
-	}
-
 	// FIXME: (mr-russ) Make a reachable goal here with GoalReachable ...
 
 	switch (DoActionMove(unit)) { // reached end-point?
diff --git a/src/action/action_patrol.cpp b/src/action/action_patrol.cpp
index 9b4b1cfc2..43ea097cc 100644
--- a/src/action/action_patrol.cpp
+++ b/src/action/action_patrol.cpp
@@ -57,6 +57,9 @@
 	file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y);
 	file.printf(" \"range\", %d,", this->Range);
 
+	if (this->WaitingCycle != 0) {
+		file.printf(" \"waiting-cycle\", %d,", this->WaitingCycle);
+	}
 	file.printf(" \"patrol\", {%d, %d},\n  ", this->WayPoint.x, this->WayPoint.y);
 	SaveDataMove(file);
 	file.printf("}");
@@ -71,6 +74,11 @@
 		lua_rawgeti(l, -1, j + 1);
 		CclGetPos(l, &this->WayPoint.x , &this->WayPoint.y);
 		lua_pop(l, 1);
+	} else if (!strcmp(value, "waiting-cycle")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->WaitingCycle = LuaToNumber(l, -1);
+		lua_pop(l, 1);
 	} else {
 		return false;
 	}
@@ -84,37 +92,30 @@
 		return false;
 	}
 
-	if (!unit.SubAction) { // first entry.
-		this->Data.Move.Cycles = 0; //moving counter
-		this->NewResetPath();
-		unit.SubAction = 1;
-	}
-
 	switch (DoActionMove(unit)) {
 		case PF_FAILED:
-			unit.SubAction = 1;
+			this->WaitingCycle = 0;
 			break;
 		case PF_UNREACHABLE:
 			// Increase range and try again
-			unit.SubAction = 1;
+			this->WaitingCycle = 1;
 			if (this->CheckRange()) {
 				this->Range++;
 				break;
 			}
 			// FALL THROUGH
 		case PF_REACHED:
-			unit.SubAction = 1;
+			this->WaitingCycle = 1;
 			this->Range = 0;
 			std::swap(this->WayPoint, this->goalPos);
 
-			this->Data.Move.Cycles = 0; //moving counter
 			this->NewResetPath();
 			break;
 		case PF_WAIT:
 			// Wait for a while then give up
-			unit.SubAction++;
-			if (unit.SubAction == 5) {
-				unit.SubAction = 1;
+			this->WaitingCycle++;
+			if (this->WaitingCycle == 5) {
+				this->WaitingCycle = 0;
 				this->Range = 0;
 				std::swap(this->WayPoint, this->goalPos);
 
@@ -123,12 +124,12 @@
 			}
 			break;
 		default: // moving
-			unit.SubAction = 1;
+			this->WaitingCycle = 0;
 			break;
 	}
 
 	if (!unit.Anim.Unbreakable) {
-		if (AutoAttack(unit, false) || AutoRepair(unit) || AutoCast(unit)) {
+		if (AutoAttack(unit) || AutoRepair(unit) || AutoCast(unit)) {
 			return true;
 		}
 	}
diff --git a/src/action/action_repair.cpp b/src/action/action_repair.cpp
index a4b983d3d..170581031 100644
--- a/src/action/action_repair.cpp
+++ b/src/action/action_repair.cpp
@@ -48,60 +48,103 @@
 #include "map.h"
 #include "pathfinder.h"
 #include "interface.h"
+#include "iolib.h"
+#include "script.h"
 
 /*----------------------------------------------------------------------------
 --  Functions
 ----------------------------------------------------------------------------*/
 
+/* virtual */ void COrder_Repair::Save(CFile &file, const CUnit &unit) const
+{
+	file.printf("{\"action-repair\",");
+
+	file.printf(" \"range\", %d,", this->Range);
+	if (this->HasGoal()) {
+		CUnit &goal = *this->GetGoal();
+		if (goal.Destroyed) {
+			/* this unit is destroyed so it's not in the global unit
+			 * array - this means it won't be saved!!! */
+			printf ("FIXME: storing destroyed Goal - loading will fail.\n");
+		}
+		file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str());
+	}
+	file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y);
+
+	file.printf(" \"repaircycle\", %d,", this->RepairCycle);
+	file.printf(" \"state\", %d,\n  ", this->State);
+
+	SaveDataMove(file);
+
+	file.printf("}");
+}
+
+/* virtual */ bool COrder_Repair::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
+{
+	if (this->ParseMoveData(l, j, value)) {
+		return true;
+	} else if (!strcmp("repaircycle", value)) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->RepairCycle = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else if (!strcmp("state", value)) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->State = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else {
+		return false;
+	}
+	return true;
+}
+
+
 
 /**
 **  Repair a unit.
 **
 **  @param unit  unit repairing
 **  @param goal  unit being repaired
+**
+**  @return true when action is finished/canceled.
 */
-static void RepairUnit(CUnit &unit, CUnit &goal)
+bool COrder_Repair::RepairUnit(const CUnit &unit, CUnit &goal)
 {
 	if (goal.CurrentAction() == UnitActionBuilt) {
 		COrder_Built &order = *static_cast<COrder_Built *>(goal.CurrentOrder());
 
-		order.ProgressHp(goal, 100 * unit.CurrentOrder()->Data.Repair.Cycles);
-		unit.CurrentOrder()->Data.Repair.Cycles = 0;
-		return ;
+		order.ProgressHp(goal, 100 * this->RepairCycle);
+		this->RepairCycle = 0;
+		return false;
 	}
-	CPlayer *player = unit.Player;
-	char buf[100];
+	if (goal.Variable[HP_INDEX].Value >= goal.Variable[HP_INDEX].Max) {
+		return true;
+	}
+	CPlayer &player = *unit.Player;
 
 	// Calculate the repair costs.
 	Assert(goal.Stats->Variables[HP_INDEX].Max);
 
 	// Check if enough resources are available
 	for (int i = 1; i < MaxCosts; ++i) {
-		if (player->Resources[i] < goal.Type->RepairCosts[i]) {
-			snprintf(buf, 100, _("We need more %s for repair!"),
-				DefaultResourceNames[i].c_str());
-			player->Notify(NotifyYellow, unit.tilePos.x, unit.tilePos.y, buf);
-			if (player->AiEnabled) {
-				// FIXME: call back to AI?
-				unit.CurrentOrder()->ClearGoal();
-				if (!unit.RestoreOrder()) {
-					unit.ClearAction();
-					unit.State = 0;
-				}
-			}
-			// FIXME: We shouldn't animate if no resources are available.
-			return;
+		if (player.Resources[i] < goal.Type->RepairCosts[i]) {
+			char buf[100];
+
+			snprintf(buf, 100, _("We need more %s for repair!"), DefaultResourceNames[i].c_str());
+			player.Notify(NotifyYellow, unit.tilePos.x, unit.tilePos.y, buf);
+			return true;
 		}
 	}
-	//
 	// Subtract the resources
-	//
-	player->SubCosts(goal.Type->RepairCosts);
+	player.SubCosts(goal.Type->RepairCosts);
 
 	goal.Variable[HP_INDEX].Value += goal.Type->RepairHP;
-	if (goal.Variable[HP_INDEX].Value > goal.Variable[HP_INDEX].Max) {
+	if (goal.Variable[HP_INDEX].Value >= goal.Variable[HP_INDEX].Max) {
 		goal.Variable[HP_INDEX].Value = goal.Variable[HP_INDEX].Max;
+		return true;
 	}
+	return false;
 }
 
 /**
@@ -109,46 +152,33 @@ static void RepairUnit(CUnit &unit, CUnit &goal)
 **
 **  @param unit  Unit, for that the repair animation is played.
 */
-static int AnimateActionRepair(CUnit &unit)
+static void AnimateActionRepair(CUnit &unit)
 {
 	UnitShowAnimation(unit, unit.Type->Animations->Repair);
-	return 0;
 }
 
-/**
-**  Unit repairs
-**
-**  @param unit  Unit, for that the attack is handled.
-*/
-void HandleActionRepair(COrder& order, CUnit &unit)
+/* virtual */ bool COrder_Repair::Execute(CUnit &unit)
 {
-	CUnit *goal;
-	int err;
-
-	switch (unit.SubAction) {
+	switch (this->State) {
 		case 0:
-			order.NewResetPath();
-			unit.SubAction = 1;
+			this->NewResetPath();
+			this->State = 1;
 			// FALL THROUGH
-		case 1:// Move near to target.
+		case 1: { // Move near to target.
 			// FIXME: RESET FIRST!! Why? We move first and than check if
 			// something is in sight.
-			err = DoActionMove(unit);
+			int err = DoActionMove(unit);
 			if (!unit.Anim.Unbreakable) {
 				// No goal: if meeting damaged building repair it.
-				goal = order.GetGoal();
+				CUnit *goal = this->GetGoal();
 
-				// Target is dead, choose new one.
-				//
-				// Check if goal is correct unit.
 				if (goal) {
 					if (!goal->IsVisibleAsGoal(*unit.Player)) {
 						DebugPrint("repair target gone.\n");
-						order.goalPos = goal->tilePos;
-						// FIXME: should I clear this here?
-						order.ClearGoal();
+						this->goalPos = goal->tilePos;
+						this->ClearGoal();
 						goal = NULL;
-						order.NewResetPath();
+						this->NewResetPath();
 					}
 				} else if (unit.Player->AiEnabled) {
 					// Ai players workers should stop if target is killed
@@ -156,70 +186,65 @@ void HandleActionRepair(COrder& order, CUnit &unit)
 				}
 
 				// Have reached target? FIXME: could use return value
-				if (goal && unit.MapDistanceTo(*goal) <= unit.Type->RepairRange &&
-						goal->Variable[HP_INDEX].Value < goal->Variable[HP_INDEX].Max) {
+				if (goal && unit.MapDistanceTo(*goal) <= unit.Type->RepairRange
+					&& goal->Variable[HP_INDEX].Value < goal->Variable[HP_INDEX].Max) {
 					unit.State = 0;
-					unit.SubAction = 2;
-					order.Data.Repair.Cycles = 0;
+					this->State = 2;
+					this->RepairCycle = 0;
 					const Vec2i dir = goal->tilePos + goal->Type->GetHalfTileSize() - unit.tilePos;
 					UnitHeadingFromDeltaXY(unit, dir);
 				} else if (err < 0) {
-					order.ClearGoal();
-					if (!unit.RestoreOrder()) {
-						unit.ClearAction();
-						unit.State = 0;
-					}
-					return;
+					return true;
 				}
-
-				// FIXME: Should be it already?
-				Assert(unit.CurrentAction() == UnitActionRepair);
 			}
 			break;
-
-		case 2:// Repair the target.
+		}
+		case 2: {// Repair the target.
 			AnimateActionRepair(unit);
-			order.Data.Repair.Cycles++;
-			if (!unit.Anim.Unbreakable) {
-				goal = unit.CurrentOrder()->GetGoal();
-
-				// Target is dead, choose new one.
-				//
-				// Check if goal is correct unit.
-				// FIXME: should I do a function for this?
-				if (goal) {
-					if (!goal->IsVisibleAsGoal(*unit.Player)) {
-						DebugPrint("repair goal is gone\n");
-						order.goalPos = goal->tilePos;
-						// FIXME: should I clear this here?
-						order.ClearGoal();
-						goal = NULL;
-						order.NewResetPath();
-					} else {
-						int dist = unit.MapDistanceTo(*goal);
-						if (dist <= unit.Type->RepairRange) {
-							RepairUnit(unit, *goal);
-							goal = order.GetGoal();
-						} else if (dist > unit.Type->RepairRange) {
-							// If goal has move, chase after it
-							unit.State = 0;
-							unit.SubAction = 0;
-						}
-					}
-				}
-
-				// Target is fine, choose new one.
-				if (!goal || goal->Variable[HP_INDEX].Value >= goal->Variable[HP_INDEX].Max) {
-					order.ClearGoal();
-					if (!unit.RestoreOrder()) {
-						unit.ClearAction();
-						unit.State = 0;
-					}
-					return;
-				}
-				// FIXME: automatic repair
+			this->RepairCycle++;
+			if (unit.Anim.Unbreakable) {
+				return false;
 			}
-			break;
+			CUnit *goal = this->GetGoal();
+
+			if (goal) {
+				if (!goal->IsVisibleAsGoal(*unit.Player)) {
+					DebugPrint("repair goal is gone\n");
+					this->goalPos = goal->tilePos;
+					// FIXME: should I clear this here?
+					this->ClearGoal();
+					goal = NULL;
+					this->NewResetPath();
+				} else {
+					const int dist = unit.MapDistanceTo(*goal);
+
+					if (dist <= unit.Type->RepairRange) {
+						if (RepairUnit(unit, *goal)) {
+							return true;
+						}
+					} else if (dist > unit.Type->RepairRange) {
+						// If goal has move, chase after it
+						unit.State = 0;
+						this->State = 0;
+					}
+				}
+			}
+			// Target is fine, choose new one.
+			if (!goal || goal->Variable[HP_INDEX].Value >= goal->Variable[HP_INDEX].Max) {
+				return true;
+			}
+			// FIXME: automatic repair
+		}
+		break;
+	}
+	return false;
+}
+
+
+void HandleActionRepair(COrder& order, CUnit &unit)
+{
+	if (order.Execute(unit)) {
+		unit.ClearAction();
 	}
 }
 
diff --git a/src/action/action_resource.cpp b/src/action/action_resource.cpp
index ef71ebc70..9d4752f2e 100644
--- a/src/action/action_resource.cpp
+++ b/src/action/action_resource.cpp
@@ -161,7 +161,7 @@ static void UnitGotoGoal(CUnit &unit, CUnit *const goal, int mode)
 		}
 	}
 	order->Range = 1;
-	unit.SubAction = mode;
+	order->SubAction.Res = mode;
 	unit.State = 0;
 	if (mode == SUB_MOVE_TO_DEPOT || mode == SUB_MOVE_TO_RESOURCE) {
 		unit.CurrentOrder()->Data.Move.Cycles = 0; //moving counter
@@ -209,7 +209,7 @@ static int StartGathering(CUnit &unit)
 		// Find an alternative, but don't look too far.
 		unit.CurrentOrder()->goalPos.x = unit.CurrentOrder()->goalPos.y = -1;
 		if ((goal = UnitFindResource(unit, unit.tilePos, 15, unit.CurrentResource, unit.Player->AiEnabled))) {
-			unit.SubAction = SUB_START_RESOURCE;
+			unit.CurrentOrder()->SubAction.Res = SUB_START_RESOURCE;
 			unit.CurrentOrder()->SetGoal(goal);
 		} else {
 			unit.CurrentOrder()->ClearGoal();
@@ -324,7 +324,7 @@ static void LoseResource(CUnit &unit, const CUnit &source)
 			unit.CurrentOrder()->Arg1.Resource.Mine = goal;
 			unit.CurrentOrder()->Range = 1;
 			unit.CurrentOrder()->goalPos = goal->tilePos;
-			unit.SubAction = SUB_MOVE_TO_RESOURCE;
+			unit.CurrentOrder()->SubAction.Res = SUB_MOVE_TO_RESOURCE;
 			unit.State = 0;
 			return;
 		}
@@ -361,7 +361,7 @@ static void LoseResource(CUnit &unit, const CUnit &source)
 	if (depot) {
 		DebugPrint("%d: Worker %d report: Resource is exhausted, Found another resource.\n"
 			_C_ unit.Player->Index _C_ unit.Slot);
-		unit.SubAction = SUB_START_RESOURCE;
+		unit.CurrentOrder()->SubAction.Res = SUB_START_RESOURCE;
 		unit.State = 0;
 		unit.CurrentOrder()->SetGoal(depot);
 	} else {
@@ -391,7 +391,9 @@ static int GatherResource(CUnit &unit)
 	int addload;
 
 	if (!resinfo.HarvestFromOutside && unit.Container != NULL) {
-		unit.Container->SubAction = SUB_GATHER_RESOURCE;
+#if 0
+//		unit.Container->SubAction = SUB_GATHER_RESOURCE;
+#endif
 		UnitShowAnimation(*unit.Container, unit.Container->Type->Animations->Harvest[unit.CurrentResource]);
 	}
 
@@ -412,7 +414,7 @@ static int GatherResource(CUnit &unit)
 	if (resinfo.TerrainHarvester && !Map.ForestOnMap(unit.CurrentOrder()->goalPos)) {
 		if (!unit.Anim.Unbreakable) {
 			// Action now breakable, move to resource again.
-			unit.SubAction = SUB_MOVE_TO_RESOURCE;
+			unit.CurrentOrder()->SubAction.Res = SUB_MOVE_TO_RESOURCE;
 			// Give it some reasonable look while searching.
 			// FIXME: which frame?
 			unit.Frame = 0;
@@ -529,7 +531,7 @@ int GetNumWaitingWorkers(const CUnit &mine)
 
 	for (int i = 0; NULL != worker; worker = worker->NextWorker, ++i)
 	{
-		if (worker->SubAction == SUB_START_GATHERING && worker->Wait) {
+		if (worker->CurrentOrder()->SubAction.Res == SUB_START_GATHERING && worker->Wait) {
 			ret++;
 		}
 		Assert(i <= mine.Resource.Assigned);
@@ -558,10 +560,11 @@ static int StopGathering(CUnit &unit)
 		}
 		source->Resource.Active--;
 		Assert(source->Resource.Active >= 0);
-
+#if 0
 		if (!resinfo.HarvestFromOutside && source->Resource.Active == 0) {
 			source->SubAction = 1;
 		}
+#endif
 		//Store resource position.
 		if (unit.Orders[0]->Arg1.Resource.Mine) {
 			unit.Orders[0]->Arg1.Resource.Mine->RefsDecrease();
@@ -575,7 +578,7 @@ static int StopGathering(CUnit &unit)
 			CUnit *next = NULL;
 			for(; NULL != worker; worker = worker->NextWorker)
 			{
-				if (worker != &unit && worker->SubAction == SUB_START_GATHERING && worker->Wait) {
+				if (worker != &unit && worker->CurrentOrder()->SubAction.Res == SUB_START_GATHERING && worker->Wait) {
 					count++;
 					if (next) {
 						if (next->Wait > worker->Wait)
@@ -849,7 +852,7 @@ void ResourceGiveUp(CUnit &unit)
 */
 static bool ActionResourceInit(CUnit &unit)
 {
-	Assert(unit.SubAction == SUB_START_RESOURCE);
+	Assert(unit.CurrentOrder()->SubAction.Res == SUB_START_RESOURCE);
 
 	CUnit *const goal = unit.CurrentOrder()->GetGoal();
 	int newres;
@@ -905,27 +908,27 @@ void HandleActionResource(COrder& order, CUnit &unit)
 	}
 
 	// Let's start mining.
-	if (unit.SubAction == SUB_START_RESOURCE) {
+	if (order.SubAction.Res == SUB_START_RESOURCE) {
 		if (ActionResourceInit(unit) == false) {
 			return;
 		}
 	}
 
 	// Move to the resource location.
-	if (SUB_MOVE_TO_RESOURCE <= unit.SubAction && unit.SubAction < SUB_UNREACHABLE_RESOURCE) {
+	if (SUB_MOVE_TO_RESOURCE <= order.SubAction.Res && order.SubAction.Res < SUB_UNREACHABLE_RESOURCE) {
 		const int ret = MoveToResource(unit);
 
 		switch (ret)
 		{
 			case -1: // Can't Reach
 			{
-				unit.SubAction++;
+				order.SubAction.Res++;
 				unit.Wait = 5;
 				return;
 			}
 			case 1: // Reached
 			{
-				unit.SubAction = SUB_START_GATHERING;
+				order.SubAction.Res = SUB_START_GATHERING;
 				break;
 			}
 			case 0: // Move along.
@@ -939,53 +942,53 @@ void HandleActionResource(COrder& order, CUnit &unit)
 	}
 
 	// Resource seems to be unreachable
-	if (unit.SubAction == SUB_UNREACHABLE_RESOURCE) {
+	if (order.SubAction.Res == SUB_UNREACHABLE_RESOURCE) {
 		ResourceGiveUp(unit);
 		return;
 	}
 
 	// Start gathering the resource
-	if (unit.SubAction == SUB_START_GATHERING) {
+	if (order.SubAction.Res == SUB_START_GATHERING) {
 		if (StartGathering(unit)) {
-			unit.SubAction = SUB_GATHER_RESOURCE;
+			order.SubAction.Res = SUB_GATHER_RESOURCE;
 		} else {
 			return;
 		}
 	}
 
 	// Gather the resource.
-	if (unit.SubAction == SUB_GATHER_RESOURCE) {
+	if (order.SubAction.Res == SUB_GATHER_RESOURCE) {
 		if (GatherResource(unit)) {
-			unit.SubAction = SUB_STOP_GATHERING;
+			order.SubAction.Res = SUB_STOP_GATHERING;
 		} else {
 			return;
 		}
 	}
 
 	// Stop gathering the resource.
-	if (unit.SubAction == SUB_STOP_GATHERING) {
+	if (order.SubAction.Res == SUB_STOP_GATHERING) {
 		if (StopGathering(unit)) {
-			unit.SubAction = SUB_MOVE_TO_DEPOT;
-			unit.CurrentOrder()->Data.Move.Cycles = 0; //moving counter
+			order.SubAction.Res = SUB_MOVE_TO_DEPOT;
+			order.Data.Move.Cycles = 0; //moving counter
 		} else
 			return;
 	}
 
 	// Move back home.
-	if (SUB_MOVE_TO_DEPOT <= unit.SubAction && unit.SubAction < SUB_UNREACHABLE_DEPOT) {
+	if (SUB_MOVE_TO_DEPOT <= order.SubAction.Res && order.SubAction.Res < SUB_UNREACHABLE_DEPOT) {
 		const int ret = MoveToDepot(unit);
 
 		switch (ret)
 		{
 			case -1: // Can't Reach
 			{
-				unit.SubAction++;
+				order.SubAction.Res++;
 				unit.Wait = 5;
 				return;
 			}
 			case 1: // Reached
 			{
-				unit.SubAction = SUB_RETURN_RESOURCE;
+				order.SubAction.Res = SUB_RETURN_RESOURCE;
 				return;
 			}
 			case 0: // Move along.
@@ -999,15 +1002,15 @@ void HandleActionResource(COrder& order, CUnit &unit)
 	}
 
 	// Depot seems to be unreachable
-	if (unit.SubAction == SUB_UNREACHABLE_DEPOT) {
+	if (order.SubAction.Res == SUB_UNREACHABLE_DEPOT) {
 		ResourceGiveUp(unit);
 		return;
 	}
 
 	// Unload resources at the depot.
-	if (unit.SubAction == SUB_RETURN_RESOURCE) {
+	if (order.SubAction.Res == SUB_RETURN_RESOURCE) {
 		if (WaitInDepot(unit)) {
-			unit.SubAction = SUB_START_RESOURCE;
+			order.SubAction.Res = SUB_START_RESOURCE;
 
 			// It's posible, though very rare that the unit's goal blows up
 			// this cycle, but after this unit. Thus, next frame the unit
diff --git a/src/action/action_returngoods.cpp b/src/action/action_returngoods.cpp
index 981c58071..846ada886 100644
--- a/src/action/action_returngoods.cpp
+++ b/src/action/action_returngoods.cpp
@@ -88,7 +88,7 @@ void HandleActionReturnGoods(COrder& order, CUnit &unit)
 	//unit.CurrentOrder()->Arg1.ResourcePos = -1;
 
 	order.NewResetPath();
-	unit.SubAction = /* SUB_MOVE_TO_DEPOT */ 70; // FIXME : Define value.
+	order.SubAction.Res = /* SUB_MOVE_TO_DEPOT */ 70; // FIXME : Define value.
 }
 
 //@}
diff --git a/src/action/action_spellcast.cpp b/src/action/action_spellcast.cpp
index 6276a4da2..2349cd0bb 100644
--- a/src/action/action_spellcast.cpp
+++ b/src/action/action_spellcast.cpp
@@ -54,7 +54,6 @@
 #include "tileset.h"
 #include "map.h"
 #include "spells.h"
-#include "interface.h"
 #include "iolib.h"
 #include "script.h"
 
@@ -81,6 +80,7 @@
 	}
 	file.printf(" \"tile\", {%d, %d},", this->goalPos.x, this->goalPos.y);
 
+	file.printf("\"state\", %d", this->State);
 	file.printf(" \"spell\", \"%s\",\n  ", this->Spell->Ident.c_str());
 
 	SaveDataMove(file);
@@ -96,6 +96,11 @@
 		lua_rawgeti(l, -1, j + 1);
 		this->Spell = SpellTypeByIdent(LuaToString(l, -1));
 		lua_pop(l, 1);
+	} else if (!strcmp(value, "state")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->State = LuaToNumber(l, -1);
+		lua_pop(l, 1);
 	} else {
 		return false;
 	}
@@ -145,45 +150,38 @@ static void AnimateActionSpellCast(CUnit &unit, COrder_SpellCast &order)
 **
 **  @param unit  Unit, for that the spell cast is handled.
 */
-static void SpellMoveToTarget(CUnit &unit)
+bool COrder_SpellCast::SpellMoveToTarget(CUnit &unit)
 {
-	CUnit *goal;
-	int err;
-
 	// Unit can't move
-	err = 1;
+	int err = 1;
 	if (unit.CanMove()) {
 		err = DoActionMove(unit);
 		if (unit.Anim.Unbreakable) {
-			return;
+			return false;
 		}
 	}
 
 	// when reached DoActionMove changes unit action
 	// FIXME: use return codes from pathfinder
-	COrderPtr order = unit.CurrentOrder();
-	goal = order->GetGoal();
+	CUnit *goal = this->GetGoal();
 
-	if (goal && unit.MapDistanceTo(*goal) <= order->Range) {
+	if (goal && unit.MapDistanceTo(*goal) <= this->Range) {
 		// there is goal and it is in range
 		unit.State = 0;
 		UnitHeadingFromDeltaXY(unit, goal->tilePos + goal->Type->GetHalfTileSize() - unit.tilePos);
-		unit.SubAction++; // cast the spell
-		return;
-	} else if (!goal && unit.MapDistanceTo(order->goalPos.x, order->goalPos.y) <= order->Range) {
+		this->State++; // cast the spell
+		return false;
+	} else if (!goal && unit.MapDistanceTo(this->goalPos.x, this->goalPos.y) <= this->Range) {
 		// there is no goal and target spot is in range
-		UnitHeadingFromDeltaXY(unit, order->goalPos - unit.tilePos);
-		unit.SubAction++; // cast the spell
-		return;
+		UnitHeadingFromDeltaXY(unit, this->goalPos - unit.tilePos);
+		this->State++; // cast the spell
+		return false;
 	} else if (err == PF_UNREACHABLE) {
-		//
 		// goal/spot unreachable and out of range -- give up
-		//
-		unit.ClearAction();
 		unit.State = 0;
-		order->ClearGoal(); // Release references
+		return true;
 	}
-	Assert(!unit.Type->Vanishes && !unit.Destroyed);
+	return false;
 }
 
 
@@ -196,7 +194,7 @@ static void SpellMoveToTarget(CUnit &unit)
 		return false;
 	}
 	const SpellType &spell = order.GetSpell();
-	switch (unit.SubAction) {
+	switch (this->State) {
 		case 0:
 			// Check if we can cast the spell.
 			if (!CanCastSpell(unit, &spell, order.GetGoal(), order.goalPos.x, order.goalPos.y)) {
@@ -221,14 +219,16 @@ static void SpellMoveToTarget(CUnit &unit)
 				unit.CurrentOrder()->NewResetPath();
 			}
 			unit.ReCast = 0; // repeat spell on next pass? (defaults to `no')
-			unit.SubAction = 1;
+			this->State = 1;
 			// FALL THROUGH
 		case 1:                         // Move to the target.
 			if (spell.Range && spell.Range != INFINITE_RANGE) {
-				SpellMoveToTarget(unit);
-				break;
+				if (SpellMoveToTarget(unit) == true) {
+					return true;
+				}
+				return false;
 			} else {
-				unit.SubAction = 2;
+				this->State = 2;
 			}
 			// FALL THROUGH
 		case 2:                         // Cast spell on the target.
@@ -252,7 +252,7 @@ static void SpellMoveToTarget(CUnit &unit)
 			break;
 
 		default:
-			unit.SubAction = 0; // Reset path, than move to target
+			this->State = 0; // Reset path, than move to target
 			break;
 	}
 	return false;
diff --git a/src/action/action_stand.cpp b/src/action/action_stand.cpp
index 22c830f95..cb41d2071 100644
--- a/src/action/action_stand.cpp
+++ b/src/action/action_stand.cpp
@@ -38,41 +38,11 @@
 #include "stratagus.h"
 #include "unit.h"
 #include "actions.h"
-#include "iolib.h"
 
 /*----------------------------------------------------------------------------
 --  Functions
 ----------------------------------------------------------------------------*/
 
-
-/* virtual */ void COrder_StandGround::Save(CFile &file, const CUnit &unit) const
-{
-	file.printf("{\"action-stand-ground\"");
-	if (this->HasGoal()) {
-		CUnit &goal = *this->GetGoal();
-		if (goal.Destroyed) {
-			/* this unit is destroyed so it's not in the global unit
-			 * array - this means it won't be saved!!! */
-			printf ("FIXME: storing destroyed Goal - loading will fail.\n");
-		}
-		file.printf(", \"goal\", \"%s\"", UnitReference(goal).c_str());
-	}
-	file.printf("}");
-}
-
-/* virtual */ bool COrder_StandGround::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
-{
-	return false;
-}
-
-/* virtual */ bool COrder_StandGround::Execute(CUnit &unit)
-{
-	ActionStillGeneric(unit, true);
-
-	return false;
-}
-
-
 /**
 **  Unit stands ground!
 **
diff --git a/src/action/action_still.cpp b/src/action/action_still.cpp
index 491498b36..889535c24 100644
--- a/src/action/action_still.cpp
+++ b/src/action/action_still.cpp
@@ -48,16 +48,21 @@
 #include "spells.h"
 #include "player.h"
 #include "iolib.h"
+#include "script.h"
 
-#define SUB_STILL_INIT		0
-#define SUB_STILL_STANDBY	1
-#define SUB_STILL_ATTACK	2
-
-
+enum {
+	SUB_STILL_INIT = 0,
+	SUB_STILL_STANDBY = 1,
+	SUB_STILL_ATTACK = 2
+};
 
 /* virtual */ void COrder_Still::Save(CFile &file, const CUnit &unit) const
 {
-	file.printf("{\"action-still\"");
+	if (this->Action == UnitActionStill) {
+		file.printf("{\"action-still\"");
+	} else {
+		file.printf("{\"action-stand-ground\",");
+	}
 	if (this->HasGoal()) {
 		CUnit &goal = *this->GetGoal();
 		if (goal.Destroyed) {
@@ -65,14 +70,24 @@
 			 * array - this means it won't be saved!!! */
 			printf ("FIXME: storing destroyed Goal - loading will fail.\n");
 		}
-		file.printf(", \"goal\", \"%s\"", UnitReference(goal).c_str());
+		file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str());
 	}
+
+	file.printf(", \"state\", %d", this->State);
 	file.printf("}");
 }
 
 /* virtual */ bool COrder_Still::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
 {
-	return false;
+	if (!strcmp("state", value)) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->State = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else {
+		return false;
+	}
+	return true;
 }
 
 
@@ -92,53 +107,47 @@ void UnHideUnit(CUnit &unit)
 */
 static bool MoveRandomly(CUnit &unit)
 {
-	if (unit.Type->RandomMovementProbability &&
-			((SyncRand() % 100) <= unit.Type->RandomMovementProbability)) {
-		// pick random location
-		Vec2i pos = unit.tilePos;
+	if (unit.Type->RandomMovementProbability == false
+		|| ((SyncRand() % 100) > unit.Type->RandomMovementProbability)) {
+		return false;
+	}
+	// pick random location
+	Vec2i pos = unit.tilePos;
 
-		switch ((SyncRand() >> 12) & 15) {
-			case 0: pos.x++; break;
-			case 1: pos.y++; break;
-			case 2: pos.x--; break;
-			case 3: pos.y--; break;
-			case 4: pos.x++; pos.y++; break;
-			case 5: pos.x--; pos.y++; break;
-			case 6: pos.y--; pos.x++; break;
-			case 7: pos.x--; pos.y--; break;
-			default:
-				break;
-		}
+	switch ((SyncRand() >> 12) & 15) {
+		case 0: pos.x++; break;
+		case 1: pos.y++; break;
+		case 2: pos.x--; break;
+		case 3: pos.y--; break;
+		case 4: pos.x++; pos.y++; break;
+		case 5: pos.x--; pos.y++; break;
+		case 6: pos.y--; pos.x++; break;
+		case 7: pos.x--; pos.y--; break;
+		default:
+			break;
+	}
 
-		// restrict to map
-		if (pos.x < 0) {
-			pos.x = 0;
-		} else if (pos.x >= Map.Info.MapWidth) {
-			pos.x = Map.Info.MapWidth - 1;
-		}
-		if (pos.y < 0) {
-			pos.y = 0;
-		} else if (pos.y >= Map.Info.MapHeight) {
-			pos.y = Map.Info.MapHeight - 1;
-		}
+	// restrict to map
+	if (pos.x < 0) {
+		pos.x = 0;
+	} else if (pos.x >= Map.Info.MapWidth) {
+		pos.x = Map.Info.MapWidth - 1;
+	}
+	if (pos.y < 0) {
+		pos.y = 0;
+	} else if (pos.y >= Map.Info.MapHeight) {
+		pos.y = Map.Info.MapHeight - 1;
+	}
 
-		// move if possible
-		if (pos != unit.tilePos) {
-			UnmarkUnitFieldFlags(unit);
-			if (UnitCanBeAt(unit, pos)) {
-				COrderPtr order = unit.CurrentOrder();
-				// FIXME: Don't use pathfinder for this, costs too much cpu.
-				order->Action = UnitActionMove;
-				Assert(!order->HasGoal());
-				order->ClearGoal();
-				order->Range = 0;
-				order->goalPos = pos;
-				unit.State = 0;
-				//return true;//TESTME: new localization
-			}
+	// move if possible
+	if (pos != unit.tilePos) {
+		UnmarkUnitFieldFlags(unit);
+		if (UnitCanBeAt(unit, pos)) {
 			MarkUnitFieldFlags(unit);
+			CommandMove(unit, pos, FlushCommands);
+			return true;
 		}
-		return true;//TESTME: old localization
+		MarkUnitFieldFlags(unit);
 	}
 	return false;
 }
@@ -152,9 +161,9 @@ bool AutoCast(CUnit &unit)
 {
 	if (unit.AutoCastSpell && !unit.Removed) { // Removed units can't cast any spells, from bunker)
 		for (unsigned int i = 0; i < SpellTypeTable.size(); ++i) {
-			if (unit.AutoCastSpell[i] &&
-				(SpellTypeTable[i]->AutoCast || SpellTypeTable[i]->AICast) &&
-					AutoCastSpell(unit, SpellTypeTable[i])) {
+			if (unit.AutoCastSpell[i]
+				&& (SpellTypeTable[i]->AutoCast || SpellTypeTable[i]->AICast)
+				&& AutoCastSpell(unit, SpellTypeTable[i])) {
 				return true;
 			}
 		}
@@ -189,7 +198,7 @@ static CUnit *UnitToRepairInRange(const CUnit &unit, int range)
 			return &candidate;
 		}
 	}
-	return NoUnitP;
+	return NULL;
 }
 
 /**
@@ -206,7 +215,7 @@ bool AutoRepair(CUnit &unit)
 	}
 	CUnit *repairedUnit = UnitToRepairInRange(unit, repairRange);
 
-	if (repairedUnit == NoUnitP) {
+	if (repairedUnit == NULL) {
 		return false;
 	}
 	const Vec2i invalidPos = {-1, -1};
@@ -221,36 +230,41 @@ bool AutoRepair(CUnit &unit)
 	return true;
 }
 
-/**
-**  Auto attack nearby units if possible
-*/
-bool AutoAttack(CUnit &unit, bool stand_ground)
+bool COrder_Still::AutoAttackStand(CUnit &unit)
 {
 	if (unit.Type->CanAttack == false) {
 		return false;
 	}
+	// Removed units can only attack in AttackRange, from bunker
+	CUnit *goal = AttackUnitsInRange(unit);
 
-	if (stand_ground || unit.Removed || unit.CanMove() == false) {
-		// Removed units can only attack in AttackRange, from bunker
-		CUnit *goal = AttackUnitsInRange(unit);
+	if (goal == NULL) {
+		return false;
+	}
 
-		if (goal == NULL) {
-			return false;
-		}
+	CUnit *oldGoal =this->GetGoal();
+	if (oldGoal && oldGoal->CurrentAction() == UnitActionDie) {
+		this->ClearGoal();
+		oldGoal = NULL;
+	}
+	if (this->State < SUB_STILL_ATTACK || oldGoal != goal) {
+		// New target.
+		this->SetGoal(goal);
+		unit.State = 0;
+		this->State = SUB_STILL_ATTACK; // Mark attacking.
+		UnitHeadingFromDeltaXY(unit, goal->tilePos + goal->Type->GetHalfTileSize() - unit.tilePos);
+	}
+	return true;
+}
 
-		CUnit *temp = unit.CurrentOrder()->GetGoal();
-		if (temp && temp->CurrentAction() == UnitActionDie) {
-			unit.CurrentOrder()->ClearGoal();
-			temp = NoUnitP;
-		}
-		if (unit.SubAction < SUB_STILL_ATTACK || temp != goal) {
-			// New target.
-			unit.CurrentOrder()->SetGoal(goal);
-			unit.State = 0;
-			unit.SubAction = SUB_STILL_ATTACK; // Mark attacking.
-			UnitHeadingFromDeltaXY(unit, goal->tilePos + goal->Type->GetHalfTileSize() - unit.tilePos);
-		}
-		return true;
+
+/**
+**  Auto attack nearby units if possible
+*/
+bool AutoAttack(CUnit &unit)
+{
+	if (unit.Type->CanAttack == false) {
+		return false;
 	}
 	// Normal units react in reaction range.
 	CUnit *goal = AttackUnitsInReactRange(unit);
@@ -258,7 +272,6 @@ bool AutoAttack(CUnit &unit, bool stand_ground)
 	if (goal == NULL) {
 		return false;
 	}
-
 	COrder *savedOrder;
 
 	if (unit.SavedOrder != NULL) {
@@ -268,7 +281,6 @@ bool AutoAttack(CUnit &unit, bool stand_ground)
 	} else {
 		savedOrder = unit.CurrentOrder()->Clone();
 	}
-
 	// Weak goal, can choose other unit, come back after attack
 	CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
 
@@ -279,28 +291,17 @@ bool AutoAttack(CUnit &unit, bool stand_ground)
 }
 
 
-
-/**
-**  Unit stands still or stand ground.
-**
-**  @param unit          Unit pointer for action.
-**  @param stand_ground  true if unit is standing ground.
-*/
-void ActionStillGeneric(CUnit &unit, bool stand_ground)
+/* virtual */ bool COrder_Still::Execute(CUnit &unit)
 {
 	// If unit is not bunkered and removed, wait
 	if (unit.Removed
-		&& (!unit.Container
-			|| !unit.Container->Type->CanTransport()
-			|| !unit.Container->Type->AttackFromTransporter
-			|| unit.Type->Missile.Missile->Class == MissileClassNone)) {
-		// If unit is in building or transporter it is removed.
-		return;
+		&& (unit.Container == NULL || unit.Container->Type->AttackFromTransporter == false)) {
+		return false;
 	}
 
-	switch (unit.SubAction) {
+	switch (this->State) {
 		case SUB_STILL_INIT: //first entry
-			unit.SubAction = SUB_STILL_STANDBY;
+			this->State = SUB_STILL_STANDBY;
 			// no break : follow
 		case SUB_STILL_STANDBY:
 			UnitShowAnimation(unit, unit.Type->Animations->Still);
@@ -309,17 +310,23 @@ void ActionStillGeneric(CUnit &unit, bool stand_ground)
 			AnimateActionAttack(unit);
 		break;
 	}
-
 	if (unit.Anim.Unbreakable) { // animation can't be aborted here
-		return;
+		return false;
 	}
-
-	if ((unit.IsAgressive() && AutoAttack(unit, stand_ground))
-		|| AutoCast(unit)
-		|| AutoRepair(unit)
-		|| MoveRandomly(unit)) {
-		return;
+	if (this->Action == UnitActionStandGround || unit.Removed || unit.CanMove() == false) {
+		if (unit.IsAgressive()) {
+			this->AutoAttackStand(unit);
+			return false;
+		}
+	} else {
+		if ((unit.IsAgressive() && AutoAttack(unit))
+			|| AutoCast(unit)
+			|| AutoRepair(unit)
+			|| MoveRandomly(unit)) {
+			return true;
+		}
 	}
+	return false;
 }
 
 /**
@@ -331,14 +338,11 @@ void HandleActionStill(COrder& order, CUnit &unit)
 {
 	Assert(order.Action == UnitActionStill);
 
-	order.Execute(unit);
+	if (order.Execute(unit)) {
+		unit.ClearAction();
+	}
 }
 
-/* virtual */ bool COrder_Still::Execute(CUnit &unit)
-{
-	ActionStillGeneric(unit, false);
-	return false;
-}
 
 
 //@}
diff --git a/src/action/action_train.cpp b/src/action/action_train.cpp
index d748a4835..822ea8cd7 100644
--- a/src/action/action_train.cpp
+++ b/src/action/action_train.cpp
@@ -48,7 +48,6 @@
 #include "missile.h"
 #include "sound.h"
 #include "ai.h"
-#include "interface.h"
 #include "ui.h"
 #include "iolib.h"
 
diff --git a/src/action/action_unload.cpp b/src/action/action_unload.cpp
index c7d925414..cd52b1f84 100644
--- a/src/action/action_unload.cpp
+++ b/src/action/action_unload.cpp
@@ -42,13 +42,50 @@
 #include "unit.h"
 #include "actions.h"
 #include "map.h"
-#include "interface.h"
 #include "pathfinder.h"
+#include "script.h"
+#include "iolib.h"
 
 /*----------------------------------------------------------------------------
 --  Functions
 ----------------------------------------------------------------------------*/
 
+/* virtual */ void COrder_Unload::Save(CFile &file, const CUnit &unit) const
+{
+	file.printf("{\"action-unload\",");
+	if (this->HasGoal()) {
+		CUnit &goal = *this->GetGoal();
+		if (goal.Destroyed) {
+			/* this unit is destroyed so it's not in the global unit
+			 * array - this means it won't be saved!!! */
+			printf ("FIXME: storing destroyed Goal - loading will fail.\n");
+		}
+		file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str());
+	}
+	file.printf(" \"tile\", {%d, %d}, ", this->goalPos.x, this->goalPos.y);
+	file.printf("\"state\", %d,\n  ");
+	SaveDataMove(file);
+	file.printf("}");
+}
+
+/* virtual */ bool COrder_Unload::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
+{
+	if (this->ParseMoveData(l, j, value) == true) {
+		return true;
+	} else if (!strcmp("state", value)) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->State = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else {
+		return false;
+	}
+	return true;
+}
+
+
+
+
 /**
 **  Find a free position close to startPos
 **
@@ -114,7 +151,7 @@ static bool FindUnloadPosition(const CUnit &transporter, const CUnit &unit, cons
 **
 **  @param unit  Unit to drop out.
 **
-**  @return      True if unit can be unloaded.
+**  @return      True if unit is unloaded.
 **
 **  @bug         FIXME: Place unit only on fields reachable from the transporter
 */
@@ -125,11 +162,12 @@ static int UnloadUnit(CUnit &transporter, CUnit &unit)
 
 	Assert(unit.Removed);
 	if (!FindUnloadPosition(transporter, unit, transporter.tilePos, maxRange, &pos)) {
-		return 0;
+		return false;
 	}
 	unit.Boarded = 0;
 	unit.Place(pos);
-	return 1;
+	transporter.BoardCount--;
+	return true;
 }
 
 /**
@@ -265,38 +303,36 @@ static int MoveToDropZone(CUnit &unit)
 /**
 **  Make one or more unit leave the transporter.
 **
-**  @param unit  Pointer to unit.
+**  @return false if action should continue
 */
-static void LeaveTransporter(CUnit &transporter)
+bool COrder_Unload::LeaveTransporter(CUnit &transporter)
 {
 	int stillonboard = 0;
-	CUnit *goal = transporter.CurrentOrder()->GetGoal();
-	//
+
 	// Goal is the specific unit unit that you want to unload.
 	// This can be NULL, in case you want to unload everything.
-	//
-	if (goal) {
-		if (goal->Destroyed) {
+	if (this->HasGoal()) {
+		CUnit &goal = *this->GetGoal();
+
+		if (goal.Destroyed) {
 			DebugPrint("destroyed unit unloading?\n");
-			transporter.CurrentOrder()->ClearGoal();
-			return;
+			this->ClearGoal();
+			return true;
 		}
 		transporter.CurrentOrder()->ClearGoal();
-		goal->tilePos = transporter.tilePos;
 		// Try to unload the unit. If it doesn't work there is no problem.
-		if (UnloadUnit(transporter, *goal)) {
-			transporter.BoardCount--;
+		if (UnloadUnit(transporter, goal)) {
+			this->ClearGoal();
+		} else {
+			++stillonboard;
 		}
 	} else {
 		// Unload all units.
-		goal = transporter.UnitInside;
+		CUnit *goal = transporter.UnitInside;
 		for (int i = transporter.InsideCount; i; --i, goal = goal->NextContained) {
 			if (goal->Boarded) {
-				goal->tilePos = transporter.tilePos;
 				if (!UnloadUnit(transporter, *goal)) {
 					++stillonboard;
-				} else {
-					transporter.BoardCount--;
 				}
 			}
 		}
@@ -309,15 +345,64 @@ static void LeaveTransporter(CUnit &transporter)
 	if (stillonboard) {
 		// We tell it to unload at it's current position. This can't be done,
 		// so it will search for a piece of free coast nearby.
-		transporter.CurrentOrder()->Action = UnitActionUnload;
-		transporter.CurrentOrder()->ClearGoal();
-		transporter.CurrentOrder()->goalPos = transporter.tilePos;
-		transporter.SubAction = 0;
+		this->State = 0;
+		return false;
 	} else {
-		transporter.ClearAction();
+		return true;
 	}
 }
 
+/* virtual */ bool COrder_Unload::Execute(CUnit &unit)
+{
+	const int maxSearchRange = 20;
+
+	if (!unit.CanMove()) {
+		this->State = 2;
+	}
+	switch (this->State) {
+		case 0: // Choose destination
+			if (!this->HasGoal()) {
+				Vec2i pos;
+
+				if (!ClosestFreeDropZone(unit, this->goalPos, maxSearchRange, &pos)) {
+					return true;
+				}
+				this->goalPos = pos;
+			}
+
+			this->NewResetPath();
+			this->State = 1;
+			// follow on next case
+		case 1: // Move unit to destination
+			// The Goal is the unit that we have to unload.
+			if (!this->HasGoal()) {
+				const int moveResult = MoveToDropZone(unit);
+
+				// We have to unload everything
+				if (moveResult) {
+					if (moveResult == PF_REACHED) {
+						if (++this->State == 1) {
+							return true;
+						}
+					} else {
+						this->State = 2;
+					}
+				}
+				return false;
+			}
+		case 2: { // Leave the transporter
+			// FIXME: show still animations ?
+			if (LeaveTransporter(unit)) {
+				return true;
+			}
+			return false;
+		}
+		default:
+			return false;
+	}
+}
+
+
 /**
 **  The transporter unloads a unit.
 **
@@ -325,52 +410,12 @@ static void LeaveTransporter(CUnit &transporter)
 */
 void HandleActionUnload(COrder& order, CUnit &unit)
 {
-	const int maxSearchRange = 20;
+	Assert(order.Action == UnitActionUnload);
 
-	if (!unit.CanMove()) {
-		unit.SubAction = 2;
-	}
-	switch (unit.SubAction) {
-		case 0: // Choose destination
-			if (!order.HasGoal()) {
-				Vec2i pos;
-
-				if (!ClosestFreeDropZone(unit, order.goalPos, maxSearchRange, &pos)) {
-					// Sorry... I give up.
-					unit.ClearAction();
-					return;
-				}
-				order.goalPos = pos;
-			}
-
-			unit.CurrentOrder()->NewResetPath();
-			unit.SubAction = 1;
-			// follow on next case
-		case 1: // Move unit to destination
-			// The Goal is the unit that we have to unload.
-			if (!unit.CurrentOrder()->HasGoal()) {
-				const int moveResult = MoveToDropZone(unit);
-
-				// We have to unload everything
-				if (moveResult) {
-					if (moveResult == PF_REACHED) {
-						if (++unit.SubAction == 1) {
-							unit.ClearAction();
-						}
-					} else {
-						unit.SubAction = 2;
-					}
-				}
-				break;
-			}
-		case 2: // Leave the transporter
-			// FIXME: show still animations ?
-			LeaveTransporter(unit);
-			if (unit.CanMove() && unit.CurrentAction() != UnitActionStill) {
-				HandleActionUnload(*unit.CurrentOrder() , unit);
-			}
-			break;
+	if (order.Execute(unit)) {
+		unit.ClearAction();
 	}
 }
 
+
 //@}
diff --git a/src/action/actions.cpp b/src/action/actions.cpp
index 0d9dd4b52..15159991a 100644
--- a/src/action/actions.cpp
+++ b/src/action/actions.cpp
@@ -47,7 +47,6 @@
 #include "player.h"
 #include "unit.h"
 #include "missile.h"
-#include "interface.h"
 #include "map.h"
 #include "sound.h"
 #include "spells.h"
@@ -133,7 +132,7 @@ unsigned SyncHash; /// Hash calculated to find sync failures
 
 /* static */ COrder* COrder::NewActionBoard(CUnit &unit)
 {
-	COrder *order = new COrder(UnitActionBoard);
+	COrder_Board *order = new COrder_Board;
 
 	order->SetGoal(&unit);
 	order->Range = 1;
@@ -234,7 +233,7 @@ unsigned SyncHash; /// Hash calculated to find sync failures
 
 /* static */ COrder* COrder::NewActionRepair(CUnit &unit, CUnit &target)
 {
-	COrder *order = new COrder(UnitActionRepair);
+	COrder_Repair *order = new COrder_Repair();
 
 	if (target.Destroyed) {
 		order->goalPos = target.tilePos + target.Type->GetHalfTileSize();
@@ -249,14 +248,13 @@ unsigned SyncHash; /// Hash calculated to find sync failures
 {
 	Assert(Map.Info.IsPointOnMap(pos));
 
-	COrder *order = new COrder(UnitActionRepair);
+	COrder_Repair *order = new COrder_Repair;
 
 	order->goalPos = pos;
 	return order;
 }
 
 
-
 /* static */ COrder* COrder::NewActionResearch(CUnit &unit, CUpgrade &upgrade)
 {
 	COrder_Research *order = new COrder_Research();
@@ -350,17 +348,14 @@ unsigned SyncHash; /// Hash calculated to find sync failures
 
 /* static */ COrder* COrder::NewActionStandGround()
 {
-	return new COrder_StandGround;
+	return new COrder_Still(true);
 }
 
 /* static */ COrder* COrder::NewActionStill()
 {
-	return new COrder_Still;
+	return new COrder_Still(false);
 }
 
-
-
-
 /* static */ COrder* COrder::NewActionTrain(CUnit &trainer, CUnitType &type)
 {
 	COrder_Train *order = new COrder_Train;
@@ -383,7 +378,7 @@ unsigned SyncHash; /// Hash calculated to find sync failures
 
 /* static */ COrder* COrder::NewActionUnload(const Vec2i &pos, CUnit *what)
 {
-	COrder *order = new COrder(UnitActionUnload);
+	COrder *order = new COrder_Unload;
 
 	order->goalPos = pos;
 	if (what && !what->Destroyed) {
@@ -452,7 +447,7 @@ void COrder::ReleaseRefs(CUnit &unit)
 	if (this->HasGoal()) {
 		// If mining decrease the active count on the resource.
 		if (this->Action == UnitActionResource) {
-			if (unit.SubAction == 60 /* SUB_GATHER_RESOURCE */ ) {
+			if (this->SubAction.Res == 60 /* SUB_GATHER_RESOURCE */ ) {
 				CUnit *goal = this->GetGoal();
 
 				goal->Resource.Active--;
@@ -460,7 +455,7 @@ void COrder::ReleaseRefs(CUnit &unit)
 			}
 		}
 		// Still shouldn't have a reference unless attacking
-		Assert(!(this->Action == UnitActionStill && !unit.SubAction));
+		Assert(!(this->Action == UnitActionStill && !SubAction.Attack));
 		this->ClearGoal();
 	}
 #ifdef DEBUG
@@ -525,11 +520,11 @@ bool COrder::OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/)
 			// Maybe AI should cancel action and save resources ???
 			return true;
 		case UnitActionResource:
-			if (unit.SubAction >= 65) {
+			if (SubAction.Res >= 65) {
 				//Normal return to depot
 				return true;
 			}
-			if (unit.SubAction > 55  &&
+			if (SubAction.Res > 55  &&
 				unit.ResourcesHeld > 0) {
 				//escape to Depot with this what you have;
 				Data.ResWorker.DoneHarvesting = 1;
@@ -1564,10 +1559,7 @@ static void HandleUnitAction(CUnit &unit)
 			delete unit.Orders[0];
 			unit.Orders.erase(unit.Orders.begin());
 
-			//
-			// Note subaction 0 should reset.
-			//
-			unit.SubAction = unit.State = 0;
+			unit.State = 0;
 			unit.Wait = 0;
 
 			if (IsOnlySelected(unit)) { // update display for new action
@@ -1721,7 +1713,7 @@ void UnitActions()
 		SyncHash = (SyncHash << 5) | (SyncHash >> 27);
 		SyncHash ^= unit.Orders.size() > 0 ? unit.CurrentAction() << 18 : 0;
 		SyncHash ^= unit.State << 12;
-		SyncHash ^= unit.SubAction << 6;
+//		SyncHash ^= unit.SubAction << 6;
 		SyncHash ^= unit.Refs << 3;
 	}
 }
diff --git a/src/action/command.cpp b/src/action/command.cpp
index dfb4f465f..18c28e678 100644
--- a/src/action/command.cpp
+++ b/src/action/command.cpp
@@ -47,7 +47,6 @@
 #include "upgrade.h"
 #include "pathfinder.h"
 #include "spells.h"
-#include "interface.h"
 #include "ui.h"
 
 /*----------------------------------------------------------------------------
@@ -107,9 +106,6 @@ static void RemoveOrder(CUnit &unit, unsigned int order)
 
 	delete unit.Orders[order];
 	unit.Orders.erase(unit.Orders.begin() + order);
-	if (order == 0) {
-		unit.SubAction = 0;
-	}
 	if (unit.Orders.empty()) {
 		unit.Orders.push_back(COrder::NewActionStill());
 	}
diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp
index 579a6fd83..c4d7f3d62 100644
--- a/src/ai/ai_resource.cpp
+++ b/src/ai/ai_resource.cpp
@@ -238,10 +238,15 @@ static int AiBuildBuilding(const CUnitType &type, CUnitType &building, int near_
 			int action = unit.Orders[j]->Action;
 			if (action == UnitActionBuild ||
 				action == UnitActionRepair ||
-				action == UnitActionReturnGoods ||
-				(action == UnitActionResource &&
-					 unit.SubAction > 55) /* SUB_START_GATHERING */) {
-				break;
+				action == UnitActionReturnGoods) {
+					break;
+				}
+			if (action == UnitActionResource) {
+				const COrder &order = *unit.Orders[j];
+
+				if (order.SubAction.Res > 55 /* SUB_START_GATHERING */) {
+					break;
+				}
 			}
 		}
 		if (j == unit.Orders.size()) {
@@ -1093,7 +1098,9 @@ static void AiCollectResources()
 					for (int k = num_units_assigned[src_c] - 1; k >= 0 && !unit; --k) {
 						unit = units_assigned[src_c][k];
 
-						if (unit->SubAction >= 65 /* SUB_STOP_GATHERING */ ) {
+						COrder &order = *unit->CurrentOrder();
+
+						if (order.SubAction.Res >= 65 /* SUB_STOP_GATHERING */ ) {
 							//worker returning with resource
 							continue;
 						}
@@ -1162,10 +1169,16 @@ static int AiRepairBuilding(const CUnitType &type, CUnit &building)
 	for (int i = 0; i < nunits; ++i) {
 		CUnit &unit = *table[i];
 
-		if (unit.Type->RepairRange && unit.Orders.size() == 1 &&
-			((unit.CurrentAction() == UnitActionResource && unit.SubAction <= 55) /* SUB_START_GATHERING */ ||
-				unit.CurrentAction() == UnitActionStill)) {
-			table[num++] = &unit;
+		if (unit.Type->RepairRange && unit.Orders.size() == 1) {
+			if (unit.CurrentAction() == UnitActionStill) {
+				table[num++] = &unit;
+			} else if (unit.CurrentAction() == UnitActionResource) {
+				COrder &order = *unit.CurrentOrder();
+
+				if (order.SubAction.Res <= 55 /* SUB_START_GATHERING */) {
+					table[num++] = &unit;
+				}
+			}
 		}
 	}
 
diff --git a/src/include/actions.h b/src/include/actions.h
index e30c5cf46..f6abac63f 100644
--- a/src/include/actions.h
+++ b/src/include/actions.h
@@ -108,6 +108,7 @@ public:
 		goalPos.x = -1;
 		goalPos.y = -1;
 		memset(&Arg1, 0, sizeof (Arg1));
+		memset(&SubAction, 0, sizeof (SubAction));
 		memset(&Data, 0, sizeof (Data));
 	}
 	virtual ~COrder();
@@ -170,10 +171,8 @@ public:
 #if 1 // currently needed for parsing
 	static COrder* NewActionAttack() { return new COrder(UnitActionAttack); }
 	static COrder* NewActionAttackGround() { return new COrder(UnitActionAttackGround); }
-	static COrder* NewActionBoard() { return new COrder(UnitActionBoard); }
 	static COrder* NewActionFollow() { return new COrder(UnitActionFollow); }
 	static COrder* NewActionMove() { return new COrder(UnitActionMove); }
-	static COrder* NewActionRepair() { return new COrder(UnitActionRepair); }
 	static COrder* NewActionResource() { return new COrder(UnitActionResource); }
 	static COrder* NewActionReturnGoods() { return new COrder(UnitActionReturnGoods); }
 	static COrder* NewActionUnload() { return new COrder(UnitActionUnload); }
@@ -199,6 +198,13 @@ public:
 		} Resource;
 	} Arg1;             /// Extra command argument.
 
+	union {
+		int Attack;
+		int Follow;
+		int Res;
+	} SubAction;
+
+
 	union _order_data_ {
 	struct _order_move_ {
 		unsigned short int Cycles;          /// how much Cycles we move.
@@ -211,17 +217,34 @@ public:
 		int TimeToHarvest;          /// how much time until we harvest some more.
 		unsigned DoneHarvesting:1;  /// Harvesting done, wait for action to break.
 	} ResWorker; /// Worker harvesting
-	struct _order_repair_ {
-		int Cycles;                 /// Cycles unit has been repairing for
-	} Repair; /// Repairing unit
 	} Data; /// Storage room for different commands
 };
 
+class COrder_Board : public COrder
+{
+	friend COrder* COrder::NewActionBoard(CUnit &unit);
+public:
+	COrder_Board() : COrder(UnitActionBoard), State(0) {}
+
+	virtual COrder_Board *Clone() const { return new COrder_Board(*this); }
+
+	virtual void Save(CFile &file, const CUnit &unit) const;
+	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
+
+	virtual bool Execute(CUnit &unit);
+
+private:
+	bool WaitForTransporter(CUnit &unit);
+
+private:
+	int State;
+};
+
 class COrder_Build : public COrder
 {
 	friend COrder* COrder::NewActionBuild(const CUnit &builder, const Vec2i &pos, CUnitType &building);
 public:
-	COrder_Build() : COrder(UnitActionBuild), Type(NULL) {}
+	COrder_Build() : COrder(UnitActionBuild), Type(NULL), State(0) {}
 
 	virtual COrder_Build *Clone() const { return new COrder_Build(*this); }
 
@@ -235,11 +258,14 @@ public:
 	const CUnitType& GetUnitType() const { return *Type; }
 
 private:
+	bool MoveToLocation(CUnit &unit);
+	CUnit *CheckCanBuild(CUnit &unit);
 	bool StartBuilding(CUnit &unit, CUnit &ontop);
 	bool BuildFromOutside(CUnit &unit) const;
 private:
 	CUnitType *Type;        /// build a unit of this unit-type
 	CUnitPtr BuildingUnit;  /// unit builded.
+	int State;
 };
 
 
@@ -298,7 +324,7 @@ class COrder_Patrol : public COrder
 {
 	friend COrder* COrder::NewActionPatrol(const Vec2i &currentPos, const Vec2i &dest);
 public:
-	COrder_Patrol() : COrder(UnitActionPatrol) {}
+	COrder_Patrol() : COrder(UnitActionPatrol), WaitingCycle(0) {}
 
 	virtual COrder_Patrol *Clone() const { return new COrder_Patrol(*this); }
 
@@ -310,8 +336,30 @@ public:
 	const Vec2i& GetWayPoint() const { return WayPoint; }
 private:
 	Vec2i WayPoint; /// position for patroling.
+	unsigned int WaitingCycle; /// number of cycle pathfinder wait.
 };
 
+class COrder_Repair : public COrder
+{
+	friend COrder* COrder::NewActionRepair(CUnit &unit, CUnit &target);
+	friend COrder* COrder::NewActionRepair(const Vec2i &pos);
+public:
+	COrder_Repair() : COrder(UnitActionRepair), State(0), RepairCycle(0) {}
+
+	virtual COrder_Repair *Clone() const { return new COrder_Repair(*this); }
+
+	virtual void Save(CFile &file, const CUnit &unit) const;
+	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
+
+	virtual bool Execute(CUnit &unit);
+private:
+	bool RepairUnit(const CUnit &unit, CUnit &goal);
+private:
+	unsigned int State;
+	unsigned int RepairCycle;
+};
+
+
 
 class COrder_Research : public COrder
 {
@@ -337,7 +385,7 @@ private:
 class COrder_SpellCast : public COrder
 {
 public:
-	COrder_SpellCast() : COrder(UnitActionSpellCast), Spell(NULL) {}
+	COrder_SpellCast() : COrder(UnitActionSpellCast), Spell(NULL), State(0) {}
 
 	virtual COrder_SpellCast *Clone() const { return new COrder_SpellCast(*this); }
 
@@ -350,30 +398,17 @@ public:
 
 	const SpellType& GetSpell() const { return *Spell; }
 	void SetSpell(SpellType &spell) { Spell = &spell; }
+private:
+	bool SpellMoveToTarget(CUnit &unit);
 private:
 	SpellType *Spell;
-};
-
-
-
-
-class COrder_StandGround : public COrder
-{
-public:
-	COrder_StandGround() : COrder(UnitActionStandGround) {}
-
-	virtual COrder_StandGround *Clone() const { return new COrder_StandGround(*this); }
-
-	virtual void Save(CFile &file, const CUnit &unit) const;
-	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
-
-	virtual bool Execute(CUnit &unit);
+	int State;
 };
 
 class COrder_Still : public COrder
 {
 public:
-	COrder_Still() : COrder(UnitActionStill) {}
+	COrder_Still(bool stand) : COrder(stand ? UnitActionStandGround : UnitActionStill), State(0) {}
 
 	virtual COrder_Still *Clone() const { return new COrder_Still(*this); }
 
@@ -381,12 +416,13 @@ public:
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
 	virtual bool Execute(CUnit &unit);
+private:
+	bool AutoAttackStand(CUnit &unit);
+private:
+	int State;
 };
 
 
-
-
-
 class COrder_Train : public COrder
 {
 	friend COrder* COrder::NewActionTrain(CUnit &trainer, CUnitType &type);
@@ -429,6 +465,27 @@ private:
 };
 
 
+
+class COrder_Unload : public COrder
+{
+	friend COrder* COrder::NewActionUnload(const Vec2i &pos, CUnit *what);
+public:
+	COrder_Unload() : COrder(UnitActionUnload), State(0) {}
+
+	virtual COrder_Unload *Clone() const { return new COrder_Unload(*this); }
+
+	virtual void Save(CFile &file, const CUnit &unit) const;
+	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
+
+	virtual bool Execute(CUnit &unit);
+
+private:
+	bool LeaveTransporter(CUnit &transporter);
+private:
+	int State;
+};
+
+
 class COrder_UpgradeTo : public COrder
 {
 	friend COrder* COrder::NewActionUpgradeTo(CUnit &unit, CUnitType &type);
@@ -451,7 +508,6 @@ private:
 	int Ticks;       /// Ticks to complete
 };
 
-
 /*----------------------------------------------------------------------------
 --  Variables
 ----------------------------------------------------------------------------*/
@@ -535,7 +591,7 @@ extern void CommandSharedVision(int player, bool state, int opponent);
 extern void DropResource(CUnit &unit);
 extern void ResourceGiveUp(CUnit &unit);
 extern int GetNumWaitingWorkers(const CUnit &mine);
-extern bool AutoAttack(CUnit &unit, bool stand_ground);
+extern bool AutoAttack(CUnit &unit);
 extern bool AutoRepair(CUnit &unit);
 extern bool AutoCast(CUnit &unit);
 
@@ -543,8 +599,6 @@ extern void UnHideUnit(CUnit &unit);
 
 typedef void HandleActionFunc(COrder& order, CUnit &unit);
 
-	/// Generic still action
-extern void ActionStillGeneric(CUnit &unit, bool stand_ground);
 	/// Handle command still
 extern HandleActionFunc HandleActionStill;
 	/// Handle command stand ground
diff --git a/src/include/unit.h b/src/include/unit.h
index 48eecbf47..1cf8597c2 100644
--- a/src/include/unit.h
+++ b/src/include/unit.h
@@ -269,12 +269,6 @@
 **  in a harvester.
 **  @todo continue documentation
 **
-**  CUnit::SubAction
-**
-**  This is an action private variable, it is zero on the first
-**  entry of an action. Must be set to zero, if an action finishes.
-**  It should only be used inside of actions.
-**
 **  CUnit::Wait
 **
 **  The unit is forced too wait for that many cycles. Be carefull,
@@ -514,7 +508,6 @@ public:
 
 	unsigned char DamagedType;   /// Index of damage type of unit which damaged this unit
 	unsigned long Attacked; /// gamecycle unit was last attacked
-	unsigned SubAction : 8; /// sub-action of unit
 	unsigned State : 8;     /// action state
 	unsigned Blink : 3;     /// Let selection rectangle blink
 	unsigned Moving : 1;    /// The unit is moving
diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp
index 8c087697b..fea37faaf 100644
--- a/src/unit/script_unit.cpp
+++ b/src/unit/script_unit.cpp
@@ -252,7 +252,14 @@ bool COrder::ParseMoveData(lua_State *l, int &j, const char *value)
 
 bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
 {
-	if (!strcmp(value, "current-resource")) {
+	if (this->ParseMoveData(l, j, value)) {
+		return true;
+	} else if (!strcmp(value, "subaction")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->SubAction.Attack = this->SubAction.Follow = this->SubAction.Res = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "current-resource")) {
 		++j;
 		lua_rawgeti(l, -1, j + 1);
 		this->CurrentResource = CclGetResourceByName(l);
@@ -324,9 +331,9 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
 	lua_pop(l, 1);
 
 	if (!strcmp(actiontype, "action-still")) {
-		*orderPtr = new COrder_Still;
+		*orderPtr = new COrder_Still(false);
 	} else if (!strcmp(actiontype, "action-stand-ground")) {
-		*orderPtr = new COrder_StandGround;
+		*orderPtr = new COrder_Still(true);
 	} else if (!strcmp(actiontype, "action-follow")) {
 		*orderPtr = COrder::NewActionFollow();
 	} else if (!strcmp(actiontype, "action-move")) {
@@ -348,7 +355,7 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
 	} else if (!strcmp(actiontype, "action-built")) {
 		*orderPtr = new COrder_Built;
 	} else if (!strcmp(actiontype, "action-board")) {
-		*orderPtr = COrder::NewActionBoard();
+		*orderPtr = new COrder_Board;
 	} else if (!strcmp(actiontype, "action-unload")) {
 		*orderPtr = COrder::NewActionUnload();
 	} else if (!strcmp(actiontype, "action-patrol")) {
@@ -356,13 +363,13 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
 	} else if (!strcmp(actiontype, "action-build")) {
 		*orderPtr = new COrder_Build;
 	} else if (!strcmp(actiontype, "action-repair")) {
-		*orderPtr = COrder::NewActionRepair();
+		*orderPtr = new COrder_Repair;
 	} else if (!strcmp(actiontype, "action-resource")) {
 		*orderPtr = COrder::NewActionResource();
 	} else if (!strcmp(actiontype, "action-return-goods")) {
 		*orderPtr = COrder::NewActionReturnGoods();
 	} else if (!strcmp(actiontype, "action-transform-into")) {
-		*orderPtr = new COrder_TransformInto();
+		*orderPtr = new COrder_TransformInto;
 	} else {
 		LuaError(l, "ParseOrder: Unsupported type: %s" _C_ actiontype);
 	}
@@ -591,8 +598,6 @@ static int CclUnit(lua_State *l)
 			lua_pushvalue(l, j + 1);
 			unit->CurrentResource = CclGetResourceByName(l);
 			lua_pop(l, 1);
-		} else if (!strcmp(value, "sub-action")) {
-			unit->SubAction = LuaToNumber(l, j + 1);
 		} else if (!strcmp(value, "wait")) {
 			unit->Wait = LuaToNumber(l, j + 1);
 		} else if (!strcmp(value, "state")) {
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 6808bdcf8..01a9f92ac 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -170,7 +170,6 @@ void CUnit::Init()
 	GroupId = 0;
 	LastGroup = 0;
 	ResourcesHeld = 0;
-	SubAction = 0;
 	Wait = 0;
 	State = 0;
 	Blink = 0;
@@ -268,7 +267,6 @@ void CUnit::ClearAction()
 	delete CurrentOrder();
 	Orders[0] = COrder::NewActionStill();
 
-	SubAction = 0;
 	if (Selected) {
 		SelectedUnitChanged();
 	}
@@ -372,7 +370,6 @@ bool CUnit::RestoreOrder()
 
 	// Restart order state.
 	this->State = 0;
-	this->SubAction = 0;
 
 	// Cannot delete this->Orders[0] since it is generally that order
 	// which call this method.
@@ -1064,7 +1061,7 @@ void UnitClearOrders(CUnit &unit)
 	}
 	unit.Orders.clear();
 	unit.Orders.push_back(COrder::NewActionStill());
-	unit.SubAction = unit.State = 0;
+	unit.State = 0;
 }
 
 /**
@@ -2136,7 +2133,6 @@ void DropOutAll(const CUnit &source)
 		DropOutOnSide(*unit, LookingW, &source);
 		Assert(!unit->CurrentOrder()->HasGoal());
 		unit->CurrentOrder()->Action = UnitActionStill;
-		unit->SubAction = 0;
 	}
 }
 
@@ -2821,7 +2817,6 @@ void LetUnitDie(CUnit &unit)
 	// Unit has death animation.
 
 	// Not good: UnitUpdateHeading(unit);
-	unit.SubAction = 0;
 	unit.State = 0;
 	delete unit.Orders[0];
 	unit.Orders[0] = COrder::NewActionDie();
diff --git a/src/unit/unit_draw.cpp b/src/unit/unit_draw.cpp
index 6d5d9a2c3..f5e272091 100644
--- a/src/unit/unit_draw.cpp
+++ b/src/unit/unit_draw.cpp
@@ -757,7 +757,8 @@ static void ShowSingleOrder(const CUnit &unit, const PixelPos &pos, const COrder
 			pos2 = CurrentViewport->TilePosToScreen_Center(order.goalPos);
 			// FALL THROUGH
 		case UnitActionAttack:
-			if (unit.SubAction & 2) { // Show weak targets.
+		{
+			if (order.SubAction.Attack & 2) { // Show weak targets.
 				e_color = ColorBlue;
 			} else {
 				e_color = ColorRed;
@@ -765,7 +766,7 @@ static void ShowSingleOrder(const CUnit &unit, const PixelPos &pos, const COrder
 			color = ColorRed;
 			dest = true;
 			break;
-
+		}
 		case UnitActionBoard:
 			e_color = color = ColorGreen;
 			dest = true;
diff --git a/src/unit/unit_save.cpp b/src/unit/unit_save.cpp
index acc3f0852..15eb222aa 100644
--- a/src/unit/unit_save.cpp
+++ b/src/unit/unit_save.cpp
@@ -108,15 +108,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
 		case UnitActionAttackGround:
 			file.printf("\"action-attack-ground\",");
 			break;
-		case UnitActionBoard:
-			file.printf("\"action-board\",");
-			break;
-		case UnitActionUnload:
-			file.printf("\"action-unload\",");
-			break;
-		case UnitActionRepair:
-			file.printf("\"action-repair\",");
-			break;
 		case UnitActionResource:
 			file.printf("\"action-resource\",");
 			break;
@@ -142,6 +133,21 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
 	}
 	file.printf(" \"tile\", {%d, %d}", order.goalPos.x, order.goalPos.y);
 
+	switch (order.Action) {
+		case UnitActionAttack:
+		case UnitActionAttackGround:
+			file.printf(", \"subaction\", %d", order.SubAction.Attack);
+			break;
+		case UnitActionFollow:
+			file.printf(", \"subaction\", %d", order.SubAction.Follow);
+			break;
+		case UnitActionResource:
+		case UnitActionReturnGoods:
+			file.printf(", \"subaction\", %d", order.SubAction.Res);
+			break;
+	}
+
+
 	// Extra arg.
 	switch (order.Action) {
 		case UnitActionResource :
@@ -330,17 +336,6 @@ void SaveUnit(const CUnit &unit, CFile *file)
 		file->printf("\"current-resource\", \"%s\",\n  ",
 			DefaultResourceNames[unit.CurrentResource].c_str());
 	}
-	if (unit.SubAction && unit.IsAgressive() &&
-		(unit.CurrentAction() == UnitActionStill ||
-		unit.CurrentAction() == UnitActionStandGround))
-	{
-		//Force recalculate Guard points
-		//if unit atack from StandGround then attac target is recalculate
-		//When unit first time handle action code.
-		file->printf("\"sub-action\", 0, ");
-	} else	{
-		file->printf("\"sub-action\", %d, ", unit.SubAction);
-	}
 	file->printf("\"wait\", %d, ", unit.Wait);
 	file->printf("\"state\", %d,", unit.State);
 	file->printf("\"anim-wait\", %d,", unit.Anim.Wait);