From a436edf6c429477eaf6915a42af5c23601c601b5 Mon Sep 17 00:00:00 2001
From: cybermind <iddqd_mail@mail.ru>
Date: Fri, 24 Feb 2012 14:49:06 +0600
Subject: [PATCH] [*]Don't include neutral units in attack calculations for
 faster computing. [-]Fixed bug with incorrect splash radius [-]Fixed
 CorrectSphashDamage behaviour with Ground Attack

---
 src/include/map.h         |  4 ++--
 src/stratagus/missile.cpp | 12 ++++++++----
 src/unit/unit_cache.cpp   | 14 +++++++++-----
 src/unit/unit_find.cpp    |  4 ++--
 4 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/src/include/map.h b/src/include/map.h
index 476fd4499..07bcd7808 100644
--- a/src/include/map.h
+++ b/src/include/map.h
@@ -427,9 +427,9 @@ public:
 
 	/// Select units in rectange range
 	int Select(int x1, int y1, int x2, int y2, CUnit *table[],
-		 const int tablesize = UnitMax);
+		 const int tablesize = UnitMax, int neutral = 0);
 	int SelectFixed(const Vec2i &ltpos, const Vec2i &rbpos, CUnit*table[],
-		 const int tablesize = UnitMax);
+		 const int tablesize = UnitMax, int neutral = 0);
 
 
 	// Select units on map tile. - helper funtion. don't use directly
diff --git a/src/stratagus/missile.cpp b/src/stratagus/missile.cpp
index 2b9c51a5f..5d278988c 100644
--- a/src/stratagus/missile.cpp
+++ b/src/stratagus/missile.cpp
@@ -945,7 +945,7 @@ static void MissileHit(Missile &missile)
 		//
 		const int range = mtype.Range;
 		CUnit *table[UnitMax];
-		const int n = Map.Select(pos.x - range + 1, pos.y - range + 1, pos.x + range, pos.y + range, table);
+		const int n = Map.Select(pos.x - range + 1, pos.y - range + 1, pos.x + range - 1, pos.y + range - 1, table);
 		Assert(missile.SourceUnit != NULL);
 		for (int i = 0; i < n; ++i) {
 			CUnit &goal = *table[i];
@@ -955,10 +955,14 @@ static void MissileHit(Missile &missile)
 			// Also check CorrectSphashDamage so land explosions can't hit the air units
 			//
 			if (CanTarget(missile.SourceUnit->Type, goal.Type)
-				&& (mtype.CorrectSphashDamage == false
-					|| goal.Type->UnitType == missile.TargetUnit->Type->UnitType)
+				&& ((missile.SourceUnit->CurrentOrder()->Action != UnitActionAttackGround &&
+						(mtype.CorrectSphashDamage == false 
+						|| goal.Type->UnitType == missile.TargetUnit->Type->UnitType))
+					|| (missile.SourceUnit->CurrentOrder()->Action == UnitActionAttackGround &&
+						(mtype.CorrectSphashDamage == false 
+						|| goal.Type->UnitType == missile.SourceUnit->Type->UnitType)))
 				&& (mtype.FriendlyFire == false
-					|| (missile.TargetUnit->Player->Index != missile.SourceUnit->Player->Index))) {
+					|| (goal.Player->Index != missile.SourceUnit->Player->Index))) {
 				int splash = goal.MapDistanceTo(pos.x, pos.y);
 
 				if (splash) {
diff --git a/src/unit/unit_cache.cpp b/src/unit/unit_cache.cpp
index 8d54b8e86..f39cc994a 100644
--- a/src/unit/unit_cache.cpp
+++ b/src/unit/unit_cache.cpp
@@ -121,10 +121,12 @@ int CMap::Select(const Vec2i &pos, CUnit *table[], const int tablesize)
 **  @param rbpos      Right Bottom position of selection rectangle
 **  @param table      All units in the selection rectangle
 **  @param tablesize  Size of table array
+**  @param neutral	  Don't include neutral units for faster computing
 **
 **  @return           Returns the number of units found
 */
-int CMap::SelectFixed(const Vec2i &ltpos, const Vec2i &rbpos, CUnit *table[], const int tablesize)
+int CMap::SelectFixed(const Vec2i &ltpos, const Vec2i &rbpos, CUnit *table[], const int tablesize,
+						int neutral)
 {
 	Assert(Info.IsPointOnMap(ltpos));
 	Assert(Info.IsPointOnMap(rbpos));
@@ -155,7 +157,8 @@ int CMap::SelectFixed(const Vec2i &ltpos, const Vec2i &rbpos, CUnit *table[], co
 					// It should only be used in here, unless you somehow want the unit
 					// to be out of cache.
 					//
-					if (!unit->CacheLock && !unit->Type->Revealer) {
+					if (!unit->CacheLock && !unit->Type->Revealer && 
+						(!neutral || neutral && unit->Player->Index != PlayerNumNeutral)) {
 						Assert(!unit->Removed);
 						unit->CacheLock = 1;
 						table[n++] = unit;
@@ -175,7 +178,8 @@ int CMap::SelectFixed(const Vec2i &ltpos, const Vec2i &rbpos, CUnit *table[], co
 					// It should only be used in here, unless you somehow want the unit
 					// to be out of cache.
 					//
-					if (!unit->CacheLock && !unit->Type->Revealer) {
+					if (!unit->CacheLock && !unit->Type->Revealer && 
+						(!neutral || unit->Player->Index != PlayerNumNeutral)) {
 						Assert(!unit->Removed);
 						unit->CacheLock = 1;
 						table[n++] = unit;
@@ -214,12 +218,12 @@ int CMap::SelectFixed(const Vec2i &ltpos, const Vec2i &rbpos, CUnit *table[], co
 }
 
 int CMap::Select(int x1, int y1,
-		int x2, int y2, CUnit *table[], const int tablesize)
+		int x2, int y2, CUnit *table[], const int tablesize, int neutral)
 {
 	//  Reduce to map limits.
 	Vec2i ltpos = {std::max<int>(x1, 0), std::max<int>(y1, 0)};
 	Vec2i rbpos = {std::min<int>(x2, Info.MapWidth - 1), std::min<int>(y2, Info.MapHeight - 1)};
 
-	return SelectFixed(ltpos, rbpos, table, tablesize);
+	return SelectFixed(ltpos, rbpos, table, tablesize, neutral);
 }
 
diff --git a/src/unit/unit_find.cpp b/src/unit/unit_find.cpp
index 9e2eaf16d..1f29ee249 100644
--- a/src/unit/unit_find.cpp
+++ b/src/unit/unit_find.cpp
@@ -659,13 +659,13 @@ CUnit *AttackUnitsInDistance(const CUnit &unit, int range)
 			int y = unit.Container->tilePos.y;
 			n = Map.Select(x - missile_range, y - missile_range,
 				x + missile_range + unit.Container->Type->TileWidth,
-				y + missile_range + unit.Container->Type->TileHeight, table);
+				y + missile_range + unit.Container->Type->TileHeight, table, UnitMax, 1);
 		} else {
 			int x = unit.tilePos.x;
 			int y = unit.tilePos.y;
 			n = Map.Select(x - missile_range, y - missile_range,
 				x + missile_range + unit.Type->TileWidth,
-				y + missile_range + unit.Type->TileHeight, table);
+				y + missile_range + unit.Type->TileHeight, table, UnitMax, 1);
 		}
 
 		if (n) {