Index: binaries/data/mods/public/simulation/components/TechnologyManager.js
===================================================================
--- binaries/data/mods/public/simulation/components/TechnologyManager.js	(revision 14908)
+++ binaries/data/mods/public/simulation/components/TechnologyManager.js	(working copy)
@@ -373,9 +373,9 @@
 		this.modificationCache[valueName][ent] = {"origValue": curValue};
 		var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
 		var templateName = cmpTemplateManager.GetCurrentTemplateName(ent);
-		// Ensure that preview entites have the same properties as the final building
-		if (templateName.indexOf("preview|") != -1)
-			templateName = templateName.slice(8);
+		// Ensure that preview or construction entites have the same properties as the final building
+		if (templateName.indexOf("preview|") > -1 || templateName.indexOf("construction|") > -1 )
+			templateName = templateName.slice(templateName.indexOf("|") + 1);
 		this.modificationCache[valueName][ent].newValue = GetTechModifiedProperty(this.modifications, cmpTemplateManager.GetTemplate(templateName), valueName, curValue);
 	}
 	
Index: binaries/data/mods/public/simulation/data/technologies/phase_town.json
===================================================================
--- binaries/data/mods/public/simulation/data/technologies/phase_town.json	(revision 14908)
+++ binaries/data/mods/public/simulation/data/technologies/phase_town.json	(working copy)
@@ -2,7 +2,7 @@
 	"genericName": "Town Phase",
 	"requirements": { "any": [{"tech":"phase_town_generic"}, {"tech":"phase_town_athen"}]},
 	"autoResearch": true,
-	"modifications": [{"value": "TerritoryInfluence/Radius", "multiply": 1.30}],
+	"modifications": [{"value": "TerritoryInfluence/Radius", "multiply": 1.30},{"value": "VisualActor/Actor", "replace":"structures/athenians/gymnasion.xml"}],
 	"affects": ["CivCentre"],
 	"soundComplete": "interface/alarm/alarm_phase.xml"
 }
Index: source/simulation2/components/CCmpVisualActor.cpp
===================================================================
--- source/simulation2/components/CCmpVisualActor.cpp	(revision 14908)
+++ source/simulation2/components/CCmpVisualActor.cpp	(working copy)
@@ -30,6 +30,7 @@
 #include "ICmpTemplateManager.h"
 #include "ICmpTerrain.h"
 #include "ICmpUnitMotion.h"
+#include "ICmpValueModificationManager.h"
 #include "ICmpVision.h"
 
 #include "graphics/Decal.h"
@@ -57,6 +58,7 @@
 		componentManager.SubscribeToMessageType(MT_Interpolate);
 		componentManager.SubscribeToMessageType(MT_RenderSubmit);
 		componentManager.SubscribeToMessageType(MT_OwnershipChanged);
+		componentManager.SubscribeToMessageType(MT_ValueModification);
 		componentManager.SubscribeGloballyToMessageType(MT_TerrainChanged);
 	}
 
@@ -63,7 +65,8 @@
 	DEFAULT_COMPONENT_ALLOCATOR(VisualActor)
 
 private:
-	std::wstring m_ActorName;
+	std::wstring m_BaseActorName, m_ActorName;
+	bool m_IsFoundationActor;
 	CUnit* m_Unit;
 
 	fixed m_R, m_G, m_B; // shading colour
@@ -188,10 +191,11 @@
 
 		m_Seed = GetEntityId();
 
-		if (paramNode.GetChild("Foundation").IsOk() && paramNode.GetChild("FoundationActor").IsOk())
-			m_ActorName = paramNode.GetChild("FoundationActor").ToString();
+		m_IsFoundationActor = paramNode.GetChild("Foundation").IsOk() && paramNode.GetChild("FoundationActor").IsOk();
+		if (m_IsFoundationActor)
+			m_BaseActorName = m_ActorName = paramNode.GetChild("FoundationActor").ToString();
 		else
-			m_ActorName = paramNode.GetChild("Actor").ToString();
+			m_BaseActorName = m_ActorName = paramNode.GetChild("Actor").ToString();
 
 		m_VisibleInAtlasOnly = paramNode.GetChild("VisibleInAtlasOnly").ToBool();
 		m_IsActorOnly = paramNode.GetChild("ActorOnly").IsOk();
@@ -228,6 +232,7 @@
 
 		serialize.NumberU32_Unbounded("seed", m_Seed);
 		// TODO: variation/selection strings
+		serialize.String("actor", m_ActorName, 0, 256);
 
 		serialize.NumberFixed_Unbounded("constructionprogress", m_ConstructionProgress);
 
@@ -240,7 +245,7 @@
 
 		if (serialize.IsDebug())
 		{
-			serialize.String("actor", m_ActorName, 0, 256);
+			serialize.String("base actor", m_BaseActorName, 0, 256);
 		}
 
 		SerializeCommon(serialize);
@@ -254,8 +259,8 @@
 
 		SerializeCommon(deserialize);
 
-		// If we serialized a different seed, reload actor
-		if (oldSeed != GetActorSeed())
+		// If we serialized a different seed or different actor, reload actor
+		if (oldSeed != GetActorSeed() || m_BaseActorName != m_ActorName)
 			ReloadActor();
 
 		fixed repeattime = m_AnimSyncRepeatTime; // save because SelectAnimation overwrites it
@@ -313,7 +318,25 @@
 			m_Unit->GetModel().SetTerrainDirty(msgData.i0, msgData.j0, msgData.i1, msgData.j1);
 			break;
 		}
+		case MT_ValueModification:
+		{
+			const CMessageValueModification& msgData = static_cast<const CMessageValueModification&> (msg);
+			if (msgData.component != L"VisualActor")
+				break;
+			CmpPtr<ICmpValueModificationManager> cmpValueModificationManager(GetSystemEntity());
+			std::wstring newActorName;
+			if (m_IsFoundationActor)
+				newActorName = cmpValueModificationManager->ApplyModifications(L"VisualActor/FoundationActor", m_BaseActorName, GetEntityId());
+			else
+				newActorName = cmpValueModificationManager->ApplyModifications(L"VisualActor/Actor", m_BaseActorName, GetEntityId());
+			if (newActorName != m_ActorName)
+			{
+				m_ActorName = newActorName;
+				ReloadActor();
+			}
+			break;
 		}
+		}
 	}
 
 	virtual CBoundingBoxAligned GetBounds()
@@ -519,7 +542,10 @@
 	if (GetSimContext().HasUnitManager())
 	{
 		std::set<CStr> selections;
-		m_Unit = GetSimContext().GetUnitManager().CreateUnit(m_ActorName, GetActorSeed(), selections);
+		std::wstring actorName = m_ActorName;
+		if (actorName.find(L".xml") == std::wstring::npos)
+			actorName += L".xml";
+		m_Unit = GetSimContext().GetUnitManager().CreateUnit(actorName, GetActorSeed(), selections);
 		if (m_Unit)
 		{
 			CModelAbstract& model = m_Unit->GetModel();
@@ -637,7 +663,10 @@
 		return;
 
 	std::set<CStr> selections;
-	CUnit* newUnit = GetSimContext().GetUnitManager().CreateUnit(m_ActorName, GetActorSeed(), selections);
+	std::wstring actorName = m_ActorName;
+	if (actorName.find(L".xml") == std::wstring::npos)
+		actorName += L".xml";
+	CUnit* newUnit = GetSimContext().GetUnitManager().CreateUnit(actorName, GetActorSeed(), selections);
 
 	if (!newUnit)
 		return;
Index: source/simulation2/components/ICmpValueModificationManager.cpp
===================================================================
--- source/simulation2/components/ICmpValueModificationManager.cpp	(revision 14908)
+++ source/simulation2/components/ICmpValueModificationManager.cpp	(working copy)
@@ -39,6 +39,11 @@
 	{
 		return m_Script.Call<u32>("ApplyModifications", valueName, currentValue, entity);
 	}
+
+	virtual std::wstring ApplyModifications(std::wstring valueName, std::wstring currentValue, entity_id_t entity)
+	{
+		return m_Script.Call<std::wstring>("ApplyModifications", valueName, currentValue, entity);
+	}
 };
 
 REGISTER_COMPONENT_SCRIPT_WRAPPER(ValueModificationManagerScripted)
Index: source/simulation2/components/ICmpValueModificationManager.h
===================================================================
--- source/simulation2/components/ICmpValueModificationManager.h	(revision 14908)
+++ source/simulation2/components/ICmpValueModificationManager.h	(working copy)
@@ -32,6 +32,7 @@
 public:
 	virtual fixed ApplyModifications(std::wstring valueName, fixed currentValue, entity_id_t entity) = 0;
 	virtual u32 ApplyModifications(std::wstring valueName, u32 currentValue, entity_id_t entity) = 0;
+	virtual std::wstring ApplyModifications(std::wstring valueName, std::wstring currentValue, entity_id_t entity) = 0;
 
 	DECLARE_INTERFACE_TYPE(ValueModificationManager)
 };
