Ticket #2373: resignation_v3_WIP.patch

File resignation_v3_WIP.patch, 17.4 KB (added by Michael, 10 years ago)

Problem left with resign and then quit

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

     
    2222{
    2323    if (btnCode !== undefined && g_messageBoxBtnFunctions[btnCode])
    2424    {
    25         if (g_messageBoxCallbackArgs[btnCode])
    26             g_messageBoxBtnFunctions[btnCode](g_messageBoxCallbackArgs[btnCode]);
     25        // cache the vales to make it possible to call a messageBox from a callback function.
     26        var callbackFunction = g_messageBoxBtnFunctions[btnCode];
     27        var callbackArgs = g_messageBoxCallbackArgs[btnCode]
     28        g_messageBoxBtnFunctions  = [];
     29        g_messageBoxCallbackArgs = [];
     30
     31        if (callbackArgs !== undefined)
     32            callbackFunction(callbackArgs);
    2733        else
    28             g_messageBoxBtnFunctions[btnCode]();
     34            callbackFunction();
     35           
     36        return;
    2937    }
    30 
    3138    g_messageBoxBtnFunctions  = [];
    3239    g_messageBoxCallbackArgs = [];
    3340}
  • binaries/data/mods/public/gui/session/menu.js

     
    147147    closeOpenDialogs();
    148148    pauseGame();
    149149    var btCaptions = ["Yes", "No"];
    150     var btCode = [leaveGame, resumeGame];
     150    var btCode = [g_IsNetworked && !g_GameEnded ? networkReturnQuestion : prepareLeaveGame, resumeGame];
    151151    messageBox(400, 200, "Are you sure you want to quit?", "Confirmation", 0, btCaptions, btCode);
    152152}
    153153
     154function networkReturnQuestion()
     155{
     156    var btCaptions = ["Yes, I will return", "No, I resign"];
     157    var btCode = [prepareLeaveGame, prepareLeaveGame];
     158    var btArgs = [true, false];
     159    messageBox(400, 200, "You are exiting the game, will you return soon?", "Confirmation", 0, btCaptions, btCode, btArgs);
     160}
    154161
    155162function openDeleteDialog(selection)
    156163{
  • binaries/data/mods/public/gui/session/messages.js

     
    207207        {
    208208            if (! message.hosts[host])
    209209            {
     210                // cache values
     211                var removedPlayerID = g_PlayerAssignments[host].player;
     212                var removedPlayerName = g_PlayerAssignments[host].name;
     213                var removedPlayerState = g_Players[removedPlayerID].state;
    210214                // Tell the user about the disconnection
    211215                addChatMessage({ "type": "disconnect", "guid": host });
    212216
    213217                // Update the cached player data, so we can display the disconnection status
    214218                updatePlayerDataRemove(g_Players, host);
     219
     220                if (removedPlayerState != "active")
     221                    return;
     222                // start timer and show timeout message
     223                Engine.PostNetworkCommand({
     224                    "type": "start-player-timeout",
     225                    "playerID": removedPlayerID,
     226                    "playerName": removedPlayerName,
     227                    "rejoinTimeLimit": REJOIN_TIME_LIMIT
     228                });
    215229            }
    216230        }
    217231
     
    225239
    226240                // Tell the user about the connection
    227241                addChatMessage({ "type": "connect", "guid": host }, message.hosts);
     242           
     243                if (g_Players[message.hosts[host].player].state != "active")
     244                    return;
     245                // stop timer and show timeout message
     246                Engine.PostNetworkCommand({
     247                    "type": "stop-player-timeout",
     248                    "playerID": message.hosts[host].player,
     249                });
    228250            }
    229251        }
    230252
  • binaries/data/mods/public/gui/session/session.js

     
    11// Network Mode
    22var g_IsNetworked = false;
     3const REJOIN_TIME_LIMIT = 15; // rejoin time limit in seconds
    34
    45// Is this user in control of game settings (i.e. is a network server, or offline player)
    56var g_IsController;
     
    3738// Whether the player has lost/won and reached the end of their game
    3839var g_GameEnded = false;
    3940
     41// true, if leave game was called
     42var g_leaveGameInProcess = false;
     43
    4044var g_Disconnected = false; // Lost connection to server
    4145
    4246// Holds player states from the last tick
     
    234238    Engine.SubmitUserReport("profile", 3, JSON.stringify(data));
    235239}
    236240
    237 function resignGame()
     241/**
     242 * let's a player resign
     243 * leaveGameAfterResign: if true, game is quit, after resign
     244 */
     245function resignGame(leaveGameAfterResign)
    238246{
    239247    var simState = GetSimState();
    240248
     
    241249    // Players can't resign if they've already won or lost.
    242250    if (simState.players[Engine.GetPlayerID()].state != "active" || g_Disconnected)
    243251        return;
    244 
    245252    // Tell other players that we have given up and been defeated
    246253    Engine.PostNetworkCommand({
    247254        "type": "defeat-player",
     
    248255        "playerId": Engine.GetPlayerID()
    249256    });
    250257
    251     global.music.setState(global.music.states.DEFEAT);
    252     resumeGame();
     258    // resume to the game, if the resign button was used
     259    if (!leaveGameAfterResign)
     260    {
     261        global.music.setState(global.music.states.DEFEAT);
     262        resumeGame();
     263    }
    253264}
    254265
    255 function leaveGame()
     266/**
     267 * prepare to leave the game
     268 * willRejoin: can be set to true, in case of network game, if the player just has to reboot or restart the game
     269 */
     270function prepareLeaveGame(willRejoin)
    256271{
    257272    var extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState");
    258273    var playerState = extendedSimState.players[Engine.GetPlayerID()];
    259274    var mapSettings = Engine.GetMapSettings();
    260275    var gameResult;
     276    var timeUntilEngineEndsGame = 1;
    261277
    262278    if (g_Disconnected)
    263279    {
     
    274290    else // "active"
    275291    {
    276292        gameResult = "You have abandoned the game.";
    277 
    278         // Tell other players that we have given up and been defeated
    279         Engine.PostNetworkCommand({
    280             "type": "defeat-player",
    281             "playerId": Engine.GetPlayerID()
    282         });
    283 
    284293        global.music.setState(global.music.states.DEFEAT);
     294       
     295        // resign, if player click on "No, I resign"
     296        if (!willRejoin)
     297        {
     298            gameResult = "You have been defeated...";
     299            resignGame(true);
     300            timeUntilEngineEndsGame = 5000; // give engine some time to deliver the network message (before the client disconnects...)
     301        }
    285302    }
     303    g_leaveGameInProcess = true;
     304    setTimeout(function() { leaveGame({"gameResult": gameResult, "extendedSimState": extendedSimState, "mapSettings": mapSettings}); }, timeUntilEngineEndsGame);
     305}
    286306
     307/**
     308 * leaves the game; is needed to give network messages time to reach their destination
     309 * data: must contain gameResult, extendedSimState and mapSettings
     310 */
     311function leaveGame(data)
     312{
    287313    stopAmbient();
    288314    Engine.EndGame();
    289315
     
    291317        Engine.SendUnregisterGame();
    292318
    293319    Engine.SwitchGuiPage("page_summary.xml", {
    294                             "gameResult"  : gameResult,
    295                             "timeElapsed" : extendedSimState.timeElapsed,
    296                             "playerStates": extendedSimState.players,
     320                            "gameResult"  : data.gameResult,
     321                            "timeElapsed" : data.extendedSimState.timeElapsed,
     322                            "playerStates": data.extendedSimState.players,
    297323                            "players": g_Players,
    298                             "mapSettings": mapSettings
     324                            "mapSettings": data.mapSettings
    299325                         });
    300326}
    301327
     
    427453        var btCode = [null];
    428454        var message = "Press OK to continue";
    429455    }
    430     else
     456    else if (!g_leaveGameInProcess)
    431457    {
    432458        var btCaptions = ["Yes", "No"];
    433         var btCode = [leaveGame, null];
     459        var btCode = [prepareLeaveGame, null];
    434460        var message = "Do you want to quit?";
    435461    }
     462    else
     463    {
     464        var btCaptions = ["Ok"];
     465        var btCode = [null];
     466        var message = "You have been defeated. Game will exit now.";
     467    }
    436468
    437469    if (playerState.state == "defeated")
    438470    {
     
    495527    updateTimeNotifications(); 
    496528
    497529    // Update music state on basis of battle state.
    498     var battleState = Engine.GuiInterfaceCall("GetBattleState", Engine.GetPlayerID());
    499     if (battleState)
    500         global.music.setState(global.music.states[battleState]);
     530    //var battleState = Engine.GuiInterfaceCall("GetBattleState", Engine.GetPlayerID());
     531    //if (battleState)
     532    //  global.music.setState(global.music.states[battleState]);
    501533   
    502534}
    503535
  • binaries/data/mods/public/gui/session/session.xml

     
    776776        z="40"
    777777    >
    778778        <object size="4 36 100%-4 50%+20">
     779       
     780            <!-- Manual button -->
     781            <object type="button"
     782                name="manualButton"
     783                style="StoneButtonFancy"
     784                size="0 0 100% 28"
     785                tooltip_style="sessionToolTip"
     786            >
     787                Manual
     788                <action on="Press">openManual();</action>
     789            </object>
     790           
     791            <!-- Chat button -->
     792            <object type="button"
     793                name="chatButton"
     794                style="StoneButtonFancy"
     795                size="0 32 100% 60"
     796                tooltip_style="sessionToolTip"
     797            >
     798                Chat
     799                <action on="Press">chatMenuButton();</action>
     800            </object>
    779801
    780         <!-- Settings button -->
    781         <object type="button"
    782             name="settingsButton"
    783             style="StoneButtonFancy"
    784             size="0 0 100% 28"
    785             tooltip_style="sessionToolTip"
    786         >
    787             Settings
    788             <action on="Press">settingsMenuButton();</action>
    789         </object>
     802            <!-- Save game button -->
     803            <object type="button"
     804                name="saveGameButton"
     805                style="StoneButtonFancy"
     806                size="0 64 100% 92"
     807                tooltip_style="sessionToolTip"
     808            >
     809                Save
     810                <action on="Press">
     811                openSave();
     812                </action>
     813            </object>
     814           
     815            <!-- Settings button -->
     816            <object type="button"
     817                name="settingsButton"
     818                style="StoneButtonFancy"
     819                size="0 96 100% 124"
     820                tooltip_style="sessionToolTip"
     821            >
     822                Settings
     823                <action on="Press">settingsMenuButton();</action>
     824            </object>
    790825
    791 
    792         <!-- Save game button -->
    793         <object type="button"
    794             name="saveGameButton"
    795             style="StoneButtonFancy"
    796             size="0 32 100% 60"
    797             tooltip_style="sessionToolTip"
    798         >
    799             Save
    800             <action on="Press">
    801             openSave();
    802             </action>
     826            <!-- Pause / Resume Button -->
     827            <object type="button"
     828                name="pauseButton"
     829                style="StoneButtonFancy"
     830                size="0 128 100% 156"
     831                tooltip_style="sessionToolTip"
     832            >
     833                <object name="pauseButtonText" type="text" style="CenteredButtonText" ghost="true">Pause</object>
     834                <action on="Press">togglePause();</action>
     835            </object>
     836           
     837            <!-- Resign button -->
     838            <object type="button"
     839                name="menuResignButton"
     840                style="StoneButtonFancy"
     841                size="0 160 100% 188"
     842                tooltip_style="sessionToolTip"
     843            >
     844                Resign
     845                <action on="Press">resignMenuButton();</action>
     846            </object>
     847           
     848            <!-- Exit button -->
     849            <object type="button"
     850                name="menuExitButton"
     851                style="StoneButtonFancy"
     852                size="0 192 100% 220"
     853                tooltip_style="sessionToolTip"
     854            >
     855                Exit
     856                <action on="Press">exitMenuButton();</action>
     857            </object>
    803858        </object>
    804 
    805         <!-- Chat button -->
    806         <object type="button"
    807             name="chatButton"
    808             style="StoneButtonFancy"
    809             size="0 64 100% 92"
    810             tooltip_style="sessionToolTip"
    811         >
    812             Chat
    813             <action on="Press">chatMenuButton();</action>
    814         </object>
    815 
    816         <!-- Resign button -->
    817         <object type="button"
    818             name="menuResignButton"
    819             style="StoneButtonFancy"
    820             size="0 96 100% 124"
    821             tooltip_style="sessionToolTip"
    822         >
    823             Resign
    824             <action on="Press">resignMenuButton();</action>
    825         </object>
    826 
    827         <!-- Exit button -->
    828         <object type="button"
    829             name="menuExitButton"
    830             style="StoneButtonFancy"
    831             size="0 128 100% 156"
    832             tooltip_style="sessionToolTip"
    833         >
    834             Exit
    835             <action on="Press">exitMenuButton();</action>
    836         </object>
    837 
    838         <!-- Pause / Resume Button -->
    839         <object type="button"
    840             name="pauseButton"
    841             style="StoneButtonFancy"
    842             size="0 160 100% 188"
    843             tooltip_style="sessionToolTip"
    844         >
    845             <object name="pauseButtonText" type="text" style="CenteredButtonText" ghost="true">Pause</object>
    846             <action on="Press">togglePause();</action>
    847         </object>
    848 
    849         <!-- Manual button -->
    850         <object type="button"
    851             name="manualButton"
    852             style="StoneButtonFancy"
    853             size="0 192 100% 220"
    854             tooltip_style="sessionToolTip"
    855         >
    856             Manual
    857             <action on="Press">openManual();</action>
    858         </object>
    859         </object>
    860859    </object>
    861860
    862861    <!-- In-progress research -->
  • binaries/data/mods/public/simulation/components/EndGameManager.js

     
    1919    // Allied victory means allied players can win if victory conditions are met for each of them
    2020    // Would be false for a "last man standing" game (when diplomacy is fully implemented)
    2121    this.alliedVictory = true;
     22   
     23    this.autoPlayerTimeout = [];
    2224};
    2325
    2426EndGameManager.prototype.SetGameType = function(newGameType)
     
    3234    return this.gameType == type;
    3335};
    3436
     37EndGameManager.prototype.startPlayerTimeout = function(playerID, playerName, timeout)
     38{
     39    // check, if the player is active
     40    var cmpPlayer =  Engine.QueryInterface(playerID, IID_Player);
     41    if (!cmpPlayer || cmpPlayer.GetState() != "active")
     42        return;
     43    var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     44    var timeElapsed = cmpTimer.GetTime();
     45    warn("["+timeElapsed+"] state: " + cmpPlayer.GetState() + " (should not be active...)");
     46   
     47    var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     48    var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     49    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     50
     51    if (!cmpGuiInterface || !cmpTimer || !cmpPlayerManager)
     52        return;
     53       
     54    // get players to send the message
     55    var players = [];
     56    for (var i = 1; i < cmpPlayerManager.GetNumPlayers(); i++)
     57            players.push(i);   
     58
     59    // add timers
     60    var textTimerID = cmpGuiInterface.AddTimeNotification({
     61        "message": playerName + " will be auto-resigned in %T",
     62        "players": players,
     63        "time": timeout
     64    });     
     65    var timerID = cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_EndGameManager, "MarkPlayerAsAutoResigned", timeout, playerID);
     66    // save timer IDs
     67    this.autoPlayerTimeout[playerID] = [textTimerID, timerID];
     68};
     69
     70EndGameManager.prototype.stopPlayerTimeout = function(playerID)
     71{
     72    if (!this.autoPlayerTimeout[playerID]) // no timeout for player
     73        return;
     74    var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     75    var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     76    if (!cmpGuiInterface || !cmpTimer)
     77        return;
     78   
     79    // delete the timers
     80    var timerIDs = this.autoPlayerTimeout[playerID];
     81    cmpGuiInterface.DeleteTimeNotification(timerIDs[0]);
     82    cmpTimer.CancelTimer(timerIDs[1]);
     83    delete this.autoPlayerTimeout[playerID];
     84};
     85
     86
     87/*
     88 * marks an player as auto resigned after an timeout.
     89 * playerID: player ID of the player to mark as auto resigned
     90 */
     91EndGameManager.prototype.MarkPlayerAsAutoResigned = function(playerID)
     92{
     93    warn("request for auto mark");
     94    var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     95    if (!cmpPlayerMan)
     96        return;
     97
     98    var playerEnt = cmpPlayerMan.GetPlayerByID(playerID);
     99    if (playerEnt == INVALID_ENTITY)
     100        return;
     101    warn("auto marked");
     102    // send OnPlayerDefeated message
     103    Engine.PostMessage(playerEnt, MT_PlayerDefeated, { "playerId": playerID } );
     104};
     105
    35106EndGameManager.prototype.MarkPlayerAsWon = function(playerID)
    36107{
    37108    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
  • binaries/data/mods/public/simulation/components/Player.js

     
    576576
    577577Player.prototype.OnPlayerDefeated = function(msg)
    578578{
     579var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     580    var timeElapsed = cmpTimer.GetTime();
     581    warn("["+timeElapsed+"] OnPlayerDefeated..........");
    579582    this.state = "defeated";
    580583
    581584    // TODO: Tribute all resources to this player's active allies (if any)
     
    600603
    601604    // Reveal the map for this player.
    602605    cmpRangeManager.SetLosRevealAll(this.playerID, true);
    603 
     606    var timeElapsed = cmpTimer.GetTime();
     607    warn("["+timeElapsed+"] OnPlayerDefeated.........." + this.state);
    604608    // Send a chat message notifying of the player's defeat.
    605609    var notification = {"type": "defeat", "player": this.playerID};
    606610    var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    323323        Engine.PostMessage(playerEnt, MT_PlayerDefeated, { "playerId": player } );
    324324        break;
    325325
     326    case "start-player-timeout":
     327        var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
     328        if (!cmpEndGameManager)
     329            return;
     330        cmpEndGameManager.startPlayerTimeout(cmd.playerID, cmd.playerName, cmd.rejoinTimeLimit * 1000);
     331        break;
     332       
     333    case "stop-player-timeout":
     334        var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
     335        if (!cmpEndGameManager)
     336            return;
     337        cmpEndGameManager.stopPlayerTimeout(cmd.playerID);
     338        break;
     339       
    326340    case "garrison":
    327341        // Verify that the building can be controlled by the player or is mutualAlly
    328342        if (CanControlUnitOrIsAlly(cmd.target, player, controlAllUnits))