From 256227dedeead88854a01b312974471781d97781 Mon Sep 17 00:00:00 2001
From: joris <joris.dauphin@gmail.com>
Date: Mon, 20 Feb 2012 12:24:22 +0100
Subject: [PATCH] Remove copy of order (use clone instead make new method to
 parse luaState Now COrder may be derivated :-)

---
 src/action/action_attack.cpp |   8 +-
 src/action/action_follow.cpp |   5 +-
 src/action/action_patrol.cpp |   2 +-
 src/action/action_still.cpp  |   2 +-
 src/action/action_train.cpp  |   3 +-
 src/action/actions.cpp       | 186 +++++++++++++----
 src/include/actions.h        |  30 ++-
 src/unit/script_unit.cpp     | 386 +++++++++++++++++++----------------
 src/unit/unit.cpp            |   2 +-
 9 files changed, 396 insertions(+), 228 deletions(-)

diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp
index a829b457a..8dfbd3d65 100644
--- a/src/action/action_attack.cpp
+++ b/src/action/action_attack.cpp
@@ -166,7 +166,7 @@ static int CheckForTargetInRange(CUnit &unit)
 		CUnit *temp = AttackUnitsInReactRange(unit);
 
 		if (temp && temp->Type->Priority > goal->Type->Priority) {
-			COrder *savedOrder = new COrder(*order);
+			COrder *savedOrder = order->Clone();
 
 			if (unit.StoreOrder(savedOrder) == false) {
 				delete savedOrder;
@@ -324,7 +324,7 @@ static void AttackTarget(CUnit &unit)
 			return;
 		}
 		// Save current command to come back.
-		COrder *savedOrder = new COrder(*order);
+		COrder *savedOrder = order->Clone();
 
 		if (unit.StoreOrder(savedOrder) == false) {
 			delete savedOrder;
@@ -345,7 +345,7 @@ static void AttackTarget(CUnit &unit)
 		if ((unit.SubAction & WEAK_TARGET)) {
 			CUnit *temp = AttackUnitsInReactRange(unit);
 			if (temp && temp->Type->Priority > goal->Type->Priority) {
-				COrder *savedOrder = new COrder(*order);
+				COrder *savedOrder = order->Clone();
 
 				if (unit.StoreOrder(savedOrder) == false) {
 					delete savedOrder;
@@ -366,7 +366,7 @@ static void AttackTarget(CUnit &unit)
 	//
 	int dist = unit.MapDistanceTo(*goal);
 	if (dist > unit.Stats->Variables[ATTACKRANGE_INDEX].Max) {
-		COrder *savedOrder = new COrder(*order);
+		COrder *savedOrder = order->Clone();
 
 		if (unit.StoreOrder(savedOrder) == false) {
 			delete savedOrder;
diff --git a/src/action/action_follow.cpp b/src/action/action_follow.cpp
index 34c06b499..ab821e0de 100644
--- a/src/action/action_follow.cpp
+++ b/src/action/action_follow.cpp
@@ -154,7 +154,8 @@ void HandleActionFollow(COrder& order, CUnit &unit)
 						}
 					}
 
-					*(unit.CurrentOrder()) = *dest.NewOrder;
+					delete unit.CurrentOrder();
+					unit.Orders[0] = dest.NewOrder->Clone();
 					unit.CurrentResource = dest.CurrentResource;
 				}
 				return;
@@ -186,7 +187,7 @@ void HandleActionFollow(COrder& order, CUnit &unit)
 			goal = AttackUnitsInReactRange(unit);
 			if (goal) {
 				// Save current command to come back.
-				COrder *savedOrder = new COrder(order);
+				COrder *savedOrder = order.Clone();
 
 				CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
 
diff --git a/src/action/action_patrol.cpp b/src/action/action_patrol.cpp
index 3124199ec..7e5cceafa 100644
--- a/src/action/action_patrol.cpp
+++ b/src/action/action_patrol.cpp
@@ -129,7 +129,7 @@ void HandleActionPatrol(COrder& order, CUnit &unit)
 			const CUnit *goal = AttackUnitsInReactRange(unit);
 			if (goal) {
 				// Save current command to come back.
-				COrder *savedOrder = new COrder(order);
+				COrder *savedOrder = order.Clone();
 
 				DebugPrint("Patrol attack %d\n" _C_ UnitNumber(*goal));
 				CommandAttack(unit, goal->tilePos, NULL, FlushCommands);
diff --git a/src/action/action_still.cpp b/src/action/action_still.cpp
index c77fef82f..ead9d330d 100644
--- a/src/action/action_still.cpp
+++ b/src/action/action_still.cpp
@@ -244,7 +244,7 @@ bool AutoRepair(CUnit &unit)
 
 		if (repairedUnit != NoUnitP) {
 			const Vec2i invalidPos = {-1, -1};
-			COrder *savedOrder = new COrder(*unit.CurrentOrder());
+			COrder *savedOrder = unit.CurrentOrder()->Clone();
 
 			//Command* will clear unit.SavedOrder
 			CommandRepair(unit, invalidPos, repairedUnit, FlushCommands);
diff --git a/src/action/action_train.cpp b/src/action/action_train.cpp
index af3103c35..93713a40e 100644
--- a/src/action/action_train.cpp
+++ b/src/action/action_train.cpp
@@ -192,7 +192,8 @@ void HandleActionTrain(COrder& order, CUnit &unit)
 			}
 
 			if (CanHandleOrder(*nunit, unit.NewOrder) == true) {
-				*(nunit->CurrentOrder()) = *unit.NewOrder;
+				delete nunit->CurrentOrder();
+				nunit->Orders[0] = unit.NewOrder->Clone();
 #if 0
 			} else {
 				// Tell the unit to move instead of trying any funny stuff.
diff --git a/src/action/actions.cpp b/src/action/actions.cpp
index c6b299209..775805297 100644
--- a/src/action/actions.cpp
+++ b/src/action/actions.cpp
@@ -90,24 +90,6 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
 --  Functions
 ----------------------------------------------------------------------------*/
 
-COrder::COrder(const COrder &rhs): Goal(rhs.Goal), Range(rhs.Range),
-	 MinRange(rhs.MinRange), Width(rhs.Width), Height(rhs.Height),
-	 Action(rhs.Action), CurrentResource(rhs.CurrentResource),
-	 goalPos(rhs.goalPos)
- {
-	if (Goal) {
-		Goal->RefsIncrease();
-	}
-
-	memcpy(&Arg1, &rhs.Arg1, sizeof(Arg1));
-	memcpy(&Data, &rhs.Data, sizeof (Data));
-	if (Action == UnitActionResource && Arg1.Resource.Mine) {
-		Arg1.Resource.Mine->RefsIncrease();
-	}
-}
-
-
-
 /* static */ COrder* COrder::NewActionAttack(const CUnit &attacker, CUnit &target)
 {
 	COrder *order = new COrder;
@@ -445,24 +427,158 @@ COrder::COrder(const COrder &rhs): Goal(rhs.Goal), Range(rhs.Range),
 	return order;
 }
 
-COrder& COrder::operator=(const COrder &rhs) {
-	if (this != &rhs) {
-		Action = rhs.Action;
-		Range = rhs.Range;
-		MinRange = rhs.MinRange;
-		Width = rhs.Width;
-		Height = rhs.Height;
-		CurrentResource = rhs.CurrentResource;
-		SetGoal(rhs.Goal);
-		goalPos = rhs.goalPos;
-		memcpy(&Arg1, &rhs.Arg1, sizeof(Arg1));
-		memcpy(&Data, &rhs.Data, sizeof (Data));
-		//FIXME: Hardcoded wood
-		if (Action == UnitActionResource && Arg1.Resource.Mine) {
-			Arg1.Resource.Mine->RefsIncrease();
-		}
+#if 1 // currently needed for parsing
+/* static */ COrder* COrder::NewActionAttack()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionAttack;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionAttackGround()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionAttackGround;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionBoard()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionBoard;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionBuild()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionBuild;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionFollow()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionFollow;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionMove()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionMove;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionPatrol()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionPatrol;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionRepair()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionRepair;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionResearch()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionResearch;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionResource()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionResource;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionReturnGoods()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionReturnGoods;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionSpellCast()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionSpellCast;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionTrain()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionTrain;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionTransformInto()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionTransformInto;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionUnload()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionUnload;
+	return order;
+}
+
+/* static */ COrder* COrder::NewActionUpgradeTo()
+{
+	COrder *order = new COrder;
+
+	order->Action = UnitActionUpgradeTo;
+	return order;
+}
+
+#endif
+
+
+
+COrder* COrder::Clone() const
+{
+	COrder *clone = new COrder();
+
+	clone->Action = this->Action;
+	clone->Range = this->Range;
+	clone->MinRange = this->MinRange;
+	clone->Width = this->Width;
+	clone->Height = this->Height;
+	clone->CurrentResource = this->CurrentResource;
+	clone->SetGoal(this->Goal);
+	clone->goalPos = this->goalPos;
+	memcpy(&clone->Arg1, &this->Arg1, sizeof (clone->Arg1));
+	memcpy(&clone->Data, &this->Data, sizeof (clone->Data));
+	//FIXME: Hardcoded wood
+	if (clone->Action == UnitActionResource && clone->Arg1.Resource.Mine) {
+		clone->Arg1.Resource.Mine->RefsIncrease();
 	}
-	return *this;
+	return clone;
 }
 
 COrder::~COrder()
diff --git a/src/include/actions.h b/src/include/actions.h
index 5f1bb8dbb..3c6980850 100644
--- a/src/include/actions.h
+++ b/src/include/actions.h
@@ -95,6 +95,7 @@ class CUnitType;
 class CUpgrade;
 class SpellType;
 class CAnimation;
+struct lua_State;
 
 /**
 **  Unit order structure.
@@ -110,11 +111,11 @@ public:
 		memset(&Arg1, 0, sizeof (Arg1));
 		memset(&Data, 0, sizeof (Data));
 	}
-	COrder(const COrder &ths);
 	~COrder();
 
+	COrder *Clone() const;
+
 	void ReleaseRefs(CUnit &owner);
-	COrder& operator=(const COrder &rhs);
 	bool CheckRange() const;
 
 	void Init() {
@@ -175,8 +176,31 @@ public:
 	static COrder* NewActionUnload(const Vec2i &pos, CUnit *what);
 	static COrder* NewActionUpgradeTo(CUnit &unit, CUnitType &type);
 
+	bool ParseGenericData(lua_State *l, int &j, const char *value);
+	bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
+
+#if 1 // currently needed for parsing
+	static COrder* NewActionAttack();
+	static COrder* NewActionAttackGround();
+	static COrder* NewActionBoard();
+	static COrder* NewActionBuild();
+	static COrder* NewActionFollow();
+	static COrder* NewActionMove();
+	static COrder* NewActionPatrol();
+	static COrder* NewActionRepair();
+	static COrder* NewActionResearch();
+	static COrder* NewActionResource();
+	static COrder* NewActionReturnGoods();
+	static COrder* NewActionSpellCast();
+	static COrder* NewActionTrain();
+	static COrder* NewActionTransformInto();
+	static COrder* NewActionUnload();
+	static COrder* NewActionUpgradeTo();
+#endif
+
 private:
-	friend void CclParseOrder(lua_State *l, const CUnit &unit, COrder* order);
+	COrder(const COrder &ths); // no implementation
+	COrder& operator=(const COrder &rhs); // no implementation
 
 	CUnit *Goal;
 public:
diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp
index 970aa7961..cdd68ab67 100644
--- a/src/unit/script_unit.cpp
+++ b/src/unit/script_unit.cpp
@@ -380,6 +380,149 @@ static void CclParseMove(lua_State *l, COrderPtr order)
 	}
 }
 
+bool COrder::ParseGenericData(lua_State *l, int &j, const char *value)
+{
+	if (!strcmp(value, "range")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Range = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "min-range")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->MinRange = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "width")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Width = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "height")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Height = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "goal")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Goal = CclGetUnitFromRef(l);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "tile")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclGetPos(l, &this->goalPos.x , &this->goalPos.y);
+		lua_pop(l, 1);
+	} else {
+		return false;
+	}
+	return true;
+}
+
+bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
+{
+	if (!strcmp(value, "type")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Arg1.Type = UnitTypeByIdent(LuaToString(l, -1));
+		lua_pop(l, 1);
+
+	} else if (!strcmp(value, "patrol")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclGetPos(l, &this->Arg1.Patrol.x , &this->Arg1.Patrol.y);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "spell")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Arg1.Spell = SpellTypeByIdent(LuaToString(l, -1));
+		lua_pop(l, 1);
+
+	} else if (!strcmp(value, "upgrade")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Arg1.Upgrade = CUpgrade::Get(LuaToString(l, -1));
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "current-resource")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->CurrentResource = CclGetResourceByName(l);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "resource-pos")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Arg1.Resource.Mine = NULL;
+		CclGetPos(l, &this->Arg1.Resource.Pos.x , &this->Arg1.Resource.Pos.y);
+		lua_pop(l, 1);
+
+		Assert(this->CurrentResource);
+	} else if (!strcmp(value, "resource-mine")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		Vec2i invalidPos = {-1, -1};
+		this->Arg1.Resource.Pos = invalidPos;
+		this->Arg1.Resource.Mine = CclGetUnitFromRef(l);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "data-built")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclParseBuilt(l, unit, this);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "data-res-worker")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclParseResWorker(l, this);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "data-research")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclParseResearch(l, this);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "data-upgrade-to")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclParseUpgradeTo(l, this);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "data-train")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclParseTrain(l, this);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "data-move")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclParseMove(l, this);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "mine")) { /* old save format */
+		int pos;
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		pos = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+
+		const Vec2i mpos = {pos >> 16, pos & 0xFFFF};
+		CUnit *mine = NULL;
+		pos = 0;
+		do {
+			pos++;
+			mine = ResourceOnMap(mpos, pos, true);
+		} while (!mine && pos < MaxCosts);
+		if (mine) {
+			Vec2i invalidPos = {-1, -1};
+			this->Arg1.Resource.Pos = invalidPos;
+
+			mine->RefsIncrease();
+			this->Arg1.Resource.Mine = mine;
+			this->CurrentResource = pos;
+		} else {
+			this->CurrentResource = WoodCost;
+			this->Arg1.Resource.Mine = NULL;
+			this->Arg1.Resource.Pos = mpos;
+		}
+	} else {
+		return false;
+	}
+	return true;
+}
 
 /**
 **  Parse order
@@ -387,184 +530,70 @@ static void CclParseMove(lua_State *l, COrderPtr order)
 **  @param l      Lua state.
 **  @param order  OUT: resulting order.
 */
-void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr order)
+void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
 {
 	const int args = lua_objlen(l, -1);
-	for (int j = 0; j < args; ++j) {
+
+	lua_rawgeti(l, -1, 1);
+	const char *actiontype = LuaToString(l, -1);
+	lua_pop(l, 1);
+
+	if (!strcmp(actiontype, "action-still")) {
+		*orderPtr = COrder::NewActionStill();
+	} else if (!strcmp(actiontype, "action-stand-ground")) {
+		*orderPtr = COrder::NewActionStandGround();
+	} else if (!strcmp(actiontype, "action-follow")) {
+		*orderPtr = COrder::NewActionFollow();
+	} else if (!strcmp(actiontype, "action-move")) {
+		*orderPtr = COrder::NewActionMove();
+	} else if (!strcmp(actiontype, "action-attack")) {
+		*orderPtr = COrder::NewActionAttack();
+	} else if (!strcmp(actiontype, "action-attack-ground")) {
+		*orderPtr = COrder::NewActionAttackGround();
+	} else if (!strcmp(actiontype, "action-die")) {
+		*orderPtr = COrder::NewActionDie();
+	} else if (!strcmp(actiontype, "action-spell-cast")) {
+		*orderPtr = COrder::NewActionSpellCast();
+	} else if (!strcmp(actiontype, "action-train")) {
+		*orderPtr = COrder::NewActionTrain();
+	} else if (!strcmp(actiontype, "action-upgrade-to")) {
+		*orderPtr = COrder::NewActionUpgradeTo();
+	} else if (!strcmp(actiontype, "action-research")) {
+		*orderPtr = COrder::NewActionResearch();
+	} else if (!strcmp(actiontype, "action-built")) {
+		*orderPtr = COrder::NewActionBuilt();
+	} else if (!strcmp(actiontype, "action-board")) {
+		*orderPtr = COrder::NewActionBoard();
+	} else if (!strcmp(actiontype, "action-unload")) {
+		*orderPtr = COrder::NewActionUnload();
+	} else if (!strcmp(actiontype, "action-patrol")) {
+		*orderPtr = COrder::NewActionPatrol();
+	} else if (!strcmp(actiontype, "action-build")) {
+		*orderPtr = COrder::NewActionBuild();
+	} else if (!strcmp(actiontype, "action-repair")) {
+		*orderPtr = COrder::NewActionRepair();
+	} 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 = COrder::NewActionTransformInto();
+	} else {
+		LuaError(l, "ParseOrder: Unsupported type: %s" _C_ actiontype);
+	}
+
+	COrder &order = **orderPtr;
+
+	for (int j = 1; j < args; ++j) {
 		lua_rawgeti(l, -1, j + 1);
 		const char *value = LuaToString(l, -1);
 		lua_pop(l, 1);
-		if (!strcmp(value, "action-none")) {
-			order->Action = UnitActionNone;
-		} else if (!strcmp(value, "action-still")) {
-			order->Action = UnitActionStill;
-		} else if (!strcmp(value, "action-stand-ground")) {
-			order->Action = UnitActionStandGround;
-		} else if (!strcmp(value, "action-follow")) {
-			order->Action = UnitActionFollow;
-		} else if (!strcmp(value, "action-move")) {
-			order->Action = UnitActionMove;
-		} else if (!strcmp(value, "action-attack")) {
-			order->Action = UnitActionAttack;
-		} else if (!strcmp(value, "action-attack-ground")) {
-			order->Action = UnitActionAttackGround;
-		} else if (!strcmp(value, "action-die")) {
-			order->Action = UnitActionDie;
-		} else if (!strcmp(value, "action-spell-cast")) {
-			order->Action = UnitActionSpellCast;
-		} else if (!strcmp(value, "action-train")) {
-			order->Action = UnitActionTrain;
-		} else if (!strcmp(value, "action-upgrade-to")) {
-			order->Action = UnitActionUpgradeTo;
-		} else if (!strcmp(value, "action-research")) {
-			order->Action = UnitActionResearch;
-		} else if (!strcmp(value, "action-built")) {
-			order->Action = UnitActionBuilt;
-		} else if (!strcmp(value, "action-board")) {
-			order->Action = UnitActionBoard;
-		} else if (!strcmp(value, "action-unload")) {
-			order->Action = UnitActionUnload;
-		} else if (!strcmp(value, "action-patrol")) {
-			order->Action = UnitActionPatrol;
-		} else if (!strcmp(value, "action-build")) {
-			order->Action = UnitActionBuild;
-		} else if (!strcmp(value, "action-repair")) {
-			order->Action = UnitActionRepair;
-		} else if (!strcmp(value, "action-resource")) {
-			order->Action = UnitActionResource;
-		} else if (!strcmp(value, "action-return-goods")) {
-			order->Action = UnitActionReturnGoods;
-		} else if (!strcmp(value, "action-transform-into")) {
-			order->Action = UnitActionTransformInto;
-		} else if (!strcmp(value, "range")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->Range = LuaToNumber(l, -1);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "min-range")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->MinRange = LuaToNumber(l, -1);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "width")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->Width = LuaToNumber(l, -1);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "height")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->Height = LuaToNumber(l, -1);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "goal")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->Goal = CclGetUnitFromRef(l);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "tile")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			CclGetPos(l, &order->goalPos.x , &order->goalPos.y);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "type")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->Arg1.Type = UnitTypeByIdent(LuaToString(l, -1));
-			lua_pop(l, 1);
 
-		} else if (!strcmp(value, "patrol")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			CclGetPos(l, &order->Arg1.Patrol.x , &order->Arg1.Patrol.y);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "spell")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->Arg1.Spell = SpellTypeByIdent(LuaToString(l, -1));
-			lua_pop(l, 1);
-
-		} else if (!strcmp(value, "upgrade")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->Arg1.Upgrade = CUpgrade::Get(LuaToString(l, -1));
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "current-resource")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->CurrentResource = CclGetResourceByName(l);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "resource-pos")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			order->Arg1.Resource.Mine = NULL;
-			CclGetPos(l, &order->Arg1.Resource.Pos.x , &order->Arg1.Resource.Pos.y);
-			lua_pop(l, 1);
-
-			Assert(order->CurrentResource);
-		} else if (!strcmp(value, "resource-mine")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			Vec2i invalidPos = {-1, -1};
-			order->Arg1.Resource.Pos = invalidPos;
-			order->Arg1.Resource.Mine = CclGetUnitFromRef(l);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "data-built")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			CclParseBuilt(l, unit, order);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "data-res-worker")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			CclParseResWorker(l, order);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "data-research")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			CclParseResearch(l, order);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "data-upgrade-to")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			CclParseUpgradeTo(l, order);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "data-train")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			CclParseTrain(l, order);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "data-move")) {
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			CclParseMove(l, order);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "mine")) { /* old save format */
-			int pos;
-			++j;
-			lua_rawgeti(l, -1, j + 1);
-			pos = LuaToNumber(l, -1);
-			lua_pop(l, 1);
-
-			const Vec2i mpos = {pos >> 16, pos & 0xFFFF};
-			CUnit *mine = NULL;
-			pos = 0;
-			do {
-				pos++;
-				mine = ResourceOnMap(mpos, pos, true);
-			} while (!mine && pos < MaxCosts);
-			if (mine) {
-				Vec2i invalidPos = {-1, -1};
-				order->Arg1.Resource.Pos = invalidPos;
-
-				mine->RefsIncrease();
-				order->Arg1.Resource.Mine = mine;
-				order->CurrentResource = pos;
-			} else {
-				order->CurrentResource = WoodCost;
-				order->Arg1.Resource.Mine = NULL;
-				order->Arg1.Resource.Pos = mpos;
-			}
-		} else {
+		if (order.ParseGenericData(l, j, value)) {
+			continue;
+		} else if (order.ParseSpecificData(l, j, value, unit)) {
+			continue;
+		}else {
 		   // This leaves a half initialized unit
 		   LuaError(l, "ParseOrder: Unsupported tag: %s" _C_ value);
 		}
@@ -590,10 +619,10 @@ static void CclParseOrders(lua_State *l, CUnit &unit)
 	for (int j = 0; j < n; ++j) {
 		lua_rawgeti(l, -1, j + 1);
 
-		unit.Orders.push_back(new COrder);
+		unit.Orders.push_back(NULL);
 		COrderPtr* order = &unit.Orders.back();
 
-		CclParseOrder(l, unit, *order);
+		CclParseOrder(l, unit, order);
 		lua_pop(l, 1);
 	}
 }
@@ -852,18 +881,15 @@ static int CclUnit(lua_State *l)
 			}
 		} else if (!strcmp(value, "critical-order")) {
 			lua_pushvalue(l, j + 1);
-			unit->CriticalOrder = new COrder;
-			CclParseOrder(l, *unit , unit->CriticalOrder);
+			CclParseOrder(l, *unit , &unit->CriticalOrder);
 			lua_pop(l, 1);
 		} else if (!strcmp(value, "saved-order")) {
 			lua_pushvalue(l, j + 1);
-			unit->SavedOrder = new COrder;
-			CclParseOrder(l, *unit, unit->SavedOrder);
+			CclParseOrder(l, *unit, &unit->SavedOrder);
 			lua_pop(l, 1);
 		} else if (!strcmp(value, "new-order")) {
 			lua_pushvalue(l, j + 1);
-			unit->NewOrder = new COrder;
-			CclParseOrder(l, *unit, unit->NewOrder);
+			CclParseOrder(l, *unit, &unit->NewOrder);
 			lua_pop(l, 1);
 		} else if (!strcmp(value, "goal")) {
 			unit->Goal = UnitSlots[(int)LuaToNumber(l, j + 1)];
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index ae8377081..e6e578e9e 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -3096,7 +3096,7 @@ void HitUnit(CUnit *attacker, CUnit &target, int damage)
 			}
 		}
 		if (goal) {
-			COrder *savedOrder = new COrder(*target.CurrentOrder());
+			COrder *savedOrder = target.CurrentOrder()->Clone();
 
 			CommandAttack(target, goal->tilePos, NoUnitP, FlushCommands);
 			if (target.StoreOrder(savedOrder) == false) {