Index: binaries/data/mods/public/gui/gamesetup/gamesetup.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/gamesetup.js	(revision 14088)
+++ binaries/data/mods/public/gui/gamesetup/gamesetup.js	(working copy)
@@ -4,8 +4,8 @@
 const DEFAULT_OFFLINE_MAP = "Acropolis 01";
 
 // TODO: Move these somewhere like simulation\data\game_types.json, Atlas needs them too
-const VICTORY_TEXT = ["Conquest", "None"];
-const VICTORY_DATA = ["conquest", "endless"];
+const VICTORY_TEXT = ["Conquest", "Wonder", "None"];
+const VICTORY_DATA = ["conquest", "wonder", "endless"];
 const VICTORY_DEFAULTIDX = 0;
 const POPULATION_CAP = ["50", "100", "150", "200", "250", "300", "Unlimited"];
 const POPULATION_CAP_DATA = [50, 100, 150, 200, 250, 300, 10000];
Index: binaries/data/mods/public/gui/session/messages.js
===================================================================
--- binaries/data/mods/public/gui/session/messages.js	(revision 14088)
+++ binaries/data/mods/public/gui/session/messages.js	(working copy)
@@ -136,12 +136,17 @@
 	var messages = [];
 	for each (var n in notifications)
 		messages.push(n.message);
-	getGUIObjectByName("notificationText").caption = messages.join("\n");
-}
-
-// Returns [username, playercolor] for the given player
-function getUsernameAndColor(player)
-{
+	getGUIObjectByName("notificationText").caption = messages.join("\n");
+}
+
+function updateTimeNotifications()
+{
+	getGUIObjectByName("timeNotificationText").caption = Engine.GuiInterfaceCall("GetTimeNotificationText");
+}
+
+// Returns [username, playercolor] for the given player
+function getUsernameAndColor(player)
+{
 	// This case is hit for AIs, whose names don't exist in playerAssignments.
 	var color = g_Players[player].color;
 	return [
Index: binaries/data/mods/public/gui/session/session.js
===================================================================
--- binaries/data/mods/public/gui/session/session.js	(revision 14088)
+++ binaries/data/mods/public/gui/session/session.js	(working copy)
@@ -440,6 +440,7 @@
 	updateResearchDisplay();
 	updateBuildingPlacementPreview();
 	updateTimeElapsedCounter();
+	updateTimeNotifications();	
 
 	// Update music state on basis of battle state.
 	var battleState = Engine.GuiInterfaceCall("GetBattleState", Engine.GetPlayerID());
Index: binaries/data/mods/public/gui/session/session.xml
===================================================================
--- binaries/data/mods/public/gui/session/session.xml	(revision 14088)
+++ binaries/data/mods/public/gui/session/session.xml	(working copy)
@@ -346,7 +346,11 @@
 	<object name="notificationPanel" type="image" size="50%-300 60 50%+300 120" ghost="true">
 	    <object name="notificationText" size="0 0 100% 100%" type="text" style="notificationPanel" ghost="true"/>
 	</object>
+	<object name="timeNotificationPanel" type="image" size="100%-600 60 100%-20 120" ghost="true">
+	    <object name="timeNotificationText" size="0 0 100% 100%" type="text" style="notificationPanel" ghost="true"/>
+	</object>
 
+
 	<!-- ================================  ================================ -->
 	<!-- Chat -->
 	<!-- ================================  ================================ -->
Index: binaries/data/mods/public/simulation/components/EndGameManager.js
===================================================================
--- binaries/data/mods/public/simulation/components/EndGameManager.js	(revision 14088)
+++ binaries/data/mods/public/simulation/components/EndGameManager.js	(working copy)
@@ -31,6 +31,29 @@
 	this.alliedVictory = flag;
 };
 
+EndGameManager.prototype.RegisterWonder = function(entity)
+{
+	if (this.gameType != "wonder")
+		return;
+
+	var cmpWon = QueryOwnerInterface(entity, IID_Player);
+	cmpWon.SetState("won");
+	
+	var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
+	var numPlayers = cmpPlayerManager.GetNumPlayers();
+	for (var i = 1; i < numPlayers; i++)
+	{
+		var playerEntityId = cmpPlayerManager.GetPlayerByID(i);
+		var cmpPlayer = Engine.QueryInterface(playerEntityId, IID_Player);
+		if (cmpPlayer.GetState() != "active")
+			continue;
+		if (this.alliedVictory && cmpPlayer.IsMutualAlly(cmpWon.GetPlayerID()))
+			cmpPlayer.SetState("won")
+		else
+			Engine.PostMessage(playerEntityId, MT_PlayerDefeated, { "playerId": i } );
+	}
+};
+
 EndGameManager.prototype.PlayerLostAllConquestCriticalEntities = function(playerID)
 {
 	if (this.gameType == "endless")
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js	(revision 14088)
+++ binaries/data/mods/public/simulation/components/GuiInterface.js	(working copy)
@@ -22,6 +22,8 @@
 	this.placementWallLastAngle = 0;
 	this.notifications = [];
 	this.renamedEntities = [];
+	this.timeNotificationID = 1;
+	this.timeNotifications = [];
 };
 
 /*
@@ -691,7 +693,56 @@
 	return cmpPlayer.GetNeededResources(amounts);
 };
 
+GuiInterface.prototype.AddTimeNotification = function(notification)
+{
+	var time = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime();
+	notification.endTime = notification.time + time;
+	notification.id = ++this.timeNotificationID;
+	this.timeNotifications.push(notification);
+	this.timeNotifications.sort(function (n1, n2){return n2.endTime - n1.endTime});
+	return this.timeNotificationID;
+};
 
+GuiInterface.prototype.DeleteTimeNotification = function(notificationID)
+{
+	for (var i in this.timeNotifications)
+	{
+		if (this.timeNotifications[i].id == notificationID)
+		{
+			this.timeNotifications.splice(i);
+			return;
+		}
+	}
+};
+
+GuiInterface.prototype.GetTimeNotificationText = function(playerID)
+{	
+	var formatTime = function(time)
+		{
+			// add 1000 ms to get ceiled instead of floored millisecons
+			// displaying 00:00 for a full second isn't nice
+			time += 1000;
+			var hours   = Math.floor(time / 1000 / 60 / 60);
+			var minutes = Math.floor(time / 1000 / 60) % 60;
+			var seconds = Math.floor(time / 1000) % 60;
+			return (hours ? hours + ':' : "") + (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
+		};
+	var time = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).GetTime();
+	var text = "";
+	for each (var n in this.timeNotifications)
+	{
+		if (time >= n.endTime)
+		{
+			// delete the notification and start over 
+			this.DeleteTimeNotification(n.id);
+			return this.GetTimeNotificationText(playerID);
+		}
+		if (n.players.indexOf(playerID) >= 0)
+			text += n.message.replace("%T",formatTime(n.endTime - time))+"\n";
+	}
+	return text;
+};
+
 GuiInterface.prototype.PushNotification = function(notification)
 {
 	this.notifications.push(notification);
@@ -1793,6 +1844,7 @@
 	"GetIncomingAttacks": 1,
 	"GetNeededResources": 1,
 	"GetNextNotification": 1,
+	"GetTimeNotificationText": 1,
 
 	"GetAvailableFormations": 1,
 	"GetFormationRequirements": 1,
Index: binaries/data/mods/public/simulation/components/ProductionQueue.js
===================================================================
--- binaries/data/mods/public/simulation/components/ProductionQueue.js	(revision 14088)
+++ binaries/data/mods/public/simulation/components/ProductionQueue.js	(working copy)
@@ -203,6 +203,14 @@
 			var buildTime = ApplyValueModificationsToTemplate("Cost/BuildTime", +template.Cost.BuildTime, cmpPlayer.GetPlayerID(), template);
 			var time = timeMult * buildTime;
 
+			var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
+			cmpGuiInterface.AddTimeNotification(
+				{
+					"message" : "Unit will be spawned in %T",
+					"time" : time*1000,
+					"players" : [cmpPlayer.GetPlayerID()],
+				});
+
 			for (var r in template.Cost.Resources)
 			{
 				costs[r] = ApplyValueModificationsToTemplate("Cost/Resources/"+r, +template.Cost.Resources[r], cmpPlayer.GetPlayerID(), template);
Index: binaries/data/mods/public/simulation/components/Wonder.js
===================================================================
--- binaries/data/mods/public/simulation/components/Wonder.js	(revision 0)
+++ binaries/data/mods/public/simulation/components/Wonder.js	(working copy)
@@ -0,0 +1,49 @@
+function Wonder() {}
+
+Wonder.prototype.Schema = 
+	"<element name='TimeTillVictory'>" +
+		"<data type='nonNegativeInteger'/>" +
+	"</element>";
+
+Wonder.prototype.Init = function()
+{
+};
+
+Wonder.prototype.OnOwnershipChanged = function(msg)
+{
+	var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+	var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
+	if (this.timer)
+	{
+		cmpTimer.CancelTimer(this.timer);
+		cmpGuiInterface.DeleteTimeNotification(this.ownMessage);
+		cmpGuiInterface.DeleteTimeNotification(this.otherMessage);
+	}
+	if (msg.to == -1)
+		return;
+	
+	var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
+	var numPlayers = cmpPlayerManager.GetNumPlayers();
+	var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+	var players = [];
+	for (var i = 1; i < numPlayers; i++)
+	{
+		if (i != msg.to)
+			players.push(i);
+	}
+	this.otherMessage = cmpGuiInterface.AddTimeNotification(
+		{
+			"message": cmpPlayer.GetName() + " will have won in %T",
+			"players": players,
+			"time": +this.template.TimeTillVictory*1000
+		});
+	this.ownMessage = cmpGuiInterface.AddTimeNotification(
+		{
+			"message": "You will have won in %T",
+			"players": [msg.to],
+			"time": +this.template.TimeTillVictory*1000
+		});
+	this.timer = cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_EndGameManager, "RegisterWonder", +this.template.TimeTillVictory*1000, this.entity);
+};
+
+Engine.RegisterComponentType(IID_Wonder, "Wonder", Wonder);
Index: binaries/data/mods/public/simulation/components/interfaces/Wonder.js
===================================================================
--- binaries/data/mods/public/simulation/components/interfaces/Wonder.js	(revision 0)
+++ binaries/data/mods/public/simulation/components/interfaces/Wonder.js	(working copy)
@@ -0,0 +1 @@
+Engine.RegisterInterface("Wonder");
Index: binaries/data/mods/public/simulation/templates/template_structure_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_wonder.xml	(revision 14088)
+++ binaries/data/mods/public/simulation/templates/template_structure_wonder.xml	(working copy)
@@ -76,4 +76,7 @@
   <VisualActor>
     <FoundationActor>structures/fndn_6x6.xml</FoundationActor>
   </VisualActor>
+  <Wonder>
+    <TimeTillVictory>300</TimeTillVictory>
+  </Wonder>
 </Entity>
