Index: binaries/data/mods/public/simulation/helpers/Damage.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Damage.js	(revision 14270)
+++ binaries/data/mods/public/simulation/helpers/Damage.js	(working copy)
@@ -99,14 +99,6 @@
 	// If there is insufficient data return an empty array.
 	if (!origin || !radius)
 		return [];
-	// Create/recycle the dummy entity used for range calculations.
-	if (!Damage.dummyTargetEntity || dummyPath != Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetCurrentTemplateName(Damage.dummyTargetEntity))
-		Damage.dummyTargetEntity = Engine.AddEntity(dummyPath);
-	// Move the dummy entity to the origin of the query.
-	var cmpDummyPosition = Engine.QueryInterface(Damage.dummyTargetEntity, IID_Position);
-	if (!cmpDummyPosition)
-		return [];
-	cmpDummyPosition.JumpTo(origin.x, origin.z);
 
 	// If the players parameter is not specified use all players.
 	if (!players)
@@ -119,7 +111,7 @@
 
 	// Call RangeManager with dummy entity and return the result.
 	var rangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
-	var rangeQuery = rangeManager.ExecuteQuery(Damage.dummyTargetEntity, 0, radius, players, IID_DamageReceiver);
+	var rangeQuery = rangeManager.ExecuteQueryAroundPos({"x": origin.x, "y": origin.z}, 0, radius, players, IID_DamageReceiver);
 	return rangeQuery;
 };
 
Index: source/simulation2/components/CCmpRangeManager.cpp
===================================================================
--- source/simulation2/components/CCmpRangeManager.cpp	(revision 14268)
+++ source/simulation2/components/CCmpRangeManager.cpp	(working copy)
@@ -33,7 +33,6 @@
 #include "graphics/Overlay.h"
 #include "graphics/Terrain.h"
 #include "lib/timer.h"
-#include "maths/FixedVector2D.h"
 #include "ps/CLogger.h"
 #include "ps/Overlay.h"
 #include "ps/Profile.h"
@@ -729,6 +728,20 @@
 		q.enabled = false;
 	}
 
+	virtual std::vector<entity_id_t> ExecuteQueryAroundPos(CFixedVector2D pos,
+		entity_pos_t minRange, entity_pos_t maxRange,
+		std::vector<int> owners, int requiredInterface)
+	{
+		Query q = ConstructQuery(INVALID_ENTITY, minRange, maxRange, owners, requiredInterface, GetEntityFlagMask("normal"));
+		std::vector<entity_id_t> r;
+		PerformQuery(q, r, pos);
+
+		// Return the list sorted by distance from the entity
+		std::stable_sort(r.begin(), r.end(), EntityDistanceOrdering(m_EntityData, pos));
+
+		return r;
+	}
+
 	virtual std::vector<entity_id_t> ExecuteQuery(entity_id_t source,
 		entity_pos_t minRange, entity_pos_t maxRange,
 		std::vector<int> owners, int requiredInterface)
@@ -746,10 +759,10 @@
 			return r;
 		}
 
-		PerformQuery(q, r);
+		CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
+		PerformQuery(q, r, pos);
 
 		// Return the list sorted by distance from the entity
-		CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
 		std::stable_sort(r.begin(), r.end(), EntityDistanceOrdering(m_EntityData, pos));
 
 		return r;
@@ -779,12 +792,12 @@
 			return r;
 		}
 
-		PerformQuery(q, r);
+		CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
+		PerformQuery(q, r, pos);
 
 		q.lastMatch = r;
 
 		// Return the list sorted by distance from the entity
-		CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
 		std::stable_sort(r.begin(), r.end(), EntityDistanceOrdering(m_EntityData, pos));
 
 		return r;
@@ -841,7 +854,8 @@
 
 			results.clear();
 			results.reserve(query.lastMatch.size());
-			PerformQuery(query, results);
+			CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
+			PerformQuery(query, results, pos);
 
 			// Compute the changes vs the last match
 			added.clear();
@@ -902,12 +916,8 @@
 	/**
 	 * Returns a list of distinct entity IDs that match the given query, sorted by ID.
 	 */
-	void PerformQuery(const Query& q, std::vector<entity_id_t>& r)
+	void PerformQuery(const Query& q, std::vector<entity_id_t>& r, CFixedVector2D pos)
 	{
-		CmpPtr<ICmpPosition> cmpSourcePosition(q.source);
-		if (!cmpSourcePosition || !cmpSourcePosition->IsInWorld())
-			return;
-		CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
 
 		// Special case: range -1.0 means check all entities ignoring distance
 		if (q.maxRange == entity_pos_t::FromInt(-1))
@@ -924,6 +934,7 @@
 		else if (q.parabolic) 
 		{
 			// elevationBonus is part of the 3D position, as the source is really that much heigher
+			CmpPtr<ICmpPosition> cmpSourcePosition(q.source);
 			CFixedVector3D pos3d = cmpSourcePosition->GetPosition()+
 			    CFixedVector3D(entity_pos_t::Zero(), q.elevationBonus, entity_pos_t::Zero()) ;
 			// Get a quick list of entities that are potentially in range, with a cutoff of 2*maxRange
@@ -992,7 +1003,6 @@
 		}
 	}
 
-
 	virtual entity_pos_t GetElevationAdaptedRange(CFixedVector3D pos, CFixedVector3D rot, entity_pos_t range, entity_pos_t elevationBonus, entity_pos_t angle)
 	{
 		entity_pos_t r = entity_pos_t::Zero() ;
Index: source/simulation2/components/ICmpRangeManager.cpp
===================================================================
--- source/simulation2/components/ICmpRangeManager.cpp	(revision 14268)
+++ source/simulation2/components/ICmpRangeManager.cpp	(working copy)
@@ -35,6 +35,7 @@
 
 BEGIN_INTERFACE_WRAPPER(RangeManager)
 DEFINE_INTERFACE_METHOD_5("ExecuteQuery", std::vector<entity_id_t>, ICmpRangeManager, ExecuteQuery, entity_id_t, entity_pos_t, entity_pos_t, std::vector<int>, int)
+DEFINE_INTERFACE_METHOD_5("ExecuteQueryAroundPos", std::vector<entity_id_t>, ICmpRangeManager, ExecuteQueryAroundPos, CFixedVector2D, entity_pos_t, entity_pos_t, std::vector<int>, int)
 DEFINE_INTERFACE_METHOD_6("CreateActiveQuery", ICmpRangeManager::tag_t, ICmpRangeManager, CreateActiveQuery, entity_id_t, entity_pos_t, entity_pos_t, std::vector<int>, int, u8)
 DEFINE_INTERFACE_METHOD_7("CreateActiveParabolicQuery", ICmpRangeManager::tag_t, ICmpRangeManager, CreateActiveParabolicQuery, entity_id_t, entity_pos_t, entity_pos_t, entity_pos_t, std::vector<int>, int, u8)
 DEFINE_INTERFACE_METHOD_1("DestroyActiveQuery", void, ICmpRangeManager, DestroyActiveQuery, ICmpRangeManager::tag_t)
Index: source/simulation2/components/ICmpRangeManager.h
===================================================================
--- source/simulation2/components/ICmpRangeManager.h	(revision 14268)
+++ source/simulation2/components/ICmpRangeManager.h	(working copy)
@@ -19,6 +19,7 @@
 #define INCLUDED_ICMPRANGEMANAGER
 
 #include "maths/FixedVector3D.h"
+#include "maths/FixedVector2D.h"
 
 #include "simulation2/system/Interface.h"
 #include "simulation2/helpers/Position.h"
@@ -92,6 +93,18 @@
 		entity_pos_t minRange, entity_pos_t maxRange, std::vector<int> owners, int requiredInterface) = 0;
 
 	/**
+	 * Execute a passive query.
+	 * @param pos the position around which the range will be computed.
+	 * @param minRange non-negative minimum distance in metres (inclusive).
+	 * @param maxRange non-negative maximum distance in metres (inclusive); or -1.0 to ignore distance.
+	 * @param owners list of player IDs that matching entities may have; -1 matches entities with no owner.
+	 * @param requiredInterface if non-zero, an interface ID that matching entities must implement.
+	 * @return list of entities matching the query, ordered by increasing distance from the source entity.
+	 */
+	virtual std::vector<entity_id_t> ExecuteQueryAroundPos(CFixedVector2D pos,
+		entity_pos_t minRange, entity_pos_t maxRange, std::vector<int> owners, int requiredInterface) = 0;
+
+	/**
 	 * Construct an active query. The query will be disabled by default.
 	 * @param source the entity around which the range will be computed.
 	 * @param minRange non-negative minimum distance in metres (inclusive).
