diff --git a/src/engine/client.h b/src/engine/client.h index 3ed77e036..3497958d3 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -179,6 +179,8 @@ public: virtual const char *GetCurrentMapPath() = 0; virtual unsigned GetMapCrc() = 0; + virtual int GetCurrentRaceTime() = 0; + virtual void RaceRecord_Start(const char *pFilename) = 0; virtual void RaceRecord_Stop() = 0; virtual bool RaceRecord_IsRecording() = 0; @@ -220,6 +222,7 @@ public: virtual int OnSnapInput(int *pData, bool Dummy, bool Force) = 0; virtual void OnDummySwap() = 0; virtual void SendDummyInfo(bool Start) = 0; + virtual int GetLastRaceTick() = 0; virtual const char *GetItemName(int Type) = 0; virtual const char *Version() = 0; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index ae7627d37..7bd838132 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -824,6 +824,13 @@ void CClient::DummyDisconnect(const char *pReason) GameClient()->OnDummyDisconnect(); } +int CClient::GetCurrentRaceTime() +{ + if(GameClient()->GetLastRaceTick() < 0) + return 0; + return (GameTick() - GameClient()->GetLastRaceTick()) / 50; +} + int CClient::SendMsgExY(CMsgPacker *pMsg, int Flags, bool System, int NetClient) { CNetChunk Packet; diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 177dff603..0f73de0ec 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -397,6 +397,8 @@ public: void GenerateTimeoutSeed(); void GenerateTimeoutCodes(); + virtual int GetCurrentRaceTime(); + const char *GetCurrentMap(); const char *GetCurrentMapPath(); unsigned GetMapCrc(); diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 3fd18325a..b8d3c99c0 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -387,7 +387,7 @@ MACRO_CONFIG_INT(ClChatReset, cl_chat_reset, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAV MACRO_CONFIG_INT(ClShowDirection, cl_show_direction, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Show tee direction") MACRO_CONFIG_INT(ClHttpMapDownload, cl_http_map_download, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Try fast HTTP map download first") MACRO_CONFIG_INT(ClOldGunPosition, cl_old_gun_position, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Tees hold gun a bit higher like in TW 0.6.1 and older") -MACRO_CONFIG_INT(ClConfirmDisconnect, cl_confirm_disconnect, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Confirmation popup before disconnecting") +MACRO_CONFIG_INT(ClConfirmDisconnectQuitTime, cl_confirm_disconnect_quit_time, 20, -1, 1440, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Confirmation popup before disconnecting/quitting after game time (in minutes, -1 to turn off, 0 to always turn on)") MACRO_CONFIG_STR(ClTimeoutCode, cl_timeout_code, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Timeout code to use") MACRO_CONFIG_STR(ClDummyTimeoutCode, cl_dummy_timeout_code, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Dummy Timeout code to use") MACRO_CONFIG_STR(ClTimeoutSeed, cl_timeout_seed, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Timeout seed") diff --git a/src/game/client/components/ghost.cpp b/src/game/client/components/ghost.cpp index 8d2fa12a7..59e6f9f8c 100644 --- a/src/game/client/components/ghost.cpp +++ b/src/game/client/components/ghost.cpp @@ -263,7 +263,7 @@ void CGhost::OnNewSnapshot() { CServerInfo ServerInfo; Client()->GetServerInfo(&ServerInfo); - if(!IsRace(&ServerInfo) || !g_Config.m_ClRaceGhost || Client()->State() != IClient::STATE_ONLINE) + if(!IsRace(&ServerInfo) || Client()->State() != IClient::STATE_ONLINE) return; if(!m_pClient->m_Snap.m_pGameInfoObj || m_pClient->m_Snap.m_SpecInfo.m_Active || !m_pClient->m_Snap.m_pLocalCharacter || !m_pClient->m_Snap.m_pLocalPrevCharacter) return; @@ -271,14 +271,18 @@ void CGhost::OnNewSnapshot() bool RaceFlag = m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_RACETIME; bool ServerControl = RaceFlag && g_Config.m_ClRaceGhostServerControl; - if(!ServerControl) - CheckStartLocal(false); - else - CheckStart(); + if(g_Config.m_ClRaceGhost) + { + if(!ServerControl) + CheckStartLocal(false); + else + CheckStart(); - if(m_Recording) - AddInfos(m_pClient->m_Snap.m_pLocalCharacter); + if(m_Recording) + AddInfos(m_pClient->m_Snap.m_pLocalCharacter); + } + // Record m_LastRaceTick for g_Config.m_ClConfirmDisconnectQuitTime anyway int RaceTick = -m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer; m_LastRaceTick = RaceFlag ? RaceTick : -1; } @@ -622,3 +626,8 @@ void CGhost::OnMapLoad() m_pClient->m_pMenus->GhostlistPopulate(); m_AllowRestart = false; } + +int CGhost::GetLastRaceTick() +{ + return m_LastRaceTick; +} diff --git a/src/game/client/components/ghost.h b/src/game/client/components/ghost.h index b0884ca46..b1e134c04 100644 --- a/src/game/client/components/ghost.h +++ b/src/game/client/components/ghost.h @@ -165,6 +165,8 @@ public: class IGhostLoader *GhostLoader() const { return m_pGhostLoader; } class IGhostRecorder *GhostRecorder() const { return m_pGhostRecorder; } + + int GetLastRaceTick(); }; #endif diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index e49710542..a6c026829 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -819,7 +819,16 @@ int CMenus::RenderMenubar(CUIRect r) Box.VSplitRight(33.0f, &Box, &Button); static int s_QuitButton=0; if(DoButton_MenuTab(&s_QuitButton, "\xEE\x97\x8D", 0, &Button, CUI::CORNER_T)) - m_Popup = POPUP_QUIT; + { + if(m_pClient->Editor()->HasUnsavedData() || Client()->GetCurrentRaceTime() / 60 >= g_Config.m_ClConfirmDisconnectQuitTime) + { + m_Popup = POPUP_QUIT; + } + else + { + Client()->Quit(); + } + } Box.VSplitRight(10.0f, &Box, &Button); Box.VSplitRight(33.0f, &Box, &Button); @@ -1217,7 +1226,6 @@ int CMenus::Render() #endif // additional info - Box.HSplitTop(10.0f, 0, &Box); Box.VMargin(20.f/UI()->Scale(), &Box); if(m_pClient->Editor()->HasUnsavedData()) { diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 879db4f08..3aa827cf5 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -54,10 +54,14 @@ void CMenus::RenderGame(CUIRect MainView) static int s_DisconnectButton = 0; if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button)) { - if(g_Config.m_ClConfirmDisconnect) + if(Client()->GetCurrentRaceTime() / 60 >= g_Config.m_ClConfirmDisconnectQuitTime) + { m_Popup = POPUP_DISCONNECT; + } else + { Client()->Disconnect(); + } } static int s_SpectateButton = 0; @@ -149,7 +153,14 @@ void CMenus::RenderGame(CUIRect MainView) } else { - Client()->DummyDisconnect(0); + if(Client()->GetCurrentRaceTime() / 60 >= g_Config.m_ClConfirmDisconnectQuitTime) + { + m_Popup = POPUP_DISCONNECT; + } + else + { + Client()->DummyDisconnect(0); + } } } } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1da331646..72c10529f 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -689,6 +689,11 @@ void CGameClient::OnDummyDisconnect() m_LastNewPredictedTick[1] = -1; } +int CGameClient::GetLastRaceTick() +{ + return m_pGhost->GetLastRaceTick(); +} + void CGameClient::OnRelease() { // release all systems diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 6c0d0ac47..53879b118 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -382,6 +382,8 @@ public: CWeaponData *GetWeaponData(int Tick) { return &m_aWeaponData[((Tick%150)+150)%150]; } CWeaponData *FindWeaponData(int TargetTick); + virtual int GetLastRaceTick(); + void FindWeaker(bool IsWeaker[2][MAX_CLIENTS]); bool AntiPingPlayers() { return g_Config.m_ClAntiPing && g_Config.m_ClAntiPingPlayers && !m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK && (m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_Tuning[g_Config.m_ClDummy].m_PlayerHooking); }