From 6d9385b8bd045be4d355dcc207b4f746f2ffce6c Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:31:17 +0200 Subject: [PATCH 1/5] outro for RoE --- client/CServerHandler.cpp | 12 +++++++++++- client/NetPacksLobbyClient.cpp | 15 ++++++++++++--- client/lobby/CBonusSelection.cpp | 19 +++++++------------ client/lobby/CBonusSelection.h | 7 ++++--- config/campaignOverrides.json | 19 +++++++++++-------- docs/modders/Campaign_Format.md | 3 ++- lib/campaign/CampaignHandler.cpp | 3 ++- lib/campaign/CampaignState.cpp | 15 +++++++++++---- lib/campaign/CampaignState.h | 10 +++++++--- lib/serializer/ESerializationVersion.h | 3 ++- 10 files changed, 69 insertions(+), 37 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 744c51f2b..4c11c21f0 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -21,7 +21,9 @@ #include "globalLobby/GlobalLobbyClient.h" #include "lobby/CSelectionBase.h" #include "lobby/CLobbyScreen.h" +#include "lobby/CBonusSelection.h" #include "windows/InfoWindows.h" +#include "media/CMusicHandler.h" #include "mainmenu/CMainMenu.h" #include "mainmenu/CPrologEpilogVideo.h" @@ -704,7 +706,15 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared else { CMM->openCampaignScreen(ourCampaign->campaignSet); - GH.windows().createAndPushWindow(true, *campaignScoreCalculator, statistic); + if(!ourCampaign->getOutroVideo().empty()) + { + CCS->musich->stopMusic(); + GH.windows().createAndPushWindow(ourCampaign->getOutroVideo(), ourCampaign->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : ourCampaign->getVideoRim(), [campaignScoreCalculator, statistic](){ + GH.windows().createAndPushWindow(true, *campaignScoreCalculator, statistic); + }); + } + else + GH.windows().createAndPushWindow(true, *campaignScoreCalculator, statistic); } }; diff --git a/client/NetPacksLobbyClient.cpp b/client/NetPacksLobbyClient.cpp index 5d81fbdef..b9b54296e 100644 --- a/client/NetPacksLobbyClient.cpp +++ b/client/NetPacksLobbyClient.cpp @@ -31,6 +31,7 @@ #include "gui/WindowHandler.h" #include "widgets/Buttons.h" #include "widgets/TextControls.h" +#include "media/CMusicHandler.h" #include "../lib/CConfigHandler.h" #include "../lib/texts/CGeneralTextHandler.h" @@ -203,11 +204,19 @@ void ApplyOnLobbyScreenNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState & if(!lobby->bonusSel && handler.si->campState && handler.getState() == EClientState::LOBBY_CAMPAIGN) { - lobby->bonusSel = std::make_shared(); + auto bonusSel = std::make_shared(); + lobby->bonusSel = bonusSel; if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty()) - GH.windows().createAndPushWindow(handler.si->campState->getIntroVideo(), handler.si->campState->getIntroVideoRim().empty() ? ImagePath::builtin("INTRORIM") : handler.si->campState->getIntroVideoRim(), lobby->bonusSel); + { + CCS->musich->stopMusic(); + GH.windows().createAndPushWindow(handler.si->campState->getIntroVideo(), handler.si->campState->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : handler.si->campState->getVideoRim(), [bonusSel](){ + if(!CSH->si->campState->getMusic().empty()) + CCS->musich->playMusic(CSH->si->campState->getMusic(), true, false); + GH.windows().pushWindow(bonusSel); + }); + } else - GH.windows().pushWindow(lobby->bonusSel); + GH.windows().pushWindow(bonusSel); } if(lobby->bonusSel) diff --git a/client/lobby/CBonusSelection.cpp b/client/lobby/CBonusSelection.cpp index e6de278b1..c43532ace 100644 --- a/client/lobby/CBonusSelection.cpp +++ b/client/lobby/CBonusSelection.cpp @@ -59,8 +59,8 @@ #include "../../lib/mapObjects/CGHeroInstance.h" -CampaignIntroVideo::CampaignIntroVideo(VideoPath video, ImagePath rim, std::shared_ptr bonusSel) - : CWindowObject(BORDERED), bonusSel(bonusSel) +CampaignRimVideo::CampaignRimVideo(VideoPath video, ImagePath rim, std::function closeCb) + : CWindowObject(BORDERED), closeCb(closeCb) { OBJECT_CONSTRUCTION; @@ -70,26 +70,21 @@ CampaignIntroVideo::CampaignIntroVideo(VideoPath video, ImagePath rim, std::shar videoPlayer = std::make_shared(Point(80, 186), video, true, [this](){ exit(); }); setBackground(rim); - - CCS->musich->stopMusic(); } -void CampaignIntroVideo::exit() +void CampaignRimVideo::exit() { close(); - - if (!CSH->si->campState->getMusic().empty()) - CCS->musich->playMusic(CSH->si->campState->getMusic(), true, false); - - GH.windows().pushWindow(bonusSel); + if(closeCb) + closeCb(); } -void CampaignIntroVideo::clickPressed(const Point & cursorPosition) +void CampaignRimVideo::clickPressed(const Point & cursorPosition) { exit(); } -void CampaignIntroVideo::keyPressed(EShortcut key) +void CampaignRimVideo::keyPressed(EShortcut key) { exit(); } diff --git a/client/lobby/CBonusSelection.h b/client/lobby/CBonusSelection.h index e6b486390..176429f8d 100644 --- a/client/lobby/CBonusSelection.h +++ b/client/lobby/CBonusSelection.h @@ -33,14 +33,15 @@ class VideoWidgetOnce; class CBonusSelection; -class CampaignIntroVideo : public CWindowObject +class CampaignRimVideo : public CWindowObject { std::shared_ptr videoPlayer; - std::shared_ptr bonusSel; + + std::function closeCb; void exit(); public: - CampaignIntroVideo(VideoPath video, ImagePath rim, std::shared_ptr bonusSel); + CampaignRimVideo(VideoPath video, ImagePath rim, std::function closeCb); void clickPressed(const Point & cursorPosition) override; void keyPressed(EShortcut key) override; diff --git a/config/campaignOverrides.json b/config/campaignOverrides.json index a14f4fa2f..d7d46ae0f 100644 --- a/config/campaignOverrides.json +++ b/config/campaignOverrides.json @@ -1,4 +1,7 @@ { + "DATA/GOOD3" : { // RoE - "Song for the Father" + "outroVideo": "Endgame" + }, "MAPS/HC1_MAIN" : { // Heroes Chronicles 1 "regions": { @@ -29,7 +32,7 @@ { "voiceProlog": "chronicles_1/H3X2BBF", "voiceEpilog": "chronicles_1/N1C_D" } ], "loadingBackground": "chronicles_1/LoadBar", - "introVideoRim": "chronicles_1/INTRORIM", + "videoRim": "chronicles_1/INTRORIM", "introVideo": "chronicles_1/Intro" }, "MAPS/HC2_MAIN" : { // Heroes Chronicles 2 @@ -62,7 +65,7 @@ { "voiceProlog": "chronicles_2/G1A", "voiceEpilog": "chronicles_2/S1C" } ], "loadingBackground": "chronicles_2/LoadBar", - "introVideoRim": "chronicles_2/INTRORIM", + "videoRim": "chronicles_2/INTRORIM", "introVideo": "chronicles_2/Intro" }, "MAPS/HC3_MAIN" : { // Heroes Chronicles 3 @@ -95,7 +98,7 @@ { "voiceProlog": "chronicles_3/G3B", "voiceEpilog": "chronicles_3/ABVOFL2" } ], "loadingBackground": "chronicles_3/LoadBar", - "introVideoRim": "chronicles_3/INTRORIM", + "videoRim": "chronicles_3/INTRORIM", "introVideo": "chronicles_3/Intro" }, "MAPS/HC4_MAIN" : { // Heroes Chronicles 4 @@ -128,7 +131,7 @@ { "voiceProlog": "chronicles_4/H3X2NBD", "voiceEpilog": "chronicles_4/S1C" } ], "loadingBackground": "chronicles_4/LoadBar", - "introVideoRim": "chronicles_4/INTRORIM", + "videoRim": "chronicles_4/INTRORIM", "introVideo": "chronicles_4/Intro" }, "MAPS/HC5_MAIN" : { // Heroes Chronicles 5 @@ -155,7 +158,7 @@ { "voiceProlog": "chronicles_5/H3X2UAH", "voiceEpilog": "chronicles_5/N1C_D" } ], "loadingBackground": "chronicles_5/LoadBar", - "introVideoRim": "chronicles_5/INTRORIM", + "videoRim": "chronicles_5/INTRORIM", "introVideo": "chronicles_5/Intro" }, "MAPS/HC6_MAIN" : { // Heroes Chronicles 6 @@ -182,7 +185,7 @@ { "voiceProlog": "chronicles_6/ABVOAB5", "voiceEpilog": "chronicles_6/ABVODB2" } ], "loadingBackground": "chronicles_6/LoadBar", - "introVideoRim": "chronicles_6/INTRORIM", + "videoRim": "chronicles_6/INTRORIM", "introVideo": "chronicles_6/Intro" }, "MAPS/HC7_MAIN" : { // Heroes Chronicles 7 @@ -215,7 +218,7 @@ { "voiceProlog": "chronicles_7/ABVOFW4", "voiceEpilog": "chronicles_7/ABVOAB1" } ], "loadingBackground": "chronicles_7/LoadBar", - "introVideoRim": "chronicles_7/INTRORIM", + "videoRim": "chronicles_7/INTRORIM", "introVideo": "chronicles_7/Intro5" }, "MAPS/HC8_MAIN" : { // Heroes Chronicles 8 @@ -248,7 +251,7 @@ { "voiceProlog": "chronicles_8/H3X2ELE", "voiceEpilog": "chronicles_8/ABVOAB7" } ], "loadingBackground": "chronicles_8/LoadBar", - "introVideoRim": "chronicles_8/INTRORIM", + "videoRim": "chronicles_8/INTRORIM", "introVideo": "chronicles_8/Intro6" } } diff --git a/docs/modders/Campaign_Format.md b/docs/modders/Campaign_Format.md index 46cc7b2de..8a319f5e8 100644 --- a/docs/modders/Campaign_Format.md +++ b/docs/modders/Campaign_Format.md @@ -54,7 +54,8 @@ In header are parameters describing campaign properties - `"allowDifficultySelection"` is a boolean field (`true`/`false`) which allows or disallows to choose difficulty before scenario start - `"loadingBackground"` is for setting a different loading screen background - `"introVideo"` is for defining an optional intro video -- `"introVideoRim"` is for the Rim around the optional video (default is INTRORIM) +- `"introVideo"` is for defining an optional outro video +- `"videoRim"` is for the Rim around the optional video (default is INTRORIM) ## Scenario description diff --git a/lib/campaign/CampaignHandler.cpp b/lib/campaign/CampaignHandler.cpp index 5c7110e00..563437cb0 100644 --- a/lib/campaign/CampaignHandler.cpp +++ b/lib/campaign/CampaignHandler.cpp @@ -169,8 +169,9 @@ void CampaignHandler::readHeaderFromJson(CampaignHeader & ret, JsonNode & reader ret.modName = modName; ret.encoding = encoding; ret.loadingBackground = ImagePath::fromJson(reader["loadingBackground"]); - ret.introVideoRim = ImagePath::fromJson(reader["introVideoRim"]); + ret.videoRim = ImagePath::fromJson(reader["videoRim"]); ret.introVideo = VideoPath::fromJson(reader["introVideo"]); + ret.outroVideo = VideoPath::fromJson(reader["outroVideo"]); } CampaignScenario CampaignHandler::readScenarioFromJson(JsonNode & reader) diff --git a/lib/campaign/CampaignState.cpp b/lib/campaign/CampaignState.cpp index e1e33c758..d4e5aaf98 100644 --- a/lib/campaign/CampaignState.cpp +++ b/lib/campaign/CampaignState.cpp @@ -210,9 +210,9 @@ ImagePath CampaignHeader::getLoadingBackground() const return loadingBackground; } -ImagePath CampaignHeader::getIntroVideoRim() const +ImagePath CampaignHeader::getVideoRim() const { - return introVideoRim; + return videoRim; } VideoPath CampaignHeader::getIntroVideo() const @@ -220,6 +220,11 @@ VideoPath CampaignHeader::getIntroVideo() const return introVideo; } +VideoPath CampaignHeader::getOutroVideo() const +{ + return outroVideo; +} + const CampaignRegions & CampaignHeader::getRegions() const { return campaignRegions; @@ -490,10 +495,12 @@ void Campaign::overrideCampaign() loadLegacyData(CampaignRegions::fromJson(entry.second["regions"]), entry.second["scenarioCount"].Integer()); if(!entry.second["loadingBackground"].isNull()) loadingBackground = ImagePath::builtin(entry.second["loadingBackground"].String()); - if(!entry.second["introVideoRim"].isNull()) - introVideoRim = ImagePath::builtin(entry.second["introVideoRim"].String()); + if(!entry.second["videoRim"].isNull()) + videoRim = ImagePath::builtin(entry.second["videoRim"].String()); if(!entry.second["introVideo"].isNull()) introVideo = VideoPath::builtin(entry.second["introVideo"].String()); + if(!entry.second["outroVideo"].isNull()) + outroVideo = VideoPath::builtin(entry.second["outroVideo"].String()); } } diff --git a/lib/campaign/CampaignState.h b/lib/campaign/CampaignState.h index 303e7428e..67e027354 100644 --- a/lib/campaign/CampaignState.h +++ b/lib/campaign/CampaignState.h @@ -98,8 +98,9 @@ class DLL_LINKAGE CampaignHeader : public boost::noncopyable std::string modName; std::string encoding; ImagePath loadingBackground; - ImagePath introVideoRim; + ImagePath videoRim; VideoPath introVideo; + VideoPath outroVideo; int numberOfScenarios = 0; bool difficultyChosenByPlayer = false; @@ -124,8 +125,9 @@ public: std::string getEncoding() const; AudioPath getMusic() const; ImagePath getLoadingBackground() const; - ImagePath getIntroVideoRim() const; + ImagePath getVideoRim() const; VideoPath getIntroVideo() const; + VideoPath getOutroVideo() const; const CampaignRegions & getRegions() const; TextContainerRegistrable & getTexts(); @@ -153,9 +155,11 @@ public: if (h.version >= Handler::Version::CHRONICLES_SUPPORT) { h & loadingBackground; - h & introVideoRim; + h & videoRim; h & introVideo; } + if (h.version >= Handler::Version::CAMPAIGN_OUTRO_SUPPORT) + h & outroVideo; } }; diff --git a/lib/serializer/ESerializationVersion.h b/lib/serializer/ESerializationVersion.h index 5c72c10fa..8a5dc8fdb 100644 --- a/lib/serializer/ESerializationVersion.h +++ b/lib/serializer/ESerializationVersion.h @@ -57,6 +57,7 @@ enum class ESerializationVersion : int32_t PLAYER_STATE_OWNED_OBJECTS, // 858 - player state stores all owned objects in a single list SAVE_COMPATIBILITY_FIXES, // 859 - implementation of previoulsy postponed changes to serialization CHRONICLES_SUPPORT, // 860 - support for heroes chronicles + CAMPAIGN_OUTRO_SUPPORT, // 861 - support for campaign outro video - CURRENT = CHRONICLES_SUPPORT + CURRENT = CAMPAIGN_OUTRO_SUPPORT }; From 0df13040ec3043b698147059550dcd8d1c064799 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:32:44 +0200 Subject: [PATCH 2/5] doc fix --- docs/modders/Campaign_Format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modders/Campaign_Format.md b/docs/modders/Campaign_Format.md index 8a319f5e8..4711361ea 100644 --- a/docs/modders/Campaign_Format.md +++ b/docs/modders/Campaign_Format.md @@ -54,7 +54,7 @@ In header are parameters describing campaign properties - `"allowDifficultySelection"` is a boolean field (`true`/`false`) which allows or disallows to choose difficulty before scenario start - `"loadingBackground"` is for setting a different loading screen background - `"introVideo"` is for defining an optional intro video -- `"introVideo"` is for defining an optional outro video +- `"outroVideo"` is for defining an optional outro video - `"videoRim"` is for the Rim around the optional video (default is INTRORIM) ## Scenario description From 45625f0355c3a12bdc3b3abdd466adf88aca12e1 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:57:53 +0200 Subject: [PATCH 3/5] added AB intro; play only when resource exists --- client/CServerHandler.cpp | 4 +++- client/NetPacksLobbyClient.cpp | 3 ++- config/campaignOverrides.json | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 4c11c21f0..4e05ce505 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -24,6 +24,8 @@ #include "lobby/CBonusSelection.h" #include "windows/InfoWindows.h" #include "media/CMusicHandler.h" +#include "media/IVideoPlayer.h" + #include "mainmenu/CMainMenu.h" #include "mainmenu/CPrologEpilogVideo.h" @@ -706,7 +708,7 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared else { CMM->openCampaignScreen(ourCampaign->campaignSet); - if(!ourCampaign->getOutroVideo().empty()) + if(!ourCampaign->getOutroVideo().empty() && CCS->videoh->open(ourCampaign->getOutroVideo(), false)) { CCS->musich->stopMusic(); GH.windows().createAndPushWindow(ourCampaign->getOutroVideo(), ourCampaign->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : ourCampaign->getVideoRim(), [campaignScoreCalculator, statistic](){ diff --git a/client/NetPacksLobbyClient.cpp b/client/NetPacksLobbyClient.cpp index b9b54296e..f280b4d44 100644 --- a/client/NetPacksLobbyClient.cpp +++ b/client/NetPacksLobbyClient.cpp @@ -32,6 +32,7 @@ #include "widgets/Buttons.h" #include "widgets/TextControls.h" #include "media/CMusicHandler.h" +#include "media/IVideoPlayer.h" #include "../lib/CConfigHandler.h" #include "../lib/texts/CGeneralTextHandler.h" @@ -206,7 +207,7 @@ void ApplyOnLobbyScreenNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState & { auto bonusSel = std::make_shared(); lobby->bonusSel = bonusSel; - if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty()) + if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty() && CCS->videoh->open(handler.si->campState->getIntroVideo(), false)) { CCS->musich->stopMusic(); GH.windows().createAndPushWindow(handler.si->campState->getIntroVideo(), handler.si->campState->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : handler.si->campState->getVideoRim(), [bonusSel](){ diff --git a/config/campaignOverrides.json b/config/campaignOverrides.json index d7d46ae0f..28bbbfca6 100644 --- a/config/campaignOverrides.json +++ b/config/campaignOverrides.json @@ -2,6 +2,10 @@ "DATA/GOOD3" : { // RoE - "Song for the Father" "outroVideo": "Endgame" }, + "DATA/AB" : { // AB Intro + "introVideo": "H3X1intr", + "videoRim": "IntroRm2" + }, "MAPS/HC1_MAIN" : { // Heroes Chronicles 1 "regions": { From f1de265568d33c0b4b102bc506b355481ff61e96 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Fri, 6 Sep 2024 23:07:24 +0200 Subject: [PATCH 4/5] roe video in line as ab --- clientapp/EntryPoint.cpp | 2 -- config/campaignOverrides.json | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/clientapp/EntryPoint.cpp b/clientapp/EntryPoint.cpp index e32303f07..3ba0ff27c 100644 --- a/clientapp/EntryPoint.cpp +++ b/clientapp/EntryPoint.cpp @@ -410,8 +410,6 @@ void playIntro() if (!CCS->videoh->playIntroVideo(VideoPath::builtin("NWCLOGO.SMK"))) return; - - CCS->videoh->playIntroVideo(VideoPath::builtin("H3INTRO.SMK")); } static void mainLoop() diff --git a/config/campaignOverrides.json b/config/campaignOverrides.json index 28bbbfca6..ce667ba85 100644 --- a/config/campaignOverrides.json +++ b/config/campaignOverrides.json @@ -1,8 +1,11 @@ { + "DATA/GOOD1" : { // RoE - "Long Live the Queen" + "introVideo": "H3INTRO" + }, "DATA/GOOD3" : { // RoE - "Song for the Father" "outroVideo": "Endgame" }, - "DATA/AB" : { // AB Intro + "DATA/AB" : { // AB - "Armageddon's Blade" "introVideo": "H3X1intr", "videoRim": "IntroRm2" }, From 7e1eddf530d2c57f56bdff12f1542213b23eff10 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Mon, 9 Sep 2024 23:08:57 +0200 Subject: [PATCH 5/5] Revert "roe video in line as ab" This reverts commit f1de265568d33c0b4b102bc506b355481ff61e96. --- clientapp/EntryPoint.cpp | 2 ++ config/campaignOverrides.json | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clientapp/EntryPoint.cpp b/clientapp/EntryPoint.cpp index 3ba0ff27c..e32303f07 100644 --- a/clientapp/EntryPoint.cpp +++ b/clientapp/EntryPoint.cpp @@ -410,6 +410,8 @@ void playIntro() if (!CCS->videoh->playIntroVideo(VideoPath::builtin("NWCLOGO.SMK"))) return; + + CCS->videoh->playIntroVideo(VideoPath::builtin("H3INTRO.SMK")); } static void mainLoop() diff --git a/config/campaignOverrides.json b/config/campaignOverrides.json index ce667ba85..28bbbfca6 100644 --- a/config/campaignOverrides.json +++ b/config/campaignOverrides.json @@ -1,11 +1,8 @@ { - "DATA/GOOD1" : { // RoE - "Long Live the Queen" - "introVideo": "H3INTRO" - }, "DATA/GOOD3" : { // RoE - "Song for the Father" "outroVideo": "Endgame" }, - "DATA/AB" : { // AB - "Armageddon's Blade" + "DATA/AB" : { // AB Intro "introVideo": "H3X1intr", "videoRim": "IntroRm2" },