diff --git a/data/languages/bosnian.txt b/data/languages/bosnian.txt index fd3c1c28d..c76c50df2 100644 --- a/data/languages/bosnian.txt +++ b/data/languages/bosnian.txt @@ -513,6 +513,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -699,6 +702,9 @@ Make collision Make external == +Max Screenshots +== + Max demos == diff --git a/data/languages/czech.txt b/data/languages/czech.txt index cfbe3e508..bd10685a8 100644 --- a/data/languages/czech.txt +++ b/data/languages/czech.txt @@ -489,6 +489,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -687,6 +690,9 @@ Make collision Make external == +Max Screenshots +== + Max demos == diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt index 9165a2f8d..75e0962c0 100644 --- a/data/languages/dutch.txt +++ b/data/languages/dutch.txt @@ -937,6 +937,12 @@ ZO Automatically record demos == +Automatically take game over screenshot +== + +Max Screenshots +== + Max demos == diff --git a/data/languages/finnish.txt b/data/languages/finnish.txt index f766429ad..a48838e2c 100644 --- a/data/languages/finnish.txt +++ b/data/languages/finnish.txt @@ -513,6 +513,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -699,6 +702,9 @@ Make collision Make external == +Max Screenshots +== + Max demos == diff --git a/data/languages/french.txt b/data/languages/french.txt index 62486b27f..48d2f4ea4 100644 --- a/data/languages/french.txt +++ b/data/languages/french.txt @@ -749,6 +749,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -821,6 +824,9 @@ Left mouse button to move. Hold shift to move the texture. Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point aswell. Right click to delete. == +Max Screenshots +== + Max demos == diff --git a/data/languages/german.txt b/data/languages/german.txt index 383d42876..a71b3e695 100644 --- a/data/languages/german.txt +++ b/data/languages/german.txt @@ -939,6 +939,12 @@ Loading DDRace Client Automatically record demos == +Automatically take game over screenshot +== + +Max Screenshots +== + Max demos == diff --git a/data/languages/italian.txt b/data/languages/italian.txt index 1ace3dbe5..c44f04eb7 100644 --- a/data/languages/italian.txt +++ b/data/languages/italian.txt @@ -483,6 +483,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -684,6 +687,9 @@ Make collision Make external == +Max Screenshots +== + Max demos == diff --git a/data/languages/polish.txt b/data/languages/polish.txt index 0d1d169f0..85871f9ad 100644 --- a/data/languages/polish.txt +++ b/data/languages/polish.txt @@ -795,6 +795,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -855,6 +858,9 @@ Load Load map == +Max Screenshots +== + Max demos == diff --git a/data/languages/portuguese.txt b/data/languages/portuguese.txt index b496b872a..e0745ed46 100644 --- a/data/languages/portuguese.txt +++ b/data/languages/portuguese.txt @@ -510,6 +510,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -699,6 +702,9 @@ Make collision Make external == +Max Screenshots +== + Max demos == diff --git a/data/languages/russian.txt b/data/languages/russian.txt index 2cb19a604..97f474157 100644 --- a/data/languages/russian.txt +++ b/data/languages/russian.txt @@ -807,6 +807,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -861,6 +864,9 @@ Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point Load map == +Max Screenshots +== + Max demos == diff --git a/data/languages/serbian.txt b/data/languages/serbian.txt index e1ec27a32..066a783e6 100644 --- a/data/languages/serbian.txt +++ b/data/languages/serbian.txt @@ -513,6 +513,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -699,6 +702,9 @@ Make collision Make external == +Max Screenshots +== + Max demos == diff --git a/data/languages/swedish.txt b/data/languages/swedish.txt index 94440b1de..e428e2c93 100644 --- a/data/languages/swedish.txt +++ b/data/languages/swedish.txt @@ -483,6 +483,9 @@ Aspect ratio Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -684,6 +687,9 @@ Make collision Make external == +Max Screenshots +== + Max demos == diff --git a/data/languages/ukrainian.txt b/data/languages/ukrainian.txt index a78edb57b..be8bea899 100644 --- a/data/languages/ukrainian.txt +++ b/data/languages/ukrainian.txt @@ -855,6 +855,9 @@ Alpha value of the envelope Automatically record demos == +Automatically take game over screenshot +== + Blue value of the envelope == @@ -891,6 +894,9 @@ Left mouse to drag. Hold ctrl to be more precise. Hold shift to alter time point Load map == +Max Screenshots +== + Max demos == diff --git a/src/engine/client.h b/src/engine/client.h index df69fbb54..ab1f05479 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -78,6 +78,7 @@ public: virtual const char *DemoPlayer_Play(const char *pFilename, int StorageType) = 0; virtual void DemoRecorder_Start(const char *pFilename, bool WithTimestamp) = 0; virtual void DemoRecorder_Stop() = 0; + virtual void AutoScreenshot_Start() = 0; // networking virtual void EnterGame() = 0; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index e2334b954..b1d02a334 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -413,6 +413,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD m_WindowMustRefocus = 0; m_SnapCrcErrors = 0; + m_AutoScreenshotRecycle = false; m_AckGameTick = -1; m_CurrentRecvTick = 0; @@ -1938,6 +1939,8 @@ void CClient::Run() } } + AutoScreenshot_Cleanup(); + // check conditions if(State() == IClient::STATE_QUITING) break; @@ -2023,10 +2026,33 @@ void CClient::Con_Ping(IConsole::IResult *pResult, void *pUserData, int ClientID pSelf->m_PingStartTime = time_get(); } +void CClient::AutoScreenshot_Start() +{ + if(g_Config.m_ClAutoScreenshot) + { + Graphics()->TakeScreenshot("auto/autoscreen"); + m_AutoScreenshotRecycle = true; + } +} + +void CClient::AutoScreenshot_Cleanup() +{ + if(m_AutoScreenshotRecycle) + { + if(g_Config.m_ClAutoScreenshotMax) + { + // clean up auto taken screens + CFileCollection AutoScreens; + AutoScreens.Init(Storage(), "screenshots/auto", "autoscreen", ".png", g_Config.m_ClAutoScreenshotMax); + } + m_AutoScreenshotRecycle = false; + } +} + void CClient::Con_Screenshot(IConsole::IResult *pResult, void *pUserData, int ClientID) { CClient *pSelf = (CClient *)pUserData; - pSelf->Graphics()->TakeScreenshot(); + pSelf->Graphics()->TakeScreenshot(0); } void CClient::Con_Rcon(IConsole::IResult *pResult, void *pUserData, int ClientID) diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 11036d229..bb5015a22 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -140,6 +140,7 @@ class CClient : public IClient, public CDemoPlayer::IListner NETADDR m_ServerAddress; int m_WindowMustRefocus; int m_SnapCrcErrors; + bool m_AutoScreenshotRecycle; int m_AckGameTick; int m_CurrentRecvTick; @@ -319,6 +320,9 @@ public: void DemoRecorder_HandleAutoStart(); void DemoRecorder_Stop(); + void AutoScreenshot_Start(); + void AutoScreenshot_Cleanup(); + virtual class CEngine *Engine() { return &m_Engine; } }; #endif diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp index fb9949533..82248f058 100644 --- a/src/engine/client/graphics.cpp +++ b/src/engine/client/graphics.cpp @@ -873,8 +873,11 @@ int CGraphics_SDL::WindowOpen() } -void CGraphics_SDL::TakeScreenshot() +void CGraphics_SDL::TakeScreenshot(const char *pFilename) { + char aDate[20]; + str_timestamp(aDate, sizeof(aDate)); + str_format(m_aScreenshotName, sizeof(m_aScreenshotName), "screenshots/%s_%s.png", pFilename?pFilename:"screenshot", aDate); m_DoScreenshot = true; } @@ -882,12 +885,7 @@ void CGraphics_SDL::Swap() { if(m_DoScreenshot) { - char aFilename[128]; - char aDate[20]; - - str_timestamp(aDate, sizeof(aDate)); - str_format(aFilename, sizeof(aFilename), "screenshots/screenshot_%s.png", aDate); - ScreenshotDirect(aFilename); + ScreenshotDirect(m_aScreenshotName); m_DoScreenshot = false; } diff --git a/src/engine/client/graphics.h b/src/engine/client/graphics.h index 17e3a83fa..20be3504f 100644 --- a/src/engine/client/graphics.h +++ b/src/engine/client/graphics.h @@ -41,6 +41,7 @@ protected: float m_Rotation; int m_Drawing; bool m_DoScreenshot; + char m_aScreenshotName[128]; float m_ScreenX0; float m_ScreenY0; @@ -136,7 +137,7 @@ public: virtual int WindowActive(); virtual int WindowOpen(); - virtual void TakeScreenshot(); + virtual void TakeScreenshot(const char *pFilename); virtual void Swap(); virtual int GetVideoModes(CVideoMode *pModes, int MaxModes); diff --git a/src/engine/graphics.h b/src/engine/graphics.h index 305319f96..de99caac1 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -127,7 +127,7 @@ public: virtual void SetColorVertex(const CColorVertex *pArray, int Num) = 0; virtual void SetColor(float r, float g, float b, float a) = 0; - virtual void TakeScreenshot() = 0; + virtual void TakeScreenshot(const char *pFilename) = 0; virtual int GetVideoModes(CVideoMode *pModes, int MaxModes) = 0; virtual void Swap() = 0; diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 7b048bce0..aeedafea7 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -19,6 +19,8 @@ MACRO_CONFIG_INT(ClAutoDemoRecord, cl_auto_demo_record, 0, 0, 1, CFGFLAG_SAVE|CF MACRO_CONFIG_INT(ClCpuThrottle, cl_cpu_throttle, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "", -1) MACRO_CONFIG_INT(ClEditor, cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "", -1) MACRO_CONFIG_INT(ClAutoDemoMax, cl_auto_demo_max, 10, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Maximum number of automatically recorded demos (0 = no limit)", -1) +MACRO_CONFIG_INT(ClAutoScreenshot, cl_auto_screenshot, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Automatically take game over screenshot", -1) +MACRO_CONFIG_INT(ClAutoScreenshotMax, cl_auto_screenshot_max, 10, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Maximum number of automatically created screenshots (0 = no limit)", -1) MACRO_CONFIG_INT(ClEventthread, cl_eventthread, 0, 0, 1, CFGFLAG_CLIENT, "Enables the usage of a thread to pump the events", -1) diff --git a/src/engine/shared/storage.cpp b/src/engine/shared/storage.cpp index d19be8a87..ffbd3aff5 100644 --- a/src/engine/shared/storage.cpp +++ b/src/engine/shared/storage.cpp @@ -57,10 +57,12 @@ public: { char aPath[MAX_PATH_LENGTH]; fs_makedir(GetPath(TYPE_SAVE, "screenshots", aPath, sizeof(aPath))); + fs_makedir(GetPath(TYPE_SAVE, "screenshots/auto", aPath, sizeof(aPath))); fs_makedir(GetPath(TYPE_SAVE, "maps", aPath, sizeof(aPath))); fs_makedir(GetPath(TYPE_SAVE, "dumps", aPath, sizeof(aPath))); fs_makedir(GetPath(TYPE_SAVE, "downloadedmaps", aPath, sizeof(aPath))); fs_makedir(GetPath(TYPE_SAVE, "demos", aPath, sizeof(aPath))); + fs_makedir(GetPath(TYPE_SAVE, "demos/auto", aPath, sizeof(aPath))); } return m_NumPaths ? 0 : 1; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 4f51d45eb..9d6328747 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -743,7 +743,7 @@ void CMenus::OnInit() // */ if(g_Config.m_ClShowWelcome) - m_Popup = POPUP_FIRST_LAUNCH; + m_Popup = POPUP_LANGUAGE; g_Config.m_ClShowWelcome = 0; Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this); @@ -979,6 +979,23 @@ int CMenus::Render() static float Offset = 0.0f; DoEditBox(&g_Config.m_Password, &TextBox, g_Config.m_Password, sizeof(g_Config.m_Password), 12.0f, &Offset, true); } + else if(m_Popup == POPUP_LANGUAGE) + { + Box = Screen; + Box.VMargin(150.0f, &Box); + Box.HMargin(150.0f, &Box); + Box.HSplitTop(20.f, &Part, &Box); + Box.HSplitBottom(20.f, &Box, &Part); + Box.HSplitBottom(24.f, &Box, &Part); + Box.HSplitBottom(20.f, &Box, 0); + Box.VMargin(20.0f, &Box); + RenderLanguageSelection(Box); + Part.VMargin(120.0f, &Part); + + static int s_Button = 0; + if(DoButton_Menu(&s_Button, Localize("Ok"), 0, &Part) || m_EscapePressed || m_EnterPressed) + m_Popup = POPUP_FIRST_LAUNCH; + } else if(m_Popup == POPUP_DELETE_DEMO) { CUIRect Yes, No; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 126d4001b..9cdd0bad1 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -95,6 +95,7 @@ class CMenus : public CComponent POPUP_MESSAGE, POPUP_DISCONNECTED, POPUP_PURE, + POPUP_LANGUAGE, POPUP_DELETE_DEMO, POPUP_PASSWORD, POPUP_QUIT, @@ -212,6 +213,7 @@ class CMenus : public CComponent static void ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); // found in menus_settings.cpp + void RenderLanguageSelection(CUIRect MainView); void RenderSettingsGeneral(CUIRect MainView); void RenderSettingsPlayer(CUIRect MainView); void RenderSettingsControls(CUIRect MainView); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index b12a0c8d5..f1b701ede 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -708,7 +708,7 @@ void LoadLanguageIndexfile(IStorage *pStorage, IConsole *pConsole, sorted_array< io_close(File); } -void CMenus::RenderSettingsGeneral(CUIRect MainView) +void CMenus::RenderLanguageSelection(CUIRect MainView) { static int s_LanguageList = 0; static int s_SelectedLanguage = 0; @@ -729,32 +729,7 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) int OldSelected = s_SelectedLanguage; - CUIRect List, Button, Label, Left; - MainView.HSplitBottom(10.0f, &MainView, 0); - MainView.HSplitBottom(70.0f, &MainView, &Left); - Left.VSplitMid(&Left, 0); - Left.HSplitTop(20.0f, &Button, &Left); - MainView.HSplitBottom(20.0f, &List, &MainView); - - // auto demo settings - { - if(DoButton_CheckBox(&g_Config.m_ClAutoDemoRecord, Localize("Automatically record demos"), g_Config.m_ClAutoDemoRecord, &Button)) - g_Config.m_ClAutoDemoRecord ^= 1; - - Left.HSplitTop(10.0f, 0, &Left); - Left.VSplitLeft(20.0f, 0, &Left); - Left.HSplitTop(20.0f, &Label, &Button); - Button.VSplitRight(20.0f, &Button, 0); - char aBuf[64]; - if(g_Config.m_ClAutoDemoMax) - str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max demos"), g_Config.m_ClAutoDemoMax); - else - str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max demos"), Localize("no limit")); - UI()->DoLabel(&Label, aBuf, 13.0f, -1); - g_Config.m_ClAutoDemoMax = static_cast(DoScrollbarH(&g_Config.m_ClAutoDemoMax, &Button, g_Config.m_ClAutoDemoMax/1000.0f)*1000.0f+0.1f); - } - - UiDoListboxStart(&s_LanguageList , &List, 24.0f, Localize("Language"), "", s_Languages.size(), 1, s_SelectedLanguage, s_ScrollValue); + UiDoListboxStart(&s_LanguageList , &MainView, 24.0f, Localize("Language"), "", s_Languages.size(), 1, s_SelectedLanguage, s_ScrollValue); for(sorted_array::range r = s_Languages.all(); !r.empty(); r.pop_front()) { @@ -773,6 +748,51 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) } } +void CMenus::RenderSettingsGeneral(CUIRect MainView) +{ + CUIRect List, Button, Label, Left, Right; + MainView.HSplitBottom(10.0f, &MainView, 0); + MainView.HSplitBottom(70.0f, &MainView, &Left); + Left.VSplitMid(&Left, &Right); + MainView.HSplitBottom(20.0f, &List, &MainView); + + // auto demo settings + { + Left.HSplitTop(20.0f, &Button, &Left); + if(DoButton_CheckBox(&g_Config.m_ClAutoDemoRecord, Localize("Automatically record demos"), g_Config.m_ClAutoDemoRecord, &Button)) + g_Config.m_ClAutoDemoRecord ^= 1; + + Right.HSplitTop(20.0f, &Button, &Right); + if(DoButton_CheckBox(&g_Config.m_ClAutoScreenshot, Localize("Automatically take game over screenshot"), g_Config.m_ClAutoScreenshot, &Button)) + g_Config.m_ClAutoScreenshot ^= 1; + + Left.HSplitTop(10.0f, 0, &Left); + Left.VSplitLeft(20.0f, 0, &Left); + Left.HSplitTop(20.0f, &Label, &Button); + Button.VSplitRight(20.0f, &Button, 0); + char aBuf[64]; + if(g_Config.m_ClAutoDemoMax) + str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max demos"), g_Config.m_ClAutoDemoMax); + else + str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max demos"), Localize("no limit")); + UI()->DoLabel(&Label, aBuf, 13.0f, -1); + g_Config.m_ClAutoDemoMax = static_cast(DoScrollbarH(&g_Config.m_ClAutoDemoMax, &Button, g_Config.m_ClAutoDemoMax/1000.0f)*1000.0f+0.1f); + + Right.HSplitTop(10.0f, 0, &Right); + Right.VSplitLeft(20.0f, 0, &Right); + Right.HSplitTop(20.0f, &Label, &Button); + Button.VSplitRight(20.0f, &Button, 0); + if(g_Config.m_ClAutoScreenshotMax) + str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max Screenshots"), g_Config.m_ClAutoScreenshotMax); + else + str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max Screenshots"), Localize("no limit")); + UI()->DoLabel(&Label, aBuf, 13.0f, -1); + g_Config.m_ClAutoScreenshotMax = static_cast(DoScrollbarH(&g_Config.m_ClAutoScreenshotMax, &Button, g_Config.m_ClAutoScreenshotMax/1000.0f)*1000.0f+0.1f); + } + + RenderLanguageSelection(List); +} + void CMenus::RenderSettings(CUIRect MainView) { static int s_SettingsPage = 0; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index f762f484a..8b57142f3 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -623,6 +623,12 @@ void CGameClient::OnStateChange(int NewState, int OldState) void CGameClient::OnShutdown() {} void CGameClient::OnEnterGame() {} +void CGameClient::OnGameOver() +{ + if(Client()->State() != IClient::STATE_DEMOPLAYBACK) + Client()->AutoScreenshot_Start(); +} + void CGameClient::OnRconLine(const char *pLine) { m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine); @@ -808,7 +814,13 @@ void CGameClient::OnNewSnapshot() } } else if(Item.m_Type == NETOBJTYPE_GAME) + { + static int s_GameOver = 0; m_Snap.m_pGameobj = (CNetObj_Game *)pData; + if(s_GameOver == 0 && m_Snap.m_pGameobj->m_GameOver != 0) + OnGameOver(); + s_GameOver = m_Snap.m_pGameobj->m_GameOver; + } else if(Item.m_Type == NETOBJTYPE_FLAG) m_Snap.m_paFlags[Item.m_Id%2] = (const CNetObj_Flag *)pData; } diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index be3738e53..f4d7b34f2 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -186,6 +186,7 @@ public: virtual void OnShutdown(); virtual void OnEnterGame(); virtual void OnRconLine(const char *pLine); + virtual void OnGameOver(); virtual const char *GetItemName(int Type); virtual const char *Version(); diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp index 352f51050..962fac2ec 100644 --- a/src/game/editor/ed_editor.cpp +++ b/src/game/editor/ed_editor.cpp @@ -3420,7 +3420,7 @@ void CEditor::UpdateAndRender() if(Input()->KeyDown(KEY_F10)) { - Graphics()->TakeScreenshot(); + Graphics()->TakeScreenshot(0); m_ShowMousePointer = true; }