2010-08-12 00:16:16 +02:00
|
|
|
// Network Mode
|
|
|
|
var g_IsNetworked = false;
|
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
// Is this user in control of game settings (i.e. is a network server, or offline player)
|
|
|
|
var g_IsController;
|
2013-11-08 10:52:48 +01:00
|
|
|
// Match ID for tracking
|
2013-11-08 16:28:38 +01:00
|
|
|
var g_MatchID;
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2010-08-12 00:16:16 +02:00
|
|
|
// Cache the basic player data (name, civ, color)
|
|
|
|
var g_Players = [];
|
2010-10-30 06:02:42 +02:00
|
|
|
// Cache the useful civ data
|
|
|
|
var g_CivData = {};
|
|
|
|
|
2013-04-04 01:24:22 +02:00
|
|
|
var g_GameSpeeds = {};
|
|
|
|
var g_CurrentSpeed;
|
|
|
|
|
2010-08-14 17:34:36 +02:00
|
|
|
var g_PlayerAssignments = { "local": { "name": "You", "player": 1 } };
|
2010-08-12 21:31:17 +02:00
|
|
|
|
2010-06-30 23:34:44 +02:00
|
|
|
// Cache dev-mode settings that are frequently or widely used
|
|
|
|
var g_DevSettings = {
|
|
|
|
controlAll: false
|
|
|
|
};
|
|
|
|
|
2012-07-24 06:14:09 +02:00
|
|
|
// Whether status bars should be shown for all of the player's units.
|
|
|
|
var g_ShowAllStatusBars = false;
|
|
|
|
|
2010-09-04 15:24:52 +02:00
|
|
|
// Indicate when one of the current player's training queues is blocked
|
|
|
|
// (this is used to support population counter blinking)
|
2012-04-20 19:21:04 +02:00
|
|
|
var g_IsTrainingBlocked = false;
|
2010-09-04 15:24:52 +02:00
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
// Cache simulation state (updated on every simulation update)
|
|
|
|
var g_SimState;
|
|
|
|
|
2010-08-28 23:12:52 +02:00
|
|
|
// Cache EntityStates
|
|
|
|
var g_EntityStates = {}; // {id:entState}
|
|
|
|
|
2010-10-01 22:51:21 +02:00
|
|
|
// Whether the player has lost/won and reached the end of their game
|
|
|
|
var g_GameEnded = false;
|
|
|
|
|
2013-03-25 06:01:36 +01:00
|
|
|
var g_Disconnected = false; // Lost connection to server
|
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
// Holds player states from the last tick
|
|
|
|
var g_CachedLastStates = "";
|
|
|
|
|
2011-09-07 03:43:56 +02:00
|
|
|
// Colors to flash when pop limit reached
|
|
|
|
const DEFAULT_POPULATION_COLOR = "white";
|
|
|
|
const POPULATION_ALERT_COLOR = "orange";
|
|
|
|
|
2013-11-30 18:30:08 +01:00
|
|
|
// List of additional entities to highlight
|
|
|
|
var g_ShowGuarding = false;
|
|
|
|
var g_ShowGuarded = false;
|
|
|
|
var g_AdditionalHighlight = [];
|
|
|
|
|
2014-01-06 14:48:17 +01:00
|
|
|
// for saving the hitpoins of the hero (is there a better way to do that?)
|
|
|
|
// Should be possible with AttackDetection but might be an overkill because it would have to loop
|
|
|
|
// always through the list of all ongoing attacks...
|
|
|
|
var g_previousHeroHitPoints = undefined;
|
2014-01-06 14:32:48 +01:00
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
function GetSimState()
|
|
|
|
{
|
|
|
|
if (!g_SimState)
|
|
|
|
g_SimState = Engine.GuiInterfaceCall("GetSimulationState");
|
|
|
|
|
|
|
|
return g_SimState;
|
|
|
|
}
|
|
|
|
|
2010-08-28 23:12:52 +02:00
|
|
|
function GetEntityState(entId)
|
|
|
|
{
|
|
|
|
if (!(entId in g_EntityStates))
|
|
|
|
{
|
|
|
|
var entState = Engine.GuiInterfaceCall("GetEntityState", entId);
|
2013-12-08 11:02:19 +01:00
|
|
|
if (entState)
|
|
|
|
entState.extended = false;
|
2010-08-28 23:12:52 +02:00
|
|
|
g_EntityStates[entId] = entState;
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_EntityStates[entId];
|
|
|
|
}
|
|
|
|
|
2013-12-08 11:02:19 +01:00
|
|
|
function GetExtendedEntityState(entId)
|
|
|
|
{
|
|
|
|
if (entId in g_EntityStates)
|
|
|
|
var entState = g_EntityStates[entId];
|
|
|
|
else
|
|
|
|
var entState = Engine.GuiInterfaceCall("GetEntityState", entId);
|
|
|
|
|
|
|
|
if (!entState || entState.extended)
|
|
|
|
return entState;
|
|
|
|
|
|
|
|
var extension = Engine.GuiInterfaceCall("GetExtendedEntityState", entId);
|
|
|
|
for (var prop in extension)
|
|
|
|
entState[prop] = extension[prop];
|
|
|
|
entState.extended = true;
|
|
|
|
g_EntityStates[entId] = entState;
|
|
|
|
|
|
|
|
return entState;
|
|
|
|
}
|
|
|
|
|
2010-08-28 23:12:52 +02:00
|
|
|
// Cache TemplateData
|
|
|
|
var g_TemplateData = {}; // {id:template}
|
|
|
|
|
2010-10-30 06:02:42 +02:00
|
|
|
|
2010-08-28 23:12:52 +02:00
|
|
|
function GetTemplateData(templateName)
|
|
|
|
{
|
|
|
|
if (!(templateName in g_TemplateData))
|
|
|
|
{
|
|
|
|
var template = Engine.GuiInterfaceCall("GetTemplateData", templateName);
|
|
|
|
g_TemplateData[templateName] = template;
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_TemplateData[templateName];
|
|
|
|
}
|
|
|
|
|
2012-04-20 19:21:04 +02:00
|
|
|
// 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];
|
|
|
|
}
|
|
|
|
|
2010-08-28 23:12:52 +02:00
|
|
|
// Init
|
2010-06-30 23:34:44 +02:00
|
|
|
function init(initData, hotloadData)
|
|
|
|
{
|
2010-08-12 00:16:16 +02:00
|
|
|
if (initData)
|
|
|
|
{
|
|
|
|
g_IsNetworked = initData.isNetworked; // Set network mode
|
2013-11-07 21:07:24 +01:00
|
|
|
g_IsController = initData.isController; // Set controller mode
|
2010-08-12 21:31:17 +02:00
|
|
|
g_PlayerAssignments = initData.playerAssignments;
|
2013-11-07 21:07:24 +01:00
|
|
|
g_MatchID = initData.attribs.matchID;
|
2010-11-03 01:21:52 +01:00
|
|
|
|
|
|
|
// Cache the player data
|
|
|
|
// (This may be updated at runtime by handleNetMessage)
|
|
|
|
g_Players = getPlayerData(g_PlayerAssignments);
|
2012-05-07 06:18:54 +02:00
|
|
|
|
|
|
|
if (initData.savedGUIData)
|
|
|
|
restoreSavedGameData(initData.savedGUIData);
|
2013-04-04 01:24:22 +02:00
|
|
|
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("gameSpeedButton").hidden = g_IsNetworked;
|
2010-08-12 00:16:16 +02:00
|
|
|
}
|
2010-08-12 05:01:33 +02:00
|
|
|
else // Needed for autostart loading option
|
|
|
|
{
|
2011-08-31 04:41:21 +02:00
|
|
|
g_Players = getPlayerData(null);
|
2010-08-12 05:01:33 +02:00
|
|
|
}
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2010-10-30 06:02:42 +02:00
|
|
|
// Cache civ data
|
|
|
|
g_CivData = loadCivData();
|
2010-10-30 15:27:23 +02:00
|
|
|
g_CivData["gaia"] = { "Code": "gaia", "Name": "Gaia" };
|
2010-08-14 06:34:49 +02:00
|
|
|
|
2013-04-04 01:24:22 +02:00
|
|
|
g_GameSpeeds = initGameSpeeds();
|
|
|
|
g_CurrentSpeed = Engine.GetSimRate();
|
2014-01-04 11:14:53 +01:00
|
|
|
var gameSpeed = Engine.GetGUIObjectByName("gameSpeed");
|
2013-04-04 01:24:22 +02:00
|
|
|
gameSpeed.list = g_GameSpeeds.names;
|
|
|
|
gameSpeed.list_data = g_GameSpeeds.speeds;
|
|
|
|
var idx = g_GameSpeeds.speeds.indexOf(g_CurrentSpeed);
|
|
|
|
gameSpeed.selected = idx != -1 ? idx : g_GameSpeeds["default"];
|
|
|
|
gameSpeed.onSelectionChange = function() { changeGameSpeed(+this.list_data[this.selected]); }
|
|
|
|
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("civIcon").sprite = "stretched:" + g_CivData[g_Players[Engine.GetPlayerID()].civ].Emblem;
|
|
|
|
Engine.GetGUIObjectByName("civIcon").tooltip = g_CivData[g_Players[Engine.GetPlayerID()].civ].Name;
|
2011-09-06 20:15:27 +02:00
|
|
|
initMenuPosition(); // set initial position
|
2011-05-04 21:31:01 +02:00
|
|
|
|
2013-07-29 02:53:44 +02:00
|
|
|
// Populate player selection dropdown
|
|
|
|
var playerNames = [];
|
|
|
|
var playerIDs = [];
|
|
|
|
for (var player in g_Players)
|
|
|
|
{
|
|
|
|
playerNames.push(g_Players[player].name);
|
|
|
|
playerIDs.push(player);
|
|
|
|
}
|
|
|
|
|
2014-01-04 11:14:53 +01:00
|
|
|
var viewPlayerDropdown = Engine.GetGUIObjectByName("viewPlayer");
|
2013-07-29 02:53:44 +02:00
|
|
|
viewPlayerDropdown.list = playerNames;
|
|
|
|
viewPlayerDropdown.list_data = playerIDs;
|
2013-07-29 22:01:09 +02:00
|
|
|
viewPlayerDropdown.selected = Engine.GetPlayerID();
|
2013-07-29 02:53:44 +02:00
|
|
|
|
2012-04-20 03:41:54 +02:00
|
|
|
// If in Atlas editor, disable the exit button
|
|
|
|
if (Engine.IsAtlasRunning())
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("menuExitButton").enabled = false;
|
2012-04-20 03:41:54 +02:00
|
|
|
|
2011-05-04 21:31:01 +02:00
|
|
|
if (hotloadData)
|
|
|
|
{
|
|
|
|
g_Selection.selected = hotloadData.selection;
|
|
|
|
}
|
2011-08-31 04:41:21 +02:00
|
|
|
else
|
2011-05-04 21:31:01 +02:00
|
|
|
{
|
2011-09-11 05:30:41 +02:00
|
|
|
// Starting for the first time:
|
|
|
|
var civMusic = g_CivData[g_Players[Engine.GetPlayerID()].civ].Music;
|
2011-09-14 14:46:34 +02:00
|
|
|
initMusic();
|
2011-09-11 05:30:41 +02:00
|
|
|
global.music.storeTracks(civMusic);
|
|
|
|
global.music.setState(global.music.states.PEACE);
|
|
|
|
playRandomAmbient("temperate");
|
2011-05-04 21:31:01 +02:00
|
|
|
}
|
|
|
|
|
2013-11-07 19:06:52 +01:00
|
|
|
if (Engine.ConfigDB_GetValue("user", "gui.session.timeelapsedcounter") === "true")
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("timeElapsedCounter").hidden = false;
|
2013-11-07 19:06:52 +01:00
|
|
|
|
2010-06-30 23:34:44 +02:00
|
|
|
onSimulationUpdate();
|
2011-02-19 04:14:37 +01:00
|
|
|
|
|
|
|
// Report the performance after 5 seconds (when we're still near
|
|
|
|
// the initial camera view) and a minute (when the profiler will
|
|
|
|
// have settled down if framerates as very low), to give some
|
|
|
|
// extremely rough indications of performance
|
|
|
|
setTimeout(function() { reportPerformance(5); }, 5000);
|
|
|
|
setTimeout(function() { reportPerformance(60); }, 60000);
|
|
|
|
}
|
|
|
|
|
2013-07-29 02:53:44 +02:00
|
|
|
function selectViewPlayer(playerID)
|
|
|
|
{
|
|
|
|
Engine.SetPlayerID(playerID);
|
|
|
|
if (playerID != 0) {
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("civIcon").sprite = "stretched:" + g_CivData[g_Players[playerID].civ].Emblem;
|
|
|
|
Engine.GetGUIObjectByName("civIcon").tooltip = g_CivData[g_Players[playerID].civ].Name;
|
2013-07-29 02:53:44 +02:00
|
|
|
}
|
|
|
|
}
|
2011-09-11 05:30:41 +02:00
|
|
|
|
2011-02-19 04:14:37 +01:00
|
|
|
function reportPerformance(time)
|
|
|
|
{
|
2011-04-28 03:21:02 +02:00
|
|
|
var settings = Engine.GetMapSettings();
|
2011-02-19 04:14:37 +01:00
|
|
|
var data = {
|
|
|
|
time: time,
|
2011-04-28 03:21:02 +02:00
|
|
|
map: settings.Name,
|
2011-04-29 19:32:35 +02:00
|
|
|
seed: settings.Seed, // only defined for random maps
|
|
|
|
size: settings.Size, // only defined for random maps
|
2011-02-19 04:14:37 +01:00
|
|
|
profiler: Engine.GetProfilerState()
|
|
|
|
};
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2011-04-29 19:32:35 +02:00
|
|
|
Engine.SubmitUserReport("profile", 3, JSON.stringify(data));
|
2010-06-30 23:34:44 +02:00
|
|
|
}
|
|
|
|
|
2012-08-05 20:07:56 +02:00
|
|
|
function resignGame()
|
|
|
|
{
|
2013-04-10 23:05:46 +02:00
|
|
|
var simState = GetSimState();
|
2012-08-05 20:07:56 +02:00
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
// Players can't resign if they've already won or lost.
|
2013-03-25 06:01:36 +01:00
|
|
|
if (simState.players[Engine.GetPlayerID()].state != "active" || g_Disconnected)
|
2012-08-05 20:07:56 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Tell other players that we have given up and been defeated
|
|
|
|
Engine.PostNetworkCommand({
|
|
|
|
"type": "defeat-player",
|
|
|
|
"playerId": Engine.GetPlayerID()
|
|
|
|
});
|
|
|
|
|
|
|
|
global.music.setState(global.music.states.DEFEAT);
|
|
|
|
resumeGame();
|
|
|
|
}
|
|
|
|
|
2010-06-30 23:34:44 +02:00
|
|
|
function leaveGame()
|
|
|
|
{
|
2010-11-14 20:09:13 +01:00
|
|
|
var extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
|
|
|
|
var playerState = extendedSimState.players[Engine.GetPlayerID()];
|
2013-11-07 21:07:24 +01:00
|
|
|
var mapSettings = Engine.GetMapSettings();
|
2010-10-01 22:51:21 +02:00
|
|
|
var gameResult;
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2013-03-25 06:01:36 +01:00
|
|
|
if (g_Disconnected)
|
|
|
|
{
|
|
|
|
gameResult = "You have been disconnected."
|
|
|
|
}
|
|
|
|
else if (playerState.state == "won")
|
2010-10-01 22:51:21 +02:00
|
|
|
{
|
|
|
|
gameResult = "You have won the battle!";
|
|
|
|
}
|
|
|
|
else if (playerState.state == "defeated")
|
|
|
|
{
|
|
|
|
gameResult = "You have been defeated...";
|
|
|
|
}
|
|
|
|
else // "active"
|
|
|
|
{
|
|
|
|
gameResult = "You have abandoned the game.";
|
|
|
|
|
2011-09-11 05:30:41 +02:00
|
|
|
// Tell other players that we have given up and been defeated
|
2010-10-01 22:51:21 +02:00
|
|
|
Engine.PostNetworkCommand({
|
|
|
|
"type": "defeat-player",
|
|
|
|
"playerId": Engine.GetPlayerID()
|
|
|
|
});
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2011-09-11 05:30:41 +02:00
|
|
|
global.music.setState(global.music.states.DEFEAT);
|
2010-10-01 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
2011-09-11 05:30:41 +02:00
|
|
|
stopAmbient();
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.EndGame();
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2013-11-08 16:28:44 +01:00
|
|
|
if (g_IsController && Engine.HasXmppClient())
|
2013-11-07 21:07:24 +01:00
|
|
|
Engine.SendUnregisterGame();
|
2013-11-08 16:28:44 +01:00
|
|
|
|
2011-09-11 05:30:41 +02:00
|
|
|
Engine.SwitchGuiPage("page_summary.xml", {
|
|
|
|
"gameResult" : gameResult,
|
|
|
|
"timeElapsed" : extendedSimState.timeElapsed,
|
2012-06-26 00:11:47 +02:00
|
|
|
"playerStates": extendedSimState.players,
|
2012-08-05 04:18:44 +02:00
|
|
|
"players": g_Players,
|
2012-06-26 00:11:47 +02:00
|
|
|
"mapSettings": mapSettings
|
2011-09-11 05:30:41 +02:00
|
|
|
});
|
2010-06-30 23:34:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return some data that we'll use when hotloading this file after changes
|
|
|
|
function getHotloadData()
|
|
|
|
{
|
|
|
|
return { selection: g_Selection.selected };
|
|
|
|
}
|
|
|
|
|
2011-10-30 02:07:28 +02:00
|
|
|
// Return some data that will be stored in saved game files
|
|
|
|
function getSavedGameData()
|
|
|
|
{
|
|
|
|
var data = {};
|
|
|
|
data.playerAssignments = g_PlayerAssignments;
|
2012-05-07 06:18:54 +02:00
|
|
|
data.groups = g_Groups.groups;
|
|
|
|
// TODO: any other gui state?
|
2011-10-30 02:07:28 +02:00
|
|
|
return data;
|
|
|
|
}
|
2011-09-12 00:42:40 +02:00
|
|
|
|
2012-05-07 06:18:54 +02:00
|
|
|
function restoreSavedGameData(data)
|
|
|
|
{
|
2013-10-11 01:58:29 +02:00
|
|
|
// Clear selection when loading a game
|
|
|
|
g_Selection.reset();
|
|
|
|
|
2012-05-07 06:18:54 +02:00
|
|
|
// Restore control groups
|
2013-05-13 00:28:02 +02:00
|
|
|
for (var groupNumber in data.groups)
|
2012-05-07 06:18:54 +02:00
|
|
|
{
|
|
|
|
g_Groups.groups[groupNumber].groups = data.groups[groupNumber].groups;
|
|
|
|
g_Groups.groups[groupNumber].ents = data.groups[groupNumber].ents;
|
|
|
|
}
|
|
|
|
updateGroups();
|
|
|
|
}
|
|
|
|
|
2011-10-30 02:07:28 +02:00
|
|
|
var lastTickTime = new Date;
|
2014-01-08 05:22:34 +01:00
|
|
|
var lastXmppClientPoll = Date.now();
|
2012-05-05 21:22:22 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called every frame.
|
|
|
|
*/
|
2010-06-30 23:34:44 +02:00
|
|
|
function onTick()
|
|
|
|
{
|
2011-10-30 02:07:28 +02:00
|
|
|
var now = new Date;
|
|
|
|
var tickLength = new Date - lastTickTime;
|
|
|
|
lastTickTime = now;
|
|
|
|
|
2010-10-01 22:51:21 +02:00
|
|
|
checkPlayerState();
|
|
|
|
|
2010-07-02 23:28:48 +02:00
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
var message = Engine.PollNetworkClient();
|
|
|
|
if (!message)
|
|
|
|
break;
|
|
|
|
handleNetMessage(message);
|
|
|
|
}
|
|
|
|
|
2012-03-08 21:42:28 +01:00
|
|
|
updateCursorAndTooltip();
|
2010-06-30 23:34:44 +02:00
|
|
|
|
2012-05-05 21:22:22 +02:00
|
|
|
// If the selection changed, we need to regenerate the sim display (the display depends on both the
|
|
|
|
// simulation state and the current selection).
|
2010-06-30 23:34:44 +02:00
|
|
|
if (g_Selection.dirty)
|
2010-08-05 12:20:47 +02:00
|
|
|
{
|
2013-12-05 19:50:29 +01:00
|
|
|
g_Selection.dirty = false;
|
|
|
|
|
2010-06-30 23:34:44 +02:00
|
|
|
onSimulationUpdate();
|
2010-08-05 12:20:47 +02:00
|
|
|
|
|
|
|
// Display rally points for selected buildings
|
|
|
|
Engine.GuiInterfaceCall("DisplayRallyPoint", { "entities": g_Selection.toList() });
|
|
|
|
}
|
2010-08-11 23:04:09 +02:00
|
|
|
|
|
|
|
// Run timers
|
|
|
|
updateTimers();
|
2010-09-28 16:19:13 +02:00
|
|
|
|
2011-09-11 05:30:41 +02:00
|
|
|
// Animate menu
|
2011-10-30 02:07:28 +02:00
|
|
|
updateMenuPosition(tickLength);
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2010-09-28 16:19:13 +02:00
|
|
|
// When training is blocked, flash population (alternates colour every 500msec)
|
2012-04-20 19:21:04 +02:00
|
|
|
if (g_IsTrainingBlocked && (Date.now() % 1000) < 500)
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("resourcePop").textcolor = POPULATION_ALERT_COLOR;
|
2010-09-04 15:24:52 +02:00
|
|
|
else
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("resourcePop").textcolor = DEFAULT_POPULATION_COLOR;
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2011-08-31 00:29:03 +02:00
|
|
|
// Clear renamed entities list
|
2011-10-23 23:00:59 +02:00
|
|
|
Engine.GuiInterfaceCall("ClearRenamedEntities");
|
2014-01-08 05:22:34 +01:00
|
|
|
|
|
|
|
// If the lobby is running, wake it up every 10 seconds so we stay connected.
|
|
|
|
if (Engine.HasXmppClient() && (Date.now() - lastXmppClientPoll) > 10000)
|
|
|
|
{
|
|
|
|
Engine.RecvXmppClient();
|
|
|
|
lastXmppClientPoll = Date.now();
|
|
|
|
}
|
2010-06-30 23:34:44 +02:00
|
|
|
}
|
|
|
|
|
2010-10-01 22:51:21 +02:00
|
|
|
function checkPlayerState()
|
|
|
|
{
|
2013-11-07 21:07:24 +01:00
|
|
|
// Once the game ends, we're done here.
|
|
|
|
if (g_GameEnded)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Send a game report for each player in this game.
|
|
|
|
var m_simState = GetSimState();
|
|
|
|
var playerState = m_simState.players[Engine.GetPlayerID()];
|
|
|
|
var tempStates = "";
|
|
|
|
for each (var player in m_simState.players) {tempStates += player.state + ",";}
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
if (g_CachedLastStates != tempStates)
|
2010-10-01 22:51:21 +02:00
|
|
|
{
|
2013-11-07 21:07:24 +01:00
|
|
|
g_CachedLastStates = tempStates;
|
|
|
|
reportGame(Engine.GuiInterfaceCall("GetExtendedSimulationState"));
|
|
|
|
}
|
2012-08-05 20:07:56 +02:00
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
// If the local player hasn't finished playing, we return here to avoid the victory/defeat messages.
|
|
|
|
if (playerState.state == "active")
|
|
|
|
return;
|
|
|
|
|
|
|
|
// We can't resign once the game is over.
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("menuResignButton").enabled = false;
|
2013-11-07 21:07:24 +01:00
|
|
|
|
|
|
|
// Make sure nothing is open to avoid stacking.
|
|
|
|
closeMenu();
|
|
|
|
closeOpenDialogs();
|
|
|
|
|
|
|
|
// Make sure this doesn't run again.
|
|
|
|
g_GameEnded = true;
|
|
|
|
|
|
|
|
if (Engine.IsAtlasRunning())
|
|
|
|
{
|
|
|
|
// If we're in Atlas, we can't leave the game
|
|
|
|
var btCaptions = ["OK"];
|
|
|
|
var btCode = [null];
|
|
|
|
var message = "Press OK to continue";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var btCaptions = ["Yes", "No"];
|
|
|
|
var btCode = [leaveGame, null];
|
|
|
|
var message = "Do you want to quit?";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playerState.state == "defeated")
|
|
|
|
{
|
|
|
|
global.music.setState(global.music.states.DEFEAT);
|
|
|
|
messageBox(400, 200, message, "DEFEATED!", 0, btCaptions, btCode);
|
2010-10-01 22:51:21 +02:00
|
|
|
}
|
2013-11-07 21:07:24 +01:00
|
|
|
else if (playerState.state == "won")
|
|
|
|
{
|
|
|
|
global.music.setState(global.music.states.VICTORY);
|
|
|
|
// TODO: Reveal map directly instead of this silly proxy.
|
2014-01-04 11:14:53 +01:00
|
|
|
if (!Engine.GetGUIObjectByName("devCommandsRevealMap").checked)
|
|
|
|
Engine.GetGUIObjectByName("devCommandsRevealMap").checked = true;
|
2013-11-07 21:07:24 +01:00
|
|
|
messageBox(400, 200, message, "VICTORIOUS!", 0, btCaptions, btCode);
|
|
|
|
}
|
|
|
|
|
2010-10-01 22:51:21 +02:00
|
|
|
}
|
|
|
|
|
2013-04-04 01:24:22 +02:00
|
|
|
function changeGameSpeed(speed)
|
|
|
|
{
|
|
|
|
// For non-networked games only
|
|
|
|
if (!g_IsNetworked)
|
|
|
|
{
|
|
|
|
Engine.SetSimRate(speed);
|
|
|
|
g_CurrentSpeed = speed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-05 21:22:22 +02:00
|
|
|
/**
|
|
|
|
* Recomputes GUI state that depends on simulation state or selection state. Called directly every simulation
|
|
|
|
* update (see session.xml), or from onTick when the selection has changed.
|
|
|
|
*/
|
2010-06-30 23:34:44 +02:00
|
|
|
function onSimulationUpdate()
|
|
|
|
{
|
2010-08-28 23:12:52 +02:00
|
|
|
g_EntityStates = {};
|
|
|
|
g_TemplateData = {};
|
2012-04-20 19:21:04 +02:00
|
|
|
g_TechnologyData = {};
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
g_SimState = Engine.GuiInterfaceCall("GetSimulationState");
|
2010-10-30 20:25:34 +02:00
|
|
|
|
2010-06-30 23:34:44 +02:00
|
|
|
// If we're called during init when the game is first loading, there will be no simulation yet, so do nothing
|
2013-04-10 23:05:46 +02:00
|
|
|
if (!g_SimState)
|
2010-06-30 23:34:44 +02:00
|
|
|
return;
|
|
|
|
|
2010-08-14 00:02:27 +02:00
|
|
|
handleNotifications();
|
2010-08-14 00:06:19 +02:00
|
|
|
|
2012-07-24 06:14:09 +02:00
|
|
|
if (g_ShowAllStatusBars)
|
|
|
|
recalculateStatusBarDisplay();
|
|
|
|
|
2013-11-30 18:30:08 +01:00
|
|
|
if (g_ShowGuarding || g_ShowGuarded)
|
|
|
|
updateAdditionalHighlight();
|
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
updateHero();
|
2011-04-26 20:19:16 +02:00
|
|
|
updateGroups();
|
2013-04-10 23:05:46 +02:00
|
|
|
updateDebug();
|
|
|
|
updatePlayerDisplay();
|
2010-08-12 00:16:16 +02:00
|
|
|
updateSelectionDetails();
|
2012-07-31 04:03:25 +02:00
|
|
|
updateResearchDisplay();
|
2011-02-11 12:17:32 +01:00
|
|
|
updateBuildingPlacementPreview();
|
2013-04-10 23:05:46 +02:00
|
|
|
updateTimeElapsedCounter();
|
2013-12-28 14:40:39 +01:00
|
|
|
updateTimeNotifications();
|
2013-01-20 23:47:59 +01:00
|
|
|
|
|
|
|
// Update music state on basis of battle state.
|
|
|
|
var battleState = Engine.GuiInterfaceCall("GetBattleState", Engine.GetPlayerID());
|
|
|
|
if (battleState)
|
|
|
|
global.music.setState(global.music.states[battleState]);
|
2014-01-06 14:32:48 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* updates a status bar on the GUI
|
|
|
|
* nameOfBar: name of the bar
|
|
|
|
* points: points to show
|
|
|
|
* maxPoints: max points
|
|
|
|
* direction: gets less from (right to left) 0; (top to bottom) 1; (left to right) 2; (bottom to top) 3;
|
|
|
|
*/
|
|
|
|
function updateGUIStatusBar(nameOfBar, points, maxPoints, direction)
|
|
|
|
{
|
|
|
|
// check, if optional direction parameter is valid.
|
2014-01-06 21:13:55 +01:00
|
|
|
if (!direction || !(direction >= 0 && direction < 4))
|
2014-01-06 14:32:48 +01:00
|
|
|
direction = 0;
|
|
|
|
|
|
|
|
// get the bar and update it
|
|
|
|
var statusBar = Engine.GetGUIObjectByName(nameOfBar);
|
2014-01-06 14:48:17 +01:00
|
|
|
if (!statusBar)
|
|
|
|
return;
|
2014-01-06 14:32:48 +01:00
|
|
|
|
2014-01-06 14:48:17 +01:00
|
|
|
var healthSize = statusBar.size;
|
|
|
|
var value = 100*Math.max(0, Math.min(1, points / maxPoints));
|
|
|
|
|
|
|
|
// inverse bar
|
|
|
|
if(direction == 2 || direction == 3)
|
|
|
|
value = 100 - value;
|
|
|
|
|
|
|
|
if(direction == 0)
|
|
|
|
healthSize.rright = value;
|
|
|
|
else if(direction == 1)
|
|
|
|
healthSize.rbottom = value;
|
|
|
|
else if(direction == 2)
|
|
|
|
healthSize.rleft = value;
|
|
|
|
else if(direction == 3)
|
|
|
|
healthSize.rtop = value;
|
|
|
|
|
|
|
|
// update bar
|
|
|
|
statusBar.size = healthSize;
|
2010-06-30 23:34:44 +02:00
|
|
|
}
|
|
|
|
|
2014-01-06 14:32:48 +01:00
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
function updateHero()
|
2013-04-03 19:27:55 +02:00
|
|
|
{
|
2013-04-10 23:05:46 +02:00
|
|
|
var simState = GetSimState();
|
2013-04-03 19:27:55 +02:00
|
|
|
var playerState = simState.players[Engine.GetPlayerID()];
|
2014-01-06 14:32:48 +01:00
|
|
|
var unitHeroPanel = Engine.GetGUIObjectByName("unitHeroPanel");
|
2014-01-04 11:14:53 +01:00
|
|
|
var heroButton = Engine.GetGUIObjectByName("unitHeroButton");
|
2013-04-03 19:27:55 +02:00
|
|
|
|
|
|
|
if (!playerState || playerState.heroes.length <= 0)
|
|
|
|
{
|
2014-01-06 14:48:17 +01:00
|
|
|
g_previousHeroHitPoints = undefined;
|
2014-01-06 14:32:48 +01:00
|
|
|
unitHeroPanel.hidden = true;
|
2013-04-03 19:27:55 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-04 11:14:53 +01:00
|
|
|
var heroImage = Engine.GetGUIObjectByName("unitHeroImage");
|
2013-12-08 11:02:19 +01:00
|
|
|
var heroState = GetExtendedEntityState(playerState.heroes[0]);
|
2013-04-03 19:27:55 +02:00
|
|
|
var template = GetTemplateData(heroState.template);
|
|
|
|
heroImage.sprite = "stretched:session/portraits/" + template.icon;
|
2013-09-16 11:14:16 +02:00
|
|
|
var hero = playerState.heroes[0];
|
2013-04-03 19:27:55 +02:00
|
|
|
|
2013-10-10 23:23:19 +02:00
|
|
|
heroButton.onpress = function()
|
|
|
|
{
|
2013-09-16 11:14:16 +02:00
|
|
|
if (!Engine.HotkeyIsPressed("selection.add"))
|
2013-10-10 23:23:19 +02:00
|
|
|
g_Selection.reset();
|
|
|
|
g_Selection.addList([hero]);
|
2013-09-16 11:14:16 +02:00
|
|
|
};
|
2013-10-10 23:23:19 +02:00
|
|
|
heroButton.ondoublepress = function() { selectAndMoveTo(getEntityOrHolder(hero)); };
|
2014-01-06 14:32:48 +01:00
|
|
|
unitHeroPanel.hidden = false;
|
2013-04-03 19:27:55 +02:00
|
|
|
|
|
|
|
// Setup tooltip
|
|
|
|
var tooltip = "[font=\"serif-bold-16\"]" + template.name.specific + "[/font]";
|
|
|
|
tooltip += "\n[font=\"serif-bold-13\"]Health:[/font] " + heroState.hitpoints + "/" + heroState.maxHitpoints;
|
2013-05-12 18:02:53 +02:00
|
|
|
tooltip += "\n[font=\"serif-bold-13\"]" + (heroState.attack ? heroState.attack.type + " " : "")
|
2013-04-03 19:27:55 +02:00
|
|
|
+ "Attack:[/font] " + damageTypeDetails(heroState.attack);
|
|
|
|
// Show max attack range if ranged attack, also convert to tiles (4m per tile)
|
|
|
|
if (heroState.attack && heroState.attack.type == "Ranged")
|
|
|
|
tooltip += ", [font=\"serif-bold-13\"]Range:[/font] " + Math.round(heroState.attack.maxRange/4);
|
|
|
|
|
|
|
|
tooltip += "\n[font=\"serif-bold-13\"]Armor:[/font] " + damageTypeDetails(heroState.armour);
|
|
|
|
tooltip += "\n" + template.tooltip;
|
|
|
|
|
|
|
|
heroButton.tooltip = tooltip;
|
2014-01-06 14:32:48 +01:00
|
|
|
|
|
|
|
// update heros health bar
|
|
|
|
updateGUIStatusBar("heroHealthBar", heroState.hitpoints, heroState.maxHitpoints);
|
|
|
|
|
|
|
|
// define the hit points if not defined
|
2014-01-06 14:48:17 +01:00
|
|
|
if (!g_previousHeroHitPoints)
|
|
|
|
g_previousHeroHitPoints = heroState.hitpoints;
|
2014-01-06 14:32:48 +01:00
|
|
|
|
|
|
|
// check, if the health of the hero changed since the last update
|
2014-01-06 14:48:17 +01:00
|
|
|
if (heroState.hitpoints < g_previousHeroHitPoints)
|
2014-01-06 14:32:48 +01:00
|
|
|
{
|
2014-01-06 14:48:17 +01:00
|
|
|
g_previousHeroHitPoints = heroState.hitpoints;
|
2014-01-06 14:32:48 +01:00
|
|
|
// trigger the animation
|
|
|
|
fadeColour("heroHitOverlay", 100, 10000, {"r": 175,"g": 0,"b": 0,"o": 100}, colourFade_attackUnit, smoothColourFadeRestart_attackUnit);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-26 20:19:16 +02:00
|
|
|
function updateGroups()
|
|
|
|
{
|
|
|
|
var guiName = "Group";
|
2011-06-18 00:13:39 +02:00
|
|
|
g_Groups.update();
|
2011-04-26 20:19:16 +02:00
|
|
|
for (var i = 0; i < 10; i++)
|
|
|
|
{
|
2014-01-04 11:14:53 +01:00
|
|
|
var button = Engine.GetGUIObjectByName("unit"+guiName+"Button["+i+"]");
|
|
|
|
var label = Engine.GetGUIObjectByName("unit"+guiName+"Label["+i+"]").caption = i;
|
2011-04-26 20:19:16 +02:00
|
|
|
if (g_Groups.groups[i].getTotalCount() == 0)
|
|
|
|
button.hidden = true;
|
|
|
|
else
|
|
|
|
button.hidden = false;
|
2012-04-24 17:58:02 +02:00
|
|
|
button.onpress = (function(i) { return function() { performGroup((Engine.HotkeyIsPressed("selection.add") ? "add" : "select"), i); } })(i);
|
2011-06-06 21:31:34 +02:00
|
|
|
button.ondoublepress = (function(i) { return function() { performGroup("snap", i); } })(i);
|
2011-04-26 20:19:16 +02:00
|
|
|
}
|
|
|
|
var numButtons = i;
|
|
|
|
var rowLength = 1;
|
|
|
|
var numRows = Math.ceil(numButtons / rowLength);
|
2014-01-04 11:14:53 +01:00
|
|
|
var buttonSideLength = Engine.GetGUIObjectByName("unit"+guiName+"Button[0]").size.bottom;
|
2011-04-26 20:19:16 +02:00
|
|
|
var buttonSpacer = buttonSideLength+1;
|
|
|
|
for (var i = 0; i < numRows; i++)
|
|
|
|
layoutButtonRow(i, guiName, buttonSideLength, buttonSpacer, rowLength*i, rowLength*(i+1) );
|
|
|
|
}
|
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
function updateDebug()
|
2010-06-30 23:34:44 +02:00
|
|
|
{
|
2013-04-10 23:05:46 +02:00
|
|
|
var simState = GetSimState();
|
2014-01-04 11:14:53 +01:00
|
|
|
var debug = Engine.GetGUIObjectByName("debug");
|
2010-06-30 23:34:44 +02:00
|
|
|
|
2014-01-04 11:14:53 +01:00
|
|
|
if (Engine.GetGUIObjectByName("devDisplayState").checked)
|
2010-06-30 23:34:44 +02:00
|
|
|
{
|
|
|
|
debug.hidden = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug.hidden = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-06-09 18:40:29 +02:00
|
|
|
var conciseSimState = deepcopy(simState);
|
|
|
|
conciseSimState.players = "<<<omitted>>>";
|
|
|
|
var text = "simulation: " + uneval(conciseSimState);
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2010-06-30 23:34:44 +02:00
|
|
|
var selection = g_Selection.toList();
|
|
|
|
if (selection.length)
|
|
|
|
{
|
2013-12-08 11:02:19 +01:00
|
|
|
var entState = GetExtendedEntityState(selection[0]);
|
2010-06-30 23:34:44 +02:00
|
|
|
if (entState)
|
|
|
|
{
|
2010-08-28 23:12:52 +02:00
|
|
|
var template = GetTemplateData(entState.template);
|
2011-06-09 18:40:29 +02:00
|
|
|
text += "\n\nentity: {\n";
|
|
|
|
for (var k in entState)
|
|
|
|
text += " "+k+":"+uneval(entState[k])+"\n";
|
|
|
|
text += "}\n\ntemplate: " + uneval(template);
|
2010-06-30 23:34:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
debug.caption = text;
|
|
|
|
}
|
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
function updatePlayerDisplay()
|
2010-06-30 23:34:44 +02:00
|
|
|
{
|
2013-04-10 23:05:46 +02:00
|
|
|
var simState = GetSimState();
|
2010-06-30 23:34:44 +02:00
|
|
|
var playerState = simState.players[Engine.GetPlayerID()];
|
2010-06-30 23:41:04 +02:00
|
|
|
if (!playerState)
|
|
|
|
return;
|
|
|
|
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("resourceFood").caption = playerState.resourceCounts.food;
|
|
|
|
Engine.GetGUIObjectByName("resourceWood").caption = playerState.resourceCounts.wood;
|
|
|
|
Engine.GetGUIObjectByName("resourceStone").caption = playerState.resourceCounts.stone;
|
|
|
|
Engine.GetGUIObjectByName("resourceMetal").caption = playerState.resourceCounts.metal;
|
|
|
|
Engine.GetGUIObjectByName("resourcePop").caption = playerState.popCount + "/" + playerState.popLimit;
|
2011-08-31 04:41:21 +02:00
|
|
|
|
2012-04-20 19:21:04 +02:00
|
|
|
g_IsTrainingBlocked = playerState.trainingBlocked;
|
2010-06-30 23:34:44 +02:00
|
|
|
}
|
2011-09-11 05:30:41 +02:00
|
|
|
|
2012-07-31 04:03:25 +02:00
|
|
|
function selectAndMoveTo(ent)
|
|
|
|
{
|
|
|
|
var entState = GetEntityState(ent);
|
2013-04-06 21:32:07 +02:00
|
|
|
if (!entState || !entState.position)
|
2012-07-31 04:03:25 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
g_Selection.reset();
|
|
|
|
g_Selection.addList([ent]);
|
|
|
|
|
|
|
|
var position = entState.position;
|
|
|
|
Engine.CameraMoveTo(position.x, position.z);
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateResearchDisplay()
|
|
|
|
{
|
|
|
|
var researchStarted = Engine.GuiInterfaceCall("GetStartedResearch", Engine.GetPlayerID());
|
|
|
|
if (!researchStarted)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Set up initial positioning.
|
2014-01-04 11:14:53 +01:00
|
|
|
var buttonSideLength = Engine.GetGUIObjectByName("researchStartedButton[0]").size.right;
|
2012-07-31 04:03:25 +02:00
|
|
|
for (var i = 0; i < 10; ++i)
|
|
|
|
{
|
2014-01-04 11:14:53 +01:00
|
|
|
var button = Engine.GetGUIObjectByName("researchStartedButton[" + i + "]");
|
2012-07-31 04:03:25 +02:00
|
|
|
var size = button.size;
|
|
|
|
size.top = (4 + buttonSideLength) * i;
|
|
|
|
size.bottom = size.top + buttonSideLength;
|
|
|
|
button.size = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
var numButtons = 0;
|
|
|
|
for (var tech in researchStarted)
|
|
|
|
{
|
|
|
|
// Show at most 10 in-progress techs.
|
2012-07-31 05:39:35 +02:00
|
|
|
if (numButtons >= 10)
|
2012-07-31 04:03:25 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
var template = GetTechnologyData(tech);
|
2014-01-04 11:14:53 +01:00
|
|
|
var button = Engine.GetGUIObjectByName("researchStartedButton[" + numButtons + "]");
|
2012-07-31 04:03:25 +02:00
|
|
|
button.hidden = false;
|
2012-08-27 09:07:33 +02:00
|
|
|
button.tooltip = getEntityNames(template);
|
2012-07-31 04:03:25 +02:00
|
|
|
button.onpress = (function(e) { return function() { selectAndMoveTo(e) } })(researchStarted[tech].researcher);
|
|
|
|
|
|
|
|
var icon = "stretched:session/portraits/" + template.icon;
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("researchStartedIcon[" + numButtons + "]").sprite = icon;
|
2012-07-31 04:03:25 +02:00
|
|
|
|
|
|
|
// Scale the progress indicator.
|
2014-01-04 11:14:53 +01:00
|
|
|
var size = Engine.GetGUIObjectByName("researchStartedProgressSlider[" + numButtons + "]").size;
|
2012-07-31 04:03:25 +02:00
|
|
|
|
|
|
|
// Buttons are assumed to be square, so left/right offsets can be used for top/bottom.
|
|
|
|
size.top = size.left + Math.round(researchStarted[tech].progress * (size.right - size.left));
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("researchStartedProgressSlider[" + numButtons + "]").size = size;
|
2012-07-31 04:03:25 +02:00
|
|
|
|
|
|
|
++numButtons;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hide unused buttons.
|
|
|
|
for (var i = numButtons; i < 10; ++i)
|
2014-01-04 11:14:53 +01:00
|
|
|
Engine.GetGUIObjectByName("researchStartedButton[" + i + "]").hidden = true;
|
2012-07-31 04:03:25 +02:00
|
|
|
}
|
|
|
|
|
2013-04-10 23:05:46 +02:00
|
|
|
function updateTimeElapsedCounter()
|
2011-10-14 01:20:34 +02:00
|
|
|
{
|
2013-04-10 23:05:46 +02:00
|
|
|
var simState = GetSimState();
|
2013-04-04 01:24:22 +02:00
|
|
|
var speed = g_CurrentSpeed != 1.0 ? " (" + g_CurrentSpeed + "x)" : "";
|
2014-01-04 11:14:53 +01:00
|
|
|
var timeElapsedCounter = Engine.GetGUIObjectByName("timeElapsedCounter");
|
2013-04-04 01:24:22 +02:00
|
|
|
timeElapsedCounter.caption = timeToString(simState.timeElapsed) + speed;
|
2011-10-14 01:20:34 +02:00
|
|
|
}
|
2011-09-11 05:30:41 +02:00
|
|
|
|
2012-07-24 06:14:09 +02:00
|
|
|
// Toggles the display of status bars for all of the player's entities.
|
|
|
|
function recalculateStatusBarDisplay()
|
|
|
|
{
|
|
|
|
if (g_ShowAllStatusBars)
|
|
|
|
var entities = Engine.PickFriendlyEntitiesOnScreen(Engine.GetPlayerID());
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var selected = g_Selection.toList();
|
|
|
|
for each (var ent in g_Selection.highlighted)
|
|
|
|
selected.push(ent);
|
|
|
|
|
|
|
|
// Remove selected entities from the 'all entities' array, to avoid disabling their status bars.
|
|
|
|
var entities = Engine.GuiInterfaceCall("GetPlayerEntities").filter(
|
|
|
|
function(idx) { return (selected.indexOf(idx) == -1); }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Engine.GuiInterfaceCall("SetStatusBars", { "entities": entities, "enabled": g_ShowAllStatusBars });
|
|
|
|
}
|
|
|
|
|
2013-11-30 18:30:08 +01:00
|
|
|
// Update the additional list of entities to be highlighted.
|
|
|
|
function updateAdditionalHighlight()
|
|
|
|
{
|
|
|
|
var entsAdd = []; // list of entities units to be highlighted
|
|
|
|
var entsRemove = [];
|
|
|
|
var highlighted = g_Selection.toList();
|
|
|
|
for each (var ent in g_Selection.highlighted)
|
|
|
|
highlighted.push(ent);
|
|
|
|
|
|
|
|
if (g_ShowGuarding)
|
|
|
|
{
|
|
|
|
// flag the guarding entities to add in this additional highlight
|
|
|
|
for each (var sel in g_Selection.selected)
|
|
|
|
{
|
|
|
|
var state = GetEntityState(sel);
|
|
|
|
if (!state.guard || !state.guard.entities.length)
|
|
|
|
continue;
|
|
|
|
for each (var ent in state.guard.entities)
|
|
|
|
if (highlighted.indexOf(ent) == -1 && entsAdd.indexOf(ent) == -1)
|
|
|
|
entsAdd.push(ent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_ShowGuarded)
|
|
|
|
{
|
|
|
|
// flag the guarded entities to add in this additional highlight
|
|
|
|
for each (var sel in g_Selection.selected)
|
|
|
|
{
|
|
|
|
var state = GetEntityState(sel);
|
|
|
|
if (!state.unitAI || !state.unitAI.isGuarding)
|
|
|
|
continue;
|
|
|
|
var ent = state.unitAI.isGuarding;
|
|
|
|
if (highlighted.indexOf(ent) == -1 && entsAdd.indexOf(ent) == -1)
|
|
|
|
entsAdd.push(ent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// flag the entities to remove (from the previously added) from this additional highlight
|
|
|
|
for each (var ent in g_AdditionalHighlight)
|
|
|
|
if (highlighted.indexOf(ent) == -1 && entsAdd.indexOf(ent) == -1 && entsRemove.indexOf(ent) == -1)
|
|
|
|
entsRemove.push(ent);
|
|
|
|
|
|
|
|
_setHighlight(entsAdd , HIGHLIGHTED_ALPHA, true );
|
|
|
|
_setHighlight(entsRemove, 0 , false);
|
|
|
|
g_AdditionalHighlight = entsAdd;
|
|
|
|
}
|
|
|
|
|
2011-09-11 05:30:41 +02:00
|
|
|
// Temporarily adding this here
|
|
|
|
const AMBIENT_TEMPERATE = "temperate";
|
|
|
|
var currentAmbient;
|
|
|
|
function playRandomAmbient(type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case AMBIENT_TEMPERATE:
|
|
|
|
// Seem to need the underscore at the end of "temperate" to avoid crash
|
|
|
|
// (Might be caused by trying to randomly load day_temperate.xml)
|
|
|
|
// currentAmbient = newRandomSound("ambient", "temperate_", "dayscape");
|
|
|
|
|
|
|
|
const AMBIENT = "audio/ambient/dayscape/day_temperate_gen_03.ogg";
|
2013-06-10 15:58:43 +02:00
|
|
|
Engine.PlayAmbientSound( AMBIENT, true );
|
2011-09-11 05:30:41 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2013-09-21 16:48:19 +02:00
|
|
|
Engine.Console_Write("Unrecognized ambient type: " + type);
|
2011-09-11 05:30:41 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Temporarily adding this here
|
|
|
|
function stopAmbient()
|
|
|
|
{
|
|
|
|
if (currentAmbient)
|
|
|
|
{
|
2012-08-15 02:10:44 +02:00
|
|
|
currentAmbient.free();
|
2011-09-11 05:30:41 +02:00
|
|
|
currentAmbient = null;
|
|
|
|
}
|
2011-10-14 01:20:34 +02:00
|
|
|
}
|
2013-11-07 21:07:24 +01:00
|
|
|
// Send a report on the game status to the lobby
|
|
|
|
function reportGame(extendedSimState)
|
|
|
|
{
|
2013-11-08 16:28:44 +01:00
|
|
|
if (!Engine.HasXmppClient())
|
|
|
|
return;
|
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
// Resources gathered and used
|
|
|
|
var playerFoodGatheredString = "";
|
|
|
|
var playerWoodGatheredString = "";
|
|
|
|
var playerStoneGatheredString = "";
|
|
|
|
var playerMetalGatheredString = "";
|
|
|
|
var playerFoodUsedString = "";
|
|
|
|
var playerWoodUsedString = "";
|
|
|
|
var playerStoneUsedString = "";
|
|
|
|
var playerMetalUsedString = "";
|
|
|
|
// Resources exchanged
|
|
|
|
var playerFoodBoughtString = "";
|
|
|
|
var playerWoodBoughtString = "";
|
|
|
|
var playerStoneBoughtString = "";
|
|
|
|
var playerMetalBoughtString = "";
|
|
|
|
var playerFoodSoldString = "";
|
|
|
|
var playerWoodSoldString = "";
|
|
|
|
var playerStoneSoldString = "";
|
|
|
|
var playerMetalSoldString = "";
|
|
|
|
var playerTradeIncomeString = "";
|
|
|
|
// Unit Stats
|
|
|
|
var playerUnitsLostString = "";
|
|
|
|
var playerUnitsTrainedString = "";
|
|
|
|
var playerEnemyUnitsKilledString = "";
|
|
|
|
// Building stats
|
|
|
|
var playerBuildingsConstructedString = "";
|
|
|
|
var playerBuildingsLostString = "";
|
|
|
|
var playerEnemyBuildingsDestroyedString = "";
|
|
|
|
var playerCivCentersBuiltString = "";
|
|
|
|
var playerEnemyCivCentersDestroyedString = "";
|
|
|
|
// Tribute
|
|
|
|
var playerTributeSentString = "";
|
|
|
|
var playerTributeReceivedString = "";
|
|
|
|
// Various
|
|
|
|
var mapName = Engine.GetMapSettings().Name;
|
|
|
|
var playerStatesString = "";
|
|
|
|
var playerCivsString = "";
|
|
|
|
var playerPercentMapExploredString = "";
|
|
|
|
var playerTreasuresCollectedString = "";
|
|
|
|
|
|
|
|
// Serialize the statistics for each player into a comma-separated list.
|
|
|
|
for each (var player in extendedSimState.players)
|
|
|
|
{
|
|
|
|
playerStatesString += player.state + ",";
|
|
|
|
playerCivsString += player.civ + ",";
|
|
|
|
playerFoodGatheredString += player.statistics.resourcesGathered.food + ",";
|
|
|
|
playerWoodGatheredString += player.statistics.resourcesGathered.wood + ",";
|
|
|
|
playerStoneGatheredString += player.statistics.resourcesGathered.stone + ",";
|
|
|
|
playerMetalGatheredString += player.statistics.resourcesGathered.metal + ",";
|
|
|
|
playerFoodUsedString += player.statistics.resourcesUsed.food + ",";
|
|
|
|
playerWoodUsedString += player.statistics.resourcesUsed.wood + ",";
|
|
|
|
playerStoneUsedString += player.statistics.resourcesUsed.stone + ",";
|
|
|
|
playerMetalUsedString += player.statistics.resourcesUsed.metal + ",";
|
|
|
|
playerUnitsLostString += player.statistics.unitsLost + ",";
|
|
|
|
playerUnitsTrainedString += player.statistics.unitsTrained + ",";
|
|
|
|
playerEnemyUnitsKilledString += player.statistics.enemyUnitsKilled + ",";
|
|
|
|
playerBuildingsConstructedString += player.statistics.buildingsConstructed + ",";
|
|
|
|
playerBuildingsLostString += player.statistics.buildingsLost + ",";
|
|
|
|
playerEnemyBuildingsDestroyedString += player.statistics.enemyBuildingsDestroyed + ",";
|
|
|
|
playerFoodBoughtString += player.statistics.resourcesBought.food + ",";
|
|
|
|
playerWoodBoughtString += player.statistics.resourcesBought.wood + ",";
|
|
|
|
playerStoneBoughtString += player.statistics.resourcesBought.stone + ",";
|
|
|
|
playerMetalBoughtString += player.statistics.resourcesBought.metal + ",";
|
|
|
|
playerFoodSoldString += player.statistics.resourcesSold.food + ",";
|
|
|
|
playerWoodSoldString += player.statistics.resourcesSold.wood + ",";
|
|
|
|
playerStoneSoldString += player.statistics.resourcesSold.stone + ",";
|
|
|
|
playerMetalSoldString += player.statistics.resourcesSold.metal + ",";
|
|
|
|
playerTributeSentString += player.statistics.tributesSent + ",";
|
|
|
|
playerTributeReceivedString += player.statistics.tributesReceived + ",";
|
|
|
|
playerPercentMapExploredString += player.statistics.precentMapExplored = ",";
|
|
|
|
playerCivCentersBuiltString += player.statistics.civCentresBuilt + ",";
|
|
|
|
playerEnemyCivCentersDestroyedString += player.statistics.enemyCivCentresDestroyed + ",";
|
|
|
|
playerTreasuresCollectedString += player.statistics.treasuresCollected + ",";
|
|
|
|
playerTradeIncomeString += player.statistics.tradeIncome + ",";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the report with serialized data
|
|
|
|
Engine.SendGameReport({
|
|
|
|
"timeElapsed" : extendedSimState.timeElapsed,
|
|
|
|
"playerStates" : playerStatesString,
|
|
|
|
"playerID": Engine.GetPlayerID(),
|
|
|
|
"matchID": g_MatchID,
|
|
|
|
"civs" : playerCivsString,
|
|
|
|
"mapName" : mapName,
|
|
|
|
"foodGathered": playerFoodGatheredString,
|
|
|
|
"woodGathered": playerWoodGatheredString,
|
|
|
|
"stoneGathered": playerStoneGatheredString,
|
|
|
|
"metalGathered": playerMetalGatheredString,
|
|
|
|
"foodUsed": playerFoodUsedString,
|
|
|
|
"woodUsed": playerWoodUsedString,
|
|
|
|
"stoneUsed": playerStoneUsedString,
|
|
|
|
"metalUsed": playerMetalUsedString,
|
|
|
|
"unitsLost": playerUnitsLostString,
|
|
|
|
"unitsTrained": playerUnitsTrainedString,
|
|
|
|
"enemyUnitsKilled": playerEnemyUnitsKilledString,
|
|
|
|
"buildingsLost": playerBuildingsLostString,
|
|
|
|
"buildingsConstructed": playerBuildingsConstructedString,
|
|
|
|
"enemyBuildingsDestroyed": playerEnemyBuildingsDestroyedString,
|
|
|
|
"foodBought": playerFoodBoughtString,
|
|
|
|
"woodBought": playerWoodBoughtString,
|
|
|
|
"stoneBought": playerStoneBoughtString,
|
|
|
|
"metalBought": playerMetalBoughtString,
|
|
|
|
"foodSold": playerFoodSoldString,
|
|
|
|
"woodSold": playerWoodSoldString,
|
|
|
|
"stoneSold": playerStoneSoldString,
|
|
|
|
"metalSold": playerMetalSoldString,
|
|
|
|
"tributeSent": playerTributeSentString,
|
|
|
|
"tributeReceived": playerTributeReceivedString,
|
|
|
|
"precentMapExplored": playerPercentMapExploredString,
|
|
|
|
"civCentersBuilt": playerCivCentersBuiltString,
|
|
|
|
"enemyCivCentersDestroyed": playerEnemyCivCentersDestroyedString,
|
|
|
|
"treasuresCollected": playerTreasuresCollectedString,
|
|
|
|
"tradeIncome": playerTradeIncomeString
|
|
|
|
});
|
|
|
|
}
|