Index: binaries/data/mods/public/simulation/components/BuildingAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/BuildingAI.js	(revision 13600)
+++ binaries/data/mods/public/simulation/components/BuildingAI.js	(working copy)
@@ -1,6 +1,7 @@
 //Number of rounds of firing per 2 seconds
 const roundCount = 10;
 const timerInterval = 2000 / roundCount;
+const attackType = "Ranged";
 
 function BuildingAI() {}
 
@@ -10,6 +11,12 @@
 	"</element>" +
 	"<element name='GarrisonArrowMultiplier'>" +
 		"<ref name='nonNegativeDecimal'/>" +
+	"</element>" +
+	"<element name='GarrisonArrowClasses'>" +
+		"<attribute name='datatype'>" +
+			"<value>tokens</value>" +
+		"</attribute>" +
+		"<text/>" +
 	"</element>";
 
 /**
@@ -19,11 +26,9 @@
 {
 	if (this.GetDefaultArrowCount() > 0 || this.GetGarrisonArrowMultiplier() > 0)
 	{
-		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
 		this.currentRound = 0;
 		//Arrows left to fire
 		this.arrowsLeft = 0;
-		this.timer = cmpTimer.SetTimeout(this.entity, IID_BuildingAI, "FireArrows", timerInterval, {});
 		this.targetUnits = [];
 	}
 };
@@ -96,12 +101,12 @@
 			players.push(i);
 	}
 	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
-	if (cmpAttack)
-	{
-		var range = cmpAttack.GetRange("Ranged");
-		this.enemyUnitsQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, IID_DamageReceiver, cmpRangeManager.GetEntityFlagMask("normal"));
-		cmpRangeManager.EnableActiveQuery(this.enemyUnitsQuery);
-	}
+	if (!cmpAttack)
+		return;
+	
+	var range = cmpAttack.GetRange(attackType);
+	this.enemyUnitsQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, IID_DamageReceiver, cmpRangeManager.GetEntityFlagMask("normal"));
+	cmpRangeManager.EnableActiveQuery(this.enemyUnitsQuery);
 };
 
 // Set up a range query for Gaia units within LOS range which can be attacked.
@@ -111,12 +116,12 @@
 	var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
 	var owner = cmpOwnership.GetOwner();
 
-	var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
+	var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
 	var playerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
 
 	if (this.gaiaUnitsQuery)
 	{
-		rangeMan.DestroyActiveQuery(this.gaiaUnitsQuery);
+		cmpRangeManager.DestroyActiveQuery(this.gaiaUnitsQuery);
 		this.gaiaUnitsQuery = undefined;
 	}
 
@@ -128,14 +133,14 @@
 		return;
 
 	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
-	if (cmpAttack)
-	{
-		var range = cmpAttack.GetRange("Ranged");
+	if (!cmpAttack)
+		return;
+	
+	var range = cmpAttack.GetRange(attackType);
 
-		// This query is only interested in Gaia entities that can attack.
-		this.gaiaUnitsQuery = rangeMan.CreateActiveQuery(this.entity, range.min, range.max, [0], IID_Attack, rangeMan.GetEntityFlagMask("normal"));
-		rangeMan.EnableActiveQuery(this.gaiaUnitsQuery);
-	}
+	// This query is only interested in Gaia entities that can attack.
+	this.gaiaUnitsQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, [0], IID_Attack, cmpRangeManager.GetEntityFlagMask("normal"));
+	cmpRangeManager.EnableActiveQuery(this.gaiaUnitsQuery);
 };
 
 /**
@@ -143,6 +148,11 @@
  */
 BuildingAI.prototype.OnRangeUpdate = function(msg)
 {
+
+	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
+	if (!cmpAttack)
+		return;
+
 	if (msg.tag == this.gaiaUnitsQuery)
 	{
 		const filter = function(e) {
@@ -161,20 +171,36 @@
 	else if (msg.tag != this.enemyUnitsQuery)
 		return;
 
+	const restrictedClasses = cmpAttack.GetRestrictedClasses(attackType);
+
 	if (msg.added.length > 0)
 	{
 		for each (var entity in msg.added)
 		{
-			this.targetUnits.push(entity);
+			var cmpIdentity = Engine.QueryInterface(entity, IID_Identity);
+			var targetClasses = cmpIdentity.GetClassesList();
+
+			if (!targetClasses.some(function(c){return restrictedClasses.indexOf(c) > -1;}))
+				this.targetUnits.push(entity);
 		}
 	}
 	if (msg.removed.length > 0)
 	{
 		for each (var entity in msg.removed)
-		{
-			this.targetUnits.splice(this.targetUnits.indexOf(entity), 1);
+		{	
+			var index = this.targetUnits.indexOf(entity);
+			if (index > -1)
+				this.targetUnits.splice(index, 1);
 		}
 	}
+	
+	if (!this.targetUnits.length || this.timer)
+		return;
+	// units entered the range, prepare to shoot	
+	var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+	var attackTimers = cmpAttack.GetTimers(attackType);
+	this.timer = cmpTimer.SetInterval(this.entity, IID_BuildingAI, "FireArrows", attackTimers.prepare, attackTimers.repeat / roundCount, {});
+	
 };
 
 BuildingAI.prototype.GetDefaultArrowCount = function()
@@ -189,6 +215,12 @@
 	return ApplyTechModificationsToEntity("BuildingAI/GarrisonArrowMultiplier", arrowMult, this.entity);
 };
 
+BuildingAI.prototype.GetGarrisonArrowClasses = function()
+{
+	var string = this.template.GarrisonArrowClasses._string || "";
+	return string.split(/\s+/);
+};
+
 /**
  * Returns the number of arrows which needs to be fired.
  * DefaultArrowCount + Garrisoned Archers(ie., any unit capable 
@@ -200,56 +232,75 @@
 	var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
 	if (cmpGarrisonHolder)
 	{
-		count += Math.round(cmpGarrisonHolder.GetGarrisonedArcherCount() * this.GetGarrisonArrowMultiplier());
+		count += Math.round(cmpGarrisonHolder.GetGarrisonedArcherCount(this.GetGarrisonArrowClasses()) * this.GetGarrisonArrowMultiplier());
 	}
 	return count;
 };
 
 /**
- * Fires arrows. Called every N times every 2 seconds
- * where N is the number of Arrows
+ * Fires arrows. Called 'roundCount' times every 'RepeatTime' seconds when there are units in the range
  */
 BuildingAI.prototype.FireArrows = function()
 {
+
+	if (!this.targetUnits.length && this.timer)
+	{
+		// stop the timer
+		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+		cmpTimer.CancelTimer(this.timer);
+		this.timer = undefined;
+		return;
+	}
+
 	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
-	if (cmpAttack)
+	if (!cmpAttack)
+		return;
+
+	var cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
+	if (cmpUnitAI)
 	{
-		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-		this.timer = cmpTimer.SetTimeout(this.entity, IID_BuildingAI, "FireArrows", timerInterval, {});
-		var arrowsToFire = 0;
-		if (this.currentRound > (roundCount - 1))
-		{
-			//Reached end of rounds. Reset count
-			this.currentRound = 0;
-		}
-		
-		if (this.currentRound == 0)
-		{
-			//First round. Calculate arrows to fire
-			this.arrowsLeft = this.GetArrowCount();
-		}
-		
-		if (this.currentRound == (roundCount - 1))
-		{
-			//Last round. Need to fire all left-over arrows
-			arrowsToFire = this.arrowsLeft;
-		}
+		var orders = cmpUnitAI.GetOrders();
+		if (orders.length && orders[0].type == 'Attack' && orders[0].data.force)
+			// user is forcing this entity to attack a certian target
+			var forcedTarget = +orders[0].data.target;
+	}
+
+	var arrowsToFire = 0;
+	
+	if (this.currentRound === 0)
+		this.arrowsLeft = this.GetArrowCount();
+	
+	if (this.currentRound === (roundCount - 1))
+	{
+		//Last round. Need to fire all left-over arrows
+		arrowsToFire = this.arrowsLeft;
+	}
+	else
+	{
+		//Fire N arrows, 0 <= N <= Number of arrows left
+		arrowsToFire = Math.min( 
+		    Math.round(2*Math.random() * this.GetArrowCount()/roundCount),  
+		    this.arrowsLeft 
+		); 
+	}
+	
+	for (var i = 0; i < arrowsToFire; ++i)
+	{
+		var target;
+		if (forcedTarget && this.targetUnits.indexOf(forcedTarget) > -1)
+			// user forced to attack a certain one, and we're able to attack the target 
+			target = forcedTarget;
 		else
-		{
-			//Fire N arrows, 0 <= N <= Number of arrows left
-			arrowsToFire = Math.floor(Math.random() * this.arrowsLeft);
-		}
-		if (this.targetUnits.length > 0)
-		{
-			for (var i = 0;i < arrowsToFire;i++)
-			{
-				cmpAttack.PerformAttack("Ranged", this.targetUnits[Math.floor(Math.random() * this.targetUnits.length)]);
-				PlaySound("arrowfly", this.entity);
-			}
-			this.arrowsLeft -= arrowsToFire;
-		}
-		this.currentRound++;
+			target = this.targetUnits[Math.floor(Math.random() * this.targetUnits.length)];
+
+		cmpAttack.PerformAttack(attackType, target);
+		// TODO use Sound.js sounds
+		PlaySound("arrowfly", this.entity); 
 	}
+	this.arrowsLeft -= arrowsToFire;
+	
+	this.currentRound = ++this.currentRound % roundCount;
+	
 };
 
 Engine.RegisterComponentType(IID_BuildingAI, "BuildingAI", BuildingAI);
Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js	(revision 13600)
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js	(working copy)
@@ -78,7 +78,7 @@
  * Get number of garrisoned units capable of shooting arrows
  * Not necessarily archers
  */
-GarrisonHolder.prototype.GetGarrisonedArcherCount = function()
+GarrisonHolder.prototype.GetGarrisonedArcherCount = function(garrisonArrowClasses)
 {
 	var count = 0;
 	for each (var entity in this.entities)
@@ -85,7 +85,7 @@
 	{
 		var cmpIdentity = Engine.QueryInterface(entity, IID_Identity);
 		var classes = cmpIdentity.GetClassesList();
-		if (classes.indexOf("Infantry") != -1 || classes.indexOf("Ranged") != -1)
+		if (classes.some(function(c){return garrisonArrowClasses.indexOf(c) > -1;}))
 			count++;
 	}
 	return count;
Index: binaries/data/mods/public/simulation/templates/structures/brit_crannog.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/brit_crannog.xml	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/structures/brit_crannog.xml	(working copy)
@@ -3,6 +3,7 @@
   <BuildingAI>
     <DefaultArrowCount>3</DefaultArrowCount>
     <GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
   </BuildingAI>
   <BuildRestrictions>
 	<Territory>own ally neutral</Territory>
Index: binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml	(working copy)
@@ -23,12 +23,13 @@
       <Spread>1.5</Spread>
     </Ranged>
   </Attack>
-  <BuildingAI>
-    <DefaultArrowCount>3</DefaultArrowCount>
-    <GarrisonArrowMultiplier>0.5</GarrisonArrowMultiplier>
-  </BuildingAI>
-  <BuildRestrictions>
-    <Territory>own neutral enemy</Territory>
+  <BuildingAI>
+    <DefaultArrowCount>3</DefaultArrowCount>
+    <GarrisonArrowMultiplier>0.5</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
+  </BuildingAI>
+  <BuildRestrictions>
+    <Territory>own neutral enemy</Territory>
     <Category>Fortress</Category>
   </BuildRestrictions>
   <Cost>
Index: binaries/data/mods/public/simulation/templates/template_structure.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure.xml	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/template_structure.xml	(working copy)
@@ -13,6 +13,7 @@
   <BuildingAI>
     <DefaultArrowCount>0</DefaultArrowCount>
     <GarrisonArrowMultiplier>0</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
   </BuildingAI>
   <BuildRestrictions>
     <PlacementType>land</PlacementType>
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	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/template_structure_defense_defense_tower.xml	(working copy)
@@ -10,15 +10,17 @@
       <ProjectileSpeed>75.0</ProjectileSpeed>
       <PrepareTime>1200</PrepareTime>
       <RepeatTime>2000</RepeatTime>
+      <RestrictedClasses datatype="tokens">Structure</RestrictedClasses>
       <Spread>1.5</Spread>
     </Ranged>
   </Attack>
-  <BuildingAI>
-    <DefaultArrowCount>1</DefaultArrowCount>
-    <GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
-  </BuildingAI>
-  <BuildRestrictions>
-    <Category>DefenseTower</Category>
+  <BuildingAI>
+    <DefaultArrowCount>1</DefaultArrowCount>
+    <GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
+  </BuildingAI>
+  <BuildRestrictions>
+    <Category>DefenseTower</Category>
   </BuildRestrictions>
   <Cost>
     <BuildTime>120</BuildTime>
Index: binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/template_structure_defense_outpost.xml	(working copy)
@@ -20,11 +20,13 @@
       <ProjectileSpeed>75.0</ProjectileSpeed>
       <PrepareTime>1200</PrepareTime>
       <RepeatTime>2000</RepeatTime>
+      <RestrictedClasses datatype="tokens">Structure</RestrictedClasses>
       <Spread>2.0</Spread>
     </Ranged>
   </Attack>
   <BuildingAI>
     <GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
   </BuildingAI>
   <BuildRestrictions>
     <Territory>own neutral</Territory>
Index: binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml	(working copy)
@@ -10,6 +10,7 @@
       <ProjectileSpeed>75.0</ProjectileSpeed>
       <PrepareTime>1200</PrepareTime>
       <RepeatTime>2000</RepeatTime>
+      <RestrictedClasses datatype="tokens">Structure</RestrictedClasses>
       <Spread>1.5</Spread>
     </Ranged>
   </Attack>
@@ -16,6 +17,7 @@
   <BuildingAI>
     <DefaultArrowCount>3</DefaultArrowCount>
     <GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
   </BuildingAI>
   <BuildRestrictions>
     <Category>Fortress</Category>
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	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml	(working copy)
@@ -16,6 +16,7 @@
   <BuildingAI>
     <DefaultArrowCount>2</DefaultArrowCount>
     <GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
   </BuildingAI>
   <Cost>
     <Population>2</Population>
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	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml	(working copy)
@@ -2,13 +2,13 @@
 <Entity parent="template_unit_mechanical_ship">
   <Attack>
     <Ranged>
-      <Hack>0.0</Hack>
-      <Pierce>40.0</Pierce>
-      <Crush>100.0</Crush>
+      <Hack>30.0</Hack>
+      <Pierce>10.0</Pierce>
+      <Crush>30.0</Crush>
       <MaxRange>65.0</MaxRange>
       <MinRange>20.0</MinRange>
       <ProjectileSpeed>40.0</ProjectileSpeed>
-      <PrepareTime>2000</PrepareTime>
+      <PrepareTime>5000</PrepareTime>
       <RepeatTime>4000</RepeatTime>
       <Spread>1.5</Spread>
     </Ranged>
@@ -21,6 +21,11 @@
       <metal>200</metal>
     </Resources>
   </Cost>
+  <BuildingAI>
+    <DefaultArrowCount>0</DefaultArrowCount>
+    <GarrisonArrowMultiplier>0.5</GarrisonArrowMultiplier>
+    <GarrisonArrowClasses datatype="tokens">Ballista</GarrisonArrowClasses>
+  </BuildingAI>
   <Footprint>
     <Square width="12.0" depth="48.0"/>
     <Height>8.0</Height>
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	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml	(working copy)
@@ -16,6 +16,7 @@
   <BuildingAI>
     <DefaultArrowCount>3</DefaultArrowCount>
     <GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
   </BuildingAI>
   <Cost>
     <Population>3</Population>
Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_onager.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_onager.xml	(revision 13600)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_onager.xml	(working copy)
@@ -53,6 +53,7 @@
   <Identity>
     <GenericName>Siege Catapult</GenericName>
     <Tooltip>Bonused vs. Structures and Massed Infantry.</Tooltip>
+    <Classes datatype="tokens">Ballista</Classes>
   </Identity>
   <Loot>
     <xp>300</xp>
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 13600)
+++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_siege_tower.xml	(working copy)
@@ -15,6 +15,7 @@
       <ProjectileSpeed>75.0</ProjectileSpeed>
       <PrepareTime>1200</PrepareTime>
       <RepeatTime>2000</RepeatTime>
+      <RestrictedClasses datatype="tokens">Structure</RestrictedClasses>
       <Spread>1.5</Spread>
     </Ranged>
   </Attack>
@@ -21,6 +22,7 @@
   <BuildingAI>
     <DefaultArrowCount>1</DefaultArrowCount>
     <GarrisonArrowMultiplier>1</GarrisonArrowMultiplier>
+	<GarrisonArrowClasses datatype="tokens">Infanty Ranged</GarrisonArrowClasses>
   </BuildingAI>
   <Cost>
     <Population>5</Population>
