diff --git a/src/action/action_resource.cpp b/src/action/action_resource.cpp
index 9d4752f2e..1530a7a12 100644
--- a/src/action/action_resource.cpp
+++ b/src/action/action_resource.cpp
@@ -47,6 +47,8 @@
 #include "interface.h"
 #include "sound.h"
 #include "map.h"
+#include "script.h"
+#include "iolib.h"
 
 /*----------------------------------------------------------------------------
 --  Declarations
@@ -66,24 +68,160 @@
 --  Functions
 ----------------------------------------------------------------------------*/
 
+Vec2i COrder_Resource::GetHarvestLocation() const
+{
+	return this->Resource.Pos;
+}
+
+bool COrder_Resource::IsGatheringStarted() const
+{
+	return this->State > SUB_START_GATHERING;
+}
+
+bool COrder_Resource::IsGatheringFinished() const
+{
+	return this->State >= SUB_STOP_GATHERING;
+}
+
+bool COrder_Resource::IsGatheringWaiting() const
+{
+	return this->State == SUB_START_GATHERING && this->worker->Wait != 0;
+}
+
+COrder_Resource::~COrder_Resource()
+{
+
+}
+
+void COrder_Resource::ReleaseRefs(CUnit &owner)
+{
+	CUnit *mine = this->Resource.Mine;
+
+	if (mine && mine->IsAlive()) {
+		owner.DeAssignWorkerFromMine(*mine);
+		this->Resource.Mine = NULL;
+	}
+	if (this->HasGoal()) {
+		// If mining decrease the active count on the resource.
+		if (this->State == SUB_GATHER_RESOURCE ) {
+			CUnit *goal = this->GetGoal();
+
+			goal->Resource.Active--;
+			Assert(goal->Resource.Active >= 0);
+		}
+		this->ClearGoal();
+	}
+}
+
+/* virtual */ void COrder_Resource::Save(CFile &file, const CUnit &unit) const
+{
+	file.printf("{\"action-resource\",");
+	if (this->Finished) {
+		file.printf(" \"finished\",");
+	}
+	file.printf(" \"range\", %d,", this->Range);
+//	file.printf(" \"width\", %d,", order.Width);
+//	file.printf(" \"height\", %d,", order.Height);
+//	file.printf(" \"min-range\", %d,", order.MinRange);
+	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);
+
+	Assert(this->worker != NULL && worker->IsAlive());
+	file.printf(" \"worker\", \"%s\",", UnitReference(worker).c_str());
+	file.printf(" \"current-res\", %d,", this->CurrentResource);
+
+	file.printf(" \"res-pos\", {%d, %d},", this->Resource.Pos.x, this->Resource.Pos.y);
+	if (this->Resource.Mine != NULL) {
+		file.printf(" \"res-mine\", \"%s\",", UnitReference(this->Resource.Mine).c_str());
+	}
+	if (this->Depot != NULL) {
+		file.printf(" \"res-depot\", \"%s\",", UnitReference(this->Depot).c_str());
+	}
+	if (this->DoneHarvesting) {
+		file.printf(" \"done-harvesting\",");
+	}
+	file.printf(" \"timetoharvest\", %d,", this->TimeToHarvest);
+	file.printf(" \"state\", %d,\n  ", this->State);
+	SaveDataMove(file);
+	file.printf("}");
+}
+
+/* virtual */ bool COrder_Resource::ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit)
+{
+	if (this->ParseMoveData(l, j, value)) {
+		return true;
+	} else if (!strcmp(value, "current-res")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->CurrentResource = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "done-harvesting")) {
+		lua_rawgeti(l, -1, j + 1);
+		this->DoneHarvesting = true;
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "res-depot")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Depot = CclGetUnitFromRef(l);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "res-mine")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->Resource.Mine = CclGetUnitFromRef(l);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "res-pos")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		CclGetPos(l, &this->Resource.Pos.x , &this->Resource.Pos.y);
+		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, "timetoharvest")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->TimeToHarvest = LuaToNumber(l, -1);
+		lua_pop(l, 1);
+	} else if (!strcmp(value, "worker")) {
+		++j;
+		lua_rawgeti(l, -1, j + 1);
+		this->worker = CclGetUnitFromRef(l);
+		lua_pop(l, 1);
+	} else {
+		return false;
+	}
+	return true;
+}
+
+
 /**
 **  Move unit to terrain.
 **
 **  @return      1 if reached, -1 if unreacheable, 0 if on the way.
 */
-static int MoveToResource_Terrain(CUnit &unit)
+int COrder_Resource::MoveToResource_Terrain(CUnit &unit)
 {
 	Vec2i pos = unit.CurrentOrder()->goalPos;
 
 	// Wood gone, look somewhere else.
-	if ((!Map.ForestOnMap(pos)) && (!unit.IX) && (!unit.IY)) {
+	if ((Map.Info.IsPointOnMap(pos) == false || Map.ForestOnMap(pos) == false) && (!unit.IX) && (!unit.IY)) {
 		if (!FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 16,
 				unit.Player, unit.CurrentOrder()->goalPos, &pos)) {
 			// no wood in range
 			return -1;
 		} else {
-			unit.CurrentOrder()->goalPos = pos;
-			unit.CurrentOrder()->NewResetPath();
+			this->goalPos = pos;
+			this->NewResetPath();
 		}
 	}
 	switch (DoActionMove(unit)) {
@@ -91,8 +229,8 @@ static int MoveToResource_Terrain(CUnit &unit)
 			unit.Wait = 10;
 			if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 9999,
 					unit.Player, unit.tilePos, &pos)) {
-				unit.CurrentOrder()->goalPos = pos;
-				unit.CurrentOrder()->NewResetPath();
+				this->goalPos = pos;
+				this->NewResetPath();
 				DebugPrint("Found a better place to harvest %d,%d\n" _C_ pos.x _C_ pos.y);
 				// FIXME: can't this overflow? It really shouldn't, since
 				// x and y are really supossed to be reachable, checked thorugh a flood fill.
@@ -112,9 +250,9 @@ static int MoveToResource_Terrain(CUnit &unit)
 **
 **  @return      1 if reached, -1 if unreacheable, 0 if on the way.
 */
-static int MoveToResource_Unit(CUnit &unit)
+int COrder_Resource::MoveToResource_Unit(CUnit &unit)
 {
-	const CUnit *goal = unit.CurrentOrder()->GetGoal();
+	const CUnit *goal = this->GetGoal();
 	Assert(goal);
 
 	switch (DoActionMove(unit)) { // reached end-point?
@@ -139,7 +277,7 @@ static int MoveToResource_Unit(CUnit &unit)
 **
 **  @return      1 if reached, -1 if unreacheable, 0 if on the way.
 */
-static int MoveToResource(CUnit &unit)
+int COrder_Resource::MoveToResource(CUnit &unit)
 {
 	const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
 
@@ -150,22 +288,20 @@ static int MoveToResource(CUnit &unit)
 	}
 }
 
-static void UnitGotoGoal(CUnit &unit, CUnit *const goal, int mode)
+void COrder_Resource::UnitGotoGoal(CUnit &unit, CUnit *const goal, int state)
 {
-	COrderPtr order = unit.CurrentOrder();
-
-	if (order->GetGoal() != goal) {
-		order->SetGoal(goal);
+	if (this->GetGoal() != goal) {
+		this->SetGoal(goal);
 		if (goal) {
-			order->goalPos.x = order->goalPos.y = -1;
+			this->goalPos.x = this->goalPos.y = -1;
 		}
 	}
-	order->Range = 1;
-	order->SubAction.Res = mode;
+	this->Range = 1;
+	this->State = state;
 	unit.State = 0;
-	if (mode == SUB_MOVE_TO_DEPOT || mode == SUB_MOVE_TO_RESOURCE) {
-		unit.CurrentOrder()->Data.Move.Cycles = 0; //moving counter
-		unit.CurrentOrder()->NewResetPath();
+	if (state == SUB_MOVE_TO_DEPOT || state == SUB_MOVE_TO_RESOURCE) {
+		this->Data.Move.Cycles = 0; //moving counter
+		this->NewResetPath();
 	}
 }
 
@@ -176,7 +312,7 @@ static void UnitGotoGoal(CUnit &unit, CUnit *const goal, int mode)
 **
 **  @return      TRUE if ready, otherwise FALSE.
 */
-static int StartGathering(CUnit &unit)
+int COrder_Resource::StartGathering(CUnit &unit)
 {
 	CUnit *goal;
 	const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
@@ -191,29 +327,29 @@ static int StartGathering(CUnit &unit)
 			return 0;
 		}
 #endif
-		UnitHeadingFromDeltaXY(unit, unit.CurrentOrder()->goalPos - unit.tilePos);
+		UnitHeadingFromDeltaXY(unit, this->goalPos - unit.tilePos);
 		if (resinfo.WaitAtResource) {
-			unit.CurrentOrder()->Data.ResWorker.TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
+			this->TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
 		} else {
-			unit.CurrentOrder()->Data.ResWorker.TimeToHarvest = 1;
+			this->TimeToHarvest = 1;
 		}
-		unit.CurrentOrder()->Data.ResWorker.DoneHarvesting = 0;
+		this->DoneHarvesting = 0;
 		return 1;
 	}
 
-	goal = unit.CurrentOrder()->GetGoal();
-	//
+	goal = this->GetGoal();
+
 	// Target is dead, stop getting resources.
-	//
 	if (!goal->IsVisibleAsGoal(*unit.Player)) {
 		// Find an alternative, but don't look too far.
-		unit.CurrentOrder()->goalPos.x = unit.CurrentOrder()->goalPos.y = -1;
+		this->goalPos.x = -1;
+		this->goalPos.y = -1;
 		if ((goal = UnitFindResource(unit, unit.tilePos, 15, unit.CurrentResource, unit.Player->AiEnabled))) {
-			unit.CurrentOrder()->SubAction.Res = SUB_START_RESOURCE;
-			unit.CurrentOrder()->SetGoal(goal);
+			this->State = SUB_START_RESOURCE;
+			this->SetGoal(goal);
 		} else {
-			unit.CurrentOrder()->ClearGoal();
-			unit.ClearAction();
+			this->ClearGoal();
+			this->Finished = true;
 		}
 		return 0;
 	}
@@ -221,16 +357,12 @@ static int StartGathering(CUnit &unit)
 	// FIXME: 0 can happen, if to near placed by map designer.
 	Assert(unit.MapDistanceTo(*goal) <= 1);
 
-	//
 	// Update the heading of a harvesting unit to looks straight at the resource.
-	//
 	if (goal) {
 		UnitHeadingFromDeltaXY(unit, goal->tilePos - unit.tilePos + goal->Type->GetHalfTileSize());
 	}
 
-	//
 	// If resource is still under construction, wait!
-	//
 	if ((goal->Type->MaxOnBoard &&
 		 goal->Resource.Active >= goal->Type->MaxOnBoard) ||
 			goal->CurrentAction() == UnitActionBuilt) {
@@ -243,12 +375,10 @@ static int StartGathering(CUnit &unit)
 		return 0;
 	}
 
-	//
 	// Place unit inside the resource
-	//
 	if (!resinfo.HarvestFromOutside) {
 		if (goal->Variable[MAXHARVESTERS_INDEX].Value == 0 || goal->Variable[MAXHARVESTERS_INDEX].Value > goal->InsideCount) {
-			unit.CurrentOrder()->ClearGoal();
+			this->ClearGoal();
 			unit.Remove(goal);
 		} else if (goal->Variable[MAXHARVESTERS_INDEX].Value <= goal->InsideCount) {
 			//Resource is full, wait
@@ -261,13 +391,11 @@ static int StartGathering(CUnit &unit)
 	goal->Resource.Active++;
 
 	if (resinfo.WaitAtResource) {
-		unit.CurrentOrder()->Data.ResWorker.TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
+		this->TimeToHarvest = resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
 	} else {
-		unit.CurrentOrder()->Data.ResWorker.TimeToHarvest = 1;
+		this->TimeToHarvest = 1;
 	}
-
-	unit.CurrentOrder()->Data.ResWorker.DoneHarvesting = 0;
-
+	this->DoneHarvesting = 0;
 	return 1;
 }
 
@@ -289,7 +417,7 @@ static void AnimateActionHarvest(CUnit &unit)
 **  @param unit    pointer to harvester unit.
 **  @param source  pointer to resource unit.
 */
-static void LoseResource(CUnit &unit, const CUnit &source)
+void COrder_Resource::LoseResource(CUnit &unit, const CUnit &source)
 {
 	CUnit *depot;
 	const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
@@ -298,12 +426,10 @@ static void LoseResource(CUnit &unit, const CUnit &source)
 		|| (!unit.Container && resinfo.HarvestFromOutside));
 
 	if (resinfo.HarvestFromOutside) {
-		unit.CurrentOrder()->ClearGoal();
+		this->ClearGoal();
 	}
 
-	//
 	// Continue to harvest if we aren't fully loaded
-	//
 	if (resinfo.HarvestFromOutside && unit.ResourcesHeld < resinfo.ResourceCapacity){
 		if (unit.Container) {
 			DropOutOnSide(unit, LookingW, &source);
@@ -312,32 +438,27 @@ static void LoseResource(CUnit &unit, const CUnit &source)
 		CUnit *goal = UnitFindResource(unit, pos, 15, unit.CurrentResource, 1);
 
 		if (goal) {
-			CUnit *mine = unit.CurrentOrder()->Arg1.Resource.Mine;
+			CUnit *mine = this->Resource.Mine;
 
 			if (mine) {
 				unit.DeAssignWorkerFromMine(*mine);
-				mine->RefsDecrease();
 			}
 			unit.AssignWorkerToMine(*goal);
-			unit.CurrentOrder()->SetGoal(goal);
-			goal->RefsIncrease();
-			unit.CurrentOrder()->Arg1.Resource.Mine = goal;
-			unit.CurrentOrder()->Range = 1;
-			unit.CurrentOrder()->goalPos = goal->tilePos;
-			unit.CurrentOrder()->SubAction.Res = SUB_MOVE_TO_RESOURCE;
+			this->SetGoal(goal);
+			this->Resource.Mine = goal;
+			this->Range = 1;
+			this->goalPos = goal->tilePos;
+			this->State = SUB_MOVE_TO_RESOURCE;
 			unit.State = 0;
 			return;
 		}
 	}
 
-	//
 	// If we are fully loaded first search for a depot.
-	//
 	if (unit.ResourcesHeld && (depot = FindDeposit(unit, 1000, unit.CurrentResource))) {
 		if (unit.Container) {
 			DropOutNearest(unit, depot->tilePos + depot->Type->GetHalfTileSize(), &source);
 		}
-		//
 		// Remember where it mined, so it can look around for another resource.
 		//
 		//FIXME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -347,28 +468,26 @@ static void LoseResource(CUnit &unit, const CUnit &source)
 			_C_ unit.Player->Index _C_ unit.Slot);
 		return;
 	}
-	//
 	// No depot found, or harvester empty
 	// Dump the unit outside and look for something to do.
-	//
 	if (unit.Container) {
 		Assert(!resinfo.HarvestFromOutside);
 		DropOutOnSide(unit, LookingW, &source);
 	}
-	unit.CurrentOrder()->goalPos.x = unit.CurrentOrder()->goalPos.y = -1;
+	this->goalPos.x = -1;
+	this->goalPos.y = -1;
 	//use depot as goal
 	depot = UnitFindResource(unit, unit.tilePos, 15, unit.CurrentResource, unit.Player->AiEnabled);
 	if (depot) {
 		DebugPrint("%d: Worker %d report: Resource is exhausted, Found another resource.\n"
 			_C_ unit.Player->Index _C_ unit.Slot);
-		unit.CurrentOrder()->SubAction.Res = SUB_START_RESOURCE;
+		this->State = SUB_START_RESOURCE;
 		unit.State = 0;
-		unit.CurrentOrder()->SetGoal(depot);
+		this->SetGoal(depot);
 	} else {
 		DebugPrint("%d: Worker %d report: Resource is exhausted, Just sits around confused.\n"
 			_C_ unit.Player->Index _C_ unit.Slot);
-		unit.ClearAction();
-		unit.CurrentOrder()->ClearGoal(); //just in case
+		this->Finished = true;
 		unit.State = 0;
 	}
 }
@@ -382,18 +501,13 @@ static void LoseResource(CUnit &unit, const CUnit &source)
 **
 **  @return      non-zero if ready, otherwise zero.
 */
-static int GatherResource(CUnit &unit)
+int COrder_Resource::GatherResource(CUnit &unit)
 {
 	CUnit *source = 0;
-	CUnit *uins;
 	const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
-	int i;
 	int addload;
 
 	if (!resinfo.HarvestFromOutside && unit.Container != NULL) {
-#if 0
-//		unit.Container->SubAction = SUB_GATHER_RESOURCE;
-#endif
 		UnitShowAnimation(*unit.Container, unit.Container->Type->Animations->Harvest[unit.CurrentResource]);
 	}
 
@@ -403,18 +517,18 @@ static int GatherResource(CUnit &unit)
 		unit.Anim.CurrAnim = NULL;
 	}
 
-	unit.CurrentOrder()->Data.ResWorker.TimeToHarvest--;
+	this->TimeToHarvest--;
 
-	if (unit.CurrentOrder()->Data.ResWorker.DoneHarvesting) {
+	if (this->DoneHarvesting) {
 		Assert(resinfo.HarvestFromOutside || resinfo.TerrainHarvester);
 		return !unit.Anim.Unbreakable;
 	}
 
 	// Target gone?
-	if (resinfo.TerrainHarvester && !Map.ForestOnMap(unit.CurrentOrder()->goalPos)) {
+	if (resinfo.TerrainHarvester && !Map.ForestOnMap(this->goalPos)) {
 		if (!unit.Anim.Unbreakable) {
 			// Action now breakable, move to resource again.
-			unit.CurrentOrder()->SubAction.Res = SUB_MOVE_TO_RESOURCE;
+			this->State = SUB_MOVE_TO_RESOURCE;
 			// Give it some reasonable look while searching.
 			// FIXME: which frame?
 			unit.Frame = 0;
@@ -423,18 +537,15 @@ static int GatherResource(CUnit &unit)
 		// No wood? Freeze!!!
 	}
 
-	while (!unit.CurrentOrder()->Data.ResWorker.DoneHarvesting &&
-			unit.CurrentOrder()->Data.ResWorker.TimeToHarvest < 0) {
+	while (!this->DoneHarvesting && this->TimeToHarvest < 0) {
 		//FIXME: rb - how should it look for WaitAtResource == 0
 		if (resinfo.WaitAtResource) {
-			unit.CurrentOrder()->Data.ResWorker.TimeToHarvest += resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
+			this->TimeToHarvest += resinfo.WaitAtResource / SpeedResourcesHarvest[resinfo.ResourceId];
 		} else {
-			unit.CurrentOrder()->Data.ResWorker.TimeToHarvest += 1;
+			this->TimeToHarvest += 1;
 		}
 
-		//
 		// Calculate how much we can load.
-		//
 		if (resinfo.ResourceStep) {
 			addload = resinfo.ResourceStep;
 		} else {
@@ -449,11 +560,11 @@ static int GatherResource(CUnit &unit)
 			unit.ResourcesHeld += addload;
 
 			if (addload && unit.ResourcesHeld == resinfo.ResourceCapacity) {
-				Map.ClearTile(MapFieldForest, unit.CurrentOrder()->goalPos);
+				Map.ClearTile(MapFieldForest, this->goalPos);
 			}
 		} else {
 			if (resinfo.HarvestFromOutside) {
-				source = unit.CurrentOrder()->GetGoal();
+				source = this->GetGoal();
 			} else {
 				source = unit.Container;
 			}
@@ -461,33 +572,29 @@ static int GatherResource(CUnit &unit)
 			Assert(source);
 			Assert(source->ResourcesHeld <= 655350);
 			bool is_visible = source->IsVisibleAsGoal(*unit.Player);
-			//
 			// Target is not dead, getting resources.
-			//
 			if (is_visible) {
 				// Don't load more that there is.
 				if (addload > source->ResourcesHeld) {
 					addload = source->ResourcesHeld;
 				}
-
 				unit.ResourcesHeld += addload;
 				source->ResourcesHeld -= addload;
 			}
 
-			//
 			// End of resource: destroy the resource.
 			// FIXME: implement depleted resources.
-			//
 			if ((!is_visible) || (source->ResourcesHeld == 0)) {
 				if (unit.Anim.Unbreakable) {
 					return 0;
 				}
 				DebugPrint("%d: Worker %d report: Resource is destroyed\n" _C_ unit.Player->Index _C_ unit.Slot);
 				bool dead = source->CurrentAction() == UnitActionDie;
-				//
+
 				// Improved version of DropOutAll that makes workers go to the depot.
-				//
 				LoseResource(unit, *source);
+				int i;
+				CUnit *uins;
 				for (i = source->InsideCount, uins = source->UnitInside;
 										i; --i, uins = uins->NextContained) {
 					if (uins->CurrentOrder()->Action == UnitActionResource) {
@@ -507,19 +614,20 @@ static int GatherResource(CUnit &unit)
 		if (resinfo.TerrainHarvester) {
 			if (unit.ResourcesHeld == resinfo.ResourceCapacity) {
 				// Mark as complete.
-				unit.CurrentOrder()->Data.ResWorker.DoneHarvesting = 1;
+				this->DoneHarvesting = true;
 			}
 			return 0;
-		} else
+		} else {
 			if (resinfo.HarvestFromOutside) {
 				if ((unit.ResourcesHeld == resinfo.ResourceCapacity) || (source == NULL)) {
 					// Mark as complete.
-					unit.CurrentOrder()->Data.ResWorker.DoneHarvesting = 1;
+					this->DoneHarvesting = true;
 				}
 				return 0;
 			} else {
 				return unit.ResourcesHeld == resinfo.ResourceCapacity && source;
 			}
+		}
 	}
 	return 0;
 }
@@ -531,7 +639,10 @@ int GetNumWaitingWorkers(const CUnit &mine)
 
 	for (int i = 0; NULL != worker; worker = worker->NextWorker, ++i)
 	{
-		if (worker->CurrentOrder()->SubAction.Res == SUB_START_GATHERING && worker->Wait) {
+		Assert(worker->CurrentAction() == UnitActionResource);
+		COrder_Resource &order = *static_cast<COrder_Resource*>(worker->CurrentOrder());
+
+		if (order.IsGatheringWaiting()) {
 			ret++;
 		}
 		Assert(i <= mine.Resource.Assigned);
@@ -546,31 +657,22 @@ int GetNumWaitingWorkers(const CUnit &mine)
 **
 **  @return      TRUE if ready, otherwise FALSE.
 */
-static int StopGathering(CUnit &unit)
+int COrder_Resource::StopGathering(CUnit &unit)
 {
 	CUnit *source = 0;
 	const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
 
 	if (!resinfo.TerrainHarvester) {
 		if (resinfo.HarvestFromOutside) {
-			source = unit.CurrentOrder()->GetGoal();
-			unit.CurrentOrder()->ClearGoal();
+			source = this->GetGoal();
+			this->ClearGoal();
 		} else {
 			source = unit.Container;
 		}
 		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();
-		}
-		source->RefsIncrease();
-		unit.Orders[0]->Arg1.Resource.Mine = source;
+		this->Resource.Mine = source;
 
 		if (source->Type->MaxOnBoard) {
 			int count = 0;
@@ -578,11 +680,14 @@ static int StopGathering(CUnit &unit)
 			CUnit *next = NULL;
 			for(; NULL != worker; worker = worker->NextWorker)
 			{
-				if (worker != &unit && worker->CurrentOrder()->SubAction.Res == SUB_START_GATHERING && worker->Wait) {
+				Assert(worker->CurrentAction() == UnitActionResource);
+				COrder_Resource& order = *static_cast<COrder_Resource*>(worker->CurrentOrder());
+				if (worker != &unit && order.IsGatheringWaiting()) {
 					count++;
 					if (next) {
-						if (next->Wait > worker->Wait)
+						if (next->Wait > worker->Wait) {
 							next = worker;
+						}
 					} else {
 						next = worker;
 					}
@@ -604,8 +709,8 @@ static int StopGathering(CUnit &unit)
 		}
 	} else {
 		// Store resource position.
-		unit.CurrentOrder()->Arg1.Resource.Pos = unit.tilePos;
-		Assert(unit.CurrentOrder()->Arg1.Resource.Mine == NULL);
+		this->Resource.Pos = unit.tilePos;
+		Assert(this->Resource.Mine == NULL);
 	}
 
 #ifdef DEBUG
@@ -621,18 +726,16 @@ static int StopGathering(CUnit &unit)
 			Assert(unit.Container);
 			DropOutOnSide(unit, LookingW, source);
 		}
-		CUnit *mine = unit.Orders[0]->Arg1.Resource.Mine;
+		CUnit *mine = this->Resource.Mine;
 
 		if (mine) {
 			unit.DeAssignWorkerFromMine(*mine);
-			mine->RefsDecrease();
-			unit.Orders[0]->Arg1.Resource.Mine = NULL;
+			this->Resource.Mine = NULL;
 		}
 
 		DebugPrint("%d: Worker %d report: Can't find a resource [%d] deposit.\n"
 				_C_ unit.Player->Index _C_ unit.Slot _C_ unit.CurrentResource);
-		unit.CurrentOrder()->ClearGoal();
-		unit.ClearAction();
+		this->Finished = true;
 		return 0;
 	} else {
 		if (!(resinfo.HarvestFromOutside || resinfo.TerrainHarvester)) {
@@ -644,7 +747,9 @@ static int StopGathering(CUnit &unit)
 	if (IsOnlySelected(unit)) {
 		SelectedUnitChanged();
 	}
-	return unit.CurrentAction() != UnitActionStill;
+#if 1
+	return 1;
+#endif
 }
 
 extern void AiNewDepotRequest(CUnit &worker);
@@ -656,12 +761,12 @@ extern void AiNewDepotRequest(CUnit &worker);
 **
 **  @return      TRUE if reached, otherwise FALSE.
 */
-static int MoveToDepot(CUnit &unit)
+int COrder_Resource::MoveToDepot(CUnit &unit)
 {
 	const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
-	CUnit *goal = unit.CurrentOrder()->GetGoal();
-	CPlayer& player = *unit.Player;
-	Assert(goal);
+	CUnit &goal = *this->GetGoal();
+	CPlayer &player = *unit.Player;
+	Assert(&goal);
 
 	switch (DoActionMove(unit)) { // reached end-point?
 		case PF_UNREACHABLE:
@@ -669,7 +774,7 @@ static int MoveToDepot(CUnit &unit)
 		case PF_REACHED:
 			break;
 		default:
-			if (unit.Anim.Unbreakable || goal->IsVisibleAsGoal(player)) {
+			if (unit.Anim.Unbreakable || goal.IsVisibleAsGoal(player)) {
 				return 0;
 			}
 			break;
@@ -678,7 +783,7 @@ static int MoveToDepot(CUnit &unit)
 	//
 	// Target is dead, stop getting resources.
 	//
-	if (!goal->IsVisibleAsGoal(player)) {
+	if (!goal.IsVisibleAsGoal(player)) {
 		DebugPrint("%d: Worker %d report: Destroyed depot\n" _C_ player.Index _C_ unit.Slot);
 
 		unit.CurrentOrder()->ClearGoal();
@@ -693,28 +798,28 @@ static int MoveToDepot(CUnit &unit)
 				_C_ player.Index _C_ unit.Slot);
 
 			// FIXME: perhaps we should choose an alternative
-			unit.ClearAction();
+			this->Finished = true;
 		}
 		return 0;
 	}
 
 	// Not ready
-	if (player.AiEnabled && unit.CurrentOrder()->Data.Move.Cycles > 300) {
+	if (player.AiEnabled && this->Data.Move.Cycles > 300) {
 		AiNewDepotRequest(unit);
 	}
 
 	// If resource depot is still under construction, wait!
-	if (goal->CurrentOrder()->Action == UnitActionBuilt) {
+	if (goal.CurrentAction() == UnitActionBuilt) {
 		unit.Wait = 10;
 		return 0;
 	}
 
-	unit.CurrentOrder()->ClearGoal();
+	this->ClearGoal();
 	unit.Wait = resinfo.WaitAtDepot;
 
 	// Place unit inside the depot
 	if (unit.Wait) {
-		unit.Remove(goal);
+		unit.Remove(&goal);
 		unit.Anim.CurrAnim = NULL;
 	}
 
@@ -743,7 +848,7 @@ static int MoveToDepot(CUnit &unit)
 **
 **  @return      TRUE if ready, otherwise FALSE.
 */
-static int WaitInDepot(CUnit &unit)
+bool COrder_Resource::WaitInDepot(CUnit &unit)
 {
 	const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
 	const CUnit *depot = ResourceDepositOnMap(unit.tilePos, resinfo.ResourceId);
@@ -752,21 +857,22 @@ static int WaitInDepot(CUnit &unit)
 
 	// Range hardcoded. don't stray too far though
 	if (resinfo.TerrainHarvester) {
-		Vec2i pos = unit.CurrentOrder()->Arg1.Resource.Pos;
+		Vec2i pos = this->Resource.Pos;
 
 		if (FindTerrainType(unit.Type->MovementMask, MapFieldForest, 0, 10, unit.Player, pos, &pos)) {
 			if (depot) {
 				DropOutNearest(unit, pos, depot);
 			}
-			unit.CurrentOrder()->goalPos = pos;
+			this->goalPos = pos;
 		} else {
 			if (depot) {
 				DropOutOnSide(unit, LookingW, depot);
 			}
-			unit.ClearAction();
+			this->Finished = true;
+			return false;
 		}
 	} else {
-		CUnit *mine = unit.CurrentOrder()->Arg1.Resource.Mine;
+		CUnit *mine = this->Resource.Mine;
 		const int range = (mine ? 15 : 1000);
 		const Vec2i pos = mine ? mine->tilePos : unit.tilePos;
 		CUnit *goal = UnitFindResource(unit, pos, range, unit.CurrentResource, unit.Player->AiEnabled, depot);
@@ -779,15 +885,13 @@ static int WaitInDepot(CUnit &unit)
 			if (goal != mine) {
 				if (mine) {
 					unit.DeAssignWorkerFromMine(*mine);
-					mine->RefsDecrease();
 				}
 				unit.AssignWorkerToMine(*goal);
-				goal->RefsIncrease();
-				unit.CurrentOrder()->Arg1.Resource.Mine = goal;
+				this->Resource.Mine = goal;
 			}
-			unit.CurrentOrder()->SetGoal(goal);
-			unit.CurrentOrder()->Range = 1;
-			unit.CurrentOrder()->goalPos.x = unit.CurrentOrder()->goalPos.y = -1;
+			this->SetGoal(goal);
+			this->Range = 1;
+			this->goalPos.x = this->goalPos.y = -1;
 		} else {
 			DebugPrint("%d: Worker %d report: [%d,%d] Resource gone near [%d,%d] in range %d. Sit and play dumb.\n"
 				_C_ unit.Player->Index _C_ unit.Slot
@@ -798,19 +902,18 @@ static int WaitInDepot(CUnit &unit)
 			}
 			if (mine) {
 				unit.DeAssignWorkerFromMine(*mine);
-				mine->RefsDecrease();
-				unit.CurrentOrder()->Arg1.Resource.Mine = NULL;
+				this->Resource.Mine = NULL;
 			}
-			unit.ClearAction();
+			this->Finished = true;
+			return false;
 		}
 	}
-	return unit.CurrentAction() != UnitActionStill;
+	return true;
 }
 
-void DropResource(CUnit &unit)
+void COrder_Resource::DropResource(CUnit &unit)
 {
 	if (unit.CurrentResource) {
-		COrderPtr order = unit.CurrentOrder();
 		const ResourceInfo &resinfo = *unit.Type->ResInfo[unit.CurrentResource];
 		if (resinfo.LoseResources && unit.ResourcesHeld < resinfo.ResourceCapacity) {
 			unit.ResourcesHeld = 0;
@@ -819,16 +922,14 @@ void DropResource(CUnit &unit)
 			unit.ResourcesHeld = 0;
 		}
 		if (!resinfo.TerrainHarvester) {
-			CUnit *mine = order->Arg1.Resource.Mine;
+			CUnit *mine = this->Resource.Mine;
 			if (mine) {
 				unit.DeAssignWorkerFromMine(*mine);
-				mine->RefsDecrease();
 			}
 		}
 		//fast clean both resource data: pos and mine
-		order->Arg1.Resource.Mine = NULL;
+		this->Resource.Mine = NULL;
 		unit.CurrentResource = 0;
-		order->CurrentResource = 0;
 	}
 }
 
@@ -837,12 +938,12 @@ void DropResource(CUnit &unit)
 **
 **  @param unit  Pointer to unit.
 */
-void ResourceGiveUp(CUnit &unit)
+void COrder_Resource::ResourceGiveUp(CUnit &unit)
 {
 	DebugPrint("%d: Worker %d report: Gave up on resource gathering.\n" _C_ unit.Player->Index _C_ unit.Slot);
-	unit.CurrentOrder()->ClearGoal();
+	this->ClearGoal();
 	DropResource(unit);
-	unit.ClearAction();
+	this->Finished = true;
 }
 
 /**
@@ -850,11 +951,11 @@ void ResourceGiveUp(CUnit &unit)
 **
 **  return false if action is canceled, true otherwise.
 */
-static bool ActionResourceInit(CUnit &unit)
+bool COrder_Resource::ActionResourceInit(CUnit &unit)
 {
-	Assert(unit.CurrentOrder()->SubAction.Res == SUB_START_RESOURCE);
+	Assert(this->State == SUB_START_RESOURCE);
 
-	CUnit *const goal = unit.CurrentOrder()->GetGoal();
+	CUnit *const goal = this->GetGoal();
 	int newres;
 
 	if (goal) {
@@ -872,20 +973,17 @@ static bool ActionResourceInit(CUnit &unit)
 		ResourceGiveUp(unit);
 		return false;
 	}
-	COrderPtr order = unit.CurrentOrder();
-	order->CurrentResource = newres;
-	if (goal && order->Arg1.Resource.Mine != goal) {
-		CUnit *mine = order->Arg1.Resource.Mine;
+	this->CurrentResource = newres;
+	if (goal && this->Resource.Mine != goal) {
+		CUnit *mine = this->Resource.Mine;
 
 		if (mine) {
 			unit.DeAssignWorkerFromMine(*mine);
-			mine->RefsDecrease();
-			order->Arg1.Resource.Mine = NULL;
+			this->Resource.Mine = NULL;
 		}
 		if (goal->CurrentAction() != UnitActionBuilt) {
 			unit.AssignWorkerToMine(*goal);
-			goal->RefsIncrease();
-			order->Arg1.Resource.Mine = goal;
+			this->Resource.Mine = goal;
 		}
 	}
 	UnitGotoGoal(unit, goal, SUB_MOVE_TO_RESOURCE);
@@ -899,7 +997,7 @@ static bool ActionResourceInit(CUnit &unit)
 **
 **  @param unit  Pointer to unit.
 */
-void HandleActionResource(COrder& order, CUnit &unit)
+void COrder_Resource::Execute(CUnit &unit)
 {
 	if (unit.Wait) {
 		// FIXME: show idle animation while we wait?
@@ -908,33 +1006,29 @@ void HandleActionResource(COrder& order, CUnit &unit)
 	}
 
 	// Let's start mining.
-	if (order.SubAction.Res == SUB_START_RESOURCE) {
+	if (this->State == SUB_START_RESOURCE) {
 		if (ActionResourceInit(unit) == false) {
 			return;
 		}
 	}
 
 	// Move to the resource location.
-	if (SUB_MOVE_TO_RESOURCE <= order.SubAction.Res && order.SubAction.Res < SUB_UNREACHABLE_RESOURCE) {
+	if (SUB_MOVE_TO_RESOURCE <= this->State && this->State < SUB_UNREACHABLE_RESOURCE) {
 		const int ret = MoveToResource(unit);
 
-		switch (ret)
-		{
-			case -1: // Can't Reach
-			{
-				order.SubAction.Res++;
+		switch (ret) {
+			case -1: { // Can't Reach
+				this->State++;
 				unit.Wait = 5;
 				return;
 			}
-			case 1: // Reached
-			{
-				order.SubAction.Res = SUB_START_GATHERING;
+			case 1: { // Reached
+				this->State = SUB_START_GATHERING;
 				break;
 			}
 			case 0: // Move along.
 				return;
-			default:
-			{
+			default: {
 				Assert(0);
 				break;
 			}
@@ -942,59 +1036,55 @@ void HandleActionResource(COrder& order, CUnit &unit)
 	}
 
 	// Resource seems to be unreachable
-	if (order.SubAction.Res == SUB_UNREACHABLE_RESOURCE) {
+	if (this->State == SUB_UNREACHABLE_RESOURCE) {
 		ResourceGiveUp(unit);
 		return;
 	}
 
 	// Start gathering the resource
-	if (order.SubAction.Res == SUB_START_GATHERING) {
+	if (this->State == SUB_START_GATHERING) {
 		if (StartGathering(unit)) {
-			order.SubAction.Res = SUB_GATHER_RESOURCE;
+			this->State = SUB_GATHER_RESOURCE;
 		} else {
 			return;
 		}
 	}
 
 	// Gather the resource.
-	if (order.SubAction.Res == SUB_GATHER_RESOURCE) {
+	if (this->State == SUB_GATHER_RESOURCE) {
 		if (GatherResource(unit)) {
-			order.SubAction.Res = SUB_STOP_GATHERING;
+			this->State = SUB_STOP_GATHERING;
 		} else {
 			return;
 		}
 	}
 
 	// Stop gathering the resource.
-	if (order.SubAction.Res == SUB_STOP_GATHERING) {
+	if (this->State == SUB_STOP_GATHERING) {
 		if (StopGathering(unit)) {
-			order.SubAction.Res = SUB_MOVE_TO_DEPOT;
-			order.Data.Move.Cycles = 0; //moving counter
+			this->State = SUB_MOVE_TO_DEPOT;
+			this->Data.Move.Cycles = 0; //moving counter
 		} else
 			return;
 	}
 
 	// Move back home.
-	if (SUB_MOVE_TO_DEPOT <= order.SubAction.Res && order.SubAction.Res < SUB_UNREACHABLE_DEPOT) {
+	if (SUB_MOVE_TO_DEPOT <= this->State && this->State < SUB_UNREACHABLE_DEPOT) {
 		const int ret = MoveToDepot(unit);
 
-		switch (ret)
-		{
-			case -1: // Can't Reach
-			{
-				order.SubAction.Res++;
+		switch (ret) {
+			case -1: { // Can't Reach
+				this->State++;
 				unit.Wait = 5;
 				return;
 			}
-			case 1: // Reached
-			{
-				order.SubAction.Res = SUB_RETURN_RESOURCE;
+			case 1: { // Reached
+				this->State = SUB_RETURN_RESOURCE;
 				return;
 			}
 			case 0: // Move along.
 				return;
-			default:
-			{
+			default: {
 				Assert(0);
 				return;
 			}
@@ -1002,15 +1092,15 @@ void HandleActionResource(COrder& order, CUnit &unit)
 	}
 
 	// Depot seems to be unreachable
-	if (order.SubAction.Res == SUB_UNREACHABLE_DEPOT) {
+	if (this->State == SUB_UNREACHABLE_DEPOT) {
 		ResourceGiveUp(unit);
 		return;
 	}
 
 	// Unload resources at the depot.
-	if (order.SubAction.Res == SUB_RETURN_RESOURCE) {
+	if (this->State == SUB_RETURN_RESOURCE) {
 		if (WaitInDepot(unit)) {
-			order.SubAction.Res = SUB_START_RESOURCE;
+			this->State = 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
@@ -1018,9 +1108,8 @@ void HandleActionResource(COrder& order, CUnit &unit)
 			// are already in SUB_MOVE_TO_RESOURCE then we can handle it.
 			// So, we pass through SUB_START_RESOURCE the very instant it
 			// goes out of the depot.
-			HandleActionResource(order, unit);
+//			HandleActionResource(order, unit);
 		}
-		return;
 	}
 }
 
diff --git a/src/action/action_returngoods.cpp b/src/action/action_returngoods.cpp
index 846ada886..3c4d18084 100644
--- a/src/action/action_returngoods.cpp
+++ b/src/action/action_returngoods.cpp
@@ -47,7 +47,7 @@
 /*----------------------------------------------------------------------------
 --  Functions
 ----------------------------------------------------------------------------*/
-
+#if 0
 /**
 **  Return goods to gold/wood deposit.
 **
@@ -90,5 +90,5 @@ void HandleActionReturnGoods(COrder& order, CUnit &unit)
 	order.NewResetPath();
 	order.SubAction.Res = /* SUB_MOVE_TO_DEPOT */ 70; // FIXME : Define value.
 }
-
+#endif
 //@}
diff --git a/src/action/action_still.cpp b/src/action/action_still.cpp
index ec386d3e9..12d0bdeeb 100644
--- a/src/action/action_still.cpp
+++ b/src/action/action_still.cpp
@@ -59,7 +59,7 @@ enum {
 /* virtual */ void COrder_Still::Save(CFile &file, const CUnit &unit) const
 {
 	if (this->Action == UnitActionStill) {
-		file.printf("{\"action-still\"");
+		file.printf("{\"action-still\",");
 	} else {
 		file.printf("{\"action-stand-ground\",");
 	}
@@ -76,7 +76,7 @@ enum {
 		file.printf(" \"goal\", \"%s\",", UnitReference(goal).c_str());
 	}
 
-	file.printf(", \"state\", %d", this->State);
+	file.printf("\"state\", %d", this->State);
 	file.printf("}");
 }
 
diff --git a/src/action/actions.cpp b/src/action/actions.cpp
index 752eaa2c0..a699e67c4 100644
--- a/src/action/actions.cpp
+++ b/src/action/actions.cpp
@@ -269,7 +269,7 @@ unsigned SyncHash; /// Hash calculated to find sync failures
 
 /* static */ COrder* COrder::NewActionResource(CUnit &harvester, const Vec2i &pos)
 {
-	COrder *order = new COrder(UnitActionResource);
+	COrder_Resource *order = new COrder_Resource(harvester);
 	Vec2i ressourceLoc;
 
 	//  Find the closest piece of wood next to a tile where the unit can move
@@ -286,16 +286,21 @@ unsigned SyncHash; /// Hash calculated to find sync failures
 		ressourceLoc = pos;
 	}
 	order->goalPos = ressourceLoc;
+	order->CurrentResource = WoodCost; // Hard-coded resource.
 	order->Range = 1;
 
 	return order;
 }
 
-/* static */ COrder* COrder::NewActionResource(CUnit &mine)
+/* static */ COrder* COrder::NewActionResource(CUnit &harvester, CUnit &mine)
 {
-	COrder *order = new COrder(UnitActionResource);
+	COrder_Resource *order = new COrder_Resource(harvester);
 
 	order->SetGoal(&mine);
+	order->Resource.Mine = &mine;
+	harvester.AssignWorkerToMine(mine);
+	order->Resource.Pos = mine.tilePos + mine.Type->GetHalfTileSize();
+	order->CurrentResource = mine.Type->GivesResource;
 	order->Range = 1;
 
 	return order;
@@ -303,16 +308,25 @@ unsigned SyncHash; /// Hash calculated to find sync failures
 
 
 
-/* static */ COrder* COrder::NewActionReturnGoods(CUnit *depot)
+/* static */ COrder* COrder::NewActionReturnGoods(CUnit &harvester, CUnit *depot)
 {
-	COrder *order = new COrder(UnitActionReturnGoods);
+	COrder_Resource *order = new COrder_Resource(harvester);
 
 	// Destination could be killed. NETWORK!
-	if (depot && !depot->Destroyed) {
-		order->SetGoal(depot);
+	if (depot && depot->Destroyed) {
+		depot = NULL;
 	}
 	order->Range = 1;
+	order->CurrentResource = harvester.CurrentResource;
+	order->DoneHarvesting = true;
 
+	if (depot == NULL) {
+		depot = FindDeposit(harvester, 1000, harvester.CurrentResource);
+	}
+	order->Depot = depot;
+	if (depot) {
+		order->UnitGotoGoal(harvester, depot, 70); //SUB_MOVE_TO_DEPOT);
+	}
 	return order;
 }
 
@@ -403,15 +417,9 @@ COrder* COrder::Clone() const
 	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 clone;
 }
 
@@ -421,47 +429,6 @@ COrder::~COrder()
 		Goal->RefsDecrease();
 		Goal = NoUnitP;
 	}
-	if (Action == UnitActionResource && Arg1.Resource.Mine) {
-		Arg1.Resource.Mine->RefsDecrease();
-		Arg1.Resource.Mine = NoUnitP;
-	}
-}
-
-void COrder::ReleaseRefs(CUnit &unit)
-{
-	// Release pending references.
-	if (this->Action == UnitActionResource) {
-		CUnit *mine = this->Arg1.Resource.Mine;
-
-		if (mine) {
-			unit.DeAssignWorkerFromMine(*mine);
-			mine->RefsDecrease();
-			this->Arg1.Resource.Mine = NULL;
-
-		}
-	}
-	if (this->HasGoal()) {
-		// If mining decrease the active count on the resource.
-		if (this->Action == UnitActionResource) {
-			if (this->SubAction.Res == 60 /* SUB_GATHER_RESOURCE */ ) {
-				CUnit *goal = this->GetGoal();
-
-				goal->Resource.Active--;
-				Assert(goal->Resource.Active >= 0);
-			}
-		}
-		// Still shouldn't have a reference unless attacking
-		Assert(this->Action != UnitActionStill);
-		this->ClearGoal();
-	}
-#ifdef DEBUG
-	 else {
-		if (unit.CurrentResource &&
-			!unit.Type->ResInfo[unit.CurrentResource]->TerrainHarvester) {
-			Assert(this->Action != UnitActionResource);
-		}
-	}
-#endif
 }
 
 void COrder::SetGoal(CUnit *const new_goal)
@@ -511,21 +478,6 @@ bool COrder::OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/)
 		case UnitActionTransformInto:
 		case UnitActionBoard:
 		case UnitActionUnload:
-		case UnitActionReturnGoods:
-			// Unit is working ?
-			// Maybe AI should cancel action and save resources ???
-			return true;
-		case UnitActionResource:
-			if (SubAction.Res >= 65) {
-				//Normal return to depot
-				return true;
-			}
-			if (SubAction.Res > 55  &&
-				unit.ResourcesHeld > 0) {
-				//escape to Depot with this what you have;
-				Data.ResWorker.DoneHarvesting = 1;
-				return true;
-			}
 		break;
 		case UnitActionAttack:
 		{
@@ -1350,8 +1302,8 @@ static void (*HandleActionTable[256])(COrder&, CUnit &) = {
 	HandleActionNone, // HandleActionPatrol,
 	HandleActionNone, // HandleActionBuild,
 	HandleActionNone, // HandleActionRepair,
-	HandleActionResource,
-	HandleActionReturnGoods,
+	HandleActionNone, // HandleActionResource,
+	HandleActionNone, // HandleActionReturnGoods,
 	HandleActionNone, // HandleActionTransformInto,
 	HandleActionNotWritten,
 
diff --git a/src/action/command.cpp b/src/action/command.cpp
index 47ef0f163..6a1999fc5 100644
--- a/src/action/command.cpp
+++ b/src/action/command.cpp
@@ -536,7 +536,7 @@ void CommandResource(CUnit &unit, CUnit &dest, int flush)
 			return;
 		}
 	}
-	*order = COrder::NewActionResource(dest);
+	*order = COrder::NewActionResource(unit, dest);
 	ClearSavedAction(unit);
 }
 
@@ -568,7 +568,7 @@ void CommandReturnGoods(CUnit &unit, CUnit *goal, int flush)
 			return;
 		}
 	}
-	*order = COrder::NewActionReturnGoods(goal);
+	*order = COrder::NewActionReturnGoods(unit, goal);
 	ClearSavedAction(unit);
 }
 
diff --git a/src/ai/ai_resource.cpp b/src/ai/ai_resource.cpp
index c4d7f3d62..58cb318b9 100644
--- a/src/ai/ai_resource.cpp
+++ b/src/ai/ai_resource.cpp
@@ -237,14 +237,13 @@ static int AiBuildBuilding(const CUnitType &type, CUnitType &building, int near_
 		for (j = 0; j < unit.Orders.size(); ++j) {
 			int action = unit.Orders[j]->Action;
 			if (action == UnitActionBuild ||
-				action == UnitActionRepair ||
-				action == UnitActionReturnGoods) {
+				action == UnitActionRepair) {
 					break;
 				}
 			if (action == UnitActionResource) {
-				const COrder &order = *unit.Orders[j];
+				const COrder_Resource &order = *static_cast<const COrder_Resource*>(unit.Orders[j]);
 
-				if (order.SubAction.Res > 55 /* SUB_START_GATHERING */) {
+				if (order.IsGatheringStarted()) {
 					break;
 				}
 			}
@@ -330,18 +329,10 @@ void AiNewDepotRequest(CUnit &worker) {
 				_C_ worker->Data.Move.Cycles
 				);
 	*/
+	Assert(worker.CurrentAction() == UnitActionResource);
+	COrder_Resource &order = *static_cast<COrder_Resource*>(worker.CurrentOrder());
 
-	Vec2i pos = {-1, -1};
-	ResourceInfo *resinfo = worker.Type->ResInfo[worker.CurrentResource];
-
-	if (resinfo->TerrainHarvester) {
-		pos = worker.CurrentOrder()->Arg1.Resource.Pos;
-	} else {
-		CUnit *mine = worker.CurrentOrder()->Arg1.Resource.Mine;
-		if (mine) {
-			pos = mine->tilePos;
-		}
-	}
+	const Vec2i pos = order.GetHarvestLocation();
 
 	if (pos.x != -1 && NULL != FindDepositNearLoc(*worker.Player, pos, 10, worker.CurrentResource)) {
 		/*
@@ -1098,9 +1089,10 @@ static void AiCollectResources()
 					for (int k = num_units_assigned[src_c] - 1; k >= 0 && !unit; --k) {
 						unit = units_assigned[src_c][k];
 
-						COrder &order = *unit->CurrentOrder();
+						Assert(unit->CurrentAction() == UnitActionResource);
+						COrder_Resource &order = *static_cast<COrder_Resource*>(unit->CurrentOrder());
 
-						if (order.SubAction.Res >= 65 /* SUB_STOP_GATHERING */ ) {
+						if (order.IsGatheringFinished()) {
 							//worker returning with resource
 							continue;
 						}
@@ -1173,9 +1165,9 @@ static int AiRepairBuilding(const CUnitType &type, CUnit &building)
 			if (unit.CurrentAction() == UnitActionStill) {
 				table[num++] = &unit;
 			} else if (unit.CurrentAction() == UnitActionResource) {
-				COrder &order = *unit.CurrentOrder();
+				COrder_Resource &order = *static_cast<COrder_Resource*>(unit.CurrentOrder());
 
-				if (order.SubAction.Res <= 55 /* SUB_START_GATHERING */) {
+				if (order.IsGatheringStarted() == false) {
 					table[num++] = &unit;
 				}
 			}
diff --git a/src/include/actions.h b/src/include/actions.h
index 0786948b6..77ce35a92 100644
--- a/src/include/actions.h
+++ b/src/include/actions.h
@@ -83,7 +83,7 @@ enum UnitAction {
 
 	UnitActionRepair,       /// unit repairing
 	UnitActionResource,     /// unit harvesting resources
-	UnitActionReturnGoods,  /// unit returning any resource
+	UnitActionDummy, // UnitActionReturnGoods,  /// unit returning any resource
 	UnitActionTransformInto /// unit transform into type.
 };
 
@@ -104,11 +104,10 @@ class COrder
 
 public:
 	COrder(int action) : Goal(NULL), Range(0), MinRange(0), Width(0),
-		Height(0), Action(action), Finished(false), CurrentResource(0)
+		Height(0), Action(action), Finished(false)
 	{
 		goalPos.x = -1;
 		goalPos.y = -1;
-		memset(&Arg1, 0, sizeof (Arg1));
 		memset(&SubAction, 0, sizeof (SubAction));
 		memset(&Data, 0, sizeof (Data));
 	}
@@ -127,7 +126,7 @@ public:
 	virtual void FillSeenValues(CUnit &unit) const;
 	virtual void AiUnitKilled(CUnit &unit);
 
-	void ReleaseRefs(CUnit &owner);
+	void ReleaseRefs(CUnit &owner) {}
 	bool CheckRange() const;
 
 	bool HasGoal() const { return Goal != NULL; }
@@ -159,8 +158,8 @@ public:
 	static COrder* NewActionRepair(const Vec2i &pos);
 	static COrder* NewActionResearch(CUnit &unit, CUpgrade &upgrade);
 	static COrder* NewActionResource(CUnit &harvester, const Vec2i &pos);
-	static COrder* NewActionResource(CUnit &mine);
-	static COrder* NewActionReturnGoods(CUnit *depot);
+	static COrder* NewActionResource(CUnit &harvester, CUnit &mine);
+	static COrder* NewActionReturnGoods(CUnit &harvester, CUnit *depot);
 	static COrder* NewActionSpellCast(SpellType &spell, const Vec2i &pos, CUnit *target);
 	static COrder* NewActionStandGround();
 	static COrder* NewActionStill();
@@ -172,8 +171,6 @@ public:
 #if 1 // currently needed for parsing
 	static COrder* NewActionAttack() { return new COrder(UnitActionAttack); }
 	static COrder* NewActionAttackGround() { return new COrder(UnitActionAttackGround); }
-	static COrder* NewActionResource() { return new COrder(UnitActionResource); }
-	static COrder* NewActionReturnGoods() { return new COrder(UnitActionReturnGoods); }
 #endif
 
 private:
@@ -184,22 +181,13 @@ public:
 	unsigned int  MinRange; /// How far away minimum
 	unsigned char Width;    /// Goal Width (used when Goal is not)
 	unsigned char Height;   /// Goal Height (used when Goal is not)
-	unsigned char Action;   /// global action
+	const unsigned char Action;   /// global action
 	bool Finished; /// true when order is finish
-	unsigned char CurrentResource; ///used in UnitActionResource and UnitActionReturnGoods
 
 	Vec2i goalPos;          /// or tile coordinate of destination
 
-	union {
-		struct {
-			Vec2i Pos; /// position for terrain resource.
-			CUnit *Mine;
-		} Resource;
-	} Arg1;             /// Extra command argument.
-
 	union {
 		int Attack;
-		int Res;
 	} SubAction;
 
 
@@ -211,13 +199,10 @@ public:
 #define MAX_PATH_LENGTH 28          /// max length of precalculated path
 		char Path[MAX_PATH_LENGTH]; /// directions of stored path
 	} Move; /// ActionMove,...
-	struct _order_resource_worker_ {
-		int TimeToHarvest;          /// how much time until we harvest some more.
-		unsigned DoneHarvesting:1;  /// Harvesting done, wait for action to break.
-	} ResWorker; /// Worker harvesting
 	} Data; /// Storage room for different commands
 };
 
+
 class COrder_Board : public COrder
 {
 	friend COrder* COrder::NewActionBoard(CUnit &unit);
@@ -409,6 +394,63 @@ private:
 	CUpgrade *Upgrade;
 };
 
+class COrder_Resource : public COrder
+{
+	friend COrder* COrder::NewActionResource(CUnit &harvester, const Vec2i &pos);
+	friend COrder* COrder::NewActionResource(CUnit &harvester, CUnit &mine);
+	friend COrder* COrder::NewActionReturnGoods(CUnit &harvester, CUnit *depot);
+
+public:
+	COrder_Resource(CUnit &harvester) : COrder(UnitActionResource), worker(&harvester),
+		CurrentResource(0), State(0), TimeToHarvest(0), DoneHarvesting(false)
+	{
+		Resource.Pos.x = Resource.Pos.y = -1;
+	}
+
+	~COrder_Resource();
+
+	virtual COrder_Resource *Clone() const { return new COrder_Resource(*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 void Execute(CUnit &unit);
+
+	bool OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/);
+	virtual void ReleaseRefs(CUnit &unit);
+
+
+	Vec2i GetHarvestLocation() const; // { return Pos || Mine->tilePos;}
+	bool IsGatheringStarted() const;
+	bool IsGatheringFinished() const;
+	bool IsGatheringWaiting() const;
+private:
+	int MoveToResource_Terrain(CUnit &unit);
+	int MoveToResource_Unit(CUnit &unit);
+	int MoveToResource(CUnit &unit);
+	void UnitGotoGoal(CUnit &unit, CUnit *const goal, int state);
+	int StartGathering(CUnit &unit);
+	void LoseResource(CUnit &unit, const CUnit &source);
+	int GatherResource(CUnit &unit);
+	int StopGathering(CUnit &unit);
+	int MoveToDepot(CUnit &unit);
+	bool WaitInDepot(CUnit &unit);
+	void DropResource(CUnit &unit);
+	void ResourceGiveUp(CUnit &unit);
+	bool ActionResourceInit(CUnit &unit);
+private:
+	CUnitPtr worker; /// unit that own this order.
+	unsigned char CurrentResource;
+	struct {
+		Vec2i Pos; /// position for terrain resource.
+		CUnitPtr Mine;
+	} Resource;
+	CUnitPtr Depot;
+	int State;
+	int TimeToHarvest;          /// how much time until we harvest some more.
+	bool DoneHarvesting;  /// Harvesting done, wait for action to break.
+};
+
 class COrder_SpellCast : public COrder
 {
 public:
@@ -614,8 +656,6 @@ extern void CommandSharedVision(int player, bool state, int opponent);
 --  Actions: in action_<name>.c
 ----------------------------------------------------------------------------*/
 
-extern void DropResource(CUnit &unit);
-extern void ResourceGiveUp(CUnit &unit);
 extern int GetNumWaitingWorkers(const CUnit &mine);
 extern bool AutoAttack(CUnit &unit);
 extern bool AutoRepair(CUnit &unit);
@@ -632,10 +672,6 @@ typedef void HandleActionFunc(COrder& order, CUnit &unit);
 
 	/// Handle command attack
 extern HandleActionFunc HandleActionAttack;
-	/// Handle command resource
-extern HandleActionFunc HandleActionResource;
-	/// Handle command return
-extern HandleActionFunc HandleActionReturnGoods;
 
 /*----------------------------------------------------------------------------
 --  Actions: actions.c
diff --git a/src/include/unit.h b/src/include/unit.h
index fe50ffac6..3808aa89a 100644
--- a/src/include/unit.h
+++ b/src/include/unit.h
@@ -1246,7 +1246,7 @@ extern void SelectionCclRegister();
 // in ccl_unit.c
 
 	/// Parse order
-extern void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr order);
+extern void CclParseOrder(lua_State *l, CUnit &unit, COrderPtr order);
 	/// register CCL units features
 extern void UnitCclRegister();
 
diff --git a/src/unit/script_unit.cpp b/src/unit/script_unit.cpp
index f1dc82a17..d45c27b74 100644
--- a/src/unit/script_unit.cpp
+++ b/src/unit/script_unit.cpp
@@ -132,39 +132,6 @@ CUnit *CclGetUnitFromRef(lua_State *l)
 	return UnitSlots[slot];
 }
 
-/**
-**  Parse res worker data
-**
-**  @param l     Lua state.
-**  @param unit  Unit pointer which should be filled with the data.
-*/
-static void CclParseResWorker(lua_State *l, COrderPtr order)
-{
-	const char *value;
-	int args;
-	int j;
-
-	if (!lua_istable(l, -1)) {
-		LuaError(l, "incorrect argument");
-	}
-	args = lua_objlen(l, -1);
-	for (j = 0; j < args; ++j) {
-		lua_rawgeti(l, -1, j + 1);
-		value = LuaToString(l, -1);
-		lua_pop(l, 1);
-		++j;
-		if (!strcmp(value, "time-to-harvest")) {
-			lua_rawgeti(l, -1, j + 1);
-			order->Data.ResWorker.TimeToHarvest = LuaToNumber(l, -1);
-			lua_pop(l, 1);
-		} else if (!strcmp(value, "done-harvesting")) {
-			order->Data.ResWorker.DoneHarvesting = 1;
-			--j;
-		} else {
-			LuaError(l, "ParseResWorker: Unsupported tag: %s" _C_ value);
-		}
-	}
-}
 
 bool COrder::ParseGenericData(lua_State *l, int &j, const char *value)
 {
@@ -261,59 +228,8 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU
 	} else if (!strcmp(value, "subaction")) {
 		++j;
 		lua_rawgeti(l, -1, j + 1);
-		this->SubAction.Attack = this->SubAction.Res = LuaToNumber(l, -1);
+		this->SubAction.Attack = LuaToNumber(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-res-worker")) {
-		++j;
-		lua_rawgeti(l, -1, j + 1);
-		CclParseResWorker(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;
 	}
@@ -326,7 +242,7 @@ bool COrder::ParseSpecificData(lua_State *l, int &j, const char *value, const CU
 **  @param l      Lua state.
 **  @param order  OUT: resulting order.
 */
-void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
+void CclParseOrder(lua_State *l, CUnit &unit, COrderPtr *orderPtr)
 {
 	const int args = lua_objlen(l, -1);
 
@@ -369,9 +285,7 @@ void CclParseOrder(lua_State *l, const CUnit &unit, COrderPtr *orderPtr)
 	} else if (!strcmp(actiontype, "action-repair")) {
 		*orderPtr = new COrder_Repair;
 	} else if (!strcmp(actiontype, "action-resource")) {
-		*orderPtr = COrder::NewActionResource();
-	} else if (!strcmp(actiontype, "action-return-goods")) {
-		*orderPtr = COrder::NewActionReturnGoods();
+		*orderPtr = new COrder_Resource(unit);
 	} else if (!strcmp(actiontype, "action-transform-into")) {
 		*orderPtr = new COrder_TransformInto;
 	} else {
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 6163199b0..24c0b2077 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -376,7 +376,6 @@ bool CUnit::RestoreOrder()
 
 	//copy
 	this->Orders.insert(this->Orders.begin() + 1, this->SavedOrder);
-	this->CurrentResource = this->SavedOrder->CurrentResource;
 
 	this->SavedOrder = NULL;
 	return true;
@@ -3410,18 +3409,6 @@ void CleanUnits()
 				continue;
 			}
 			if (!unit->Destroyed) {
-				if (unit->CurrentAction() == UnitActionResource) {
-					ResourceInfo *resinfo = unit->Type->ResInfo[unit->CurrentResource];
-					if (resinfo && !resinfo->TerrainHarvester) {
-						CUnit *mine = unit->CurrentOrder()->Arg1.Resource.Mine;
-						if (mine && !mine->Destroyed) {
-							unit->DeAssignWorkerFromMine(*mine);
-							mine->RefsDecrease();
-							unit->CurrentOrder()->Arg1.Resource.Mine = NULL;
-						}
-					}
-				}
-				unit->CurrentOrder()->ClearGoal();
 				if (!unit->Removed) {
 					unit->Remove(NULL);
 				}
diff --git a/src/unit/unit_draw.cpp b/src/unit/unit_draw.cpp
index f6673c774..b56876ea1 100644
--- a/src/unit/unit_draw.cpp
+++ b/src/unit/unit_draw.cpp
@@ -819,11 +819,6 @@ static void ShowSingleOrder(const CUnit &unit, const PixelPos &pos, const COrder
 			dest = true;
 			break;
 
-		case UnitActionReturnGoods:
-			e_color = color = ColorYellow;
-			dest = true;
-			break;
-
 		default:
 			e_color = color = ColorGray;
 			DebugPrint("Unknown action %d\n" _C_ order.Action);
diff --git a/src/unit/unit_save.cpp b/src/unit/unit_save.cpp
index d8c5dc0a3..d1e1db55b 100644
--- a/src/unit/unit_save.cpp
+++ b/src/unit/unit_save.cpp
@@ -102,12 +102,6 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
 		case UnitActionAttackGround:
 			file.printf("\"action-attack-ground\",");
 			break;
-		case UnitActionResource:
-			file.printf("\"action-resource\",");
-			break;
-		case UnitActionReturnGoods:
-			file.printf("\"action-return-goods\",");
-			break;
 		default:
 			DebugPrint("Unknown action in order\n");
 	}
@@ -137,52 +131,16 @@ void SaveOrder(const COrder &order, const CUnit &unit, CFile *file)
 		case UnitActionAttackGround:
 			file.printf(", \"subaction\", %d", order.SubAction.Attack);
 			break;
-		case UnitActionResource:
-		case UnitActionReturnGoods:
-			file.printf(", \"subaction\", %d", order.SubAction.Res);
-			break;
-	}
-
-
-	// Extra arg.
-	switch (order.Action) {
-		case UnitActionResource :
-		case UnitActionReturnGoods :
-			if (order.CurrentResource) {
-				file.printf(", \"current-resource\", \"%s\",", DefaultResourceNames[order.CurrentResource].c_str());
-				const CUnit *mine = order.Arg1.Resource.Mine;
-
-				if (mine == NULL) {
-					const Vec2i &pos = order.Arg1.Resource.Pos;
-
-					file.printf(" \"resource-pos\", {%d, %d}", pos.x, pos.y);
-				} else {
-					if (mine->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 Mine - loading will fail.\n");
-					}
-					file.printf(" \"resource-mine\", \"%s\"", UnitReference(*mine).c_str());
-				}
-			}
-			break;
 		default:
 			break;
 	}
+
 	//
 	//  Order data part
 	//
 	switch (order.Action) {
 		case UnitActionStill:
-			// FIXME: support other resource types
-			break;
 		case UnitActionResource:
-			file.printf(", \"data-res-worker\", {\"time-to-harvest\", %d", order.Data.ResWorker.TimeToHarvest);
-			if (order.Data.ResWorker.DoneHarvesting) {
-				file.printf(", \"done-harvesting\"");
-			}
-			file.printf("}");
-			break;
 		case UnitActionBuilt:
 		case UnitActionResearch:
 		case UnitActionUpgradeTo: