Index: ps/trunk/binaries/data/mods/public/gui/session/chat/Chat.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/chat/Chat.js
+++ ps/trunk/binaries/data/mods/public/gui/session/chat/Chat.js
@@ -35,8 +35,10 @@
this.ChatHistory.displayChatHistory();
});
- registerPlayersFinishedHandler(this.onUpdatePlayers.bind(this));
- playerViewControl.registerViewedPlayerChangeHandler(this.onUpdatePlayers.bind(this));
+ let updater = this.onUpdatePlayers.bind(this);
+ registerPlayersFinishedHandler(updater);
+ registerPlayerAssignmentsChangeHandler(updater);
+ playerViewControl.registerViewedPlayerChangeHandler(updater);
Engine.SetGlobalHotkey("chat", this.openPage.bind(this));
Engine.SetGlobalHotkey("privatechat", this.openPage.bind(this));
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyGamelistReporter.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyGamelistReporter.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyGamelistReporter.js
@@ -0,0 +1,90 @@
+/**
+ * Send the current list of players, teams, AIs, observers and defeated/won and offline states to the lobby.
+ * This report excludes the matchsettings, since they do not change during the match.
+ *
+ * The playerData format from g_GameAttributes is kept to reuse the GUI function presenting the data,
+ * but the payload size is minimized by only extracting properties relevant for display.
+ */
+class LobbyGamelistReporter
+{
+ constructor()
+ {
+ if (!LobbyGamelistReporter.Available())
+ throw new Error("Lobby gamelist service not available");
+
+ let updater = this.sendGamelistUpdate.bind(this);
+ registerPlayersInitHandler(updater);
+ registerPlayersFinishedHandler(updater);
+ registerPlayerAssignmentsChangeHandler(updater);
+ }
+
+ sendGamelistUpdate()
+ {
+ Engine.SendChangeStateGame(
+ this.countConnectedPlayers(),
+ playerDataToStringifiedTeamList([...this.getPlayers(), ...this.getObservers()]));
+ }
+
+ getPlayers()
+ {
+ let players = [];
+
+ // Skip gaia
+ for (let playerID = 1; playerID < g_GameAttributes.settings.PlayerData.length; ++playerID)
+ {
+ let pData = g_GameAttributes.settings.PlayerData[playerID];
+
+ let player = {
+ "Name": pData.Name,
+ "Civ": pData.Civ
+ };
+
+ if (g_GameAttributes.settings.LockTeams)
+ player.Team = pData.Team;
+
+ if (pData.AI)
+ {
+ player.AI = pData.AI;
+ player.AIDiff = pData.AIDiff;
+ player.AIBehavior = pData.AIBehavior;
+ }
+
+ if (g_Players[playerID].offline)
+ player.Offline = true;
+
+ // Whether the player has won or was defeated
+ let state = g_Players[playerID].state;
+ if (state != "active")
+ player.State = state;
+
+ players.push(player);
+ }
+ return players;
+ }
+
+ getObservers()
+ {
+ let observers = [];
+ for (let guid in g_PlayerAssignments)
+ if (g_PlayerAssignments[guid].player == -1)
+ observers.push({
+ "Name": g_PlayerAssignments[guid].name,
+ "Team": "observer"
+ });
+ return observers;
+ }
+
+ countConnectedPlayers()
+ {
+ let connectedPlayers = 0;
+ for (let guid in g_PlayerAssignments)
+ if (g_PlayerAssignments[guid].player != -1)
+ ++connectedPlayers;
+ return connectedPlayers;
+ }
+}
+
+LobbyGamelistReporter.Available = function()
+{
+ return Engine.HasXmppClient() && g_IsController;
+};
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Buildings.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Buildings.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Buildings.js
@@ -0,0 +1,23 @@
+/**
+ * This class reports the buildings built, lost and destroyed of some selected structure classes.
+ */
+LobbyRatingReport.prototype.Buildings = class
+{
+ insertValues(report, playerStates)
+ {
+ let lower = txt => txt.substr(0, 1).toLowerCase() + txt.substr(1);
+ let time = playerStates[0].sequences.time.length - 1;
+
+ for (let buildingClass in playerStates[0].sequences.buildingsConstructed)
+ report[lower(buildingClass) + "BuildingsConstructed"] = playerStates.map(playerState =>
+ playerState.sequences.buildingsConstructed[buildingClass][time]).join(",") + ",";
+
+ for (let buildingClass in playerStates[0].sequences.buildingsLost)
+ report[lower(buildingClass) + "BuildingsLost"] = playerStates.map(playerState =>
+ playerState.sequences.buildingsLost[buildingClass][time]).join(",") + ",";
+
+ for (let buildingClass in playerStates[0].sequences.enemyBuildingsDestroyed)
+ report["enemy" + buildingClass + "BuildingsDestroyed"] = playerStates.map(playerState =>
+ playerState.sequences.enemyBuildingsDestroyed[buildingClass][time]).join(",") + ",";
+ }
+};
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Misc.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Misc.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Misc.js
@@ -0,0 +1,21 @@
+/**
+ * This class counts trade, tributes, loot and map exploration.
+ */
+LobbyRatingReport.prototype.Misc = class
+{
+ insertValues(report, playerStates)
+ {
+ for (let category of this.MiscCategories)
+ report[category] = playerStates.map(playerState =>
+ playerState.sequences[category][playerState.sequences.time.length - 1]).join(",") + ",";
+ }
+};
+
+LobbyRatingReport.prototype.Misc.prototype.MiscCategories = [
+ "tradeIncome",
+ "tributesSent",
+ "tributesReceived",
+ "treasuresCollected",
+ "lootCollected",
+ "percentMapExplored"
+];
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Players.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Players.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Players.js
@@ -0,0 +1,15 @@
+/**
+ * This class reports the chosen settings and victory state of the participating players.
+ */
+LobbyRatingReport.prototype.Players = class
+{
+ insertValues(report, playerStates)
+ {
+ Object.assign(report, {
+ "playerStates": playerStates.map(playerState => playerState.state).join(",") + ",",
+ "civs": playerStates.map(playerState => playerState.civ).join(",") + ",",
+ "teams": playerStates.map(playerState => playerState.team).join(",") + ",",
+ "teamsLocked": String(playerStates.every(playerState => playerState.teamsLocked))
+ });
+ }
+};
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Resources.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Resources.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Resources.js
@@ -0,0 +1,25 @@
+/**
+ * This class reports the amount of resources that each player has obtained or used.
+ */
+LobbyRatingReport.prototype.Resources = class
+{
+ insertValues(report, playerStates)
+ {
+ let time = playerStates[0].sequences.time.length - 1;
+
+ for (let action of this.Actions)
+ for (let resCode of g_ResourceData.GetCodes())
+ report[resCode + action] = playerStates.map(playerState =>
+ playerState.sequences["resources" + action][resCode][time]).join(",") + ",";
+
+ report.vegetarianFoodGathered = playerStates.map(
+ playerState => playerState.sequences.resourcesGathered.vegetarianFood[time]).join(",") + ",";
+ }
+};
+
+LobbyRatingReport.prototype.Resources.prototype.Actions = [
+ "Gathered",
+ "Used",
+ "Sold",
+ "Bought"
+];
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Score.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Score.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Score.js
@@ -0,0 +1,57 @@
+/**
+ * This class computes the economic and military score points of each player.
+ */
+LobbyRatingReport.prototype.Score = class
+{
+ insertValues(report, playerStates)
+ {
+ Object.assign(report, {
+ "economyScore": playerStates.map(this.economyScore.bind(this)).join(",") + ",",
+ "militaryScore": playerStates.map(this.militaryScore.bind(this)).join(",") + ",",
+ "totalScore": playerStates.map(this.totalScore.bind(this)).join(",") + ",",
+ });
+ }
+
+ /**
+ * Keep this in sync with summary screen score computation!
+ */
+ economyScore(playerState)
+ {
+ let total = 0;
+ let time = playerState.sequences.time.length - 1;
+
+ // Notice that this avoids the vegetarianFood property of resourcesGathered
+ for (let resCode of g_ResourceData.GetCodes())
+ total += playerState.sequences.resourcesGathered[resCode][time];
+
+ total += playerState.sequences.tradeIncome[time];
+
+ return Math.round(total / 10);
+ }
+
+ militaryScore(playerState)
+ {
+ let time = playerState.sequences.time.length - 1;
+
+ let totalDestruction =
+ playerState.sequences.enemyUnitsKilledValue[time] +
+ playerState.sequences.enemyBuildingsDestroyedValue[time] +
+ playerState.sequences.unitsCapturedValue[time] +
+ playerState.sequences.buildingsCapturedValue[time];
+
+ return Math.round(totalDestruction / 10);
+ }
+
+ explorationScore(playerState)
+ {
+ let time = playerState.sequences.time.length - 1;
+ return playerState.sequences.percentMapExplored[time] * 10;
+ }
+
+ totalScore(playerState)
+ {
+ return this.economyScore(playerState) +
+ this.militaryScore(playerState) +
+ this.explorationScore(playerState);
+ }
+};
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Units.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Units.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReport/Units.js
@@ -0,0 +1,23 @@
+/**
+ * This class reports the units trained, lost and killed of some selected unit classes.
+ */
+LobbyRatingReport.prototype.Units = class
+{
+ insertValues(report, playerStates)
+ {
+ let lower = txt => txt.substr(0, 1).toLowerCase() + txt.substr(1);
+ let time = playerStates[0].sequences.time.length - 1;
+
+ for (let unitClass in playerStates[0].sequences.unitsTrained)
+ report[lower(unitClass) + "UnitsTrained"] = playerStates.map(playerState =>
+ playerState.sequences.unitsTrained[unitClass][time]).join(",") + ",";
+
+ for (let unitClass in playerStates[0].sequences.unitsLost)
+ report[lower(unitClass) + "UnitsLost"] = playerStates.map(playerState =>
+ playerState.sequences.unitsLost[unitClass][time]).join(",") + ",";
+
+ for (let unitClass in playerStates[0].sequences.enemyUnitsKilled)
+ report["enemy" + unitClass + "UnitsKilled"] = playerStates.map(playerState =>
+ playerState.sequences.enemyUnitsKilled[unitClass][time]).join(",") + ",";
+ }
+};
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReporter.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReporter.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyRatingReporter.js
@@ -0,0 +1,53 @@
+/**
+ * This is a container for classes that extend the report object.
+ * Keep in sync with the lobby bot code, the StatisticsTracker.
+ */
+class LobbyRatingReport
+{
+}
+
+/**
+ * This class reports the state of the current game to the lobby bot when the current player has been defeated or won.
+ */
+class LobbyRatingReporter
+{
+ constructor()
+ {
+ if (!LobbyRatingReporter.Available())
+ throw new Error("Lobby rating service is not available");
+
+ registerPlayersFinishedHandler(this.onPlayersFinished.bind(this));
+ }
+
+ onPlayersFinished(players)
+ {
+ // Observers don't send the state, players send it only once per match
+ if (players.indexOf(Engine.GetPlayerID()) != -1)
+ return;
+
+ let extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
+
+ let report = {
+ "playerID": Engine.GetPlayerID(),
+ "matchID": g_GameAttributes.matchID,
+ "mapName": g_GameAttributes.settings.Name,
+ "timeElapsed": extendedSimState.timeElapsed,
+ };
+
+ // Remove gaia
+ let playerStates = clone(extendedSimState.players).slice(1);
+
+ for (let name in LobbyRatingReport.prototype)
+ new LobbyRatingReport.prototype[name]().insertValues(report, playerStates);
+
+ Engine.SendGameReport(report);
+ }
+}
+
+/**
+ * Only 1v1 games are rated, account for gaia.
+ */
+LobbyRatingReporter.Available = function()
+{
+ return Engine.HasXmppClient() && Engine.IsRankedGame() && g_GameAttributes.settings.PlayerData.length == 3;
+};
Index: ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyService.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyService.js
+++ ps/trunk/binaries/data/mods/public/gui/session/lobby/LobbyService.js
@@ -0,0 +1,18 @@
+/**
+ * @file The lobby scripting code is kept separate from the rest of the session to
+ * ease distribution of the game without any lobby code.
+ */
+
+/**
+ * The host sends a gamelist update everytime a client joins or leaves the match.
+ */
+var g_LobbyGamelistReporter =
+ LobbyGamelistReporter.Available() &&
+ new LobbyGamelistReporter();
+
+/**
+ * The participants of a rated 1v1 match send a rating report when the winner was decided.
+ */
+var g_LobbyRatingReporter =
+ LobbyRatingReporter.Available() &&
+ new LobbyRatingReporter();
Index: ps/trunk/binaries/data/mods/public/gui/session/messages.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/messages.js
+++ ps/trunk/binaries/data/mods/public/gui/session/messages.js
@@ -14,6 +14,11 @@
var g_TutorialNewMessageTags = { "color": "yellow" };
/**
+ * These handlers are called everytime a client joins or disconnects.
+ */
+var g_PlayerAssignmentsChangeHandlers = new Set();
+
+/**
* Handle all netmessage types that can occur.
*/
var g_NetMessageTypes = {
@@ -281,6 +286,11 @@
}
};
+function registerPlayerAssignmentsChangeHandler(handler)
+{
+ g_PlayerAssignmentsChangeHandlers.add(handler);
+}
+
/**
* Loads all known cheat commands.
*/
@@ -561,9 +571,11 @@
onClientJoin(guid);
});
+ for (let handler of g_PlayerAssignmentsChangeHandlers)
+ handler();
+
+ // TODO: use subscription instead
updateGUIObjects();
- g_Chat.onUpdatePlayers();
- sendLobbyPlayerlistUpdate();
}
function onClientJoin(guid)
Index: ps/trunk/binaries/data/mods/public/gui/session/session.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/session.js
+++ ps/trunk/binaries/data/mods/public/gui/session/session.js
@@ -154,7 +154,7 @@
* These events are fired when the user has performed a hotkey assignment change.
* Currently only fired on init, but to be fired from any hotkey editor dialog.
*/
-var g_HotkeyChangeHandlers = [];
+var g_HotkeyChangeHandlers = new Set();
/**
* Top coordinate of the research list.
@@ -312,8 +312,6 @@
g_Players = hotloadData.player;
}
- sendLobbyPlayerlistUpdate();
-
// TODO: use event instead
onSimulationUpdate();
@@ -352,7 +350,7 @@
function registerHotkeyChangeHandler(handler)
{
- g_HotkeyChangeHandlers.push(handler);
+ g_HotkeyChangeHandlers.add(handler);
}
function updatePlayerData()
@@ -505,11 +503,6 @@
"players": players
});
- if (players.indexOf(Engine.GetPlayerID()) != -1)
- reportGame();
-
- sendLobbyPlayerlistUpdate();
-
updatePlayerData();
// TODO: The other calls in this function should move too
@@ -1161,259 +1154,3 @@
g_ResearchListTop = 4 + 14 * counters.length;
}
-
-/**
- * Send the current list of players, teams, AIs, observers and defeated/won and offline states to the lobby.
- * The playerData format from g_GameAttributes is kept to reuse the GUI function presenting the data.
- */
-function sendLobbyPlayerlistUpdate()
-{
- if (!g_IsController || !Engine.HasXmppClient())
- return;
-
- // Extract the relevant player data and minimize packet load
- let minPlayerData = [];
- for (let playerID in g_GameAttributes.settings.PlayerData)
- {
- if (+playerID == 0)
- continue;
-
- let pData = g_GameAttributes.settings.PlayerData[playerID];
-
- let minPData = { "Name": pData.Name, "Civ": pData.Civ };
-
- if (g_GameAttributes.settings.LockTeams)
- minPData.Team = pData.Team;
-
- if (pData.AI)
- {
- minPData.AI = pData.AI;
- minPData.AIDiff = pData.AIDiff;
- minPData.AIBehavior = pData.AIBehavior;
- }
-
- if (g_Players[playerID].offline)
- minPData.Offline = true;
-
- // Whether the player has won or was defeated
- let state = g_Players[playerID].state;
- if (state != "active")
- minPData.State = state;
-
- minPlayerData.push(minPData);
- }
-
- // Add observers
- let connectedPlayers = 0;
- for (let guid in g_PlayerAssignments)
- {
- let pData = g_GameAttributes.settings.PlayerData[g_PlayerAssignments[guid].player];
-
- if (pData)
- ++connectedPlayers;
- else
- minPlayerData.push({
- "Name": g_PlayerAssignments[guid].name,
- "Team": "observer"
- });
- }
-
- Engine.SendChangeStateGame(connectedPlayers, playerDataToStringifiedTeamList(minPlayerData));
-}
-
-/**
- * Send a report on the gamestatus to the lobby.
- * Keep in sync with source/tools/XpartaMuPP/LobbyRanking.py
- */
-function reportGame()
-{
- // Only 1v1 games are rated (and Gaia is part of g_Players)
- if (!Engine.HasXmppClient() || !Engine.IsRankedGame() ||
- g_Players.length != 3 || Engine.GetPlayerID() == -1)
- return;
-
- let extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
-
- let unitsClasses = [
- "total",
- "Infantry",
- "Worker",
- "FemaleCitizen",
- "Cavalry",
- "Champion",
- "Hero",
- "Siege",
- "Ship",
- "Trader"
- ];
-
- let unitsCountersTypes = [
- "unitsTrained",
- "unitsLost",
- "enemyUnitsKilled"
- ];
-
- let buildingsClasses = [
- "total",
- "CivCentre",
- "House",
- "Economic",
- "Outpost",
- "Military",
- "Fortress",
- "Wonder"
- ];
-
- let buildingsCountersTypes = [
- "buildingsConstructed",
- "buildingsLost",
- "enemyBuildingsDestroyed"
- ];
-
- let resourcesTypes = [
- "wood",
- "food",
- "stone",
- "metal"
- ];
-
- let resourcesCounterTypes = [
- "resourcesGathered",
- "resourcesUsed",
- "resourcesSold",
- "resourcesBought"
- ];
-
- let misc = [
- "tradeIncome",
- "tributesSent",
- "tributesReceived",
- "treasuresCollected",
- "lootCollected",
- "percentMapExplored"
- ];
-
- let playerStatistics = {};
-
- // Unit Stats
- for (let unitCounterType of unitsCountersTypes)
- {
- if (!playerStatistics[unitCounterType])
- playerStatistics[unitCounterType] = { };
- for (let unitsClass of unitsClasses)
- playerStatistics[unitCounterType][unitsClass] = "";
- }
-
- playerStatistics.unitsLostValue = "";
- playerStatistics.unitsKilledValue = "";
- // Building stats
- for (let buildingCounterType of buildingsCountersTypes)
- {
- if (!playerStatistics[buildingCounterType])
- playerStatistics[buildingCounterType] = { };
- for (let buildingsClass of buildingsClasses)
- playerStatistics[buildingCounterType][buildingsClass] = "";
- }
-
- playerStatistics.buildingsLostValue = "";
- playerStatistics.enemyBuildingsDestroyedValue = "";
- // Resources
- for (let resourcesCounterType of resourcesCounterTypes)
- {
- if (!playerStatistics[resourcesCounterType])
- playerStatistics[resourcesCounterType] = { };
- for (let resourcesType of resourcesTypes)
- playerStatistics[resourcesCounterType][resourcesType] = "";
- }
- playerStatistics.resourcesGathered.vegetarianFood = "";
-
- for (let type of misc)
- playerStatistics[type] = "";
-
- // Total
- playerStatistics.economyScore = "";
- playerStatistics.militaryScore = "";
- playerStatistics.totalScore = "";
-
- let mapName = g_GameAttributes.settings.Name;
- let playerStates = "";
- let playerCivs = "";
- let teams = "";
- let teamsLocked = true;
-
- // Serialize the statistics for each player into a comma-separated list.
- // Ignore gaia
- for (let i = 1; i < extendedSimState.players.length; ++i)
- {
- let player = extendedSimState.players[i];
- let maxIndex = player.sequences.time.length - 1;
-
- playerStates += player.state + ",";
- playerCivs += player.civ + ",";
- teams += player.team + ",";
- teamsLocked = teamsLocked && player.teamsLocked;
- for (let resourcesCounterType of resourcesCounterTypes)
- for (let resourcesType of resourcesTypes)
- playerStatistics[resourcesCounterType][resourcesType] += player.sequences[resourcesCounterType][resourcesType][maxIndex] + ",";
- playerStatistics.resourcesGathered.vegetarianFood += player.sequences.resourcesGathered.vegetarianFood[maxIndex] + ",";
-
- for (let unitCounterType of unitsCountersTypes)
- for (let unitsClass of unitsClasses)
- playerStatistics[unitCounterType][unitsClass] += player.sequences[unitCounterType][unitsClass][maxIndex] + ",";
-
- for (let buildingCounterType of buildingsCountersTypes)
- for (let buildingsClass of buildingsClasses)
- playerStatistics[buildingCounterType][buildingsClass] += player.sequences[buildingCounterType][buildingsClass][maxIndex] + ",";
- let total = 0;
- for (let type in player.sequences.resourcesGathered)
- total += player.sequences.resourcesGathered[type][maxIndex];
-
- playerStatistics.economyScore += total + ",";
- playerStatistics.militaryScore += Math.round((player.sequences.enemyUnitsKilledValue[maxIndex] +
- player.sequences.enemyBuildingsDestroyedValue[maxIndex]) / 10) + ",";
- playerStatistics.totalScore += (total + Math.round((player.sequences.enemyUnitsKilledValue[maxIndex] +
- player.sequences.enemyBuildingsDestroyedValue[maxIndex]) / 10)) + ",";
-
- for (let type of misc)
- playerStatistics[type] += player.sequences[type][maxIndex] + ",";
- }
-
- // Send the report with serialized data
- let reportObject = {};
- reportObject.timeElapsed = extendedSimState.timeElapsed;
- reportObject.playerStates = playerStates;
- reportObject.playerID = Engine.GetPlayerID();
- reportObject.matchID = g_GameAttributes.matchID;
- reportObject.civs = playerCivs;
- reportObject.teams = teams;
- reportObject.teamsLocked = String(teamsLocked);
- reportObject.ceasefireActive = String(extendedSimState.ceasefireActive);
- reportObject.ceasefireTimeRemaining = String(extendedSimState.ceasefireTimeRemaining);
- reportObject.mapName = mapName;
- reportObject.economyScore = playerStatistics.economyScore;
- reportObject.militaryScore = playerStatistics.militaryScore;
- reportObject.totalScore = playerStatistics.totalScore;
- for (let rct of resourcesCounterTypes)
- for (let rt of resourcesTypes)
- reportObject[rt + rct.substr(9)] = playerStatistics[rct][rt];
- // eg. rt = food rct.substr = Gathered rct = resourcesGathered
-
- reportObject.vegetarianFoodGathered = playerStatistics.resourcesGathered.vegetarianFood;
- for (let type of unitsClasses)
- {
- // eg. type = Infantry (type.substr(0,1)).toLowerCase()+type.substr(1) = infantry
- reportObject[(type.substr(0, 1)).toLowerCase() + type.substr(1) + "UnitsTrained"] = playerStatistics.unitsTrained[type];
- reportObject[(type.substr(0, 1)).toLowerCase() + type.substr(1) + "UnitsLost"] = playerStatistics.unitsLost[type];
- reportObject["enemy" + type + "UnitsKilled"] = playerStatistics.enemyUnitsKilled[type];
- }
- for (let type of buildingsClasses)
- {
- reportObject[(type.substr(0, 1)).toLowerCase() + type.substr(1) + "BuildingsConstructed"] = playerStatistics.buildingsConstructed[type];
- reportObject[(type.substr(0, 1)).toLowerCase() + type.substr(1) + "BuildingsLost"] = playerStatistics.buildingsLost[type];
- reportObject["enemy" + type + "BuildingsDestroyed"] = playerStatistics.enemyBuildingsDestroyed[type];
- }
- for (let type of misc)
- reportObject[type] = playerStatistics[type];
-
- Engine.SendGameReport(reportObject);
-}
Index: ps/trunk/binaries/data/mods/public/gui/session/session.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/session.xml
+++ ps/trunk/binaries/data/mods/public/gui/session/session.xml
@@ -8,6 +8,8 @@
+
+
Index: ps/trunk/binaries/data/mods/public/gui/summary/counters.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/summary/counters.js
+++ ps/trunk/binaries/data/mods/public/gui/summary/counters.js
@@ -120,9 +120,14 @@
}
}
+/**
+ * Keep this in sync with the score computation in session/ for the lobby rating reports!
+ */
function calculateEconomyScore(playerState, index)
{
let total = 0;
+
+ // Notice that this skips the vegetarianFood property of resourcesGathered
for (let type of g_ResourceData.GetCodes())
total += playerState.sequences.resourcesGathered[type][index];
@@ -130,6 +135,9 @@
return Math.round(total / 10);
}
+/**
+ * Keep this in sync with the score computation in session/ for the lobby rating reports!
+ */
function calculateMilitaryScore(playerState, index)
{
return Math.round((playerState.sequences.enemyUnitsKilledValue[index] +
@@ -138,12 +146,18 @@
playerState.sequences.buildingsCapturedValue[index]) / 10);
}
+/**
+ * Keep this in sync with the score computation in session/ for the lobby rating reports!
+ */
function calculateExplorationScore(playerState, index)
{
return playerState.sequences.percentMapExplored[index] * 10;
}
-function calculateScoreTotal(playerState, index)
+/**
+ * Keep this in sync with the score computation in session/ for the lobby rating reports!
+ */
+ function calculateScoreTotal(playerState, index)
{
return calculateEconomyScore(playerState, index) +
calculateMilitaryScore(playerState, index) +