Просмотр исходного кода

Integrated CClientState into GameEngine class

Ivan Savenko 9 месяцев назад
Родитель
Сommit
f657e85305
51 измененных файлов с 240 добавлено и 275 удалено
  1. 0 1
      client/CGameInfo.cpp
  2. 0 12
      client/CGameInfo.h
  3. 12 12
      client/CPlayerInterface.cpp
  4. 2 2
      client/CServerHandler.cpp
  5. 26 2
      client/GameEngine.cpp
  6. 14 4
      client/GameEngine.h
  7. 6 6
      client/HeroMovementController.cpp
  8. 3 3
      client/NetPacksLobbyClient.cpp
  9. 35 35
      client/adventureMap/AdventureMapInterface.cpp
  10. 4 4
      client/adventureMap/CInGameConsole.cpp
  11. 7 7
      client/adventureMap/CInfoBar.cpp
  12. 11 10
      client/adventureMap/MapAudioPlayer.cpp
  13. 1 1
      client/adventureMap/TurnTimerWidget.cpp
  14. 19 19
      client/battle/BattleActionsController.cpp
  15. 7 7
      client/battle/BattleAnimationClasses.cpp
  16. 2 1
      client/battle/BattleEffectsController.cpp
  17. 4 4
      client/battle/BattleFieldController.cpp
  18. 10 10
      client/battle/BattleInterface.cpp
  19. 2 2
      client/battle/BattleInterfaceClasses.cpp
  20. 1 1
      client/battle/BattleObstacleController.cpp
  21. 2 2
      client/battle/BattleSiegeController.cpp
  22. 1 1
      client/battle/BattleStacksController.cpp
  23. 4 4
      client/battle/BattleWindow.cpp
  24. 5 6
      client/eventsSDL/InputHandler.cpp
  25. 4 7
      client/eventsSDL/InputSourceGameController.cpp
  26. 3 4
      client/eventsSDL/InputSourceTouch.cpp
  27. 2 2
      client/globalLobby/GlobalLobbyClient.cpp
  28. 1 1
      client/globalLobby/GlobalLobbyWidget.cpp
  29. 1 1
      client/gui/WindowHandler.cpp
  30. 1 1
      client/lobby/CBonusSelection.cpp
  31. 1 1
      client/lobby/CSelectionBase.cpp
  32. 1 1
      client/lobby/OptionsTab.cpp
  33. 1 1
      client/mainmenu/CCampaignScreen.cpp
  34. 2 2
      client/mainmenu/CHighScoreScreen.cpp
  35. 3 3
      client/mainmenu/CMainMenu.cpp
  36. 9 9
      client/mainmenu/CPrologEpilogVideo.cpp
  37. 2 2
      client/mapView/MapViewActions.cpp
  38. 1 1
      client/media/CMusicHandler.cpp
  39. 1 4
      client/media/CSoundHandler.cpp
  40. 1 1
      client/renderSDL/ScreenHandler.cpp
  41. 2 2
      client/widgets/Buttons.cpp
  42. 8 8
      client/widgets/VideoWidget.cpp
  43. 2 2
      client/windows/CCastleInterface.cpp
  44. 1 1
      client/windows/CExchangeWindow.cpp
  45. 1 1
      client/windows/CPuzzleWindow.cpp
  46. 3 3
      client/windows/CWindowObject.cpp
  47. 4 4
      client/windows/CWindowWithArtifacts.cpp
  48. 2 2
      client/windows/InfoWindows.cpp
  49. 4 4
      client/windows/settings/GeneralOptionsTab.cpp
  50. 0 5
      clientapp/CMakeLists.txt
  51. 1 46
      clientapp/EntryPoint.cpp

+ 0 - 1
client/CGameInfo.cpp

@@ -13,7 +13,6 @@
 #include "../lib/VCMI_Lib.h"
 
 CGameInfo * CGI;
-CClientState * CCS = nullptr;
 CServerHandler * CSH;
 
 

+ 0 - 12
client/CGameInfo.h

@@ -41,18 +41,6 @@ class CursorHandler;
 class IVideoPlayer;
 class CServerHandler;
 
-//a class for non-mechanical client GUI classes
-class CClientState
-{
-public:
-	ISoundPlayer * soundh;
-	IMusicPlayer * musich;
-	CConsoleHandler * consoleh;
-	CursorHandler * curh;
-	IVideoPlayer * videoh;
-};
-extern CClientState * CCS;
-
 /// CGameInfo class
 /// for allowing different functions for accessing game information
 class CGameInfo final : public Services

+ 12 - 12
client/CPlayerInterface.cpp

@@ -166,7 +166,7 @@ void CPlayerInterface::initGameInterface(std::shared_ptr<Environment> ENV, std::
 	env = ENV;
 
 	pathfinderCache = std::make_unique<PathfinderCache>(cb.get(), PathfinderOptions(cb.get()));
-	CCS->musich->loadTerrainMusicThemes();
+	ENGINE->music().loadTerrainMusicThemes();
 	initializeHeroTownList();
 
 	adventureInt.reset(new AdventureMapInterface());
@@ -447,7 +447,7 @@ void CPlayerInterface::heroVisit(const CGHeroInstance * visitor, const CGObjectI
 	{
 		auto visitSound = visitedObj->getVisitSound(CRandomGenerator::getDefault());
 		if (visitSound)
-			CCS->soundh->playSound(visitSound.value());
+			ENGINE->sound().playSound(visitSound.value());
 	}
 }
 
@@ -457,7 +457,7 @@ void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
 	localState->addWanderingHero(hero);
 	adventureInt->onHeroChanged(hero);
 	if(castleInt)
-		CCS->soundh->playSound(soundBase::newBuilding);
+		ENGINE->sound().playSound(soundBase::newBuilding);
 }
 void CPlayerInterface::openTownWindow(const CGTownInstance * town)
 {
@@ -521,7 +521,7 @@ void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, PrimarySkill psk
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	waitWhileDialog();
-	CCS->soundh->playSound(soundBase::heroNewLevel);
+	ENGINE->sound().playSound(soundBase::heroNewLevel);
 	ENGINE->windows().createAndPushWindow<CLevelWindow>(hero, pskill, skills, [=](ui32 selection)
 	{
 		cb->selectionMade(selection, queryID);
@@ -532,7 +532,7 @@ void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander,
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	waitWhileDialog();
-	CCS->soundh->playSound(soundBase::heroNewLevel);
+	ENGINE->sound().playSound(soundBase::heroNewLevel);
 	ENGINE->windows().createAndPushWindow<CStackWindow>(commander, skills, [=](ui32 selection)
 	{
 		cb->selectionMade(selection, queryID);
@@ -1008,7 +1008,7 @@ void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &t
 		movementController->requestMovementAbort();
 
 		if (makingTurn && ENGINE->windows().count() > 0 && LOCPLINT == this)
-			CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
+			ENGINE->sound().playSound(static_cast<soundBase::soundID>(soundID));
 		return;
 	}
 
@@ -1050,7 +1050,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
 
 	if ((makingTurn || (battleInt && battleInt->curInt && battleInt->curInt.get() == this)) && ENGINE->windows().count() > 0 && LOCPLINT == this)
 	{
-		CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
+		ENGINE->sound().playSound(static_cast<soundBase::soundID>(soundID));
 		showingDialog->setBusy();
 		movementController->requestMovementAbort(); // interrupt movement to show dialog
 		ENGINE->windows().pushWindow(temp);
@@ -1084,7 +1084,7 @@ void CPlayerInterface::showBlockingDialog(const std::string &text, const std::ve
 	waitWhileDialog();
 
 	movementController->requestMovementAbort();
-	CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID));
+	ENGINE->sound().playSound(static_cast<soundBase::soundID>(soundID));
 
 	if (!selection && cancel) //simple yes/no dialog
 	{
@@ -1432,7 +1432,7 @@ void CPlayerInterface::centerView (int3 pos, int focusTime)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	waitWhileDialog();
-	CCS->curh->hide();
+	ENGINE->cursor().hide();
 	adventureInt->centerOnTile(pos);
 	if (focusTime)
 	{
@@ -1443,7 +1443,7 @@ void CPlayerInterface::centerView (int3 pos, int focusTime)
 			boost::this_thread::sleep_for(boost::chrono::milliseconds(focusTime));
 		}
 	}
-	CCS->curh->show();
+	ENGINE->cursor().show();
 }
 
 void CPlayerInterface::objectRemoved(const CGObjectInstance * obj, const PlayerColor & initiator)
@@ -1455,7 +1455,7 @@ void CPlayerInterface::objectRemoved(const CGObjectInstance * obj, const PlayerC
 		if (removalSound)
 		{
 			waitWhileDialog();
-			CCS->soundh->playSound(removalSound.value());
+			ENGINE->sound().playSound(removalSound.value());
 		}
 	}
 	CGI->mh->waitForOngoingAnimations();
@@ -1632,7 +1632,7 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, SpellID sp
 
 	auto castSoundPath = spellID.toSpell()->getCastSound();
 	if(!castSoundPath.empty())
-		CCS->soundh->playSound(castSoundPath);
+		ENGINE->sound().playSound(castSoundPath);
 }
 
 void CPlayerInterface::tryDigging(const CGHeroInstance * h)

+ 2 - 2
client/CServerHandler.cpp

@@ -721,9 +721,9 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared
 		else
 		{
 			CMM->openCampaignScreen(ourCampaign->campaignSet);
-			if(!ourCampaign->getOutroVideo().empty() && CCS->videoh->open(ourCampaign->getOutroVideo(), 1))
+			if(!ourCampaign->getOutroVideo().empty() && ENGINE->video().open(ourCampaign->getOutroVideo(), 1))
 			{
-				CCS->musich->stopMusic();
+				ENGINE->music().stopMusic();
 				ENGINE->windows().createAndPushWindow<VideoWindow>(ourCampaign->getOutroVideo(), ourCampaign->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : ourCampaign->getVideoRim(), false, 1, [campaignScoreCalculator, statistic](bool skipped){
 					ENGINE->windows().createAndPushWindow<CHighScoreInputScreen>(true, *campaignScoreCalculator, statistic);
 				});

+ 26 - 2
client/GameEngine.cpp

@@ -18,6 +18,11 @@
 #include "gui/EventDispatcher.h"
 #include "eventsSDL/InputHandler.h"
 
+#include "media/CMusicHandler.h"
+#include "media/CSoundHandler.h"
+#include "media/CVideoHandler.h"
+#include "media/CEmptyVideoPlayer.h"
+
 #include "CGameInfo.h"
 #include "CPlayerInterface.h"
 #include "adventureMap/AdventureMapInterface.h"
@@ -64,6 +69,25 @@ void GameEngine::init()
 	shortcutsHandlerInstance = std::make_unique<ShortcutHandler>();
 	inputHandlerInstance = std::make_unique<InputHandler>(); // Must be after windowHandlerInstance and shortcutsHandlerInstance
 	framerateManagerInstance = std::make_unique<FramerateManager>(settings["video"]["targetfps"].Integer());
+
+#ifndef ENABLE_VIDEO
+	videoPlayerInstance = std::make_unique<CEmptyVideoPlayer>();
+#else
+	if (!settings["session"]["headless"].Bool())
+		videoPlayerInstance = std::make_unique<CVideoPlayer>();
+	else
+		videoPlayerInstance = std::make_unique<CEmptyVideoPlayer>();
+#endif
+
+	if(!settings["session"]["headless"].Bool())
+	{
+		soundPlayerInstance = std::make_unique<CSoundHandler>();
+		musicPlayerInstance = std::make_unique<CMusicHandler>();
+		sound().setVolume((ui32)settings["general"]["sound"].Float());
+		music().setVolume((ui32)settings["general"]["music"].Float());
+	}
+
+	cursorHandlerInstance = std::make_unique<CursorHandler>();
 }
 
 void GameEngine::handleEvents()
@@ -98,7 +122,7 @@ void GameEngine::renderFrame()
 		screenHandlerInstance->updateScreenTexture();
 
 		windows().onFrameRendered();
-		CCS->curh->update();
+		ENGINE->cursor().update();
 	}
 
 	screenHandlerInstance->presentScreenTexture();
@@ -229,5 +253,5 @@ void GameEngine::onScreenResize(bool resolutionChanged)
 		screenHandler().onScreenResize();
 
 	windows().onScreenResize();
-	CCS->curh->onScreenResize();
+	ENGINE->cursor().onScreenResize();
 }

+ 14 - 4
client/GameEngine.h

@@ -26,8 +26,11 @@ class IScreenHandler;
 class WindowHandler;
 class EventDispatcher;
 class InputHandler;
+class ISoundPlayer;
+class IMusicPlayer;
+class CursorHandler;
+class IVideoPlayer;
 
-// Handles GUI logic and drawing
 class GameEngine
 {
 private:
@@ -46,6 +49,11 @@ private:
 	std::unique_ptr<EventDispatcher> eventDispatcherInstance;
 	std::unique_ptr<InputHandler> inputHandlerInstance;
 
+	std::unique_ptr<ISoundPlayer> soundPlayerInstance;
+	std::unique_ptr<IMusicPlayer> musicPlayerInstance;
+	std::unique_ptr<CursorHandler> cursorHandlerInstance;
+	std::unique_ptr<IVideoPlayer> videoPlayerInstance;
+
 public:
 	boost::mutex interfaceMutex;
 
@@ -57,6 +65,11 @@ public:
 	EventDispatcher & events();
 	InputHandler & input();
 
+	ISoundPlayer & sound() { return *soundPlayerInstance; }
+	IMusicPlayer & music() { return *musicPlayerInstance; }
+	CursorHandler & cursor() { return *cursorHandlerInstance; }
+	IVideoPlayer & video() { return *videoPlayerInstance; }
+
 	/// Returns current logical screen dimensions
 	/// May not match size of window if user has UI scaling different from 100%
 	Point screenDimensions() const;
@@ -74,9 +87,6 @@ public:
 	/// returns true if Shift is currently pressed down
 	bool isKeyboardShiftDown() const;
 
-	void startTextInput(const Rect & where);
-	void stopTextInput();
-
 	IScreenHandler & screenHandler();
 	IRenderHandler & renderHandler();
 	WindowHandler & windows();

+ 6 - 6
client/HeroMovementController.cpp

@@ -158,7 +158,7 @@ void HeroMovementController::onTryMoveHero(const CGHeroInstance * hero, const Tr
 		{
 			auto removalSound = hero->getRemovalSound(CRandomGenerator::getDefault());
 			if (removalSound)
-				CCS->soundh->playSound(removalSound.value());
+				ENGINE->sound().playSound(removalSound.value());
 		}
 	}
 
@@ -270,7 +270,7 @@ void HeroMovementController::endMove(const CGHeroInstance * hero)
 	currentlyMovingHero = nullptr;
 	stopMovementSound();
 	adventureInt->onHeroChanged(hero);
-	CCS->curh->show();
+	ENGINE->cursor().show();
 }
 
 AudioPath HeroMovementController::getMovementSoundFor(const CGHeroInstance * hero, int3 posPrev, int3 posNext, EPathNodeAction moveType)
@@ -309,10 +309,10 @@ void HeroMovementController::updateMovementSound(const CGHeroInstance * h, int3
 		currentMovementSoundName = newSoundName;
 
 		if(currentMovementSoundChannel != -1)
-			CCS->soundh->stopSound(currentMovementSoundChannel);
+			ENGINE->sound().stopSound(currentMovementSoundChannel);
 
 		if(!currentMovementSoundName.empty())
-			currentMovementSoundChannel = CCS->soundh->playSound(currentMovementSoundName, -1, true);
+			currentMovementSoundChannel = ENGINE->sound().playSound(currentMovementSoundName, -1, true);
 		else
 			currentMovementSoundChannel = -1;
 	}
@@ -321,7 +321,7 @@ void HeroMovementController::updateMovementSound(const CGHeroInstance * h, int3
 void HeroMovementController::stopMovementSound()
 {
 	if(currentMovementSoundChannel != -1)
-		CCS->soundh->stopSound(currentMovementSoundChannel);
+		ENGINE->sound().stopSound(currentMovementSoundChannel);
 	currentMovementSoundChannel = -1;
 	currentMovementSoundName = AudioPath();
 }
@@ -344,7 +344,7 @@ void HeroMovementController::requestMovementStart(const CGHeroInstance * h, cons
 	duringMovement = true;
 	currentlyMovingHero = h;
 
-	CCS->curh->hide();
+	ENGINE->cursor().hide();
 	sendMovementRequest(h, path);
 }
 

+ 3 - 3
client/NetPacksLobbyClient.cpp

@@ -209,12 +209,12 @@ void ApplyOnLobbyScreenNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState &
 	{
 		auto bonusSel = std::make_shared<CBonusSelection>();
 		lobby->bonusSel = bonusSel;
-		if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty() && CCS->videoh->open(handler.si->campState->getIntroVideo(), 1))
+		if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty() && ENGINE->video().open(handler.si->campState->getIntroVideo(), 1))
 		{
-			CCS->musich->stopMusic();
+			ENGINE->music().stopMusic();
 			ENGINE->windows().createAndPushWindow<VideoWindow>(handler.si->campState->getIntroVideo(), handler.si->campState->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : handler.si->campState->getVideoRim(), false, 1, [bonusSel](bool skipped){
 				if(!CSH->si->campState->getMusic().empty())
-					CCS->musich->playMusic(CSH->si->campState->getMusic(), true, false);
+					ENGINE->music().playMusic(CSH->si->campState->getMusic(), true, false);
 				ENGINE->windows().pushWindow(bonusSel);
 			});
 		}

+ 35 - 35
client/adventureMap/AdventureMapInterface.cpp

@@ -149,7 +149,7 @@ void AdventureMapInterface::activate()
 void AdventureMapInterface::deactivate()
 {
 	CIntObject::deactivate();
-	CCS->curh->set(Cursor::Map::POINTER);
+	ENGINE->cursor().set(Cursor::Map::POINTER);
 
 	if(LOCPLINT)
 		LOCPLINT->cingconsole->deactivate();
@@ -254,30 +254,30 @@ void AdventureMapInterface::handleMapScrollingUpdate(uint32_t timePassed)
 	if(scrollDelta.x > 0)
 	{
 		if(scrollDelta.y < 0)
-			CCS->curh->set(Cursor::Map::SCROLL_NORTHEAST);
+			ENGINE->cursor().set(Cursor::Map::SCROLL_NORTHEAST);
 		if(scrollDelta.y > 0)
-			CCS->curh->set(Cursor::Map::SCROLL_SOUTHEAST);
+			ENGINE->cursor().set(Cursor::Map::SCROLL_SOUTHEAST);
 		if(scrollDelta.y == 0)
-			CCS->curh->set(Cursor::Map::SCROLL_EAST);
+			ENGINE->cursor().set(Cursor::Map::SCROLL_EAST);
 	}
 	if(scrollDelta.x < 0)
 	{
 		if(scrollDelta.y < 0)
-			CCS->curh->set(Cursor::Map::SCROLL_NORTHWEST);
+			ENGINE->cursor().set(Cursor::Map::SCROLL_NORTHWEST);
 		if(scrollDelta.y > 0)
-			CCS->curh->set(Cursor::Map::SCROLL_SOUTHWEST);
+			ENGINE->cursor().set(Cursor::Map::SCROLL_SOUTHWEST);
 		if(scrollDelta.y == 0)
-			CCS->curh->set(Cursor::Map::SCROLL_WEST);
+			ENGINE->cursor().set(Cursor::Map::SCROLL_WEST);
 	}
 
 	if (scrollDelta.x == 0)
 	{
 		if(scrollDelta.y < 0)
-			CCS->curh->set(Cursor::Map::SCROLL_NORTH);
+			ENGINE->cursor().set(Cursor::Map::SCROLL_NORTH);
 		if(scrollDelta.y > 0)
-			CCS->curh->set(Cursor::Map::SCROLL_SOUTH);
+			ENGINE->cursor().set(Cursor::Map::SCROLL_SOUTH);
 		if(scrollDelta.y == 0)
-			CCS->curh->set(Cursor::Map::POINTER);
+			ENGINE->cursor().set(Cursor::Map::POINTER);
 	}
 
 	scrollingWasActive = scrollingActive;
@@ -610,32 +610,32 @@ void AdventureMapInterface::onTileHovered(const int3 &targetPosition)
 		{
 		case SpellID::SCUTTLE_BOAT:
 			if(isValidAdventureSpellTarget(targetPosition))
-				CCS->curh->set(Cursor::Map::SCUTTLE_BOAT);
+				ENGINE->cursor().set(Cursor::Map::SCUTTLE_BOAT);
 			else
-				CCS->curh->set(Cursor::Map::POINTER);
+				ENGINE->cursor().set(Cursor::Map::POINTER);
 			return;
 
 		case SpellID::DIMENSION_DOOR:
 			if(isValidAdventureSpellTarget(targetPosition))
 			{
 				if(LOCPLINT->cb->getSettings().getBoolean(EGameSettings::DIMENSION_DOOR_TRIGGERS_GUARDS) && LOCPLINT->cb->isTileGuardedUnchecked(targetPosition))
-					CCS->curh->set(Cursor::Map::T1_ATTACK);
+					ENGINE->cursor().set(Cursor::Map::T1_ATTACK);
 				else
-					CCS->curh->set(Cursor::Map::TELEPORT);
+					ENGINE->cursor().set(Cursor::Map::TELEPORT);
 				return;
 			}
 			else
-				CCS->curh->set(Cursor::Map::POINTER);
+				ENGINE->cursor().set(Cursor::Map::POINTER);
 			return;
 		default:
-			CCS->curh->set(Cursor::Map::POINTER);
+			ENGINE->cursor().set(Cursor::Map::POINTER);
 			return;
 		}
 	}
 
 	if(!isTargetPositionVisible)
 	{
-		CCS->curh->set(Cursor::Map::POINTER);
+		ENGINE->cursor().set(Cursor::Map::POINTER);
 		return;
 	}
 
@@ -663,14 +663,14 @@ void AdventureMapInterface::onTileHovered(const int3 &targetPosition)
 		if(objAtTile)
 		{
 			if(objAtTile->ID == Obj::TOWN && objRelations != PlayerRelations::ENEMIES)
-				CCS->curh->set(Cursor::Map::TOWN);
+				ENGINE->cursor().set(Cursor::Map::TOWN);
 			else if(objAtTile->ID == Obj::HERO && objRelations == PlayerRelations::SAME_PLAYER)
-				CCS->curh->set(Cursor::Map::HERO);
+				ENGINE->cursor().set(Cursor::Map::HERO);
 			else
-				CCS->curh->set(Cursor::Map::POINTER);
+				ENGINE->cursor().set(Cursor::Map::POINTER);
 		}
 		else
-			CCS->curh->set(Cursor::Map::POINTER);
+			ENGINE->cursor().set(Cursor::Map::POINTER);
 	}
 	else if(const CGHeroInstance * hero = LOCPLINT->localState->getCurrentHero())
 	{
@@ -694,17 +694,17 @@ void AdventureMapInterface::onTileHovered(const int3 &targetPosition)
 		{
 			if(objAtTile->ID == Obj::TOWN && objRelations != PlayerRelations::ENEMIES)
 			{
-				CCS->curh->set(Cursor::Map::TOWN);
+				ENGINE-> cursor().set(Cursor::Map::TOWN);
 				return;
 			}
 			else if(objAtTile->ID == Obj::HERO && objRelations == PlayerRelations::SAME_PLAYER)
 			{
-				CCS->curh->set(Cursor::Map::HERO);
+				ENGINE-> cursor().set(Cursor::Map::HERO);
 				return;
 			}
 			else if (objAtTile->ID == Obj::SHIPYARD && objRelations != PlayerRelations::ENEMIES)
 			{
-				CCS->curh->set(Cursor::Map::T1_SAIL);
+				ENGINE-> cursor().set(Cursor::Map::T1_SAIL);
 				return;
 			}
 
@@ -719,9 +719,9 @@ void AdventureMapInterface::onTileHovered(const int3 &targetPosition)
 		case EPathNodeAction::NORMAL:
 		case EPathNodeAction::TELEPORT_NORMAL:
 			if(pathNode->layer == EPathfindingLayer::LAND)
-				CCS->curh->set(cursorMove[turns]);
+				ENGINE->cursor().set(cursorMove[turns]);
 			else
-				CCS->curh->set(cursorSail[turns]);
+				ENGINE->cursor().set(cursorSail[turns]);
 			break;
 
 		case EPathNodeAction::VISIT:
@@ -730,12 +730,12 @@ void AdventureMapInterface::onTileHovered(const int3 &targetPosition)
 			if(objAtTile && objAtTile->ID == Obj::HERO)
 			{
 				if(LOCPLINT->localState->getCurrentArmy()  == objAtTile)
-					CCS->curh->set(Cursor::Map::HERO);
+					ENGINE->cursor().set(Cursor::Map::HERO);
 				else
-					CCS->curh->set(cursorExchange[turns]);
+					ENGINE->cursor().set(cursorExchange[turns]);
 			}
 			else if(pathNode->layer == EPathfindingLayer::LAND)
-				CCS->curh->set(cursorVisit[turns]);
+				ENGINE->cursor().set(cursorVisit[turns]);
 			else if (pathNode->layer == EPathfindingLayer::SAIL &&
 					 objAtTile &&
 					 objAtTile->isCoastVisitable() &&
@@ -743,27 +743,27 @@ void AdventureMapInterface::onTileHovered(const int3 &targetPosition)
 					 pathNode->theNodeBefore->layer == EPathfindingLayer::LAND )
 			{
 				// exception - when visiting shipwreck located on coast from land - show 'horse' cursor, not 'ship' cursor
-				CCS->curh->set(cursorVisit[turns]);
+				ENGINE->cursor().set(cursorVisit[turns]);
 			}
 			else
-				CCS->curh->set(cursorSailVisit[turns]);
+				ENGINE->cursor().set(cursorSailVisit[turns]);
 			break;
 
 		case EPathNodeAction::BATTLE:
 		case EPathNodeAction::TELEPORT_BATTLE:
-			CCS->curh->set(cursorAttack[turns]);
+			ENGINE->cursor().set(cursorAttack[turns]);
 			break;
 
 		case EPathNodeAction::EMBARK:
-			CCS->curh->set(cursorSail[turns]);
+			ENGINE->cursor().set(cursorSail[turns]);
 			break;
 
 		case EPathNodeAction::DISEMBARK:
-			CCS->curh->set(cursorDisembark[turns]);
+			ENGINE->cursor().set(cursorDisembark[turns]);
 			break;
 
 		default:
-				CCS->curh->set(Cursor::Map::POINTER);
+				ENGINE->cursor().set(Cursor::Map::POINTER);
 			break;
 		}
 	}

+ 4 - 4
client/adventureMap/CInGameConsole.cpp

@@ -113,12 +113,12 @@ void CInGameConsole::addMessage(const std::string & timeFormatted, const std::st
 
 	ENGINE->windows().totalRedraw(); // FIXME: ingame console has no parent widget set
 
-	int volume = CCS->soundh->getVolume();
+	int volume = ENGINE->sound().getVolume();
 	if(volume == 0)
-		CCS->soundh->setVolume(settings["general"]["sound"].Integer());
-	int handle = CCS->soundh->playSound(AudioPath::builtin("CHAT"));
+		ENGINE->sound().setVolume(settings["general"]["sound"].Integer());
+	int handle = ENGINE->sound().playSound(AudioPath::builtin("CHAT"));
 	if(volume == 0)
-		CCS->soundh->setCallback(handle, [&]() { if(!ENGINE->screenHandler().hasFocus()) CCS->soundh->setVolume(0); });
+		ENGINE->sound().setCallback(handle, [&]() { if(!ENGINE->screenHandler().hasFocus()) ENGINE->sound().setVolume(0); });
 }
 
 bool CInGameConsole::captureThisKey(EShortcut key)

+ 7 - 7
client/adventureMap/CInfoBar.cpp

@@ -230,22 +230,22 @@ CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component
 
 void CInfoBar::playNewDaySound()
 {
-	int volume = CCS->soundh->getVolume();
+	int volume = ENGINE->sound().getVolume();
 	int handle = -1;
 	if(volume == 0)
-		CCS->soundh->setVolume(settings["general"]["sound"].Integer());
+		ENGINE->sound().setVolume(settings["general"]["sound"].Integer());
 
 	if(LOCPLINT->cb->getDate(Date::DAY_OF_WEEK) != 1) // not first day of the week
-		handle = CCS->soundh->playSound(soundBase::newDay);
+		handle = ENGINE->sound().playSound(soundBase::newDay);
 	else if(LOCPLINT->cb->getDate(Date::WEEK) != 1) // not first week in month
-		handle = CCS->soundh->playSound(soundBase::newWeek);
+		handle = ENGINE->sound().playSound(soundBase::newWeek);
 	else if(LOCPLINT->cb->getDate(Date::MONTH) != 1) // not first month
-		handle = CCS->soundh->playSound(soundBase::newMonth);
+		handle = ENGINE->sound().playSound(soundBase::newMonth);
 	else
-		handle = CCS->soundh->playSound(soundBase::newDay);
+		handle = ENGINE->sound().playSound(soundBase::newDay);
 
 	if(volume == 0)
-		CCS->soundh->setCallback(handle, [&]() { if(!ENGINE->screenHandler().hasFocus()) CCS->soundh->setVolume(0); });
+		ENGINE->sound().setCallback(handle, [&]() { if(!ENGINE->screenHandler().hasFocus()) ENGINE->sound().setVolume(0); });
 }
 
 void CInfoBar::reset()

+ 11 - 10
client/adventureMap/MapAudioPlayer.cpp

@@ -13,6 +13,7 @@
 #include "../CCallback.h"
 #include "../CGameInfo.h"
 #include "../CPlayerInterface.h"
+#include "../GameEngine.h"
 #include "../mapView/mapHandler.h"
 #include "../media/IMusicPlayer.h"
 #include "../media/ISoundPlayer.h"
@@ -164,7 +165,7 @@ void MapAudioPlayer::updateAmbientSounds()
 
 	int3 pos = currentSelection->getSightCenter();
 	std::unordered_set<int3> tiles;
-	LOCPLINT->cb->getVisibleTilesInRange(tiles, pos, CCS->soundh->ambientGetRange(), int3::DIST_CHEBYSHEV);
+	LOCPLINT->cb->getVisibleTilesInRange(tiles, pos, ENGINE->sound().ambientGetRange(), int3::DIST_CHEBYSHEV);
 	for(int3 tile : tiles)
 	{
 		int dist = pos.dist(tile, int3::DIST_CHEBYSHEV);
@@ -172,7 +173,7 @@ void MapAudioPlayer::updateAmbientSounds()
 		for(auto & soundName : getAmbientSounds(tile))
 			updateSounds(soundName, dist);
 	}
-	CCS->soundh->ambientUpdateChannels(currentSounds);
+	ENGINE->sound().ambientUpdateChannels(currentSounds);
 }
 
 void MapAudioPlayer::updateMusic()
@@ -182,12 +183,12 @@ void MapAudioPlayer::updateMusic()
 		const auto * tile = LOCPLINT->cb->getTile(currentSelection->visitablePos());
 
 		if (tile)
-			CCS->musich->playMusicFromSet("terrain", tile->getTerrain()->getJsonKey(), true, false);
+			ENGINE->music().playMusicFromSet("terrain", tile->getTerrain()->getJsonKey(), true, false);
 	}
 
 	if(audioPlaying && enemyMakingTurn)
 	{
-		CCS->musich->playMusicFromSet("enemy-turn", true, false);
+		ENGINE->music().playMusicFromSet("enemy-turn", true, false);
 	}
 }
 
@@ -214,8 +215,8 @@ MapAudioPlayer::MapAudioPlayer()
 
 MapAudioPlayer::~MapAudioPlayer()
 {
-	CCS->soundh->ambientStopAllChannels();
-	CCS->musich->stopMusic(1000);
+	ENGINE->sound().ambientStopAllChannels();
+	ENGINE->music().stopMusic(1000);
 }
 
 void MapAudioPlayer::onSelectionChanged(const CArmedInstance * newSelection)
@@ -227,8 +228,8 @@ void MapAudioPlayer::onSelectionChanged(const CArmedInstance * newSelection)
 void MapAudioPlayer::onAudioPaused()
 {
 	audioPlaying = false;
-	CCS->soundh->ambientStopAllChannels();
-	CCS->musich->stopMusic(1000);
+	ENGINE->sound().ambientStopAllChannels();
+	ENGINE->music().stopMusic(1000);
 }
 
 void MapAudioPlayer::onAudioResumed()
@@ -255,6 +256,6 @@ void MapAudioPlayer::onPlayerTurnEnded()
 {
 	playerMakingTurn = false;
 	enemyMakingTurn = false;
-	CCS->soundh->ambientStopAllChannels();
-	CCS->musich->stopMusic(1000);
+	ENGINE->sound().ambientStopAllChannels();
+	ENGINE->music().stopMusic(1000);
 }

+ 1 - 1
client/adventureMap/TurnTimerWidget.cpp

@@ -110,7 +110,7 @@ void TurnTimerWidget::updateNotifications(PlayerColor player, int timeMs)
 	int newTimeSeconds = timeMs / 1000;
 
 	if (newTimeSeconds != lastSoundCheckSeconds && notificationThresholds.count(newTimeSeconds))
-		CCS->soundh->playSound(AudioPath::builtin("WE5"));
+		ENGINE->sound().playSound(AudioPath::builtin("WE5"));
 
 	lastSoundCheckSeconds = newTimeSeconds;
 }

+ 19 - 19
client/battle/BattleActionsController.cpp

@@ -213,7 +213,7 @@ void BattleActionsController::enterCreatureCastingMode()
 			owner.giveCommand(EActionType::MONSTER_SPELL, BattleHex::INVALID, spell->getId());
 			selectedStack = nullptr;
 
-			CCS->curh->set(Cursor::Combat::POINTER);
+			ENGINE->cursor().set(Cursor::Combat::POINTER);
 		}
 		return;
 	}
@@ -403,15 +403,15 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
 	switch (action.get())
 	{
 		case PossiblePlayerBattleAction::CHOOSE_TACTICS_STACK:
-			CCS->curh->set(Cursor::Combat::POINTER);
+			ENGINE->cursor().set(Cursor::Combat::POINTER);
 			return;
 
 		case PossiblePlayerBattleAction::MOVE_TACTICS:
 		case PossiblePlayerBattleAction::MOVE_STACK:
 			if (owner.stacksController->getActiveStack()->hasBonusOfType(BonusType::FLYING))
-				CCS->curh->set(Cursor::Combat::FLY);
+				ENGINE->cursor().set(Cursor::Combat::FLY);
 			else
-				CCS->curh->set(Cursor::Combat::MOVE);
+				ENGINE->cursor().set(Cursor::Combat::MOVE);
 			return;
 
 		case PossiblePlayerBattleAction::ATTACK:
@@ -433,16 +433,16 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
 
 			assert(sectorCursor.count(direction) > 0);
 			if (sectorCursor.count(direction))
-				CCS->curh->set(sectorCursor.at(direction));
+				ENGINE->cursor().set(sectorCursor.at(direction));
 
 			return;
 		}
 
 		case PossiblePlayerBattleAction::SHOOT:
 			if (owner.getBattle()->battleHasShootingPenalty(owner.stacksController->getActiveStack(), targetHex))
-				CCS->curh->set(Cursor::Combat::SHOOT_PENALTY);
+				ENGINE->cursor().set(Cursor::Combat::SHOOT_PENALTY);
 			else
-				CCS->curh->set(Cursor::Combat::SHOOT);
+				ENGINE->cursor().set(Cursor::Combat::SHOOT);
 			return;
 
 		case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
@@ -450,30 +450,30 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
 		case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
 		case PossiblePlayerBattleAction::FREE_LOCATION:
 		case PossiblePlayerBattleAction::OBSTACLE:
-			CCS->curh->set(Cursor::Spellcast::SPELL);
+			ENGINE->cursor().set(Cursor::Spellcast::SPELL);
 			return;
 
 		case PossiblePlayerBattleAction::TELEPORT:
-			CCS->curh->set(Cursor::Combat::TELEPORT);
+			ENGINE->cursor().set(Cursor::Combat::TELEPORT);
 			return;
 
 		case PossiblePlayerBattleAction::SACRIFICE:
-			CCS->curh->set(Cursor::Combat::SACRIFICE);
+			ENGINE->cursor().set(Cursor::Combat::SACRIFICE);
 			return;
 
 		case PossiblePlayerBattleAction::HEAL:
-			CCS->curh->set(Cursor::Combat::HEAL);
+			ENGINE->cursor().set(Cursor::Combat::HEAL);
 			return;
 
 		case PossiblePlayerBattleAction::CATAPULT:
-			CCS->curh->set(Cursor::Combat::SHOOT_CATAPULT);
+			ENGINE->cursor().set(Cursor::Combat::SHOOT_CATAPULT);
 			return;
 
 		case PossiblePlayerBattleAction::CREATURE_INFO:
-			CCS->curh->set(Cursor::Combat::QUERY);
+			ENGINE->cursor().set(Cursor::Combat::QUERY);
 			return;
 		case PossiblePlayerBattleAction::HERO_INFO:
-			CCS->curh->set(Cursor::Combat::HERO);
+			ENGINE->cursor().set(Cursor::Combat::HERO);
 			return;
 	}
 	assert(0);
@@ -488,13 +488,13 @@ void BattleActionsController::actionSetCursorBlocked(PossiblePlayerBattleAction
 		case PossiblePlayerBattleAction::TELEPORT:
 		case PossiblePlayerBattleAction::SACRIFICE:
 		case PossiblePlayerBattleAction::FREE_LOCATION:
-			CCS->curh->set(Cursor::Combat::BLOCKED);
+			ENGINE->cursor().set(Cursor::Combat::BLOCKED);
 			return;
 		default:
 			if (targetHex == -1)
-				CCS->curh->set(Cursor::Combat::POINTER);
+				ENGINE->cursor().set(Cursor::Combat::POINTER);
 			else
-				CCS->curh->set(Cursor::Combat::BLOCKED);
+				ENGINE->cursor().set(Cursor::Combat::BLOCKED);
 			return;
 	}
 	assert(0);
@@ -888,7 +888,7 @@ void BattleActionsController::onHexHovered(const BattleHex & hoveredHex)
 			ENGINE->statusbar()->clearIfMatching(currentConsoleMsg);
 
 		currentConsoleMsg.clear();
-		CCS->curh->set(Cursor::Combat::BLOCKED);
+		ENGINE->cursor().set(Cursor::Combat::BLOCKED);
 		return;
 	}
 
@@ -918,7 +918,7 @@ void BattleActionsController::onHexHovered(const BattleHex & hoveredHex)
 
 void BattleActionsController::onHoverEnded()
 {
-	CCS->curh->set(Cursor::Combat::POINTER);
+	ENGINE->cursor().set(Cursor::Combat::POINTER);
 
 	if (!currentConsoleMsg.empty())
 		ENGINE->statusbar()->clearIfMatching(currentConsoleMsg);

+ 7 - 7
client/battle/BattleAnimationClasses.cpp

@@ -124,7 +124,7 @@ void StackActionAnimation::setSound( const AudioPath & sound )
 bool StackActionAnimation::init()
 {
 	if (!sound.empty())
-		CCS->soundh->playSound(sound);
+		ENGINE->sound().playSound(sound);
 
 	if (myAnim->framesInGroup(currGroup) > 0)
 	{
@@ -358,7 +358,7 @@ bool MovementAnimation::init()
 
 	if (moveSoundHandler == -1)
 	{
-		moveSoundHandler = CCS->soundh->playSound(stack->unitType()->sounds.move, -1);
+		moveSoundHandler = ENGINE->sound().playSound(stack->unitType()->sounds.move, -1);
 	}
 
 	Point begPosition = owner.stacksController->getStackPositionAtHex(prevHex, stack);
@@ -419,7 +419,7 @@ MovementAnimation::~MovementAnimation()
 	assert(stack);
 
 	if(moveSoundHandler != -1)
-		CCS->soundh->stopSound(moveSoundHandler);
+		ENGINE->sound().stopSound(moveSoundHandler);
 }
 
 MovementAnimation::MovementAnimation(BattleInterface & owner, const CStack *stack, const BattleHexArray & _destTiles, int _distance)
@@ -455,7 +455,7 @@ bool MovementEndAnimation::init()
 	logAnim->debug("CMovementEndAnimation::init: stack %s", stack->getName());
 	myAnim->pos.moveTo(owner.stacksController->getStackPositionAtHex(nextHex, stack));
 
-	CCS->soundh->playSound(stack->unitType()->sounds.endMoving);
+	ENGINE->sound().playSound(stack->unitType()->sounds.endMoving);
 
 	if(!myAnim->framesInGroup(ECreatureAnimType::MOVE_END))
 	{
@@ -475,7 +475,7 @@ MovementEndAnimation::~MovementEndAnimation()
 	if(myAnim->getType() != ECreatureAnimType::DEAD)
 		myAnim->setType(ECreatureAnimType::HOLDING); //resetting to default
 
-	CCS->curh->show();
+	ENGINE->cursor().show();
 }
 
 MovementStartAnimation::MovementStartAnimation(BattleInterface & owner, const CStack * _stack)
@@ -496,7 +496,7 @@ bool MovementStartAnimation::init()
 	}
 
 	logAnim->debug("CMovementStartAnimation::init: stack %s", stack->getName());
-	CCS->soundh->playSound(stack->unitType()->sounds.startMoving);
+	ENGINE->sound().playSound(stack->unitType()->sounds.startMoving);
 
 	if(!myAnim->framesInGroup(ECreatureAnimType::MOVE_START))
 	{
@@ -816,7 +816,7 @@ void CatapultAnimation::tick(uint32_t msPassed)
 	auto soundFilename  = AudioPath::builtin((catapultDamage > 0) ? "WALLHIT" : "WALLMISS");
 	AnimationPath effectFilename = AnimationPath::builtin((catapultDamage > 0) ? "SGEXPL" : "CSGRCK");
 
-	CCS->soundh->playSound( soundFilename );
+	ENGINE->sound().playSound( soundFilename );
 	owner.stacksController->addNewAnim( new EffectAnimation(owner, effectFilename, shotTarget));
 }
 

+ 2 - 1
client/battle/BattleEffectsController.cpp

@@ -20,6 +20,7 @@
 
 #include "../CGameInfo.h"
 #include "../CPlayerInterface.h"
+#include "../GameEngine.h"
 #include "../media/ISoundPlayer.h"
 #include "../render/Canvas.h"
 #include "../render/CAnimation.h"
@@ -50,7 +51,7 @@ void BattleEffectsController::displayEffect(EBattleEffect effect, const AudioPat
 
 	AnimationPath customAnim = AnimationPath::builtinTODO(graphics->battleACToDef[effectID][0]);
 
-	CCS->soundh->playSound( soundFile );
+	ENGINE->sound().playSound( soundFile );
 
 	owner.stacksController->addNewAnim(new EffectAnimation(owner, customAnim, destTile, 0, transparencyFactor));
 }

+ 4 - 4
client/battle/BattleFieldController.cpp

@@ -857,19 +857,19 @@ void BattleFieldController::show(Canvas & to)
 
 	if (isActive() && isGesturing() && getHoveredHex() != BattleHex::INVALID)
 	{
-		auto combatCursorIndex = CCS->curh->get<Cursor::Combat>();
+		auto combatCursorIndex = ENGINE->cursor().get<Cursor::Combat>();
 		if (combatCursorIndex)
 		{
 			auto combatImageIndex = static_cast<size_t>(*combatCursorIndex);
-			to.draw(attackCursors->getImage(combatImageIndex), hexPositionAbsolute(getHoveredHex()).center() - CCS->curh->getPivotOffsetCombat(combatImageIndex));
+			to.draw(attackCursors->getImage(combatImageIndex), hexPositionAbsolute(getHoveredHex()).center() - ENGINE->cursor().getPivotOffsetCombat(combatImageIndex));
 			return;
 		}
 
-		auto spellCursorIndex = CCS->curh->get<Cursor::Spellcast>();
+		auto spellCursorIndex = ENGINE->cursor().get<Cursor::Spellcast>();
 		if (spellCursorIndex)
 		{
 			auto spellImageIndex = static_cast<size_t>(*spellCursorIndex);
-			to.draw(spellCursors->getImage(spellImageIndex), hexPositionAbsolute(getHoveredHex()).center() - CCS->curh->getPivotOffsetSpellcast());
+			to.draw(spellCursors->getImage(spellImageIndex), hexPositionAbsolute(getHoveredHex()).center() - ENGINE->cursor().getPivotOffsetSpellcast());
 			return;
 		}
 

+ 10 - 10
client/battle/BattleInterface.cpp

@@ -126,13 +126,13 @@ void BattleInterface::playIntroSoundAndUnlockInterface()
 	int battleIntroSoundChannel = -1;
 
 	if (!battlefieldSound.empty())
-		battleIntroSoundChannel = CCS->soundh->playSound(battlefieldSound);
+		battleIntroSoundChannel = ENGINE->sound().playSound(battlefieldSound);
 	else
-		battleIntroSoundChannel = CCS->soundh->playSoundFromSet(battleIntroSounds);
+		battleIntroSoundChannel = ENGINE->sound().playSoundFromSet(battleIntroSounds);
 
 	if (battleIntroSoundChannel != -1)
 	{
-		CCS->soundh->setCallback(battleIntroSoundChannel, onIntroPlayed);
+		ENGINE->sound().setCallback(battleIntroSoundChannel, onIntroPlayed);
 
 		if (settings["gameTweaks"]["skipBattleIntroMusic"].Bool())
 			openingEnd();
@@ -157,9 +157,9 @@ void BattleInterface::onIntroSoundPlayed()
 	const auto & battlefieldMusic = bfieldType.getInfo()->musicFilename;
 
 	if (!battlefieldMusic.empty())
-		CCS->musich->playMusic(battlefieldMusic, true, true);
+		ENGINE->music().playMusic(battlefieldMusic, true, true);
 	else
-		CCS->musich->playMusicFromSet("battle", true, true);
+		ENGINE->music().playMusicFromSet("battle", true, true);
 }
 
 void BattleInterface::openingEnd()
@@ -301,7 +301,7 @@ void BattleInterface::sendCommand(BattleAction command, const CStack * actor)
 		stacksController->setActiveStack(nullptr);
 		//next stack will be activated when action ends
 	}
-	CCS->curh->set(Cursor::Combat::POINTER);
+	ENGINE->cursor().set(Cursor::Combat::POINTER);
 }
 
 const CGHeroInstance * BattleInterface::getActiveHero()
@@ -337,7 +337,7 @@ void BattleInterface::battleFinished(const BattleResult& br, QueryID queryID)
 	checkForAnimations();
 	stacksController->setActiveStack(nullptr);
 
-	CCS->curh->set(Cursor::Map::POINTER);
+	ENGINE->cursor().set(Cursor::Map::POINTER);
 	curInt->waitWhileDialog();
 
 	if(settings["session"]["spectate"].Bool() && settings["session"]["spectate-skip-battle-result"].Bool())
@@ -371,7 +371,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
 		stacksController->deactivateStack();
 	}
 
-	CCS->curh->set(Cursor::Combat::BLOCKED);
+	ENGINE->cursor().set(Cursor::Combat::BLOCKED);
 
 	const SpellID spellID = sc->spellID;
 
@@ -390,7 +390,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
 					EAnimationEvents::BEFORE_HIT;//FIXME: recheck whether this should be on projectile spawning
 
 		addToAnimationStage(group, [=]() {
-			CCS->soundh->playSound(castSoundPath);
+			ENGINE->sound().playSound(castSoundPath);
 		});
 	}
 
@@ -447,7 +447,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
 	if (!sc->resistedCres.empty())
 	{
 		addToAnimationStage(EAnimationEvents::HIT, [=](){
-			CCS->soundh->playSound(AudioPath::builtin("MAGICRES"));
+			ENGINE->sound().playSound(AudioPath::builtin("MAGICRES"));
 		});
 	}
 

+ 2 - 2
client/battle/BattleInterfaceClasses.cpp

@@ -337,7 +337,7 @@ void BattleHero::heroLeftClicked()
 
 	if(owner.getBattle()->battleCanCastSpell(hero, spells::Mode::HERO) == ESpellCastProblem::OK) //check conditions
 	{
-		CCS->curh->set(Cursor::Map::POINTER);
+		ENGINE->cursor().set(Cursor::Map::POINTER);
 		ENGINE->windows().createAndPushWindow<CSpellWindow>(hero, owner.getCurrentPlayerInterface());
 	}
 }
@@ -843,7 +843,7 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface
 	description = std::make_shared<CTextBox>(resources.resultText.toString(), Rect(69, 203, 330, 68), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
 	videoPlayer = std::make_shared<VideoWidget>(Point(107, 70), resources.prologueVideo, resources.loopedVideo, false);
 
-	CCS->musich->playMusic(resources.musicName, false, true);
+	ENGINE->music().playMusic(resources.musicName, false, true);
 }
 
 BattleResultResources BattleResultWindow::getResources(const BattleResult & br)

+ 1 - 1
client/battle/BattleObstacleController.cpp

@@ -113,7 +113,7 @@ void BattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr<
 		//we assume here that effect graphics have the same size as the usual obstacle image
 		// -> if we know how to blit obstacle, let's blit the effect in the same place
 		Point whereTo = getObstaclePosition(first, *oi);
-		CCS->soundh->playSound( oi->getAppearSound() );
+		ENGINE->sound().playSound( oi->getAppearSound() );
 		owner.stacksController->addNewAnim(new EffectAnimation(owner, oi->getAppearAnimation(), whereTo, oi->pos));
 
 		//so when multiple obstacles are added, they show up one after another

+ 2 - 2
client/battle/BattleSiegeController.cpp

@@ -258,7 +258,7 @@ void BattleSiegeController::gateStateChanged(const EGateState state)
 		wallPieceImages[EWallVisual::GATE] = ENGINE->renderHandler().loadImage(getWallPieceImageName(EWallVisual::GATE,  stateId), EImageBlitMode::COLORKEY);
 
 	if (playSound)
-		CCS->soundh->playSound(soundBase::DRAWBRG);
+		ENGINE->sound().playSound(soundBase::DRAWBRG);
 }
 
 void BattleSiegeController::showAbsoluteObstacles(Canvas & canvas)
@@ -349,7 +349,7 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
 		for (auto attackInfo : ca.attackedParts)
 			positions.push_back(owner.stacksController->getStackPositionAtHex(attackInfo.destinationTile, nullptr) + Point(99, 120));
 
-		CCS->soundh->playSound( AudioPath::builtin("WALLHIT") );
+		ENGINE->sound().playSound( AudioPath::builtin("WALLHIT") );
 		owner.stacksController->addNewAnim(new EffectAnimation(owner, AnimationPath::builtin("SGEXPL.DEF"), positions));
 	}
 

+ 1 - 1
client/battle/BattleStacksController.cpp

@@ -472,7 +472,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
 			{
 				auto spell = attackedInfo.spellEffect.toSpell();
 				if (!spell->getCastSound().empty())
-					CCS->soundh->playSound(spell->getCastSound());
+					ENGINE->sound().playSound(spell->getCastSound());
 
 
 				owner.displaySpellEffect(spell, attackedInfo.defender->getPosition());

+ 4 - 4
client/battle/BattleWindow.cpp

@@ -541,7 +541,7 @@ void BattleWindow::bOptionsf()
 	if (owner.actionsController->heroSpellcastingModeActive())
 		return;
 
-	CCS->curh->set(Cursor::Map::POINTER);
+	ENGINE->cursor().set(Cursor::Map::POINTER);
 
 	ENGINE->windows().createAndPushWindow<SettingsMainWindow>(&owner);
 }
@@ -598,7 +598,7 @@ void BattleWindow::bFleef()
 void BattleWindow::reallyFlee()
 {
 	owner.giveCommand(EActionType::RETREAT);
-	CCS->curh->set(Cursor::Map::POINTER);
+	ENGINE->cursor().set(Cursor::Map::POINTER);
 }
 
 void BattleWindow::reallySurrender()
@@ -610,7 +610,7 @@ void BattleWindow::reallySurrender()
 	else
 	{
 		owner.giveCommand(EActionType::SURRENDER);
-		CCS->curh->set(Cursor::Map::POINTER);
+		ENGINE->cursor().set(Cursor::Map::POINTER);
 	}
 }
 
@@ -722,7 +722,7 @@ void BattleWindow::bSpellf()
 	if(!myHero)
 		return;
 
-	CCS->curh->set(Cursor::Map::POINTER);
+	ENGINE->cursor().set(Cursor::Map::POINTER);
 
 	ESpellCastProblem spellCastProblem = owner.getBattle()->battleCanCastSpell(myHero, spells::Mode::HERO);
 

+ 5 - 6
client/eventsSDL/InputHandler.cpp

@@ -248,8 +248,8 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
 			{
 				boost::mutex::scoped_lock interfaceLock(ENGINE->interfaceMutex);
 				if(settings["general"]["audioMuteFocus"].Bool()) {
-					CCS->musich->setVolume(settings["general"]["music"].Integer());
-					CCS->soundh->setVolume(settings["general"]["sound"].Integer());
+					ENGINE->music().setVolume(settings["general"]["music"].Integer());
+					ENGINE->sound().setVolume(settings["general"]["sound"].Integer());
 				}
 			}
 				break;
@@ -257,8 +257,8 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
 			{
 				boost::mutex::scoped_lock interfaceLock(ENGINE->interfaceMutex);
 				if(settings["general"]["audioMuteFocus"].Bool()) {
-					CCS->musich->setVolume(0);
-					CCS->soundh->setVolume(0);
+					ENGINE->music().setVolume(0);
+					ENGINE->sound().setVolume(0);
 				}
 			}
 				break;
@@ -293,8 +293,7 @@ void InputHandler::preprocessEvent(const SDL_Event & ev)
 	if(ev.type == SDL_MOUSEMOTION)
 	{
 		boost::mutex::scoped_lock interfaceLock(ENGINE->interfaceMutex);
-		if (CCS && CCS->curh)
-			CCS->curh->cursorMove(ev.motion.x, ev.motion.y);
+		ENGINE->cursor().cursorMove(ev.motion.x, ev.motion.y);
 	}
 
 	{

+ 4 - 7
client/eventsSDL/InputSourceGameController.cpp

@@ -195,14 +195,12 @@ void InputSourceGameController::handleEventAxisMotion(const SDL_ControllerAxisEv
 
 void InputSourceGameController::tryToConvertCursor()
 {
-	assert(CCS);
-	assert(CCS->curh);
-	if(CCS->curh->getShowType() == Cursor::ShowType::HARDWARE)
+	if(ENGINE->cursor().getShowType() == Cursor::ShowType::HARDWARE)
 	{
 		int scalingFactor = ENGINE->screenHandler().getScalingFactor();
 		const Point & cursorPosition = ENGINE->getCursorPosition();
-		CCS->curh->changeCursor(Cursor::ShowType::SOFTWARE);
-		CCS->curh->cursorMove(cursorPosition.x * scalingFactor, cursorPosition.y * scalingFactor);
+		ENGINE->cursor().changeCursor(Cursor::ShowType::SOFTWARE);
+		ENGINE->cursor().cursorMove(cursorPosition.x * scalingFactor, cursorPosition.y * scalingFactor);
 		ENGINE->input().setCursorPosition(cursorPosition);
 	}
 }
@@ -232,8 +230,7 @@ void InputSourceGameController::doCursorMove(int deltaX, int deltaY)
 	int newY = std::min(std::max(cursorPosition.y + deltaY, 0), screenSize.y);
 	Point targetPosition{newX, newY};
 	ENGINE->input().setCursorPosition(targetPosition);
-	if(CCS && CCS->curh)
-		CCS->curh->cursorMove(ENGINE->getCursorPosition().x * scalingFactor, ENGINE->getCursorPosition().y * scalingFactor);
+	ENGINE->cursor().cursorMove(ENGINE->getCursorPosition().x * scalingFactor, ENGINE->getCursorPosition().y * scalingFactor);
 }
 
 int InputSourceGameController::getMoveDis(float planDis)

+ 3 - 4
client/eventsSDL/InputSourceTouch.cpp

@@ -58,8 +58,8 @@ InputSourceTouch::InputSourceTouch()
 
 void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfinger)
 {
-	if (CCS && CCS->curh && settings["video"]["cursor"].String() == "software" && state != TouchState::RELATIVE_MODE)
-		CCS->curh->cursorMove(ENGINE->getCursorPosition().x, ENGINE->getCursorPosition().y);
+	if (settings["video"]["cursor"].String() == "software" && state != TouchState::RELATIVE_MODE)
+		ENGINE->cursor().cursorMove(ENGINE->getCursorPosition().x, ENGINE->getCursorPosition().y);
 
 	switch(state)
 	{
@@ -74,8 +74,7 @@ void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfin
 			};
 
 			ENGINE->input().moveCursorPosition(moveDistance);
-			if (CCS && CCS->curh)
-				CCS->curh->cursorMove(ENGINE->getCursorPosition().x * scalingFactor, ENGINE->getCursorPosition().y * scalingFactor);
+			ENGINE->cursor().cursorMove(ENGINE->getCursorPosition().x * scalingFactor, ENGINE->getCursorPosition().y * scalingFactor);
 
 			break;
 		}

+ 2 - 2
client/globalLobby/GlobalLobbyClient.cpp

@@ -217,7 +217,7 @@ void GlobalLobbyClient::receiveChatMessage(const JsonNode & json)
 		lobbyWindowPtr->refreshChatText();
 
 		if(channelType == "player" || (lobbyWindowPtr->isChannelOpen(channelType, channelName) && lobbyWindowPtr->isActive()))
-			CCS->soundh->playSound(AudioPath::builtin("CHAT"));
+			ENGINE->sound().playSound(AudioPath::builtin("CHAT"));
 	}
 }
 
@@ -342,7 +342,7 @@ void GlobalLobbyClient::receiveInviteReceived(const JsonNode & json)
 		lobbyWindowPtr->refreshChatText();
 	}
 
-	CCS->soundh->playSound(AudioPath::builtin("CHAT"));
+	ENGINE->sound().playSound(AudioPath::builtin("CHAT"));
 }
 
 void GlobalLobbyClient::receiveJoinRoomSuccess(const JsonNode & json)

+ 1 - 1
client/globalLobby/GlobalLobbyWidget.cpp

@@ -222,7 +222,7 @@ GlobalLobbyChannelCardBase::GlobalLobbyChannelCardBase(GlobalLobbyWindow * windo
 
 void GlobalLobbyChannelCardBase::clickPressed(const Point & cursorPosition)
 {
-	CCS->soundh->playSound(soundBase::button);
+	ENGINE->sound().playSound(soundBase::button);
 	window->doOpenChannel(channelType, channelName, channelDescription);
 }
 

+ 1 - 1
client/gui/WindowHandler.cpp

@@ -44,7 +44,7 @@ void WindowHandler::pushWindow(std::shared_ptr<IShowActivatable> newInt)
 	if(!windowsStack.empty())
 		windowsStack.back()->deactivate();
 	windowsStack.push_back(newInt);
-	CCS->curh->set(Cursor::Map::POINTER);
+	ENGINE->cursor().set(Cursor::Map::POINTER);
 	newInt->activate();
 	totalRedraw();
 }

+ 1 - 1
client/lobby/CBonusSelection.cpp

@@ -137,7 +137,7 @@ CBonusSelection::CBonusSelection()
 	}
 
 	if (!getCampaign()->getMusic().empty())
-		CCS->musich->playMusic( getCampaign()->getMusic(), true, false);
+		ENGINE->music().playMusic( getCampaign()->getMusic(), true, false);
 
 	if(CSH->getState() != EClientState::GAMEPLAY && settings["general"]["enableUiEnhancements"].Bool())
 	{

+ 1 - 1
client/lobby/CSelectionBase.cpp

@@ -396,7 +396,7 @@ void CChatBox::keyPressed(EShortcut key)
 
 void CChatBox::addNewMessage(const std::string & text)
 {
-	CCS->soundh->playSound(AudioPath::builtin("CHAT"));
+	ENGINE->sound().playSound(AudioPath::builtin("CHAT"));
 	chatHistory->setText(chatHistory->label->getText() + text + "\n");
 	if(chatHistory->slider)
 		chatHistory->slider->scrollToMax();

+ 1 - 1
client/lobby/OptionsTab.cpp

@@ -482,7 +482,7 @@ void OptionsTab::SelectionWindow::apply()
 	if(ENGINE->windows().isTopWindow(this))
 	{
 		ENGINE->input().hapticFeedback();
-		CCS->soundh->playSound(soundBase::button);
+		ENGINE->sound().playSound(soundBase::button);
 
 		close();
 

+ 1 - 1
client/mainmenu/CCampaignScreen.cpp

@@ -73,7 +73,7 @@ CCampaignScreen::CCampaignScreen(const JsonNode & config, std::string name)
 
 void CCampaignScreen::activate()
 {
-	CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, false);
+	ENGINE->music().playMusic(AudioPath::builtin("Music/MainMenu"), true, false);
 
 	CWindowObject::activate();
 }

+ 2 - 2
client/mainmenu/CHighScoreScreen.cpp

@@ -204,12 +204,12 @@ CHighScoreInputScreen::CHighScoreInputScreen(bool won, HighScoreCalculation calc
 		for (int i = 0; i < 5; i++)
 			texts.push_back(std::make_shared<CMultiLineLabel>(Rect(textareaW * i + border - (textareaW / 2), 530, textareaW, 100), FONT_HIGH_SCORE, ETextAlignment::TOPCENTER, Colors::WHITE, t[i]));
  
-		CCS->musich->playMusic(AudioPath::builtin("music/Win Scenario"), true, true);
+		ENGINE->music().playMusic(AudioPath::builtin("music/Win Scenario"), true, true);
 	}
 	else
 	{
 		videoPlayer = std::make_shared<VideoWidgetOnce>(Point(0, 0), VideoPath::builtin("LOSEGAME.SMK"), true, this);
-		CCS->musich->playMusic(AudioPath::builtin("music/UltimateLose"), false, true);
+		ENGINE->music().playMusic(AudioPath::builtin("music/UltimateLose"), false, true);
 	}
 
 	if (settings["general"]["enableUiEnhancements"].Bool())

+ 3 - 3
client/mainmenu/CMainMenu.cpp

@@ -339,7 +339,7 @@ CMainMenu::~CMainMenu()
 void CMainMenu::playIntroVideos()
 {
 	auto playVideo = [](std::string video, bool rim, float scaleFactor, std::function<void(bool)> cb){
-		if(CCS->videoh->open(VideoPath::builtin(video), scaleFactor))
+		if(ENGINE->video().open(VideoPath::builtin(video), scaleFactor))
 			ENGINE->windows().createAndPushWindow<VideoWindow>(VideoPath::builtin(video), rim ? ImagePath::builtin("INTRORIM") : ImagePath::builtin(""), true, scaleFactor, [cb](bool skipped){ cb(skipped); });
 		else
 			cb(true);
@@ -362,7 +362,7 @@ void CMainMenu::playIntroVideos()
 
 void CMainMenu::playMusic()
 {
-	CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
+	ENGINE->music().playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
 }
 
 void CMainMenu::activate()
@@ -723,7 +723,7 @@ CLoadingScreen::CLoadingScreen(ImagePath background)
 
 	addUsedEvents(TIME);
 
-	CCS->musich->stopMusic(5000);
+	ENGINE->music().stopMusic(5000);
 
 	const auto& conf = CMainMenuConfig::get().getConfig()["loading"];
 	const auto& nameConfig = conf["name"];

+ 9 - 9
client/mainmenu/CPrologEpilogVideo.cpp

@@ -48,16 +48,16 @@ CPrologEpilogVideo::CPrologEpilogVideo(CampaignScenarioPrologEpilog _spe, std::f
 	if (videoPlayer->pos.h == 400)
 		videoPlayer->moveBy(Point(0, 100));
 
-	CCS->musich->setVolume(CCS->musich->getVolume() / 2); // background volume is too loud by default
-	CCS->musich->playMusic(spe.prologMusic, true, true);
-	voiceDurationMilliseconds = CCS->soundh->getSoundDurationMilliseconds(spe.prologVoice);
-	voiceSoundHandle = CCS->soundh->playSound(spe.prologVoice);
+	ENGINE->music().setVolume(ENGINE->music().getVolume() / 2); // background volume is too loud by default
+	ENGINE->music().playMusic(spe.prologMusic, true, true);
+	voiceDurationMilliseconds = ENGINE->sound().getSoundDurationMilliseconds(spe.prologVoice);
+	voiceSoundHandle = ENGINE->sound().playSound(spe.prologVoice);
 	auto onVoiceStop = [this]()
 	{
 		voiceStopped = true;
 		elapsedTimeMilliseconds = 0;
 	};
-	CCS->soundh->setCallback(voiceSoundHandle, onVoiceStop);
+	ENGINE->sound().setCallback(voiceSoundHandle, onVoiceStop);
 
 	text = std::make_shared<CMultiLineLabel>(Rect(100, 500, 600, 100), EFonts::FONT_BIG, ETextAlignment::CENTER, Colors::METALLIC_GOLD, spe.prologText.toString());
 	if(text->getLines().size() == 3)
@@ -92,11 +92,11 @@ void CPrologEpilogVideo::show(Canvas & to)
 
 void CPrologEpilogVideo::clickPressed(const Point & cursorPosition)
 {
-	CCS->musich->setVolume(CCS->musich->getVolume() * 2); // restore background volume
+	ENGINE->music().setVolume(ENGINE->music().getVolume() * 2); // restore background volume
 	close();
-	CCS->soundh->resetCallback(voiceSoundHandle); // reset callback to avoid memory corruption since 'this' will be destroyed
-	CCS->soundh->stopSound(voiceSoundHandle);
-	CCS->soundh->stopSound(videoSoundHandle);
+	ENGINE->sound().resetCallback(voiceSoundHandle); // reset callback to avoid memory corruption since 'this' will be destroyed
+	ENGINE->sound().stopSound(voiceSoundHandle);
+	ENGINE->sound().stopSound(videoSoundHandle);
 	if(exitCb)
 		exitCb();
 }

+ 2 - 2
client/mapView/MapViewActions.cpp

@@ -144,7 +144,7 @@ void MapViewActions::handleHover(const Point & cursorPosition)
 
 	if(!context->isInMap(tile))
 	{
-		CCS->curh->set(Cursor::Map::POINTER);
+		ENGINE->cursor().set(Cursor::Map::POINTER);
 		return;
 	}
 
@@ -156,6 +156,6 @@ void MapViewActions::hover(bool on)
 	if(!on)
 	{
 		ENGINE->statusbar()->clear();
-		CCS->curh->set(Cursor::Map::POINTER);
+		ENGINE->cursor().set(Cursor::Map::POINTER);
 	}
 }

+ 1 - 1
client/media/CMusicHandler.cpp

@@ -56,7 +56,7 @@ CMusicHandler::CMusicHandler():
 	{
 		Mix_HookMusicFinished([]()
 		{
-			CCS->musich->musicFinishedCallback();
+			ENGINE->music().musicFinishedCallback();
 		});
 	}
 }

+ 1 - 4
client/media/CSoundHandler.cpp

@@ -48,10 +48,7 @@ CSoundHandler::CSoundHandler():
 	{
 		Mix_ChannelFinished([](int channel)
 		{
-			if (CCS)
-			{
-				CCS->soundh->soundFinishedCallback(channel);
-			}
+			ENGINE->sound().soundFinishedCallback(channel);
 		});
 	}
 }

+ 1 - 1
client/renderSDL/ScreenHandler.cpp

@@ -627,7 +627,7 @@ void ScreenHandler::presentScreenTexture()
 {
 	SDL_RenderClear(mainRenderer);
 	SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr);
-	CCS->curh->render();
+	ENGINE->cursor().render();
 	SDL_RenderPresent(mainRenderer);
 }
 

+ 2 - 2
client/widgets/Buttons.cpp

@@ -257,7 +257,7 @@ void CButton::clickPressed(const Point & cursorPosition)
 	{
 		if (!soundDisabled)
 		{
-			CCS->soundh->playSound(soundBase::button);
+			ENGINE->sound().playSound(soundBase::button);
 			ENGINE->input().hapticFeedback();
 		}
 		setState(EButtonState::PRESSED);
@@ -484,7 +484,7 @@ void CToggleButton::clickPressed(const Point & cursorPosition)
 
 	if (canActivate())
 	{
-		CCS->soundh->playSound(soundBase::button);
+		ENGINE->sound().playSound(soundBase::button);
 		ENGINE->input().hapticFeedback();
 		setState(EButtonState::PRESSED);
 	}

+ 8 - 8
client/widgets/VideoWidget.cpp

@@ -66,7 +66,7 @@ void VideoWidgetBase::playVideo(const VideoPath & fileToPlay)
 		}
 	}
 
-	videoInstance = CCS->videoh->open(videoFile, scaleFactor * preScaleFactor);
+	videoInstance = ENGINE->video().open(videoFile, scaleFactor * preScaleFactor);
 	if (videoInstance)
 	{
 		pos.w = videoInstance->size().x;
@@ -96,7 +96,7 @@ void VideoWidgetBase::loadAudio(const VideoPath & fileToPlay)
 	if (!playAudio)
 		return;
 
-	audioData = CCS->videoh->getAudio(fileToPlay);
+	audioData = ENGINE->video().getAudio(fileToPlay);
 }
 
 void VideoWidgetBase::startAudio()
@@ -104,11 +104,11 @@ void VideoWidgetBase::startAudio()
 	if(audioData.first == nullptr)
 		return;
 
-	audioHandle = CCS->soundh->playSound(audioData);
+	audioHandle = ENGINE->sound().playSound(audioData);
 
 	if(audioHandle != -1)
 	{
-		CCS->soundh->setCallback(
+		ENGINE->sound().setCallback(
 			audioHandle,
 			[this]()
 			{
@@ -122,8 +122,8 @@ void VideoWidgetBase::stopAudio()
 {
 	if(audioHandle != -1)
 	{
-		CCS->soundh->resetCallback(audioHandle);
-		CCS->soundh->stopSound(audioHandle);
+		ENGINE->sound().resetCallback(audioHandle);
+		ENGINE->sound().stopSound(audioHandle);
 		audioHandle = -1;
 	}
 }
@@ -144,7 +144,7 @@ void VideoWidgetBase::activate()
 {
 	CIntObject::activate();
 	if(audioHandle != -1)
-		CCS->soundh->resumeSound(audioHandle);
+		ENGINE->sound().resumeSound(audioHandle);
 	else
 		startAudio();
 	if(videoInstance)
@@ -154,7 +154,7 @@ void VideoWidgetBase::activate()
 void VideoWidgetBase::deactivate()
 {
 	CIntObject::deactivate();
-	CCS->soundh->pauseSound(audioHandle);
+	ENGINE->sound().pauseSound(audioHandle);
 	if(videoInstance)
 		videoInstance->deactivate();
 }

+ 2 - 2
client/windows/CCastleInterface.cpp

@@ -1453,7 +1453,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
 	recreateIcons();
 	if (!from)
 		adventureInt->onAudioPaused();
-	CCS->musich->playMusicFromSet("faction", town->getFaction()->getJsonKey(), true, false);
+	ENGINE->music().playMusicFromSet("faction", town->getFaction()->getJsonKey(), true, false);
 }
 
 CCastleInterface::~CCastleInterface()
@@ -1516,7 +1516,7 @@ void CCastleInterface::townChange()
 void CCastleInterface::addBuilding(BuildingID bid)
 {
 	if (town->getTown()->buildings.at(bid)->mode != CBuilding::BUILD_AUTO)
-		CCS->soundh->playSound(soundBase::newBuilding);
+		ENGINE->sound().playSound(soundBase::newBuilding);
 
 	deactivate();
 	builds->addBuilding(bid);

+ 1 - 1
client/windows/CExchangeWindow.cpp

@@ -371,7 +371,7 @@ bool CExchangeWindow::holdsGarrison(const CArmedInstance * army)
 
 void CExchangeWindow::questLogShortcut()
 {
-	CCS->curh->dragAndDropCursor(nullptr);
+	ENGINE->cursor().dragAndDropCursor(nullptr);
 	LOCPLINT->showQuestLog();
 }
 

+ 1 - 1
client/windows/CPuzzleWindow.cpp

@@ -35,7 +35,7 @@ CPuzzleWindow::CPuzzleWindow(const int3 & GrailPos, double discoveredRatio)
 {
 	OBJECT_CONSTRUCTION;
 
-	CCS->soundh->playSound(soundBase::OBELISK);
+	ENGINE->sound().playSound(soundBase::OBELISK);
 
 	quitb = std::make_shared<CButton>(Point(670, 538), AnimationPath::builtin("IOK6432.DEF"), CButton::tooltip(CGI->generaltexth->allTexts[599]), std::bind(&CPuzzleWindow::close, this), EShortcut::GLOBAL_RETURN);
 	quitb->setBorderColor(Colors::METALLIC_GOLD);

+ 3 - 3
client/windows/CWindowObject.cpp

@@ -44,7 +44,7 @@ CWindowObject::CWindowObject(int options_, const ImagePath & imageName, Point ce
 		assert(parent == nullptr); //Safe to remove, but windows should not have parent
 
 	if (options & RCLICK_POPUP)
-		CCS->curh->hide();
+		ENGINE->cursor().hide();
 
 	if (background)
 		pos = background->center(centerAt);
@@ -64,7 +64,7 @@ CWindowObject::CWindowObject(int options_, const ImagePath & imageName):
 		assert(parent == nullptr); //Safe to remove, but windows should not have parent
 
 	if(options & RCLICK_POPUP)
-		CCS->curh->hide();
+		ENGINE->cursor().hide();
 
 	if(background)
 		pos = background->center();
@@ -78,7 +78,7 @@ CWindowObject::CWindowObject(int options_, const ImagePath & imageName):
 CWindowObject::~CWindowObject()
 {
 	if(options & RCLICK_POPUP)
-		CCS->curh->show();
+		ENGINE->cursor().show();
 }
 
 std::shared_ptr<CPicture> CWindowObject::createBg(const ImagePath & imageName, bool playerColored)

+ 4 - 4
client/windows/CWindowWithArtifacts.cpp

@@ -154,7 +154,7 @@ void CWindowWithArtifacts::activate()
 
 void CWindowWithArtifacts::deactivate()
 {
-	CCS->curh->dragAndDropCursor(nullptr);
+	ENGINE->cursor().dragAndDropCursor(nullptr);
 	CWindowObject::deactivate();
 }
 
@@ -179,7 +179,7 @@ void CWindowWithArtifacts::update()
 		else
 		{
 			artSet->unmarkSlots();
-			CCS->curh->dragAndDropCursor(nullptr);
+			ENGINE->cursor().dragAndDropCursor(nullptr);
 		}
 
 		// Make sure the status bar is updated so it does not display old text
@@ -238,11 +238,11 @@ void CWindowWithArtifacts::setCursorAnimation(const CArtifactInstance & artInst)
 		auto image = ENGINE->renderHandler().loadImage(AnimationPath::builtin("spellscr"), artInst.getScrollSpellID().num, 0, EImageBlitMode::COLORKEY);
 		image->scaleTo(Point(44,34), EScalingAlgorithm::BILINEAR);
 
-		CCS->curh->dragAndDropCursor(image);
+		ENGINE->cursor().dragAndDropCursor(image);
 	}
 	else
 	{
-		CCS->curh->dragAndDropCursor(AnimationPath::builtin("artifact"), artInst.getType()->getIconIndex());
+		ENGINE->cursor().dragAndDropCursor(AnimationPath::builtin("artifact"), artInst.getType()->getIconIndex());
 	}
 }
 

+ 2 - 2
client/windows/InfoWindows.cpp

@@ -248,14 +248,14 @@ CRClickPopupInt::CRClickPopupInt(const std::shared_ptr<CIntObject> & our) :
 {
 	addUsedEvents(DRAG_POPUP);
 
-	CCS->curh->hide();
+	ENGINE->cursor().hide();
 	inner = our;
 	addChild(our.get(), false);
 }
 
 CRClickPopupInt::~CRClickPopupInt()
 {
-	CCS->curh->show();
+	ENGINE->cursor().show();
 }
 
 void CRClickPopupInt::mouseDraggedPopup(const Point & cursorPosition, const Point & lastUpdateDistance)

+ 4 - 4
client/windows/settings/GeneralOptionsTab.cpp

@@ -236,10 +236,10 @@ GeneralOptionsTab::GeneralOptionsTab()
 		audioMuteFocusCheckbox->setSelected(settings["general"]["audioMuteFocus"].Bool());
 
 	std::shared_ptr<CSlider> musicSlider = widget<CSlider>("musicSlider");
-	musicSlider->scrollTo(CCS->musich->getVolume());
+	musicSlider->scrollTo(ENGINE->music().getVolume());
 
 	std::shared_ptr<CSlider> volumeSlider = widget<CSlider>("soundVolumeSlider");
-	volumeSlider->scrollTo(CCS->soundh->getVolume());
+	volumeSlider->scrollTo(ENGINE->sound().getVolume());
 
 	std::shared_ptr<CToggleGroup> creatureGrowthAsDwellingPicker = widget<CToggleGroup>("availableCreaturesAsDwellingPicker");
 	creatureGrowthAsDwellingPicker->setSelected(settings["gameTweaks"]["availableCreaturesAsDwellingLabel"].Bool());
@@ -248,10 +248,10 @@ GeneralOptionsTab::GeneralOptionsTab()
 	compactTownCreatureInfo->setSelected(settings["gameTweaks"]["compactTownCreatureInfo"].Bool());
 
 	std::shared_ptr<CLabel> musicVolumeLabel = widget<CLabel>("musicValueLabel");
-	musicVolumeLabel->setText(std::to_string(CCS->musich->getVolume()) + "%");
+	musicVolumeLabel->setText(std::to_string(ENGINE->music().getVolume()) + "%");
 
 	std::shared_ptr<CLabel> soundVolumeLabel = widget<CLabel>("soundValueLabel");
-	soundVolumeLabel->setText(std::to_string(CCS->soundh->getVolume()) + "%");
+	soundVolumeLabel->setText(std::to_string(ENGINE->sound().getVolume()) + "%");
 
 	updateResolutionSelector();
 }

+ 0 - 5
clientapp/CMakeLists.txt

@@ -42,11 +42,6 @@ target_include_directories(vcmiclient
 	PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
 )
 
-if(ENABLE_VIDEO)
-	target_compile_definitions(vcmiclient PRIVATE ENABLE_VIDEO)
-endif()
-
-
 if(WIN32)
 	target_sources(vcmiclient PRIVATE "VCMI_client.rc")
 	set_target_properties(vcmiclient

+ 1 - 46
clientapp/EntryPoint.cpp

@@ -308,32 +308,9 @@ int main(int argc, char * argv[])
 	if(!settings["session"]["headless"].Bool())
 		ENGINE->init();
 
-	CCS = new CClientState();
 	CGI = new CGameInfo(); //contains all global information about game (texts, lodHandlers, map handler etc.)
 	CSH = new CServerHandler();
 	
-	// Initialize video
-#ifndef ENABLE_VIDEO
-	CCS->videoh = new CEmptyVideoPlayer();
-#else
-	if (!settings["session"]["headless"].Bool() && !vm.count("disable-video"))
-		CCS->videoh = new CVideoPlayer();
-	else
-		CCS->videoh = new CEmptyVideoPlayer();
-#endif
-
-	logGlobal->info("\tInitializing video: %d ms", pomtime.getDiff());
-
-	if(!settings["session"]["headless"].Bool())
-	{
-		//initializing audio
-		CCS->soundh = new CSoundHandler();
-		CCS->soundh->setVolume((ui32)settings["general"]["sound"].Float());
-		CCS->musich = new CMusicHandler();
-		CCS->musich->setVolume((ui32)settings["general"]["music"].Float());
-		logGlobal->info("Initializing screen and sound handling: %d ms", pomtime.getDiff());
-	}
-
 #ifndef VCMI_NO_THREADED_LOAD
 	//we can properly play intro only in the main thread, so we have to move loading to the separate thread
 	boost::thread loading([]()
@@ -369,13 +346,10 @@ int main(int argc, char * argv[])
 		graphics = new Graphics(); // should be before curh
 		ENGINE->renderHandler().onLibraryLoadingFinished(CGI);
 
-		CCS->curh = new CursorHandler();
-		logGlobal->info("Screen handler: %d ms", pomtime.getDiff());
-
 		CMessage::init();
 		logGlobal->info("Message handler: %d ms", pomtime.getDiff());
 
-		CCS->curh->show();
+		ENGINE->cursor().show();
 	}
 
 	logGlobal->info("Initialization of VCMI (together): %d ms", total.getDiff());
@@ -474,17 +448,6 @@ static void mainLoop()
 
 	if(!settings["session"]["headless"].Bool())
 	{
-		// cleanup, mostly to remove false leaks from analyzer
-		if(CCS)
-		{
-			delete CCS->consoleh;
-			delete CCS->curh;
-			delete CCS->videoh;
-			delete CCS->musich;
-			delete CCS->soundh;
-
-			vstd::clear_pointer(CCS);
-		}
 		CMessage::dispose();
 
 		vstd::clear_pointer(graphics);
@@ -525,14 +488,6 @@ void handleQuit(bool ask)
 		return;
 	}
 
-	// FIXME: avoids crash if player attempts to close game while opening is still playing
-	// use cursor handler as indicator that loading is not done yet
-	// proper solution would be to abort init thread (or wait for it to finish)
-	if (!CCS->curh)
-	{
-		quitApplicationImmediately(0);
-	}
-
 	if (LOCPLINT)
 		LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[69], quitApplication, nullptr);
 	else