Index: binaries/data/mods/public/gui/gamesetup/gamesetup.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -137,6 +137,7 @@ * Highlight ready players. */ const g_ReadyColor = "green"; +const g_StayReadyColor = "blue"; /** * Placeholder item for the map-dropdownlist. @@ -172,6 +173,9 @@ /** * Whether the current player is ready to start the game. + * 0 - not ready + * 1 - ready + * 2 - stay ready */ var g_IsReady; @@ -706,7 +710,7 @@ { --g_ReadyChanged; - if (g_ReadyChanged < 1 && g_PlayerAssignments[message.guid].player != -1) + if (g_ReadyChanged < 1 && g_PlayerAssignments[message.guid].player != -1 && message.status < 2) addChatMessage({ "type": message.status == 1 ? "ready" : "not-ready", "guid": message.guid @@ -1857,7 +1861,7 @@ function toggleReady() { - setReady(!g_IsReady); + setReady((g_IsReady + 1) % 3); } function setReady(ready, sendMessage = true) @@ -1871,14 +1875,15 @@ return; let button = Engine.GetGUIObjectByName("startGame"); - - button.caption = g_IsReady ? - translate("I'm not ready!") : - translate("I'm ready"); - - button.tooltip = g_IsReady ? - translate("State that you are not ready to play.") : - translate("State that you are ready to play!"); + button.caption = [ + translate("I'm ready"), translate("Stay ready"), + translate("I'm not ready!")][+g_IsReady]; + + button.tooltip = [ + translate("State that you are ready to play!"), + translate("Stay ready even when the game settings change."), + translate("State that you are not ready to play.") + ][+g_IsReady]; } function updateReadyUI() @@ -1897,7 +1902,9 @@ let pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[g_PlayerAssignments[guid].player - 1] : {}; isAI[g_PlayerAssignments[guid].player] = false; if (g_PlayerAssignments[guid].status || !g_IsNetworked) - Engine.GetGUIObjectByName("playerName[" + (g_PlayerAssignments[guid].player - 1) + "]").caption = '[color="' + g_ReadyColor + '"]' + translate(getSetting(pData, pDefs, "Name")) + '[/color]'; + Engine.GetGUIObjectByName("playerName[" + (g_PlayerAssignments[guid].player - 1) + "]").caption = + '[color="' + (g_PlayerAssignments[guid].status == 1 ? g_ReadyColor : g_StayReadyColor) + '"]' + + translate(getSetting(pData, pDefs, "Name")) + '[/color]'; else { Engine.GetGUIObjectByName("playerName[" + (g_PlayerAssignments[guid].player - 1) + "]").caption = translate(getSetting(pData, pDefs, "Name")); @@ -1913,7 +1920,8 @@ let pData = g_GameAttributes.settings.PlayerData ? g_GameAttributes.settings.PlayerData[playerid] : {}; let pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[playerid] : {}; if (isAI[playerid + 1]) - Engine.GetGUIObjectByName("playerName[" + playerid + "]").caption = '[color="' + g_ReadyColor + '"]' + translate(getSetting(pData, pDefs, "Name")) + '[/color]'; + Engine.GetGUIObjectByName("playerName[" + playerid + "]").caption = + '[color="' + g_StayReadyColor + '"]' + translate(getSetting(pData, pDefs, "Name")) + '[/color]'; } // The host is not allowed to start until everyone is ready. @@ -1950,7 +1958,7 @@ Engine.ClearAllPlayerReady(); setReady(true); } - else + else if (g_IsReady != 2) setReady(false, false); } Index: source/network/NetServer.cpp =================================================================== --- source/network/NetServer.cpp +++ source/network/NetServer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2017 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -774,7 +774,8 @@ void CNetServerWorker::ClearAllPlayerReady() { for (PlayerAssignmentMap::iterator it = m_PlayerAssignments.begin(); it != m_PlayerAssignments.end(); ++it) - it->second.m_Status = 0; + if (it->second.m_Status != 2) + it->second.m_Status = 0; SendPlayerAssignments(); }