From 17540efd29b45131ffc03eaaef1de80b924f2cb0 Mon Sep 17 00:00:00 2001
From: Joris <joris.dauphin@gmail.com>
Date: Fri, 11 May 2012 14:58:43 +0200
Subject: [PATCH] Fix CUnit::RestoreOrder to remove invalid stocked order. Make
 the check of Order validity more generic.

---
 src/action/action_attack.cpp          | 14 ++++++++++++++
 src/action/action_board.cpp           |  5 +++++
 src/action/action_build.cpp           |  8 ++++++++
 src/action/action_built.cpp           |  5 +++++
 src/action/action_die.cpp             |  5 +++++
 src/action/action_follow.cpp          |  5 +++++
 src/action/action_move.cpp            |  5 +++++
 src/action/action_patrol.cpp          |  5 +++++
 src/action/action_repair.cpp          |  6 ++++--
 src/action/action_research.cpp        |  5 ++++-
 src/action/action_resource.cpp        |  5 +++++
 src/action/action_spellcast.cpp       |  5 +++++
 src/action/action_still.cpp           |  5 +++++
 src/action/action_train.cpp           |  5 +++++
 src/action/action_unload.cpp          |  5 +++++
 src/action/action_upgradeto.cpp       | 11 +++++++++++
 src/include/action/action_attack.h    |  1 +
 src/include/action/action_board.h     |  2 ++
 src/include/action/action_build.h     |  2 ++
 src/include/action/action_built.h     |  2 ++
 src/include/action/action_die.h       |  2 ++
 src/include/action/action_follow.h    |  2 ++
 src/include/action/action_move.h      |  2 ++
 src/include/action/action_patrol.h    |  2 ++
 src/include/action/action_repair.h    |  2 ++
 src/include/action/action_research.h  |  2 ++
 src/include/action/action_resource.h  |  2 ++
 src/include/action/action_spellcast.h |  2 ++
 src/include/action/action_still.h     |  2 ++
 src/include/action/action_train.h     |  2 ++
 src/include/action/action_unload.h    |  2 ++
 src/include/action/action_upgradeto.h |  4 ++++
 src/include/actions.h                 |  1 +
 src/unit/unit.cpp                     |  6 +++---
 34 files changed, 133 insertions(+), 6 deletions(-)

diff --git a/src/action/action_attack.cpp b/src/action/action_attack.cpp
index 9b341bceb..7bda9c0b8 100644
--- a/src/action/action_attack.cpp
+++ b/src/action/action_attack.cpp
@@ -185,6 +185,20 @@ void AnimateActionAttack(CUnit &unit, COrder &order)
 	return true;
 }
 
+/* virtual */ bool COrder_Attack::IsValid() const
+{
+	if (Action == UnitActionAttack) {
+		if (this->HasGoal()) {
+			return this->GetGoal()->IsAlive();
+		} else {
+			return Map.Info.IsPointOnMap(this->goalPos);
+		}
+	} else {
+		Assert(Action == UnitActionAttackGround);
+		return Map.Info.IsPointOnMap(this->goalPos);
+	}
+}
+
 /* virtual */ PixelPos COrder_Attack::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	PixelPos targetPos;
diff --git a/src/action/action_board.cpp b/src/action/action_board.cpp
index 2a5d1c2c1..1ef544dcb 100644
--- a/src/action/action_board.cpp
+++ b/src/action/action_board.cpp
@@ -111,6 +111,11 @@ enum {
 	return true;
 }
 
+/* virtual */ bool COrder_Board::IsValid() const
+{
+	return this->HasGoal() && this->GetGoal()->IsAliveOnMap();
+}
+
 /* virtual */ PixelPos COrder_Board::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	PixelPos targetPos;
diff --git a/src/action/action_build.cpp b/src/action/action_build.cpp
index 786afdc56..58dfe8d6b 100644
--- a/src/action/action_build.cpp
+++ b/src/action/action_build.cpp
@@ -45,6 +45,7 @@
 #include "ai.h"
 #include "animation.h"
 #include "iolib.h"
+#include "map.h"
 #include "pathfinder.h"
 #include "player.h"
 #include "script.h"
@@ -72,6 +73,8 @@ enum {
 
 /* static */ COrder *COrder::NewActionBuild(const CUnit &builder, const Vec2i &pos, CUnitType &building)
 {
+	Assert(Map.Info.IsPointOnMap(pos));
+
 	COrder_Build *order = new COrder_Build;
 
 	order->goalPos = pos;
@@ -140,6 +143,11 @@ enum {
 	return true;
 }
 
+/* virtual */ bool COrder_Build::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Build::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	PixelPos targetPos = vp.TilePosToScreen_TopLeft(this->goalPos);
diff --git a/src/action/action_built.cpp b/src/action/action_built.cpp
index 5b0a9ea0f..db8c1b9df 100644
--- a/src/action/action_built.cpp
+++ b/src/action/action_built.cpp
@@ -123,6 +123,11 @@ extern void AiReduceMadeInBuilt(PlayerAi &pai, const CUnitType &type);
 	return true;
 }
 
+/* virtual */ bool COrder_Built::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Built::Show(const CViewport & , const PixelPos &lastScreenPos) const
 {
 	return lastScreenPos;
diff --git a/src/action/action_die.cpp b/src/action/action_die.cpp
index 7311d78f7..c15c5cbfc 100644
--- a/src/action/action_die.cpp
+++ b/src/action/action_die.cpp
@@ -68,6 +68,11 @@
 	return false;
 }
 
+/* virtual */ bool COrder_Die::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Die::Show(const CViewport & , const PixelPos &lastScreenPos) const
 {
 	return lastScreenPos;
diff --git a/src/action/action_follow.cpp b/src/action/action_follow.cpp
index 510c58fb4..8c1b0f6fe 100644
--- a/src/action/action_follow.cpp
+++ b/src/action/action_follow.cpp
@@ -118,6 +118,11 @@ enum {
 	return true;
 }
 
+/* virtual */ bool COrder_Follow::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Follow::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	PixelPos targetPos;
diff --git a/src/action/action_move.cpp b/src/action/action_move.cpp
index 11a09b54f..2d654396f 100644
--- a/src/action/action_move.cpp
+++ b/src/action/action_move.cpp
@@ -97,6 +97,11 @@
 	return true;
 }
 
+/* virtual */ bool COrder_Move::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Move::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	const PixelPos targetPos = vp.TilePosToScreen_Center(this->goalPos);
diff --git a/src/action/action_patrol.cpp b/src/action/action_patrol.cpp
index 3cb139539..6831efe27 100644
--- a/src/action/action_patrol.cpp
+++ b/src/action/action_patrol.cpp
@@ -110,6 +110,11 @@
 	return true;
 }
 
+/* virtual */ bool COrder_Patrol::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Patrol::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	const PixelPos pos1 = vp.TilePosToScreen_Center(this->goalPos);
diff --git a/src/action/action_repair.cpp b/src/action/action_repair.cpp
index 0e0075350..4cd2b177e 100644
--- a/src/action/action_repair.cpp
+++ b/src/action/action_repair.cpp
@@ -129,8 +129,10 @@
 	return true;
 }
 
-
-
+/* virtual */ bool COrder_Repair::IsValid() const
+{
+	return true;
+}
 
 /* virtual */ PixelPos COrder_Repair::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
diff --git a/src/action/action_research.cpp b/src/action/action_research.cpp
index 1b5de7513..c7c0ea8a8 100644
--- a/src/action/action_research.cpp
+++ b/src/action/action_research.cpp
@@ -97,7 +97,10 @@
 	return true;
 }
 
-
+/* virtual */ bool COrder_Research::IsValid() const
+{
+	return true;
+}
 
 /* virtual */ PixelPos COrder_Research::Show(const CViewport & , const PixelPos &lastScreenPos) const
 {
diff --git a/src/action/action_resource.cpp b/src/action/action_resource.cpp
index 0473d1ab6..8e423637e 100644
--- a/src/action/action_resource.cpp
+++ b/src/action/action_resource.cpp
@@ -254,6 +254,11 @@ COrder_Resource::~COrder_Resource()
 	return true;
 }
 
+/* virtual */ bool COrder_Resource::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Resource::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	PixelPos targetPos;
diff --git a/src/action/action_spellcast.cpp b/src/action/action_spellcast.cpp
index 615f7ddaa..25386ce12 100644
--- a/src/action/action_spellcast.cpp
+++ b/src/action/action_spellcast.cpp
@@ -134,6 +134,11 @@
 	return true;
 }
 
+/* virtual */ bool COrder_SpellCast::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_SpellCast::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	PixelPos targetPos;
diff --git a/src/action/action_still.cpp b/src/action/action_still.cpp
index 4312b98ef..e8552270f 100644
--- a/src/action/action_still.cpp
+++ b/src/action/action_still.cpp
@@ -104,6 +104,11 @@ enum {
 	return true;
 }
 
+/* virtual */ bool COrder_Still::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Still::Show(const CViewport & , const PixelPos &lastScreenPos) const
 {
 	if (this->Action == UnitActionStandGround) {
diff --git a/src/action/action_train.cpp b/src/action/action_train.cpp
index 54e64bb47..a6e024d66 100644
--- a/src/action/action_train.cpp
+++ b/src/action/action_train.cpp
@@ -97,6 +97,11 @@
 	return true;
 }
 
+/* virtual */ bool COrder_Train::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Train::Show(const CViewport & , const PixelPos &lastScreenPos) const
 {
 	return lastScreenPos;
diff --git a/src/action/action_unload.cpp b/src/action/action_unload.cpp
index 3532ffa00..2bff5a448 100644
--- a/src/action/action_unload.cpp
+++ b/src/action/action_unload.cpp
@@ -96,6 +96,11 @@
 	return true;
 }
 
+/* virtual */ bool COrder_Unload::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_Unload::Show(const CViewport &vp, const PixelPos &lastScreenPos) const
 {
 	const PixelPos targetPos = vp.TilePosToScreen_Center(this->goalPos);
diff --git a/src/action/action_upgradeto.cpp b/src/action/action_upgradeto.cpp
index 346a8a396..b089eda5c 100644
--- a/src/action/action_upgradeto.cpp
+++ b/src/action/action_upgradeto.cpp
@@ -188,6 +188,12 @@ static int TransformUnitIntoType(CUnit &unit, const CUnitType &newtype)
 	return true;
 }
 
+/* virtual */ bool COrder_TransformInto::IsValid() const
+{
+	return true;
+}
+
+
 /* virtual */ PixelPos COrder_TransformInto::Show(const CViewport & , const PixelPos &lastScreenPos) const
 {
 	return lastScreenPos;
@@ -233,6 +239,11 @@ static int TransformUnitIntoType(CUnit &unit, const CUnitType &newtype)
 	return true;
 }
 
+/* virtual */ bool COrder_UpgradeTo::IsValid() const
+{
+	return true;
+}
+
 /* virtual */ PixelPos COrder_UpgradeTo::Show(const CViewport & , const PixelPos &lastScreenPos) const
 {
 	return lastScreenPos;
diff --git a/src/include/action/action_attack.h b/src/include/action/action_attack.h
index faf4ac82c..91341a71c 100644
--- a/src/include/action/action_attack.h
+++ b/src/include/action/action_attack.h
@@ -48,6 +48,7 @@ public:
 
 	virtual COrder_Attack *Clone() const { return new COrder_Attack(*this); }
 
+	virtual bool IsValid() const;
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_board.h b/src/include/action/action_board.h
index f9ca4f87f..5d527d54d 100644
--- a/src/include/action/action_board.h
+++ b/src/include/action/action_board.h
@@ -45,6 +45,8 @@ public:
 
 	virtual COrder_Board *Clone() const { return new COrder_Board(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_build.h b/src/include/action/action_build.h
index 4234ecd6f..3a148c24a 100644
--- a/src/include/action/action_build.h
+++ b/src/include/action/action_build.h
@@ -45,6 +45,8 @@ public:
 
 	virtual COrder_Build *Clone() const { return new COrder_Build(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_built.h b/src/include/action/action_built.h
index bf5f61568..8fed119d6 100644
--- a/src/include/action/action_built.h
+++ b/src/include/action/action_built.h
@@ -42,6 +42,8 @@ public:
 
 	virtual COrder_Built *Clone() const { return new COrder_Built(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_die.h b/src/include/action/action_die.h
index 22cdc2d58..77934cc4b 100644
--- a/src/include/action/action_die.h
+++ b/src/include/action/action_die.h
@@ -44,6 +44,8 @@ public:
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
+	virtual bool IsValid() const;
+
 	virtual void Execute(CUnit &unit);
 	virtual PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const;
 	virtual void UpdatePathFinderData(PathFinderInput &input) { UpdatePathFinderData_NotCalled(input); }
diff --git a/src/include/action/action_follow.h b/src/include/action/action_follow.h
index 15a48ebaf..7a4c156ca 100644
--- a/src/include/action/action_follow.h
+++ b/src/include/action/action_follow.h
@@ -45,6 +45,8 @@ public:
 
 	virtual COrder_Follow *Clone() const { return new COrder_Follow(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_move.h b/src/include/action/action_move.h
index 3bcd455ca..3476bc56c 100644
--- a/src/include/action/action_move.h
+++ b/src/include/action/action_move.h
@@ -45,6 +45,8 @@ public:
 
 	virtual COrder_Move *Clone() const { return new COrder_Move(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_patrol.h b/src/include/action/action_patrol.h
index 206d60662..9b5a7ce66 100644
--- a/src/include/action/action_patrol.h
+++ b/src/include/action/action_patrol.h
@@ -45,6 +45,8 @@ public:
 
 	virtual COrder_Patrol *Clone() const { return new COrder_Patrol(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_repair.h b/src/include/action/action_repair.h
index 1dd427274..b4769674d 100644
--- a/src/include/action/action_repair.h
+++ b/src/include/action/action_repair.h
@@ -46,6 +46,8 @@ public:
 
 	virtual COrder_Repair *Clone() const { return new COrder_Repair(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_research.h b/src/include/action/action_research.h
index 51b4730d6..4a28b5ff9 100644
--- a/src/include/action/action_research.h
+++ b/src/include/action/action_research.h
@@ -41,6 +41,8 @@ public:
 
 	virtual COrder_Research *Clone() const { return new COrder_Research(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_resource.h b/src/include/action/action_resource.h
index cef36a3c2..929158339 100644
--- a/src/include/action/action_resource.h
+++ b/src/include/action/action_resource.h
@@ -51,6 +51,8 @@ public:
 
 	virtual COrder_Resource *Clone() const { return new COrder_Resource(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_spellcast.h b/src/include/action/action_spellcast.h
index 0ac867c57..228d14371 100644
--- a/src/include/action/action_spellcast.h
+++ b/src/include/action/action_spellcast.h
@@ -45,6 +45,8 @@ public:
 
 	virtual COrder_SpellCast *Clone() const { return new COrder_SpellCast(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_still.h b/src/include/action/action_still.h
index 94d35042b..44c1d7cde 100644
--- a/src/include/action/action_still.h
+++ b/src/include/action/action_still.h
@@ -41,6 +41,8 @@ public:
 
 	virtual COrder_Still *Clone() const { return new COrder_Still(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_train.h b/src/include/action/action_train.h
index a0f1f4f8d..c7544c059 100644
--- a/src/include/action/action_train.h
+++ b/src/include/action/action_train.h
@@ -42,6 +42,8 @@ public:
 
 	virtual COrder_Train *Clone() const { return new COrder_Train(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_unload.h b/src/include/action/action_unload.h
index 5071b7868..102c5221c 100644
--- a/src/include/action/action_unload.h
+++ b/src/include/action/action_unload.h
@@ -45,6 +45,8 @@ public:
 
 	virtual COrder_Unload *Clone() const { return new COrder_Unload(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/action/action_upgradeto.h b/src/include/action/action_upgradeto.h
index 48452a84e..73a42acec 100644
--- a/src/include/action/action_upgradeto.h
+++ b/src/include/action/action_upgradeto.h
@@ -42,6 +42,8 @@ public:
 
 	virtual COrder_TransformInto *Clone() const { return new COrder_TransformInto(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
@@ -62,6 +64,8 @@ public:
 
 	virtual COrder_UpgradeTo *Clone() const { return new COrder_UpgradeTo(*this); }
 
+	virtual bool IsValid() const;
+
 	virtual void Save(CFile &file, const CUnit &unit) const;
 	virtual bool ParseSpecificData(lua_State *l, int &j, const char *value, const CUnit &unit);
 
diff --git a/src/include/actions.h b/src/include/actions.h
index dd13c7fbc..99067e416 100644
--- a/src/include/actions.h
+++ b/src/include/actions.h
@@ -106,6 +106,7 @@ public:
 	virtual COrder *Clone() const = 0;
 	virtual void Execute(CUnit &unit) = 0;
 	virtual void Cancel(CUnit &unit) {}
+	virtual bool IsValid() const = 0;
 
 	virtual PixelPos Show(const CViewport &vp, const PixelPos &lastScreenPos) const = 0;
 
diff --git a/src/unit/unit.cpp b/src/unit/unit.cpp
index 41c320f59..2bdd9cb5a 100644
--- a/src/unit/unit.cpp
+++ b/src/unit/unit.cpp
@@ -369,9 +369,9 @@ bool CUnit::RestoreOrder()
 {
 	COrder *savedOrder = this->SavedOrder;
 
-	if (savedOrder == NULL
-		|| (savedOrder->Action == UnitActionAttack
-			&& (!savedOrder->HasGoal() || savedOrder->GetGoal()->IsAlive()))) {
+	if (savedOrder == NULL || savedOrder->IsValid() == false) {
+		delete this->SavedOrder;
+		this->SavedOrder = NULL;
 		return false;
 	}