From 137e4e58fd3706ad1ab8202a5acf5003ed1e89d0 Mon Sep 17 00:00:00 2001
From: joris <joris.dauphin@gmail.com>
Date: Tue, 14 Feb 2012 12:08:22 +0100
Subject: [PATCH] Move some code into COrder

---
 src/action/actions.cpp | 212 ++++++++++++++++++++++++++++++-----------
 src/ai/ai.cpp          |  43 ++-------
 src/include/actions.h  |   6 ++
 src/unit/unit.cpp      |  60 +-----------
 4 files changed, 178 insertions(+), 143 deletions(-)

diff --git a/src/action/actions.cpp b/src/action/actions.cpp
index 7825ff60b..af78512c3 100644
--- a/src/action/actions.cpp
+++ b/src/action/actions.cpp
@@ -58,11 +58,52 @@
 
 unsigned SyncHash; /// Hash calculated to find sync failures
 
+
+extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
+
+
 /*----------------------------------------------------------------------------
 --  Functions
 ----------------------------------------------------------------------------*/
 
-COrder::~COrder() {
+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();
+	}
+}
+
+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();
+		}
+	}
+	return *this;
+}
+
+COrder::~COrder()
+{
 	if (Goal) {
 		Goal->RefsDecrease();
 		Goal = NoUnitP;
@@ -110,46 +151,6 @@ void COrder::ReleaseRefs(CUnit &unit)
 #endif
 }
 
-
-
-
-
-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();
-	}
-}
-
-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();
-		}
-	}
-	return *this;
-}
-
 void COrder::SetGoal(CUnit *const new_goal)
 {
 	if (new_goal) {
@@ -175,6 +176,118 @@ bool COrder::CheckRange() const
 	return (Range <= Map.Info.MapWidth || Range <= Map.Info.MapHeight);
 }
 
+void COrder::FillSeenValues(CUnit &unit) const
+{
+	unit.Seen.State = (Action == UnitActionBuilt) | ((Action == UnitActionUpgradeTo) << 1);
+	if (unit.CurrentAction() == UnitActionDie) {
+		unit.Seen.State = 3;
+	}
+	if (Action == UnitActionBuilt) {
+		unit.Seen.CFrame = Data.Built.Frame;
+	} else {
+		unit.Seen.CFrame = NULL;
+	}
+}
+
+bool COrder::OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/)
+{
+	Assert(unit.CurrentOrder() == this);
+
+	switch (Action) {
+		case UnitActionTrain:
+		case UnitActionUpgradeTo:
+		case UnitActionResearch:
+		case UnitActionBuilt:
+		case UnitActionBuild:
+		case UnitActionTransformInto:
+		case UnitActionBoard:
+		case UnitActionUnload:
+		case UnitActionReturnGoods:
+			// Unit is working ?
+			// Maybe AI should cancel action and save resources ???
+			return true;
+		case UnitActionResource:
+			if (unit.SubAction >= 65) {
+				//Normal return to depot
+				return true;
+			}
+			if (unit.SubAction > 55  &&
+				unit.ResourcesHeld > 0) {
+				//escape to Depot with this what you have;
+				Data.ResWorker.DoneHarvesting = 1;
+				return true;
+			}
+		break;
+		case UnitActionAttack:
+		{
+			CUnit *goal = GetGoal();
+			if (goal) {
+				if (goal == attacker ||
+					(goal->CurrentAction() == UnitActionAttack &&
+					goal->CurrentOrder()->GetGoal() == &unit))
+				{
+					//we already fight with one of attackers;
+					return true;
+				}
+			}
+		}
+		default:
+		break;
+	}
+	return false;
+}
+
+
+/** Called when unit is killed.
+**  warn the AI module.
+*/
+void COrder::AiUnitKilled(CUnit& unit)
+{
+	switch (Action) {
+		case UnitActionStill:
+		case UnitActionAttack:
+		case UnitActionMove:
+			break;
+		case UnitActionBuilt:
+			DebugPrint("%d: %d(%s) killed, under construction!\n" _C_
+				unit.Player->Index _C_ UnitNumber(unit) _C_ unit.Type->Ident.c_str());
+			AiReduceMadeInBuilt(*unit.Player->Ai, *unit.Type);
+			break;
+		case UnitActionBuild:
+			DebugPrint("%d: %d(%s) killed, with order %s!\n" _C_
+				unit.Player->Index _C_ UnitNumber(unit) _C_
+				unit.Type->Ident.c_str() _C_ Arg1.Type->Ident.c_str());
+			if (!HasGoal()) {
+				AiReduceMadeInBuilt(*unit.Player->Ai, *Arg1.Type);
+			}
+			break;
+		default:
+			DebugPrint("FIXME: %d: %d(%s) killed, with order %d!\n" _C_
+				unit.Player->Index _C_ UnitNumber(unit) _C_
+				unit.Type->Ident.c_str() _C_ Action);
+			break;
+	}
+}
+
+/**
+**  Call when animation step is "attack"
+*/
+void COrder::OnAnimationAttack(CUnit &unit)
+{
+	Assert(unit.CurrentOrder() == this);
+
+	if (Action == UnitActionSpellCast) {
+		CUnit *goal = GetGoal();
+		if (goal && !goal->IsVisibleAsGoal(*unit.Player)) {
+			unit.ReCast = 0;
+		} else {
+			unit.ReCast = SpellCast(unit, Arg1.Spell, goal, goalPos.x, goalPos.y);
+		}
+	} else {
+		FireMissile(unit);
+	}
+	UnHideUnit(unit); // unit is invisible until attacks
+}
 
 
 /*----------------------------------------------------------------------------
@@ -282,21 +395,10 @@ int UnitShowAnimationScaled(CUnit &unit, const CAnimation *anim, int scale)
 				break;
 
 			case AnimationAttack:
-				if (unit.CurrentAction() == UnitActionSpellCast) {
-					CUnit *goal = unit.CurrentOrder()->GetGoal();
-					if (goal && !goal->IsVisibleAsGoal(*unit.Player)) {
-						unit.ReCast = 0;
-					} else {
-						COrderPtr order = unit.CurrentOrder();
-						unit.ReCast = SpellCast(unit, order->Arg1.Spell,
-											goal, order->goalPos.x, order->goalPos.y);
-					}
-				} else {
-					FireMissile(unit);
-				}
-				UnHideUnit(unit); // unit is invisible until attacks
+			{
+				unit.CurrentOrder()->OnAnimationAttack(unit);
 				break;
-
+			}
 			case AnimationSpawnMissile:
 				x = unit.tilePos.x * PixelTileSize.x + PixelTileSize.x / 2;  
 				y = unit.tilePos.y * PixelTileSize.y + PixelTileSize.y / 2;
diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp
index fa4b5affc..f51556c1e 100644
--- a/src/ai/ai.cpp
+++ b/src/ai/ai.cpp
@@ -620,17 +620,17 @@ static void AiRemoveFromBuilt(PlayerAi *pai, const CUnitType &type)
 **  @param type  Unit-type which is now available.
 **  @return      True if the unit-type could be reduced.
 */
-static int AiReduceMadeInBuilt2(PlayerAi *pai, const CUnitType &type)
+static bool AiReduceMadeInBuilt2(PlayerAi &pai, const CUnitType &type)
 {
 	std::vector<AiBuildQueue>::iterator i;
 
-	for (i = pai->UnitTypeBuilt.begin(); i != pai->UnitTypeBuilt.end(); ++i) {
+	for (i = pai.UnitTypeBuilt.begin(); i != pai.UnitTypeBuilt.end(); ++i) {
 		if (&type == (*i).Type && (*i).Made) {
 			(*i).Made--;
-			return 1;
+			return true;
 		}
 	}
-	return 0;
+	return false;
 }
 
 /**
@@ -639,7 +639,7 @@ static int AiReduceMadeInBuilt2(PlayerAi *pai, const CUnitType &type)
 **  @param pai   Computer AI player.
 **  @param type  Unit-type which is now available.
 */
-static void AiReduceMadeInBuilt(PlayerAi *pai, const CUnitType &type)
+void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type)
 {
 	if (AiReduceMadeInBuilt2(pai, type)) {
 		return;
@@ -653,7 +653,7 @@ static void AiReduceMadeInBuilt(PlayerAi *pai, const CUnitType &type)
 			return;
 		}
 	}
-	if (pai->Player == ThisPlayer) {
+	if (pai.Player == ThisPlayer) {
 		DebugPrint
 			("My guess is that you built something under ai me. naughty boy!\n");
 		return;
@@ -722,6 +722,7 @@ void AiHelpMe(const CUnit *attacker, CUnit &defender)
 
 					if (aiunit.StoreOrder(savedOrder) == false) {
 						delete savedOrder;
+						savedOrder = NULL;
 					}
 				}
 			}
@@ -779,31 +780,7 @@ void AiUnitKilled(CUnit &unit)
 		}
 	}
 
-	// FIXME: must handle all orders...
-	switch (unit.CurrentAction()) {
-		case UnitActionStill:
-		case UnitActionAttack:
-		case UnitActionMove:
-			break;
-		case UnitActionBuilt:
-			DebugPrint("%d: %d(%s) killed, under construction!\n" _C_
-				unit.Player->Index _C_ UnitNumber(unit) _C_ unit.Type->Ident.c_str());
-			AiReduceMadeInBuilt(unit.Player->Ai, *unit.Type);
-			break;
-		case UnitActionBuild:
-			DebugPrint("%d: %d(%s) killed, with order %s!\n" _C_
-				unit.Player->Index _C_ UnitNumber(unit) _C_
-				unit.Type->Ident.c_str() _C_ unit.CurrentOrder()->Arg1.Type->Ident.c_str());
-			if (!unit.CurrentOrder()->HasGoal()) {
-				AiReduceMadeInBuilt(unit.Player->Ai, *unit.CurrentOrder()->Arg1.Type);
-			}
-			break;
-		default:
-			DebugPrint("FIXME: %d: %d(%s) killed, with order %d!\n" _C_
-				unit.Player->Index _C_ UnitNumber(unit) _C_
-				unit.Type->Ident.c_str() _C_ unit.CurrentAction());
-			break;
-	}
+	unit.CurrentOrder()->AiUnitKilled(unit);
 }
 
 /**
@@ -840,7 +817,7 @@ void AiCanNotBuild(CUnit &unit, const CUnitType &what)
 		what.Ident.c_str() _C_ unit.tilePos.x _C_ unit.tilePos.y);
 
 	Assert(unit.Player->Type != PlayerPerson);
-	AiReduceMadeInBuilt(unit.Player->Ai, what);
+	AiReduceMadeInBuilt(*unit.Player->Ai, what);
 }
 
 /**
@@ -852,7 +829,7 @@ void AiCanNotBuild(CUnit &unit, const CUnitType &what)
 void AiCanNotReach(CUnit &unit, const CUnitType &what)
 {
 	Assert(unit.Player->Type != PlayerPerson);
-	AiReduceMadeInBuilt(unit.Player->Ai, what);
+	AiReduceMadeInBuilt(*unit.Player->Ai, what);
 }
 
 /**
diff --git a/src/include/actions.h b/src/include/actions.h
index 82bf0459b..ec9b9a43c 100644
--- a/src/include/actions.h
+++ b/src/include/actions.h
@@ -144,6 +144,12 @@ public:
 	void NewResetPath() { Data.Move.Fast = 1; Data.Move.Length = 0; }
 
 
+	void FillSeenValues(CUnit &unit) const;
+
+	bool OnAiHitUnit(CUnit &unit, CUnit *attacker, int /*damage*/);
+	void AiUnitKilled(CUnit &unit);
+
+	void OnAnimationAttack(CUnit &unit);
 private:
 	friend void CclParseOrder(lua_State *l, const CUnit &unit, COrder* order);
 
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 986982e90..7042ed69a 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -1127,18 +1127,10 @@ static void UnitFillSeenValues(CUnit &unit)
 	unit.Seen.IY = unit.IY;
 	unit.Seen.IX = unit.IX;
 	unit.Seen.Frame = unit.Frame;
-	unit.Seen.State = (unit.CurrentAction() == UnitActionBuilt) |
-			((unit.CurrentAction() == UnitActionUpgradeTo) << 1);
-	if (unit.CurrentAction() == UnitActionDie) {
-		unit.Seen.State = 3;
-	}
 	unit.Seen.Type = unit.Type;
 	unit.Seen.Constructed = unit.Constructed;
-	if (unit.CurrentAction() == UnitActionBuilt) {
-		unit.Seen.CFrame = unit.CurrentOrder()->Data.Built.Frame;
-	} else {
-		unit.Seen.CFrame = NULL;
-	}
+
+	unit.CurrentOrder()->FillSeenValues(unit);
 }
 
 /**
@@ -2949,55 +2941,13 @@ void HitUnit(CUnit *attacker, CUnit &target, int damage)
 	}
 
 	/* Target Reaction on Hit */
-	if (target.Player->AiEnabled){
-		switch (target.CurrentAction()) {
-			case UnitActionTrain:
-			case UnitActionUpgradeTo:
-			case UnitActionResearch:
-			case UnitActionBuilt:
-			case UnitActionBuild:
-			case UnitActionTransformInto:
-			case UnitActionBoard:
-			case UnitActionUnload:
-			case UnitActionReturnGoods:
-				//
-				// Unit is working?
-				// Maybe AI should cance action and save resources???
-				//
-				return;
-			case UnitActionResource:
-				if (target.SubAction >= 65) {
-					//Normal return to depot
-					return;
-				}
-				if (target.SubAction > 55  &&
-					target.ResourcesHeld > 0) {
-					//escape to Depot with this what you have;
-					target.CurrentOrder()->Data.ResWorker.DoneHarvesting = 1;
-					return;
-				}
-			break;
-			case UnitActionAttack:
-			{
-				CUnit *goal = target.CurrentOrder()->GetGoal();
-				if (goal) {
-					if (goal == attacker ||
-						(goal->CurrentAction() == UnitActionAttack &&
-						goal->CurrentOrder()->GetGoal() == &target))
-					{
-						//we already fight with one of attackers;
-						return;
-					}
-				}
-			}
-			default:
-			break;
+	if (target.Player->AiEnabled) {
+		if (target.CurrentOrder()->OnAiHitUnit(target, attacker, damage)) {
+			return;
 		}
 	}
 
-	//
 	// Attack units in range (which or the attacker?)
-	//
 	if (attacker && target.IsAgressive() && target.CanMove()) {
 		if (target.CurrentAction() != UnitActionStill && !target.Player->AiEnabled) {
 			return;