diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.js b/binaries/data/mods/public/gui/gamesetup/gamesetup.js
index d2f9c7f1b7..845f92a94b 100644
--- a/binaries/data/mods/public/gui/gamesetup/gamesetup.js
+++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.js
@@ -4,8 +4,8 @@ const DEFAULT_NETWORKED_MAP = "Acropolis 01";
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];
diff --git a/binaries/data/mods/public/gui/session/messages.js b/binaries/data/mods/public/gui/session/messages.js
index b940599e00..31466aeefb 100644
--- a/binaries/data/mods/public/gui/session/messages.js
+++ b/binaries/data/mods/public/gui/session/messages.js
@@ -136,12 +136,17 @@ function displayNotifications()
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 [
diff --git a/binaries/data/mods/public/gui/session/session.js b/binaries/data/mods/public/gui/session/session.js
index 3047067080..45186ce8df 100644
--- a/binaries/data/mods/public/gui/session/session.js
+++ b/binaries/data/mods/public/gui/session/session.js
@@ -479,6 +479,7 @@ function onSimulationUpdate()
updateResearchDisplay();
updateBuildingPlacementPreview();
updateTimeElapsedCounter();
+ updateTimeNotifications();
// Update music state on basis of battle state.
var battleState = Engine.GuiInterfaceCall("GetBattleState", Engine.GetPlayerID());
diff --git a/binaries/data/mods/public/gui/session/session.xml b/binaries/data/mods/public/gui/session/session.xml
index 4487acf0b1..454faa1247 100644
--- a/binaries/data/mods/public/gui/session/session.xml
+++ b/binaries/data/mods/public/gui/session/session.xml
@@ -345,6 +345,10 @@
+
+
+
+
diff --git a/binaries/data/mods/public/simulation/components/EndGameManager.js b/binaries/data/mods/public/simulation/components/EndGameManager.js
index f783bca85d..1a0d35bd76 100644
--- a/binaries/data/mods/public/simulation/components/EndGameManager.js
+++ b/binaries/data/mods/public/simulation/components/EndGameManager.js
@@ -24,6 +24,39 @@ EndGameManager.prototype.Init = function()
EndGameManager.prototype.SetGameType = function(newGameType)
{
this.gameType = newGameType;
+ Engine.BroadcastMessage(MT_GameTypeChanged, {});
+};
+
+EndGameManager.prototype.CheckGameType = function(type)
+{
+ return this.gameType == type;
+};
+
+EndGameManager.prototype.RegisterWonder = function(entity)
+{
+ if (!this.CheckGameType("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 } );
+ }
+
+ // Reveal the map to all players
+ var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
+ cmpRangeManager.SetLosRevealAll(-1, true);
};
EndGameManager.prototype.SetAlliedVictory = function(flag)
diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js
index a252b5c237..c169f7ae73 100644
--- a/binaries/data/mods/public/simulation/components/GuiInterface.js
+++ b/binaries/data/mods/public/simulation/components/GuiInterface.js
@@ -22,6 +22,8 @@ GuiInterface.prototype.Init = function()
this.placementWallLastAngle = 0;
this.notifications = [];
this.renamedEntities = [];
+ this.timeNotificationID = 1;
+ this.timeNotifications = [];
};
/*
@@ -728,6 +730,55 @@ GuiInterface.prototype.GetNeededResources = function(player, amounts)
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)
{
@@ -1879,6 +1930,7 @@ var exposedFunctions = {
"GetIncomingAttacks": 1,
"GetNeededResources": 1,
"GetNextNotification": 1,
+ "GetTimeNotificationText": 1,
"GetAvailableFormations": 1,
"GetFormationRequirements": 1,
diff --git a/binaries/data/mods/public/simulation/components/Wonder.js b/binaries/data/mods/public/simulation/components/Wonder.js
new file mode 100644
index 0000000000..c2c1853f31
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/Wonder.js
@@ -0,0 +1,67 @@
+function Wonder() {}
+
+Wonder.prototype.Schema =
+ "" +
+ "" +
+ "";
+
+Wonder.prototype.Init = function()
+{
+};
+
+Wonder.prototype.OnOwnershipChanged = function(msg)
+{
+ this.ResetTimer(msg.to);
+};
+
+Wonder.prototype.OnGameTypeChanged = function()
+{
+ var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+ if (!cmpPlayer)
+ return;
+ this.ResetTimer(cmpPlayer.GetPlayerID());
+};
+
+Wonder.prototype.ResetTimer = function(ownerID)
+{
+ var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
+ // remove existing messages if any
+ if (this.timer)
+ {
+ cmpTimer.CancelTimer(this.timer);
+ cmpGuiInterface.DeleteTimeNotification(this.ownMessage);
+ cmpGuiInterface.DeleteTimeNotification(this.otherMessage);
+ }
+ if (ownerID <= 0)
+ return;
+
+ var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
+ if (!cmpEndGameManager.CheckGameType("wonder"))
+ return;
+
+ // create new messages, and start timer to register defeat.
+ 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 != ownerID)
+ 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": [ownerID],
+ "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);
diff --git a/binaries/data/mods/public/simulation/components/interfaces/EndGameManager.js b/binaries/data/mods/public/simulation/components/interfaces/EndGameManager.js
index 77286b1598..17333a3fff 100644
--- a/binaries/data/mods/public/simulation/components/interfaces/EndGameManager.js
+++ b/binaries/data/mods/public/simulation/components/interfaces/EndGameManager.js
@@ -1,2 +1,3 @@
Engine.RegisterInterface("EndGameManager");
Engine.RegisterMessageType("PlayerDefeated");
+Engine.RegisterMessageType("GameTypeChanged");
diff --git a/binaries/data/mods/public/simulation/components/interfaces/Wonder.js b/binaries/data/mods/public/simulation/components/interfaces/Wonder.js
new file mode 100644
index 0000000000..b02be73d74
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/interfaces/Wonder.js
@@ -0,0 +1 @@
+Engine.RegisterInterface("Wonder");
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_wonder.xml b/binaries/data/mods/public/simulation/templates/template_structure_wonder.xml
index 1ee0e5e745..b5a87ff46b 100644
--- a/binaries/data/mods/public/simulation/templates/template_structure_wonder.xml
+++ b/binaries/data/mods/public/simulation/templates/template_structure_wonder.xml
@@ -76,4 +76,7 @@
structures/fndn_6x6.xml
+
+ 300
+
diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp
index 5e08cbf0e1..55e1d17499 100644
--- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp
+++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp
@@ -145,6 +145,7 @@ void MapSettingsControl::CreateWidgets()
wxArrayString gameTypes;
gameTypes.Add(_T("conquest"));
+ gameTypes.Add(_T("wonder"));
gameTypes.Add(_T("endless"));
wxFlexGridSizer* gridSizer = new wxFlexGridSizer(2, 5, 5);