Ticket #1090: playercomponent_savegamesummaryreplaycleanup.patch

File playercomponent_savegamesummaryreplaycleanup.patch, 45.1 KB (added by elexis, 8 years ago)

cleans up related and related related code in several ways, most notably changes the player component to trigger the defeat directly instead of sending a message to it to remove duplicate messages.

  • binaries/data/mods/public/gui/common/functions_utility.js

    function clearChatMessages()  
    206206    }
    207207}
    208208
    209209/**
    210210 * Returns a formatted string describing the player assignments.
    211  * Including civs, teams, AI settings and player colors
    212  * which are given in data (array of objects per player).
     211 * Needs g_CivData to translate!
    213212 *
     213 * @param {object} playerDataArray - As known from gamesetup and simstate.
     214 * @param {(string[]|false)} playerStates - One of "won", "defeated", "active" for each player.
    214215 * @returns {string}
    215216 */
    216 function formatPlayerInfo(data)
     217function formatPlayerInfo(playerDataArray, playerStates)
    217218{
    218219    let playerDescriptions = {};
    219220    let playerIdx = 0;
    220     for (let playerData of data)
     221
     222    for (let playerData of playerDataArray)
    221223    {
     224        if (playerData == null || playerData.Civ == "gaia")
     225            continue;
     226
    222227        ++playerIdx;
    223228        let teamIdx = playerData.Team;
    224         let showDefeated = playerData.state && playerData.state == "defeated";
    225229        let isAI = playerData.AI && playerData.AI != "";
     230        let playerState = playerStates && playerStates[playerIdx];
     231        let isActive = !playerState || playerState == "active";
    226232
    227         let translated;
    228         if (!isAI && !showDefeated)
    229             translated = translateWithContext("replay", "%(playerName)s (%(civ)s)");
    230         else if (!isAI && showDefeated)
    231             translated = translateWithContext("replay", "%(playerName)s (%(civ)s, defeated)");
    232         else if (isAI && !showDefeated)
    233             translated = translateWithContext("replay", "%(playerName)s (%(civ)s, %(AIdifficulty)s %(AIname)s)");
     233        let playerDescription;
     234        if (isAI)
     235        {
     236            if (isActive)
     237                playerDescription = translateWithContext("replay", "%(playerName)s (%(civ)s, %(AIdifficulty)s %(AIname)s, %(state)s)");
     238            else
     239                playerDescription = translateWithContext("replay", "%(playerName)s (%(civ)s, %(AIdifficulty)s %(AIname)s)");
     240        }
    234241        else
    235             translated = translateWithContext("replay", "%(playerName)s (%(civ)s, %(AIdifficulty)s %(AIname)s, defeated)");
     242        {
     243            if (isActive)
     244                playerDescription = translateWithContext("replay", "%(playerName)s (%(civ)s, %(state)s)");
     245            else
     246                playerDescription = translateWithContext("replay", "%(playerName)s (%(civ)s)");
     247        }
    236248
    237249        // Sort player descriptions by team
    238250        if (!playerDescriptions[teamIdx])
    239251            playerDescriptions[teamIdx] = [];
    240         playerDescriptions[teamIdx].push(sprintf(translated, {
    241             "playerName": '[color="' + rgbToGuiColor(playerData.Color) + '"]' + escapeText(playerData.Name) + "[/color]",
    242             "civ": playerData.Civ,
     252
     253        playerDescriptions[teamIdx].push(sprintf(playerDescription, {
     254            "playerName":
     255                '[color="' +
     256                rgbToGuiColor(playerData.Color || g_Settings.PlayerDefaults[playerIdx].Color) +
     257                '"]' + escapeText(playerData.Name) + "[/color]",
     258
     259            "civ":
     260                !playerData.Civ ?
     261                    translate("Unknown Civilization") :
     262                        g_CivData && g_CivData[playerData.Civ] && g_CivData[playerData.Civ].Name ?
     263                        translate(g_CivData[playerData.Civ].Name) :
     264                        playerData.Civ,
     265
     266            "state":
     267                playerState == "defeated" ?
     268                    translateWithContext("playerState", "Defeated") :
     269                    translateWithContext("playerState", "Won"),
     270
    243271            "AIname": isAI ? translateAIName(playerData.AI) : "",
    244272            "AIdifficulty": isAI ? translateAIDifficulty(playerData.AIDiff) : ""
    245273        }));
    246274    }
    247275
    function formatPlayerInfo(data)  
    251279    if (teams.length == 1)
    252280        return playerDescriptions[teams[0]].join("\n") + "\n";
    253281
    254282    // If there are teams, merge "Team N:" + playerDescriptions
    255283    return teams.map(team => {
    256         let teamCaption = (team == -1) ? translate("No Team") : sprintf(translate("Team %(team)s"), { "team": +team + 1 });
    257         return '[font="sans-bold-14"]' + teamCaption + "[/font]:\n" + playerDescriptions[team].join("\n");
     284
     285        let teamCaption = team == -1 ?
     286            translate("No Team") :
     287            sprintf(translate("Team %(team)s"), { "team": +team + 1 });
     288
     289        return sprintf(translateWithContext("replay", "%(team)s:\n%(playerDescriptions)s"), {
     290            "team": '[font="sans-bold-14"]' + teamCaption + "[/font]",
     291            "playerDescriptions": playerDescriptions[team].join("\n")
     292        });
    258293    }).join("\n\n");
    259294}
  • binaries/data/mods/public/gui/replaymenu/replay_menu.js

     
    22 * Used for checking replay compatibility.
    33 */
    44const g_EngineInfo = Engine.GetEngineInfo();
    55
    66/**
    7  * To show the titles of the selected civs in the replay details.
     7 * Needed for formatPlayerInfo to show the player civs in the details.
    88 */
    99const g_CivData = loadCivData();
    1010
    1111/**
    1212 * Used for creating the mapsize filter.
    function displayReplayList()  
    188188    if (replaySelection.selected != -1)
    189189        g_SelectedReplayDirectory = g_ReplaysFiltered[replaySelection.selected].directory;
    190190
    191191    filterReplays();
    192192
    193     // Create GUI list data
    194193    var list = g_ReplaysFiltered.map(replay => {
    195194        let works = replay.isCompatible;
    196195        return {
    197196            "directories": replay.directory,
    198197            "months": greyout(getReplayDateTime(replay), works),
    function displayReplayList()  
    202201            "durations": greyout(getReplayDuration(replay), works),
    203202            "playerNames": greyout(getReplayPlayernames(replay), works)
    204203        };
    205204    });
    206205
    207     // Extract arrays
    208206    if (list.length)
    209207        list = prepareForDropdown(list);
    210208
    211209    // Push to GUI
    212210    replaySelection.selected = -1;
    function displayReplayList()  
    219217
    220218    // Change these last, otherwise crash
    221219    replaySelection.list = list.directories || [];
    222220    replaySelection.list_data = list.directories || [];
    223221
    224     // Restore selection
    225222    replaySelection.selected = replaySelection.list.findIndex(directory => directory == g_SelectedReplayDirectory);
    226223
    227224    displayReplayDetails();
    228225}
    229226
    230227/**
    231228 * Shows preview image, description and player text in the right panel.
    232229 */
    233230function displayReplayDetails()
    234231{
    235     var selected = Engine.GetGUIObjectByName("replaySelection").selected;
    236     var replaySelected = selected > -1;
     232    let selected = Engine.GetGUIObjectByName("replaySelection").selected;
     233    let replaySelected = selected > -1;
    237234
    238235    Engine.GetGUIObjectByName("replayInfo").hidden = !replaySelected;
    239236    Engine.GetGUIObjectByName("replayInfoEmpty").hidden = replaySelected;
    240237    Engine.GetGUIObjectByName("startReplayButton").enabled = replaySelected;
    241238    Engine.GetGUIObjectByName("deleteReplayButton").enabled = replaySelected;
    242239    Engine.GetGUIObjectByName("summaryButton").hidden = true;
    243240
    244241    if (!replaySelected)
    245242        return;
    246243
    247     var replay = g_ReplaysFiltered[selected];
    248     var mapData = getMapDescriptionAndPreview(replay.attribs.settings.mapType, replay.attribs.map);
     244    let replay = g_ReplaysFiltered[selected];
    249245
    250     // Update GUI
    251246    Engine.GetGUIObjectByName("sgMapName").caption = translate(replay.attribs.settings.Name);
    252247    Engine.GetGUIObjectByName("sgMapSize").caption = translateMapSize(replay.attribs.settings.Size);
    253248    Engine.GetGUIObjectByName("sgMapType").caption = translateMapType(replay.attribs.settings.mapType);
    254249    Engine.GetGUIObjectByName("sgVictory").caption = translateVictoryCondition(replay.attribs.settings.GameType);
    255250    Engine.GetGUIObjectByName("sgNbPlayers").caption = replay.attribs.settings.PlayerData.length;
    256     Engine.GetGUIObjectByName("sgPlayersNames").caption = getReplayTeamText(replay);
     251
     252    let metadata = Engine.GetReplayMetadata(replay.directory);
     253    let mapData = getMapDescriptionAndPreview(replay.attribs.settings.mapType, replay.attribs.map);
     254    let playerStates =
     255        Engine.GetGUIObjectByName("showSpoiler").checked &&
     256        metadata &&
     257        metadata.playerStates &&
     258        metadata.playerStates.map(pState => pState.state);
     259
     260    Engine.GetGUIObjectByName("sgPlayersNames").caption = formatPlayerInfo(replay.attribs.settings.PlayerData, playerStates);
    257261    Engine.GetGUIObjectByName("sgMapDescription").caption = mapData.description;
    258262    Engine.GetGUIObjectByName("summaryButton").hidden = !Engine.HasReplayMetadata(replay.directory);
    259263
    260264    setMapPreviewImage("sgMapPreview", mapData.preview);
    261265}
    function isReplayCompatible(replay)  
    329333 */
    330334function replayHasSameEngineVersion(replay)
    331335{
    332336    return replay.attribs.engine_version && replay.attribs.engine_version == g_EngineInfo.engine_version;
    333337}
    334 
    335 /**
    336  * Returns a description of the player assignments.
    337  * Including civs, teams, AI settings and player colors.
    338  *
    339  * If the spoiler-checkbox is checked, it also shows defeated players.
    340  *
    341  * @returns {string}
    342  */
    343 function getReplayTeamText(replay)
    344 {
    345     // Load replay metadata
    346     const metadata = Engine.GetReplayMetadata(replay.directory);
    347     const spoiler = Engine.GetGUIObjectByName("showSpoiler").checked;
    348 
    349     let data = [];
    350     let playerIdx = 0;
    351     for (let playerData of replay.attribs.settings.PlayerData)
    352     {
    353         ++playerIdx;
    354         data.push({
    355             "Team": playerData.Team,
    356             "Name": playerData.Name,
    357             "Civ": !playerData.Civ ? translate("Unknown Civilization") :
    358                 (g_CivData[playerData.Civ] && g_CivData[playerData.Civ].Name ? translate(g_CivData[playerData.Civ].Name) : playerData.Civ),
    359             "Color": playerData.Color ? playerData.Color : g_Settings.PlayerDefaults[playerIdx].Color,
    360             "AI": playerData.AI,
    361             "AIDiff": playerData.AIDiff,
    362             "Defeated": spoiler && metadata && metadata.playerStates && metadata.playerStates[playerIdx].state == "defeated"
    363         });
    364     }
    365 
    366     return formatPlayerInfo(data);
    367 }
  • binaries/data/mods/public/gui/savedgames/load.js

     
    11var g_SavedGamesMetadata = [];
    22
     3/**
     4 * Needed for formatPlayerInfo to show the player civs in the details.
     5 */
     6const g_CivData = loadCivData();
     7
    38function init()
    49{
    510    let gameSelection = Engine.GetGUIObjectByName("gameSelection");
    611
    712    let savedGames = Engine.GetSavedGames().sort(sortDecreasingDate);
    function selectionChanged()  
    5661    let caption = sprintf(translate("Mods: %(mods)s"), { "mods": metadata.mods.join(translate(", ")) });
    5762    if (!hasSameMods(metadata, Engine.GetEngineInfo()))
    5863        caption = "[color=\"orange\"]" + caption + "[/color]";
    5964    Engine.GetGUIObjectByName("savedMods").caption = caption;
    6065
    61     let data = [];
    62     let playerIdx = 0;
    63     for (let playerData of metadata.initAttributes.settings.PlayerData)
    64     {
    65         if (playerData == null || playerData.Civ == "gaia")
    66             continue;
    67         ++playerIdx;
    68         data.push({
    69             "Team": playerData.Team,
    70             "Name": playerData.Name,
    71             "Civ": playerData.Civ,
    72             "Color": playerData.Color,
    73             "AI": playerData.AI,
    74             "AIDiff": playerData.AIDiff,
    75             "Defeated": metadata.gui.states && metadata.gui.states[playerIdx] == "defeated"
    76         });
    77     }
    78 
    79     Engine.GetGUIObjectByName("savedPlayersNames").caption = formatPlayerInfo(data);
     66    Engine.GetGUIObjectByName("savedPlayersNames").caption = formatPlayerInfo(
     67        metadata.initAttributes.settings.PlayerData,
     68        metadata.gui.states
     69    );
    8070}
    8171
    8272function loadGame()
    8373{
    8474    let gameSelection = Engine.GetGUIObjectByName("gameSelection");
  • binaries/data/mods/public/gui/savedgames/load.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22
    33<objects>
    44
    55    <script file="gui/common/color.js" />
     6    <script file="gui/common/functions_civinfo.js"/>
    67    <script file="gui/common/functions_global_object.js" />
    78    <script file="gui/common/functions_utility.js" />
    89    <script file="gui/common/functions_utility_loadsave.js" />
    910    <script file="gui/common/settings.js" />
    1011    <script file="gui/savedgames/load.js" />
     
    2829                <action on="Press">Engine.PopGuiPage();</action>
    2930            </object>
    3031
    3132            <object name="deleteGameButton" type="button" size="33%+20 100%-60 66%-15 100%-32" style="StoneButton" hotkey="session.savedgames.delete">
    3233                <translatableAttribute id="caption">Delete</translatableAttribute>
    33                 <action on="Press">
    34                     if (!this.enabled)
    35                         return;
    36                     if (Engine.HotkeyIsPressed("session.savedgames.noconfirmation"))
    37                         deleteGameWithoutConfirmation();
    38                     else
    39                         deleteGame();
    40                 </action>
     34                <action on="Press">deleteGame();</action>
    4135            </object>
    4236
    4337            <object name="loadGameButton" type="button" style="StoneButton" size="66%-5 100%-60 100%-25 100%-32">
    4438                <translatableAttribute id="caption">Load</translatableAttribute>
    4539                <action on="Press">loadGame();</action>
  • binaries/data/mods/public/gui/savedgames/save.js

    function selectDescription()  
    1515function init(data)
    1616{
    1717    g_SavedGameData = data && data.savedGameData || {};
    1818    let simulationState = Engine.GuiInterfaceCall("GetSimulationState");
    1919    g_SavedGameData.timeElapsed = simulationState.timeElapsed;
    20     g_SavedGameData.states = [];
    21     for (let player of simulationState.players)
    22         g_SavedGameData.states.push(player.state);
     20    g_SavedGameData.states = simulationState.players.map(pState => pState.state);
    2321
    2422    let gameSelection = Engine.GetGUIObjectByName("gameSelection");
    2523    Engine.GetGUIObjectByName("deleteGameButton").enabled = false;
    2624
    2725    let savedGames = Engine.GetSavedGames().sort(sortDecreasingDate);
  • binaries/data/mods/public/gui/session/messages.js

    var g_FormatChatMessage = {  
    9999            }
    100100        ),
    101101    "clientlist": msg => getUsernameList(),
    102102    "message": msg => formatChatCommand(msg),
    103103    "defeat": msg => formatDefeatMessage(msg),
     104    "won": msg => formatWonMessage(msg),
    104105    "diplomacy": msg => formatDiplomacyMessage(msg),
    105106    "tribute": msg => formatTributeMessage(msg),
    106107    "attack": msg => formatAttackMessage(msg)
    107108};
    108109
    var g_NotificationsTypes =  
    244245            "type": "defeat",
    245246            "guid": findGuidForPlayerID(player),
    246247            "player": player,
    247248            "resign": !!notification.resign
    248249        });
    249 
    250         updateDiplomacy();
    251         updateChatAddressees();
     250        playerFinished(player, false);
     251    },
     252    "won": function(notification, player)
     253    {
     254        addChatMessage({
     255            "type": "won",
     256            "guid": findGuidForPlayerID(player),
     257            "player": player
     258        });
     259        playerFinished(player, true);
    252260    },
    253261    "diplomacy": function(notification, player)
    254262    {
    255263        addChatMessage({
    256264            "type": "diplomacy",
    function formatDefeatMessage(msg)  
    743751            translate("%(player)s has been defeated."),
    744752        { "player": colorizePlayernameByID(msg.player) }
    745753    );
    746754}
    747755
     756function formatWonMessage(msg)
     757{
     758    return sprintf(translate("%(player)s has won."), {
     759        "player": colorizePlayernameByID(msg.player)
     760    });
     761}
     762
    748763function formatDiplomacyMessage(msg)
    749764{
    750765    let messageType;
    751766
    752767    if (g_IsObserver)
  • binaries/data/mods/public/gui/session/session.js

    var g_EntityStates = {};  
    117117var g_TemplateData = {};
    118118var g_TemplateDataWithoutLocalization = {};
    119119var g_TechnologyData = {};
    120120
    121121/**
    122  * Cache concatenated list of player states ("active", "defeated" or "won").
    123  */
    124 var g_CachedLastStates = "";
    125 
    126 /**
    127  * Whether the current player has lost/won and reached the end of their game.
    128  * Used for reporting the gamestate and showing the game-end message only once.
    129  */
    130 var g_GameEnded = false;
    131 
    132 /**
    133122 * Top coordinate of the research list.
    134123 * Changes depending on the number of displayed counters.
    135124 */
    136125var g_ResearchListTop = 4;
    137126
    function init(initData, hotloadData)  
    238227        g_PlayerAssignments = initData.playerAssignments;
    239228        g_MatchID = initData.attribs.matchID;
    240229        g_ReplaySelectionData = initData.replaySelectionData;
    241230        g_HasRejoined = initData.isRejoining;
    242231
    243         g_Players = getPlayerData();
    244 
    245232        if (initData.savedGUIData)
    246233            restoreSavedGameData(initData.savedGUIData);
    247234
    248235        Engine.GetGUIObjectByName("gameSpeedButton").hidden = g_IsNetworked;
    249236    }
    250237    else // Needed for autostart loading option
    251238    {
    252239        if (g_IsReplay)
    253240            g_PlayerAssignments.local.player = -1;
    254 
    255         g_Players = getPlayerData();
    256241    }
    257242
     243    g_Players = getPlayerData();
     244
    258245    g_CivData = loadCivData();
    259246    g_CivData.gaia = { "Code": "gaia", "Name": translate("Gaia") };
    260247
    261248    initializeMusic(); // before changing the perspective
    262249    selectViewPlayer(g_ViewedPlayer);
    function controlsPlayer(playerID)  
    433420    return playerState && (
    434421        playerState.state != "defeated" || playerState.controlsAll);
    435422}
    436423
    437424/**
     425 * Called when a player has won or was defeated.
     426 */
     427function playerFinished(player, won)
     428{
     429    reportGame();
     430    updateDiplomacy();
     431    updateChatAddressees();
     432
     433    if (player != Engine.GetPlayerID() || Engine.IsAtlasRunning())
     434        return;
     435
     436    global.music.setState(
     437        won ?
     438            global.music.states.VICTORY :
     439            global.music.states.DEFEAT
     440    );
     441
     442    closeOpenDialogs();
     443
     444    // Select observermode
     445    if (!won)
     446        Engine.GetGUIObjectByName("viewPlayer").selected = 0;
     447
     448    messageBox(
     449        400, 200,
     450        g_IsNetworked && g_IsController ?
     451            translate("Do you want to quit? Leaving will disconnect all other players.") :
     452            translate("Do you want to quit?"),
     453        won ?
     454            translate("VICTORIOUS!") :
     455            translate("DEFEATED!"),
     456        [translate("No"), translate("Yes")],
     457        [null, leaveGame]
     458    );
     459}
     460
     461/**
    438462 * Sets civ icon for the currently viewed player.
    439463 * Hides most gui objects for observers.
    440464 */
    441465function updateTopPanel()
    442466{
    function resignGame(leaveGameAfterResign  
    505529 * @param willRejoin If player is going to be rejoining a networked game.
    506530 */
    507531function leaveGame(willRejoin)
    508532{
    509533    let extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
    510     let mapSettings = Engine.GetMapSettings();
    511     let gameResult;
    512 
    513     if (Engine.GetPlayerID() == -1)
    514     {
    515         gameResult = translate("You have left the game.");
    516         global.music.setState(global.music.states.VICTORY);
    517     }
    518     else
    519     {
    520         let playerState = extendedSimState.players[Engine.GetPlayerID()];
    521         if (g_Disconnected)
    522             gameResult = translate("You have been disconnected.");
    523         else if (playerState.state == "won")
    524             gameResult = translate("You have won the battle!");
    525         else if (playerState.state == "defeated")
    526             gameResult = translate("You have been defeated...");
    527         else // "active"
    528         {
    529             global.music.setState(global.music.states.DEFEAT);
    530             if (willRejoin)
    531                 gameResult = translate("You have left the game.");
    532             else
    533             {
    534                 gameResult = translate("You have abandoned the game.");
    535                 resignGame(true);
    536             }
    537         }
    538     }
    539 
    540     let summary = {
     534    let simData = {
    541535        "timeElapsed" : extendedSimState.timeElapsed,
    542536        "playerStates": extendedSimState.players,
    543         "players": g_Players,
    544         "mapSettings": Engine.GetMapSettings(),
     537        "mapSettings": Engine.GetMapSettings()
    545538    };
    546539
    547540    if (!g_IsReplay)
    548         Engine.SaveReplayMetadata(JSON.stringify(summary));
     541        Engine.SaveReplayMetadata(JSON.stringify(simData));
    549542
    550     if (!g_HasRejoined)
    551         summary.replayDirectory = Engine.GetCurrentReplayDirectory();
    552     summary.replaySelectionData = g_ReplaySelectionData;
     543    let guiData = {
     544        "assignedPlayer": Engine.GetPlayerID(),
     545        "disconnected": g_Disconnected,
     546        "isReplay": g_IsReplay,
     547        "replayDirectory": !g_HasRejoined && Engine.GetCurrentReplayDirectory(),
     548        "replaySelectionData": g_ReplaySelectionData,
     549    };
     550
     551    if (!willRejoin &&
     552        simData[Engine.GetPlayerID()] &&
     553        simData[Engine.GetPlayerID()].state == "active")
     554        resignGame(true);
    553555
    554556    Engine.EndGame();
    555557
    556558    if (g_IsController && Engine.HasXmppClient())
    557559        Engine.SendUnregisterGame();
    558560
    559     summary.gameResult = gameResult;
    560     summary.isReplay = g_IsReplay;
    561     Engine.SwitchGuiPage("page_summary.xml", summary);
     561    Engine.SwitchGuiPage("page_summary.xml", {
     562        "gui": guiData,
     563        "sim": simData
     564    });
    562565}
    563566
    564567// Return some data that we'll use when hotloading this file after changes
    565568function getHotloadData()
    566569{
    function onTick()  
    603606
    604607    let now = new Date();
    605608    let tickLength = new Date() - lastTickTime;
    606609    lastTickTime = now;
    607610
    608     checkPlayerState();
    609 
    610611    handleNetMessages();
    611612
    612613    updateCursorAndTooltip();
    613614
    614615    if (g_Selection.dirty)
    function onTick()  
    630631    Engine.GetGUIObjectByName("resourcePop").textcolor = g_IsTrainingBlocked && Date.now() % 1000 < 500 ? g_PopulationAlertColor : g_DefaultPopulationColor;
    631632
    632633    Engine.GuiInterfaceCall("ClearRenamedEntities");
    633634}
    634635
    635 function checkPlayerState()
    636 {
    637     if (g_GameEnded || Engine.GetPlayerID() < 1)
    638         return;
    639 
    640     // Send a game report for each player in this game.
    641     let m_simState = GetSimState();
    642     let playerState = m_simState.players[Engine.GetPlayerID()];
    643     let tempStates = "";
    644     for (let player of m_simState.players)
    645         tempStates += player.state + ",";
    646 
    647     if (g_CachedLastStates != tempStates)
    648     {
    649         g_CachedLastStates = tempStates;
    650         reportGame();
    651     }
    652 
    653     if (playerState.state == "active")
    654         return;
    655 
    656     // Make sure nothing is open to avoid stacking.
    657     closeOpenDialogs();
    658 
    659     // Make sure this doesn't run again.
    660     g_GameEnded = true;
    661 
    662     // Select observermode
    663     Engine.GetGUIObjectByName("viewPlayer").selected = playerState.state == "won" ? g_ViewedPlayer + 1 : 0;
    664 
    665     let btCaptions;
    666     let btCode;
    667     let message;
    668     let title;
    669     if (Engine.IsAtlasRunning())
    670     {
    671         // If we're in Atlas, we can't leave the game
    672         btCaptions = [translate("OK")];
    673         btCode = [null];
    674         message = translate("Press OK to continue");
    675     }
    676     else
    677     {
    678         btCaptions = [translate("No"), translate("Yes")];
    679         btCode = [null, leaveGame];
    680         message = translate("Do you want to quit?");
    681     }
    682 
    683     if (playerState.state == "defeated")
    684     {
    685         title = translate("DEFEATED!");
    686         global.music.setState(global.music.states.DEFEAT);
    687     }
    688     else if (playerState.state == "won")
    689     {
    690         title = translate("VICTORIOUS!");
    691         global.music.setState(global.music.states.VICTORY);
    692         // TODO: Reveal map directly instead of this silly proxy.
    693         if (!Engine.GetGUIObjectByName("devCommandsRevealMap").checked)
    694             Engine.GetGUIObjectByName("devCommandsRevealMap").checked = true;
    695     }
    696 
    697     messageBox(400, 200, message, title, btCaptions, btCode);
    698 }
    699 
    700636function changeGameSpeed(speed)
    701637{
    702638    if (!g_IsNetworked)
    703639        Engine.SetSimRate(speed);
    704640}
    function onSimulationUpdate()  
    735671
    736672    if (!g_SimState)
    737673        return;
    738674
    739675    handleNotifications();
    740 
    741676    updateGUIObjects();
    742677}
    743678
    744679function updateGUIObjects()
    745680{
    function updateGUIObjects()  
    768703        let playerState = GetSimState().players[g_ViewedPlayer];
    769704        g_DevSettings.controlAll = playerState && playerState.controlsAll;
    770705        Engine.GetGUIObjectByName("devControlAll").checked = g_DevSettings.controlAll;
    771706    }
    772707
    773     if (g_ViewedPlayer != -1 && !g_GameEnded)
     708    if (!g_IsObserver)
    774709    {
    775710        // Update music state on basis of battle state.
    776711        let battleState = Engine.GuiInterfaceCall("GetBattleState", g_ViewedPlayer);
    777712        if (battleState)
    778713            global.music.setState(global.music.states[battleState]);
    function updateGUIStatusBar(nameOfBar, p  
    826761        healthSize.rtop = value;
    827762
    828763    statusBar.size = healthSize;
    829764}
    830765
    831 
    832766function updateHeroes()
    833767{
    834768    let playerState = GetSimState().players[g_ViewedPlayer];
    835769    let heroes = playerState ? playerState.heroes : [];
    836770
    function playAmbient()  
    11401074    Engine.PlayAmbientSound(g_Ambient[Math.floor(Math.random() * g_Ambient.length)], true);
    11411075}
    11421076
    11431077function getBuildString()
    11441078{
    1145     return sprintf(translate("Build: %(buildDate)s (%(revision)s)"), { "buildDate": Engine.GetBuildTimestamp(0), revision: Engine.GetBuildTimestamp(2) });
     1079    return sprintf(translate("Build: %(buildDate)s (%(revision)s)"), {
     1080        "buildDate": Engine.GetBuildTimestamp(0),
     1081        "revision": Engine.GetBuildTimestamp(2)
     1082    });
    11461083}
    11471084
    11481085function showTimeWarpMessageBox()
    11491086{
    11501087    messageBox(
    function showTimeWarpMessageBox()  
    11581095 * Send a report on the gamestatus to the lobby.
    11591096 */
    11601097function reportGame()
    11611098{
    11621099    // Only 1v1 games are rated (and Gaia is part of g_Players)
    1163     if (!Engine.HasXmppClient() || !Engine.IsRankedGame() || g_Players.length != 3)
     1100    if (!Engine.HasXmppClient() || !Engine.IsRankedGame() ||
     1101        g_Players.length != 3 || Engine.GetPlayerID() == -1)
    11641102        return;
    11651103
    11661104    let extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
    11671105
    11681106    let unitsClasses = [
  • binaries/data/mods/public/gui/session/utility_functions.js

     
     1/**
     2 * Before removing data, consider this data is partially used in the replay menu.
     3 */
    14function getPlayerData(previousData = undefined)
    25{
    36    let players = [];
    47
    58    let simState = GetSimState();
  • binaries/data/mods/public/gui/summary/layout.js

    function updateGeneralPanelTeams()  
    315315    // If there are no players without team, hide "player name" heading
    316316    if (!g_WithoutTeam)
    317317        Engine.GetGUIObjectByName("playerNameHeading").caption = "";
    318318}
    319319
    320 function updateObjectPlayerPosition()
     320function initPlayerBoxPositions()
    321321{
    322322    for (let h = 0; h < g_MaxPlayers; ++h)
    323323    {
    324324        let playerBox = Engine.GetGUIObjectByName("playerBox[" + h + "]");
    325325        let boxSize = playerBox.size;
  • binaries/data/mods/public/gui/summary/summary.js

    function updatePanelData(panelInfo)  
    8080    updateGeneralPanelTeams();
    8181
    8282    let playerBoxesCounts = [ ];
    8383    for (let i = 0; i < g_PlayerCount; ++i)
    8484    {
    85         let playerState = g_GameData.playerStates[i+1];
     85        let playerState = g_GameData.sim.playerStates[i+1];
    8686
    8787        if (!playerBoxesCounts[playerState.team+1])
    8888            playerBoxesCounts[playerState.team+1] = 1;
    8989        else
    9090            playerBoxesCounts[playerState.team+1] += 1;
    function updatePanelData(panelInfo)  
    104104            playerCivicBoxColumn = "civIcont[" + playerState.team + "][" + positionObject + "]";
    105105            playerCounterValue = "valueDataTeam[" + playerState.team + "][" + positionObject + "]";
    106106        }
    107107
    108108        let colorString = "color: " +
    109                 Math.floor(playerState.color.r * 255) + " " +
    110                 Math.floor(playerState.color.g * 255) + " " +
    111                 Math.floor(playerState.color.b * 255);
     109            Math.floor(playerState.color.r * 255) + " " +
     110            Math.floor(playerState.color.g * 255) + " " +
     111            Math.floor(playerState.color.b * 255);
    112112
    113113        let rowPlayerObject = Engine.GetGUIObjectByName(rowPlayer);
    114114        rowPlayerObject.hidden = false;
    115115        rowPlayerObject.sprite = colorString + g_PlayerBoxAlpha;
    116116
    function updatePanelData(panelInfo)  
    119119        rowPlayerObject.size = boxSize;
    120120
    121121        let playerColorBox = Engine.GetGUIObjectByName(playerColorBoxColumn);
    122122        playerColorBox.sprite = colorString + g_PlayerColorBoxAlpha;
    123123
    124         Engine.GetGUIObjectByName(playerNameColumn).caption = g_GameData.players[i+1].name;
     124        Engine.GetGUIObjectByName(playerNameColumn).caption = g_GameData.sim.playerStates[i+1].name;
    125125
    126126        let civIcon = Engine.GetGUIObjectByName(playerCivicBoxColumn);
    127127        civIcon.sprite = "stretched:" + g_CivData[playerState.civ].Emblem;
    128128        civIcon.tooltip = g_CivData[playerState.civ].Name;
    129129
    function updatePanelData(panelInfo)  
    135135    let teamCounterFn = panelInfo.teamCounterFn;
    136136    if (g_Teams && teamCounterFn)
    137137        teamCounterFn(panelInfo.counters);
    138138}
    139139
     140function confirmStartReplay()
     141{
     142    if (Engine.HasXmppClient())
     143        messageBox(
     144            400, 200,
     145            translate("Are you sure you want to quit the lobby?"),
     146            translate("Confirmation"),
     147            [translate("No"), translate("Yes")],
     148            [null, startReplay]
     149        );
     150    else
     151        startReplay();
     152}
     153
     154function continueButton()
     155{
     156    if (g_GameData.gui.isInGame)
     157        Engine.PopGuiPageCB(0);
     158    else if (g_GameData.gui.isReplay)
     159        Engine.SwitchGuiPage("page_replaymenu.xml", {
     160            "replaySelectionData": g_GameData.gui.replaySelectionData
     161        });
     162    else if (Engine.HasXmppClient())
     163        Engine.SwitchGuiPage("page_lobby.xml");
     164    else
     165        Engine.SwitchGuiPage("page_pregame.xml");
     166}
     167
    140168function startReplay()
    141169{
    142170    if (Engine.HasXmppClient())
    143171        Engine.StopXmppClient();
    144172
    145     Engine.StartVisualReplay(g_GameData.replayDirectory);
     173    Engine.StartVisualReplay(g_GameData.gui.replayDirectory);
    146174    Engine.SwitchGuiPage("page_loading.xml", {
    147         "attribs": Engine.GetReplayAttributes(g_GameData.replayDirectory),
     175        "attribs": Engine.GetReplayAttributes(g_GameData.gui.replayDirectory),
    148176        "isNetworked": false,
    149177        "playerAssignments": {
    150178            "local": {
    151179                "name": singleplayerName(),
    152180                "player": -1
    153181            }
    154182        },
    155183        "savedGUIData": "",
    156184        "isReplay": true,
    157         "replaySelectionData": g_GameData.replaySelectionData
     185        "replaySelectionData": g_GameData.gui.replaySelectionData
    158186    });
    159187}
    160188
    161189function init(data)
    162190{
    163     updateObjectPlayerPosition();
    164191    g_GameData = data;
    165192
    166     let mapSize = data.mapSettings.Size && g_Settings.MapSizes.find(size => size.Tiles == data.mapSettings.Size);
    167     let mapType = g_Settings.MapTypes.find(mapType => mapType.Name == data.mapSettings.mapType);
     193    let assignedState = g_GameData.sim.playerStates[g_GameData.gui.assignedPlayer || -1];
    168194   
     195    Engine.GetGUIObjectByName("summaryText").caption =
     196        !assignedState ?
     197            translate("You have left the game.") :
     198        g_GameData.gui.disconnected ?
     199            translate("You have been disconnected.") :
     200        assignedState.state == "won" ?
     201            translate("You have won the battle!") :
     202        assignedState.state == "defeated" ?
     203            translate("You have been defeated...") :
     204            translate("You have abandoned the game.");
     205
     206    initPlayerBoxPositions();
     207
    169208    Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
    170209        translate("Game time elapsed: %(time)s"), {
    171             "time": timeToString(data.timeElapsed)
     210            "time": timeToString(g_GameData.sim.timeElapsed)
    172211    });
    173212
    174     Engine.GetGUIObjectByName("summaryText").caption = data.gameResult;
     213    let mapType = g_Settings.MapTypes.find(mapType => mapType.Name == g_GameData.sim.mapSettings.mapType);
     214    let mapSize = g_Settings.MapSizes.find(size => size.Tiles == g_GameData.sim.mapSettings.Size || 0);
    175215
    176216    Engine.GetGUIObjectByName("mapName").caption = sprintf(
    177217        translate("%(mapName)s - %(mapType)s"), {
    178             "mapName": translate(data.mapSettings.Name),
     218            "mapName": translate(g_GameData.sim.mapSettings.Name),
    179219            "mapType": mapSize ? mapSize.LongName : (mapType ? mapType.Title : "")
    180220        });
    181221
    182     Engine.GetGUIObjectByName("replayButton").hidden = g_GameData.isInGame || !g_GameData.replayDirectory;
     222    Engine.GetGUIObjectByName("replayButton").hidden = g_GameData.gui.isInGame || !g_GameData.gui.replayDirectory;
    183223
    184224    // Panels
    185     g_PlayerCount = data.playerStates.length - 1;
     225    g_PlayerCount = data.sim.playerStates.length - 1;
    186226
    187     if (data.mapSettings.LockTeams)
     227    if (data.sim.mapSettings.LockTeams)
    188228    {
    189229        // Count teams
    190230        for (let t = 0; t < g_PlayerCount; ++t)
    191231        {
    192             let playerTeam = data.playerStates[t+1].team;
     232            let playerTeam = g_GameData.sim.playerStates[t+1].team;
    193233            g_Teams[playerTeam] = (g_Teams[playerTeam] || 0) + 1;
    194234        }
    195235
    196236        if (g_Teams.length == g_PlayerCount)
    197237            g_Teams = false;    // Each player has his own team. Displaying teams makes no sense.
    function init(data)  
    201241
    202242    // Erase teams data if teams are not displayed
    203243    if (!g_Teams)
    204244    {
    205245        for (let p = 0; p < g_PlayerCount; ++p)
    206             data.playerStates[p+1].team = -1;
     246            g_GameData.sim.playerStates[p+1].team = -1;
    207247    }
    208248
    209249    g_WithoutTeam = g_PlayerCount;
    210250    if (g_Teams)
    211251    {
  • binaries/data/mods/public/gui/summary/summary.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22
    3 <!--
    4 ==========================================
    5 - POST-GAME SUMMARY SCREEN -
    6 ==========================================
    7 -->
    8 
    93<objects>
    104    <script file="gui/common/functions_global_object.js"/>
    115    <script file="gui/common/functions_civinfo.js"/>
    126    <script file="gui/common/functions_utility.js"/>
    137    <script file="gui/common/settings.js"/>
     
    162156            </object>
    163157        </object>
    164158
    165159        <object type="button" name="replayButton" style="ModernButtonRed" size="100%-310 100%-48 100%-170 100%-20">
    166160            <translatableAttribute id="caption">Replay</translatableAttribute>
    167             <action on="Press"><![CDATA[
    168                 if (g_GameData.isInGame)
    169                     return;
    170 
    171                 if (Engine.HasXmppClient())
    172                     messageBox(
    173                         400, 200,
    174                         translate("Are you sure you want to quit the lobby?"),
    175                         translate("Confirmation"),
    176                         [translate("No"), translate("Yes")],
    177                         [null, startReplay]
    178                     );
    179                 else
    180                     startReplay();
    181                 ]]>
    182             </action>
     161            <action on="Press">confirmStartReplay();</action>
    183162        </object>
    184163
    185164        <object type="button" style="ModernButtonRed" size="100%-160 100%-48 100%-20 100%-20">
    186165            <translatableAttribute id="caption">Continue</translatableAttribute>
    187             <action on="Press"><![CDATA[
    188                 if (g_GameData.isInGame)
    189                 {
    190                     Engine.PopGuiPageCB(0);
    191                 }
    192                 else if (g_GameData.isReplay)
    193                 {
    194                     Engine.SwitchGuiPage("page_replaymenu.xml", { "replaySelectionData": g_GameData.replaySelectionData });
    195                 }
    196                 else if (!Engine.HasXmppClient())
    197                 {
    198                     Engine.SwitchGuiPage("page_pregame.xml");
    199                 }
    200                 else
    201                 {
    202                     Engine.LobbySetPlayerPresence("available");
    203                     Engine.SwitchGuiPage("page_lobby.xml");
    204                 }
    205                 ]]>
    206             </action>
     166            <action on="Press">continueButton();</action>
    207167        </object>
    208168    </object>
    209169</objects>
  • binaries/data/mods/public/maps/scripts/ConquestCommon.js

    Trigger.prototype.ConquestHandlerOwnerSh  
    2323    let index = entities.indexOf(msg.entity);
    2424
    2525    if (index >= 0)
    2626    {
    2727        entities.splice(index, 1);
    28         if (!entities.length && Engine.QueryInterface(this.conquestEntitiesByPlayer[msg.from].player, IID_Player).GetState() == "active")
    29             Engine.PostMessage(this.conquestEntitiesByPlayer[msg.from].player, MT_PlayerDefeated, { "playerId": msg.from } );
     28        if (!entities.length)
     29        {
     30            let cmpPlayer = QueryPlayerIDInterface(msg.from);
     31            if (cmpPlayer)
     32                cmpPlayer.SetState("defeated");
     33        }
    3034    }
    3135}
    3236
    3337Trigger.prototype.ConquestAddStructure = function(msg)
    3438{
  • binaries/data/mods/public/maps/scripts/TriggerHelper.js

    TriggerHelper.SetPlayerWon = function(pl  
    125125/**
    126126 * Defeats a player
    127127 */
    128128TriggerHelper.DefeatPlayer = function(playerID)
    129129{
    130     let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
    131     let playerEnt = cmpPlayerManager.GetPlayerByID(playerID);
    132 
    133     Engine.PostMessage(playerEnt, MT_PlayerDefeated, { "playerId": playerID } );
     130    let cmpPlayer = QueryPlayerIDInterface(playerID);
     131    if (cmpPlayer)
     132        cmpPlayer.SetState("defeated");
    134133};
    135134
    136135/**
    137136 * Returns the number of current players
    138137 */
  • binaries/data/mods/public/simulation/components/EndGameManager.js

     
    11/**
    2  * System component which regularly checks victory/defeat conditions
    3  * and if they are satisfied then it marks the player as victorious/defeated.
     2 * System component which regularly checks victory/defeat conditions and if
     3 * they are satisfied then it marks the player as victorious/defeated.
    44 */
    55function EndGameManager() {}
    66
    77EndGameManager.prototype.Schema =
    88    "<a:component type='system'/><empty/>";
    EndGameManager.prototype.MarkPlayerAsWon  
    5050    let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
    5151    let numPlayers = cmpPlayerManager.GetNumPlayers();
    5252
    5353    for (let i = 1; i < numPlayers; ++i)
    5454    {
    55         let playerEntityId = cmpPlayerManager.GetPlayerByID(i);
    56         let cmpPlayer = Engine.QueryInterface(playerEntityId, IID_Player);
     55        let cmpPlayer = QueryPlayerIDInterface(i);
    5756
    58         if (cmpPlayer.GetState() != "active")
    59             continue;
    60 
    61         if (playerID == cmpPlayer.GetPlayerID() || this.alliedVictory && cmpPlayer.IsMutualAlly(playerID))
     57        if (playerID == i || this.alliedVictory && cmpPlayer.IsMutualAlly(playerID))
    6258            cmpPlayer.SetState("won");
    6359        else
    64             Engine.PostMessage(playerEntityId, MT_PlayerDefeated, {
    65                 "playerId": i,
    66                 "skipAlliedVictoryCheck": true
    67             });
     60            cmpPlayer.SetState("defeated");
    6861    }
    69 
    70     // Reveal the map to all players
    71     let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
    72     cmpRangeManager.SetLosRevealAll(-1, true);
    7362};
    7463
    7564EndGameManager.prototype.SetAlliedVictory = function(flag)
    7665{
    7766    this.alliedVictory = flag;
    EndGameManager.prototype.AlliedVictoryCh  
    9988
    10089        allies.push(playerID);
    10190    }
    10291
    10392    if (this.alliedVictory || allies.length == 1)
    104     {
    10593        for (let playerID of allies)
    10694        {
    10795            let cmpPlayer = QueryPlayerIDInterface(playerID);
    10896            if (cmpPlayer)
    10997                cmpPlayer.SetState("won");
    11098        }
    111 
    112         let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
    113         if (cmpRangeManager)
    114             cmpRangeManager.SetLosRevealAll(-1, true);
    115     }
    11699    else
    117100        this.lastManStandingMessage = cmpGuiInterface.AddTimeNotification({
    118101            "message": markForTranslation("Last remaining player wins."),
    119102            "translateMessage": true,
    120103        }, 12 * 60 * 60 * 1000); // 12 hours
  • binaries/data/mods/public/simulation/components/Player.js

    Player.prototype.SetTradingGoods = funct  
    357357Player.prototype.GetState = function()
    358358{
    359359    return this.state;
    360360};
    361361
    362 Player.prototype.SetState = function(newState)
     362Player.prototype.SetState = function(newState, resign, skipAlliedVictoryCheck)
    363363{
     364    if (this.state != "active")
     365        return;
     366
     367    if (newState != "won" && newState != "defeated")
     368    {
     369        warn("Can't change playerstate to " + this.state);
     370        return;
     371    }
     372
    364373    this.state = newState;
     374
     375    let won = newState == "won";
     376
     377    // Reveal map to all or only that player
     378    let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
     379    cmpRangeManager.SetLosRevealAll(won ? -1 : this.playerID, true);
     380
     381    if (!won)
     382    {
     383        // Reassign all player's entities to Gaia
     384        let entities = cmpRangeManager.GetEntitiesByPlayer(this.playerID);
     385
     386        // The ownership change is done in two steps so that entities don't hit idle
     387        // (and thus possibly look for "enemies" to attack) before nearby allies get
     388        // converted to Gaia as well.
     389        for (let entity of entities)
     390        {
     391            let cmpOwnership = Engine.QueryInterface(entity, IID_Ownership);
     392            cmpOwnership.SetOwnerQuiet(0);
     393        }
     394
     395        // With the real ownership change complete, send OwnershipChanged messages.
     396        for (let entity of entities)
     397            Engine.PostMessage(entity, MT_OwnershipChanged, {
     398                "entity": entity,
     399                "from": this.playerID,
     400                "to": 0
     401            });
     402    }
     403
     404    // Inform the simulation
     405    if (won)
     406        Engine.BroadcastMessage(MT_PlayerWon, { "playerId": this.playerID });
     407    else
     408        Engine.BroadcastMessage(MT_PlayerDefeated, {
     409            "playerId": this.playerID,
     410            "skipAlliedVictoryCheck": skipAlliedVictoryCheck
     411        });
     412
     413    // Inform the GUI
     414    let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     415    if (won)
     416        cmpGUIInterface.PushNotification({
     417            "type": "won",
     418            "players": [this.playerID]
     419        });
     420    else
     421        cmpGUIInterface.PushNotification({
     422            "type": "defeat",
     423            "players": [this.playerID],
     424            "resign": resign
     425        });
    365426};
    366427
    367428Player.prototype.GetTeam = function()
    368429{
    369430    return this.team;
    Player.prototype.OnGlobalOwnershipChange  
    647708        if (cmpIdentity && cmpIdentity.HasClass("Hero"))
    648709            this.heroes.push(msg.entity);
    649710    }
    650711};
    651712
    652 Player.prototype.OnPlayerDefeated = function(msg)
    653 {
    654     this.state = "defeated";
    655 
    656     // Reassign all player's entities to Gaia
    657     var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
    658     var entities = cmpRangeManager.GetEntitiesByPlayer(this.playerID);
    659 
    660     // The ownership change is done in two steps so that entities don't hit idle
    661     // (and thus possibly look for "enemies" to attack) before nearby allies get
    662     // converted to Gaia as well.
    663     for (var entity of entities)
    664     {
    665         var cmpOwnership = Engine.QueryInterface(entity, IID_Ownership);
    666         cmpOwnership.SetOwnerQuiet(0);
    667     }
    668 
    669     // With the real ownership change complete, send OwnershipChanged messages.
    670     for (var entity of entities)
    671         Engine.PostMessage(entity, MT_OwnershipChanged, {
    672             "entity": entity,
    673             "from": this.playerID,
    674             "to": 0
    675         });
    676 
    677     // Reveal the map for this player.
    678     cmpRangeManager.SetLosRevealAll(this.playerID, true);
    679 
    680     // Send a chat message notifying of the player's defeat.
    681     var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
    682     cmpGUIInterface.PushNotification({
    683         "type": "defeat",
    684         "players": [this.playerID],
    685         "resign": !!msg.resign
    686     });
    687 };
    688 
    689713Player.prototype.OnResearchFinished = function(msg)
    690714{
    691715    if (msg.tech == this.template.SharedLosTech)
    692716        this.UpdateSharedLos();
    693717    else if (msg.tech == this.template.SharedDropsitesTech)
  • binaries/data/mods/public/simulation/components/interfaces/EndGameManager.js

     
    11Engine.RegisterInterface("EndGameManager");
    22Engine.RegisterMessageType("PlayerDefeated");
     3Engine.RegisterMessageType("PlayerWon");
    34Engine.RegisterMessageType("GameTypeChanged");
  • binaries/data/mods/public/simulation/helpers/Cheat.js

    function Cheat(input)  
    4646            else
    4747                Engine.DestroyEntity(ent);
    4848        }
    4949        return;
    5050    case "defeatplayer":
    51         var playerEnt = cmpPlayerManager.GetPlayerByID(input.parameter);
    52         if (playerEnt == INVALID_ENTITY)
    53             return;
    54         Engine.PostMessage(playerEnt, MT_PlayerDefeated, { "playerId": input.parameter });
     51        cmpPlayer = QueryPlayerIDInterface(input.parameter);
     52        if (cmpPlayer)
     53            cmpPlayer.SetState("defeated");
    5554        return;
    5655    case "createunits":
    5756        var cmpProductionQueue = input.selected.length && Engine.QueryInterface(input.selected[0], IID_ProductionQueue);
    5857        if (!cmpProductionQueue)
    5958        {
  • binaries/data/mods/public/simulation/helpers/Commands.js

    var g_Commands = {  
    412412        }
    413413    },
    414414
    415415    "defeat-player": function(player, cmd, data)
    416416    {
    417         // Send "OnPlayerDefeated" message to player
    418         Engine.PostMessage(data.playerEnt, MT_PlayerDefeated, { "playerId": player, "resign": !!cmd.resign });
     417        let cmpPlayer = QueryPlayerIDInterface(player);
     418        if (cmpPlayer)
     419            cmpPlayer.SetState("defeated", !!cmd.resign);
    419420    },
    420421
    421422    "garrison": function(player, cmd, data)
    422423    {
    423424        // Verify that the building can be controlled by the player or is mutualAlly