Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_tower.xml	(revision 13562)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_tower.xml	(working copy)
@@ -33,6 +33,7 @@
   <Footprint replace="">
     <Square width="15.0" depth="15.0"/>
     <Height>20.0</Height>
+	<SpawnPoint x='0' z='15'/>
   </Footprint>
   <GarrisonHolder>
     <Max>20</Max>
Index: binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_tower.xml	(revision 13562)
+++ binaries/data/mods/public/simulation/templates/units/hele_mechanical_siege_tower.xml	(working copy)
@@ -4,7 +4,7 @@
     <Civ>hele</Civ>
     <SpecificName>Helépolis</SpecificName>
     <Tooltip>Siege Tower.
-Garrison up to 20 units inside for massive firepower.</Tooltip>
+Garrison up to 20 units inside for massive firepower. Stand in front of a wall and ungarrison your units over the wall.</Tooltip>
     <History>When Demetrius Poliorcetes besieged Salamis, in Cyprus, he instructed that a machine be constructed, which he called "the taker of cities." Its form was that of a square tower, each side 90 cubits high and 45 wide. It rested on four wheels, each eight cubits high. It was divided into nine stories, the lower of which contained machines for throwing great stones, the middle large catapults for throwing spears, and the highest, other machines for throwing smaller stones, together with smaller catapults. It was manned with 200 soldiers, besides those that moved it by pushing the parallel beams at the bottom.</History>
     <Icon>units/hele_mechanical_siege_tower.png</Icon>
   </Identity>
Index: binaries/data/mods/public/simulation/templates/units/mace_mechanical_siege_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/units/mace_mechanical_siege_tower.xml	(revision 13562)
+++ binaries/data/mods/public/simulation/templates/units/mace_mechanical_siege_tower.xml	(working copy)
@@ -4,7 +4,7 @@
     <Civ>mace</Civ>
     <SpecificName>Helépolis</SpecificName>
     <Tooltip>Siege Tower.
-Garrison up to 20 units inside for massive firepower.</Tooltip>
+Garrison up to 20 units inside for massive firepower. Stand in front of a wall, and ungarrison your units over the wall.</Tooltip>
     <History>When Demetrius Poliorcetes besieged Salamis, in Cyprus, he instructed that a machine be constructed, which he called "the taker of cities." Its form was that of a square tower, each side 90 cubits high and 45 wide. It rested on four wheels, each eight cubits high. It was divided into nine stories, the lower of which contained machines for throwing great stones, the middle large catapults for throwing spears, and the highest, other machines for throwing smaller stones, together with smaller catapults. It was manned with 200 soldiers, besides those that moved it by pushing the parallel beams at the bottom.</History>
     <Icon>units/hele_mechanical_siege_tower.png</Icon>
   </Identity>
Index: source/simulation2/components/CCmpFootprint.cpp
===================================================================
--- source/simulation2/components/CCmpFootprint.cpp	(revision 13562)
+++ source/simulation2/components/CCmpFootprint.cpp	(working copy)
@@ -43,6 +43,10 @@
 	entity_pos_t m_Size1; // height/radius
 	entity_pos_t m_Height;
 
+	CFixedVector2D m_SpawnPoint;
+
+	bool m_SpawnPointSet;
+
 	static std::string GetSchema()
 	{
 		return
@@ -73,7 +77,17 @@
 			"</choice>"
 			"<element name='Height' a:help='Vertical extent of the footprint (in metres)'>"
 				"<ref name='nonNegativeDecimal'/>"
-			"</element>";
+			"</element>"
+			"<optional>"
+				"<element name='SpawnPoint' a:help='let units spawn to an explicit spawn position (relative to this entity)'>"
+					"<attribute name='x'>"
+						"<data type='decimal'/>"
+					"</attribute>"
+					"<attribute name='z'>"
+						"<data type='decimal'/>"
+					"</attribute>"
+				"</element>"
+			"</optional>";
 	}
 
 	virtual void Init(const CParamNode& paramNode)
@@ -97,6 +111,18 @@
 		}
 
 		m_Height = paramNode.GetChild("Height").ToFixed();
+
+		if (paramNode.GetChild("SpawnPoint").IsOk())
+		{
+			entity_pos_t startX = paramNode.GetChild("SpawnPoint").GetChild("@x").ToFixed();
+			entity_pos_t startZ = paramNode.GetChild("SpawnPoint").GetChild("@z").ToFixed();
+			m_SpawnPoint = CFixedVector2D(startX, startZ);
+			m_SpawnPointSet = true;
+		}
+		else
+		{
+			m_SpawnPointSet = false;
+		}
 	}
 
 	virtual void Deinit()
@@ -165,6 +191,64 @@
 		// Max spawning distance in tiles
 		const i32 maxSpawningDistance = 4;
 
+		if (m_SpawnPointSet)
+		{
+			fixed s, c;
+			sincos_approx(initialAngle, s, c);
+
+			CFixedVector2D v = m_SpawnPoint;
+			v = v.Rotate(initialAngle);
+			initialPos = initialPos + v;
+
+			// try initial position as a start
+			SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity
+			if (cmpPathfinder->CheckUnitPlacement(filter, initialPos.X, initialPos.Y, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
+				return CFixedVector3D(initialPos.X, fixed::Zero(), initialPos.Y); // this position is okay, so return it
+
+			// Expand outwards from initial position
+			for (i32 dist = 0; dist <= maxSpawningDistance; ++dist)
+			{
+				// The spawn point should be far enough from this footprint to fit the unit, plus a little gap
+				entity_pos_t clearance = spawnedRadius + entity_pos_t::FromInt(2 + (int)TERRAIN_TILE_SIZE*dist);
+
+				for (i32 edge = 0; edge < 4; ++edge)
+				{
+					// Try equally-spaced points along the edge in alternating directions, starting from the middle
+					const i32 numPoints = 9 + 2*dist;
+
+					// Compute the direction and length of the current edge
+					CFixedVector2D dir;
+					switch (edge)
+					{
+					case 0:
+						dir = CFixedVector2D(c, -s);
+						break;
+					case 1:
+						dir = CFixedVector2D(-s, -c);
+						break;
+					case 2:
+						dir = CFixedVector2D(s, c);
+						break;
+					case 3:
+						dir = CFixedVector2D(-c, s);
+						break;
+					}
+					CFixedVector2D center = initialPos - dir.Perpendicular().Multiply(clearance);
+					dir = dir.Multiply((clearance*2) / (int)(numPoints-1));
+
+					for (i32 i = 0; i < (numPoints+1)/2; i = (i > 0 ? -i : 1-i)) // [0, +1, -1, +2, -2, ... (np-1)/2, -(np-1)/2]
+					{
+						CFixedVector2D pos (center + dir*i);
+
+						SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity
+						if (cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
+							return CFixedVector3D(pos.X, fixed::Zero(), pos.Y); // this position is okay, so return it
+					}
+				}
+			}
+		}
+		
+		// try spawning around footprint
 		if (m_Shape == CIRCLE)
 		{
 			// Expand outwards from foundation
