Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js	(révision 14490)
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js	(copie de travail)
@@ -13,8 +13,11 @@
 	"<element name='EjectHealth' a:help='Percentage of maximum health below which this holder no longer allows garrisoning'>" +
 		"<ref name='nonNegativeDecimal'/>" +
 	"</element>" +
-	"<element name='EjectEntitiesOnDestroy' a:help='Whether the entity should eject or kill all garrisoned entities on destroy'>" +
-		"<data type='boolean'/>" +
+	"<element name='EjectClassesOnDestroy' a:help='Classes of entities to be ejected on destroy. Others are killed'>" +
+		"<attribute name='datatype'>" +
+			"<value>tokens</value>" +
+		"</attribute>" +
+		"<text/>" +
 	"</element>" +
 	"<element name='BuffHeal' a:help='Number of hit points that will be restored to this holder&apos;s garrisoned units each second'>" +
 		"<ref name='nonNegativeDecimal'/>" +
@@ -105,11 +108,6 @@
 	return ApplyValueModificationsToEntity("GarrisonHolder/BuffHeal", +this.template.BuffHeal, this.entity);
 };
 
-GarrisonHolder.prototype.EjectEntitiesOnDestroy = function()
-{
-	return this.template.EjectEntitiesOnDestroy == "true";
-};
-
 /**
  * Set this entity to allow or disallow garrisoning in
  * Every component calling this function should do it with its own ID, and as long as one
@@ -270,7 +268,15 @@
 	
 	// Find spawning location
 	var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint);
-	var pos = cmpFootprint.PickSpawnPoint(entity);
+	var cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
+	var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
+	// If the garrisonHolder is a sinking ship, restrict the location to the intersection of both passabilities
+	// TODO: should use passability classes to be more generic
+	if ((!cmpHealth || cmpHealth.GetHitpoints() == 0) && cmpIdentity && cmpIdentity.HasClass("Ship"))
+		var pos = cmpFootprint.PickSpawnPointBothPass(entity);
+	else
+		var pos = cmpFootprint.PickSpawnPoint(entity);
+
 	if (pos.y < 0)
 	{
 		// Error: couldn't find space satisfying the unit's passability criteria
@@ -602,8 +608,13 @@
 	var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
 	// Eject the units which can be ejected (if not in world, it generally means this holder
 	// is inside a holder which kills its entities, so do not eject)
-	if (cmpPosition.IsInWorld() && this.EjectEntitiesOnDestroy())
-		this.PerformEject(entities, true);
+	if (cmpPosition.IsInWorld())
+	{
+		var cmpGarrisonHolder = this;
+		var ejectables = entities.filter(function(ent) { return cmpGarrisonHolder.IsEjectable(ent) });
+		if (ejectables.length)
+			this.PerformEject(ejectables, false);
+	}
 
 	// And destroy all remaining entities
 	for each (var entity in entities)
@@ -621,5 +632,20 @@
 	this.UpdateGarrisonFlag();
 };
 
+/**
+ * Checks if an entity is ejectable on destroy if possible
+ */
+GarrisonHolder.prototype.IsEjectable = function(entity)
+{
+	var ejectableClasses = this.template.EjectClassesOnDestroy._string;
+	ejectableClasses = ejectableClasses ? ejectableClasses.split(/\s+/) : [];
+	var entityClasses = (Engine.QueryInterface(entity, IID_Identity)).GetClassesList();
+	for each (var ejectableClass in ejectableClasses)
+		if (entityClasses.indexOf(ejectableClass) != -1)
+			return true;
+
+	return false;
+};
+
 Engine.RegisterComponentType(IID_GarrisonHolder, "GarrisonHolder", GarrisonHolder);
 
Index: binaries/data/mods/public/simulation/templates/other/plane.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/plane.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/other/plane.xml	(copie de travail)
@@ -24,7 +24,7 @@
     <List datatype="tokens">Support Infantry</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>5</LoadingRange>
-    <EjectEntitiesOnDestroy>false</EjectEntitiesOnDestroy> 
+    <EjectClassesOnDestroy datatype="tokens" /> 
   </GarrisonHolder>
   <Decay>
     <Inactive/>
Index: binaries/data/mods/public/simulation/templates/structures/athen_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/athen_wonder.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/structures/athen_wonder.xml	(copie de travail)
@@ -7,7 +7,7 @@
   <GarrisonHolder>
     <Max>30</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>3</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/structures/cart_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_wonder.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/structures/cart_wonder.xml	(copie de travail)
@@ -7,7 +7,7 @@
   <GarrisonHolder>
     <Max>30</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>3</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/structures/hele_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/hele_wonder.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/structures/hele_wonder.xml	(copie de travail)
@@ -7,7 +7,7 @@
   <GarrisonHolder>
     <Max>30</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>3</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/structures/mace_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/mace_wonder.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/structures/mace_wonder.xml	(copie de travail)
@@ -7,7 +7,7 @@
   <GarrisonHolder>
     <Max>30</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>3</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/structures/ptol_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/ptol_wonder.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/structures/ptol_wonder.xml	(copie de travail)
@@ -7,7 +7,7 @@
   <GarrisonHolder>
     <Max>30</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>3</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/structures/rome_tent.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_tent.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/structures/rome_tent.xml	(copie de travail)
@@ -16,7 +16,7 @@
   <GarrisonHolder>
     <Max>5</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry</List>
     <BuffHeal>0</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/structures/rome_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_wonder.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/structures/rome_wonder.xml	(copie de travail)
@@ -7,7 +7,7 @@
   <GarrisonHolder>
     <Max>30</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>3</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/structures/spart_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/spart_wonder.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/structures/spart_wonder.xml	(copie de travail)
@@ -7,7 +7,7 @@
   <GarrisonHolder>
     <Max>30</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>3</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml	(copie de travail)
@@ -49,7 +49,7 @@
   <GarrisonHolder>
     <Max>20</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>1</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml	(copie de travail)
@@ -18,7 +18,7 @@
     <Max>3</Max>
     <BuffHeal>0</BuffHeal>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support</List>
     <LoadingRange>1</LoadingRange>
   </GarrisonHolder>
Index: binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml	(copie de travail)
@@ -23,7 +23,7 @@
   <GarrisonHolder>
     <Max>20</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>3</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_defense_defense_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_defense_defense_tower.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_defense_defense_tower.xml	(copie de travail)
@@ -46,7 +46,7 @@
   <GarrisonHolder>
     <Max>5</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry</List>
     <BuffHeal>0</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml	(copie de travail)
@@ -44,7 +44,7 @@
   <GarrisonHolder>
     <Max>1</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry</List>
     <BuffHeal>0</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_defense_wall_tower.xml	(copie de travail)
@@ -41,7 +41,7 @@
   <GarrisonHolder>
     <Max>5</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry</List>
     <BuffHeal>0</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml	(copie de travail)
@@ -16,7 +16,7 @@
   <GarrisonHolder>
     <Max>10</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Infantry Cavalry</List>
     <BuffHeal>0</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_military_blacksmith.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_military_blacksmith.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_military_blacksmith.xml	(copie de travail)
@@ -16,7 +16,7 @@
   <GarrisonHolder>
     <Max>1</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Infantry</List>
     <BuffHeal>0</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml	(copie de travail)
@@ -46,7 +46,7 @@
   <GarrisonHolder>
     <Max>20</Max>
     <EjectHealth>0.075</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry Siege</List>
     <BuffHeal>0</BuffHeal>
     <LoadingRange>6</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml	(copie de travail)
@@ -13,7 +13,7 @@
   <GarrisonHolder>
     <Max>10</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Animal</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_structure_special.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_special.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_structure_special.xml	(copie de travail)
@@ -29,7 +29,7 @@
   <GarrisonHolder>
     <Max>5</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml	(copie de travail)
@@ -33,7 +33,7 @@
   <GarrisonHolder>
     <Max>20</Max>
     <EjectHealth>0</EjectHealth>
-    <EjectEntitiesOnDestroy>false</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>10</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml	(copie de travail)
@@ -22,7 +22,7 @@
   <GarrisonHolder>
     <Max>1</Max>
     <EjectHealth>0</EjectHealth>
-    <EjectEntitiesOnDestroy>false</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>10</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml	(copie de travail)
@@ -14,7 +14,7 @@
   <GarrisonHolder>
     <Max>15</Max>
     <EjectHealth>0</EjectHealth>
-    <EjectEntitiesOnDestroy>false</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>10</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml	(copie de travail)
@@ -41,7 +41,7 @@
   <GarrisonHolder>
     <Max>50</Max>
     <EjectHealth>0</EjectHealth>
-    <EjectEntitiesOnDestroy>false</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry Siege</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>10</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml	(copie de travail)
@@ -33,7 +33,7 @@
   <GarrisonHolder>
     <Max>30</Max>
     <EjectHealth>0</EjectHealth>
-    <EjectEntitiesOnDestroy>false</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Female Infantry</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry Cavalry Siege</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>10</LoadingRange>
Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ram.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ram.xml	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_ram.xml	(copie de travail)
@@ -48,7 +48,7 @@
   <GarrisonHolder>
     <Max>5</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry</List>
     <BuffHeal>1</BuffHeal>
     <LoadingRange>2</LoadingRange>
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	(révision 14490)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_tower.xml	(copie de travail)
@@ -46,7 +46,7 @@
   <GarrisonHolder>
     <Max>20</Max>
     <EjectHealth>0.1</EjectHealth>
-    <EjectEntitiesOnDestroy>true</EjectEntitiesOnDestroy>
+    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     <List datatype="tokens">Support Infantry</List>
     <BuffHeal>0</BuffHeal>
     <LoadingRange>2</LoadingRange>
Index: source/simulation2/components/CCmpFootprint.cpp
===================================================================
--- source/simulation2/components/CCmpFootprint.cpp	(révision 14490)
+++ source/simulation2/components/CCmpFootprint.cpp	(copie de travail)
@@ -158,7 +158,7 @@
 		CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
 		if (!cmpPathfinder)
 			return error;
-		
+
 		CFixedVector2D initialPos = cmpPosition->GetPosition2D();
 		entity_angle_t initialAngle = cmpPosition->GetRotation().Y;
 
@@ -250,6 +250,144 @@
 
 		return error;
 	}
+
+	virtual CFixedVector3D PickSpawnPointBothPass(entity_id_t spawned)
+	{
+		// Try to find a free space inside and around this footprint
+		// at the intersection between the footprint passability and the unit passability.
+		// (useful for example for destroyed ships where the spawning point should be in the intersection
+		// of the unit and ship passabilities).
+		// As the overlap between these passabilities regions may be narrow, we need a small step (1 meter)
+
+		const CFixedVector3D error(fixed::FromInt(-1), fixed::FromInt(-1), fixed::FromInt(-1));
+
+		CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
+		if (!cmpPosition || !cmpPosition->IsInWorld())
+			return error;
+
+		CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
+		if (!cmpObstructionManager)
+			return error;
+
+		entity_pos_t spawnedRadius;
+		ICmpObstructionManager::tag_t spawnedTag;
+
+		CmpPtr<ICmpObstruction> cmpSpawnedObstruction(GetSimContext(), spawned);
+		if (cmpSpawnedObstruction)
+		{
+			spawnedRadius = cmpSpawnedObstruction->GetUnitRadius();
+			spawnedTag = cmpSpawnedObstruction->GetObstruction();
+		}
+		// else use zero radius
+
+		// Get passability class from UnitMotion
+		CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), spawned);
+		if (!cmpUnitMotion)
+			return error;
+
+		ICmpPathfinder::pass_class_t spawnedPass = cmpUnitMotion->GetPassabilityClass();
+		CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
+		if (!cmpPathfinder)
+			return error;
+
+		// Get the Footprint entity passability
+		CmpPtr<ICmpUnitMotion> cmpEntityMotion(GetEntityHandle());
+		if (!cmpEntityMotion)
+			return error;
+		ICmpPathfinder::pass_class_t entityPass = cmpEntityMotion->GetPassabilityClass();
+		
+		CFixedVector2D initialPos = cmpPosition->GetPosition2D();
+		entity_angle_t initialAngle = cmpPosition->GetRotation().Y;
+
+		// Max spawning distance + 1 (in meters)
+		const i32 maxSpawningDistance = 13;
+
+		if (m_Shape == CIRCLE)
+		{
+			// Expand outwards from foundation with a fixed step of 1 meter
+			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(1+dist);
+				entity_pos_t radius = m_Size0 + clearance;
+
+				// Try equally-spaced points around the circle in alternating directions, starting from the front
+				const i32 numPoints = 31 + 2*dist;
+				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]
+				{
+					entity_angle_t angle = initialAngle + (entity_angle_t::Pi()*2).Multiply(entity_angle_t::FromInt(i)/(int)numPoints);
+
+					fixed s, c;
+					sincos_approx(angle, s, c);
+
+					CFixedVector3D pos (initialPos.X + s.Multiply(radius), fixed::Zero(), initialPos.Y + c.Multiply(radius));
+
+					SkipTagObstructionFilter filter(spawnedTag); // ignore collisions with the spawned entity
+					if (cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Z, spawnedRadius, spawnedPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS &&
+						cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Z, spawnedRadius, entityPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
+						return pos; // this position is okay, so return it
+				}
+			}
+		}
+		else
+		{
+			fixed s, c;
+			sincos_approx(initialAngle, s, c);
+
+			// Expand outwards from foundation with a fixed step of 1 meter
+			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(1+dist);
+
+				for (i32 edge = 0; edge < 4; ++edge)
+				{
+					// Compute the direction and length of the current edge
+					CFixedVector2D dir;
+					fixed sx, sy;
+					switch (edge)
+					{
+					case 0:
+						dir = CFixedVector2D(c, -s);
+						sx = m_Size0;
+						sy = m_Size1;
+						break;
+					case 1:
+						dir = CFixedVector2D(-s, -c);
+						sx = m_Size1;
+						sy = m_Size0;
+						break;
+					case 2:
+						dir = CFixedVector2D(s, c);
+						sx = m_Size1;
+						sy = m_Size0;
+						break;
+					case 3:
+						dir = CFixedVector2D(-c, s);
+						sx = m_Size0;
+						sy = m_Size1;
+						break;
+					}
+					sx = sx/2 + clearance;
+					sy = sy/2 + clearance;
+					// Try equally-spaced (1 meter) points along the edge in alternating directions, starting from the middle
+					i32 numPoints = 1 + 2*sx.ToInt_RoundToNearest();
+					CFixedVector2D center = initialPos - dir.Perpendicular().Multiply(sy);
+					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 &&
+							cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, spawnedRadius, entityPass) == ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
+       							return CFixedVector3D(pos.X, fixed::Zero(), pos.Y); // this position is okay, so return it
+					}
+				}
+			}
+		}
+
+		return error;
+	}
 };
 
 REGISTER_COMPONENT_TYPE(Footprint)
Index: source/simulation2/components/ICmpFootprint.cpp
===================================================================
--- source/simulation2/components/ICmpFootprint.cpp	(révision 14490)
+++ source/simulation2/components/ICmpFootprint.cpp	(copie de travail)
@@ -62,5 +62,6 @@
 
 BEGIN_INTERFACE_WRAPPER(Footprint)
 DEFINE_INTERFACE_METHOD_1("PickSpawnPoint", CFixedVector3D, ICmpFootprint, PickSpawnPoint, entity_id_t)
+DEFINE_INTERFACE_METHOD_1("PickSpawnPointBothPass", CFixedVector3D, ICmpFootprint, PickSpawnPointBothPass, entity_id_t)
 DEFINE_INTERFACE_METHOD_0("GetShape", CScriptVal, ICmpFootprint, GetShape_wrapper)
 END_INTERFACE_WRAPPER(Footprint)
Index: source/simulation2/components/ICmpFootprint.h
===================================================================
--- source/simulation2/components/ICmpFootprint.h	(révision 14490)
+++ source/simulation2/components/ICmpFootprint.h	(copie de travail)
@@ -64,6 +64,13 @@
 	 */
 	virtual CFixedVector3D PickSpawnPoint(entity_id_t spawned) = 0;
 
+	/**
+	 * Pick a sensible position to place a newly-spawned entity near this footprint,
+	 * at the intersection between the footprint passability and the entity one.
+	 * @return the X and Z coordinates of the spawn point, with Y = 0; or the special value (-1, -1, -1) if there's no space
+	 */
+	virtual CFixedVector3D PickSpawnPointBothPass(entity_id_t spawned) = 0;
+
 	DECLARE_INTERFACE_TYPE(Footprint)
 };
 
