Index: source/simulation2/system/ComponentManager.h
===================================================================
--- source/simulation2/system/ComponentManager.h	(revision 11571)
+++ source/simulation2/system/ComponentManager.h	(working copy)
@@ -233,6 +233,7 @@
 	static int Script_AddLocalEntity(void* cbdata, std::string templateName);
 	static void Script_DestroyEntity(void* cbdata, int ent);
 	static CScriptVal Script_ReadJSONFile(void* cbdata, std::wstring fileName);
+	static std::vector<std::string> Script_FindAllTechnologyTemplates(void* cbdata);
 
 	CMessage* ConstructMessage(int mtid, CScriptVal data);
 	void SendGlobalMessage(entity_id_t ent, const CMessage& msg) const;
Index: source/simulation2/system/ComponentManager.cpp
===================================================================
--- source/simulation2/system/ComponentManager.cpp	(revision 11571)
+++ source/simulation2/system/ComponentManager.cpp	(working copy)
@@ -81,6 +81,7 @@
 		m_ScriptInterface.RegisterFunction<int, std::string, CComponentManager::Script_AddLocalEntity> ("AddLocalEntity");
 		m_ScriptInterface.RegisterFunction<void, int, CComponentManager::Script_DestroyEntity> ("DestroyEntity");
 		m_ScriptInterface.RegisterFunction<CScriptVal, std::wstring, CComponentManager::Script_ReadJSONFile> ("ReadJSONFile");
+		m_ScriptInterface.RegisterFunction<std::vector<std::string>, CComponentManager::Script_FindAllTechnologyTemplates> ("FindAllTechnologyTemplates");
 	}
 
 	// Define MT_*, IID_* as script globals, and store their names
@@ -944,3 +945,29 @@
 
 	return componentManager->GetScriptInterface().ReadJSONFile(path).get();
 }
+
+static Status AddToTechnologyTemplates(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData)
+{
+	std::vector<std::string>& templates = *(std::vector<std::string>*)cbData;
+
+	// Strip the .json extension
+	VfsPath pathstem = pathname.ChangeExtension(L"");
+	// Strip the root from the path
+	std::wstring name = pathstem.string().substr(ARRAY_SIZE("simulation/data/technologies/")-1);
+
+	templates.push_back(std::string(name.begin(), name.end()));
+	return INFO::OK;
+}
+
+std::vector<std::string> CComponentManager::Script_FindAllTechnologyTemplates(void* cbdata)
+{
+	std::vector<std::string> templates;
+
+	Status ok;
+
+	// Find all the technology template files
+	ok = vfs::ForEachFile(g_VFS, "simulation/data/technologies/", AddToTechnologyTemplates, (uintptr_t)&templates, L"*.json", vfs::DIR_RECURSIVE);
+	WARN_IF_ERR(ok);
+
+	return templates;
+}
Index: source/simulation2/Simulation2.cpp
===================================================================
--- source/simulation2/Simulation2.cpp	(revision 11571)
+++ source/simulation2/Simulation2.cpp	(working copy)
@@ -125,6 +125,7 @@
 			LOAD_SCRIPTED_COMPONENT("GuiInterface");
 			LOAD_SCRIPTED_COMPONENT("PlayerManager");
 			LOAD_SCRIPTED_COMPONENT("Timer");
+			LOAD_SCRIPTED_COMPONENT("TechnologyTemplateManager");
 
 #undef LOAD_SCRIPTED_COMPONENT
 		}
Index: binaries/data/mods/internal/simulation/templates/campaigns/campaign_religious_test.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/campaigns/campaign_religious_test.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/campaigns/campaign_religious_test.xml	(working copy)
@@ -20,7 +20,7 @@
     <Radius>100</Radius>
     <Weight>65536</Weight>
   </TerritoryInfluence>
-  <TrainingQueue disable=""/>
+  <ProductionQueue disable=""/>
   <VisualActor>
     <Actor>structures/hellenes/temple_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/campaigns/campaign_city_test.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/campaigns/campaign_city_test.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/campaigns/campaign_city_test.xml	(working copy)
@@ -35,14 +35,14 @@
     <Radius>300</Radius>
     <Weight>35000</Weight>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       -units/{civ}_support_female_citizen
       campaigns/army_mace_hero_alexander
       campaigns/army_mace_standard
       units/{civ}_support_trader
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>campaigns/structures/hellenes/settlement_curtainwall.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/campaigns/campaign_city_minor_test.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/campaigns/campaign_city_minor_test.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/campaigns/campaign_city_minor_test.xml	(working copy)
@@ -35,13 +35,13 @@
     <Radius>150</Radius>
     <Weight>35000</Weight>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       -units/{civ}_support_female_citizen
       campaigns/army_mace_hero_alexander
       campaigns/army_mace_standard
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>campaigns/structures/hellenes/settlement_curtainwall.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/mace_corral.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/mace_corral.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/mace_corral.xml	(working copy)
@@ -18,11 +18,11 @@
   <Obstruction>
     <Static width="14.0" depth="14.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/corral.xml</Actor>
     <FoundationActor>structures/fndn_3x3.xml</FoundationActor>
Index: binaries/data/mods/internal/simulation/templates/structures/mace_barracks.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/mace_barracks.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/mace_barracks.xml	(working copy)
@@ -15,7 +15,7 @@
     <SpecificName>Stratēgeîon</SpecificName>
     <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/mace_infantry_spearman_b
       units/mace_infantry_javelinist_b
@@ -24,7 +24,7 @@
       units/mace_cavalry_spearman_b
       units/mace_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/barracks.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/spart_corral.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/spart_corral.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/spart_corral.xml	(working copy)
@@ -18,11 +18,11 @@
   <Obstruction>
     <Static width="14.0" depth="14.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/corral.xml</Actor>
     <FoundationActor>structures/fndn_3x3.xml</FoundationActor>
Index: binaries/data/mods/internal/simulation/templates/structures/mace_fortress.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/mace_fortress.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/mace_fortress.xml	(working copy)
@@ -19,7 +19,7 @@
   <Obstruction>
     <Static width="24.0" depth="26.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/mace_hero_philip
       units/mace_hero_alexander
@@ -30,7 +30,7 @@
       units/mace_mechanical_siege_lithobolos
       units/mace_mechanical_siege_tower
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/fortress_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/spart_barracks.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/spart_barracks.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/spart_barracks.xml	(working copy)
@@ -15,14 +15,14 @@
     <SpecificName>Stratēgeîon</SpecificName>
     <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/spart_infantry_spearman_b
       units/spart_champion_infantry_sword
       units/spart_infantry_javelinist_b
       units/spart_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/barracks.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/spart_syssiton.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/spart_syssiton.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/spart_syssiton.xml	(working copy)
@@ -33,12 +33,12 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_hero_leonidas
       units/spart_champion_infantry_spear
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/gymnasion.xml</Actor>
     <FoundationActor>structures/fndn_6x6.xml</FoundationActor>
Index: binaries/data/mods/internal/simulation/templates/structures/spart_fortress.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/spart_fortress.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/spart_fortress.xml	(working copy)
@@ -19,11 +19,11 @@
   <Obstruction>
     <Static width="24.0" depth="26.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/spart_mechanical_siege_ram
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/fortress_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/mace_civil_centre.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/mace_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/mace_civil_centre.xml	(working copy)
@@ -11,13 +11,13 @@
     <SpecificName>Agorā́</SpecificName>
     <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/mace_infantry_spearman_b
       units/mace_infantry_javelinist_b
       units/mace_cavalry_spearman_b
 	</Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/civic_centre_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/mace_dock.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/mace_dock.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/mace_dock.xml	(working copy)
@@ -11,12 +11,12 @@
     <SpecificName>Limḗn</SpecificName>
     <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_ship_bireme
       units/hele_ship_trireme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/dock.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/spart_civil_centre.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/spart_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/spart_civil_centre.xml	(working copy)
@@ -11,13 +11,13 @@
     <SpecificName>Agorā́</SpecificName>
     <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/spart_infantry_spearman_b
       units/spart_infantry_javelinist_b
       units/spart_cavalry_javelinist_b
 	</Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/civic_centre_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/spart_gerousia.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/spart_gerousia.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/spart_gerousia.xml	(working copy)
@@ -34,11 +34,11 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_hero_leonidas
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/tholos.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/internal/simulation/templates/structures/spart_dock.xml
===================================================================
--- binaries/data/mods/internal/simulation/templates/structures/spart_dock.xml	(revision 11571)
+++ binaries/data/mods/internal/simulation/templates/structures/spart_dock.xml	(working copy)
@@ -11,12 +11,12 @@
     <SpecificName>Limḗn</SpecificName>
     <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/spart_ship_bireme
       units/spart_ship_trireme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/dock.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/gui/session/session.xml
===================================================================
--- binaries/data/mods/public/gui/session/session.xml	(revision 11571)
+++ binaries/data/mods/public/gui/session/session.xml	(working copy)
@@ -727,11 +727,15 @@
 				</object>
 
 				<object name="unitResearchPanel"
-					style="TranslucentPanelThinBorder"
-					size="0 100%-56 100% 100%"
-					type="text"
+					size="14 100%-56 100% 100%"
 				>
-
+					<object size="0 0 100% 100%">
+						<repeat count="8">
+							<object name="unitResearchButton[n]" hidden="true" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom">
+								<object name="unitResearchIcon[n]" type="image" ghost="true" size="3 3 43 43"/>
+							</object>
+						</repeat>
+					</object>
 					[research commands]
 				</object>
 
Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js	(revision 11571)
+++ binaries/data/mods/public/gui/session/input.js	(working copy)
@@ -764,7 +764,7 @@
 		case "hotkeyup":
 			if (ev.hotkey == "session.batchtrain")
 			{
-				flushTrainingQueueBatch();
+				flushTrainingBatch();
 				inputState = INPUT_NORMAL;
 			}
 			break;
@@ -1202,13 +1202,13 @@
 var batchTrainingCount;
 const batchIncrementSize = 5;
 
-function flushTrainingQueueBatch()
+function flushTrainingBatch()
 {
 	Engine.PostNetworkCommand({"type": "train", "entity": batchTrainingEntity, "template": batchTrainingType, "count": batchTrainingCount});
 }
 
 // Called by GUI when user clicks training button
-function addToTrainingQueue(entity, trainEntType)
+function addTrainingToQueue(entity, trainEntType)
 {
 	if (Engine.HotkeyIsPressed("session.batchtrain"))
 	{
@@ -1223,7 +1223,7 @@
 			// Otherwise start a new one
 			else
 			{
-				flushTrainingQueueBatch();
+				flushTrainingBatch();
 				// fall through to create the new batch
 			}
 		}
@@ -1239,9 +1239,15 @@
 	}
 }
 
+// Called by GUI when user clicks training button
+function addResearchToQueue(entity, trainEntType)
+{
+	Engine.PostNetworkCommand({"type": "research", "entity": entity, "template": trainEntType});
+}
+
 // Returns the number of units that will be present in a batch if the user clicks
 // the training button with shift down
-function getTrainingQueueBatchStatus(entity, trainEntType)
+function getTrainingBatchStatus(entity, trainEntType)
 {
 	if (inputState == INPUT_BATCHTRAINING && batchTrainingEntity == entity && batchTrainingType == trainEntType)
 		return [batchTrainingCount, batchIncrementSize];
@@ -1250,9 +1256,9 @@
 }
 
 // Called by GUI when user clicks production queue item
-function removeFromTrainingQueue(entity, id)
+function removeFromProductionQueue(entity, id)
 {
-	Engine.PostNetworkCommand({"type": "stop-train", "entity": entity, "id": id});
+	Engine.PostNetworkCommand({"type": "stop-production", "entity": entity, "id": id});
 }
 
 // Called by unit selection buttons
Index: binaries/data/mods/public/gui/session/unit_commands.js
===================================================================
--- binaries/data/mods/public/gui/session/unit_commands.js	(revision 11571)
+++ binaries/data/mods/public/gui/session/unit_commands.js	(working copy)
@@ -4,6 +4,7 @@
 const GARRISON = "Garrison";
 const FORMATION = "Formation";
 const TRAINING = "Training";
+const RESEARCH = "Research";
 const CONSTRUCTION = "Construction";
 const COMMAND = "Command";
 const STANCE = "Stance";
@@ -23,7 +24,7 @@
 const BARTER_ACTIONS = ["Sell", "Buy"];
 
 // The number of currently visible buttons (used to optimise showing/hiding)
-var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Training": 0, "Barter": 0, "Trading": 0, "Construction": 0, "Command": 0, "Stance": 0};
+var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Training": 0, "Research": 0, "Barter": 0, "Trading": 0, "Construction": 0, "Command": 0, "Stance": 0};
 
 // Unit panels are panels with row(s) of buttons
 var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Training", "Barter", "Trading", "Construction", "Research", "Stance", "Command"];
@@ -163,6 +164,11 @@
 			if (numberOfItems > 24)
 				numberOfItems =  24;
 			break;
+		
+		case RESEARCH:
+			if (numberOfItems > 8)
+				numberOfItems =  8;
+			break;
 
 		case CONSTRUCTION:
 			if (numberOfItems > 24)
@@ -183,13 +189,54 @@
 	for (i = 0; i < numberOfItems; i++)
 	{
 		var item = items[i];
-		var entType = ((guiName == "Queue")? item.template : item);
+		
+		// If a tech has been researched it leaves an empty slot
+		if (guiName == RESEARCH && !item)
+		{
+			getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
+			continue;
+		}
+		
+		// Get the entity type and load the template for that type if necessary
+		var entType;
 		var template;
-		if (guiName != "Formation" && guiName != "Command" && guiName != "Stance")
+		switch (guiName)
 		{
-			template = GetTemplateData(entType);
-			if (!template)
-				continue; // ignore attempts to use invalid templates (an error should have been reported already)
+			case QUEUE:
+				// The queue can hold both technologies and units so we need to use the correct code for
+				// loading the templates
+				if (item.unitTemplate)
+				{
+					entType = item.unitTemplate;
+					template = GetTemplateData(entType);
+				}
+				else if (item.technologyTemplate)
+				{
+					entType = item.technologyTemplate;
+					template = GetTechnologyData(entType);
+				}
+			
+				if (!template)
+					continue; // ignore attempts to use invalid templates (an error should have been
+					          // reported already)
+				break;
+			case RESEARCH:
+				entType = item;
+				template = GetTechnologyData(entType);
+				if (!template)
+					continue; // ignore attempts to use invalid templates (an error should have been
+					          // reported already)
+				break;
+			case SELECTION:
+			case GARRISON:
+			case TRAINING:
+			case CONSTRUCTION:
+				entType = item;
+				template = GetTemplateData(entType);
+				if (!template)
+					continue; // ignore attempts to use invalid templates (an error should have been
+					          // reported already)
+				break;
 		}
 
 		switch (guiName)
@@ -233,7 +280,7 @@
 				if (template.tooltip)
 					tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]";
 
-				var [batchSize, batchIncrement] = getTrainingQueueBatchStatus(unitEntState.id, entType);
+				var [batchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType);
 				var trainNum = batchSize ? batchSize+batchIncrement : batchIncrement;
 
 				tooltip += "\n" + getEntityCost(template);
@@ -250,7 +297,16 @@
 				tooltip += "\n\n[font=\"serif-bold-13\"]Shift-click[/font][font=\"serif-13\"] to train " + trainNum + ".[/font]";
 
 				break;
+				
+			case RESEARCH:
+				var tooltip = getEntityNameWithGenericType(template);
 
+				if (template.tooltip)
+					tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]";
+
+				tooltip += "\n" + getEntityCost(template);
+				break;
+
 			case CONSTRUCTION:
 				var tooltip = getEntityNameWithGenericType(template);
 				if (template.tooltip)
@@ -352,7 +408,25 @@
 		}
 		else if (template.icon)
 		{
-			icon.sprite = "stretched:session/portraits/" + template.icon;
+			var grayscale = "";
+			button.enabled = true;
+			
+			if (template.requiredTechnology && !Engine.GuiInterfaceCall("IsTechnologyResearched", template.requiredTechnology))
+			{
+				button.enabled = false;
+				var techName = getEntityName(GetTechnologyData(template.requiredTechnology));
+				button.tooltip += "\nRequires " + techName;
+				grayscale = "grayscale:";
+			}
+			
+			if (guiName == RESEARCH && !Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType))
+			{
+				button.enabled = false;
+				button.tooltip += "\n" + GetTechnologyData(entType).requirementsTooltip;
+				grayscale = "grayscale:";
+			}
+			
+			icon.sprite = "stretched:" + grayscale + "session/portraits/" + template.icon;
 		}
 		else
 		{
@@ -537,16 +611,22 @@
 		{
 			setupUnitPanel("Construction", usedPanels, entState, entState.buildEntities, startBuildingPlacement);
 		}
-
-		if (entState.training && entState.training.entities.length)
+		
+		if (entState.production && entState.production.entities.length)
 		{
-			setupUnitPanel("Training", usedPanels, entState, entState.training.entities,
-				function (trainEntType) { addToTrainingQueue(entState.id, trainEntType); } );
+			setupUnitPanel("Training", usedPanels, entState, entState.production.entities,
+				function (trainEntType) { addTrainingToQueue(entState.id, trainEntType); } );
 		}
+		
+		if (entState.production && entState.production.technologies.length)
+		{
+			setupUnitPanel("Research", usedPanels, entState, entState.production.technologies,
+				function (researchType) { addResearchToQueue(entState.id, researchType); } );
+		}
 
-		if (entState.training && entState.training.queue.length)
-			setupUnitPanel("Queue", usedPanels, entState, entState.training.queue,
-				function (item) { removeFromTrainingQueue(entState.id, item.id); } );
+		if (entState.production && entState.production.queue.length)
+			setupUnitPanel("Queue", usedPanels, entState, entState.production.queue,
+				function (item) { removeFromProductionQueue(entState.id, item.id); } );
 
 		if (entState.trader)
 		{
Index: binaries/data/mods/public/gui/session/session.js
===================================================================
--- binaries/data/mods/public/gui/session/session.js	(revision 11571)
+++ binaries/data/mods/public/gui/session/session.js	(working copy)
@@ -15,7 +15,7 @@
 
 // Indicate when one of the current player's training queues is blocked
 // (this is used to support population counter blinking)
-var g_IsTrainingQueueBlocked = false;
+var g_IsTrainingBlocked = false;
 
 // Cache EntityStates
 var g_EntityStates = {}; // {id:entState}
@@ -53,6 +53,20 @@
 	return g_TemplateData[templateName];
 }
 
+// Cache TechnologyData
+var g_TechnologyData = {}; // {id:template}
+
+function GetTechnologyData(technologyName)
+{
+	if (!(technologyName in g_TechnologyData))
+	{
+		var template = Engine.GuiInterfaceCall("GetTechnologyData", technologyName);
+		g_TechnologyData[technologyName] = template;
+	}
+
+	return g_TechnologyData[technologyName];
+}
+
 // Init
 function init(initData, hotloadData)
 {
@@ -206,7 +220,7 @@
 	global.music.updateTimer();
 
 	// When training is blocked, flash population (alternates colour every 500msec)
-	if (g_IsTrainingQueueBlocked && (Date.now() % 1000) < 500)
+	if (g_IsTrainingBlocked && (Date.now() % 1000) < 500)
 		getGUIObjectByName("resourcePop").textcolor = POPULATION_ALERT_COLOR;
 	else
 		getGUIObjectByName("resourcePop").textcolor = DEFAULT_POPULATION_COLOR;
@@ -257,6 +271,7 @@
 	g_Selection.dirty = false;
 	g_EntityStates = {};
 	g_TemplateData = {};
+	g_TechnologyData = {};
 
 	var simState = Engine.GuiInterfaceCall("GetSimulationState");
 
@@ -345,7 +360,7 @@
 	getGUIObjectByName("resourceMetal").caption = playerState.resourceCounts.metal;
 	getGUIObjectByName("resourcePop").caption = playerState.popCount + "/" + playerState.popLimit;
 
-	g_IsTrainingQueueBlocked = playerState.trainingQueueBlocked;
+	g_IsTrainingBlocked = playerState.trainingBlocked;
 }
 
 function updateTimeElapsedCounter(simState)
Index: binaries/data/mods/public/simulation/helpers/Commands.js
===================================================================
--- binaries/data/mods/public/simulation/helpers/Commands.js	(revision 11571)
+++ binaries/data/mods/public/simulation/helpers/Commands.js	(working copy)
@@ -135,9 +135,18 @@
 		// Verify that the building can be controlled by the player
 		if (CanControlUnit(cmd.entity, player, controlAllUnits))
 		{
-			var queue = Engine.QueryInterface(cmd.entity, IID_TrainingQueue);
-			if (queue)
-				queue.AddBatch(cmd.template, +cmd.count, cmd.metadata);
+			var cmpTechMan = QueryOwnerInterface(cmd.entity, IID_TechnologyManager);
+			// TODO: Enable this check once the AI gets technology support
+			if (cmpTechMan.CanProduce(cmd.template) || true)
+			{
+				var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue);
+				if (queue)
+					queue.AddBatch(cmd.template, "unit", +cmd.count, cmd.metadata);
+			}
+			else if (g_DebugCommands)
+			{
+				warn("Invalid command: training requires unresearched technology: " + uneval(cmd));
+			}
 		}
 		else if (g_DebugCommands)
 		{
@@ -145,17 +154,40 @@
 		}
 		break;
 
-	case "stop-train":
+	case "research":
 		// Verify that the building can be controlled by the player
 		if (CanControlUnit(cmd.entity, player, controlAllUnits))
 		{
-			var queue = Engine.QueryInterface(cmd.entity, IID_TrainingQueue);
+			var cmpTechMan = QueryOwnerInterface(cmd.entity, IID_TechnologyManager);
+			// TODO: Enable this check once the AI gets technology support
+			if (cmpTechMan.CanResearch(cmd.template) || true)
+			{
+				var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue);
+				if (queue)
+					queue.AddBatch(cmd.template, "technology");
+			}
+			else if (g_DebugCommands)
+			{
+				warn("Invalid command: Requirements to research technology are not met: " + uneval(cmd));
+			}
+		}
+		else if (g_DebugCommands)
+		{
+			warn("Invalid command: research building cannot be controlled by player "+player+": "+uneval(cmd));
+		}
+		break;
+
+	case "stop-production":
+		// Verify that the building can be controlled by the player
+		if (CanControlUnit(cmd.entity, player, controlAllUnits))
+		{
+			var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue);
 			if (queue)
 				queue.RemoveBatch(cmd.id);
 		}
 		else if (g_DebugCommands)
 		{
-			warn("Invalid command: training building cannot be controlled by player "+player+": "+uneval(cmd));
+			warn("Invalid command: production building cannot be controlled by player "+player+": "+uneval(cmd));
 		}
 		break;
 
@@ -233,7 +265,23 @@
 			Engine.DestroyEntity(ent);
 			break;
 		}
+		
+		var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager);
+		// TODO: Enable this check once the AI gets technology support
+		if (!cmpTechMan.CanProduce(cmd.template) && false)
+		{
+			if (g_DebugCommands)
+			{
+				warn("Invalid command: required technology check failed for player "+player+": "+uneval(cmd));
+			}
 
+			var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
+			cmpGuiInterface.PushNotification({ "player": player, "message": "Building's technology requirements are not met." });
+
+			// Remove the foundation because the construction was aborted
+			Engine.DestroyEntity(ent);
+		}
+
 		// TODO: AI has no visibility info
 		if (!cmpPlayer.IsAI())
 		{
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js	(revision 11571)
+++ binaries/data/mods/public/simulation/components/GuiInterface.js	(working copy)
@@ -66,7 +66,7 @@
 			"popLimit": cmpPlayer.GetPopulationLimit(),
 			"popMax": cmpPlayer.GetMaxPopulation(),
 			"resourceCounts": cmpPlayer.GetResourceCounts(),
-			"trainingQueueBlocked": cmpPlayer.IsTrainingQueueBlocked(),
+			"trainingBlocked": cmpPlayer.IsTrainingBlocked(),
 			"state": cmpPlayer.GetState(),
 			"team": cmpPlayer.GetTeam(),
 			"phase": cmpPlayer.GetPhase(),
@@ -177,12 +177,13 @@
 		ret.buildEntities = cmpBuilder.GetEntitiesList();
 	}
 
-	var cmpTrainingQueue = Engine.QueryInterface(ent, IID_TrainingQueue);
-	if (cmpTrainingQueue)
+	var cmpProductionQueue = Engine.QueryInterface(ent, IID_ProductionQueue);
+	if (cmpProductionQueue)
 	{
-		ret.training = {
-			"entities": cmpTrainingQueue.GetEntitiesList(),
-			"queue": cmpTrainingQueue.GetQueue(),
+		ret.production = {
+			"entities": cmpProductionQueue.GetEntitiesList(),
+			"technologies": cmpProductionQueue.GetTechnologiesList(),
+			"queue": cmpProductionQueue.GetQueue(),
 		};
 	}
 
@@ -346,6 +347,7 @@
 		};
 		ret.icon = template.Identity.Icon;
 		ret.tooltip =  template.Identity.Tooltip;
+		ret.requiredTechnology = template.Identity.RequiredTechnology;
 	}
 
 	if (template.UnitMotion)
@@ -359,6 +361,68 @@
 	return ret;
 };
 
+GuiInterface.prototype.GetTechnologyData = function(player, name)
+{
+	var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager);
+	var template = cmpTechTempMan.GetTemplate(name);
+	
+	if (!template)
+	{
+		warn("tried to get data for invaalid technology: " + name);
+		return null;
+	}
+	
+	var ret = {};
+	
+	var cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
+	var specific = template.specificName;
+	if (template["specificName_" + cmpPlayer.GetCiv()])
+		specific = template["specificName_" + cmpPlayer.GetCiv()];
+	
+	ret.name = {
+		"specific": specific,
+		"generic": template.genericName,
+	};
+	ret.icon = template.icon;
+	ret.cost = {
+		"food": +template.cost.food,
+		"wood": +template.cost.wood,
+		"metal": +template.cost.metal,
+		"stone": +template.cost.stone,
+	}
+	ret.tooltip = template.tooltip;
+	
+	if (template.requirementsTooltip)
+		ret.requirementsTooltip = template.requirementsTooltip;
+	else
+		ret.requirementsTooltip = "";
+	
+	ret.description = template.description;
+	
+	return ret;
+};
+
+GuiInterface.prototype.IsTechnologyResearched = function(player, tech)
+{
+	var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager);
+	
+	if (!cmpTechMan)
+		return false;
+	
+	return cmpTechMan.IsTechnologyResearched(tech);
+}
+
+// Checks whether the requirements for this technology have been met
+GuiInterface.prototype.CheckTechnologyRequirements = function(player, tech)
+{
+	var cmpTechMan = QueryPlayerIDInterface(player, IID_TechnologyManager);
+	
+	if (!cmpTechMan)
+		return false;
+	
+	return cmpTechMan.CanResearch(tech);
+}
+
 GuiInterface.prototype.PushNotification = function(notification)
 {
 	this.notifications.push(notification);
@@ -812,6 +876,9 @@
 	"ClearRenamedEntities": 1,
 	"GetEntityState": 1,
 	"GetTemplateData": 1,
+	"GetTechnologyData": 1,
+	"IsTechnologyResearched": 1,
+	"CheckTechnologyRequirements": 1,
 	"GetNextNotification": 1,
 
 	"GetFormationRequirements": 1,
Index: binaries/data/mods/public/simulation/components/interfaces/TrainingQueue.js
===================================================================
--- binaries/data/mods/public/simulation/components/interfaces/TrainingQueue.js	(working copy)
+++ binaries/data/mods/public/simulation/components/interfaces/TrainingQueue.js	(revision 11571)
@@ -1,9 +0,0 @@
-Engine.RegisterInterface("TrainingQueue");
-
-// Message of the form { } (use GetQueue if you want the current details),
-// sent to the current entity whenever the training queue changes.
-Engine.RegisterMessageType("TrainingQueueChanged");
-
-// Message of the form { entities: [id, ...], metadata: ... }
-// sent to the current entity whenever a unit has been trained.
-Engine.RegisterMessageType("TrainingFinished");
Index: binaries/data/mods/public/simulation/components/interfaces/TechnologyManager.js
===================================================================
--- binaries/data/mods/public/simulation/components/interfaces/TechnologyManager.js	(revision 0)
+++ binaries/data/mods/public/simulation/components/interfaces/TechnologyManager.js	(revision 0)
@@ -0,0 +1,5 @@
+Engine.RegisterInterface("TechnologyManager");
+
+// Message of the form { "component": "Attack", "player": 3 }
+// Sent when a new technology is researched which modifies a component
+Engine.RegisterMessageType("TechnologyModificationChange");
Index: binaries/data/mods/public/simulation/components/interfaces/ProductionQueue.js
===================================================================
--- binaries/data/mods/public/simulation/components/interfaces/ProductionQueue.js	(revision 11375)
+++ binaries/data/mods/public/simulation/components/interfaces/ProductionQueue.js	(working copy)
@@ -1,8 +1,8 @@
-Engine.RegisterInterface("TrainingQueue");
+Engine.RegisterInterface("ProductionQueue");
 
 // Message of the form { } (use GetQueue if you want the current details),
 // sent to the current entity whenever the training queue changes.
-Engine.RegisterMessageType("TrainingQueueChanged");
+Engine.RegisterMessageType("ProductionQueueChanged");
 
 // Message of the form { entities: [id, ...], metadata: ... }
 // sent to the current entity whenever a unit has been trained.
Index: binaries/data/mods/public/simulation/components/interfaces/TechnologyTemplateManager.js
===================================================================
--- binaries/data/mods/public/simulation/components/interfaces/TechnologyTemplateManager.js	(revision 0)
+++ binaries/data/mods/public/simulation/components/interfaces/TechnologyTemplateManager.js	(revision 0)
@@ -0,0 +1 @@
+Engine.RegisterInterface("TechnologyTemplateManager");
\ No newline at end of file
Index: binaries/data/mods/public/simulation/components/ResourceGatherer.js
===================================================================
--- binaries/data/mods/public/simulation/components/ResourceGatherer.js	(revision 11571)
+++ binaries/data/mods/public/simulation/components/ResourceGatherer.js	(working copy)
@@ -125,19 +125,40 @@
 		return undefined;
 };
 
+// Remove any cached template data which is based on technology data
+ResourceGatherer.prototype.OnTechnologyModificationChange = function(msg)
+{
+	var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+	if (!cmpOwnership)
+		return;
+	
+	var player = cmpOwnership.GetOwner();
+	
+	if (msg.component === "ResourceGatherer" && msg.player === player)
+		delete this.gatherRatesCache;
+};
+
 ResourceGatherer.prototype.GetGatherRates = function()
 {
-	var ret = {};
-	for (var r in this.template.Rates)
-		ret[r] = this.template.Rates[r] * this.template.BaseSpeed;
-	return ret;
+	if (!this.gatherRatesCache){
+		this.gatherRatesCache = {};
+		var cmpTechManager = QueryOwnerInterface(this.entity, IID_TechnologyManager);
+		var baseSpeed = cmpTechManager.ApplyModifications("ResourceGatherer/BaseSpeed", this.template.BaseSpeed, this.entity);
+		for (var r in this.template.Rates)
+		{
+			var rate = cmpTechManager.ApplyModifications("ResourceGatherer/Rates/" + r, this.template.Rates[r], this.entity);
+			this.gatherRatesCache[r] = rate * baseSpeed;
+		}
+	}
+	
+	return this.gatherRatesCache;
 };
 
 ResourceGatherer.prototype.GetRange = function()
 {
 	return { "max": +this.template.MaxDistance, "min": 0 };
 	// maybe this should depend on the unit or target or something?
-}
+};
 
 /**
  * Try to gather treasure
@@ -223,13 +244,13 @@
 	var type = cmpResourceSupply.GetType();
 
 	var rate;
-	if (type.specific && this.template.Rates[type.generic+"."+type.specific])
-		rate = this.template.Rates[type.generic+"."+type.specific];
+	if (type.specific && this.GetGatherRates()[type.generic+"."+type.specific])
+		rate = this.GetGatherRates()[type.generic+"."+type.specific];
 	else
-		rate = this.template.Rates[type.generic];
+		rate = this.GetGatherRates()[type.generic];
 
-	return (rate || 0) * this.template.BaseSpeed;
-}
+	return (rate || 0);
+};
 
 /**
  * Returns whether this unit can carry more of the given type of resource.
Index: binaries/data/mods/public/simulation/components/TrainingQueue.js
===================================================================
--- binaries/data/mods/public/simulation/components/TrainingQueue.js	(working copy)
+++ binaries/data/mods/public/simulation/components/TrainingQueue.js	(revision 11571)
@@ -1,400 +0,0 @@
-var g_ProgressInterval = 1000;
-const MAX_QUEUE_SIZE = 16;
-
-function TrainingQueue() {}
-
-TrainingQueue.prototype.Schema =
-	"<a:help>Allows the building to train new units.</a:help>" +
-	"<a:example>" +
-		"<Entities datatype='tokens'>" +
-			"\n    units/{civ}_support_female_citizen\n    units/{civ}_support_trader\n    units/celt_infantry_spearman_b\n  " +
-		"</Entities>" +
-	"</a:example>" +
-	"<element name='Entities' a:help='Space-separated list of entity template names that this building can train. The special string \"{civ}\" will be automatically replaced by the building&apos;s four-character civ code'>" +
-		"<attribute name='datatype'>" +
-			"<value>tokens</value>" +
-		"</attribute>" +
-		"<text/>" +
-	"</element>";
-
-TrainingQueue.prototype.Init = function()
-{
-	this.nextID = 1;
-
-	this.queue = [];
-	// Queue items are:
-	//   {
-	//     "id": 1,
-	//     "player": 1, // who paid for this batch; we need this to cope with refunds cleanly
-	//     "template": "units/example",
-	//     "count": 10,
-	//     "resources": { "wood": 100, ... },	// resources per unit, multiply by count to get total
-	//     "population": 1,	// population per unit, multiply by count to get total
-	//     "trainingStarted": false, // true iff we have reserved population
-	//     "timeTotal": 15000, // msecs
-	//     "timeRemaining": 10000, // msecs
-	//   }
-	
-	this.timer = undefined; // g_ProgressInterval msec timer, active while the queue is non-empty
-	
-	this.entityCache = [];
-	this.spawnNotified = false;
-};
-
-/*
- * Returns list of entities that can be trained by this building.
- */
-TrainingQueue.prototype.GetEntitiesList = function()
-{
-	var string = this.template.Entities._string;
-	
-	// Replace the "{civ}" codes with this entity's civ ID
-	var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
-	if (cmpIdentity)
-		string = string.replace(/\{civ\}/g, cmpIdentity.GetCiv());
-	
-	return string.split(/\s+/);
-};
-
-/*
- * Adds a new batch of identical units to the training queue.
- */
-TrainingQueue.prototype.AddBatch = function(templateName, count, metadata)
-{
-	// TODO: there should probably be a limit on the number of queued batches
-	// TODO: there should be a way for the GUI to determine whether it's going
-	// to be possible to add a batch (based on resource costs and length limits)
-	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
-
-	if (this.queue.length < MAX_QUEUE_SIZE)
-	{
-		// Find the template data so we can determine the build costs
-		var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
-		var template = cmpTempMan.GetTemplate(templateName);
-		if (!template)
-			return;
-
-		// Apply a time discount to larger batches.
-		// TODO: work out what equation we should use here.
-		var timeMult = Math.pow(count, 0.7);
-
-		var time = timeMult * template.Cost.BuildTime;
-
-		var totalCosts = {};
-		for each (var r in ["food", "wood", "stone", "metal"])
-			totalCosts[r] = Math.floor(count * template.Cost.Resources[r]);
-
-		var population = template.Cost.Population;
-	
-		// TrySubtractResources should report error to player (they ran out of resources)
-		if (!cmpPlayer.TrySubtractResources(totalCosts))
-			return;
-
-		this.queue.push({
-			"id": this.nextID++,
-			"player": cmpPlayer.GetPlayerID(),
-			"template": templateName,
-			"count": count,
-			"metadata": metadata,
-			"resources": deepcopy(template.Cost.Resources), // need to copy to avoid serialization problems
-			"population": population,
-			"trainingStarted": false,
-			"timeTotal": time*1000,
-			"timeRemaining": time*1000,
-		});
-		Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });
-
-		// If this is the first item in the queue, start the timer
-		if (!this.timer)
-		{
-			var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-			this.timer = cmpTimer.SetTimeout(this.entity, IID_TrainingQueue, "ProgressTimeout", g_ProgressInterval, {});
-		}
-	}
-	else
-	{
-		var notification = {"player": cmpPlayer.GetPlayerID(), "message": "The training queue is full."};
-		var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
-		cmpGUIInterface.PushNotification(notification);
-	}
-};
-
-/*
- * Removes an existing batch of units from the training queue.
- * Refunds resource costs and population reservations.
- */
-TrainingQueue.prototype.RemoveBatch = function(id)
-{
-	// Destroy any cached entities (those which didn't spawn for some reason)
-	for (var i = 0; i < this.entityCache.length; ++i)
-	{
-		Engine.DestroyEntity(this.entityCache[i]);
-	}
-	this.entityCache = [];
-	
-	for (var i = 0; i < this.queue.length; ++i)
-	{
-		var item = this.queue[i];
-		if (item.id != id)
-			continue;
-
-		// Now we've found the item to remove
-
-		var cmpPlayer = QueryPlayerIDInterface(item.player, IID_Player);
-
-		// Refund the resource cost for this batch
-		var totalCosts = {};
-		for each (var r in ["food", "wood", "stone", "metal"])
-			totalCosts[r] = Math.floor(item.count * item.resources[r]);
-			
-		cmpPlayer.AddResources(totalCosts);
-
-		// Remove reserved population slots if necessary
-		if (item.trainingStarted)
-			cmpPlayer.UnReservePopulationSlots(item.population * item.count);
-
-		// Remove from the queue
-		// (We don't need to remove the timer - it'll expire if it discovers the queue is empty)
-		this.queue.splice(i, 1);
-		Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });
-
-		return;
-	}
-};
-
-/*
- * Returns basic data from all batches in the training queue.
- */
-TrainingQueue.prototype.GetQueue = function()
-{
-	var out = [];
-	for each (var item in this.queue)
-	{
-		out.push({
-			"id": item.id,
-			"template": item.template,
-			"count": item.count,
-			"progress": 1-(item.timeRemaining/item.timeTotal),
-			"metadata": item.metadata,
-		});
-	}
-	return out;
-};
-
-/*
- * Removes all existing batches from the queue.
- */
-TrainingQueue.prototype.ResetQueue = function()
-{
-	// Empty the training queue and refund all the resource costs
-	// to the player. (This is to avoid players having to micromanage their
-	// buildings' queues when they're about to be destroyed or captured.)
-
-	while (this.queue.length)
-		this.RemoveBatch(this.queue[0].id);
-};
-
-TrainingQueue.prototype.OnOwnershipChanged = function(msg)
-{
-	if (msg.from != -1)
-	{
-		// Unset flag that previous owner's training queue may be blocked
-		var cmpPlayer = QueryPlayerIDInterface(msg.from, IID_Player);
-		if (cmpPlayer && this.queue.length > 0)
-			cmpPlayer.UnBlockTrainingQueue();
-	}
-
-	// Reset the training queue whenever the owner changes.
-	// (This should prevent players getting surprised when they capture
-	// an enemy building, and then loads of the enemy's civ's soldiers get
-	// created from it. Also it means we don't have to worry about
-	// updating the reserved pop slots.)
-	this.ResetQueue();
-};
-
-TrainingQueue.prototype.OnDestroy = function()
-{
-	// Reset the queue to refund any resources
-	this.ResetQueue();
-
-	if (this.timer)
-	{
-		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-		cmpTimer.CancelTimer(this.timer);
-	}
-};
-
-/*
- * This function creates the entities and places them in world if possible.
- * returns the number of successfully spawned entities.
- */
-TrainingQueue.prototype.SpawnUnits = function(templateName, count, metadata)
-{
-	var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint);
-	var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
-	var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
-	var cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint);
-	
-	var spawnedEnts = [];
-	
-	if (this.entityCache.length == 0)
-	{
-		// We need entities to test spawning, but we don't want to waste resources,
-		//	so only create them once and use as needed
-		for (var i = 0; i < count; ++i)
-		{
-			this.entityCache.push(Engine.AddEntity(templateName));
-		}
-	}
-
-	for (var i = 0; i < count; ++i)
-	{
-		var ent = this.entityCache[0];
-		var pos = cmpFootprint.PickSpawnPoint(ent);
-		if (pos.y < 0)
-		{
-			// Fail: there wasn't any space to spawn the unit
-			break;
-		}
-		else
-		{
-			// Successfully spawned
-			var cmpNewPosition = Engine.QueryInterface(ent, IID_Position);
-			cmpNewPosition.JumpTo(pos.x, pos.z);
-			// TODO: what direction should they face in?
-
-			var cmpNewOwnership = Engine.QueryInterface(ent, IID_Ownership);
-			cmpNewOwnership.SetOwner(cmpOwnership.GetOwner());
-			
-			var cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
-			cmpPlayerStatisticsTracker.IncreaseTrainedUnitsCounter();
-
-			// Play a sound, but only for the first in the batch (to avoid nasty phasing effects)
-			if (spawnedEnts.length == 0)
-				PlaySound("trained", ent);
-			
-			this.entityCache.shift();
-			spawnedEnts.push(ent);
-		}
-	}
-
-	if (spawnedEnts.length > 0)
-	{
-		// If a rally point is set, walk towards it (in formation) using a suitable command based on where the 
-		// rally point is placed.
-		if (cmpRallyPoint)
-		{
-			var rallyPos = cmpRallyPoint.GetPosition();
-			if (rallyPos)
-			{
-				ProcessCommand(cmpOwnership.GetOwner(), GetRallyPointCommand(cmpRallyPoint, spawnedEnts));
-			}
-		}
-
-		Engine.PostMessage(this.entity, MT_TrainingFinished, {
-			"entities": spawnedEnts,
-			"owner": cmpOwnership.GetOwner(),
-			"metadata": metadata,
-		});
-	}
-	
-	return spawnedEnts.length;
-};
-
-/*
- * Increments progress on the first batch in the training queue, and blocks the
- * queue if population limit is reached or some units failed to spawn.
- */
-TrainingQueue.prototype.ProgressTimeout = function(data)
-{
-	// Allocate the 1000msecs to as many queue items as it takes
-	// until we've used up all the time (so that we work accurately
-	// with items that take fractions of a second)
-	var time = g_ProgressInterval;
-	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
-
-	while (time > 0 && this.queue.length)
-	{
-		var item = this.queue[0];
-		if (!item.trainingStarted)
-		{
-			// Batch's training hasn't started yet.
-			// Try to reserve the necessary population slots
-			if (!cmpPlayer.TryReservePopulationSlots(item.population * item.count))
-			{
-				// No slots available - don't train this batch now
-				// (we'll try again on the next timeout)
-
-				// Set flag that training queue is blocked
-				cmpPlayer.BlockTrainingQueue();
-				break;
-			}
-
-			// Unset flag that training queue is blocked
-			cmpPlayer.UnBlockTrainingQueue();
-
-			item.trainingStarted = true;
-		}
-
-		// If we won't finish the batch now, just update its timer
-		if (item.timeRemaining > time)
-		{
-			item.timeRemaining -= time;
-			break;
-		}
-
-		var numSpawned = this.SpawnUnits(item.template, item.count, item.metadata);
-		if (numSpawned == item.count)
-		{
-			// All entities spawned, this batch finished
-			cmpPlayer.UnReservePopulationSlots(item.population * numSpawned);
-			time -= item.timeRemaining;
-			this.queue.shift();
-			// Unset flag that training queue is blocked
-			cmpPlayer.UnBlockTrainingQueue();
-			this.spawnNotified = false;
-			Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });
-		}
-		else
-		{
-			if (numSpawned > 0)
-			{
-				// Only partially finished
-				cmpPlayer.UnReservePopulationSlots(item.population * numSpawned);
-				item.count -= numSpawned;
-				Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });
-			}
-
-			// Some entities failed to spawn
-			// Set flag that training queue is blocked
-			cmpPlayer.BlockTrainingQueue();
-			
-			if (!this.spawnNotified)
-			{
-				var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
-				var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained units" };
-				var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
-				cmpGUIInterface.PushNotification(notification);
-				this.spawnNotified = true;
-			}
-			break;
-		}
-	}
-
-	// If the queue's empty, delete the timer, else repeat it
-	if (this.queue.length == 0)
-	{
-		this.timer = undefined;
-
-		// Unset flag that training queue is blocked
-		// (This might happen when the player unqueues all batches)
-		cmpPlayer.UnBlockTrainingQueue();
-	}
-	else
-	{
-		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-		this.timer = cmpTimer.SetTimeout(this.entity, IID_TrainingQueue, "ProgressTimeout", g_ProgressInterval, data);
-	}
-}
-
-Engine.RegisterComponentType(IID_TrainingQueue, "TrainingQueue", TrainingQueue);
Index: binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js	(revision 11571)
+++ binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js	(working copy)
@@ -12,7 +12,7 @@
 Engine.LoadComponentScript("interfaces/ResourceDropsite.js");
 Engine.LoadComponentScript("interfaces/ResourceGatherer.js");
 Engine.LoadComponentScript("interfaces/ResourceSupply.js");
-Engine.LoadComponentScript("interfaces/TrainingQueue.js");
+Engine.LoadComponentScript("interfaces/ProductionQueue.js");
 Engine.LoadComponentScript("interfaces/Trader.js")
 Engine.LoadComponentScript("interfaces/Timer.js");
 Engine.LoadComponentScript("interfaces/StatisticsTracker.js");
@@ -58,7 +58,7 @@
 	GetPopulationLimit: function() { return 20; },
 	GetMaxPopulation: function() { return 200; },
 	GetResourceCounts: function() { return { food: 100 }; },
-	IsTrainingQueueBlocked: function() { return false; },
+	IsTrainingBlocked: function() { return false; },
 	GetState: function() { return "active"; },
 	GetTeam: function() { return -1; },
 	GetDiplomacy: function() { return [-1, 1]; },
@@ -105,7 +105,7 @@
 	GetPopulationLimit: function() { return 30; },
 	GetMaxPopulation: function() { return 300; },
 	GetResourceCounts: function() { return { food: 200 }; },
-	IsTrainingQueueBlocked: function() { return false; },
+	IsTrainingBlocked: function() { return false; },
 	GetState: function() { return "active"; },
 	GetTeam: function() { return -1; },
 	GetDiplomacy: function() { return [-1, 1]; },
@@ -157,7 +157,7 @@
 			popLimit: 20,
 			popMax: 200,
 			resourceCounts: { food: 100 },
-			trainingQueueBlocked: false,
+			trainingBlocked: false,
 			state: "active",
 			team: -1,
 			phase: "",
@@ -174,7 +174,7 @@
 			popLimit: 30,
 			popMax: 300,
 			resourceCounts: { food: 200 },
-			trainingQueueBlocked: false,
+			trainingBlocked: false,
 			state: "active",
 			team: -1,
 			phase: "village",
@@ -198,7 +198,7 @@
 			popLimit: 20,
 			popMax: 200,
 			resourceCounts: { food: 100 },
-			trainingQueueBlocked: false,
+			trainingBlocked: false,
 			state: "active",
 			team: -1,
 			phase: "",
@@ -231,7 +231,7 @@
 			popLimit: 30,
 			popMax: 300,
 			resourceCounts: { food: 200 },
-			trainingQueueBlocked: false,
+			trainingBlocked: false,
 			state: "active",
 			team: -1,
 			phase: "village",
Index: binaries/data/mods/public/simulation/components/Identity.js
===================================================================
--- binaries/data/mods/public/simulation/components/Identity.js	(revision 11571)
+++ binaries/data/mods/public/simulation/components/Identity.js	(working copy)
@@ -68,6 +68,11 @@
 		"<element name='Icon'>" +
 			"<text/>" +
 		"</element>" +
+	"</optional>" +
+	"<optional>" +
+		"<element name='RequiredTechnology' a:help='Optional name of a technology which must be researched before the entity can be produced'>" +
+			"<text/>" +
+		"</element>" +
 	"</optional>";
 
 
@@ -126,6 +131,6 @@
 Identity.prototype.GetSelectionGroupName = function()
 {
 	return (this.template.SelectionGroupName || "");
-}
+};
 
 Engine.RegisterComponentType(IID_Identity, "Identity", Identity);
Index: binaries/data/mods/public/simulation/components/AIProxy.js
===================================================================
--- binaries/data/mods/public/simulation/components/AIProxy.js	(revision 11571)
+++ binaries/data/mods/public/simulation/components/AIProxy.js	(working copy)
@@ -119,12 +119,12 @@
 	this.changes.unitAIOrderData = msg.to;
 };
 
-AIProxy.prototype.OnTrainingQueueChanged = function(msg)
+AIProxy.prototype.OnProductionQueueChanged = function(msg)
 {
 	this.NotifyChange();
 
-	var cmpTrainingQueue = Engine.QueryInterface(this.entity, IID_TrainingQueue);
-	this.changes.trainingQueue = cmpTrainingQueue.GetQueue();
+	var cmpProductionQueue = Engine.QueryInterface(this.entity, IID_ProductionQueue);
+	this.changes.trainingQueue = cmpProductionQueue.GetQueue();
 };
 
 AIProxy.prototype.OnGarrisonedUnitsChanged = function(msg)
@@ -206,11 +206,11 @@
 		ret.unitAIOrderData = cmpUnitAI.GetOrderData();
 	}
 
-	var cmpTrainingQueue = Engine.QueryInterface(this.entity, IID_TrainingQueue);
-	if (cmpTrainingQueue)
+	var cmpProductionQueue = Engine.QueryInterface(this.entity, IID_ProductionQueue);
+	if (cmpProductionQueue)
 	{
-		// Updated by OnTrainingQueueChanged
-		ret.trainingQueue = cmpTrainingQueue.GetQueue();
+		// Updated by OnProductionQueueChanged
+		ret.trainingQueue = cmpProductionQueue.GetQueue();
 	}
 
 	var cmpFoundation = Engine.QueryInterface(this.entity, IID_Foundation);
Index: binaries/data/mods/public/simulation/components/Player.js
===================================================================
--- binaries/data/mods/public/simulation/components/Player.js	(revision 11571)
+++ binaries/data/mods/public/simulation/components/Player.js	(working copy)
@@ -12,7 +12,7 @@
 	this.popUsed = 0; // population of units owned or trained by this player
 	this.popBonuses = 0; // sum of population bonuses of player's entities
 	this.maxPop = 300; // maximum population
-	this.trainingQueueBlocked = false; // indicates whether any training queue is currently blocked
+	this.trainingBlocked = false; // indicates whether any training queue is currently blocked
 	this.resourceCount = {
 		"food": 1000,	
 		"wood": 1000,	
@@ -104,19 +104,19 @@
 	return this.maxPop;
 };
 
-Player.prototype.IsTrainingQueueBlocked = function()
+Player.prototype.IsTrainingBlocked = function()
 {
-	return this.trainingQueueBlocked;
+	return this.trainingBlocked;
 };
 
-Player.prototype.BlockTrainingQueue = function()
+Player.prototype.BlockTraining = function()
 {
-	this.trainingQueueBlocked = true;
+	this.trainingBlocked = true;
 };
 
-Player.prototype.UnBlockTrainingQueue = function()
+Player.prototype.UnBlockTraining = function()
 {
-	this.trainingQueueBlocked = false;
+	this.trainingBlocked = false;
 };
 
 Player.prototype.SetResourceCounts = function(resources)
Index: binaries/data/mods/public/simulation/components/TechnologyManager.js
===================================================================
--- binaries/data/mods/public/simulation/components/TechnologyManager.js	(revision 0)
+++ binaries/data/mods/public/simulation/components/TechnologyManager.js	(revision 0)
@@ -0,0 +1,312 @@
+function TechnologyManager() {}
+
+TechnologyManager.prototype.Schema =
+	"<a:component type='system'/><empty/>";
+
+TechnologyManager.prototype.Init = function ()
+{
+	var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager);
+	this.allTechs = cmpTechTempMan.GetAllTechs();
+	this.researchedTechs = {}; // technologies which have been researched
+	this.inProgressTechs = {}; // technologies which are being researched currently
+	
+	// This stores the modifications to unit stats from researched technologies
+	// Example data: {"ResourceGatherer/Rates/food.grain": [ {"multiplier": 1.15, "affects": ["Female", "Infantry Swordsman"]},
+	//                                                      {"add": 2} ]}
+	this.modifications = {};
+	
+	this.typeCounts = {}; // stores the number of entities of each type 
+	this.classCounts = {}; // stores the number of entities of each Class
+	this.typeCountsByClass = {}; // stores the number of entities of each type for each class i.e.
+	                             // {"someClass": {"unit/spearman": 2, "unit/cav": 5} "someOtherClass":...}
+	
+	// Some technologies are automatically researched when their conditions are met.  They have no cost and are 
+	// researched instantly.  This allows civ bonuses and more complicated technologies.
+	this.autoResearchTech = {};
+	for (var key in this.allTechs)
+	{
+		if (this.allTechs[key].autoResearch)
+			this.autoResearchTech[key] = this.allTechs[key];
+	}
+	
+	this._UpdateAutoResearch();
+};
+
+// This function checks if the requirements of any autoresearch techs are met and if they are it researches them
+TechnologyManager.prototype._UpdateAutoResearch = function ()
+{
+	for (var key in this.autoResearchTech)
+	{
+		if (this.CanResearch(key))
+		{
+			delete this.autoResearchTech[key];
+			this.ResearchTechnology(key);
+			return; // We will have recursively handled any knock-on effects so can just return
+		}
+	}
+}
+
+TechnologyManager.prototype.GetTechnologyTemplate = function (tech)
+{
+	return this.allTechs[tech];
+};
+
+// This function checks an entity template to see if it's technology requirements have been met
+TechnologyManager.prototype.CanProduce = function (templateName)
+{
+	var cmpTempManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
+	var template = cmpTempManager.GetTemplate(templateName);
+	
+	if (template.Identity && template.Identity.RequiredTechnology)
+		return this.IsTechnologyResearched(template.Identity.RequiredTechnology);
+	else
+		return true; // If there is no required technology then this entity can be produced
+};
+
+TechnologyManager.prototype.IsTechnologyResearched = function (tech)
+{
+	return (this.researchedTechs[tech] !== undefined);
+};
+
+// Checks the requirements for a technology to see if it can be researched at the current time
+TechnologyManager.prototype.CanResearch = function (tech)
+{
+	var template = this.GetTechnologyTemplate(tech);
+	if (!template)
+	{
+		warn("Technology \"" + tech + "\" does not exist");
+		return false;
+	}
+	
+	var ret = true;
+	
+	// The technology which this technology supercedes is required
+	if (template.supercedes)
+		ret = ret && this.IsTechnologyResearched(template.supercedes);
+	
+	ret = ret && this._CheckTechnologyRequirements(template.requirements);
+	
+	return ret;
+};
+
+TechnologyManager.prototype._CheckTechnologyRequirements = function (reqs)
+{
+	// If there are no requirements then all requirements are met
+	if (!reqs)
+		return true;
+	
+	if (reqs.tech)
+	{
+		return this.IsTechnologyResearched(reqs.tech);
+	}
+	else if (reqs.all)
+	{
+		var ret = true;
+		for (var i = 0; i < reqs.all.length; i++)
+		{
+			ret = ret && this._CheckTechnologyRequirements(reqs.all[i]);
+		}
+		return ret;
+	}
+	else if (reqs.any)
+	{
+		for (var i = 0; i < reqs.any.length; i++)
+		{
+			if (this._CheckTechnologyRequirements(reqs.any[i]))
+				return true;
+		}
+		return false
+	}
+	else if (reqs["class"])
+	{
+		return (reqs.numberOfTypes <= Object.keys(this.typeCountsByClass[reqs["class"]]).length);
+	}
+	
+	// The technologies requirements are not a recognised format
+	error("Bad requirements " + uneval(reqs));
+	return false;
+};
+
+TechnologyManager.prototype.OnGlobalOwnershipChanged = function (msg)
+{
+	// This automatically updates typeCounts, classCounts and typeCountsByClass
+	var playerID = (Engine.QueryInterface(this.entity, IID_Player)).GetPlayerID();
+	if (msg.to == playerID)
+	{
+		var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
+		var template = cmpTemplateManager.GetCurrentTemplateName(msg.entity);
+		
+		this.typeCounts[template] = this.typeCounts[template] || 0;
+		this.typeCounts[template] += 1;
+		
+		// don't use foundations for the class counts
+		if (Engine.QueryInterface(msg.entity, IID_Foundation))
+			return;
+		
+		var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity);
+		if (cmpIdentity)
+		{
+			var classes = cmpIdentity.GetClassesList();
+			for (var i in classes)
+			{
+				this.classCounts[classes[i]] = this.classCounts[classes[i]] || 0;
+				this.classCounts[classes[i]] += 1;
+				
+				this.typeCountsByClass[classes[i]] = this.typeCountsByClass[classes[i]] || {};
+				this.typeCountsByClass[classes[i]][template] = this.typeCountsByClass[classes[i]][template] || 0;
+				this.typeCountsByClass[classes[i]][template] += 1;
+			}
+		}
+	}
+	if (msg.from == playerID)
+	{
+		var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
+		var template = cmpTemplateManager.GetCurrentTemplateName(msg.entity);
+		
+		this.typeCounts[template] -= 1;
+		
+		// don't use foundations for the class counts
+		if (Engine.QueryInterface(msg.entity, IID_Foundation))
+			return;
+		
+		var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity);
+		if (cmpIdentity)
+		{
+			var classes = cmpIdentity.GetClassesList();
+			for (var i in classes)
+			{
+				this.classCounts[classes[i]] -= 1;
+				
+				this.typeCountsByClass[classes[i]][template] -= 1;
+			}
+		}
+	}
+};
+	
+// Marks a technology as researched.  Note that this does not verify that the requirements are met.
+TechnologyManager.prototype.ResearchTechnology = function (tech)
+{
+	this.StoppedResearch(tech); // The tech is no longer being currently researched
+	
+	var template = this.GetTechnologyTemplate(tech);
+	if (template)
+	{
+		var modifiedComponents = {};
+		this.researchedTechs[tech] = template;
+		// store the modifications in an easy to access structure
+		if (template.modifications)
+		{
+			var affects = [];
+			if (template.affects && template.affects.length > 0)
+			{
+				for (var i in template.affects)
+				{
+					// Put the list of classes into an array for convenient access
+					affects.push(template.affects[i].split(" "));
+				}
+			}
+			else
+			{
+				affects.push([]);
+			}
+			
+			// We add an item to this.modifications for every 
+			for (var i in template.modifications)
+			{
+				var modification = template.modifications[i];
+				if (!this.modifications[modification.value])
+					this.modifications[modification.value] = [];
+				
+				var mod = {"affects": affects};
+				// copy the modification data into our new data structure
+				for (var j in modification)
+					if (j !== "value")
+						mod[j] = modification[j]
+				
+				this.modifications[modification.value].push(mod);
+				modifiedComponents[modification.value.split("/")[0]] = true;
+			}
+		}
+		
+		var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player);
+		var player = cmpPlayer.GetPlayerID();
+		
+		for (var component in modifiedComponents)
+			Engine.BroadcastMessage(MT_TechnologyModificationChange, { "component": component, "player": player });
+		
+		this._UpdateAutoResearch();
+	}
+	else
+	{
+		error("Tried to research invalid techonology: " + uneval(tech));
+	}
+};
+
+TechnologyManager.prototype.ApplyModifications = function(valueName, curValue, ent)
+{	
+	// Get all modifications to this value
+	var modifications = this.modifications[valueName];
+	if (!modifications) // no modifications so return the orignal value
+		return curValue;
+	
+	// Get the classes which this entity belongs to
+	var cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
+	var classes = cmpIdentity.GetClassesList();
+	
+	var retValue = +curValue;
+	
+	for (var i in modifications)
+	{
+		var modification = modifications[i];
+		var applies = false;
+		// See if any of the lists of classes matches this entity
+		for (var j in modification.affects)
+		{
+			var hasAllClasses = true;
+			// Check each 
+			for (var k in modification.affects[j])
+				hasAllClasses = hasAllClasses && (classes.indexOf(modification.affects[j][k]) !== -1);
+			
+			if (hasAllClasses)
+			{
+				applies = true;
+				break;
+			}
+		}
+		
+		// Nothing is cumulative so that ordering doesn't matter as much as possible
+		if (modification.multiplier)
+			retValue += (modification.multiplier - 1) * +curValue;
+		else if (modification.add)
+			retValue += modification.add;
+		else if (modification.replace) // This will depend on ordering because there is no choice
+			retValue = modification.replace;
+		else
+			warn("modification format not recognised (modifying " + valueName + "): " + uneval(modification));
+	}
+	
+	return retValue;
+};
+
+// Marks a technology as being currently researched
+TechnologyManager.prototype.StartedResearch = function (tech)
+{
+	this.inProgressTechs[tech] = true;
+};
+
+// Marks a technology as not being currently researched
+TechnologyManager.prototype.StoppedResearch = function (tech)
+{
+	delete this.inProgressTechs[tech];
+};
+
+// Checks whether a technology is being currently researched
+TechnologyManager.prototype.IsInProgress = function(tech)
+{
+	if (this.inProgressTechs[tech])
+		return true;
+	else
+		return false;
+};
+
+Engine.RegisterComponentType(IID_TechnologyManager, "TechnologyManager", TechnologyManager);
Index: binaries/data/mods/public/simulation/components/ProductionQueue.js
===================================================================
--- binaries/data/mods/public/simulation/components/ProductionQueue.js	(revision 11375)
+++ binaries/data/mods/public/simulation/components/ProductionQueue.js	(working copy)
@@ -1,23 +1,33 @@
 var g_ProgressInterval = 1000;
 const MAX_QUEUE_SIZE = 16;
 
-function TrainingQueue() {}
+function ProductionQueue() {}
 
-TrainingQueue.prototype.Schema =
-	"<a:help>Allows the building to train new units.</a:help>" +
+ProductionQueue.prototype.Schema =
+	"<a:help>Allows the building to train new units and research technologies.</a:help>" +
 	"<a:example>" +
 		"<Entities datatype='tokens'>" +
 			"\n    units/{civ}_support_female_citizen\n    units/{civ}_support_trader\n    units/celt_infantry_spearman_b\n  " +
 		"</Entities>" +
 	"</a:example>" +
-	"<element name='Entities' a:help='Space-separated list of entity template names that this building can train. The special string \"{civ}\" will be automatically replaced by the building&apos;s four-character civ code'>" +
-		"<attribute name='datatype'>" +
-			"<value>tokens</value>" +
-		"</attribute>" +
-		"<text/>" +
-	"</element>";
+	"<optional>" + 
+		"<element name='Entities' a:help='Space-separated list of entity template names that this building can train. The special string \"{civ}\" will be automatically replaced by the building&apos;s four-character civ code'>" +
+			"<attribute name='datatype'>" +
+				"<value>tokens</value>" +
+			"</attribute>" +
+			"<text/>" +
+		"</element>" +
+	"</optional>" + 
+	"<optional>" + 
+		"<element name='Technologies' a:help='Space-separated list of technology names that this building can research.'>" +
+			"<attribute name='datatype'>" +
+				"<value>tokens</value>" +
+			"</attribute>" +
+			"<text/>" +
+		"</element>" +
+	"</optional>";
 
-TrainingQueue.prototype.Init = function()
+ProductionQueue.prototype.Init = function()
 {
 	this.nextID = 1;
 
@@ -26,14 +36,24 @@
 	//   {
 	//     "id": 1,
 	//     "player": 1, // who paid for this batch; we need this to cope with refunds cleanly
-	//     "template": "units/example",
+	//     "unitTemplate": "units/example",
 	//     "count": 10,
 	//     "resources": { "wood": 100, ... },	// resources per unit, multiply by count to get total
 	//     "population": 1,	// population per unit, multiply by count to get total
-	//     "trainingStarted": false, // true iff we have reserved population
+	//     "productionStarted": false, // true iff we have reserved population
 	//     "timeTotal": 15000, // msecs
 	//     "timeRemaining": 10000, // msecs
 	//   }
+	//   
+	//   {
+	//     "id": 1,
+	//     "player": 1, // who paid for this research; we need this to cope with refunds cleanly
+	//     "technologyTemplate": "example_tech",
+	//     "resources": { "wood": 100, ... },	// resources needed for research
+	//     "productionStarted": false, // true iff production has started
+	//     "timeTotal": 15000, // msecs
+	//     "timeRemaining": 10000, // msecs
+	//   }
 	
 	this.timer = undefined; // g_ProgressInterval msec timer, active while the queue is non-empty
 	
@@ -44,8 +64,11 @@
 /*
  * Returns list of entities that can be trained by this building.
  */
-TrainingQueue.prototype.GetEntitiesList = function()
+ProductionQueue.prototype.GetEntitiesList = function()
 {
+	if (!this.template.Entities)
+		return [];
+	
 	var string = this.template.Entities._string;
 	
 	// Replace the "{civ}" codes with this entity's civ ID
@@ -57,10 +80,56 @@
 };
 
 /*
- * Adds a new batch of identical units to the training queue.
+ * Returns list of technologies that can be researched by this building.
  */
-TrainingQueue.prototype.AddBatch = function(templateName, count, metadata)
+ProductionQueue.prototype.GetTechnologiesList = function()
 {
+	if (!this.template.Technologies)
+		return [];
+	
+	var string = this.template.Technologies._string;
+	
+	var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager);
+	if (!cmpTechMan)
+		return [];
+	
+	var techs = string.split(/\s+/);
+	var ret = [];
+	var superceded = {}; // Stores the tech which supercedes the key 
+	
+	// Add any top level technologies to an array which corresponds to the displayed icons
+	// Also store the "children" for the superceding, 
+	for (var i in techs)
+	{
+		var tech = techs[i];
+		var template = cmpTechMan.GetTechnologyTemplate(tech);
+		if (!template.supercedes || techs.indexOf(template.supercedes) === -1)
+			ret.push(tech);
+		else
+			superceded[template.supercedes] = tech;
+	}
+	
+	// Now make researched/in progress techs invisible
+	for (var i in ret)
+	{
+		var tech = ret[i];
+		while (cmpTechMan.IsTechnologyResearched(tech) || cmpTechMan.IsInProgress(tech))
+		{
+			tech = superceded[tech];
+		}
+
+		
+		ret[i] = tech;
+	}
+	
+	return ret;
+};
+
+/*
+ * Adds a new batch of identical units to train or a technology to research to the production queue.
+ */
+ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadata)
+{
 	// TODO: there should probably be a limit on the number of queued batches
 	// TODO: there should be a way for the GUI to determine whether it's going
 	// to be possible to add a batch (based on resource costs and length limits)
@@ -68,62 +137,106 @@
 
 	if (this.queue.length < MAX_QUEUE_SIZE)
 	{
-		// Find the template data so we can determine the build costs
-		var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
-		var template = cmpTempMan.GetTemplate(templateName);
-		if (!template)
-			return;
+		
+		if (type == "unit")
+		{
+			// Find the template data so we can determine the build costs
+			var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
+			var template = cmpTempMan.GetTemplate(templateName);
+			if (!template)
+				return;
+			
+			// Apply a time discount to larger batches.
+			// TODO: work out what equation we should use here.
+			var timeMult = Math.pow(count, 0.7);
 
-		// Apply a time discount to larger batches.
-		// TODO: work out what equation we should use here.
-		var timeMult = Math.pow(count, 0.7);
+			var time = timeMult * template.Cost.BuildTime;
 
-		var time = timeMult * template.Cost.BuildTime;
+			var totalCosts = {};
+			for each (var r in ["food", "wood", "stone", "metal"])
+				totalCosts[r] = Math.floor(count * template.Cost.Resources[r]);
 
-		var totalCosts = {};
-		for each (var r in ["food", "wood", "stone", "metal"])
-			totalCosts[r] = Math.floor(count * template.Cost.Resources[r]);
+			var population = template.Cost.Population;
+		
+			// TrySubtractResources should report error to player (they ran out of resources)
+			if (!cmpPlayer.TrySubtractResources(totalCosts))
+				return;
 
-		var population = template.Cost.Population;
-	
-		// TrySubtractResources should report error to player (they ran out of resources)
-		if (!cmpPlayer.TrySubtractResources(totalCosts))
+			this.queue.push({
+				"id": this.nextID++,
+				"player": cmpPlayer.GetPlayerID(),
+				"unitTemplate": templateName,
+				"count": count,
+				"metadata": metadata,
+				"resources": deepcopy(template.Cost.Resources), // need to copy to avoid serialization problems
+				"population": population,
+				"productionStarted": false,
+				"timeTotal": time*1000,
+				"timeRemaining": time*1000,
+			});
+		}
+		else if (type == "technology")
+		{
+			// Load the technology template
+			var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager);
+			var template = cmpTechTempMan.GetTemplate(templateName);
+			if (!template)
+				return;
+			
+			var time = template.researchTime;
+
+			var cost = {};
+			for each (var r in ["food", "wood", "stone", "metal"])
+				cost[r] = Math.floor(template.cost[r]);
+			
+			// TrySubtractResources should report error to player (they ran out of resources)
+			if (!cmpPlayer.TrySubtractResources(cost))
+				return;
+			
+			// Tell the technology manager that we have started researching this so that people can't research the same 
+			// thing twice.
+			var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager);
+			cmpTechMan.StartedResearch(templateName);
+
+			this.queue.push({
+				"id": this.nextID++,
+				"player": cmpPlayer.GetPlayerID(),
+				"count": 1,
+				"technologyTemplate": templateName,
+				"resources": deepcopy(template.cost), // need to copy to avoid serialization problems
+				"productionStarted": false,
+				"timeTotal": time*1000,
+				"timeRemaining": time*1000,
+			});
+		}
+		else
+		{
+			warn("Tried to add invalid item of type \"" + type + "\" and template \"" + templateName + "\" to a production queue");
 			return;
+		}
+		
+		Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { });
 
-		this.queue.push({
-			"id": this.nextID++,
-			"player": cmpPlayer.GetPlayerID(),
-			"template": templateName,
-			"count": count,
-			"metadata": metadata,
-			"resources": deepcopy(template.Cost.Resources), // need to copy to avoid serialization problems
-			"population": population,
-			"trainingStarted": false,
-			"timeTotal": time*1000,
-			"timeRemaining": time*1000,
-		});
-		Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });
-
 		// If this is the first item in the queue, start the timer
 		if (!this.timer)
 		{
 			var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-			this.timer = cmpTimer.SetTimeout(this.entity, IID_TrainingQueue, "ProgressTimeout", g_ProgressInterval, {});
+			this.timer = cmpTimer.SetTimeout(this.entity, IID_ProductionQueue, "ProgressTimeout", g_ProgressInterval, {});
 		}
 	}
 	else
 	{
-		var notification = {"player": cmpPlayer.GetPlayerID(), "message": "The training queue is full."};
+		var notification = {"player": cmpPlayer.GetPlayerID(), "message": "The production queue is full."};
 		var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
 		cmpGUIInterface.PushNotification(notification);
 	}
 };
 
 /*
- * Removes an existing batch of units from the training queue.
+ * Removes an existing batch of units from the production queue.
  * Refunds resource costs and population reservations.
  */
-TrainingQueue.prototype.RemoveBatch = function(id)
+ProductionQueue.prototype.RemoveBatch = function(id)
 {
 	// Destroy any cached entities (those which didn't spawn for some reason)
 	for (var i = 0; i < this.entityCache.length; ++i)
@@ -139,40 +252,48 @@
 			continue;
 
 		// Now we've found the item to remove
-
+		
 		var cmpPlayer = QueryPlayerIDInterface(item.player, IID_Player);
 
 		// Refund the resource cost for this batch
 		var totalCosts = {};
 		for each (var r in ["food", "wood", "stone", "metal"])
 			totalCosts[r] = Math.floor(item.count * item.resources[r]);
-			
+		
 		cmpPlayer.AddResources(totalCosts);
-
+		
 		// Remove reserved population slots if necessary
-		if (item.trainingStarted)
+		if (item.productionStarted && item.unitTemplate)
 			cmpPlayer.UnReservePopulationSlots(item.population * item.count);
-
+		
+		// Mark the research as stopped if we cancel it
+		if (item.technologyTemplate)
+		{
+			var cmpTechMan = QueryOwnerInterface(this.entity, IID_TechnologyManager);
+			cmpTechMan.StoppedResearch(item.technologyTemplate);
+		}
+		
 		// Remove from the queue
 		// (We don't need to remove the timer - it'll expire if it discovers the queue is empty)
 		this.queue.splice(i, 1);
-		Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });
+		Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { });
 
 		return;
 	}
 };
 
 /*
- * Returns basic data from all batches in the training queue.
+ * Returns basic data from all batches in the production queue.
  */
-TrainingQueue.prototype.GetQueue = function()
+ProductionQueue.prototype.GetQueue = function()
 {
 	var out = [];
 	for each (var item in this.queue)
 	{
 		out.push({
 			"id": item.id,
-			"template": item.template,
+			"unitTemplate": item.unitTemplate,
+			"technologyTemplate": item.technologyTemplate,
 			"count": item.count,
 			"progress": 1-(item.timeRemaining/item.timeTotal),
 			"metadata": item.metadata,
@@ -184,9 +305,9 @@
 /*
  * Removes all existing batches from the queue.
  */
-TrainingQueue.prototype.ResetQueue = function()
+ProductionQueue.prototype.ResetQueue = function()
 {
-	// Empty the training queue and refund all the resource costs
+	// Empty the production queue and refund all the resource costs
 	// to the player. (This is to avoid players having to micromanage their
 	// buildings' queues when they're about to be destroyed or captured.)
 
@@ -194,17 +315,17 @@
 		this.RemoveBatch(this.queue[0].id);
 };
 
-TrainingQueue.prototype.OnOwnershipChanged = function(msg)
+ProductionQueue.prototype.OnOwnershipChanged = function(msg)
 {
 	if (msg.from != -1)
 	{
-		// Unset flag that previous owner's training queue may be blocked
+		// Unset flag that previous owner's training may be blocked
 		var cmpPlayer = QueryPlayerIDInterface(msg.from, IID_Player);
 		if (cmpPlayer && this.queue.length > 0)
-			cmpPlayer.UnBlockTrainingQueue();
+			cmpPlayer.UnBlockTraining();
 	}
 
-	// Reset the training queue whenever the owner changes.
+	// Reset the production queue whenever the owner changes.
 	// (This should prevent players getting surprised when they capture
 	// an enemy building, and then loads of the enemy's civ's soldiers get
 	// created from it. Also it means we don't have to worry about
@@ -212,7 +333,7 @@
 	this.ResetQueue();
 };
 
-TrainingQueue.prototype.OnDestroy = function()
+ProductionQueue.prototype.OnDestroy = function()
 {
 	// Reset the queue to refund any resources
 	this.ResetQueue();
@@ -228,7 +349,7 @@
  * This function creates the entities and places them in world if possible.
  * returns the number of successfully spawned entities.
  */
-TrainingQueue.prototype.SpawnUnits = function(templateName, count, metadata)
+ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata)
 {
 	var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint);
 	var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
@@ -302,10 +423,10 @@
 };
 
 /*
- * Increments progress on the first batch in the training queue, and blocks the
+ * Increments progress on the first batch in the production queue, and blocks the
  * queue if population limit is reached or some units failed to spawn.
  */
-TrainingQueue.prototype.ProgressTimeout = function(data)
+ProductionQueue.prototype.ProgressTimeout = function(data)
 {
 	// Allocate the 1000msecs to as many queue items as it takes
 	// until we've used up all the time (so that we work accurately
@@ -316,24 +437,28 @@
 	while (time > 0 && this.queue.length)
 	{
 		var item = this.queue[0];
-		if (!item.trainingStarted)
+		if (!item.productionStarted)
 		{
-			// Batch's training hasn't started yet.
-			// Try to reserve the necessary population slots
-			if (!cmpPlayer.TryReservePopulationSlots(item.population * item.count))
+			// If the item is a unit then do population checks
+			if (item.unitTemplate)
 			{
-				// No slots available - don't train this batch now
-				// (we'll try again on the next timeout)
+				// Batch's training hasn't started yet.
+				// Try to reserve the necessary population slots
+				if (item.unitTemplate && !cmpPlayer.TryReservePopulationSlots(item.population * item.count))
+				{
+					// No slots available - don't train this batch now
+					// (we'll try again on the next timeout)
 
-				// Set flag that training queue is blocked
-				cmpPlayer.BlockTrainingQueue();
-				break;
+					// Set flag that training is blocked
+					cmpPlayer.BlockTraining();
+					break;
+				}
+				
+				// Unset flag that training is blocked
+				cmpPlayer.UnBlockTraining();
 			}
 
-			// Unset flag that training queue is blocked
-			cmpPlayer.UnBlockTrainingQueue();
-
-			item.trainingStarted = true;
+			item.productionStarted = true;
 		}
 
 		// If we won't finish the batch now, just update its timer
@@ -343,42 +468,53 @@
 			break;
 		}
 
-		var numSpawned = this.SpawnUnits(item.template, item.count, item.metadata);
-		if (numSpawned == item.count)
+		if (item.unitTemplate)
 		{
-			// All entities spawned, this batch finished
-			cmpPlayer.UnReservePopulationSlots(item.population * numSpawned);
-			time -= item.timeRemaining;
-			this.queue.shift();
-			// Unset flag that training queue is blocked
-			cmpPlayer.UnBlockTrainingQueue();
-			this.spawnNotified = false;
-			Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });
-		}
-		else
-		{
-			if (numSpawned > 0)
+			var numSpawned = this.SpawnUnits(item.unitTemplate, item.count, item.metadata);
+			if (numSpawned == item.count)
 			{
-				// Only partially finished
+				// All entities spawned, this batch finished
 				cmpPlayer.UnReservePopulationSlots(item.population * numSpawned);
-				item.count -= numSpawned;
-				Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { });
+				time -= item.timeRemaining;
+				this.queue.shift();
+				// Unset flag that training is blocked
+				cmpPlayer.UnBlockTraining();
+				this.spawnNotified = false;
+				Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { });
 			}
+			else
+			{
+				if (numSpawned > 0)
+				{
+					// Only partially finished
+					cmpPlayer.UnReservePopulationSlots(item.population * numSpawned);
+					item.count -= numSpawned;
+					Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { });
+				}
 
-			// Some entities failed to spawn
-			// Set flag that training queue is blocked
-			cmpPlayer.BlockTrainingQueue();
-			
-			if (!this.spawnNotified)
-			{
-				var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
-				var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained units" };
-				var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
-				cmpGUIInterface.PushNotification(notification);
-				this.spawnNotified = true;
+				// Some entities failed to spawn
+				// Set flag that training is blocked
+				cmpPlayer.BlockTraining();
+				
+				if (!this.spawnNotified)
+				{
+					var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+					var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained units" };
+					var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
+					cmpGUIInterface.PushNotification(notification);
+					this.spawnNotified = true;
+				}
+				break;
 			}
-			break;
 		}
+		else if (item.technologyTemplate)
+		{
+			var cmpTechnologyManager = QueryOwnerInterface(this.entity, IID_TechnologyManager);
+			cmpTechnologyManager.ResearchTechnology(item.technologyTemplate);
+			
+			this.queue.shift();
+			Engine.PostMessage(this.entity, MT_ProductionQueueChanged, { });
+		}
 	}
 
 	// If the queue's empty, delete the timer, else repeat it
@@ -386,15 +522,15 @@
 	{
 		this.timer = undefined;
 
-		// Unset flag that training queue is blocked
+		// Unset flag that training is blocked
 		// (This might happen when the player unqueues all batches)
-		cmpPlayer.UnBlockTrainingQueue();
+		cmpPlayer.UnBlockTraining();
 	}
 	else
 	{
 		var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
-		this.timer = cmpTimer.SetTimeout(this.entity, IID_TrainingQueue, "ProgressTimeout", g_ProgressInterval, data);
+		this.timer = cmpTimer.SetTimeout(this.entity, IID_ProductionQueue, "ProgressTimeout", g_ProgressInterval, data);
 	}
 }
 
-Engine.RegisterComponentType(IID_TrainingQueue, "TrainingQueue", TrainingQueue);
+Engine.RegisterComponentType(IID_ProductionQueue, "ProductionQueue", ProductionQueue);
Index: binaries/data/mods/public/simulation/components/TechnologyTemplateManager.js
===================================================================
--- binaries/data/mods/public/simulation/components/TechnologyTemplateManager.js	(revision 0)
+++ binaries/data/mods/public/simulation/components/TechnologyTemplateManager.js	(revision 0)
@@ -0,0 +1,39 @@
+/**
+ * System component which loads the technology data files
+ */
+function TechnologyTemplateManager() {}
+
+TechnologyTemplateManager.prototype.Schema =
+	"<a:component type='system'/><empty/>";
+	
+TechnologyTemplateManager.prototype.Init = function()
+{
+	this.allTechs = {};
+	var techNames = this.ListAllTechs();
+	for (i in techNames)
+		this.GetTemplate(techNames[i]);
+};
+
+TechnologyTemplateManager.prototype.GetTemplate = function(template)
+{
+	if (!this.allTechs[template])
+	{
+		this.allTechs[template] = Engine.ReadJSONFile("technologies/" + template + ".json");
+		if (! this.allTechs[template])
+			error("Failed to load technology \"" + template + "\"");
+	}
+	
+	return this.allTechs[template];
+};
+
+TechnologyTemplateManager.prototype.ListAllTechs = function()
+{
+	return Engine.FindAllTechnologyTemplates();
+}
+
+TechnologyTemplateManager.prototype.GetAllTechs = function()
+{
+	return this.allTechs;
+}
+
+Engine.RegisterComponentType(IID_TechnologyTemplateManager, "TechnologyTemplateManager", TechnologyTemplateManager);
\ No newline at end of file
Index: binaries/data/mods/public/simulation/ai/common-api/base.js
===================================================================
--- binaries/data/mods/public/simulation/ai/common-api/base.js	(revision 11571)
+++ binaries/data/mods/public/simulation/ai/common-api/base.js	(working copy)
@@ -43,7 +43,7 @@
 // CCmpTemplateManager::CopyFoundationSubset and only includes components
 // that our EntityTemplate class currently uses.)
 var g_FoundationForbiddenComponents = {
-	"TrainingQueue": 1,
+	"ProductionQueue": 1,
 	"ResourceSupply": 1,
 	"ResourceDropsite": 1,
 	"GarrisonHolder": 1,
Index: binaries/data/mods/public/simulation/ai/common-api/entity.js
===================================================================
--- binaries/data/mods/public/simulation/ai/common-api/entity.js	(revision 11571)
+++ binaries/data/mods/public/simulation/ai/common-api/entity.js	(working copy)
@@ -126,10 +126,10 @@
 	},
 
 	trainableEntities: function() {
-		if (!this._template.TrainingQueue)
+		if (!this._template.ProductionQueue)
 			return undefined;
 		var civ = this.civ();
-		var templates = this._template.TrainingQueue.Entities._string.replace(/\{civ\}/g, civ).split(/\s+/);
+		var templates = this._template.ProductionQueue.Entities._string.replace(/\{civ\}/g, civ).split(/\s+/);
 		return templates;
 	},
 
Index: binaries/data/mods/public/simulation/ai/common-api-v2/base.js
===================================================================
--- binaries/data/mods/public/simulation/ai/common-api-v2/base.js	(revision 11571)
+++ binaries/data/mods/public/simulation/ai/common-api-v2/base.js	(working copy)
@@ -44,7 +44,7 @@
 // CCmpTemplateManager::CopyFoundationSubset and only includes components
 // that our EntityTemplate class currently uses.)
 var g_FoundationForbiddenComponents = {
-	"TrainingQueue": 1,
+	"ProductionQueue": 1,
 	"ResourceSupply": 1,
 	"ResourceDropsite": 1,
 	"GarrisonHolder": 1,
Index: binaries/data/mods/public/simulation/ai/common-api-v2/entity.js
===================================================================
--- binaries/data/mods/public/simulation/ai/common-api-v2/entity.js	(revision 11571)
+++ binaries/data/mods/public/simulation/ai/common-api-v2/entity.js	(working copy)
@@ -127,10 +127,10 @@
 	},
 
 	trainableEntities: function() {
-		if (!this._template.TrainingQueue)
+		if (!this._template.ProductionQueue)
 			return undefined;
 		var civ = this.civ();
-		var templates = this._template.TrainingQueue.Entities._string.replace(/\{civ\}/g, civ).split(/\s+/);
+		var templates = this._template.ProductionQueue.Entities._string.replace(/\{civ\}/g, civ).split(/\s+/);
 		return templates;
 	},
 
Index: binaries/data/mods/public/simulation/data/technologies/town_phase.json
===================================================================
--- binaries/data/mods/public/simulation/data/technologies/town_phase.json	(revision 0)
+++ binaries/data/mods/public/simulation/data/technologies/town_phase.json	(revision 0)
@@ -0,0 +1,11 @@
+{
+	"genericName": "Town Phase",
+	"description": "Advances from a small village to a bustling town, ready to expand rapidly.",
+	"cost": { "food": 100, "wood": 100, "stone": 0, "metal": 50 },
+	"requirements": { "class": "Village", "numberOfTypes": 2 },
+	"requirementsTooltip": "Requires two village structures",
+	"supercedes": "village_phase",
+	"icon": "technologies/town_phase.png",
+	"researchTime": 10,
+	"tooltip": "Advance to Town Phase"
+}
Index: binaries/data/mods/public/simulation/data/technologies/city_phase.json
===================================================================
--- binaries/data/mods/public/simulation/data/technologies/city_phase.json	(revision 0)
+++ binaries/data/mods/public/simulation/data/technologies/city_phase.json	(revision 0)
@@ -0,0 +1,11 @@
+{
+	"genericName": "City Phase",
+	"specificName": "Generic Specific City Name",
+	"specificName_hele": "Greek City",
+	"description": "Advances from a bustling town to a veritable metropolis, full of the wonders of modern technology.",
+	"cost": {"food": 0, "wood": 0, "stone": 50, "metal": 0},
+	"supercedes": "town_phase",
+	"icon": "technologies/city_phase.png",
+	"researchTime": 10,
+	"tooltip": "Advance to City Phase"
+}
Index: binaries/data/mods/public/simulation/data/technologies/plough.json
===================================================================
--- binaries/data/mods/public/simulation/data/technologies/plough.json	(revision 0)
+++ binaries/data/mods/public/simulation/data/technologies/plough.json	(revision 0)
@@ -0,0 +1,12 @@
+{
+	"genericName": "Plough",
+	"description": "A horse drawn instrument to turn the sod",
+	"cost": {"food": 0, "wood": 0, "stone": 0, "metal": 0},
+	"requirements": {"tech": "town_phase"},
+	"requirementsTooltip": "Requires Town Phase",
+	"icon": "technologies/plough.png",
+	"researchTime": 10,
+	"tooltip": "Discover the Plough",
+	"modifications": [{"value": "ResourceGatherer/Rates/food.grain", "multiplier": 15}],
+	"affects": ["Female"]
+}
Index: binaries/data/mods/public/simulation/data/technologies/village_phase.json
===================================================================
--- binaries/data/mods/public/simulation/data/technologies/village_phase.json	(revision 0)
+++ binaries/data/mods/public/simulation/data/technologies/village_phase.json	(revision 0)
@@ -0,0 +1,8 @@
+{
+	"genericName": "Village Phase",
+	"description": "Advances from a small village to a bustling town, ready to expand rapidly.",
+	"autoResearch": true,
+	"icon": "technologies/town_phase.png",
+	"researchTime": 10,
+	"tooltip": "Advance to Town Phase"
+}
Index: binaries/data/mods/public/simulation/templates/special/player.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/special/player.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/special/player.xml	(working copy)
@@ -10,4 +10,5 @@
   </BuildLimits>
   <Player/>
   <StatisticsTracker/>
+  <TechnologyManager/>
 </Entity>
Index: binaries/data/mods/public/simulation/templates/structures/celt_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/celt_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/celt_dock.xml	(working copy)
@@ -15,11 +15,11 @@
   <Obstruction>
     <Static width="10.0" depth="22.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/celt_ship_trireme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/celts/dock_new.xml</Actor>
     <FoundationActor>structures/fndn_celt_dock.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/rome_army_camp.xml	(working copy)
@@ -68,7 +68,7 @@
     <HealthDecayRate>5</HealthDecayRate>
   </TerritoryDecay>
   <TerritoryInfluence disable=""/>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/rome_infantry_swordsman_b
       units/rome_infantry_spearman_a
@@ -78,7 +78,7 @@
 	  units/rome_mechanical_siege_scorpio
 	  units/rome_mechanical_siege_ram
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <Vision>
     <Range>60</Range>
   </Vision>
@@ -86,4 +86,4 @@
     <FoundationActor>structures/fndn_8x8.xml</FoundationActor>
     <Actor>structures/romans/camp.xml</Actor>
   </VisualActor>
-</Entity>
\ No newline at end of file
+</Entity>
Index: binaries/data/mods/public/simulation/templates/structures/hele_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/hele_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/hele_civil_centre.xml	(working copy)
@@ -11,13 +11,13 @@
     <SpecificName>Agorā́</SpecificName>
     <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_infantry_spearman_b
       units/hele_infantry_javelinist_b
       units/hele_cavalry_javelinist_b
 	</Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/civic_centre_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/mace_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/mace_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/mace_barracks.xml	(working copy)
@@ -15,7 +15,7 @@
     <SpecificName>Stratēgeîon</SpecificName>
     <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/mace_infantry_spearman_b
       units/mace_infantry_javelinist_b
@@ -24,7 +24,7 @@
       units/mace_cavalry_spearman_b
       units/mace_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/barracks.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/pers_apadana.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/pers_apadana.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/pers_apadana.xml	(working copy)
@@ -32,14 +32,14 @@
     <Root>true</Root>
     <Radius>38</Radius>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
 	  units/pers_hero_cyrus
 	  units/pers_hero_darius
 	  units/pers_hero_xerxes
       units/pers_champion_infantry
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/persians/sb1_new.xml</Actor>
     <FoundationActor>structures/fndn_6x6.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/iber_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/iber_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/iber_corral.xml	(working copy)
@@ -12,11 +12,11 @@
   <Obstruction>
     <Static width="14.0" depth="14.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/iberians/corral.xml</Actor>
     <FoundationActor>structures/fndn_4x4.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/pers_stables.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/pers_stables.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/pers_stables.xml	(working copy)
@@ -25,14 +25,14 @@
   <Obstruction>
     <Static width="18.0" depth="16.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/pers_cavalry_spearman_b
       units/pers_cavalry_swordsman_b
       units/pers_cavalry_javelinist_b
 	  units/pers_cavalry_archer_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/persians/stables.xml</Actor>
     <FoundationActor>structures/fndn_4x4.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/rome_civil_centre.xml	(working copy)
@@ -12,13 +12,13 @@
   <Obstruction>
     <Static width="37.0" depth="37.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/rome_infantry_swordsman_b
       units/rome_infantry_javelinist_b
       units/rome_cavalry_spearman_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <FoundationActor>structures/fndn_8x8.xml</FoundationActor>
     <Actor>structures/romans/civic_centre.xml</Actor>
Index: binaries/data/mods/public/simulation/templates/structures/spart_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/spart_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/spart_corral.xml	(working copy)
@@ -18,11 +18,11 @@
   <Obstruction>
     <Static width="14.0" depth="14.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/corral.xml</Actor>
     <FoundationActor>structures/fndn_3x3.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/athen_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/athen_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/athen_dock.xml	(working copy)
@@ -11,12 +11,12 @@
     <SpecificName>Limḗn</SpecificName>
     <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/athen_ship_bireme
       units/athen_ship_trireme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/athenians/dock.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/rome_corral.xml	(working copy)
@@ -12,12 +12,12 @@
   <Obstruction>
     <Static width="14" depth="20"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
       gaia/fauna_sheep
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <FoundationActor>structures/fndn_2x4.xml</FoundationActor>
     <Actor>structures/romans/corral.xml</Actor>
Index: binaries/data/mods/public/simulation/templates/structures/spart_syssiton.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/spart_syssiton.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/spart_syssiton.xml	(working copy)
@@ -33,12 +33,12 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_hero_leonidas
       units/spart_champion_infantry_spear
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/gymnasion.xml</Actor>
     <FoundationActor>structures/fndn_6x6.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_super_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_super_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_super_dock.xml	(working copy)
@@ -46,13 +46,13 @@
   </Sound>
   <TerritoryDecay disable=""/>
   <TerritoryInfluence disable=""/>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_ship_bireme
       units/cart_ship_trireme
       units/cart_ship_quinquereme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <Vision>
     <Range>100</Range>
   </Vision>
Index: binaries/data/mods/public/simulation/templates/structures/iber_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/iber_fortress.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/iber_fortress.xml	(working copy)
@@ -19,7 +19,7 @@
   <Obstruction>
     <Static width="27.0" depth="27.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/iber_hero_caros
       units/iber_hero_indibil
@@ -28,7 +28,7 @@
       units/iber_champion_cavalry
 	  units/iber_mechanical_siege_ram
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/iberians/fortress.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/pers_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/pers_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/pers_corral.xml	(working copy)
@@ -18,11 +18,11 @@
   <Obstruction>
     <Static width="17.0" depth="11.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/persians/corral.xml</Actor>
     <FoundationActor>structures/fndn_4x2.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/celt_fortress_b.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/celt_fortress_b.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/celt_fortress_b.xml	(working copy)
@@ -29,7 +29,7 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/celt_hero_boudicca
       units/celt_hero_caratacos
@@ -38,7 +38,7 @@
       units/celt_champion_infantry_brit
 	  units/celt_mechanical_siege_ram
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <Vision>
     <Range>100</Range>
   </Vision>
Index: binaries/data/mods/public/simulation/templates/structures/spart_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/spart_fortress.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/spart_fortress.xml	(working copy)
@@ -19,11 +19,11 @@
   <Obstruction>
     <Static width="24.0" depth="26.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/spart_mechanical_siege_ram
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/fortress_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/athen_gymnasion.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/athen_gymnasion.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/athen_gymnasion.xml	(working copy)
@@ -33,12 +33,12 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/athen_champion_infantry
       units/athen_champion_ranged
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/athenians/gymnasion.xml</Actor>
     <FoundationActor>structures/fndn_6x6.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_corral.xml	(working copy)
@@ -12,11 +12,11 @@
   <Obstruction>
     <Static width="16.0" depth="14.5"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/corral.xml</Actor>
     <FoundationActor>structures/fndn_3x3.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/pers_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/pers_fortress.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/pers_fortress.xml	(working copy)
@@ -12,12 +12,12 @@
     <History>The Susa Chateau was a fortress in the administrative capital of Susa, which was reconstructed by a French archaeologist in 1890 with the use of original building material.</History>
 	<Tooltip>Train Champion Units and Construct Siege Rams.</Tooltip>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/pers_champion_cavalry
 	  units/pers_mechanical_siege_ram
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/persians/fortress.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/mace_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/mace_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/mace_dock.xml	(working copy)
@@ -11,12 +11,12 @@
     <SpecificName>Limḗn</SpecificName>
     <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_ship_bireme
       units/hele_ship_trireme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/dock.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/iber_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/iber_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/iber_civil_centre.xml	(working copy)
@@ -5,13 +5,13 @@
     <SpecificName>Oppidum</SpecificName>
     <History>The Oppidum, plural Oppida (oh-PEE-dah), has a long history in the Iberian Peninsula. They were walled towns, dating back to even before the time period of the game and expanding greatly during it. They were usually built upon heights for better defensive purposes but sometimes right out on the plains, especially in the east where there may not have been heights at desirable locations near meandering rivers. This concept drawing is derived from an actual archeological site that has been excavated in the northeast of Spain having belonged to the Ilergete (ee-layer-HAY-tay) tribe as shown in the figure below and from the virtual reconstruction of the site at the museum located adjacent to it.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/iber_infantry_swordsman_b
       units/iber_infantry_javelinist_b
       units/iber_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/iberians/civil_centre.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/spart_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/spart_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/spart_civil_centre.xml	(working copy)
@@ -11,13 +11,13 @@
     <SpecificName>Agorā́</SpecificName>
     <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/spart_infantry_spearman_b
       units/spart_infantry_javelinist_b
       units/spart_cavalry_javelinist_b
 	</Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/civic_centre_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_fortress.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_fortress.xml	(working copy)
@@ -13,7 +13,7 @@
   <Obstruction>
     <Static width="26.0" depth="28.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_hero_hamilcar
       units/cart_hero_hannibal
@@ -22,7 +22,7 @@
       units/cart_mechanical_siege_ballista
       units/cart_mechanical_siege_oxybeles
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/fortress.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/hele_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/hele_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/hele_barracks.xml	(working copy)
@@ -15,7 +15,7 @@
     <SpecificName>Stratēgeîon</SpecificName>
     <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_infantry_spearman_b
       units/hele_infantry_javelinist_b
@@ -24,7 +24,7 @@
       units/hele_cavalry_swordsman_b
       units/hele_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/barracks.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/pers_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/pers_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/pers_civil_centre.xml	(working copy)
@@ -12,13 +12,13 @@
     <SpecificName>Xsacapava</SpecificName>
     <History>Possibly of Median origin, the word 'satrapy' means province. Soon after coming to the throne, Darius the Great carried out a vast administrative reform, dividing the huge empire into 20 satrapies governed by satraps.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/pers_infantry_spearman_b
       units/pers_infantry_archer_b
       units/pers_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/persians/civil_centre.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/hele_gymnasion.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/hele_gymnasion.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/hele_gymnasion.xml	(working copy)
@@ -33,14 +33,14 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_champion_cavalry_mace
       units/hele_champion_infantry_mace
       units/hele_champion_infantry_polis
       units/hele_champion_swordsman_polis
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/gymnasion.xml</Actor>
     <FoundationActor>structures/fndn_6x6.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_embassy_iberian.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_embassy_iberian.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_embassy_iberian.xml	(working copy)
@@ -17,13 +17,13 @@
   <Obstruction>
     <Static width="16.0" depth="16.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_infantry_javelinist_b
       units/cart_infantry_slinger_b
       units/cart_cavalry_swordsman_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/embassy_iberian.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_embassy_italiote.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_embassy_italiote.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_embassy_italiote.xml	(working copy)
@@ -20,12 +20,12 @@
   <Obstruction>
     <Static width="11.0" depth="14.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_infantry_swordsman_2_b
       units/cart_cavalry_spearman_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/embassy_italiote.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/celt_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/celt_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/celt_civil_centre.xml	(working copy)
@@ -12,13 +12,13 @@
   <Obstruction>
     <Static width="25.0" depth="25.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/celt_infantry_spearman_b
       units/celt_infantry_javelinist_b
       units/celt_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/celts/civic_centre.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_civil_centre.xml	(working copy)
@@ -5,13 +5,13 @@
     <SpecificName>Merkāz</SpecificName>
     <History>Carthiginian's History</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_infantry_spearman_b
       units/cart_infantry_archer_b
       units/cart_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/civil_centre.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/athen_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/athen_fortress.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/athen_fortress.xml	(working copy)
@@ -19,12 +19,12 @@
   <Obstruction>
     <Static width="24.0" depth="26.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/athen_mechanical_siege_oxybeles
       units/athen_mechanical_siege_lithobolos
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/athenians/fortress.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_fortress.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/rome_fortress.xml	(working copy)
@@ -5,7 +5,7 @@
     <SpecificName>Castellum</SpecificName>
     <History>Fortified auxillary camp.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/rome_hero_marcellus
       units/rome_hero_maximus
@@ -16,7 +16,7 @@
 	  units/rome_mechanical_siege_scorpio
 	  units/rome_mechanical_siege_ram
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/romans/fortress.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/mace_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/mace_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/mace_corral.xml	(working copy)
@@ -18,11 +18,11 @@
   <Obstruction>
     <Static width="14.0" depth="14.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/corral.xml</Actor>
     <FoundationActor>structures/fndn_3x3.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/hele_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/hele_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/hele_dock.xml	(working copy)
@@ -11,12 +11,12 @@
     <SpecificName>Limḗn</SpecificName>
     <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_ship_bireme
       units/hele_ship_trireme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/dock.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/pers_sb2.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/pers_sb2.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/pers_sb2.xml	(working copy)
@@ -40,13 +40,13 @@
     <Root>false</Root>
     <Radius>38</Radius>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
 	  units/pers_kardakes_hoplite
 	  units/pers_kardakes_skirmisher
 	  units/pers_war_elephant
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/persians/sb2.xml</Actor>
     <FoundationActor>structures/fndn_6x6.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/athen_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/athen_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/athen_civil_centre.xml	(working copy)
@@ -11,13 +11,13 @@
     <SpecificName>Agorā́</SpecificName>
     <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/athen_infantry_spearman_b
       units/athen_infantry_slinger_b
       units/athen_cavalry_javelinist_b
 	</Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/athenians/civic_centre_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/iber_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/iber_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/iber_barracks.xml	(working copy)
@@ -11,7 +11,7 @@
     <SpecificName>Cuartel</SpecificName>
     <History>To the best of our knowledge, the Iberians did not have standing armies in the sense that we know of them elsewhere or of today, it is doubtful that they had specific structures designated as military centres; however as a game construct we show a modest structure wherein military related activities take place.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/iber_infantry_spearman_b
       units/iber_infantry_swordsman_b
@@ -20,7 +20,7 @@
       units/iber_cavalry_spearman_b
       units/iber_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/iberians/barracks.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/mace_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/mace_fortress.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/mace_fortress.xml	(working copy)
@@ -19,7 +19,7 @@
   <Obstruction>
     <Static width="24.0" depth="26.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/mace_hero_philip
       units/mace_hero_alexander
@@ -30,7 +30,7 @@
       units/mace_mechanical_siege_lithobolos
       units/mace_mechanical_siege_tower
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/fortress_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/spart_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/spart_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/spart_barracks.xml	(working copy)
@@ -15,14 +15,14 @@
     <SpecificName>Stratēgeîon</SpecificName>
     <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/spart_infantry_spearman_b
       units/spart_champion_infantry_sword
       units/spart_infantry_javelinist_b
       units/spart_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/barracks.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/rome_dock.xml	(working copy)
@@ -12,13 +12,13 @@
   <Obstruction>
     <Static width="20.0" depth="24.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/rome_ship_bireme
       units/rome_ship_trireme
       units/rome_ship_quinquereme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/romans/dock.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/pers_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/pers_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/pers_barracks.xml	(working copy)
@@ -17,13 +17,13 @@
 	<Tooltip>Levy citizen-infantry units.</Tooltip>
     <Icon>structures/pers_barracks.png</Icon>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/pers_infantry_spearman_b
       units/pers_infantry_javelinist_b
 	  units/pers_infantry_archer_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/persians/barracks.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/celt_kennel.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/celt_kennel.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/celt_kennel.xml	(working copy)
@@ -40,11 +40,11 @@
     <Radius>20</Radius>
     <Weight>65536</Weight>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/celt_war_dog_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/celts/kennel.xml</Actor>
     <FoundationActor>structures/fndn_2x2.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/celt_fortress_g.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/celt_fortress_g.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/celt_fortress_g.xml	(working copy)
@@ -16,7 +16,7 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/celt_hero_brennus
       units/celt_hero_britomartus
@@ -25,7 +25,7 @@
       units/celt_champion_infantry_gaul
 	  units/celt_mechanical_siege_ram
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/celts/fortress_gallic.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/celt_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/celt_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/celt_corral.xml	(working copy)
@@ -12,11 +12,11 @@
   <Obstruction>
     <Static width="10.0" depth="20.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_sheep
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/celts/plot_corral.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/mace_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/mace_civil_centre.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/mace_civil_centre.xml	(working copy)
@@ -11,13 +11,13 @@
     <SpecificName>Agorā́</SpecificName>
     <History>The most important place in most Classical Greek poleis, the Agora served many purposes; it was a place for public speeches and was the stage for civic life and commercial interests.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/mace_infantry_spearman_b
       units/mace_infantry_javelinist_b
       units/mace_cavalry_spearman_b
 	</Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/civic_centre_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/celt_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/celt_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/celt_barracks.xml	(working copy)
@@ -14,7 +14,7 @@
   <Obstruction>
     <Static width="20.0" depth="20.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/celt_infantry_spearman_b
       units/celt_infantry_javelinist_b
@@ -22,7 +22,7 @@
       units/celt_cavalry_swordsman_b
       units/celt_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/celts/barracks_new.xml</Actor>
     <FoundationActor>structures/fndn_5x5.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_barracks.xml	(working copy)
@@ -19,13 +19,13 @@
   <Obstruction>
     <Static width="22.0" depth="23.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_infantry_spearman_b
       units/cart_infantry_archer_b
 	  units/cart_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/barracks.xml</Actor>
     <FoundationActor>structures/fndn_5x5.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/hele_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/hele_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/hele_corral.xml	(working copy)
@@ -18,11 +18,11 @@
   <Obstruction>
     <Static width="14.0" depth="14.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/corral.xml</Actor>
     <FoundationActor>structures/fndn_3x3.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/iber_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/iber_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/iber_dock.xml	(working copy)
@@ -12,11 +12,11 @@
   <Obstruction>
     <Static width="14.0" depth="24.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/iber_ship_fire
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/iberians/dock.xml</Actor>
     <FoundationActor>structures/fndn_dock_iber.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/hele_prytaneion.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/hele_prytaneion.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/hele_prytaneion.xml	(working copy)
@@ -34,7 +34,7 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_hero_alexander
       units/hele_hero_demetrius
@@ -43,7 +43,7 @@
       units/hele_hero_themistocles
       units/hele_hero_xenophon
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/tholos.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/spart_gerousia.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/spart_gerousia.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/spart_gerousia.xml	(working copy)
@@ -34,11 +34,11 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_hero_leonidas
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/tholos.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/spart_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/spart_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/spart_dock.xml	(working copy)
@@ -11,12 +11,12 @@
     <SpecificName>Limḗn</SpecificName>
     <History>Greece is a sea country, which is why some of the greatest Hellenic and Hellenistic cities like Ephesus, Corinth, Alexandria and Antioch were built by the sea. It should also be noted that all colonies during the Great Colonisation were thriving port centres, which traded with the local population.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/spart_ship_bireme
       units/spart_ship_trireme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/dock.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_temple.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_temple.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_temple.xml	(working copy)
@@ -18,11 +18,11 @@
   <Obstruction>
     <Static width="17.0" depth="30.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_champion_infantry
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/temple_big.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_embassy_celtic.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_embassy_celtic.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_embassy_celtic.xml	(working copy)
@@ -24,12 +24,12 @@
   <Obstruction>
     <Static width="15.0" depth="12.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_infantry_swordsman_b
       units/cart_cavalry_swordsman_2_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/embassy_celtic.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/athen_corral.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/athen_corral.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/athen_corral.xml	(working copy)
@@ -18,11 +18,11 @@
   <Obstruction>
     <Static width="14.0" depth="14.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       gaia/fauna_goat
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/athenians/corral.xml</Actor>
     <FoundationActor>structures/fndn_3x3.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/structures/hele_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/hele_fortress.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/hele_fortress.xml	(working copy)
@@ -19,13 +19,13 @@
   <Obstruction>
     <Static width="24.0" depth="26.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/hele_mechanical_siege_oxybeles
       units/hele_mechanical_siege_lithobolos
       units/hele_mechanical_siege_tower
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/hellenes/fortress_new.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/athen_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/athen_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/athen_barracks.xml	(working copy)
@@ -15,7 +15,7 @@
     <SpecificName>Stratēgeîon</SpecificName>
     <History>The Stratigeion was the main military headquarters, where important decisions were taken and plans for battles discussed by the Hellene Generals, or "Strategoi".</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/athen_infantry_spearman_b
       units/athen_infantry_javelinist_b
@@ -23,7 +23,7 @@
       units/athen_cavalry_swordsman_b
       units/athen_cavalry_javelinist_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/athenians/barracks.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/athen_prytaneion.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/athen_prytaneion.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/athen_prytaneion.xml	(working copy)
@@ -34,13 +34,13 @@
       <death>attack/destruction/building_collapse_large.xml</death>
     </SoundGroups>
   </Sound>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/athen_hero_themistocles
       units/athen_hero_pericles
       units/athen_hero_xenophon
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/athenians/prytaneion.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/pers_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/pers_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/pers_dock.xml	(working copy)
@@ -18,12 +18,12 @@
   <Obstruction>
     <Static width="23.0" depth="15.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/pers_ship_bireme
       units/pers_ship_trireme
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/persians/dock.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/structures/rome_barracks.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/rome_barracks.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/rome_barracks.xml	(working copy)
@@ -18,14 +18,14 @@
   <Obstruction>
     <Static width="24.0" depth="24.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/rome_infantry_swordsman_b
       units/rome_infantry_spearman_a
       units/rome_infantry_javelinist_b
       units/rome_cavalry_spearman_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <FoundationActor>structures/fndn_5x5.xml</FoundationActor>
     <Actor>structures/romans/barracks.xml</Actor>
Index: binaries/data/mods/public/simulation/templates/structures/cart_embassy.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/cart_embassy.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/structures/cart_embassy.xml	(working copy)
@@ -21,7 +21,7 @@
   <Obstruction>
     <Static width="28.0" depth="28.0"/>
   </Obstruction>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_infantry_swordsman_b
       units/cart_infantry_javelinist_b
@@ -29,7 +29,7 @@
       units/cart_cavalry_swordsman_b
       units/cart_cavalry_spearman_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/carthaginians/embassy.xml</Actor>
     <FoundationActor>structures/fndn_5x5.xml</FoundationActor>
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	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml	(working copy)
@@ -62,6 +62,7 @@
 		CivCentre
 	</Classes>
     <Icon>structures/civic_centre.png</Icon>
+	<RequiredTechnology>town_phase</RequiredTechnology>
   </Identity>
   <Loot>
     <xp>200</xp>
@@ -89,11 +90,16 @@
     <Radius>180</Radius>
     <Weight>65536</Weight>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/{civ}_support_female_citizen
     </Entities>
-  </TrainingQueue>
+    <Technologies datatype="tokens">
+      town_phase
+	  city_phase
+	  plough
+    </Technologies>
+  </ProductionQueue>
   <Vision>
     <Range>90</Range>
   </Vision>
Index: binaries/data/mods/public/simulation/templates/units/pers_infantry_spearman_b.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/units/pers_infantry_spearman_b.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/units/pers_infantry_spearman_b.xml	(working copy)
@@ -23,6 +23,7 @@
     <SpecificName>Mada Sparabara</SpecificName>
     <Icon>units/pers_infantry_spearman.png</Icon>
     <History>Mede Shieldbearers comprised the main infantry regiment of the Persians during this period, especially in the reign of Xerxes. First under the Medes and later the Achaemenids these soldiers were the bread and butter infantry for hand-to-hand engagement. Within the Satabam, the basic tactical unit of the Achamenid army, the shieldbearers formed the first two ranks, protecting the arhcers and also serving as a way to keep the enemy pinned down until the cavalry could act. While well known for tenacity the shieldbearers were not equipped to last long in an extended melee with heavy infantry, like hoplites. </History>
+    <RequiredTechnology>town_phase</RequiredTechnology>
   </Identity>
   <Promotion>
     <Entity>units/pers_infantry_spearman_a</Entity>
Index: binaries/data/mods/public/simulation/templates/units/pers_hero_cyrus.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/units/pers_hero_cyrus.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/units/pers_hero_cyrus.xml	(working copy)
@@ -9,11 +9,11 @@
 Hero Aura: "Lead from the Front." Boosts attack of nearby cavalry units.</Tooltip>
     <History>(559 BC - 530 BC) The son of a Median princess and the ruler of Anshan; justly called the 'Father of the Empire', Cyrus the Great conquered Media, Lydia, Babylonia and Bactria, thereby establishing the Persian Empire. He was also renown as a benevolent conqueror. Technically the second ruler of the Persians by that name, and so appears as Kurush II on his documents and coins. Kurush I was his grandfather.</History>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/pers_champion_infantry
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>units/persians/hero_cyrus.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/units/athen_ship_trireme.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/units/athen_ship_trireme.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/units/athen_ship_trireme.xml	(working copy)
@@ -9,11 +9,11 @@
     <History>The first Triremes were built circa 650BC, and by 500BC the Trireme was the most widely used heavy warship of the Greek city-states. In the Trireme the outriggers were now an integral part of the ship's hull. The Trireme also had a partial or full fighting deck above the rowers. The length of the Trireme remained approximately 35-38 meters, and the beam was approximately 3.5 metres. A Trireme carried 170 oarsmen, plus twenty sailors and fourteen marines in Greek navies. The top speed of a Trireme was approximately 11.5 knots. Some Triremes may have been able to reach higher speeds in short bursts. A Trireme travelling from Athens to Mitylene in 427BC made the 350 kilometre trip in only 24 hours, averaging eight knots (14.6 km/h). The Trireme could accelerate much faster than a Bireme or Penteconter, and was much more manoeuvrable. This gave the Trireme an advantage in combat, where higher speed and manoeuvrability meant a better chance of victory.</History>
     <Icon>units/hele_ship_trireme.png</Icon>
   </Identity>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/athen_champion_marine
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/athenians/trireme.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml	(working copy)
@@ -49,11 +49,11 @@
     <Radius>40</Radius>
     <Weight>65536</Weight>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/{civ}_support_trader
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <Vision>
     <Range>32</Range>
   </Vision>
Index: binaries/data/mods/public/simulation/templates/other/celt_homestead.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/celt_homestead.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/other/celt_homestead.xml	(working copy)
@@ -35,13 +35,13 @@
   <ResourceDropsite>
     <Types>food wood stone metal</Types>
   </ResourceDropsite>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/celt_cavalry_javelinist_b
       units/celt_infantry_javelinist_b
       units/celt_infantry_spearman_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <TerritoryInfluence>
     <Radius>100</Radius>
     <Weight>65536</Weight>
Index: binaries/data/mods/public/simulation/templates/other/celt_tavern.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/celt_tavern.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/other/celt_tavern.xml	(working copy)
@@ -39,11 +39,11 @@
     <Radius>32</Radius>
     <Weight>65536</Weight>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/celt_fanatic
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>structures/celts/tavern.xml</Actor>
     <FoundationActor>structures/fndn_4x4.xml</FoundationActor>
Index: binaries/data/mods/public/simulation/templates/other/pers_inn.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/pers_inn.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/other/pers_inn.xml	(working copy)
@@ -21,11 +21,11 @@
   <TerritoryInfluence>
     <Radius>26</Radius>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/{civ}_support_female_citizen
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>props/structures/persians/alt_building_04.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/other/hellenic_royal_stoa.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/hellenic_royal_stoa.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/other/hellenic_royal_stoa.xml	(working copy)
@@ -48,13 +48,13 @@
     <Radius>40</Radius>
     <Weight>65536</Weight>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/thrace_black_cloak
 	  units/mace_thorakites
 	  units/mace_thureophoros
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <Vision>
     <Range>40</Range>
     <RetainInFog>true</RetainInFog>
Index: binaries/data/mods/public/simulation/templates/other/pers_apartment_block.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/pers_apartment_block.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/other/pers_apartment_block.xml	(working copy)
@@ -21,11 +21,11 @@
   <TerritoryInfluence>
     <Radius>25</Radius>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/{civ}_support_female_citizen
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <VisualActor>
     <Actor>props/structures/persians/alt_building_03.xml</Actor>
   </VisualActor>
Index: binaries/data/mods/public/simulation/templates/other/cart_tophet.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/other/cart_tophet.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/other/cart_tophet.xml	(working copy)
@@ -34,11 +34,11 @@
     <Static width="22.0" depth="24.0"/>
   </Obstruction>
   <TerritoryDecay disable=""/>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/cart_sacred_band_cavalry
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <Vision>
     <Range>40</Range>
   </Vision>
Index: binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml	(working copy)
@@ -63,11 +63,11 @@
     <Radius>40</Radius>
     <Weight>65536</Weight>
   </TerritoryInfluence>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/{civ}_support_healer_b
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <Vision>
     <Range>40</Range>
   </Vision>
Index: binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml	(revision 11571)
+++ binaries/data/mods/public/simulation/templates/template_structure_military_dock.xml	(working copy)
@@ -57,12 +57,12 @@
     </SoundGroups>
   </Sound>
   <TerritoryDecay disable=""/>
-  <TrainingQueue>
+  <ProductionQueue>
     <Entities datatype="tokens">
       units/{civ}_ship_fishing
       units/{civ}_ship_merchant
     </Entities>
-  </TrainingQueue>
+  </ProductionQueue>
   <Vision>
     <Range>40</Range>
   </Vision>
