From 180de1f00d8f2330ae959ab654ded52ddf0af1ef Mon Sep 17 00:00:00 2001
From: Tim Felgentreff <timfelgentreff@gmail.com>
Date: Wed, 5 Jun 2013 11:38:12 +0200
Subject: [PATCH] allow distance rules to specify owner of units

---
 src/include/unittype.h       |  1 +
 src/unit/build.cpp           | 56 +++++++++++++++++++-----------------
 src/unit/script_unittype.cpp |  2 ++
 3 files changed, 32 insertions(+), 27 deletions(-)

diff --git a/src/include/unittype.h b/src/include/unittype.h
index 50e4a879d..e466a083d 100644
--- a/src/include/unittype.h
+++ b/src/include/unittype.h
@@ -408,6 +408,7 @@ public:
 	int Distance;        /// distance to build (circle)
 	DistanceTypeType DistanceType;
 	std::string RestrictTypeName;
+	std::string RestrictTypeOwner;
 	CUnitType *RestrictType;
 };
 
diff --git a/src/unit/build.cpp b/src/unit/build.cpp
index c9102c482..9b15b6bbe 100644
--- a/src/unit/build.cpp
+++ b/src/unit/build.cpp
@@ -134,43 +134,45 @@ bool CBuildRestrictionDistance::Check(const CUnit *builder, const CUnitType &typ
 	std::vector<CUnit *> table;
 	Select(pos1, pos2, table);
 
-	switch (this->DistanceType) {
-		case GreaterThan :
-		case GreaterThanEqual :
-			for (size_t i = 0; i != table.size(); ++i) {
-				if (builder != table[i] && this->RestrictType == table[i]->Type &&
-					MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) <= distance) {
+	for (size_t i = 0; i != table.size(); ++i) {
+		if (builder != table[i] &&
+		    // unit has RestrictType or no RestrictType was set, but a RestrictTypeOwner
+		    (this->RestrictType == table[i]->Type || !this->RestrictType && this->RestrictTypeOwner.size() > 0) &&
+		    // RestrictTypeOwner is not set or unit belongs to a suitable player
+		    (this->RestrictTypeOwner.size() == 0 ||
+		     !this->RestrictTypeOwner.compare("self") && ThisPlayer == table[i]->Player ||
+		     !this->RestrictTypeOwner.compare("allied") && (ThisPlayer == table[i]->Player || ThisPlayer->IsAllied(*table[i]->Player)) ||
+		     !this->RestrictTypeOwner.compare("enemy") && ThisPlayer->IsEnemy(*table[i]->Player))) {
+
+			switch (this->DistanceType) {
+			case GreaterThan :
+			case GreaterThanEqual :
+				if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) <= distance) {
 					return false;
 				}
-			}
-			return true;
-		case LessThan :
-		case LessThanEqual :
-			for (size_t i = 0; i != table.size(); ++i) {
-				if (builder != table[i] && this->RestrictType == table[i]->Type &&
-					MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) <= distance) {
+				break;
+		        case LessThan :
+		        case LessThanEqual :
+				if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) <= distance) {
 					return true;
 				}
-			}
-			return false;
-		case Equal :
-			for (size_t i = 0; i != table.size(); ++i) {
-				if (builder != table[i] && this->RestrictType == table[i]->Type &&
-					MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) == distance) {
+				break;
+			case Equal :
+				if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) == distance) {
 					return true;
 				}
-			}
-			return false;
-		case NotEqual :
-			for (size_t i = 0; i != table.size(); ++i) {
-				if (builder != table[i] && this->RestrictType == table[i]->Type &&
-					MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) == distance) {
+				break;
+			case NotEqual :
+				if (MapDistanceBetweenTypes(type, pos, *table[i]->Type, table[i]->tilePos) == distance) {
 					return false;
 				}
+				break;
 			}
-			return true;
+		}
 	}
-	return false;
+	return (this->DistanceType == GreaterThan ||
+		this->DistanceType == GreaterThanEqual ||
+		this->DistanceType == NotEqual);
 }
 
 inline bool CBuildRestrictionAddOn::functor::operator()(const CUnit *const unit) const
diff --git a/src/unit/script_unittype.cpp b/src/unit/script_unittype.cpp
index 9d0e87da7..698143c4d 100644
--- a/src/unit/script_unittype.cpp
+++ b/src/unit/script_unittype.cpp
@@ -254,6 +254,8 @@ static void ParseBuildingRules(lua_State *l, std::vector<CBuildRestriction *> &b
 					}
 				} else if (!strcmp(value, "Type")) {
 					b->RestrictTypeName = LuaToString(l, -1);
+				} else if (!strcmp(value, "Owner")) {
+					b->RestrictTypeOwner = LuaToString(l, -1);
 				} else {
 					LuaError(l, "Unsupported BuildingRules distance tag: %s" _C_ value);
 				}